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