xref: /trunk/main/vcl/source/control/menubtn.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb) !
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #ifndef _SV_RC_H
32 #include <tools/rc.h>
33 #endif
34 #include <vcl/decoview.hxx>
35 #include <vcl/event.hxx>
36 #include <vcl/menu.hxx>
37 #include <vcl/timer.hxx>
38 #include <vcl/menubtn.hxx>
39 
40 
41 
42 // =======================================================================
43 
44 #define IMAGEBUTTON_BORDER_OFF1     11
45 #define IMAGEBUTTON_BORDER_OFF2     16
46 
47 // =======================================================================
48 
49 void MenuButton::ImplInitMenuButtonData()
50 {
51     mnDDStyle       = PUSHBUTTON_DROPDOWN_MENUBUTTON;
52 
53     mpMenuTimer     = NULL;
54     mpMenu          = NULL;
55     mpOwnMenu       = NULL;
56     mnCurItemId     = 0;
57     mnMenuMode      = 0;
58 }
59 
60 // -----------------------------------------------------------------------
61 
62 void MenuButton::ImplInit( Window* pParent, WinBits nStyle )
63 {
64     if ( !(nStyle & WB_NOTABSTOP) )
65         nStyle |= WB_TABSTOP;
66 
67     PushButton::ImplInit( pParent, nStyle );
68 }
69 
70 // -----------------------------------------------------------------------
71 
72 void MenuButton::ImplExecuteMenu()
73 {
74     Activate();
75 
76     if ( mpMenu )
77     {
78         Point aPos( 0, 1 );
79         Size aSize = GetSizePixel();
80         Rectangle aRect( aPos, aSize );
81         SetPressed( sal_True );
82         EndSelection();
83         mnCurItemId = mpMenu->Execute( this, aRect, POPUPMENU_EXECUTE_DOWN );
84         SetPressed( sal_False );
85         if ( mnCurItemId )
86         {
87             Select();
88             mnCurItemId = 0;
89         }
90     }
91 }
92 
93 // -----------------------------------------------------------------------
94 
95 MenuButton::MenuButton( Window* pParent, WinBits nWinBits ) :
96     PushButton( WINDOW_MENUBUTTON )
97 {
98     ImplInitMenuButtonData();
99     ImplInit( pParent, nWinBits );
100 }
101 
102 // -----------------------------------------------------------------------
103 
104 MenuButton::MenuButton( Window* pParent, const ResId& rResId ) :
105     PushButton( WINDOW_MENUBUTTON )
106 {
107     ImplInitMenuButtonData();
108     rResId.SetRT( RSC_MENUBUTTON );
109     WinBits nStyle = ImplInitRes( rResId );
110     ImplInit( pParent, nStyle );
111     ImplLoadRes( rResId );
112 
113     if ( !(nStyle & WB_HIDE) )
114         Show();
115 }
116 
117 // -----------------------------------------------------------------------
118 
119 void MenuButton::ImplLoadRes( const ResId& rResId )
120 {
121     Control::ImplLoadRes( rResId );
122 
123     sal_uLong nObjMask = ReadLongRes();
124 
125     if ( RSCMENUBUTTON_MENU & nObjMask )
126     {
127         mpOwnMenu = new PopupMenu( ResId( (RSHEADER_TYPE*)GetClassRes(), *rResId.GetResMgr() ) );
128         SetPopupMenu( mpOwnMenu );
129         IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
130     }
131 }
132 
133 // -----------------------------------------------------------------------
134 
135 MenuButton::~MenuButton()
136 {
137     if ( mpMenuTimer )
138         delete mpMenuTimer;
139     if ( mpOwnMenu )
140         delete mpOwnMenu;
141 }
142 
143 // -----------------------------------------------------------------------
144 
145 IMPL_LINK( MenuButton, ImplMenuTimeoutHdl, Timer*, EMPTYARG )
146 {
147     // Abfragen, ob Button-Benutzung noch aktiv ist, da diese ja auch
148     // vorher abgebrochen wurden sein koennte
149     if ( IsTracking() )
150     {
151         if ( !(GetStyle() & WB_NOPOINTERFOCUS) )
152             GrabFocus();
153         ImplExecuteMenu();
154     }
155 
156     return 0;
157 }
158 
159 // -----------------------------------------------------------------------
160 
161 void MenuButton::MouseButtonDown( const MouseEvent& rMEvt )
162 {
163     bool bExecute = true;
164     if ( mnMenuMode & MENUBUTTON_MENUMODE_TIMED )
165     {
166         // if the separated dropdown symbol is hit,
167         // execute the popup immediately
168         if( ! ImplGetSymbolRect().IsInside( rMEvt.GetPosPixel() ) )
169         {
170             if ( !mpMenuTimer )
171             {
172                 mpMenuTimer = new Timer;
173                 mpMenuTimer->SetTimeoutHdl( LINK( this, MenuButton, ImplMenuTimeoutHdl ) );
174             }
175 
176             mpMenuTimer->SetTimeout( GetSettings().GetMouseSettings().GetActionDelay() );
177             mpMenuTimer->Start();
178 
179             PushButton::MouseButtonDown( rMEvt );
180             bExecute = false;
181         }
182     }
183     if( bExecute )
184     {
185         if ( PushButton::ImplHitTestPushButton( this, rMEvt.GetPosPixel() ) )
186         {
187             if ( !(GetStyle() & WB_NOPOINTERFOCUS) )
188                 GrabFocus();
189             ImplExecuteMenu();
190         }
191     }
192 }
193 
194 // -----------------------------------------------------------------------
195 
196 void MenuButton::KeyInput( const KeyEvent& rKEvt )
197 {
198     KeyCode aKeyCode = rKEvt.GetKeyCode();
199     sal_uInt16 nCode = aKeyCode.GetCode();
200     if ( (nCode == KEY_DOWN) && aKeyCode.IsMod2() )
201         ImplExecuteMenu();
202     else if ( !(mnMenuMode & MENUBUTTON_MENUMODE_TIMED) &&
203               !aKeyCode.GetModifier() &&
204               ((nCode == KEY_RETURN) || (nCode == KEY_SPACE)) )
205         ImplExecuteMenu();
206     else
207         PushButton::KeyInput( rKEvt );
208 }
209 
210 // -----------------------------------------------------------------------
211 
212 void MenuButton::Activate()
213 {
214     maActivateHdl.Call( this );
215 }
216 
217 // -----------------------------------------------------------------------
218 
219 void MenuButton::Select()
220 {
221     maSelectHdl.Call( this );
222 }
223 
224 // -----------------------------------------------------------------------
225 
226 void MenuButton::SetMenuMode( sal_uInt16 nMode )
227 {
228     // Fuer die 5.1-Auslieferung besser noch nicht inline, ansonsten kann
229     // diese Funktion zur 6.0 inline werden
230     mnMenuMode = nMode;
231 }
232 
233 // -----------------------------------------------------------------------
234 
235 void MenuButton::SetPopupMenu( PopupMenu* pNewMenu )
236 {
237     // Fuer die 5.1-Auslieferung besser noch nicht inline, ansonsten kann
238     // diese Funktion zur 6.0 inline werden
239     mpMenu = pNewMenu;
240 }
241