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