]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/mdi.cpp
reSWIGged
[wxWidgets.git] / src / gtk / mdi.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/gtk/mdi.cpp
3// Purpose:
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
13#include "wx/mdi.h"
14#include "wx/notebook.h"
15
16#if wxUSE_MDI
17
18#include "wx/dialog.h"
19#include "wx/menu.h"
20#include "wx/intl.h"
21#include "wx/gtk/private.h"
22
23#include <glib.h>
24#include <gdk/gdk.h>
25#include <gtk/gtk.h>
26#include "wx/gtk/win_gtk.h"
27
28//-----------------------------------------------------------------------------
29// constants
30//-----------------------------------------------------------------------------
31
32const int wxMENU_HEIGHT = 27;
33
34//-----------------------------------------------------------------------------
35// globals
36//-----------------------------------------------------------------------------
37
38extern wxList wxPendingDelete;
39
40//-----------------------------------------------------------------------------
41// "switch_page"
42//-----------------------------------------------------------------------------
43
44extern "C" {
45static void
46gtk_mdi_page_change_callback( GtkNotebook *WXUNUSED(widget),
47 GtkNotebookPage *page,
48 gint WXUNUSED(page_num),
49 wxMDIParentFrame *parent )
50{
51 if (g_isIdle)
52 wxapp_install_idle_handler();
53
54 // send deactivate event to old child
55
56 wxMDIChildFrame *child = parent->GetActiveChild();
57 if (child)
58 {
59 wxActivateEvent event1( wxEVT_ACTIVATE, false, child->GetId() );
60 event1.SetEventObject( child);
61 child->GetEventHandler()->ProcessEvent( event1 );
62 }
63
64 // send activate event to new child
65
66 wxMDIClientWindow *client_window = parent->GetClientWindow();
67 if (!client_window)
68 return;
69
70 child = (wxMDIChildFrame*) NULL;
71
72 wxWindowList::compatibility_iterator node = client_window->GetChildren().GetFirst();
73 while (node)
74 {
75 wxMDIChildFrame *child_frame = wxDynamicCast( node->GetData(), wxMDIChildFrame );
76 // CE: we come here in the destructor with a null child_frame - I think because
77 // g_signal_connect (m_widget, "switch_page", (see below)
78 // isn't deleted early enough
79 if (!child_frame)
80 return ;
81
82 if (child_frame->m_page == page)
83 {
84 child = child_frame;
85 break;
86 }
87 node = node->GetNext();
88 }
89
90 if (!child)
91 return;
92
93 wxActivateEvent event2( wxEVT_ACTIVATE, true, child->GetId() );
94 event2.SetEventObject( child);
95 child->GetEventHandler()->ProcessEvent( event2 );
96}
97}
98
99//-----------------------------------------------------------------------------
100// wxMDIParentFrame
101//-----------------------------------------------------------------------------
102
103IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame,wxFrame)
104
105void wxMDIParentFrame::Init()
106{
107 m_justInserted = false;
108 m_clientWindow = (wxMDIClientWindow *) NULL;
109}
110
111wxMDIParentFrame::~wxMDIParentFrame()
112{
113}
114
115bool wxMDIParentFrame::Create(wxWindow *parent,
116 wxWindowID id,
117 const wxString& title,
118 const wxPoint& pos,
119 const wxSize& size,
120 long style,
121 const wxString& name )
122{
123 wxFrame::Create( parent, id, title, pos, size, style, name );
124
125 OnCreateClient();
126
127 return true;
128}
129
130void wxMDIParentFrame::GtkOnSize( int x, int y, int width, int height )
131{
132 wxFrame::GtkOnSize( x, y, width, height );
133
134 wxMDIChildFrame *child_frame = GetActiveChild();
135 if (!child_frame) return;
136
137 wxMenuBar *menu_bar = child_frame->m_menuBar;
138 if (!menu_bar) return;
139 if (!menu_bar->m_widget) return;
140
141 menu_bar->m_x = 0;
142 menu_bar->m_y = 0;
143 menu_bar->m_width = m_width;
144 menu_bar->m_height = wxMENU_HEIGHT;
145 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
146 menu_bar->m_widget,
147 0, 0, m_width, wxMENU_HEIGHT );
148}
149
150void wxMDIParentFrame::OnInternalIdle()
151{
152 /* if a an MDI child window has just been inserted
153 it has to be brought to the top in idle time. we
154 simply set the last notebook page active as new
155 pages can only be appended at the end */
156
157 if (m_justInserted)
158 {
159 GtkNotebook *notebook = GTK_NOTEBOOK(m_clientWindow->m_widget);
160 gtk_notebook_set_current_page( notebook, g_list_length( notebook->children ) - 1 );
161
162 /* need to set the menubar of the child */
163 wxMDIChildFrame *active_child_frame = GetActiveChild();
164 if (active_child_frame != NULL)
165 {
166 wxMenuBar *menu_bar = active_child_frame->m_menuBar;
167 if (menu_bar)
168 {
169 menu_bar->m_width = m_width;
170 menu_bar->m_height = wxMENU_HEIGHT;
171 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
172 menu_bar->m_widget,
173 0, 0, m_width, wxMENU_HEIGHT );
174 menu_bar->SetInvokingWindow(active_child_frame);
175 }
176 }
177 m_justInserted = false;
178 return;
179 }
180
181 wxFrame::OnInternalIdle();
182
183 wxMDIChildFrame *active_child_frame = GetActiveChild();
184 bool visible_child_menu = false;
185
186 wxWindowList::compatibility_iterator node = m_clientWindow->GetChildren().GetFirst();
187 while (node)
188 {
189 wxMDIChildFrame *child_frame = wxDynamicCast( node->GetData(), wxMDIChildFrame );
190
191 if ( child_frame )
192 {
193 wxMenuBar *menu_bar = child_frame->m_menuBar;
194 if ( menu_bar )
195 {
196 if (child_frame == active_child_frame)
197 {
198 if (menu_bar->Show(true))
199 {
200 menu_bar->m_width = m_width;
201 menu_bar->m_height = wxMENU_HEIGHT;
202 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
203 menu_bar->m_widget,
204 0, 0, m_width, wxMENU_HEIGHT );
205 menu_bar->SetInvokingWindow( child_frame );
206 }
207 visible_child_menu = true;
208 }
209 else
210 {
211 if (menu_bar->Show(false))
212 {
213 menu_bar->UnsetInvokingWindow( child_frame );
214 }
215 }
216 }
217 }
218
219 node = node->GetNext();
220 }
221
222 /* show/hide parent menu bar as required */
223 if ((m_frameMenuBar) &&
224 (m_frameMenuBar->IsShown() == visible_child_menu))
225 {
226 if (visible_child_menu)
227 {
228 m_frameMenuBar->Show( false );
229 m_frameMenuBar->UnsetInvokingWindow( this );
230 }
231 else
232 {
233 m_frameMenuBar->Show( true );
234 m_frameMenuBar->SetInvokingWindow( this );
235
236 m_frameMenuBar->m_width = m_width;
237 m_frameMenuBar->m_height = wxMENU_HEIGHT;
238 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
239 m_frameMenuBar->m_widget,
240 0, 0, m_width, wxMENU_HEIGHT );
241 }
242 }
243}
244
245void wxMDIParentFrame::DoGetClientSize(int *width, int *height ) const
246{
247 wxFrame::DoGetClientSize( width, height );
248}
249
250wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
251{
252 if (!m_clientWindow) return (wxMDIChildFrame*) NULL;
253
254 GtkNotebook *notebook = GTK_NOTEBOOK(m_clientWindow->m_widget);
255 if (!notebook) return (wxMDIChildFrame*) NULL;
256
257 gint i = gtk_notebook_get_current_page( notebook );
258 if (i < 0) return (wxMDIChildFrame*) NULL;
259
260 GtkNotebookPage* page = (GtkNotebookPage*) (g_list_nth(notebook->children,i)->data);
261 if (!page) return (wxMDIChildFrame*) NULL;
262
263 wxWindowList::compatibility_iterator node = m_clientWindow->GetChildren().GetFirst();
264 while (node)
265 {
266 wxMDIChildFrame *child_frame = wxDynamicCast( node->GetData(), wxMDIChildFrame );
267
268 wxASSERT_MSG( child_frame, _T("child is not a wxMDIChildFrame") );
269
270 if (child_frame->m_page == page)
271 return child_frame;
272 node = node->GetNext();
273 }
274
275 return (wxMDIChildFrame*) NULL;
276}
277
278wxMDIClientWindow *wxMDIParentFrame::GetClientWindow() const
279{
280 return m_clientWindow;
281}
282
283wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
284{
285 m_clientWindow = new wxMDIClientWindow( this );
286 return m_clientWindow;
287}
288
289void wxMDIParentFrame::ActivateNext()
290{
291 if (m_clientWindow)
292 gtk_notebook_next_page( GTK_NOTEBOOK(m_clientWindow->m_widget) );
293}
294
295void wxMDIParentFrame::ActivatePrevious()
296{
297 if (m_clientWindow)
298 gtk_notebook_prev_page( GTK_NOTEBOOK(m_clientWindow->m_widget) );
299}
300
301//-----------------------------------------------------------------------------
302// wxMDIChildFrame
303//-----------------------------------------------------------------------------
304
305IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame,wxFrame)
306
307BEGIN_EVENT_TABLE(wxMDIChildFrame, wxFrame)
308 EVT_ACTIVATE(wxMDIChildFrame::OnActivate)
309 EVT_MENU_HIGHLIGHT_ALL(wxMDIChildFrame::OnMenuHighlight)
310END_EVENT_TABLE()
311
312wxMDIChildFrame::wxMDIChildFrame()
313{
314 m_menuBar = (wxMenuBar *) NULL;
315 m_page = (GtkNotebookPage *) NULL;
316}
317
318wxMDIChildFrame::wxMDIChildFrame( wxMDIParentFrame *parent,
319 wxWindowID id, const wxString& title,
320 const wxPoint& WXUNUSED(pos), const wxSize& size,
321 long style, const wxString& name )
322{
323 m_menuBar = (wxMenuBar *) NULL;
324 m_page = (GtkNotebookPage *) NULL;
325 Create( parent, id, title, wxDefaultPosition, size, style, name );
326}
327
328wxMDIChildFrame::~wxMDIChildFrame()
329{
330 if (m_menuBar)
331 delete m_menuBar;
332}
333
334bool wxMDIChildFrame::Create( wxMDIParentFrame *parent,
335 wxWindowID id, const wxString& title,
336 const wxPoint& WXUNUSED(pos), const wxSize& size,
337 long style, const wxString& name )
338{
339 m_title = title;
340
341 return wxWindow::Create( parent->GetClientWindow(), id, wxDefaultPosition, size, style, name );
342}
343
344void wxMDIChildFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
345{
346 wxWindow::DoSetSize( x, y, width, height, sizeFlags );
347}
348
349void wxMDIChildFrame::DoSetClientSize(int width, int height)
350{
351 wxWindow::DoSetClientSize( width, height );
352}
353
354void wxMDIChildFrame::DoGetClientSize( int *width, int *height ) const
355{
356 wxWindow::DoGetClientSize( width, height );
357}
358
359void wxMDIChildFrame::AddChild( wxWindowBase *child )
360{
361 wxWindow::AddChild(child);
362}
363
364void wxMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar )
365{
366 wxASSERT_MSG( m_menuBar == NULL, wxT("Only one menubar allowed") );
367
368 m_menuBar = menu_bar;
369
370 if (m_menuBar)
371 {
372 wxMDIParentFrame *mdi_frame = (wxMDIParentFrame*)m_parent->GetParent();
373
374 m_menuBar->SetParent( mdi_frame );
375
376 /* insert the invisible menu bar into the _parent_ mdi frame */
377 gtk_pizza_put( GTK_PIZZA(mdi_frame->m_mainWidget),
378 m_menuBar->m_widget,
379 0, 0, mdi_frame->m_width, wxMENU_HEIGHT );
380 }
381}
382
383wxMenuBar *wxMDIChildFrame::GetMenuBar() const
384{
385 return m_menuBar;
386}
387
388void wxMDIChildFrame::Activate()
389{
390 wxMDIParentFrame* parent = (wxMDIParentFrame*) GetParent();
391 GtkNotebook* notebook = GTK_NOTEBOOK(parent->m_widget);
392 gint pageno = gtk_notebook_page_num( notebook, m_widget );
393 gtk_notebook_set_current_page( notebook, pageno );
394}
395
396void wxMDIChildFrame::OnActivate( wxActivateEvent& WXUNUSED(event) )
397{
398}
399
400void wxMDIChildFrame::OnMenuHighlight( wxMenuEvent& event )
401{
402#if wxUSE_STATUSBAR
403 wxMDIParentFrame *mdi_frame = (wxMDIParentFrame*)m_parent->GetParent();
404 if ( !ShowMenuHelp(mdi_frame->GetStatusBar(), event.GetMenuId()) )
405 {
406 // we don't have any help text for this item, but may be the MDI frame
407 // does?
408 mdi_frame->OnMenuHighlight(event);
409 }
410#endif // wxUSE_STATUSBAR
411}
412
413void wxMDIChildFrame::SetTitle( const wxString &title )
414{
415 if ( title == m_title )
416 return;
417
418 m_title = title;
419
420 wxMDIParentFrame* parent = (wxMDIParentFrame*) GetParent();
421 GtkNotebook* notebook = GTK_NOTEBOOK(parent->m_widget);
422 gtk_notebook_set_tab_label_text(notebook, m_widget, wxGTK_CONV( title ) );
423}
424
425//-----------------------------------------------------------------------------
426// "size_allocate"
427//-----------------------------------------------------------------------------
428
429extern "C" {
430static void gtk_page_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxWindow *win )
431{
432 if (g_isIdle) wxapp_install_idle_handler();
433
434 if ((win->m_x == alloc->x) &&
435 (win->m_y == alloc->y) &&
436 (win->m_width == alloc->width) &&
437 (win->m_height == alloc->height) &&
438 (win->m_sizeSet))
439 {
440 return;
441 }
442
443 win->SetSize( alloc->x, alloc->y, alloc->width, alloc->height );
444}
445}
446
447//-----------------------------------------------------------------------------
448// InsertChild callback for wxMDIClientWindow
449//-----------------------------------------------------------------------------
450
451static void wxInsertChildInMDI( wxMDIClientWindow* parent, wxMDIChildFrame* child )
452{
453 wxString s = child->GetTitle();
454 if (s.IsNull()) s = _("MDI child");
455
456 GtkWidget *label_widget = gtk_label_new( s.mbc_str() );
457 gtk_misc_set_alignment( GTK_MISC(label_widget), 0.0, 0.5 );
458
459 g_signal_connect (child->m_widget, "size_allocate",
460 G_CALLBACK (gtk_page_size_callback), child);
461
462 GtkNotebook *notebook = GTK_NOTEBOOK(parent->m_widget);
463
464 gtk_notebook_append_page( notebook, child->m_widget, label_widget );
465
466 child->m_page = (GtkNotebookPage*) (g_list_last(notebook->children)->data);
467
468 wxMDIParentFrame *parent_frame = (wxMDIParentFrame*) parent->GetParent();
469 parent_frame->m_justInserted = true;
470}
471
472//-----------------------------------------------------------------------------
473// wxMDIClientWindow
474//-----------------------------------------------------------------------------
475
476IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow,wxWindow)
477
478wxMDIClientWindow::wxMDIClientWindow()
479{
480}
481
482wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame *parent, long style )
483{
484 CreateClient( parent, style );
485}
486
487wxMDIClientWindow::~wxMDIClientWindow()
488{
489
490}
491
492bool wxMDIClientWindow::CreateClient( wxMDIParentFrame *parent, long style )
493{
494 m_needParent = true;
495
496 m_insertCallback = (wxInsertChildFunction)wxInsertChildInMDI;
497
498 if (!PreCreation( parent, wxDefaultPosition, wxDefaultSize ) ||
499 !CreateBase( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style, wxDefaultValidator, wxT("wxMDIClientWindow") ))
500 {
501 wxFAIL_MSG( wxT("wxMDIClientWindow creation failed") );
502 return false;
503 }
504
505 m_widget = gtk_notebook_new();
506
507 g_signal_connect (m_widget, "switch_page",
508 G_CALLBACK (gtk_mdi_page_change_callback), parent);
509
510 gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget), 1 );
511
512 m_parent->DoAddChild( this );
513
514 PostCreation();
515
516 Show( true );
517
518 return true;
519}
520
521#endif