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