Improvements for notebooks on various versions of GTK
[wxWidgets.git] / src / gtk / mdi.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mdi.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 "mdi.h"
12 #endif
13
14 #include "wx/mdi.h"
15 #include "wx/dialog.h"
16 #include "wx/menu.h"
17 #include "wx/gtk/win_gtk.h"
18 #include <wx/intl.h>
19
20 //-----------------------------------------------------------------------------
21 // constants
22 //-----------------------------------------------------------------------------
23
24 const int wxMENU_HEIGHT = 30;
25
26 //-----------------------------------------------------------------------------
27 // globals
28 //-----------------------------------------------------------------------------
29
30 extern wxList wxPendingDelete;
31
32 //-----------------------------------------------------------------------------
33 // "size_allocate"
34 //-----------------------------------------------------------------------------
35
36 static void gtk_page_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxWindow *win )
37 {
38 if ((win->m_x == alloc->x) &&
39 (win->m_y == alloc->y) &&
40 (win->m_width == alloc->width) &&
41 (win->m_height == alloc->height) &&
42 (win->m_sizeSet))
43 {
44 return;
45 }
46
47 win->SetSize( alloc->x, alloc->y, alloc->width, alloc->height );
48 }
49
50 //-----------------------------------------------------------------------------
51 // page change callback
52 //-----------------------------------------------------------------------------
53
54 static void gtk_page_change_callback( GtkNotebook *WXUNUSED(widget),
55 GtkNotebookPage *page,
56 gint WXUNUSED(nPage),
57 wxMDIClientWindow *client_win )
58 {
59 wxNode *node = client_win->m_children.First();
60 while (node)
61 {
62 wxMDIChildFrame *child_frame = (wxMDIChildFrame *)node->Data();
63 if (child_frame->m_page == page)
64 {
65 wxMDIParentFrame *mdi_frame = (wxMDIParentFrame*)client_win->m_parent;
66 mdi_frame->m_currentChild = child_frame;
67 mdi_frame->SetMDIMenuBar( child_frame->m_menuBar );
68 return;
69 }
70 node = node->Next();
71 }
72 }
73
74 //-----------------------------------------------------------------------------
75 // wxMDIParentFrame
76 //-----------------------------------------------------------------------------
77
78 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame,wxFrame)
79
80 BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
81 END_EVENT_TABLE()
82
83 wxMDIParentFrame::wxMDIParentFrame(void)
84 {
85 m_clientWindow = (wxMDIClientWindow *) NULL;
86 m_currentChild = (wxMDIChildFrame *) NULL;
87 m_parentFrameActive = TRUE;
88 }
89
90 wxMDIParentFrame::wxMDIParentFrame( wxWindow *parent,
91 wxWindowID id, const wxString& title,
92 const wxPoint& pos, const wxSize& size,
93 long style, const wxString& name )
94 {
95 m_clientWindow = (wxMDIClientWindow *) NULL;
96 m_currentChild = (wxMDIChildFrame *) NULL;
97 m_parentFrameActive = TRUE;
98 Create( parent, id, title, pos, size, style, name );
99 }
100
101 wxMDIParentFrame::~wxMDIParentFrame(void)
102 {
103 }
104
105 bool wxMDIParentFrame::Create( wxWindow *parent,
106 wxWindowID id, const wxString& title,
107 const wxPoint& pos, const wxSize& size,
108 long style, const wxString& name )
109 {
110 wxFrame::Create( parent, id, title, pos, size, style, name );
111
112 OnCreateClient();
113
114 return TRUE;
115 }
116
117 void wxMDIParentFrame::GtkOnSize( int x, int y, int width, int height )
118 {
119 wxFrame::GtkOnSize( x, y, width, height );
120
121 if (m_mdiMenuBar)
122 {
123 m_mdiMenuBar->m_x = 1;
124 m_mdiMenuBar->m_y = 1;
125 m_mdiMenuBar->m_width = m_width-2;
126 m_mdiMenuBar->m_height = wxMENU_HEIGHT-2;
127 gtk_myfixed_move( GTK_MYFIXED(m_wxwindow), m_mdiMenuBar->m_widget, 1, 1 );
128 gtk_widget_set_usize( m_mdiMenuBar->m_widget, m_width-2, wxMENU_HEIGHT-2 );
129 }
130 }
131
132 void wxMDIParentFrame::SetMDIMenuBar( wxMenuBar *menu_bar )
133 {
134 if (m_mdiMenuBar) m_mdiMenuBar->Show( FALSE );
135 m_mdiMenuBar = menu_bar;
136 if (m_mdiMenuBar)
137 {
138 m_mdiMenuBar->m_x = 1;
139 m_mdiMenuBar->m_y = 1;
140 m_mdiMenuBar->m_width = m_width-2;
141 m_mdiMenuBar->m_height = wxMENU_HEIGHT-2;
142 gtk_myfixed_move( GTK_MYFIXED(m_wxwindow), m_mdiMenuBar->m_widget, 1, 1 );
143 gtk_widget_set_usize( m_mdiMenuBar->m_widget, m_width-2, wxMENU_HEIGHT-2 );
144 m_mdiMenuBar->Show( TRUE );
145 }
146 }
147
148 void wxMDIParentFrame::GetClientSize(int *width, int *height ) const
149 {
150 wxFrame::GetClientSize( width, height );
151 }
152
153 wxMDIChildFrame *wxMDIParentFrame::GetActiveChild(void) const
154 {
155 return m_currentChild;
156 }
157
158 wxMDIClientWindow *wxMDIParentFrame::GetClientWindow(void) const
159 {
160 return m_clientWindow;
161 }
162
163 wxMDIClientWindow *wxMDIParentFrame::OnCreateClient(void)
164 {
165 m_clientWindow = new wxMDIClientWindow( this );
166 return m_clientWindow;
167 }
168
169 void wxMDIParentFrame::ActivateNext(void)
170 {
171 if (m_clientWindow)
172 gtk_notebook_next_page( GTK_NOTEBOOK(m_clientWindow->m_widget) );
173 }
174
175 void wxMDIParentFrame::ActivatePrevious(void)
176 {
177 if (m_clientWindow)
178 gtk_notebook_prev_page( GTK_NOTEBOOK(m_clientWindow->m_widget) );
179 }
180
181 void wxMDIParentFrame::OnActivate( wxActivateEvent& WXUNUSED(event) )
182 {
183 }
184
185 void wxMDIParentFrame::OnSysColourChanged( wxSysColourChangedEvent& WXUNUSED(event) )
186 {
187 }
188
189 //-----------------------------------------------------------------------------
190 // wxMDIChildFrame
191 //-----------------------------------------------------------------------------
192
193 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame,wxFrame)
194
195 BEGIN_EVENT_TABLE(wxMDIChildFrame, wxFrame)
196 EVT_ACTIVATE(wxMDIChildFrame::OnActivate)
197 END_EVENT_TABLE()
198
199 wxMDIChildFrame::wxMDIChildFrame(void)
200 {
201 m_menuBar = (wxMenuBar *) NULL;
202 m_page = (GtkNotebookPage *) NULL;
203 }
204
205 wxMDIChildFrame::wxMDIChildFrame( wxMDIParentFrame *parent,
206 wxWindowID id, const wxString& title,
207 const wxPoint& WXUNUSED(pos), const wxSize& size,
208 long style, const wxString& name )
209 {
210 m_menuBar = (wxMenuBar *) NULL;
211 m_page = (GtkNotebookPage *) NULL;
212 Create( parent, id, title, wxDefaultPosition, size, style, name );
213 }
214
215 wxMDIChildFrame::~wxMDIChildFrame(void)
216 {
217 if (m_menuBar)
218 {
219 wxMDIParentFrame *mdi_frame = (wxMDIParentFrame*)m_parent->m_parent;
220 if (mdi_frame->m_currentChild == this)
221 {
222 mdi_frame->SetMDIMenuBar( (wxMenuBar *) NULL );
223 mdi_frame->m_currentChild = (wxMDIChildFrame *) NULL;
224 }
225 delete m_menuBar;
226 }
227 }
228
229 bool wxMDIChildFrame::Create( wxMDIParentFrame *parent,
230 wxWindowID id, const wxString& title,
231 const wxPoint& WXUNUSED(pos), const wxSize& size,
232 long style, const wxString& name )
233 {
234 m_title = title;
235
236 return wxWindow::Create( parent->GetClientWindow(), id, wxDefaultPosition, size, style, name );
237 }
238
239 void wxMDIChildFrame::GetClientSize( int *width, int *height ) const
240 {
241 wxWindow::GetClientSize( width, height );
242 }
243
244 void wxMDIChildFrame::AddChild( wxWindow *child )
245 {
246 wxWindow::AddChild( child );
247 }
248
249 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
250 {
251 menu->SetInvokingWindow( win );
252 wxNode *node = menu->m_items.First();
253 while (node)
254 {
255 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
256 if (menuitem->IsSubMenu())
257 SetInvokingWindow( menuitem->GetSubMenu(), win );
258 node = node->Next();
259 }
260 }
261
262 void wxMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar )
263 {
264 m_menuBar = menu_bar;
265
266 if (m_menuBar)
267 {
268 wxMDIParentFrame *mdi_frame = (wxMDIParentFrame*)m_parent->m_parent;
269
270 if (m_menuBar->m_parent != this)
271 {
272 wxNode *node = m_menuBar->m_menus.First();
273 while (node)
274 {
275 wxMenu *menu = (wxMenu*)node->Data();
276 SetInvokingWindow( menu, this );
277 node = node->Next();
278 }
279
280 m_menuBar->m_parent = mdi_frame;
281 }
282 mdi_frame->SetMDIMenuBar( m_menuBar );
283
284 gtk_myfixed_put( GTK_MYFIXED(mdi_frame->m_wxwindow),
285 m_menuBar->m_widget, m_menuBar->m_x, m_menuBar->m_y );
286 }
287 }
288
289 wxMenuBar *wxMDIChildFrame::GetMenuBar()
290 {
291 return m_menuBar;
292 }
293
294 void wxMDIChildFrame::Activate(void)
295 {
296 }
297
298 void wxMDIChildFrame::OnActivate( wxActivateEvent &WXUNUSED(event) )
299 {
300 }
301
302 //-----------------------------------------------------------------------------
303 // InsertChild callback for wxMDIClientWindow
304 //-----------------------------------------------------------------------------
305
306 static void wxInsertChildInMDI( wxMDIClientWindow* parent, wxMDIChildFrame* child )
307 {
308 wxString s = child->m_title;
309 if (s.IsNull()) s = _("MDI child");
310
311 GtkWidget *label_widget = gtk_label_new( s );
312 gtk_misc_set_alignment( GTK_MISC(label_widget), 0.0, 0.5 );
313
314 gtk_signal_connect( GTK_OBJECT(child->m_widget), "size_allocate",
315 GTK_SIGNAL_FUNC(gtk_page_size_callback), (gpointer)child );
316
317 GtkNotebook *notebook = GTK_NOTEBOOK(parent->m_widget);
318
319 gtk_notebook_append_page( notebook, child->m_widget, label_widget );
320
321 child->m_page = (GtkNotebookPage*) (g_list_last(notebook->children)->data);
322
323 gtk_notebook_set_page( notebook, parent->m_children.Number()-1 );
324
325 gtk_page_change_callback( (GtkNotebook *) NULL, child->m_page, 0, parent );
326 }
327
328 //-----------------------------------------------------------------------------
329 // wxMDIClientWindow
330 //-----------------------------------------------------------------------------
331
332 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow,wxWindow)
333
334 wxMDIClientWindow::wxMDIClientWindow(void)
335 {
336 }
337
338 wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame *parent, long style )
339 {
340 CreateClient( parent, style );
341 }
342
343 wxMDIClientWindow::~wxMDIClientWindow(void)
344 {
345 }
346
347 bool wxMDIClientWindow::CreateClient( wxMDIParentFrame *parent, long style )
348 {
349 m_needParent = TRUE;
350
351 m_insertCallback = (wxInsertChildFunction)wxInsertChildInMDI;
352
353 PreCreation( parent, -1, wxPoint(10,10), wxSize(100,100), style, "wxMDIClientWindow" );
354
355 m_widget = gtk_notebook_new();
356
357 gtk_signal_connect( GTK_OBJECT(m_widget), "switch_page",
358 GTK_SIGNAL_FUNC(gtk_page_change_callback), (gpointer)this );
359
360 gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget), 1 );
361
362 m_parent->AddChild( this );
363
364 (m_parent->m_insertCallback)( m_parent, this );
365
366 PostCreation();
367
368 Show( TRUE );
369
370 return TRUE;
371 }
372
373
374