]> git.saurik.com Git - wxWidgets.git/blob - src/univ/topluniv.cpp
input handling in wxTLW/Univ
[wxWidgets.git] / src / univ / topluniv.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: topluniv.cpp
3 // Author: Vaclav Slavik
4 // Id: $Id$
5 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
6 // Licence: wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8
9 // ============================================================================
10 // declarations
11 // ============================================================================
12
13 // ----------------------------------------------------------------------------
14 // headers
15 // ----------------------------------------------------------------------------
16
17 #ifdef __GNUG__
18 #pragma implementation "univtoplevel.h"
19 #endif
20
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
23
24 #ifdef __BORLANDC__
25 #pragma hdrstop
26 #endif
27
28 #include "wx/defs.h"
29 #include "wx/toplevel.h"
30 #include "wx/univ/renderer.h"
31 #include "wx/dcclient.h"
32 #include "wx/bitmap.h"
33 #include "wx/image.h"
34 #include "wx/cshelp.h"
35
36
37 // ----------------------------------------------------------------------------
38 // event tables
39 // ----------------------------------------------------------------------------
40
41 BEGIN_EVENT_TABLE(wxTopLevelWindow, wxTopLevelWindowNative)
42 WX_EVENT_TABLE_INPUT_CONSUMER(wxTopLevelWindow)
43 EVT_NC_PAINT(wxTopLevelWindow::OnNcPaint)
44 END_EVENT_TABLE()
45
46 WX_FORWARD_TO_INPUT_CONSUMER(wxTopLevelWindow)
47
48
49 // ============================================================================
50 // implementation
51 // ============================================================================
52
53 int wxTopLevelWindow::ms_drawDecorations = -1;
54
55 void wxTopLevelWindow::Init()
56 {
57 m_isActive = FALSE;
58 m_windowStyle = 0;
59 m_pressedButton = 0;
60 }
61
62 bool wxTopLevelWindow::Create(wxWindow *parent,
63 wxWindowID id,
64 const wxString& title,
65 const wxPoint& pos,
66 const wxSize& sizeOrig,
67 long style,
68 const wxString &name)
69 {
70 // init them to avoid compiler warnings
71 long styleOrig = 0,
72 exstyleOrig = 0;
73
74 if ( ms_drawDecorations == -1 )
75 ms_drawDecorations = TRUE;
76 // FIXME_MGL -- this is temporary; we assume for now that native TLW
77 // can't do decorations, which is not true
78
79 if ( ms_drawDecorations )
80 {
81 CreateInputHandler(wxINP_HANDLER_TOPLEVEL);
82
83 styleOrig = style;
84 exstyleOrig = GetExtraStyle();
85 style &= ~(wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX |
86 wxSYSTEM_MENU | wxRESIZE_BORDER | wxFRAME_TOOL_WINDOW |
87 wxTHICK_FRAME);
88 style = wxSIMPLE_BORDER;
89 SetExtraStyle(exstyleOrig &
90 ~(wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP));
91 }
92
93 if ( !wxTopLevelWindowNative::Create(parent, id, title, pos,
94 sizeOrig, style, name) )
95 return FALSE;
96
97 if ( ms_drawDecorations )
98 {
99 m_windowStyle = styleOrig;
100 m_exStyle = exstyleOrig;
101 }
102
103 return TRUE;
104 }
105
106 bool wxTopLevelWindow::ShowFullScreen(bool show, long style)
107 {
108 if ( show == IsFullScreen() ) return FALSE;
109
110 if ( ms_drawDecorations )
111 {
112 if ( show )
113 {
114 m_fsSavedStyle = m_windowStyle;
115 if ( style & wxFULLSCREEN_NOBORDER )
116 m_windowStyle |= wxSIMPLE_BORDER;
117 if ( style & wxFULLSCREEN_NOCAPTION )
118 m_windowStyle &= ~wxCAPTION;
119 }
120 else
121 {
122 m_windowStyle = m_fsSavedStyle;
123 }
124 }
125
126 return wxTopLevelWindowNative::ShowFullScreen(show, style);
127 }
128
129 long wxTopLevelWindow::GetDecorationsStyle() const
130 {
131 long style = 0;
132
133 if ( m_windowStyle & wxCAPTION )
134 {
135 style |= wxTOPLEVEL_TITLEBAR | wxTOPLEVEL_BUTTON_CLOSE;
136 if ( m_windowStyle & wxMINIMIZE_BOX )
137 style |= wxTOPLEVEL_BUTTON_ICONIZE;
138 if ( m_windowStyle & wxMAXIMIZE_BOX )
139 style |= wxTOPLEVEL_BUTTON_MAXIMIZE;
140 #if wxUSE_HELP
141 if ( m_exStyle & (wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP))
142 style |= wxTOPLEVEL_BUTTON_HELP;
143 #endif
144 }
145 if ( (m_windowStyle & (wxSIMPLE_BORDER | wxNO_BORDER)) == 0 )
146 style |= wxTOPLEVEL_BORDER;
147 if ( m_windowStyle & (wxRESIZE_BORDER | wxTHICK_FRAME) )
148 style |= wxTOPLEVEL_RESIZEABLE;
149
150 if ( IsMaximized() )
151 style |= wxTOPLEVEL_MAXIMIZED;
152 if ( GetIcon().Ok() )
153 style |= wxTOPLEVEL_ICON;
154 if ( m_isActive )
155 style |= wxTOPLEVEL_ACTIVE;
156
157 return style;
158 }
159
160 void wxTopLevelWindow::RefreshTitleBar()
161 {
162 wxNcPaintEvent event(GetId());
163 event.SetEventObject(this);
164 GetEventHandler()->ProcessEvent(event);
165 }
166
167 // ----------------------------------------------------------------------------
168 // client area handling
169 // ----------------------------------------------------------------------------
170
171 wxPoint wxTopLevelWindow::GetClientAreaOrigin() const
172 {
173 if ( ms_drawDecorations )
174 {
175 int w, h;
176 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
177 wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(),
178 wxSize(w, h));
179 rect = m_renderer->GetFrameClientArea(rect,
180 GetDecorationsStyle());
181 return rect.GetPosition();
182 }
183 else
184 {
185 return wxTopLevelWindowNative::GetClientAreaOrigin();
186 }
187 }
188
189 void wxTopLevelWindow::DoGetClientSize(int *width, int *height) const
190 {
191 if ( ms_drawDecorations )
192 {
193 int w, h;
194 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
195 wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(),
196 wxSize(w, h));
197 rect = m_renderer->GetFrameClientArea(rect,
198 GetDecorationsStyle());
199 if ( width )
200 *width = rect.width;
201 if ( height )
202 *height = rect.height;
203 }
204 else
205 wxTopLevelWindowNative::DoGetClientSize(width, height);
206 }
207
208 void wxTopLevelWindow::DoSetClientSize(int width, int height)
209 {
210 if ( ms_drawDecorations )
211 {
212 wxSize size = m_renderer->GetFrameTotalSize(wxSize(width, height),
213 GetDecorationsStyle());
214 wxTopLevelWindowNative::DoSetClientSize(size.x, size.y);
215 }
216 else
217 wxTopLevelWindowNative::DoSetClientSize(width, height);
218 }
219
220 void wxTopLevelWindow::OnNcPaint(wxPaintEvent& event)
221 {
222 if ( !ms_drawDecorations || !m_renderer )
223 event.Skip();
224 else
225 {
226 // get the window rect
227 wxRect rect;
228 wxSize size = GetSize();
229 rect.x =
230 rect.y = 0;
231 rect.width = size.x;
232 rect.height = size.y;
233
234 wxWindowDC dc(this);
235 m_renderer->DrawFrameTitleBar(dc, rect,
236 GetTitle(), m_titlebarIcon,
237 GetDecorationsStyle(),
238 m_pressedButton,
239 wxCONTROL_PRESSED);
240 }
241 }
242
243 long wxTopLevelWindow::HitTest(const wxPoint& pt) const
244 {
245 int w, h;
246 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
247 wxRect rect(wxTopLevelWindowNative::GetClientAreaOrigin(), wxSize(w, h));
248
249 return m_renderer->HitTestFrame(rect, pt, GetDecorationsStyle());
250 }
251
252 // ----------------------------------------------------------------------------
253 // icons
254 // ----------------------------------------------------------------------------
255
256 void wxTopLevelWindow::SetIcon(const wxIcon& icon)
257 {
258 wxTopLevelWindowNative::SetIcon(icon);
259 if ( !m_renderer ) return;
260
261 wxSize size = m_renderer->GetFrameIconSize();
262
263 if ( !icon.Ok() || size.x == -1 )
264 m_titlebarIcon = icon;
265 else
266 {
267 wxBitmap bmp1;
268 bmp1.CopyFromIcon(icon);
269 if ( !bmp1.Ok() )
270 m_titlebarIcon = wxNullIcon;
271 else if ( bmp1.GetWidth() == size.x && bmp1.GetHeight() == size.y )
272 m_titlebarIcon = icon;
273 else
274 {
275 wxImage img = bmp1.ConvertToImage();
276 img.Rescale(size.x, size.y);
277 m_titlebarIcon.CopyFromBitmap(wxBitmap(img));
278 }
279 }
280 }
281
282 // ----------------------------------------------------------------------------
283 // actions
284 // ----------------------------------------------------------------------------
285
286 void wxTopLevelWindow::ClickTitleBarButton(long button)
287 {
288 switch ( button )
289 {
290 case wxTOPLEVEL_BUTTON_CLOSE:
291 Close();
292 break;
293
294 case wxTOPLEVEL_BUTTON_ICONIZE:
295 Iconize();
296 break;
297
298 case wxTOPLEVEL_BUTTON_MAXIMIZE:
299 Maximize();
300 break;
301
302 case wxTOPLEVEL_BUTTON_RESTORE:
303 Restore();
304 break;
305
306 case wxTOPLEVEL_BUTTON_HELP:
307 #if wxUSE_HELP
308 {
309 wxContextHelp contextHelp(this);
310 }
311 #endif
312 break;
313
314 default:
315 wxFAIL_MSG(wxT("incorrect button specification"));
316 }
317 }
318
319 bool wxTopLevelWindow::PerformAction(const wxControlAction& action,
320 long numArg,
321 const wxString& strArg)
322 {
323 if ( action == wxACTION_TOPLEVEL_ACTIVATE )
324 {
325 if ( m_isActive != (bool)numArg )
326 {
327 Refresh();
328 m_isActive = (bool)numArg;
329 wxNcPaintEvent event(GetId());
330 event.SetEventObject(this);
331 GetEventHandler()->ProcessEvent(event);
332 }
333 return TRUE;
334 }
335
336 else if ( action == wxACTION_TOPLEVEL_BUTTON_PRESS )
337 {
338 m_pressedButton = numArg;
339 RefreshTitleBar();
340 return TRUE;
341 }
342
343 else if ( action == wxACTION_TOPLEVEL_BUTTON_RELEASE )
344 {
345 m_pressedButton = 0;
346 RefreshTitleBar();
347 return TRUE;
348 }
349
350 else if ( action == wxACTION_TOPLEVEL_BUTTON_CLICK )
351 {
352 m_pressedButton = 0;
353 RefreshTitleBar();
354 ClickTitleBarButton(numArg);
355 return TRUE;
356 }
357
358 else
359 return FALSE;
360 }
361
362
363 // ============================================================================
364 // wxStdFrameInputHandler: handles focus, resizing and titlebar buttons clicks
365 // ============================================================================
366
367 wxStdFrameInputHandler::wxStdFrameInputHandler(wxInputHandler *inphand)
368 : wxStdInputHandler(inphand)
369 {
370 m_winCapture = NULL;
371 m_winHitTest = 0;
372 m_winPressed = 0;
373 }
374
375 bool wxStdFrameInputHandler::HandleMouse(wxInputConsumer *consumer,
376 const wxMouseEvent& event)
377 {
378 // the button has 2 states: pressed and normal with the following
379 // transitions between them:
380 //
381 // normal -> left down -> capture mouse and go to pressed state
382 // pressed -> left up inside -> generate click -> go to normal
383 // outside ------------------>
384 //
385 // the other mouse buttons are ignored
386 if ( event.Button(1) )
387 {
388 if ( event.ButtonDown(1) )
389 {
390 wxTopLevelWindow *w = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
391 long hit = w->HitTest(event.GetPosition());
392
393 if ( hit & wxHT_TOPLEVEL_ANY_BUTTON )
394 {
395 m_winCapture = w;
396 m_winCapture->CaptureMouse();
397 m_winHitTest = hit;
398 m_winPressed = hit;
399 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
400 return TRUE;
401 }
402 }
403
404 else // up
405 {
406 if ( m_winCapture )
407 {
408 m_winCapture->ReleaseMouse();
409 m_winCapture = NULL;
410
411 if ( m_winHitTest == m_winPressed )
412 {
413 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, m_winPressed);
414 return TRUE;
415 }
416 }
417 //else: the mouse was released outside the window, this doesn't
418 // count as a click
419 }
420 }
421
422 return wxStdInputHandler::HandleMouse(consumer, event);
423 }
424
425 bool wxStdFrameInputHandler::HandleMouseMove(wxInputConsumer *consumer,
426 const wxMouseEvent& event)
427 {
428 // we only have to do something when the mouse leaves/enters the pressed
429 // button and don't care about the other ones
430 if ( event.GetEventObject() == m_winCapture )
431 {
432 long hit = m_winCapture->HitTest(event.GetPosition());
433
434 if ( hit != m_winHitTest )
435 {
436 if ( hit != m_winPressed )
437 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_RELEASE, m_winPressed);
438 else
439 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
440
441 m_winHitTest = hit;
442 return TRUE;
443 }
444 }
445
446 return wxStdInputHandler::HandleMouseMove(consumer, event);
447 }
448
449 bool wxStdFrameInputHandler::HandleActivation(wxInputConsumer *consumer,
450 bool activated)
451 {
452 consumer->PerformAction(wxACTION_TOPLEVEL_ACTIVATE, activated);
453 return FALSE;
454 }