Small modifications to Vadims changes
[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/intl.h>
18
19 #include "glib.h"
20 #include "gdk/gdk.h"
21 #include "gtk/gtk.h"
22 #include "wx/gtk/win_gtk.h"
23
24 //-----------------------------------------------------------------------------
25 // constants
26 //-----------------------------------------------------------------------------
27
28 const int wxMENU_HEIGHT = 27;
29
30 //-----------------------------------------------------------------------------
31 // idle system
32 //-----------------------------------------------------------------------------
33
34 extern void wxapp_install_idle_handler();
35 extern bool g_isIdle;
36
37 //-----------------------------------------------------------------------------
38 // globals
39 //-----------------------------------------------------------------------------
40
41 extern wxList wxPendingDelete;
42
43 //-----------------------------------------------------------------------------
44 // wxMDIParentFrame
45 //-----------------------------------------------------------------------------
46
47 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame,wxFrame)
48
49 BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
50 END_EVENT_TABLE()
51
52 wxMDIParentFrame::wxMDIParentFrame()
53 {
54 m_justInserted = FALSE;
55 m_clientWindow = (wxMDIClientWindow *) NULL;
56 }
57
58 wxMDIParentFrame::wxMDIParentFrame( wxWindow *parent,
59 wxWindowID id, const wxString& title,
60 const wxPoint& pos, const wxSize& size,
61 long style, const wxString& name )
62 {
63 m_justInserted = FALSE;
64 m_clientWindow = (wxMDIClientWindow *) NULL;
65 Create( parent, id, title, pos, size, style, name );
66 }
67
68 wxMDIParentFrame::~wxMDIParentFrame()
69 {
70 }
71
72 bool wxMDIParentFrame::Create( wxWindow *parent,
73 wxWindowID id, const wxString& title,
74 const wxPoint& pos, const wxSize& size,
75 long style, const wxString& name )
76 {
77 wxFrame::Create( parent, id, title, pos, size, style, name );
78
79 OnCreateClient();
80
81 return TRUE;
82 }
83
84 void wxMDIParentFrame::GtkOnSize( int x, int y, int width, int height )
85 {
86 wxFrame::GtkOnSize( x, y, width, height );
87
88 wxMDIChildFrame *child_frame = GetActiveChild();
89 if (!child_frame) return;
90
91 wxMenuBar *menu_bar = child_frame->m_menuBar;
92 if (!menu_bar) return;
93 if (!menu_bar->m_widget) return;
94
95 menu_bar->InternalSetPosition(0, 0);
96 menu_bar->InternalSetSize(m_width, wxMENU_HEIGHT);
97 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
98 menu_bar->m_widget,
99 0, 0, m_width, wxMENU_HEIGHT );
100 }
101
102 void wxMDIParentFrame::OnInternalIdle()
103 {
104 /* if a an MDI child window has just been inserted
105 it has to be brought to the top in idle time. we
106 simply set the last notebook page active as new
107 pages can only be appended at the end */
108
109 if (m_justInserted)
110 {
111 GtkNotebook *notebook = GTK_NOTEBOOK(m_clientWindow->m_widget);
112 gtk_notebook_set_page( notebook, g_list_length( notebook->children ) - 1 );
113
114 m_justInserted = FALSE;
115 return;
116 }
117
118 wxFrame::OnInternalIdle();
119
120 wxMDIChildFrame *active_child_frame = GetActiveChild();
121 bool visible_child_menu = FALSE;
122
123 wxNode *node = m_clientWindow->GetChildren().First();
124 while (node)
125 {
126 wxMDIChildFrame *child_frame = (wxMDIChildFrame *)node->Data();
127 if (child_frame->m_menuBar)
128 {
129 if (child_frame == active_child_frame)
130 {
131 gtk_widget_show( child_frame->m_menuBar->m_widget );
132 visible_child_menu = TRUE;
133 }
134 else
135 gtk_widget_hide( child_frame->m_menuBar->m_widget );
136 }
137 node = node->Next();
138 }
139
140 /* show/hide parent menu bar as required */
141 if (m_frameMenuBar) m_frameMenuBar->Show( !visible_child_menu );
142 }
143
144 void wxMDIParentFrame::GetClientSize(int *width, int *height ) const
145 {
146 wxFrame::GetClientSize( width, height );
147 }
148
149 wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
150 {
151 if (!m_clientWindow) return (wxMDIChildFrame*) NULL;
152
153 GtkNotebook *notebook = GTK_NOTEBOOK(m_clientWindow->m_widget);
154 if (!notebook) return (wxMDIChildFrame*) NULL;
155
156 #if (GTK_MINOR_VERSION > 0)
157 gint i = gtk_notebook_get_current_page( notebook );
158 #else
159 gint i = gtk_notebook_current_page( notebook );
160 #endif
161 if (i < 0) return (wxMDIChildFrame*) NULL;
162
163 GtkNotebookPage* page = (GtkNotebookPage*) (g_list_nth(notebook->children,i)->data);
164 if (!page) return (wxMDIChildFrame*) NULL;
165
166 wxNode *node = m_clientWindow->GetChildren().First();
167 while (node)
168 {
169 wxMDIChildFrame *child_frame = (wxMDIChildFrame *)node->Data();
170 if (child_frame->m_page == page)
171 return child_frame;
172 node = node->Next();
173 }
174
175 return (wxMDIChildFrame*) NULL;
176 }
177
178 wxMDIClientWindow *wxMDIParentFrame::GetClientWindow() const
179 {
180 return m_clientWindow;
181 }
182
183 wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
184 {
185 m_clientWindow = new wxMDIClientWindow( this );
186 return m_clientWindow;
187 }
188
189 void wxMDIParentFrame::ActivateNext()
190 {
191 if (m_clientWindow)
192 gtk_notebook_next_page( GTK_NOTEBOOK(m_clientWindow->m_widget) );
193 }
194
195 void wxMDIParentFrame::ActivatePrevious()
196 {
197 if (m_clientWindow)
198 gtk_notebook_prev_page( GTK_NOTEBOOK(m_clientWindow->m_widget) );
199 }
200
201 void wxMDIParentFrame::OnActivate( wxActivateEvent& WXUNUSED(event) )
202 {
203 }
204
205 void wxMDIParentFrame::OnSysColourChanged( wxSysColourChangedEvent& WXUNUSED(event) )
206 {
207 }
208
209 //-----------------------------------------------------------------------------
210 // wxMDIChildFrame
211 //-----------------------------------------------------------------------------
212
213 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame,wxFrame)
214
215 BEGIN_EVENT_TABLE(wxMDIChildFrame, wxFrame)
216 EVT_ACTIVATE(wxMDIChildFrame::OnActivate)
217 END_EVENT_TABLE()
218
219 wxMDIChildFrame::wxMDIChildFrame()
220 {
221 m_menuBar = (wxMenuBar *) NULL;
222 m_page = (GtkNotebookPage *) NULL;
223 }
224
225 wxMDIChildFrame::wxMDIChildFrame( wxMDIParentFrame *parent,
226 wxWindowID id, const wxString& title,
227 const wxPoint& WXUNUSED(pos), const wxSize& size,
228 long style, const wxString& name )
229 {
230 m_menuBar = (wxMenuBar *) NULL;
231 m_page = (GtkNotebookPage *) NULL;
232 Create( parent, id, title, wxDefaultPosition, size, style, name );
233 }
234
235 wxMDIChildFrame::~wxMDIChildFrame()
236 {
237 if (m_menuBar)
238 delete m_menuBar;
239 }
240
241 bool wxMDIChildFrame::Create( wxMDIParentFrame *parent,
242 wxWindowID id, const wxString& title,
243 const wxPoint& WXUNUSED(pos), const wxSize& size,
244 long style, const wxString& name )
245 {
246 m_title = title;
247
248 return wxWindow::Create( parent->GetClientWindow(), id, wxDefaultPosition, size, style, name );
249 }
250
251 void wxMDIChildFrame::GetClientSize( int *width, int *height ) const
252 {
253 wxWindow::GetClientSize( width, height );
254 }
255
256 void wxMDIChildFrame::AddChild( wxWindow *child )
257 {
258 wxWindow::AddChild( child );
259 }
260
261 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
262 {
263 menu->SetInvokingWindow( win );
264 wxNode *node = menu->GetItems().First();
265 while (node)
266 {
267 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
268 if (menuitem->IsSubMenu())
269 SetInvokingWindow( menuitem->GetSubMenu(), win );
270 node = node->Next();
271 }
272 }
273
274 void wxMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar )
275 {
276 m_menuBar = menu_bar;
277
278 if (m_menuBar)
279 {
280 wxMDIParentFrame *mdi_frame = (wxMDIParentFrame*)m_parent->GetParent();
281
282 if (m_menuBar->GetParent() != this)
283 {
284 wxNode *node = m_menuBar->GetMenus().First();
285 while (node)
286 {
287 wxMenu *menu = (wxMenu*)node->Data();
288 SetInvokingWindow( menu, this );
289 node = node->Next();
290 }
291
292 m_menuBar->SetParent( mdi_frame );
293 }
294
295 /* the menu bar of the child window is shown in idle time as needed */
296 gtk_widget_hide( m_menuBar->m_widget );
297
298 /* insert the invisible menu bar into the _parent_ mdi frame */
299 gtk_myfixed_put( GTK_MYFIXED(mdi_frame->m_mainWidget),
300 m_menuBar->m_widget,
301 0, 0, mdi_frame->m_width, wxMENU_HEIGHT );
302 }
303 }
304
305 wxMenuBar *wxMDIChildFrame::GetMenuBar() const
306 {
307 return m_menuBar;
308 }
309
310 void wxMDIChildFrame::Activate()
311 {
312 }
313
314 void wxMDIChildFrame::OnActivate( wxActivateEvent &WXUNUSED(event) )
315 {
316 }
317
318 //-----------------------------------------------------------------------------
319 // "size_allocate"
320 //-----------------------------------------------------------------------------
321
322 static void gtk_page_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxWindow *win )
323 {
324 if (g_isIdle) wxapp_install_idle_handler();
325
326 if ((win->m_x == alloc->x) &&
327 (win->m_y == alloc->y) &&
328 (win->m_width == alloc->width) &&
329 (win->m_height == alloc->height) &&
330 (win->m_sizeSet))
331 {
332 return;
333 }
334
335 win->SetSize( alloc->x, alloc->y, alloc->width, alloc->height );
336 }
337
338 //-----------------------------------------------------------------------------
339 // InsertChild callback for wxMDIClientWindow
340 //-----------------------------------------------------------------------------
341
342 static void wxInsertChildInMDI( wxMDIClientWindow* parent, wxMDIChildFrame* child )
343 {
344 wxString s = child->m_title;
345 if (s.IsNull()) s = _("MDI child");
346
347 GtkWidget *label_widget = gtk_label_new( s.mbc_str() );
348 gtk_misc_set_alignment( GTK_MISC(label_widget), 0.0, 0.5 );
349
350 gtk_signal_connect( GTK_OBJECT(child->m_widget), "size_allocate",
351 GTK_SIGNAL_FUNC(gtk_page_size_callback), (gpointer)child );
352
353 GtkNotebook *notebook = GTK_NOTEBOOK(parent->m_widget);
354
355 gtk_notebook_append_page( notebook, child->m_widget, label_widget );
356
357 child->m_page = (GtkNotebookPage*) (g_list_last(notebook->children)->data);
358
359 wxMDIParentFrame *parent_frame = (wxMDIParentFrame*) parent->GetParent();
360 parent_frame->m_justInserted = TRUE;
361 }
362
363 //-----------------------------------------------------------------------------
364 // wxMDIClientWindow
365 //-----------------------------------------------------------------------------
366
367 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow,wxWindow)
368
369 wxMDIClientWindow::wxMDIClientWindow()
370 {
371 }
372
373 wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame *parent, long style )
374 {
375 CreateClient( parent, style );
376 }
377
378 wxMDIClientWindow::~wxMDIClientWindow()
379 {
380 }
381
382 bool wxMDIClientWindow::CreateClient( wxMDIParentFrame *parent, long style )
383 {
384 m_needParent = TRUE;
385
386 m_insertCallback = (wxInsertChildFunction)wxInsertChildInMDI;
387
388 PreCreation( parent, -1, wxPoint(10,10), wxSize(100,100), style, "wxMDIClientWindow" );
389
390 m_widget = gtk_notebook_new();
391
392 gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget), 1 );
393
394 m_parent->DoAddChild( this );
395
396 PostCreation();
397
398 Show( TRUE );
399
400 return TRUE;
401 }
402