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