]> git.saurik.com Git - wxWidgets.git/blob - src/univ/topluniv.cpp
fixed crash in wxSpinButton (patch 646214)
[wxWidgets.git] / src / univ / topluniv.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: topluniv.cpp
3 // Author: Vaclav Slavik
4 // Id: $Id$
5 // Copyright: (c) 2001-2002 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
30 #ifndef WX_PRECOMP
31 #include "wx/dcclient.h"
32 #include "wx/settings.h"
33 #endif
34
35 #include "wx/toplevel.h"
36 #include "wx/univ/renderer.h"
37 #include "wx/bitmap.h"
38 #include "wx/image.h"
39 #include "wx/cshelp.h"
40 #include "wx/evtloop.h"
41
42
43 // ----------------------------------------------------------------------------
44 // event tables
45 // ----------------------------------------------------------------------------
46
47 BEGIN_EVENT_TABLE(wxTopLevelWindow, wxTopLevelWindowNative)
48 WX_EVENT_TABLE_INPUT_CONSUMER(wxTopLevelWindow)
49 EVT_NC_PAINT(wxTopLevelWindow::OnNcPaint)
50 EVT_MENU_RANGE(wxID_CLOSE_FRAME, wxID_RESTORE_FRAME, wxTopLevelWindow::OnSystemMenu)
51 END_EVENT_TABLE()
52
53 WX_FORWARD_TO_INPUT_CONSUMER(wxTopLevelWindow)
54
55 // ============================================================================
56 // implementation
57 // ============================================================================
58
59 int wxTopLevelWindow::ms_drawDecorations = -1;
60 int wxTopLevelWindow::ms_canIconize = -1;
61
62 void wxTopLevelWindow::Init()
63 {
64 m_isActive = FALSE;
65 m_windowStyle = 0;
66 m_pressedButton = 0;
67 }
68
69 bool wxTopLevelWindow::Create(wxWindow *parent,
70 wxWindowID id,
71 const wxString& title,
72 const wxPoint& pos,
73 const wxSize& size,
74 long style,
75 const wxString &name)
76 {
77 // init them to avoid compiler warnings
78 long styleOrig = 0,
79 exstyleOrig = 0;
80
81 if ( ms_drawDecorations == -1 )
82 {
83 ms_drawDecorations =
84 !wxSystemSettings::HasFeature(wxSYS_CAN_DRAW_FRAME_DECORATIONS)
85 || wxGetEnv(wxT("WXDECOR"), NULL);
86 // FIXME -- wxUniv should provide a way to force non-native decorations!
87 // $WXDECOR is just a hack in absence of better wxUniv solution
88 }
89
90 if ( ms_canIconize == -1 )
91 {
92 ms_canIconize = wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME);
93 }
94
95 if ( ms_drawDecorations )
96 {
97 CreateInputHandler(wxINP_HANDLER_TOPLEVEL);
98
99 styleOrig = style;
100 exstyleOrig = GetExtraStyle();
101 style &= ~(wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX |
102 wxSYSTEM_MENU | wxRESIZE_BORDER | wxFRAME_TOOL_WINDOW |
103 wxTHICK_FRAME);
104 style = wxSIMPLE_BORDER;
105 SetExtraStyle(exstyleOrig &
106 ~(wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP));
107 }
108
109 if ( !wxTopLevelWindowNative::Create(parent, id, title, pos,
110 size, style, name) )
111 return FALSE;
112
113 if ( ms_drawDecorations )
114 {
115 m_windowStyle = styleOrig;
116 m_exStyle = exstyleOrig;
117 }
118
119 return TRUE;
120 }
121
122 bool wxTopLevelWindow::ShowFullScreen(bool show, long style)
123 {
124 if ( show == IsFullScreen() ) return FALSE;
125
126 if ( ms_drawDecorations )
127 {
128 if ( show )
129 {
130 m_fsSavedStyle = m_windowStyle;
131 if ( style & wxFULLSCREEN_NOBORDER )
132 m_windowStyle |= wxSIMPLE_BORDER;
133 if ( style & wxFULLSCREEN_NOCAPTION )
134 m_windowStyle &= ~wxCAPTION;
135 }
136 else
137 {
138 m_windowStyle = m_fsSavedStyle;
139 }
140 }
141
142 return wxTopLevelWindowNative::ShowFullScreen(show, style);
143 }
144
145 long wxTopLevelWindow::GetDecorationsStyle() const
146 {
147 long style = 0;
148
149 if ( m_windowStyle & wxCAPTION )
150 {
151 style |= wxTOPLEVEL_TITLEBAR | wxTOPLEVEL_BUTTON_CLOSE;
152 if ( (m_windowStyle & wxMINIMIZE_BOX) && ms_canIconize )
153 style |= wxTOPLEVEL_BUTTON_ICONIZE;
154 if ( m_windowStyle & wxMAXIMIZE_BOX )
155 {
156 if ( IsMaximized() )
157 style |= wxTOPLEVEL_BUTTON_RESTORE;
158 else
159 style |= wxTOPLEVEL_BUTTON_MAXIMIZE;
160 }
161 #if wxUSE_HELP
162 if ( m_exStyle & (wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP))
163 style |= wxTOPLEVEL_BUTTON_HELP;
164 #endif
165 }
166 if ( (m_windowStyle & (wxSIMPLE_BORDER | wxNO_BORDER)) == 0 )
167 style |= wxTOPLEVEL_BORDER;
168 if ( m_windowStyle & (wxRESIZE_BORDER | wxTHICK_FRAME) )
169 style |= wxTOPLEVEL_RESIZEABLE;
170
171 if ( IsMaximized() )
172 style |= wxTOPLEVEL_MAXIMIZED;
173 if ( GetIcon().Ok() )
174 style |= wxTOPLEVEL_ICON;
175 if ( m_isActive )
176 style |= wxTOPLEVEL_ACTIVE;
177
178 return style;
179 }
180
181 void wxTopLevelWindow::RefreshTitleBar()
182 {
183 wxNcPaintEvent event(GetId());
184 event.SetEventObject(this);
185 GetEventHandler()->ProcessEvent(event);
186 }
187
188 // ----------------------------------------------------------------------------
189 // client area handling
190 // ----------------------------------------------------------------------------
191
192 wxPoint wxTopLevelWindow::GetClientAreaOrigin() const
193 {
194 if ( ms_drawDecorations )
195 {
196 int w, h;
197 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
198 wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(),
199 wxSize(w, h));
200 rect = m_renderer->GetFrameClientArea(rect,
201 GetDecorationsStyle());
202 return rect.GetPosition();
203 }
204 else
205 {
206 return wxTopLevelWindowNative::GetClientAreaOrigin();
207 }
208 }
209
210 void wxTopLevelWindow::DoGetClientSize(int *width, int *height) const
211 {
212 if ( ms_drawDecorations )
213 {
214 int w, h;
215 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
216 wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(),
217 wxSize(w, h));
218 rect = m_renderer->GetFrameClientArea(rect,
219 GetDecorationsStyle());
220 if ( width )
221 *width = rect.width;
222 if ( height )
223 *height = rect.height;
224 }
225 else
226 wxTopLevelWindowNative::DoGetClientSize(width, height);
227 }
228
229 void wxTopLevelWindow::DoSetClientSize(int width, int height)
230 {
231 if ( ms_drawDecorations )
232 {
233 wxSize size = m_renderer->GetFrameTotalSize(wxSize(width, height),
234 GetDecorationsStyle());
235 wxTopLevelWindowNative::DoSetClientSize(size.x, size.y);
236 }
237 else
238 wxTopLevelWindowNative::DoSetClientSize(width, height);
239 }
240
241 void wxTopLevelWindow::OnNcPaint(wxPaintEvent& event)
242 {
243 if ( !ms_drawDecorations || !m_renderer )
244 event.Skip();
245 else
246 {
247 // get the window rect
248 wxRect rect;
249 wxSize size = GetSize();
250 rect.x =
251 rect.y = 0;
252 rect.width = size.x;
253 rect.height = size.y;
254
255 wxWindowDC dc(this);
256 m_renderer->DrawFrameTitleBar(dc, rect,
257 GetTitle(), m_titlebarIcon,
258 GetDecorationsStyle(),
259 m_pressedButton,
260 wxCONTROL_PRESSED);
261 }
262 }
263
264 long wxTopLevelWindow::HitTest(const wxPoint& pt) const
265 {
266 int w, h;
267 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
268 wxRect rect(wxTopLevelWindowNative::GetClientAreaOrigin(), wxSize(w, h));
269
270 return m_renderer->HitTestFrame(rect, pt+GetClientAreaOrigin(), GetDecorationsStyle());
271 }
272
273 int wxTopLevelWindow::GetMinWidth() const
274 {
275 if ( ms_drawDecorations )
276 {
277 return wxMax(wxTopLevelWindowNative::GetMinWidth(),
278 m_renderer->GetFrameMinSize(GetDecorationsStyle()).x);
279 }
280 else
281 return wxTopLevelWindowNative::GetMinWidth();
282 }
283
284 int wxTopLevelWindow::GetMinHeight() const
285 {
286 if ( ms_drawDecorations )
287 {
288 return wxMax(wxTopLevelWindowNative::GetMinHeight(),
289 m_renderer->GetFrameMinSize(GetDecorationsStyle()).y);
290 }
291 else
292 return wxTopLevelWindowNative::GetMinHeight();
293 }
294
295 // ----------------------------------------------------------------------------
296 // icons
297 // ----------------------------------------------------------------------------
298
299 void wxTopLevelWindow::SetIcons(const wxIconBundle& icons)
300 {
301 wxTopLevelWindowNative::SetIcons(icons);
302
303 if ( ms_drawDecorations && m_renderer )
304 {
305 wxSize size = m_renderer->GetFrameIconSize();
306 const wxIcon& icon = icons.GetIcon( size );
307
308 if ( !icon.Ok() || size.x == -1 )
309 m_titlebarIcon = icon;
310 else
311 {
312 wxBitmap bmp1;
313 bmp1.CopyFromIcon(icon);
314 if ( !bmp1.Ok() )
315 m_titlebarIcon = wxNullIcon;
316 else if ( bmp1.GetWidth() == size.x && bmp1.GetHeight() == size.y )
317 m_titlebarIcon = icon;
318 else
319 {
320 wxImage img = bmp1.ConvertToImage();
321 img.Rescale(size.x, size.y);
322 m_titlebarIcon.CopyFromBitmap(wxBitmap(img));
323 }
324 }
325 }
326 }
327
328 // ----------------------------------------------------------------------------
329 // interactive manipulation
330 // ----------------------------------------------------------------------------
331
332
333 static bool wxGetResizingCursor(long hitTestResult, wxCursor& cursor)
334 {
335 if ( hitTestResult & wxHT_TOPLEVEL_ANY_BORDER )
336 {
337 switch (hitTestResult)
338 {
339 case wxHT_TOPLEVEL_BORDER_N:
340 case wxHT_TOPLEVEL_BORDER_S:
341 cursor = wxCursor(wxCURSOR_SIZENS);
342 break;
343 case wxHT_TOPLEVEL_BORDER_W:
344 case wxHT_TOPLEVEL_BORDER_E:
345 cursor = wxCursor(wxCURSOR_SIZEWE);
346 break;
347 case wxHT_TOPLEVEL_BORDER_NE:
348 case wxHT_TOPLEVEL_BORDER_SW:
349 cursor = wxCursor(wxCURSOR_SIZENESW);
350 break;
351 case wxHT_TOPLEVEL_BORDER_NW:
352 case wxHT_TOPLEVEL_BORDER_SE:
353 cursor = wxCursor(wxCURSOR_SIZENWSE);
354 break;
355 default:
356 return FALSE;
357 break;
358 }
359 return TRUE;
360 }
361
362 return FALSE;
363 }
364
365 #define wxINTERACTIVE_RESIZE_DIR \
366 (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E | \
367 wxINTERACTIVE_RESIZE_S | wxINTERACTIVE_RESIZE_N)
368
369 struct wxInteractiveMoveData
370 {
371 wxTopLevelWindow *m_window;
372 wxEventLoop *m_evtLoop;
373 int m_flags;
374 wxRect m_rect;
375 wxRect m_rectOrig;
376 wxPoint m_pos;
377 wxSize m_minSize, m_maxSize;
378 bool m_sizingCursor;
379 };
380
381 class wxInteractiveMoveHandler : public wxEvtHandler
382 {
383 public:
384 wxInteractiveMoveHandler(wxInteractiveMoveData& data) : m_data(data) {}
385
386 private:
387 DECLARE_EVENT_TABLE()
388 void OnMouseMove(wxMouseEvent& event);
389 void OnMouseDown(wxMouseEvent& event);
390 void OnMouseUp(wxMouseEvent& event);
391 void OnKeyDown(wxKeyEvent& event);
392
393 wxInteractiveMoveData& m_data;
394 };
395
396 BEGIN_EVENT_TABLE(wxInteractiveMoveHandler, wxEvtHandler)
397 EVT_MOTION(wxInteractiveMoveHandler::OnMouseMove)
398 EVT_LEFT_DOWN(wxInteractiveMoveHandler::OnMouseDown)
399 EVT_LEFT_UP(wxInteractiveMoveHandler::OnMouseUp)
400 EVT_KEY_DOWN(wxInteractiveMoveHandler::OnKeyDown)
401 END_EVENT_TABLE()
402
403
404 static inline LINKAGEMODE
405 void wxApplyResize(wxInteractiveMoveData& data, const wxPoint& diff)
406 {
407 if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
408 {
409 data.m_rect.x += diff.x;
410 data.m_rect.width -= diff.x;
411 }
412 else if ( data.m_flags & wxINTERACTIVE_RESIZE_E )
413 {
414 data.m_rect.width += diff.x;
415 }
416 if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
417 {
418 data.m_rect.y += diff.y;
419 data.m_rect.height -= diff.y;
420 }
421 else if ( data.m_flags & wxINTERACTIVE_RESIZE_S )
422 {
423 data.m_rect.height += diff.y;
424 }
425
426 if ( data.m_minSize.x != -1 && data.m_rect.width < data.m_minSize.x )
427 {
428 if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
429 data.m_rect.x -= data.m_minSize.x - data.m_rect.width;
430 data.m_rect.width = data.m_minSize.x;
431 }
432 if ( data.m_maxSize.x != -1 && data.m_rect.width > data.m_maxSize.x )
433 {
434 if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
435 data.m_rect.x -= data.m_minSize.x - data.m_rect.width;
436 data.m_rect.width = data.m_maxSize.x;
437 }
438 if ( data.m_minSize.y != -1 && data.m_rect.height < data.m_minSize.y )
439 {
440 if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
441 data.m_rect.y -= data.m_minSize.y - data.m_rect.height;
442 data.m_rect.height = data.m_minSize.y;
443 }
444 if ( data.m_maxSize.y != -1 && data.m_rect.height > data.m_maxSize.y )
445 {
446 if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
447 data.m_rect.y -= data.m_minSize.y - data.m_rect.height;
448 data.m_rect.height = data.m_maxSize.y;
449 }
450 }
451
452 void wxInteractiveMoveHandler::OnMouseMove(wxMouseEvent& event)
453 {
454 if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
455 event.Skip();
456
457 else if ( m_data.m_flags & wxINTERACTIVE_MOVE )
458 {
459 wxPoint diff = wxGetMousePosition() - m_data.m_pos;
460 m_data.m_rect = m_data.m_rectOrig;
461 m_data.m_rect.Offset(diff);
462 m_data.m_window->Move(m_data.m_rect.GetPosition());
463 }
464
465 else if ( m_data.m_flags & wxINTERACTIVE_RESIZE )
466 {
467 wxPoint diff = wxGetMousePosition() - m_data.m_pos;
468 m_data.m_rect = m_data.m_rectOrig;
469 wxApplyResize(m_data, diff);
470 m_data.m_window->SetSize(m_data.m_rect);
471 }
472 }
473
474 void wxInteractiveMoveHandler::OnMouseDown(wxMouseEvent& event)
475 {
476 if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
477 {
478 m_data.m_evtLoop->Exit();
479 }
480 }
481
482 void wxInteractiveMoveHandler::OnKeyDown(wxKeyEvent& event)
483 {
484 wxPoint diff(-1,-1);
485
486 switch ( event.GetKeyCode() )
487 {
488 case WXK_UP: diff = wxPoint(0, -16); break;
489 case WXK_DOWN: diff = wxPoint(0, 16); break;
490 case WXK_LEFT: diff = wxPoint(-16, 0); break;
491 case WXK_RIGHT: diff = wxPoint(16, 0); break;
492 case WXK_ESCAPE:
493 m_data.m_window->SetSize(m_data.m_rectOrig);
494 m_data.m_evtLoop->Exit();
495 return;
496 case WXK_RETURN:
497 m_data.m_evtLoop->Exit();
498 return;
499 }
500
501 if ( diff.x != -1 )
502 {
503 if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
504 {
505 m_data.m_flags &= ~wxINTERACTIVE_WAIT_FOR_INPUT;
506 if ( m_data.m_sizingCursor )
507 {
508 wxEndBusyCursor();
509 m_data.m_sizingCursor = FALSE;
510 }
511
512 if ( m_data.m_flags & wxINTERACTIVE_MOVE )
513 {
514 m_data.m_pos = m_data.m_window->GetPosition() +
515 wxPoint(m_data.m_window->GetSize().x/2, 8);
516 }
517 }
518
519 wxPoint warp;
520 bool changeCur = FALSE;
521
522 if ( m_data.m_flags & wxINTERACTIVE_MOVE )
523 {
524 m_data.m_rect.Offset(diff);
525 m_data.m_window->Move(m_data.m_rect.GetPosition());
526 warp = wxPoint(m_data.m_window->GetSize().x/2, 8);
527 }
528 else /* wxINTERACTIVE_RESIZE */
529 {
530 if ( !(m_data.m_flags &
531 (wxINTERACTIVE_RESIZE_N | wxINTERACTIVE_RESIZE_S)) )
532 {
533 if ( diff.y < 0 )
534 {
535 m_data.m_flags |= wxINTERACTIVE_RESIZE_N;
536 m_data.m_pos.y = m_data.m_window->GetPosition().y;
537 changeCur = TRUE;
538 }
539 else if ( diff.y > 0 )
540 {
541 m_data.m_flags |= wxINTERACTIVE_RESIZE_S;
542 m_data.m_pos.y = m_data.m_window->GetPosition().y +
543 m_data.m_window->GetSize().y;
544 changeCur = TRUE;
545 }
546 }
547 if ( !(m_data.m_flags &
548 (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E)) )
549 {
550 if ( diff.x < 0 )
551 {
552 m_data.m_flags |= wxINTERACTIVE_RESIZE_W;
553 m_data.m_pos.x = m_data.m_window->GetPosition().x;
554 changeCur = TRUE;
555 }
556 else if ( diff.x > 0 )
557 {
558 m_data.m_flags |= wxINTERACTIVE_RESIZE_E;
559 m_data.m_pos.x = m_data.m_window->GetPosition().x +
560 m_data.m_window->GetSize().x;
561 changeCur = TRUE;
562 }
563 }
564
565 wxApplyResize(m_data, diff);
566 m_data.m_window->SetSize(m_data.m_rect);
567
568 if ( m_data.m_flags & wxINTERACTIVE_RESIZE_W )
569 warp.x = 0;
570 else if ( m_data.m_flags & wxINTERACTIVE_RESIZE_E )
571 warp.x = m_data.m_window->GetSize().x-1;
572 else
573 warp.x = wxGetMousePosition().x - m_data.m_window->GetPosition().x;
574
575 if ( m_data.m_flags & wxINTERACTIVE_RESIZE_N )
576 warp.y = 0;
577 else if ( m_data.m_flags & wxINTERACTIVE_RESIZE_S )
578 warp.y = m_data.m_window->GetSize().y-1;
579 else
580 warp.y = wxGetMousePosition().y - m_data.m_window->GetPosition().y;
581 }
582
583 warp -= m_data.m_window->GetClientAreaOrigin();
584 m_data.m_window->WarpPointer(warp.x, warp.y);
585
586 if ( changeCur )
587 {
588 long hit = m_data.m_window->HitTest(warp);
589 wxCursor cur;
590 if ( wxGetResizingCursor(hit, cur) )
591 {
592 if ( m_data.m_sizingCursor )
593 wxEndBusyCursor();
594 wxBeginBusyCursor(&cur);
595 m_data.m_sizingCursor = TRUE;
596 }
597 }
598 }
599 }
600
601 void wxInteractiveMoveHandler::OnMouseUp(wxMouseEvent& event)
602 {
603 m_data.m_evtLoop->Exit();
604 }
605
606
607 void wxTopLevelWindow::InteractiveMove(int flags)
608 {
609 wxASSERT_MSG( !((flags & wxINTERACTIVE_MOVE) && (flags & wxINTERACTIVE_RESIZE)),
610 wxT("can't move and resize window at the same time") );
611
612 wxASSERT_MSG( !(flags & wxINTERACTIVE_RESIZE) ||
613 (flags & wxINTERACTIVE_WAIT_FOR_INPUT) ||
614 (flags & wxINTERACTIVE_RESIZE_DIR),
615 wxT("direction of resizing not specified") );
616
617 wxInteractiveMoveData data;
618 wxEventLoop loop;
619
620 SetFocus();
621
622 #ifndef __WXGTK__
623 if ( flags & wxINTERACTIVE_WAIT_FOR_INPUT )
624 {
625 wxCursor sizingCursor(wxCURSOR_SIZING);
626 wxBeginBusyCursor(&sizingCursor);
627 data.m_sizingCursor = TRUE;
628 }
629 else
630 #endif
631 data.m_sizingCursor = FALSE;
632
633 data.m_window = this;
634 data.m_evtLoop = &loop;
635 data.m_flags = flags;
636 data.m_rect = data.m_rectOrig = GetRect();
637 data.m_pos = wxGetMousePosition();
638 data.m_minSize = wxSize(GetMinWidth(), GetMinHeight());
639 data.m_maxSize = wxSize(GetMaxWidth(), GetMaxHeight());
640
641 wxEvtHandler *handler = new wxInteractiveMoveHandler(data);
642 this->PushEventHandler(handler);
643
644 CaptureMouse();
645 loop.Run();
646 ReleaseMouse();
647
648 this->RemoveEventHandler(handler);
649 delete handler;
650
651 if ( data.m_sizingCursor )
652 wxEndBusyCursor();
653 }
654
655 // ----------------------------------------------------------------------------
656 // actions
657 // ----------------------------------------------------------------------------
658
659 void wxTopLevelWindow::ClickTitleBarButton(long button)
660 {
661 switch ( button )
662 {
663 case wxTOPLEVEL_BUTTON_CLOSE:
664 Close();
665 break;
666
667 case wxTOPLEVEL_BUTTON_ICONIZE:
668 Iconize();
669 break;
670
671 case wxTOPLEVEL_BUTTON_MAXIMIZE:
672 Maximize();
673 break;
674
675 case wxTOPLEVEL_BUTTON_RESTORE:
676 Restore();
677 break;
678
679 case wxTOPLEVEL_BUTTON_HELP:
680 #if wxUSE_HELP
681 {
682 wxContextHelp contextHelp(this);
683 }
684 #endif
685 break;
686
687 default:
688 wxFAIL_MSG(wxT("incorrect button specification"));
689 }
690 }
691
692 bool wxTopLevelWindow::PerformAction(const wxControlAction& action,
693 long numArg,
694 const wxString& strArg)
695 {
696 bool isActive = numArg != 0;
697
698 if ( action == wxACTION_TOPLEVEL_ACTIVATE )
699 {
700 if ( m_isActive != isActive )
701 {
702 m_isActive = isActive;
703 RefreshTitleBar();
704 }
705 return TRUE;
706 }
707
708 else if ( action == wxACTION_TOPLEVEL_BUTTON_PRESS )
709 {
710 m_pressedButton = numArg;
711 RefreshTitleBar();
712 return TRUE;
713 }
714
715 else if ( action == wxACTION_TOPLEVEL_BUTTON_RELEASE )
716 {
717 m_pressedButton = 0;
718 RefreshTitleBar();
719 return TRUE;
720 }
721
722 else if ( action == wxACTION_TOPLEVEL_BUTTON_CLICK )
723 {
724 m_pressedButton = 0;
725 RefreshTitleBar();
726 ClickTitleBarButton(numArg);
727 return TRUE;
728 }
729
730 else if ( action == wxACTION_TOPLEVEL_MOVE )
731 {
732 InteractiveMove(wxINTERACTIVE_MOVE);
733 return TRUE;
734 }
735
736 else if ( action == wxACTION_TOPLEVEL_RESIZE )
737 {
738 int flags = wxINTERACTIVE_RESIZE;
739 if ( numArg & wxHT_TOPLEVEL_BORDER_N )
740 flags |= wxINTERACTIVE_RESIZE_N;
741 if ( numArg & wxHT_TOPLEVEL_BORDER_S )
742 flags |= wxINTERACTIVE_RESIZE_S;
743 if ( numArg & wxHT_TOPLEVEL_BORDER_W )
744 flags |= wxINTERACTIVE_RESIZE_W;
745 if ( numArg & wxHT_TOPLEVEL_BORDER_E )
746 flags |= wxINTERACTIVE_RESIZE_E;
747 InteractiveMove(flags);
748 return TRUE;
749 }
750
751 else
752 return FALSE;
753 }
754
755 void wxTopLevelWindow::OnSystemMenu(wxCommandEvent& event)
756 {
757 bool ret = TRUE;
758
759 switch (event.GetId())
760 {
761 case wxID_CLOSE_FRAME:
762 ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
763 wxTOPLEVEL_BUTTON_CLOSE);
764 break;
765 case wxID_MOVE_FRAME:
766 InteractiveMove(wxINTERACTIVE_MOVE | wxINTERACTIVE_WAIT_FOR_INPUT);
767 break;
768 case wxID_RESIZE_FRAME:
769 InteractiveMove(wxINTERACTIVE_RESIZE | wxINTERACTIVE_WAIT_FOR_INPUT);
770 break;
771 case wxID_MAXIMIZE_FRAME:
772 ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
773 wxTOPLEVEL_BUTTON_MAXIMIZE);
774 break;
775 case wxID_ICONIZE_FRAME:
776 ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
777 wxTOPLEVEL_BUTTON_ICONIZE);
778 break;
779 case wxID_RESTORE_FRAME:
780 ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
781 wxTOPLEVEL_BUTTON_RESTORE);
782 break;
783
784 default:
785 ret = FALSE;
786 }
787
788 if ( !ret )
789 event.Skip();
790 }
791
792
793 // ============================================================================
794 // wxStdFrameInputHandler: handles focus, resizing and titlebar buttons clicks
795 // ============================================================================
796
797 wxStdFrameInputHandler::wxStdFrameInputHandler(wxInputHandler *inphand)
798 : wxStdInputHandler(inphand)
799 {
800 m_winCapture = NULL;
801 m_winHitTest = 0;
802 m_winPressed = 0;
803 m_borderCursorOn = FALSE;
804 }
805
806 bool wxStdFrameInputHandler::HandleMouse(wxInputConsumer *consumer,
807 const wxMouseEvent& event)
808 {
809 // the button has 2 states: pressed and normal with the following
810 // transitions between them:
811 //
812 // normal -> left down -> capture mouse and go to pressed state
813 // pressed -> left up inside -> generate click -> go to normal
814 // outside ------------------>
815 //
816 // the other mouse buttons are ignored
817 if ( event.Button(1) )
818 {
819 if ( event.ButtonDown(1) )
820 {
821 wxTopLevelWindow *w = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
822 long hit = w->HitTest(event.GetPosition());
823
824 if ( hit & wxHT_TOPLEVEL_ANY_BUTTON )
825 {
826 m_winCapture = w;
827 m_winCapture->CaptureMouse();
828 m_winHitTest = hit;
829 m_winPressed = hit;
830 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
831 return TRUE;
832 }
833 else if ( (hit & wxHT_TOPLEVEL_TITLEBAR) && !w->IsMaximized() )
834 {
835 consumer->PerformAction(wxACTION_TOPLEVEL_MOVE);
836 return TRUE;
837 }
838 else if ( (consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER)
839 && (hit & wxHT_TOPLEVEL_ANY_BORDER) )
840 {
841 consumer->PerformAction(wxACTION_TOPLEVEL_RESIZE, hit);
842 return TRUE;
843 }
844 }
845
846 else // up
847 {
848 if ( m_winCapture )
849 {
850 m_winCapture->ReleaseMouse();
851 m_winCapture = NULL;
852
853 if ( m_winHitTest == m_winPressed )
854 {
855 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, m_winPressed);
856 return TRUE;
857 }
858 }
859 //else: the mouse was released outside the window, this doesn't
860 // count as a click
861 }
862 }
863
864 return wxStdInputHandler::HandleMouse(consumer, event);
865 }
866
867 bool wxStdFrameInputHandler::HandleMouseMove(wxInputConsumer *consumer,
868 const wxMouseEvent& event)
869 {
870 if ( event.GetEventObject() == m_winCapture )
871 {
872 long hit = m_winCapture->HitTest(event.GetPosition());
873
874 if ( hit != m_winHitTest )
875 {
876 if ( hit != m_winPressed )
877 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_RELEASE, m_winPressed);
878 else
879 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
880
881 m_winHitTest = hit;
882 return TRUE;
883 }
884 }
885 else if ( consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER )
886 {
887 wxTopLevelWindow *win = wxStaticCast(consumer->GetInputWindow(),
888 wxTopLevelWindow);
889 long hit = win->HitTest(event.GetPosition());
890
891 if ( hit != m_winHitTest )
892 {
893 m_winHitTest = hit;
894
895 if ( m_borderCursorOn )
896 {
897 m_borderCursorOn = FALSE;
898 win->SetCursor(m_origCursor);
899 }
900
901 if ( hit & wxHT_TOPLEVEL_ANY_BORDER )
902 {
903 wxCursor cur;
904
905 m_borderCursorOn = wxGetResizingCursor(hit, cur);
906 if ( m_borderCursorOn )
907 {
908 m_origCursor = win->GetCursor();
909 win->SetCursor(cur);
910 }
911 }
912 }
913 }
914
915 return wxStdInputHandler::HandleMouseMove(consumer, event);
916 }
917
918 bool wxStdFrameInputHandler::HandleActivation(wxInputConsumer *consumer,
919 bool activated)
920 {
921 if ( m_borderCursorOn )
922 {
923 consumer->GetInputWindow()->SetCursor(m_origCursor);
924 m_borderCursorOn = FALSE;
925 }
926 consumer->PerformAction(wxACTION_TOPLEVEL_ACTIVATE, activated);
927 return FALSE;
928 }