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