]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/frame.cpp
Fix for TextCtrl problem as reported by Vegh
[wxWidgets.git] / src / gtk1 / frame.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: frame.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "frame.h"
12 #endif
13
14 #include "wx/frame.h"
15 #include "wx/dialog.h"
16 #include "wx/control.h"
17 #include "wx/app.h"
18 #include "wx/menu.h"
19 #include "wx/toolbar.h"
20 #include "wx/statusbr.h"
21 #include "wx/dcclient.h"
22 #include "wx/gtk/win_gtk.h"
23
24 //-----------------------------------------------------------------------------
25 // constants
26 //-----------------------------------------------------------------------------
27
28 const int wxMENU_HEIGHT = 30;
29 const int wxSTATUS_HEIGHT = 25;
30
31 //-----------------------------------------------------------------------------
32 // data
33 //-----------------------------------------------------------------------------
34
35 extern wxList wxTopLevelWindows;
36 extern wxList wxPendingDelete;
37
38 //-----------------------------------------------------------------------------
39 // "size_allocate"
40 //-----------------------------------------------------------------------------
41
42 static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxFrame *win )
43 {
44 if (!win->HasVMT()) return;
45
46 /*
47 printf( "OnFrameResize from " );
48 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
49 printf( win->GetClassInfo()->GetClassName() );
50 printf( ".\n" );
51 */
52
53 win->GtkOnSize( alloc->x, alloc->y, alloc->width, alloc->height );
54 }
55
56 //-----------------------------------------------------------------------------
57 // "delete_event"
58 //-----------------------------------------------------------------------------
59
60 static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxFrame *win )
61 {
62 /*
63 printf( "OnDelete from " );
64 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
65 printf( win->GetClassInfo()->GetClassName() );
66 printf( ".\n" );
67 */
68
69 win->Close();
70
71 return TRUE;
72 }
73
74 //-----------------------------------------------------------------------------
75 // "configure_event"
76 //-----------------------------------------------------------------------------
77
78 static gint gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *event, wxFrame *win )
79 {
80 if (!win->HasVMT()) return FALSE;
81
82 win->m_x = event->x;
83 win->m_y = event->y;
84
85 return FALSE;
86 }
87
88 //-----------------------------------------------------------------------------
89 // wxFrame
90 //-----------------------------------------------------------------------------
91
92 BEGIN_EVENT_TABLE(wxFrame, wxWindow)
93 EVT_SIZE(wxFrame::OnSize)
94 EVT_CLOSE(wxFrame::OnCloseWindow)
95 EVT_IDLE(wxFrame::OnIdle)
96 END_EVENT_TABLE()
97
98 IMPLEMENT_DYNAMIC_CLASS(wxFrame,wxWindow)
99
100 wxFrame::wxFrame()
101 {
102 m_frameMenuBar = (wxMenuBar *) NULL;
103 m_frameStatusBar = (wxStatusBar *) NULL;
104 m_frameToolBar = (wxToolBar *) NULL;
105 m_sizeSet = FALSE;
106 wxTopLevelWindows.Insert( this );
107 }
108
109 wxFrame::wxFrame( wxWindow *parent, wxWindowID id, const wxString &title,
110 const wxPoint &pos, const wxSize &size,
111 long style, const wxString &name )
112 {
113 m_frameMenuBar = (wxMenuBar *) NULL;
114 m_frameStatusBar = (wxStatusBar *) NULL;
115 m_frameToolBar = (wxToolBar *) NULL;
116 m_sizeSet = FALSE;
117 Create( parent, id, title, pos, size, style, name );
118 wxTopLevelWindows.Insert( this );
119 }
120
121 bool wxFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
122 const wxPoint &pos, const wxSize &size,
123 long style, const wxString &name )
124 {
125 m_needParent = FALSE;
126
127 PreCreation( parent, id, pos, size, style, name );
128
129 m_title = title;
130
131 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
132 if (style & wxSIMPLE_BORDER) win_type = GTK_WINDOW_POPUP;
133
134 m_widget = gtk_window_new( win_type );
135 if ((size.x != -1) && (size.y != -1))
136 gtk_widget_set_usize( m_widget, m_width, m_height );
137 if ((pos.x != -1) && (pos.y != -1))
138 gtk_widget_set_uposition( m_widget, m_x, m_y );
139
140 gtk_window_set_title( GTK_WINDOW(m_widget), title );
141 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
142
143 gtk_widget_set( m_widget, "GtkWindow::allow_shrink", TRUE, NULL );
144
145 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
146 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
147
148 m_wxwindow = gtk_myfixed_new();
149 gtk_widget_show( m_wxwindow );
150 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
151
152 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
153
154 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
155 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
156
157 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
158 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
159
160 if (m_parent) m_parent->AddChild( this );
161
162 PostCreation();
163
164 return TRUE;
165 }
166
167 wxFrame::~wxFrame()
168 {
169 if (m_frameMenuBar) delete m_frameMenuBar;
170 if (m_frameStatusBar) delete m_frameStatusBar;
171 if (m_frameToolBar) delete m_frameToolBar;
172
173 wxTopLevelWindows.DeleteObject( this );
174 if (wxTopLevelWindows.Number() == 0) wxTheApp->ExitMainLoop();
175 }
176
177 bool wxFrame::Show( bool show )
178 {
179 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
180
181 if (show)
182 {
183 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
184 m_sizeSet = FALSE;
185 ProcessEvent( event );
186 }
187 return wxWindow::Show( show );
188 }
189
190 void wxFrame::OnCloseWindow( wxCloseEvent &event )
191 {
192 if (GetEventHandler()->OnClose() || event.GetForce()) this->Destroy();
193 }
194
195 bool wxFrame::Destroy()
196 {
197 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
198
199 if (!wxPendingDelete.Member(this))
200 wxPendingDelete.Append(this);
201
202 return TRUE;
203 }
204
205 wxPoint wxFrame::GetClientAreaOrigin() const
206 {
207 wxPoint pt(0, 0);
208 if (m_frameMenuBar)
209 {
210 int h = 0;
211 m_frameMenuBar->GetSize( (int*)NULL, &h );
212 pt.y += h + 2;
213 }
214 if (m_frameToolBar)
215 {
216 int h = 0;
217 m_frameToolBar->GetSize( (int*)NULL, &h );
218 pt.y += h;
219 }
220 return pt;
221 }
222
223 void wxFrame::ImplementSetPosition(void)
224 {
225 if ((m_x != -1) || (m_y != -1))
226 gtk_widget_set_uposition( m_widget, m_x, m_y );
227 }
228
229 void wxFrame::Centre( int direction )
230 {
231 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
232
233 if (direction & wxHORIZONTAL == wxHORIZONTAL) m_x = (gdk_screen_width () - m_width) / 2;
234 if (direction & wxVERTICAL == wxVERTICAL) m_y = (gdk_screen_height () - m_height) / 2;
235
236 ImplementSetPosition();
237 }
238
239 void wxFrame::GetClientSize( int *width, int *height ) const
240 {
241 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
242
243 wxWindow::GetClientSize( width, height );
244 if (height)
245 {
246 if (m_frameMenuBar) (*height) -= wxMENU_HEIGHT;
247 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
248 if (m_frameToolBar)
249 {
250 int y = 0;
251 m_frameToolBar->GetSize( (int *) NULL, &y );
252 (*height) -= y;
253 }
254 }
255 }
256
257 void wxFrame::SetClientSize( int const width, int const height )
258 {
259 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
260
261 int h = height;
262 if (m_frameMenuBar) h += wxMENU_HEIGHT;
263 if (m_frameStatusBar) h += wxSTATUS_HEIGHT;
264 if (m_frameToolBar)
265 {
266 int y = 0;
267 m_frameToolBar->GetSize( (int *) NULL, &y );
268 h += y;
269 }
270 wxWindow::SetClientSize( width, h );
271 }
272
273 void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int width, int height )
274 {
275 // due to a bug in gtk, x,y are always 0
276 // m_x = x;
277 // m_y = y;
278
279 if ((m_height == height) && (m_width == width) &&
280 (m_sizeSet)) return;
281 if (!m_wxwindow) return;
282
283 m_width = width;
284 m_height = height;
285 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
286 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
287 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_minWidth;
288 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_minHeight;
289
290 gtk_widget_set_usize( m_widget, m_width, m_height );
291
292 // This emulates the new wxMSW behaviour
293
294 if (m_frameMenuBar)
295 {
296 m_frameMenuBar->m_x = 1;
297 m_frameMenuBar->m_y = 1;
298 m_frameMenuBar->m_width = m_width-2;
299 m_frameMenuBar->m_height = wxMENU_HEIGHT-2;
300 gtk_myfixed_move( GTK_MYFIXED(m_wxwindow), m_frameMenuBar->m_widget, 1, 1 );
301 gtk_widget_set_usize( m_frameMenuBar->m_widget, m_width-2, wxMENU_HEIGHT-2 );
302 }
303
304 if (m_frameToolBar)
305 {
306 int y = 0;
307 if (m_frameMenuBar) y = wxMENU_HEIGHT;
308 int h = m_frameToolBar->m_height;
309
310 m_frameToolBar->m_x = 2;
311 gtk_myfixed_move( GTK_MYFIXED(m_wxwindow), m_frameToolBar->m_widget, 2, y );
312 gtk_widget_set_usize( m_frameToolBar->m_widget, m_width-3, h );
313 }
314
315 if (m_frameStatusBar)
316 {
317 // OK, this hurts in the eye, but I don't want to call SetSize()
318 // because I don't want to call any non-native functions here.
319 m_frameStatusBar->m_x = 0;
320 m_frameStatusBar->m_y = m_height-wxSTATUS_HEIGHT;
321 m_frameStatusBar->m_width = m_width;
322 m_frameStatusBar->m_height = wxSTATUS_HEIGHT;
323 gtk_myfixed_move( GTK_MYFIXED(m_wxwindow), m_frameStatusBar->m_widget, 0, m_height-wxSTATUS_HEIGHT );
324 gtk_widget_set_usize( m_frameStatusBar->m_widget, m_width, wxSTATUS_HEIGHT );
325 }
326
327 m_sizeSet = TRUE;
328
329 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
330 event.SetEventObject( this );
331 ProcessEvent( event );
332 }
333
334 void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) )
335 {
336 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
337
338 if ( GetAutoLayout() )
339 Layout();
340 else {
341 // no child: go out !
342 if (!GetChildren()->First())
343 return;
344
345 // do we have exactly one child?
346 wxWindow *child = (wxWindow *) NULL;
347 for(wxNode *node = GetChildren()->First(); node; node = node->Next())
348 {
349 wxWindow *win = (wxWindow *)node->Data();
350 if (!IS_KIND_OF(win,wxFrame) && !IS_KIND_OF(win,wxDialog)
351 #if 0 // not in m_children anyway ?
352 && (win != m_frameMenuBar) &&
353 (win != m_frameToolBar) &&
354 (win != m_frameStatusBar)
355 #endif
356 )
357 {
358 if ( child ) // it's the second one: do nothing
359 return;
360
361 child = win;
362 }
363 }
364
365 // yes: set it's size to fill all the frame
366 int client_x, client_y;
367 GetClientSize(&client_x, &client_y);
368 child->SetSize( 1, 1, client_x-2, client_y);
369 }
370 }
371
372 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
373 {
374 menu->SetInvokingWindow( win );
375 wxNode *node = menu->m_items.First();
376 while (node)
377 {
378 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
379 if (menuitem->IsSubMenu())
380 SetInvokingWindow( menuitem->GetSubMenu(), win );
381 node = node->Next();
382 }
383 }
384
385 void wxFrame::SetMenuBar( wxMenuBar *menuBar )
386 {
387 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
388 wxASSERT_MSG( (m_wxwindow != NULL), "invalid frame" );
389
390 m_frameMenuBar = menuBar;
391
392 if (m_frameMenuBar)
393 {
394 wxNode *node = m_frameMenuBar->m_menus.First();
395 while (node)
396 {
397 wxMenu *menu = (wxMenu*)node->Data();
398 SetInvokingWindow( menu, this );
399 node = node->Next();
400 }
401
402 if (m_frameMenuBar->m_parent != this)
403 {
404 m_frameMenuBar->m_parent = this;
405 gtk_myfixed_put( GTK_MYFIXED(m_wxwindow),
406 m_frameMenuBar->m_widget, m_frameMenuBar->m_x, m_frameMenuBar->m_y );
407 }
408 }
409 }
410
411 wxMenuBar *wxFrame::GetMenuBar(void) const
412 {
413 return m_frameMenuBar;
414 }
415
416 wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
417 {
418 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
419
420 wxCHECK_MSG( m_frameToolBar == NULL, FALSE, "recreating toolbar in wxFrame" );
421
422 m_frameToolBar = OnCreateToolBar( style, id, name );
423
424 GetChildren()->DeleteObject( m_frameToolBar );
425
426 return m_frameToolBar;
427 }
428
429 wxToolBar* wxFrame::OnCreateToolBar( long style, wxWindowID id, const wxString& name )
430 {
431 return new wxToolBar( this, id, wxDefaultPosition, wxDefaultSize, style, name );
432 }
433
434 wxToolBar *wxFrame::GetToolBar(void) const
435 {
436 return m_frameToolBar;
437 }
438
439 wxStatusBar* wxFrame::CreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
440 {
441 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
442
443 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE, "recreating status bar in wxFrame" );
444
445 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
446
447 return m_frameStatusBar;
448 }
449
450 wxStatusBar *wxFrame::OnCreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
451 {
452 wxStatusBar *statusBar = (wxStatusBar *) NULL;
453
454 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20), style, name);
455
456 // Set the height according to the font and the border size
457 wxClientDC dc(statusBar);
458 dc.SetFont( *statusBar->GetFont() );
459
460 long x, y;
461 dc.GetTextExtent( "X", &x, &y );
462
463 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
464
465 statusBar->SetSize( -1, -1, 100, height );
466
467 statusBar->SetFieldsCount( number );
468 return statusBar;
469 }
470
471 void wxFrame::SetStatusText(const wxString& text, int number)
472 {
473 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
474
475 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set text for" );
476
477 m_frameStatusBar->SetStatusText(text, number);
478 }
479
480 void wxFrame::SetStatusWidths(int n, const int widths_field[] )
481 {
482 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
483
484 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set widths for" );
485
486 m_frameStatusBar->SetStatusWidths(n, widths_field);
487 }
488
489 wxStatusBar *wxFrame::GetStatusBar(void) const
490 {
491 return m_frameStatusBar;
492 }
493
494 void wxFrame::SetTitle( const wxString &title )
495 {
496 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
497
498 m_title = title;
499 if (m_title.IsNull()) m_title = "";
500 gtk_window_set_title( GTK_WINDOW(m_widget), title );
501 }
502
503 void wxFrame::SetIcon( const wxIcon &icon )
504 {
505 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
506
507 m_icon = icon;
508 if (!icon.Ok()) return;
509
510 wxMask *mask = icon.GetMask();
511 GdkBitmap *bm = (GdkBitmap *) NULL;
512 if (mask) bm = mask->GetBitmap();
513
514 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
515 }