]> git.saurik.com Git - wxWidgets.git/blame - src/univ/topluniv.cpp
mention wx[Flex]GridSizer too
[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"
0f1bf77d
VS
40
41
42// ----------------------------------------------------------------------------
43// event tables
44// ----------------------------------------------------------------------------
45
24a23c35 46BEGIN_EVENT_TABLE(wxTopLevelWindow, wxTopLevelWindowNative)
ea1b0d6c 47 WX_EVENT_TABLE_INPUT_CONSUMER(wxTopLevelWindow)
24a23c35
VS
48 EVT_NC_PAINT(wxTopLevelWindow::OnNcPaint)
49END_EVENT_TABLE()
50
ea1b0d6c
VS
51WX_FORWARD_TO_INPUT_CONSUMER(wxTopLevelWindow)
52
0f1bf77d
VS
53// ============================================================================
54// implementation
55// ============================================================================
56
24a23c35
VS
57int wxTopLevelWindow::ms_drawDecorations = -1;
58
0f1bf77d
VS
59void wxTopLevelWindow::Init()
60{
24a23c35 61 m_isActive = FALSE;
ea1b0d6c 62 m_windowStyle = 0;
813edf09 63 m_pressedButton = 0;
0f1bf77d
VS
64}
65
66bool wxTopLevelWindow::Create(wxWindow *parent,
67 wxWindowID id,
68 const wxString& title,
69 const wxPoint& pos,
7ee7c43f 70 const wxSize& size,
0f1bf77d
VS
71 long style,
72 const wxString &name)
73{
2e9f62da
VZ
74 // init them to avoid compiler warnings
75 long styleOrig = 0,
76 exstyleOrig = 0;
24a23c35 77
b225f659 78 // FIXME -- wxUniv should provide a way to force non-native decorations!
24a23c35 79 if ( ms_drawDecorations == -1 )
f8e3449c 80 ms_drawDecorations = !wxSystemSettings::HasFrameDecorations();
24a23c35
VS
81
82 if ( ms_drawDecorations )
83 {
ea1b0d6c
VS
84 CreateInputHandler(wxINP_HANDLER_TOPLEVEL);
85
24a23c35
VS
86 styleOrig = style;
87 exstyleOrig = GetExtraStyle();
7ee7c43f
VZ
88 style &= ~(wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX |
89 wxSYSTEM_MENU | wxRESIZE_BORDER | wxFRAME_TOOL_WINDOW |
813edf09
VS
90 wxTHICK_FRAME);
91 style = wxSIMPLE_BORDER;
7ee7c43f 92 SetExtraStyle(exstyleOrig &
813edf09 93 ~(wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP));
24a23c35
VS
94 }
95
7ee7c43f
VZ
96 if ( !wxTopLevelWindowNative::Create(parent, id, title, pos,
97 size, style, name) )
98 return FALSE;
99
24a23c35
VS
100 if ( ms_drawDecorations )
101 {
102 m_windowStyle = styleOrig;
103 m_exStyle = exstyleOrig;
104 }
7ee7c43f 105
0f1bf77d
VS
106 return TRUE;
107}
108
109bool wxTopLevelWindow::ShowFullScreen(bool show, long style)
110{
111 if ( show == IsFullScreen() ) return FALSE;
7ee7c43f 112
ea1b0d6c
VS
113 if ( ms_drawDecorations )
114 {
115 if ( show )
116 {
117 m_fsSavedStyle = m_windowStyle;
118 if ( style & wxFULLSCREEN_NOBORDER )
119 m_windowStyle |= wxSIMPLE_BORDER;
120 if ( style & wxFULLSCREEN_NOCAPTION )
121 m_windowStyle &= ~wxCAPTION;
122 }
123 else
124 {
125 m_windowStyle = m_fsSavedStyle;
126 }
127 }
2e9f62da 128
ea1b0d6c 129 return wxTopLevelWindowNative::ShowFullScreen(show, style);
0f1bf77d
VS
130}
131
24a23c35
VS
132long wxTopLevelWindow::GetDecorationsStyle() const
133{
134 long style = 0;
135
136 if ( m_windowStyle & wxCAPTION )
137 {
ea1b0d6c 138 style |= wxTOPLEVEL_TITLEBAR | wxTOPLEVEL_BUTTON_CLOSE;
24a23c35 139 if ( m_windowStyle & wxMINIMIZE_BOX )
813edf09 140 style |= wxTOPLEVEL_BUTTON_ICONIZE;
24a23c35 141 if ( m_windowStyle & wxMAXIMIZE_BOX )
15678bec
VS
142 {
143 if ( IsMaximized() )
144 style |= wxTOPLEVEL_BUTTON_RESTORE;
145 else
146 style |= wxTOPLEVEL_BUTTON_MAXIMIZE;
147 }
813edf09 148#if wxUSE_HELP
24a23c35 149 if ( m_exStyle & (wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP))
ea1b0d6c 150 style |= wxTOPLEVEL_BUTTON_HELP;
813edf09 151#endif
24a23c35
VS
152 }
153 if ( (m_windowStyle & (wxSIMPLE_BORDER | wxNO_BORDER)) == 0 )
154 style |= wxTOPLEVEL_BORDER;
155 if ( m_windowStyle & (wxRESIZE_BORDER | wxTHICK_FRAME) )
156 style |= wxTOPLEVEL_RESIZEABLE;
7ee7c43f 157
24a23c35
VS
158 if ( IsMaximized() )
159 style |= wxTOPLEVEL_MAXIMIZED;
160 if ( GetIcon().Ok() )
161 style |= wxTOPLEVEL_ICON;
ea1b0d6c 162 if ( m_isActive )
24a23c35
VS
163 style |= wxTOPLEVEL_ACTIVE;
164
165 return style;
166}
167
813edf09
VS
168void wxTopLevelWindow::RefreshTitleBar()
169{
170 wxNcPaintEvent event(GetId());
171 event.SetEventObject(this);
172 GetEventHandler()->ProcessEvent(event);
173}
174
24a23c35
VS
175// ----------------------------------------------------------------------------
176// client area handling
177// ----------------------------------------------------------------------------
178
179wxPoint wxTopLevelWindow::GetClientAreaOrigin() const
180{
181 if ( ms_drawDecorations )
182 {
183 int w, h;
184 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
185 wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(),
186 wxSize(w, h));
7ee7c43f 187 rect = m_renderer->GetFrameClientArea(rect,
24a23c35
VS
188 GetDecorationsStyle());
189 return rect.GetPosition();
190 }
191 else
192 {
193 return wxTopLevelWindowNative::GetClientAreaOrigin();
194 }
195}
196
197void wxTopLevelWindow::DoGetClientSize(int *width, int *height) const
198{
199 if ( ms_drawDecorations )
200 {
201 int w, h;
202 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
203 wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(),
204 wxSize(w, h));
7ee7c43f 205 rect = m_renderer->GetFrameClientArea(rect,
24a23c35
VS
206 GetDecorationsStyle());
207 if ( width )
208 *width = rect.width;
209 if ( height )
210 *height = rect.height;
211 }
212 else
213 wxTopLevelWindowNative::DoGetClientSize(width, height);
214}
215
216void wxTopLevelWindow::DoSetClientSize(int width, int height)
217{
218 if ( ms_drawDecorations )
219 {
7ee7c43f 220 wxSize size = m_renderer->GetFrameTotalSize(wxSize(width, height),
24a23c35
VS
221 GetDecorationsStyle());
222 wxTopLevelWindowNative::DoSetClientSize(size.x, size.y);
223 }
224 else
225 wxTopLevelWindowNative::DoSetClientSize(width, height);
226}
227
228void wxTopLevelWindow::OnNcPaint(wxPaintEvent& event)
229{
230 if ( !ms_drawDecorations || !m_renderer )
231 event.Skip();
232 else
233 {
234 // get the window rect
235 wxRect rect;
236 wxSize size = GetSize();
237 rect.x =
238 rect.y = 0;
239 rect.width = size.x;
240 rect.height = size.y;
241
242 wxWindowDC dc(this);
7ee7c43f 243 m_renderer->DrawFrameTitleBar(dc, rect,
24a23c35 244 GetTitle(), m_titlebarIcon,
813edf09
VS
245 GetDecorationsStyle(),
246 m_pressedButton,
247 wxCONTROL_PRESSED);
24a23c35
VS
248 }
249}
250
813edf09
VS
251long wxTopLevelWindow::HitTest(const wxPoint& pt) const
252{
253 int w, h;
254 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
255 wxRect rect(wxTopLevelWindowNative::GetClientAreaOrigin(), wxSize(w, h));
7ee7c43f 256
813edf09
VS
257 return m_renderer->HitTestFrame(rect, pt, GetDecorationsStyle());
258}
259
24a23c35
VS
260// ----------------------------------------------------------------------------
261// icons
262// ----------------------------------------------------------------------------
263
264void wxTopLevelWindow::SetIcon(const wxIcon& icon)
265{
266 wxTopLevelWindowNative::SetIcon(icon);
24a23c35 267
15678bec 268 if ( ms_drawDecorations && m_renderer )
24a23c35 269 {
15678bec
VS
270 wxSize size = m_renderer->GetFrameIconSize();
271
272 if ( !icon.Ok() || size.x == -1 )
24a23c35
VS
273 m_titlebarIcon = icon;
274 else
275 {
15678bec
VS
276 wxBitmap bmp1;
277 bmp1.CopyFromIcon(icon);
278 if ( !bmp1.Ok() )
279 m_titlebarIcon = wxNullIcon;
280 else if ( bmp1.GetWidth() == size.x && bmp1.GetHeight() == size.y )
281 m_titlebarIcon = icon;
282 else
283 {
284 wxImage img = bmp1.ConvertToImage();
285 img.Rescale(size.x, size.y);
286 m_titlebarIcon.CopyFromBitmap(wxBitmap(img));
287 }
24a23c35
VS
288 }
289 }
290}
ea1b0d6c
VS
291
292// ----------------------------------------------------------------------------
293// actions
294// ----------------------------------------------------------------------------
295
813edf09
VS
296void wxTopLevelWindow::ClickTitleBarButton(long button)
297{
298 switch ( button )
299 {
300 case wxTOPLEVEL_BUTTON_CLOSE:
301 Close();
302 break;
303
304 case wxTOPLEVEL_BUTTON_ICONIZE:
305 Iconize();
306 break;
307
308 case wxTOPLEVEL_BUTTON_MAXIMIZE:
309 Maximize();
310 break;
311
312 case wxTOPLEVEL_BUTTON_RESTORE:
313 Restore();
314 break;
315
316 case wxTOPLEVEL_BUTTON_HELP:
317#if wxUSE_HELP
318 {
319 wxContextHelp contextHelp(this);
320 }
321#endif
322 break;
7ee7c43f 323
813edf09
VS
324 default:
325 wxFAIL_MSG(wxT("incorrect button specification"));
326 }
327}
328
ea1b0d6c
VS
329bool wxTopLevelWindow::PerformAction(const wxControlAction& action,
330 long numArg,
331 const wxString& strArg)
332{
7ee7c43f
VZ
333 bool isActive = numArg != 0;
334
ea1b0d6c
VS
335 if ( action == wxACTION_TOPLEVEL_ACTIVATE )
336 {
7ee7c43f 337 if ( m_isActive != isActive )
ea1b0d6c 338 {
7ee7c43f 339 m_isActive = isActive;
b22d16ad 340 RefreshTitleBar();
ea1b0d6c
VS
341 }
342 return TRUE;
343 }
7ee7c43f 344
813edf09
VS
345 else if ( action == wxACTION_TOPLEVEL_BUTTON_PRESS )
346 {
347 m_pressedButton = numArg;
348 RefreshTitleBar();
349 return TRUE;
350 }
7ee7c43f 351
813edf09
VS
352 else if ( action == wxACTION_TOPLEVEL_BUTTON_RELEASE )
353 {
354 m_pressedButton = 0;
355 RefreshTitleBar();
356 return TRUE;
357 }
7ee7c43f 358
813edf09
VS
359 else if ( action == wxACTION_TOPLEVEL_BUTTON_CLICK )
360 {
361 m_pressedButton = 0;
362 RefreshTitleBar();
363 ClickTitleBarButton(numArg);
364 return TRUE;
365 }
b22d16ad
VS
366
367 else if ( action == wxACTION_TOPLEVEL_MOVE )
368 {
369 InteractiveMove(wxINTERACTIVE_MOVE);
370 return TRUE;
371 }
372
373 else if ( action == wxACTION_TOPLEVEL_RESIZE )
374 {
375 int flags = wxINTERACTIVE_RESIZE;
376 if ( numArg & wxHT_TOPLEVEL_BORDER_N )
377 flags |= wxINTERACTIVE_RESIZE_N;
378 if ( numArg & wxHT_TOPLEVEL_BORDER_S )
379 flags |= wxINTERACTIVE_RESIZE_S;
380 if ( numArg & wxHT_TOPLEVEL_BORDER_W )
381 flags |= wxINTERACTIVE_RESIZE_W;
382 if ( numArg & wxHT_TOPLEVEL_BORDER_E )
383 flags |= wxINTERACTIVE_RESIZE_E;
384 InteractiveMove(flags);
385 return TRUE;
386 }
387
ea1b0d6c
VS
388 else
389 return FALSE;
390}
391
392
393// ============================================================================
394// wxStdFrameInputHandler: handles focus, resizing and titlebar buttons clicks
395// ============================================================================
396
397wxStdFrameInputHandler::wxStdFrameInputHandler(wxInputHandler *inphand)
398 : wxStdInputHandler(inphand)
399{
813edf09
VS
400 m_winCapture = NULL;
401 m_winHitTest = 0;
402 m_winPressed = 0;
b22d16ad 403 m_borderCursorOn = FALSE;
ea1b0d6c
VS
404}
405
406bool wxStdFrameInputHandler::HandleMouse(wxInputConsumer *consumer,
407 const wxMouseEvent& event)
408{
813edf09
VS
409 // the button has 2 states: pressed and normal with the following
410 // transitions between them:
411 //
412 // normal -> left down -> capture mouse and go to pressed state
413 // pressed -> left up inside -> generate click -> go to normal
414 // outside ------------------>
415 //
416 // the other mouse buttons are ignored
417 if ( event.Button(1) )
418 {
419 if ( event.ButtonDown(1) )
420 {
421 wxTopLevelWindow *w = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
422 long hit = w->HitTest(event.GetPosition());
7ee7c43f 423
813edf09
VS
424 if ( hit & wxHT_TOPLEVEL_ANY_BUTTON )
425 {
426 m_winCapture = w;
427 m_winCapture->CaptureMouse();
428 m_winHitTest = hit;
429 m_winPressed = hit;
430 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
431 return TRUE;
432 }
b22d16ad
VS
433 else if ( hit & wxHT_TOPLEVEL_TITLEBAR )
434 {
435 consumer->PerformAction(wxACTION_TOPLEVEL_MOVE);
436 return TRUE;
437 }
438 else if ( (consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER)
439 && (hit & wxHT_TOPLEVEL_ANY_BORDER) )
440 {
441 consumer->PerformAction(wxACTION_TOPLEVEL_RESIZE, hit);
442 return TRUE;
443 }
813edf09
VS
444 }
445
446 else // up
447 {
448 if ( m_winCapture )
449 {
450 m_winCapture->ReleaseMouse();
451 m_winCapture = NULL;
452
453 if ( m_winHitTest == m_winPressed )
454 {
455 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, m_winPressed);
456 return TRUE;
457 }
458 }
459 //else: the mouse was released outside the window, this doesn't
460 // count as a click
461 }
462 }
463
ea1b0d6c
VS
464 return wxStdInputHandler::HandleMouse(consumer, event);
465}
466
7ee7c43f 467bool wxStdFrameInputHandler::HandleMouseMove(wxInputConsumer *consumer,
ea1b0d6c
VS
468 const wxMouseEvent& event)
469{
813edf09
VS
470 if ( event.GetEventObject() == m_winCapture )
471 {
472 long hit = m_winCapture->HitTest(event.GetPosition());
473
474 if ( hit != m_winHitTest )
475 {
476 if ( hit != m_winPressed )
477 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_RELEASE, m_winPressed);
478 else
479 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
7ee7c43f 480
813edf09
VS
481 m_winHitTest = hit;
482 return TRUE;
483 }
484 }
b22d16ad
VS
485 else if ( consumer->GetInputWindow()->GetWindowStyle() & wxRESIZE_BORDER )
486 {
487 wxTopLevelWindow *win = wxStaticCast(consumer->GetInputWindow(),
488 wxTopLevelWindow);
489 long hit = win->HitTest(event.GetPosition());
490
491 if ( hit != m_winHitTest )
492 {
493 m_winHitTest = hit;
494
495 if ( m_borderCursorOn )
496 {
497 m_borderCursorOn = FALSE;
498 win->SetCursor(m_origCursor);
499 }
500
501 if ( hit & wxHT_TOPLEVEL_ANY_BORDER )
502 {
503 m_borderCursorOn = TRUE;
504 wxCursor cur;
505
506 switch (hit)
507 {
508 case wxHT_TOPLEVEL_BORDER_N:
509 case wxHT_TOPLEVEL_BORDER_S:
510 cur = wxCursor(wxCURSOR_SIZENS);
511 break;
512 case wxHT_TOPLEVEL_BORDER_W:
513 case wxHT_TOPLEVEL_BORDER_E:
514 cur = wxCursor(wxCURSOR_SIZEWE);
515 break;
516 case wxHT_TOPLEVEL_BORDER_NE:
517 case wxHT_TOPLEVEL_BORDER_SW:
518 cur = wxCursor(wxCURSOR_SIZENESW);
519 break;
520 case wxHT_TOPLEVEL_BORDER_NW:
521 case wxHT_TOPLEVEL_BORDER_SE:
522 cur = wxCursor(wxCURSOR_SIZENWSE);
523 break;
524 default:
525 m_borderCursorOn = FALSE;
526 break;
527 }
528 if ( m_borderCursorOn )
529 {
530 m_origCursor = win->GetCursor();
531 win->SetCursor(cur);
532 }
533 }
534 }
535 }
813edf09 536
ea1b0d6c
VS
537 return wxStdInputHandler::HandleMouseMove(consumer, event);
538}
539
7ee7c43f 540bool wxStdFrameInputHandler::HandleActivation(wxInputConsumer *consumer,
ea1b0d6c
VS
541 bool activated)
542{
b22d16ad
VS
543 if ( m_borderCursorOn )
544 {
545 consumer->GetInputWindow()->SetCursor(m_origCursor);
546 m_borderCursorOn = FALSE;
547 }
ea1b0d6c
VS
548 consumer->PerformAction(wxACTION_TOPLEVEL_ACTIVATE, activated);
549 return FALSE;
550}