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