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