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