]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/frame.cpp
wxMDIChildFrame inherits from wxFrame
[wxWidgets.git] / src / gtk / frame.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: frame.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Created: 01/02/97
6 // Id:
7 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #ifdef __GNUG__
12 #pragma implementation "frame.h"
13 #endif
14
15 #include "wx/frame.h"
16 #include "wx/dialog.h"
17 #include "wx/control.h"
18 #include "wx/app.h"
19 #include "wx/menu.h"
20 #include "wx/toolbar.h"
21 #include "wx/statusbr.h"
22 #include "wx/gtk/win_gtk.h"
23
24 const wxMENU_HEIGHT = 28;
25 const wxSTATUS_HEIGHT = 25;
26
27 extern wxList wxTopLevelWindows;
28 extern wxList wxPendingDelete;
29
30 //-----------------------------------------------------------------------------
31 // wxFrame
32 //-----------------------------------------------------------------------------
33
34 //-----------------------------------------------------------------------------
35 // size
36
37 void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxFrame *win )
38 {
39 if (!win->HasVMT()) return;
40
41 /*
42 printf( "OnFrameResize from " );
43 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
44 printf( win->GetClassInfo()->GetClassName() );
45 printf( ".\n" );
46 */
47
48 win->GtkOnSize( alloc->x, alloc->y, alloc->width, alloc->height );
49 };
50
51 //-----------------------------------------------------------------------------
52 // delete
53
54 bool gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxFrame *win )
55 {
56 /*
57 printf( "OnDelete from " );
58 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
59 printf( win->GetClassInfo()->GetClassName() );
60 printf( ".\n" );
61 */
62
63 win->Close();
64
65 return TRUE;
66 };
67
68 //-----------------------------------------------------------------------------
69
70 BEGIN_EVENT_TABLE(wxFrame, wxWindow)
71 EVT_SIZE(wxFrame::OnSize)
72 EVT_CLOSE(wxFrame::OnCloseWindow)
73 EVT_IDLE(wxFrame::OnIdle)
74 END_EVENT_TABLE()
75
76 IMPLEMENT_DYNAMIC_CLASS(wxFrame,wxWindow)
77
78 wxFrame::wxFrame()
79 {
80 m_frameMenuBar = NULL;
81 m_frameStatusBar = NULL;
82 m_frameToolBar = NULL;
83 m_sizeSet = FALSE;
84 m_addPrivateChild = FALSE;
85 m_wxwindow = NULL;
86 m_mainWindow = NULL;
87 wxTopLevelWindows.Insert( this );
88 };
89
90 wxFrame::wxFrame( wxWindow *parent, wxWindowID id, const wxString &title,
91 const wxPoint &pos, const wxSize &size,
92 long style, const wxString &name )
93 {
94 m_frameMenuBar = NULL;
95 m_frameStatusBar = NULL;
96 m_frameToolBar = NULL;
97 m_sizeSet = FALSE;
98 m_addPrivateChild = FALSE;
99 m_wxwindow = NULL;
100 m_mainWindow = NULL;
101 Create( parent, id, title, pos, size, style, name );
102 wxTopLevelWindows.Insert( this );
103 };
104
105 bool wxFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
106 const wxPoint &pos, const wxSize &size,
107 long style, const wxString &name )
108 {
109 m_needParent = FALSE;
110
111 PreCreation( parent, id, pos, size, style, name );
112
113 m_title = title;
114
115 m_widget = gtk_window_new( GTK_WINDOW_TOPLEVEL );
116 if ((size.x != -1) && (size.y != -1))
117 gtk_widget_set_usize( m_widget, m_width, m_height );
118 if ((pos.x != -1) && (pos.y != -1))
119 gtk_widget_set_uposition( m_widget, m_x, m_y );
120
121 gtk_window_set_title( GTK_WINDOW(m_widget), title );
122 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
123
124 gtk_widget_set( m_widget, "GtkWindow::allow_shrink", TRUE, NULL);
125
126 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
127 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
128
129 m_mainWindow = gtk_myfixed_new();
130 gtk_widget_show( m_mainWindow );
131 GTK_WIDGET_UNSET_FLAGS( m_mainWindow, GTK_CAN_FOCUS );
132
133 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWindow );
134 gtk_widget_set_uposition( m_mainWindow, 0, 0 );
135
136 m_wxwindow = gtk_myfixed_new();
137 gtk_widget_show( m_wxwindow );
138 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
139
140 gtk_container_add( GTK_CONTAINER(m_mainWindow), m_wxwindow );
141
142 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
143 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
144
145 PostCreation();
146
147 gtk_widget_realize( m_mainWindow );
148
149 return TRUE;
150 };
151
152 wxFrame::~wxFrame()
153 {
154 if (m_frameMenuBar) delete m_frameMenuBar;
155 if (m_frameStatusBar) delete m_frameStatusBar;
156
157 // if (m_mainWindow) gtk_widget_destroy( m_mainWindow );
158
159 wxTopLevelWindows.DeleteObject( this );
160 if (wxTopLevelWindows.Number() == 0) wxTheApp->ExitMainLoop();
161 };
162
163 bool wxFrame::Show( bool show )
164 {
165 if (show)
166 {
167 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
168 m_sizeSet = FALSE;
169 ProcessEvent( event );
170 };
171 return wxWindow::Show( show );
172 };
173
174 void wxFrame::Enable( bool enable )
175 {
176 wxWindow::Enable( enable );
177 gtk_widget_set_sensitive( m_mainWindow, enable );
178 };
179
180 void wxFrame::OnCloseWindow( wxCloseEvent &event )
181 {
182 if ( GetEventHandler()->OnClose() || event.GetForce())
183 {
184 this->Destroy();
185 }
186 };
187
188 bool wxFrame::Destroy()
189 {
190 if (!wxPendingDelete.Member(this))
191 wxPendingDelete.Append(this);
192
193 return TRUE;
194 }
195
196 void wxFrame::GetClientSize( int *width, int *height ) const
197 {
198 wxWindow::GetClientSize( width, height );
199 if (height)
200 {
201 if (m_frameMenuBar) (*height) -= wxMENU_HEIGHT;
202 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
203 if (m_frameToolBar)
204 {
205 int y = 0;
206 m_frameToolBar->GetSize( NULL, &y );
207 (*height) -= y;
208 }
209 };
210 };
211
212 void wxFrame::GtkOnSize( int x, int y, int width, int height )
213 {
214 m_x = x;
215 m_y = y;
216
217 if ((m_height == height) && (m_width == width) &&
218 (m_sizeSet)) return;
219 if (!m_mainWindow) return;
220 if (!m_wxwindow) return;
221
222 m_width = width;
223 m_height = height;
224
225 gtk_widget_set_usize( m_widget, width, height );
226
227 int main_x = 0;
228 int main_y = 0;
229 int main_height = height;
230 int main_width = width;
231
232 // This emulates Windows behaviour:
233 // The menu bar is part of the main window, but the status bar
234 // is on the implementation side in the client area. The
235 // function GetClientSize returns the size of the client area
236 // minus the status bar height. Under wxGTK, the main window
237 // is represented by m_mainWindow. The menubar is inserted
238 // into m_mainWindow whereas the statusbar is insertes into
239 // m_wxwindow just like any other window.
240
241 // not really needed
242 gtk_widget_set_usize( m_mainWindow, width, height );
243
244 if (m_frameMenuBar)
245 {
246 main_y = wxMENU_HEIGHT;
247 main_height -= wxMENU_HEIGHT;
248 };
249
250 int toolbar_height = 0;
251 if (m_frameToolBar) m_frameToolBar->GetSize( NULL, &toolbar_height );
252
253 main_y += toolbar_height;
254 main_height -= toolbar_height;
255
256 gtk_widget_set_uposition( GTK_WIDGET(m_wxwindow), main_x, main_y );
257 gtk_widget_set_usize( GTK_WIDGET(m_wxwindow), main_width, main_height );
258
259 if (m_frameMenuBar)
260 {
261 gtk_widget_set_uposition( m_frameMenuBar->m_widget, 1, 1 );
262 gtk_widget_set_usize( m_frameMenuBar->m_widget, width-2, wxMENU_HEIGHT-2 );
263 };
264
265 if (m_frameToolBar)
266 {
267 gtk_widget_set_uposition( m_frameToolBar->m_widget, 1, wxMENU_HEIGHT );
268 gtk_widget_set_usize( m_frameToolBar->m_widget, width-2, toolbar_height );
269 };
270
271 if (m_frameStatusBar)
272 {
273 m_frameStatusBar->SetSize( 0, main_height-wxSTATUS_HEIGHT, width, wxSTATUS_HEIGHT );
274 };
275
276 m_sizeSet = TRUE;
277
278 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
279 event.SetEventObject( this );
280 ProcessEvent( event );
281 };
282
283 void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) )
284 {
285 if ( GetAutoLayout() )
286 Layout();
287 else {
288 // no child: go out !
289 if (!GetChildren()->First())
290 return;
291
292 // do we have exactly one child?
293 wxWindow *child = NULL;
294 for(wxNode *node = GetChildren()->First(); node; node = node->Next())
295 {
296 wxWindow *win = (wxWindow *)node->Data();
297 if (!IS_KIND_OF(win,wxFrame) && !IS_KIND_OF(win,wxDialog)
298 #if 0 // not in m_children anyway
299 && (win != m_frameMenuBar) &&
300 (win != m_frameToolBar) &&
301 (win != m_frameStatusBar)
302 #endif
303 )
304 {
305 if ( child ) // it's the second one: do nothing
306 return;
307
308 child = win;
309 };
310 };
311
312 // yes: set it's size to fill all the frame
313 int client_x, client_y;
314 GetClientSize(&client_x, &client_y);
315 child->SetSize( 1, 1, client_x-2, client_y);
316 }
317 };
318
319 void wxFrame::AddChild( wxWindow *child )
320 {
321 // wxFrame and wxDialog as children aren't placed into the parents
322
323 if (child->IsKindOf(CLASSINFO(wxFrame)) || child->IsKindOf(CLASSINFO(wxDialog)))
324 {
325 m_children.Append( child );
326
327 if ((child->m_x != -1) && (child->m_y != -1))
328 gtk_widget_set_uposition( child->m_widget, child->m_x, child->m_y );
329
330 return;
331 }
332
333 if (m_addPrivateChild)
334 {
335 gtk_myfixed_put( GTK_MYFIXED(m_mainWindow), child->m_widget, child->m_x, child->m_y );
336
337 gtk_widget_set_usize( child->m_widget, child->m_width, child->m_height );
338 }
339 else
340 {
341 m_children.Append( child );
342
343 if (m_wxwindow)
344 gtk_myfixed_put( GTK_MYFIXED(m_wxwindow), child->m_widget, child->m_x, child->m_y );
345
346 gtk_widget_set_usize( child->m_widget, child->m_width, child->m_height );
347 }
348 };
349
350 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
351 {
352 menu->SetInvokingWindow( win );
353 wxNode *node = menu->m_items.First();
354 while (node)
355 {
356 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
357 if (menuitem->IsSubMenu())
358 SetInvokingWindow( menuitem->GetSubMenu(), win );
359 node = node->Next();
360 };
361 };
362
363 void wxFrame::SetMenuBar( wxMenuBar *menuBar )
364 {
365 m_frameMenuBar = menuBar;
366
367 if (m_frameMenuBar)
368 {
369 if (m_frameMenuBar->m_parent != this)
370 {
371 wxNode *node = m_frameMenuBar->m_menus.First();
372 while (node)
373 {
374 wxMenu *menu = (wxMenu*)node->Data();
375 SetInvokingWindow( menu, this );
376 node = node->Next();
377 };
378
379 m_frameMenuBar->m_parent = this;
380 gtk_myfixed_put( GTK_MYFIXED(m_mainWindow),
381 m_frameMenuBar->m_widget, m_frameMenuBar->m_x, m_frameMenuBar->m_y );
382 }
383 }
384 };
385
386 wxMenuBar *wxFrame::GetMenuBar(void)
387 {
388 return m_frameMenuBar;
389 };
390
391 wxToolBar *wxFrame::CreateToolBar( long style , wxWindowID id, const wxString& name )
392 {
393 m_addPrivateChild = TRUE;
394
395 m_frameToolBar = new wxToolBar( this, id, wxDefaultPosition, wxDefaultSize, style, name );
396
397 m_addPrivateChild = FALSE;
398
399 return m_frameToolBar;
400 };
401
402 wxToolBar *wxFrame::GetToolBar(void)
403 {
404 return m_frameToolBar;
405 };
406
407 wxStatusBar* wxFrame::CreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
408 {
409 if (m_frameStatusBar)
410 delete m_frameStatusBar;
411
412 m_frameStatusBar = new wxStatusBar( this, id, wxPoint(0,0), wxSize(100,20), style, name );
413
414 m_frameStatusBar->SetFieldsCount( number );
415
416 return m_frameStatusBar;
417 };
418
419 void wxFrame::SetStatusText( const wxString &text, int number )
420 {
421 if (m_frameStatusBar) m_frameStatusBar->SetStatusText( text, number );
422 };
423
424 void wxFrame::SetStatusWidths( int n, int *width )
425 {
426 if (m_frameStatusBar) m_frameStatusBar->SetStatusWidths( n, width );
427 };
428
429 wxStatusBar *wxFrame::GetStatusBar(void)
430 {
431 return m_frameStatusBar;
432 };
433
434 void wxFrame::SetTitle( const wxString &title )
435 {
436 m_title = title;
437 gtk_window_set_title( GTK_WINDOW(m_widget), title );
438 };
439
440 void wxFrame::SetSizeHints(int minW, int minH, int maxW, int maxH, int WXUNUSED(incW) )
441 {
442 if (m_wxwindow)
443 gdk_window_set_hints( m_wxwindow->window, -1, -1,
444 minW, minH, maxW, maxH, GDK_HINT_MIN_SIZE | GDK_HINT_MIN_SIZE );
445 }
446
447 void wxFrame::SetIcon( const wxIcon &icon )
448 {
449 m_icon = icon;
450 if (!icon.Ok()) return;
451
452 wxMask *mask = icon.GetMask();
453 GdkBitmap *bm = NULL;
454 if (mask) bm = mask->GetBitmap();
455
456 gdk_window_set_icon( m_widget->window, NULL, icon.GetPixmap(), bm );
457 }
458