]> git.saurik.com Git - wxWidgets.git/blame - src/univ/topluniv.cpp
make more wxImage methods const
[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;
214 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
215 wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(),
216 wxSize(w, h));
7ee7c43f 217 rect = m_renderer->GetFrameClientArea(rect,
24a23c35
VS
218 GetDecorationsStyle());
219 if ( width )
220 *width = rect.width;
221 if ( height )
222 *height = rect.height;
223 }
224 else
225 wxTopLevelWindowNative::DoGetClientSize(width, height);
226}
227
228void wxTopLevelWindow::DoSetClientSize(int width, int height)
229{
230 if ( ms_drawDecorations )
231 {
7ee7c43f 232 wxSize size = m_renderer->GetFrameTotalSize(wxSize(width, height),
24a23c35
VS
233 GetDecorationsStyle());
234 wxTopLevelWindowNative::DoSetClientSize(size.x, size.y);
235 }
236 else
237 wxTopLevelWindowNative::DoSetClientSize(width, height);
238}
239
240void wxTopLevelWindow::OnNcPaint(wxPaintEvent& event)
241{
242 if ( !ms_drawDecorations || !m_renderer )
243 event.Skip();
244 else
245 {
246 // get the window rect
247 wxRect rect;
248 wxSize size = GetSize();
249 rect.x =
250 rect.y = 0;
251 rect.width = size.x;
252 rect.height = size.y;
253
254 wxWindowDC dc(this);
7ee7c43f 255 m_renderer->DrawFrameTitleBar(dc, rect,
24a23c35 256 GetTitle(), m_titlebarIcon,
813edf09
VS
257 GetDecorationsStyle(),
258 m_pressedButton,
259 wxCONTROL_PRESSED);
24a23c35
VS
260 }
261}
262
813edf09
VS
263long wxTopLevelWindow::HitTest(const wxPoint& pt) const
264{
265 int w, h;
266 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
267 wxRect rect(wxTopLevelWindowNative::GetClientAreaOrigin(), wxSize(w, h));
7ee7c43f 268
badc44fe 269 return m_renderer->HitTestFrame(rect, pt+GetClientAreaOrigin(), GetDecorationsStyle());
813edf09
VS
270}
271
24a23c35
VS
272// ----------------------------------------------------------------------------
273// icons
274// ----------------------------------------------------------------------------
275
276void wxTopLevelWindow::SetIcon(const wxIcon& icon)
277{
278 wxTopLevelWindowNative::SetIcon(icon);
24a23c35 279
15678bec 280 if ( ms_drawDecorations && m_renderer )
24a23c35 281 {
15678bec
VS
282 wxSize size = m_renderer->GetFrameIconSize();
283
284 if ( !icon.Ok() || size.x == -1 )
24a23c35
VS
285 m_titlebarIcon = icon;
286 else
287 {
15678bec
VS
288 wxBitmap bmp1;
289 bmp1.CopyFromIcon(icon);
290 if ( !bmp1.Ok() )
291 m_titlebarIcon = wxNullIcon;
292 else if ( bmp1.GetWidth() == size.x && bmp1.GetHeight() == size.y )
293 m_titlebarIcon = icon;
294 else
295 {
296 wxImage img = bmp1.ConvertToImage();
297 img.Rescale(size.x, size.y);
298 m_titlebarIcon.CopyFromBitmap(wxBitmap(img));
299 }
24a23c35
VS
300 }
301 }
302}
ea1b0d6c 303
621b405f
VS
304// ----------------------------------------------------------------------------
305// interactive manipulation
306// ----------------------------------------------------------------------------
307
308#define wxINTERACTIVE_RESIZE_DIR \
309 (wxINTERACTIVE_RESIZE_W | wxINTERACTIVE_RESIZE_E | \
310 wxINTERACTIVE_RESIZE_S | wxINTERACTIVE_RESIZE_N)
311
312struct wxInteractiveMoveData
313{
314 wxTopLevelWindowBase *m_window;
315 wxEventLoop *m_evtLoop;
316 int m_flags;
317 wxRect m_rect;
318 wxRect m_rectOrig;
319 wxPoint m_pos;
320 wxSize m_minSize, m_maxSize;
321};
322
323class wxInteractiveMoveHandler : public wxEvtHandler
324{
325public:
326 wxInteractiveMoveHandler(wxInteractiveMoveData& data) : m_data(data) {}
327
328private:
329 DECLARE_EVENT_TABLE()
330 void OnMouseMove(wxMouseEvent& event);
331 void OnMouseDown(wxMouseEvent& event);
332 void OnMouseUp(wxMouseEvent& event);
333 void OnKeyDown(wxKeyEvent& event);
334
335 wxInteractiveMoveData& m_data;
336};
337
338BEGIN_EVENT_TABLE(wxInteractiveMoveHandler, wxEvtHandler)
339 EVT_MOTION(wxInteractiveMoveHandler::OnMouseMove)
340 EVT_LEFT_DOWN(wxInteractiveMoveHandler::OnMouseDown)
341 EVT_LEFT_UP(wxInteractiveMoveHandler::OnMouseUp)
342 EVT_KEY_DOWN(wxInteractiveMoveHandler::OnKeyDown)
343END_EVENT_TABLE()
344
345
346static inline LINKAGEMODE
347void wxApplyResize(wxInteractiveMoveData& data, const wxPoint& diff)
348{
349 if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
350 {
351 data.m_rect.x += diff.x;
352 data.m_rect.width -= diff.x;
353 }
354 else if ( data.m_flags & wxINTERACTIVE_RESIZE_E )
355 {
356 data.m_rect.width += diff.x;
357 }
358 if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
359 {
360 data.m_rect.y += diff.y;
361 data.m_rect.height -= diff.y;
362 }
363 else if ( data.m_flags & wxINTERACTIVE_RESIZE_S )
364 {
365 data.m_rect.height += diff.y;
366 }
367
368 if ( data.m_minSize.x != -1 && data.m_rect.width < data.m_minSize.x )
369 {
370 if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
371 data.m_rect.x -= data.m_minSize.x - data.m_rect.width;
372 data.m_rect.width = data.m_minSize.x;
373 }
374 if ( data.m_maxSize.x != -1 && data.m_rect.width > data.m_maxSize.x )
375 {
376 if ( data.m_flags & wxINTERACTIVE_RESIZE_W )
377 data.m_rect.x -= data.m_minSize.x - data.m_rect.width;
378 data.m_rect.width = data.m_maxSize.x;
379 }
380 if ( data.m_minSize.y != -1 && data.m_rect.height < data.m_minSize.y )
381 {
382 if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
383 data.m_rect.y -= data.m_minSize.y - data.m_rect.height;
384 data.m_rect.height = data.m_minSize.y;
385 }
386 if ( data.m_maxSize.y != -1 && data.m_rect.height > data.m_maxSize.y )
387 {
388 if ( data.m_flags & wxINTERACTIVE_RESIZE_N )
389 data.m_rect.y -= data.m_minSize.y - data.m_rect.height;
390 data.m_rect.height = data.m_maxSize.y;
391 }
392}
393
394void wxInteractiveMoveHandler::OnMouseMove(wxMouseEvent& event)
395{
396 if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
397 event.Skip();
398
399 else if ( m_data.m_flags & wxINTERACTIVE_MOVE )
400 {
401 wxPoint diff = wxGetMousePosition() - m_data.m_pos;
402 m_data.m_rect = m_data.m_rectOrig;
403 m_data.m_rect.Offset(diff);
404 m_data.m_window->Move(m_data.m_rect.GetPosition());
405 }
406
407 else if ( m_data.m_flags & wxINTERACTIVE_RESIZE )
408 {
409 wxPoint diff = wxGetMousePosition() - m_data.m_pos;
410 m_data.m_rect = m_data.m_rectOrig;
411 wxApplyResize(m_data, diff);
412 m_data.m_window->SetSize(m_data.m_rect);
413 }
414}
415
416void wxInteractiveMoveHandler::OnMouseDown(wxMouseEvent& event)
417{
418 if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
419 {
420 m_data.m_flags &= ~wxINTERACTIVE_WAIT_FOR_INPUT;
421 m_data.m_pos = wxGetMousePosition();
422 }
423}
424
425void wxInteractiveMoveHandler::OnKeyDown(wxKeyEvent& event)
426{
427 if ( m_data.m_flags & wxINTERACTIVE_WAIT_FOR_INPUT )
428 {
429 m_data.m_flags &= ~wxINTERACTIVE_WAIT_FOR_INPUT;
430 m_data.m_pos = wxGetMousePosition();
431 }
432
433 wxPoint diff(-1,-1);
434
435 switch ( event.GetKeyCode() )
436 {
437 case WXK_UP: diff = wxPoint(0, -16); break;
438 case WXK_DOWN: diff = wxPoint(0, 16); break;
439 case WXK_LEFT: diff = wxPoint(-16, 0); break;
440 case WXK_RIGHT: diff = wxPoint(16, 0); break;
441 case WXK_ESCAPE:
442 m_data.m_window->SetSize(m_data.m_rectOrig);
443 m_data.m_evtLoop->Exit();
444 return;
445 case WXK_RETURN:
446 m_data.m_evtLoop->Exit();
447 return;
448 }
449
450 if ( diff.x != -1 )
451 {
452 if ( m_data.m_flags & wxINTERACTIVE_MOVE )
453 {
454 m_data.m_rect.Offset(diff);
455 m_data.m_window->Move(m_data.m_rect.GetPosition());
456 }
457 else /* wxINTERACTIVE_RESIZE */
458 {
459 if ( !(m_data.m_flags & wxINTERACTIVE_RESIZE_DIR) )
460 {
461 if ( diff.y < 0 )
462 m_data.m_flags |= wxINTERACTIVE_RESIZE_N;
463 else if ( diff.y > 0 )
464 m_data.m_flags |= wxINTERACTIVE_RESIZE_S;
465 if ( diff.x < 0 )
466 m_data.m_flags |= wxINTERACTIVE_RESIZE_W;
467 else if ( diff.x > 0 )
468 m_data.m_flags |= wxINTERACTIVE_RESIZE_E;
469 }
470
471 wxApplyResize(m_data, diff);
472 m_data.m_window->SetSize(m_data.m_rect);
473 }
474 }
475}
476
477void wxInteractiveMoveHandler::OnMouseUp(wxMouseEvent& event)
478{
479 m_data.m_evtLoop->Exit();
480}
481
482
483void wxTopLevelWindow::InteractiveMove(int flags)
484{
485 wxASSERT_MSG( !((flags & wxINTERACTIVE_MOVE) && (flags & wxINTERACTIVE_RESIZE)),
486 wxT("can't move and resize window at the same time") );
487
488 wxASSERT_MSG( !(flags & wxINTERACTIVE_RESIZE) ||
489 (flags & wxINTERACTIVE_WAIT_FOR_INPUT) ||
490 (flags & wxINTERACTIVE_RESIZE_DIR),
491 wxT("direction of resizing not specified") );
492
493 wxInteractiveMoveData data;
494 wxEventLoop loop;
495 wxWindow *focus = FindFocus();
496
497 // FIXME - display resize cursor if waiting for initial input
498
499 data.m_window = this;
500 data.m_evtLoop = &loop;
501 data.m_flags = flags;
502 data.m_rect = data.m_rectOrig = GetRect();
503 data.m_pos = wxGetMousePosition();
504 data.m_minSize = wxSize(GetMinWidth(), GetMinHeight());
505 data.m_maxSize = wxSize(GetMaxWidth(), GetMaxHeight());
506
507 this->PushEventHandler(new wxInteractiveMoveHandler(data));
508 if ( focus )
509 focus->PushEventHandler(new wxInteractiveMoveHandler(data));
510
511 CaptureMouse();
512 loop.Run();
513 ReleaseMouse();
514
515 this->PopEventHandler(TRUE/*delete*/);
516 if ( focus )
517 focus->PopEventHandler(TRUE/*delete*/);
518}
519
ea1b0d6c
VS
520// ----------------------------------------------------------------------------
521// actions
522// ----------------------------------------------------------------------------
523
813edf09
VS
524void wxTopLevelWindow::ClickTitleBarButton(long button)
525{
526 switch ( button )
527 {
528 case wxTOPLEVEL_BUTTON_CLOSE:
529 Close();
530 break;
531
532 case wxTOPLEVEL_BUTTON_ICONIZE:
533 Iconize();
534 break;
535
536 case wxTOPLEVEL_BUTTON_MAXIMIZE:
537 Maximize();
538 break;
539
540 case wxTOPLEVEL_BUTTON_RESTORE:
541 Restore();
542 break;
543
544 case wxTOPLEVEL_BUTTON_HELP:
545#if wxUSE_HELP
546 {
547 wxContextHelp contextHelp(this);
548 }
549#endif
550 break;
7ee7c43f 551
813edf09
VS
552 default:
553 wxFAIL_MSG(wxT("incorrect button specification"));
554 }
555}
556
ea1b0d6c
VS
557bool wxTopLevelWindow::PerformAction(const wxControlAction& action,
558 long numArg,
559 const wxString& strArg)
560{
7ee7c43f
VZ
561 bool isActive = numArg != 0;
562
ea1b0d6c
VS
563 if ( action == wxACTION_TOPLEVEL_ACTIVATE )
564 {
7ee7c43f 565 if ( m_isActive != isActive )
ea1b0d6c 566 {
7ee7c43f 567 m_isActive = isActive;
b22d16ad 568 RefreshTitleBar();
ea1b0d6c
VS
569 }
570 return TRUE;
571 }
7ee7c43f 572
813edf09
VS
573 else if ( action == wxACTION_TOPLEVEL_BUTTON_PRESS )
574 {
575 m_pressedButton = numArg;
576 RefreshTitleBar();
577 return TRUE;
578 }
7ee7c43f 579
813edf09
VS
580 else if ( action == wxACTION_TOPLEVEL_BUTTON_RELEASE )
581 {
582 m_pressedButton = 0;
583 RefreshTitleBar();
584 return TRUE;
585 }
7ee7c43f 586
813edf09
VS
587 else if ( action == wxACTION_TOPLEVEL_BUTTON_CLICK )
588 {
589 m_pressedButton = 0;
590 RefreshTitleBar();
591 ClickTitleBarButton(numArg);
592 return TRUE;
593 }
71e03035 594
b22d16ad
VS
595 else if ( action == wxACTION_TOPLEVEL_MOVE )
596 {
597 InteractiveMove(wxINTERACTIVE_MOVE);
598 return TRUE;
599 }
71e03035 600
b22d16ad
VS
601 else if ( action == wxACTION_TOPLEVEL_RESIZE )
602 {
603 int flags = wxINTERACTIVE_RESIZE;
604 if ( numArg & wxHT_TOPLEVEL_BORDER_N )
605 flags |= wxINTERACTIVE_RESIZE_N;
606 if ( numArg & wxHT_TOPLEVEL_BORDER_S )
607 flags |= wxINTERACTIVE_RESIZE_S;
608 if ( numArg & wxHT_TOPLEVEL_BORDER_W )
609 flags |= wxINTERACTIVE_RESIZE_W;
610 if ( numArg & wxHT_TOPLEVEL_BORDER_E )
611 flags |= wxINTERACTIVE_RESIZE_E;
612 InteractiveMove(flags);
613 return TRUE;
614 }
71e03035 615
ea1b0d6c
VS
616 else
617 return FALSE;
618}
619
620
621// ============================================================================
622// wxStdFrameInputHandler: handles focus, resizing and titlebar buttons clicks
623// ============================================================================
624
625wxStdFrameInputHandler::wxStdFrameInputHandler(wxInputHandler *inphand)
626 : wxStdInputHandler(inphand)
627{
813edf09
VS
628 m_winCapture = NULL;
629 m_winHitTest = 0;
630 m_winPressed = 0;
b22d16ad 631 m_borderCursorOn = FALSE;
ea1b0d6c
VS
632}
633
634bool wxStdFrameInputHandler::HandleMouse(wxInputConsumer *consumer,
635 const wxMouseEvent& event)
636{
813edf09
VS
637 // the button has 2 states: pressed and normal with the following
638 // transitions between them:
639 //
640 // normal -> left down -> capture mouse and go to pressed state
641 // pressed -> left up inside -> generate click -> go to normal
642 // outside ------------------>
643 //
644 // the other mouse buttons are ignored
645 if ( event.Button(1) )
646 {
647 if ( event.ButtonDown(1) )
648 {
649 wxTopLevelWindow *w = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
650 long hit = w->HitTest(event.GetPosition());
7ee7c43f 651
813edf09
VS
652 if ( hit & wxHT_TOPLEVEL_ANY_BUTTON )
653 {
654 m_winCapture = w;
655 m_winCapture->CaptureMouse();
656 m_winHitTest = hit;
657 m_winPressed = hit;
658 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
659 return TRUE;
660 }
b22d16ad
VS
661 else if ( hit & wxHT_TOPLEVEL_TITLEBAR )
662 {
663 consumer->PerformAction(wxACTION_TOPLEVEL_MOVE);
664 return TRUE;
665 }
666 else if ( (consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER)
667 && (hit & wxHT_TOPLEVEL_ANY_BORDER) )
668 {
669 consumer->PerformAction(wxACTION_TOPLEVEL_RESIZE, hit);
670 return TRUE;
671 }
813edf09
VS
672 }
673
674 else // up
675 {
676 if ( m_winCapture )
677 {
678 m_winCapture->ReleaseMouse();
679 m_winCapture = NULL;
680
681 if ( m_winHitTest == m_winPressed )
682 {
683 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, m_winPressed);
684 return TRUE;
685 }
686 }
687 //else: the mouse was released outside the window, this doesn't
688 // count as a click
689 }
690 }
691
ea1b0d6c
VS
692 return wxStdInputHandler::HandleMouse(consumer, event);
693}
694
7ee7c43f 695bool wxStdFrameInputHandler::HandleMouseMove(wxInputConsumer *consumer,
ea1b0d6c
VS
696 const wxMouseEvent& event)
697{
813edf09
VS
698 if ( event.GetEventObject() == m_winCapture )
699 {
700 long hit = m_winCapture->HitTest(event.GetPosition());
701
702 if ( hit != m_winHitTest )
703 {
704 if ( hit != m_winPressed )
705 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_RELEASE, m_winPressed);
706 else
707 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
7ee7c43f 708
813edf09
VS
709 m_winHitTest = hit;
710 return TRUE;
711 }
712 }
b22d16ad
VS
713 else if ( consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER )
714 {
71e03035 715 wxTopLevelWindow *win = wxStaticCast(consumer->GetInputWindow(),
b22d16ad
VS
716 wxTopLevelWindow);
717 long hit = win->HitTest(event.GetPosition());
71e03035 718
b22d16ad
VS
719 if ( hit != m_winHitTest )
720 {
721 m_winHitTest = hit;
71e03035 722
b22d16ad
VS
723 if ( m_borderCursorOn )
724 {
725 m_borderCursorOn = FALSE;
726 win->SetCursor(m_origCursor);
727 }
71e03035 728
b22d16ad
VS
729 if ( hit & wxHT_TOPLEVEL_ANY_BORDER )
730 {
731 m_borderCursorOn = TRUE;
732 wxCursor cur;
71e03035 733
b22d16ad
VS
734 switch (hit)
735 {
736 case wxHT_TOPLEVEL_BORDER_N:
737 case wxHT_TOPLEVEL_BORDER_S:
738 cur = wxCursor(wxCURSOR_SIZENS);
739 break;
740 case wxHT_TOPLEVEL_BORDER_W:
741 case wxHT_TOPLEVEL_BORDER_E:
742 cur = wxCursor(wxCURSOR_SIZEWE);
743 break;
744 case wxHT_TOPLEVEL_BORDER_NE:
745 case wxHT_TOPLEVEL_BORDER_SW:
746 cur = wxCursor(wxCURSOR_SIZENESW);
747 break;
748 case wxHT_TOPLEVEL_BORDER_NW:
749 case wxHT_TOPLEVEL_BORDER_SE:
750 cur = wxCursor(wxCURSOR_SIZENWSE);
751 break;
752 default:
753 m_borderCursorOn = FALSE;
754 break;
755 }
756 if ( m_borderCursorOn )
757 {
758 m_origCursor = win->GetCursor();
759 win->SetCursor(cur);
760 }
761 }
762 }
763 }
813edf09 764
ea1b0d6c
VS
765 return wxStdInputHandler::HandleMouseMove(consumer, event);
766}
767
7ee7c43f 768bool wxStdFrameInputHandler::HandleActivation(wxInputConsumer *consumer,
ea1b0d6c
VS
769 bool activated)
770{
b22d16ad
VS
771 if ( m_borderCursorOn )
772 {
773 consumer->GetInputWindow()->SetCursor(m_origCursor);
774 m_borderCursorOn = FALSE;
775 }
ea1b0d6c
VS
776 consumer->PerformAction(wxACTION_TOPLEVEL_ACTIVATE, activated);
777 return FALSE;
778}