]> git.saurik.com Git - wxWidgets.git/blame - src/univ/topluniv.cpp
toplevel fixes
[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"
29#include "wx/toplevel.h"
24a23c35
VS
30#include "wx/univ/renderer.h"
31#include "wx/dcclient.h"
32#include "wx/bitmap.h"
33#include "wx/image.h"
813edf09 34#include "wx/cshelp.h"
0f1bf77d
VS
35
36
37// ----------------------------------------------------------------------------
38// event tables
39// ----------------------------------------------------------------------------
40
24a23c35 41BEGIN_EVENT_TABLE(wxTopLevelWindow, wxTopLevelWindowNative)
ea1b0d6c 42 WX_EVENT_TABLE_INPUT_CONSUMER(wxTopLevelWindow)
24a23c35
VS
43 EVT_NC_PAINT(wxTopLevelWindow::OnNcPaint)
44END_EVENT_TABLE()
45
ea1b0d6c
VS
46WX_FORWARD_TO_INPUT_CONSUMER(wxTopLevelWindow)
47
0f1bf77d
VS
48
49// ============================================================================
50// implementation
51// ============================================================================
52
24a23c35
VS
53int wxTopLevelWindow::ms_drawDecorations = -1;
54
0f1bf77d
VS
55void wxTopLevelWindow::Init()
56{
24a23c35 57 m_isActive = FALSE;
ea1b0d6c 58 m_windowStyle = 0;
813edf09 59 m_pressedButton = 0;
0f1bf77d
VS
60}
61
62bool wxTopLevelWindow::Create(wxWindow *parent,
63 wxWindowID id,
64 const wxString& title,
65 const wxPoint& pos,
66 const wxSize& sizeOrig,
67 long style,
68 const wxString &name)
69{
2e9f62da
VZ
70 // init them to avoid compiler warnings
71 long styleOrig = 0,
72 exstyleOrig = 0;
24a23c35
VS
73
74 if ( ms_drawDecorations == -1 )
75 ms_drawDecorations = TRUE;
76 // FIXME_MGL -- this is temporary; we assume for now that native TLW
77 // can't do decorations, which is not true
78
79 if ( ms_drawDecorations )
80 {
ea1b0d6c
VS
81 CreateInputHandler(wxINP_HANDLER_TOPLEVEL);
82
24a23c35
VS
83 styleOrig = style;
84 exstyleOrig = GetExtraStyle();
813edf09
VS
85 style &= ~(wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX |
86 wxSYSTEM_MENU | wxRESIZE_BORDER | wxFRAME_TOOL_WINDOW |
87 wxTHICK_FRAME);
88 style = wxSIMPLE_BORDER;
89 SetExtraStyle(exstyleOrig &
90 ~(wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP));
24a23c35
VS
91 }
92
0f1bf77d
VS
93 if ( !wxTopLevelWindowNative::Create(parent, id, title, pos,
94 sizeOrig, style, name) )
95 return FALSE;
0f1bf77d 96
24a23c35
VS
97 if ( ms_drawDecorations )
98 {
99 m_windowStyle = styleOrig;
100 m_exStyle = exstyleOrig;
101 }
102
0f1bf77d
VS
103 return TRUE;
104}
105
106bool wxTopLevelWindow::ShowFullScreen(bool show, long style)
107{
108 if ( show == IsFullScreen() ) return FALSE;
109
ea1b0d6c
VS
110 if ( ms_drawDecorations )
111 {
112 if ( show )
113 {
114 m_fsSavedStyle = m_windowStyle;
115 if ( style & wxFULLSCREEN_NOBORDER )
116 m_windowStyle |= wxSIMPLE_BORDER;
117 if ( style & wxFULLSCREEN_NOCAPTION )
118 m_windowStyle &= ~wxCAPTION;
119 }
120 else
121 {
122 m_windowStyle = m_fsSavedStyle;
123 }
124 }
2e9f62da 125
ea1b0d6c 126 return wxTopLevelWindowNative::ShowFullScreen(show, style);
0f1bf77d
VS
127}
128
24a23c35
VS
129long wxTopLevelWindow::GetDecorationsStyle() const
130{
131 long style = 0;
132
133 if ( m_windowStyle & wxCAPTION )
134 {
ea1b0d6c 135 style |= wxTOPLEVEL_TITLEBAR | wxTOPLEVEL_BUTTON_CLOSE;
24a23c35 136 if ( m_windowStyle & wxMINIMIZE_BOX )
813edf09 137 style |= wxTOPLEVEL_BUTTON_ICONIZE;
24a23c35 138 if ( m_windowStyle & wxMAXIMIZE_BOX )
ea1b0d6c 139 style |= wxTOPLEVEL_BUTTON_MAXIMIZE;
813edf09 140#if wxUSE_HELP
24a23c35 141 if ( m_exStyle & (wxFRAME_EX_CONTEXTHELP | wxDIALOG_EX_CONTEXTHELP))
ea1b0d6c 142 style |= wxTOPLEVEL_BUTTON_HELP;
813edf09 143#endif
24a23c35
VS
144 }
145 if ( (m_windowStyle & (wxSIMPLE_BORDER | wxNO_BORDER)) == 0 )
146 style |= wxTOPLEVEL_BORDER;
147 if ( m_windowStyle & (wxRESIZE_BORDER | wxTHICK_FRAME) )
148 style |= wxTOPLEVEL_RESIZEABLE;
149
150 if ( IsMaximized() )
151 style |= wxTOPLEVEL_MAXIMIZED;
152 if ( GetIcon().Ok() )
153 style |= wxTOPLEVEL_ICON;
ea1b0d6c 154 if ( m_isActive )
24a23c35
VS
155 style |= wxTOPLEVEL_ACTIVE;
156
157 return style;
158}
159
813edf09
VS
160void wxTopLevelWindow::RefreshTitleBar()
161{
162 wxNcPaintEvent event(GetId());
163 event.SetEventObject(this);
164 GetEventHandler()->ProcessEvent(event);
165}
166
24a23c35
VS
167// ----------------------------------------------------------------------------
168// client area handling
169// ----------------------------------------------------------------------------
170
171wxPoint wxTopLevelWindow::GetClientAreaOrigin() const
172{
173 if ( ms_drawDecorations )
174 {
175 int w, h;
176 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
177 wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(),
178 wxSize(w, h));
179 rect = m_renderer->GetFrameClientArea(rect,
180 GetDecorationsStyle());
181 return rect.GetPosition();
182 }
183 else
184 {
185 return wxTopLevelWindowNative::GetClientAreaOrigin();
186 }
187}
188
189void wxTopLevelWindow::DoGetClientSize(int *width, int *height) const
190{
191 if ( ms_drawDecorations )
192 {
193 int w, h;
194 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
195 wxRect rect = wxRect(wxTopLevelWindowNative::GetClientAreaOrigin(),
196 wxSize(w, h));
197 rect = m_renderer->GetFrameClientArea(rect,
198 GetDecorationsStyle());
199 if ( width )
200 *width = rect.width;
201 if ( height )
202 *height = rect.height;
203 }
204 else
205 wxTopLevelWindowNative::DoGetClientSize(width, height);
206}
207
208void wxTopLevelWindow::DoSetClientSize(int width, int height)
209{
210 if ( ms_drawDecorations )
211 {
212 wxSize size = m_renderer->GetFrameTotalSize(wxSize(width, height),
213 GetDecorationsStyle());
214 wxTopLevelWindowNative::DoSetClientSize(size.x, size.y);
215 }
216 else
217 wxTopLevelWindowNative::DoSetClientSize(width, height);
218}
219
220void wxTopLevelWindow::OnNcPaint(wxPaintEvent& event)
221{
222 if ( !ms_drawDecorations || !m_renderer )
223 event.Skip();
224 else
225 {
226 // get the window rect
227 wxRect rect;
228 wxSize size = GetSize();
229 rect.x =
230 rect.y = 0;
231 rect.width = size.x;
232 rect.height = size.y;
233
234 wxWindowDC dc(this);
235 m_renderer->DrawFrameTitleBar(dc, rect,
236 GetTitle(), m_titlebarIcon,
813edf09
VS
237 GetDecorationsStyle(),
238 m_pressedButton,
239 wxCONTROL_PRESSED);
24a23c35
VS
240 }
241}
242
813edf09
VS
243long wxTopLevelWindow::HitTest(const wxPoint& pt) const
244{
245 int w, h;
246 wxTopLevelWindowNative::DoGetClientSize(&w, &h);
247 wxRect rect(wxTopLevelWindowNative::GetClientAreaOrigin(), wxSize(w, h));
248
249 return m_renderer->HitTestFrame(rect, pt, GetDecorationsStyle());
250}
251
24a23c35
VS
252// ----------------------------------------------------------------------------
253// icons
254// ----------------------------------------------------------------------------
255
256void wxTopLevelWindow::SetIcon(const wxIcon& icon)
257{
258 wxTopLevelWindowNative::SetIcon(icon);
259 if ( !m_renderer ) return;
260
261 wxSize size = m_renderer->GetFrameIconSize();
262
263 if ( !icon.Ok() || size.x == -1 )
264 m_titlebarIcon = icon;
265 else
266 {
267 wxBitmap bmp1;
268 bmp1.CopyFromIcon(icon);
269 if ( !bmp1.Ok() )
270 m_titlebarIcon = wxNullIcon;
271 else if ( bmp1.GetWidth() == size.x && bmp1.GetHeight() == size.y )
272 m_titlebarIcon = icon;
273 else
274 {
275 wxImage img = bmp1.ConvertToImage();
276 img.Rescale(size.x, size.y);
ea1b0d6c 277 m_titlebarIcon.CopyFromBitmap(wxBitmap(img));
24a23c35
VS
278 }
279 }
280}
ea1b0d6c
VS
281
282// ----------------------------------------------------------------------------
283// actions
284// ----------------------------------------------------------------------------
285
813edf09
VS
286void wxTopLevelWindow::ClickTitleBarButton(long button)
287{
288 switch ( button )
289 {
290 case wxTOPLEVEL_BUTTON_CLOSE:
291 Close();
292 break;
293
294 case wxTOPLEVEL_BUTTON_ICONIZE:
295 Iconize();
296 break;
297
298 case wxTOPLEVEL_BUTTON_MAXIMIZE:
299 Maximize();
300 break;
301
302 case wxTOPLEVEL_BUTTON_RESTORE:
303 Restore();
304 break;
305
306 case wxTOPLEVEL_BUTTON_HELP:
307#if wxUSE_HELP
308 {
309 wxContextHelp contextHelp(this);
310 }
311#endif
312 break;
313
314 default:
315 wxFAIL_MSG(wxT("incorrect button specification"));
316 }
317}
318
ea1b0d6c
VS
319bool wxTopLevelWindow::PerformAction(const wxControlAction& action,
320 long numArg,
321 const wxString& strArg)
322{
323 if ( action == wxACTION_TOPLEVEL_ACTIVATE )
324 {
325 if ( m_isActive != (bool)numArg )
326 {
327 Refresh();
328 m_isActive = (bool)numArg;
329 wxNcPaintEvent event(GetId());
330 event.SetEventObject(this);
331 GetEventHandler()->ProcessEvent(event);
ea1b0d6c
VS
332 }
333 return TRUE;
334 }
813edf09
VS
335
336 else if ( action == wxACTION_TOPLEVEL_BUTTON_PRESS )
337 {
338 m_pressedButton = numArg;
339 RefreshTitleBar();
340 return TRUE;
341 }
342
343 else if ( action == wxACTION_TOPLEVEL_BUTTON_RELEASE )
344 {
345 m_pressedButton = 0;
346 RefreshTitleBar();
347 return TRUE;
348 }
349
350 else if ( action == wxACTION_TOPLEVEL_BUTTON_CLICK )
351 {
352 m_pressedButton = 0;
353 RefreshTitleBar();
354 ClickTitleBarButton(numArg);
355 return TRUE;
356 }
357
ea1b0d6c
VS
358 else
359 return FALSE;
360}
361
362
363// ============================================================================
364// wxStdFrameInputHandler: handles focus, resizing and titlebar buttons clicks
365// ============================================================================
366
367wxStdFrameInputHandler::wxStdFrameInputHandler(wxInputHandler *inphand)
368 : wxStdInputHandler(inphand)
369{
813edf09
VS
370 m_winCapture = NULL;
371 m_winHitTest = 0;
372 m_winPressed = 0;
ea1b0d6c
VS
373}
374
375bool wxStdFrameInputHandler::HandleMouse(wxInputConsumer *consumer,
376 const wxMouseEvent& event)
377{
813edf09
VS
378 // the button has 2 states: pressed and normal with the following
379 // transitions between them:
380 //
381 // normal -> left down -> capture mouse and go to pressed state
382 // pressed -> left up inside -> generate click -> go to normal
383 // outside ------------------>
384 //
385 // the other mouse buttons are ignored
386 if ( event.Button(1) )
387 {
388 if ( event.ButtonDown(1) )
389 {
390 wxTopLevelWindow *w = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
391 long hit = w->HitTest(event.GetPosition());
392
393 if ( hit & wxHT_TOPLEVEL_ANY_BUTTON )
394 {
395 m_winCapture = w;
396 m_winCapture->CaptureMouse();
397 m_winHitTest = hit;
398 m_winPressed = hit;
399 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
400 return TRUE;
401 }
402 }
403
404 else // up
405 {
406 if ( m_winCapture )
407 {
408 m_winCapture->ReleaseMouse();
409 m_winCapture = NULL;
410
411 if ( m_winHitTest == m_winPressed )
412 {
413 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK, m_winPressed);
414 return TRUE;
415 }
416 }
417 //else: the mouse was released outside the window, this doesn't
418 // count as a click
419 }
420 }
421
ea1b0d6c
VS
422 return wxStdInputHandler::HandleMouse(consumer, event);
423}
424
425bool wxStdFrameInputHandler::HandleMouseMove(wxInputConsumer *consumer,
426 const wxMouseEvent& event)
427{
813edf09
VS
428 // we only have to do something when the mouse leaves/enters the pressed
429 // button and don't care about the other ones
430 if ( event.GetEventObject() == m_winCapture )
431 {
432 long hit = m_winCapture->HitTest(event.GetPosition());
433
434 if ( hit != m_winHitTest )
435 {
436 if ( hit != m_winPressed )
437 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_RELEASE, m_winPressed);
438 else
439 consumer->PerformAction(wxACTION_TOPLEVEL_BUTTON_PRESS, m_winPressed);
440
441 m_winHitTest = hit;
442 return TRUE;
443 }
444 }
445
ea1b0d6c
VS
446 return wxStdInputHandler::HandleMouseMove(consumer, event);
447}
448
449bool wxStdFrameInputHandler::HandleActivation(wxInputConsumer *consumer,
450 bool activated)
451{
452 consumer->PerformAction(wxACTION_TOPLEVEL_ACTIVATE, activated);
453 return FALSE;
454}