]> git.saurik.com Git - wxWidgets.git/blob - src/univ/topluniv.cpp
don't include scrollbar area in client size
[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;
243 wxSize size = GetSize();
244 rect.x =
245 rect.y = 0;
246 rect.width = size.x;
247 rect.height = size.y;
248
249 wxWindowDC dc(this);
250 m_renderer->DrawFrameTitleBar(dc, rect,
251 GetTitle(), m_titlebarIcon,
252 GetDecorationsStyle(),
253 m_pressedButton,
254 wxCONTROL_PRESSED);
255 }
256 }
257
258 long wxTopLevelWindow::HitTest(const wxPoint& pt) const
259 {
260 int w, h;
261 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
262 wxRect rect(wxTopLevelWindowNative::GetClientAreaOrigin(), wxSize(w, h));
263
264 return m_renderer->HitTestFrame(rect, pt+GetClientAreaOrigin(), GetDecorationsStyle());
265 }
266
267 int wxTopLevelWindow::GetMinWidth() const
268 {
269 if ( ms_drawDecorations )
270 {
271 return wxMax(wxTopLevelWindowNative::GetMinWidth(),
272 m_renderer->GetFrameMinSize(GetDecorationsStyle()).x);
273 }
274 else
275 return wxTopLevelWindowNative::GetMinWidth();
276 }
277
278 int wxTopLevelWindow::GetMinHeight() const
279 {
280 if ( ms_drawDecorations )
281 {
282 return wxMax(wxTopLevelWindowNative::GetMinHeight(),
283 m_renderer->GetFrameMinSize(GetDecorationsStyle()).y);
284 }
285 else
286 return wxTopLevelWindowNative::GetMinHeight();
287 }
288
289 // ----------------------------------------------------------------------------
290 // icons
291 // ----------------------------------------------------------------------------
292
293 void wxTopLevelWindow::SetIcons(const wxIconBundle& icons)
294 {
295 wxTopLevelWindowNative::SetIcons(icons);
296
297 if ( ms_drawDecorations && m_renderer )
298 {
299 wxSize size = m_renderer->GetFrameIconSize();
300 const wxIcon& icon = icons.GetIcon( size );
301
302 if ( !icon.Ok() || size.x == wxDefaultCoord )
303 m_titlebarIcon = icon;
304 else
305 {
306 wxBitmap bmp1;
307 bmp1.CopyFromIcon(icon);
308 if ( !bmp1.Ok() )
309 m_titlebarIcon = wxNullIcon;
310 else if ( bmp1.GetWidth() == size.x && bmp1.GetHeight() == size.y )
311 m_titlebarIcon = icon;
312 else
313 {
314 wxImage img = bmp1.ConvertToImage();
315 img.Rescale(size.x, size.y);
316 m_titlebarIcon.CopyFromBitmap(wxBitmap(img));
317 }
318 }
319 }
320 }
321
322 // ----------------------------------------------------------------------------
323 // interactive manipulation
324 // ----------------------------------------------------------------------------
325
326
327 static bool wxGetResizingCursor(long hitTestResult, wxCursor& cursor)
328 {
329 if ( hitTestResult & wxHT_TOPLEVEL_ANY_BORDER )
330 {
331 switch (hitTestResult)
332 {
333 case wxHT_TOPLEVEL_BORDER_N:
334 case wxHT_TOPLEVEL_BORDER_S:
335 cursor = wxCursor(wxCURSOR_SIZENS);
336 break;
337 case wxHT_TOPLEVEL_BORDER_W:
338 case wxHT_TOPLEVEL_BORDER_E:
339 cursor = wxCursor(wxCURSOR_SIZEWE);
340 break;
341 case wxHT_TOPLEVEL_BORDER_NE:
342 case wxHT_TOPLEVEL_BORDER_SW:
343 cursor = wxCursor(wxCURSOR_SIZENESW);
344 break;
345 case wxHT_TOPLEVEL_BORDER_NW:
346 case wxHT_TOPLEVEL_BORDER_SE:
347 cursor = wxCursor(wxCURSOR_SIZENWSE);
348 break;
349 default:
350 return false;
351 }
352 return true;
353 }
354
355 return false;
356 }
357
358 #define wxINTERACTIVE_RESIZE_DIR \
359 (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E | \
360 wxINTERACTIVE_RESIZE_S | wxINTERACTIVE_RESIZE_N)
361
362 struct wxInteractiveMoveData
363 {
364 wxTopLevelWindow *m_window;
365 wxEventLoop *m_evtLoop;
366 int m_flags;
367 wxRect m_rect;
368 wxRect m_rectOrig;
369 wxPoint m_pos;
370 wxSize m_minSize, m_maxSize;
371 bool m_sizingCursor;
372 };
373
374 class wxInteractiveMoveHandler : public wxEvtHandler
375 {
376 public:
377 wxInteractiveMoveHandler(wxInteractiveMoveData& data) : m_data(data) {}
378
379 private:
380 DECLARE_EVENT_TABLE()
381 void OnMouseMove(wxMouseEvent& event);
382 void OnMouseDown(wxMouseEvent& event);
383 void OnMouseUp(wxMouseEvent& event);
384 void OnKeyDown(wxKeyEvent& event);
385
386 wxInteractiveMoveData& m_data;
387 };
388
389 BEGIN_EVENT_TABLE(wxInteractiveMoveHandler, wxEvtHandler)
390 EVT_MOTION(wxInteractiveMoveHandler::OnMouseMove)
391 EVT_LEFT_DOWN(wxInteractiveMoveHandler::OnMouseDown)
392 EVT_LEFT_UP(wxInteractiveMoveHandler::OnMouseUp)
393 EVT_KEY_DOWN(wxInteractiveMoveHandler::OnKeyDown)
394 END_EVENT_TABLE()
395
396
397 static inline LINKAGEMODE
398 void wxApplyResize(wxInteractiveMoveData& data, const wxPoint& diff)
399 {
400 if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
401 {
402 data.m_rect.x += diff.x;
403 data.m_rect.width -= diff.x;
404 }
405 else if ( data.m_flags & wxINTERACTIVE_RESIZE_E )
406 {
407 data.m_rect.width += diff.x;
408 }
409 if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
410 {
411 data.m_rect.y += diff.y;
412 data.m_rect.height -= diff.y;
413 }
414 else if ( data.m_flags & wxINTERACTIVE_RESIZE_S )
415 {
416 data.m_rect.height += diff.y;
417 }
418
419 if ( data.m_minSize.x != wxDefaultCoord && data.m_rect.width < data.m_minSize.x )
420 {
421 if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
422 data.m_rect.x -= data.m_minSize.x - data.m_rect.width;
423 data.m_rect.width = data.m_minSize.x;
424 }
425 if ( data.m_maxSize.x != wxDefaultCoord && data.m_rect.width > data.m_maxSize.x )
426 {
427 if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
428 data.m_rect.x -= data.m_minSize.x - data.m_rect.width;
429 data.m_rect.width = data.m_maxSize.x;
430 }
431 if ( data.m_minSize.y != wxDefaultCoord && data.m_rect.height < data.m_minSize.y )
432 {
433 if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
434 data.m_rect.y -= data.m_minSize.y - data.m_rect.height;
435 data.m_rect.height = data.m_minSize.y;
436 }
437 if ( data.m_maxSize.y != wxDefaultCoord && data.m_rect.height > data.m_maxSize.y )
438 {
439 if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
440 data.m_rect.y -= data.m_minSize.y - data.m_rect.height;
441 data.m_rect.height = data.m_maxSize.y;
442 }
443 }
444
445 void wxInteractiveMoveHandler::OnMouseMove(wxMouseEvent& event)
446 {
447 if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
448 event.Skip();
449
450 else if ( m_data.m_flags & wxINTERACTIVE_MOVE )
451 {
452 wxPoint diff = wxGetMousePosition() - m_data.m_pos;
453 m_data.m_rect = m_data.m_rectOrig;
454 m_data.m_rect.Offset(diff);
455 m_data.m_window->Move(m_data.m_rect.GetPosition());
456 }
457
458 else if ( m_data.m_flags & wxINTERACTIVE_RESIZE )
459 {
460 wxPoint diff = wxGetMousePosition() - m_data.m_pos;
461 m_data.m_rect = m_data.m_rectOrig;
462 wxApplyResize(m_data, diff);
463 m_data.m_window->SetSize(m_data.m_rect);
464 }
465 }
466
467 void wxInteractiveMoveHandler::OnMouseDown(wxMouseEvent& WXUNUSED(event))
468 {
469 if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
470 {
471 m_data.m_evtLoop->Exit();
472 }
473 }
474
475 void wxInteractiveMoveHandler::OnKeyDown(wxKeyEvent& event)
476 {
477 wxPoint diff(wxDefaultCoord,wxDefaultCoord);
478
479 switch ( event.GetKeyCode() )
480 {
481 case WXK_UP: diff = wxPoint(0, -16); break;
482 case WXK_DOWN: diff = wxPoint(0, 16); break;
483 case WXK_LEFT: diff = wxPoint(-16, 0); break;
484 case WXK_RIGHT: diff = wxPoint(16, 0); break;
485 case WXK_ESCAPE:
486 m_data.m_window->SetSize(m_data.m_rectOrig);
487 m_data.m_evtLoop->Exit();
488 return;
489 case WXK_RETURN:
490 m_data.m_evtLoop->Exit();
491 return;
492 }
493
494 if ( diff.x != wxDefaultCoord )
495 {
496 if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
497 {
498 m_data.m_flags &= ~wxINTERACTIVE_WAIT_FOR_INPUT;
499 if ( m_data.m_sizingCursor )
500 {
501 wxEndBusyCursor();
502 m_data.m_sizingCursor = false;
503 }
504
505 if ( m_data.m_flags & wxINTERACTIVE_MOVE )
506 {
507 m_data.m_pos = m_data.m_window->GetPosition() +
508 wxPoint(m_data.m_window->GetSize().x/2, 8);
509 }
510 }
511
512 wxPoint warp;
513 bool changeCur = false;
514
515 if ( m_data.m_flags & wxINTERACTIVE_MOVE )
516 {
517 m_data.m_rect.Offset(diff);
518 m_data.m_window->Move(m_data.m_rect.GetPosition());
519 warp = wxPoint(m_data.m_window->GetSize().x/2, 8);
520 }
521 else /* wxINTERACTIVE_RESIZE */
522 {
523 if ( !(m_data.m_flags &
524 (wxINTERACTIVE_RESIZE_N | wxINTERACTIVE_RESIZE_S)) )
525 {
526 if ( diff.y < 0 )
527 {
528 m_data.m_flags |= wxINTERACTIVE_RESIZE_N;
529 m_data.m_pos.y = m_data.m_window->GetPosition().y;
530 changeCur = true;
531 }
532 else if ( diff.y > 0 )
533 {
534 m_data.m_flags |= wxINTERACTIVE_RESIZE_S;
535 m_data.m_pos.y = m_data.m_window->GetPosition().y +
536 m_data.m_window->GetSize().y;
537 changeCur = true;
538 }
539 }
540 if ( !(m_data.m_flags &
541 (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E)) )
542 {
543 if ( diff.x < 0 )
544 {
545 m_data.m_flags |= wxINTERACTIVE_RESIZE_W;
546 m_data.m_pos.x = m_data.m_window->GetPosition().x;
547 changeCur = true;
548 }
549 else if ( diff.x > 0 )
550 {
551 m_data.m_flags |= wxINTERACTIVE_RESIZE_E;
552 m_data.m_pos.x = m_data.m_window->GetPosition().x +
553 m_data.m_window->GetSize().x;
554 changeCur = true;
555 }
556 }
557
558 wxApplyResize(m_data, diff);
559 m_data.m_window->SetSize(m_data.m_rect);
560
561 if ( m_data.m_flags & wxINTERACTIVE_RESIZE_W )
562 warp.x = 0;
563 else if ( m_data.m_flags & wxINTERACTIVE_RESIZE_E )
564 warp.x = m_data.m_window->GetSize().x-1;
565 else
566 warp.x = wxGetMousePosition().x - m_data.m_window->GetPosition().x;
567
568 if ( m_data.m_flags & wxINTERACTIVE_RESIZE_N )
569 warp.y = 0;
570 else if ( m_data.m_flags & wxINTERACTIVE_RESIZE_S )
571 warp.y = m_data.m_window->GetSize().y-1;
572 else
573 warp.y = wxGetMousePosition().y - m_data.m_window->GetPosition().y;
574 }
575
576 warp -= m_data.m_window->GetClientAreaOrigin();
577 m_data.m_window->WarpPointer(warp.x, warp.y);
578
579 if ( changeCur )
580 {
581 long hit = m_data.m_window->HitTest(warp);
582 wxCursor cur;
583 if ( wxGetResizingCursor(hit, cur) )
584 {
585 if ( m_data.m_sizingCursor )
586 wxEndBusyCursor();
587 wxBeginBusyCursor(&cur);
588 m_data.m_sizingCursor = true;
589 }
590 }
591 }
592 }
593
594 void wxInteractiveMoveHandler::OnMouseUp(wxMouseEvent& WXUNUSED(event))
595 {
596 m_data.m_evtLoop->Exit();
597 }
598
599
600 void wxTopLevelWindow::InteractiveMove(int flags)
601 {
602 wxASSERT_MSG( !((flags & wxINTERACTIVE_MOVE) && (flags & wxINTERACTIVE_RESIZE)),
603 wxT("can't move and resize window at the same time") );
604
605 wxASSERT_MSG( !(flags & wxINTERACTIVE_RESIZE) ||
606 (flags & wxINTERACTIVE_WAIT_FOR_INPUT) ||
607 (flags & wxINTERACTIVE_RESIZE_DIR),
608 wxT("direction of resizing not specified") );
609
610 wxInteractiveMoveData data;
611 wxEventLoop loop;
612
613 SetFocus();
614
615 #ifndef __WXGTK__
616 if ( flags & wxINTERACTIVE_WAIT_FOR_INPUT )
617 {
618 wxCursor sizingCursor(wxCURSOR_SIZING);
619 wxBeginBusyCursor(&sizingCursor);
620 data.m_sizingCursor = true;
621 }
622 else
623 #endif
624 data.m_sizingCursor = false;
625
626 data.m_window = this;
627 data.m_evtLoop = &loop;
628 data.m_flags = flags;
629 data.m_rect = data.m_rectOrig = GetRect();
630 data.m_pos = wxGetMousePosition();
631 data.m_minSize = wxSize(GetMinWidth(), GetMinHeight());
632 data.m_maxSize = wxSize(GetMaxWidth(), GetMaxHeight());
633
634 wxEvtHandler *handler = new wxInteractiveMoveHandler(data);
635 this->PushEventHandler(handler);
636
637 CaptureMouse();
638 loop.Run();
639 ReleaseMouse();
640
641 this->RemoveEventHandler(handler);
642 delete handler;
643
644 if ( data.m_sizingCursor )
645 wxEndBusyCursor();
646 }
647
648 // ----------------------------------------------------------------------------
649 // actions
650 // ----------------------------------------------------------------------------
651
652 void wxTopLevelWindow::ClickTitleBarButton(long button)
653 {
654 switch ( button )
655 {
656 case wxTOPLEVEL_BUTTON_CLOSE:
657 Close();
658 break;
659
660 case wxTOPLEVEL_BUTTON_ICONIZE:
661 Iconize();
662 break;
663
664 case wxTOPLEVEL_BUTTON_MAXIMIZE:
665 Maximize();
666 break;
667
668 case wxTOPLEVEL_BUTTON_RESTORE:
669 Restore();
670 break;
671
672 case wxTOPLEVEL_BUTTON_HELP:
673 #if wxUSE_HELP
674 {
675 wxContextHelp contextHelp(this);
676 }
677 #endif
678 break;
679
680 default:
681 wxFAIL_MSG(wxT("incorrect button specification"));
682 }
683 }
684
685 bool wxTopLevelWindow::PerformAction(const wxControlAction& action,
686 long numArg,
687 const wxString& WXUNUSED(strArg))
688 {
689 bool isActive = numArg != 0;
690
691 if ( action == wxACTION_TOPLEVEL_ACTIVATE )
692 {
693 if ( m_isActive != isActive )
694 {
695 m_isActive = isActive;
696 RefreshTitleBar();
697 }
698 return true;
699 }
700
701 else if ( action == wxACTION_TOPLEVEL_BUTTON_PRESS )
702 {
703 m_pressedButton = numArg;
704 RefreshTitleBar();
705 return true;
706 }
707
708 else if ( action == wxACTION_TOPLEVEL_BUTTON_RELEASE )
709 {
710 m_pressedButton = 0;
711 RefreshTitleBar();
712 return true;
713 }
714
715 else if ( action == wxACTION_TOPLEVEL_BUTTON_CLICK )
716 {
717 m_pressedButton = 0;
718 RefreshTitleBar();
719 ClickTitleBarButton(numArg);
720 return true;
721 }
722
723 else if ( action == wxACTION_TOPLEVEL_MOVE )
724 {
725 InteractiveMove(wxINTERACTIVE_MOVE);
726 return true;
727 }
728
729 else if ( action == wxACTION_TOPLEVEL_RESIZE )
730 {
731 int flags = wxINTERACTIVE_RESIZE;
732 if ( numArg & wxHT_TOPLEVEL_BORDER_N )
733 flags |= wxINTERACTIVE_RESIZE_N;
734 if ( numArg & wxHT_TOPLEVEL_BORDER_S )
735 flags |= wxINTERACTIVE_RESIZE_S;
736 if ( numArg & wxHT_TOPLEVEL_BORDER_W )
737 flags |= wxINTERACTIVE_RESIZE_W;
738 if ( numArg & wxHT_TOPLEVEL_BORDER_E )
739 flags |= wxINTERACTIVE_RESIZE_E;
740 InteractiveMove(flags);
741 return true;
742 }
743
744 else
745 return false;
746 }
747
748 void wxTopLevelWindow::OnSystemMenu(wxCommandEvent& event)
749 {
750 bool ret = true;
751
752 switch (event.GetId())
753 {
754 case wxID_CLOSE_FRAME:
755 ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
756 wxTOPLEVEL_BUTTON_CLOSE);
757 break;
758 case wxID_MOVE_FRAME:
759 InteractiveMove(wxINTERACTIVE_MOVE | wxINTERACTIVE_WAIT_FOR_INPUT);
760 break;
761 case wxID_RESIZE_FRAME:
762 InteractiveMove(wxINTERACTIVE_RESIZE | wxINTERACTIVE_WAIT_FOR_INPUT);
763 break;
764 case wxID_MAXIMIZE_FRAME:
765 ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
766 wxTOPLEVEL_BUTTON_MAXIMIZE);
767 break;
768 case wxID_ICONIZE_FRAME:
769 ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
770 wxTOPLEVEL_BUTTON_ICONIZE);
771 break;
772 case wxID_RESTORE_FRAME:
773 ret = PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
774 wxTOPLEVEL_BUTTON_RESTORE);
775 break;
776
777 default:
778 ret = false;
779 }
780
781 if ( !ret )
782 event.Skip();
783 }
784
785
786 // ============================================================================
787 // wxStdFrameInputHandler: handles focus, resizing and titlebar buttons clicks
788 // ============================================================================
789
790 wxStdFrameInputHandler::wxStdFrameInputHandler(wxInputHandler *inphand)
791 : wxStdInputHandler(inphand)
792 {
793 m_winCapture = NULL;
794 m_winHitTest = 0;
795 m_winPressed = 0;
796 m_borderCursorOn = false;
797 }
798
799 bool wxStdFrameInputHandler::HandleMouse(wxInputConsumer *consumer,
800 const wxMouseEvent& event)
801 {
802 // the button has 2 states: pressed and normal with the following
803 // transitions between them:
804 //
805 // normal -> left down -> capture mouse and go to pressed state
806 // pressed -> left up inside -> generate click -> go to normal
807 // outside ------------------>
808 //
809 // the other mouse buttons are ignored
810 if ( event.Button(1) )
811 {
812 if ( event.ButtonDown(1) )
813 {
814 wxTopLevelWindow *w = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
815 long hit = w->HitTest(event.GetPosition());
816
817 if ( hit & wxHT_TOPLEVEL_ANY_BUTTON )
818 {
819 m_winCapture = w;
820 m_winCapture->CaptureMouse();
821 m_winHitTest = hit;
822 m_winPressed = hit;
823 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
824 return true;
825 }
826 else if ( (hit & wxHT_TOPLEVEL_TITLEBAR) && !w->IsMaximized() )
827 {
828 consumer->PerformAction(wxACTION_TOPLEVEL_MOVE);
829 return true;
830 }
831 else if ( (consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER)
832 && (hit & wxHT_TOPLEVEL_ANY_BORDER) )
833 {
834 consumer->PerformAction(wxACTION_TOPLEVEL_RESIZE, hit);
835 return true;
836 }
837 }
838
839 else // up
840 {
841 if ( m_winCapture )
842 {
843 m_winCapture->ReleaseMouse();
844 m_winCapture = NULL;
845
846 if ( m_winHitTest == m_winPressed )
847 {
848 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, m_winPressed);
849 return true;
850 }
851 }
852 //else: the mouse was released outside the window, this doesn't
853 // count as a click
854 }
855 }
856
857 return wxStdInputHandler::HandleMouse(consumer, event);
858 }
859
860 bool wxStdFrameInputHandler::HandleMouseMove(wxInputConsumer *consumer,
861 const wxMouseEvent& event)
862 {
863 if ( event.GetEventObject() == m_winCapture )
864 {
865 long hit = m_winCapture->HitTest(event.GetPosition());
866
867 if ( hit != m_winHitTest )
868 {
869 if ( hit != m_winPressed )
870 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_RELEASE, m_winPressed);
871 else
872 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
873
874 m_winHitTest = hit;
875 return true;
876 }
877 }
878 else if ( consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER )
879 {
880 wxTopLevelWindow *win = wxStaticCast(consumer->GetInputWindow(),
881 wxTopLevelWindow);
882 long hit = win->HitTest(event.GetPosition());
883
884 if ( hit != m_winHitTest )
885 {
886 m_winHitTest = hit;
887
888 if ( m_borderCursorOn )
889 {
890 m_borderCursorOn = false;
891 win->SetCursor(m_origCursor);
892 }
893
894 if ( hit & wxHT_TOPLEVEL_ANY_BORDER )
895 {
896 wxCursor cur;
897
898 m_borderCursorOn = wxGetResizingCursor(hit, cur);
899 if ( m_borderCursorOn )
900 {
901 m_origCursor = win->GetCursor();
902 win->SetCursor(cur);
903 }
904 }
905 }
906 }
907
908 return wxStdInputHandler::HandleMouseMove(consumer, event);
909 }
910
911 bool wxStdFrameInputHandler::HandleActivation(wxInputConsumer *consumer,
912 bool activated)
913 {
914 if ( m_borderCursorOn )
915 {
916 consumer->GetInputWindow()->SetCursor(m_origCursor);
917 m_borderCursorOn = false;
918 }
919 consumer->PerformAction(wxACTION_TOPLEVEL_ACTIVATE, activated);
920 return false;
921 }