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