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