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