]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/mdi.cpp
Some edits to the schedule.
[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"
dcf924a3
RR
15
16#if wxUSE_MDI_ARCHITECTURE
17
e3e65dac 18#include "wx/dialog.h"
cf4219e7 19#include "wx/menu.h"
1a5a8367 20#include <wx/intl.h>
716b7364 21
83624f79
RR
22#include "glib.h"
23#include "gdk/gdk.h"
24#include "gtk/gtk.h"
25#include "wx/gtk/win_gtk.h"
26
6ca41e57
RR
27//-----------------------------------------------------------------------------
28// constants
29//-----------------------------------------------------------------------------
30
a0fdacee 31const int wxMENU_HEIGHT = 27;
6ca41e57 32
acfd422a
RR
33//-----------------------------------------------------------------------------
34// idle system
35//-----------------------------------------------------------------------------
36
37extern void wxapp_install_idle_handler();
38extern bool g_isIdle;
39
6ca41e57
RR
40//-----------------------------------------------------------------------------
41// globals
716b7364
RR
42//-----------------------------------------------------------------------------
43
44extern wxList wxPendingDelete;
c801d85f 45
5e014a0c
RR
46//-----------------------------------------------------------------------------
47// "switch_page"
48//-----------------------------------------------------------------------------
49
50static void gtk_mdi_page_change_callback(GtkNotebook *WXUNUSED(widget),
51 GtkNotebookPage *WXUNUSED(page),
5e0201ea 52 gint WXUNUSED(page),
5e014a0c
RR
53 wxMDIParentFrame *parent )
54{
55 if (g_isIdle)
56 wxapp_install_idle_handler();
57
58 wxMDIChildFrame *child = parent->GetActiveChild();
59
60 if (!child) return;
61
62 wxActivateEvent event( wxEVT_ACTIVATE, TRUE, child->GetId() );
63 event.SetEventObject( child);
64 child->GetEventHandler()->ProcessEvent( event );
65}
66
6ca41e57
RR
67//-----------------------------------------------------------------------------
68// wxMDIParentFrame
33d0b396
RR
69//-----------------------------------------------------------------------------
70
c801d85f
KB
71IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame,wxFrame)
72
716b7364
RR
73BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
74END_EVENT_TABLE()
75
ab2b3dd4 76wxMDIParentFrame::wxMDIParentFrame()
c801d85f 77{
ab2b3dd4 78 m_justInserted = FALSE;
83624f79 79 m_clientWindow = (wxMDIClientWindow *) NULL;
ff7b1510 80}
c801d85f
KB
81
82wxMDIParentFrame::wxMDIParentFrame( wxWindow *parent,
debe6624 83 wxWindowID id, const wxString& title,
c801d85f 84 const wxPoint& pos, const wxSize& size,
debe6624 85 long style, const wxString& name )
c801d85f 86{
ab2b3dd4 87 m_justInserted = FALSE;
83624f79 88 m_clientWindow = (wxMDIClientWindow *) NULL;
83624f79 89 Create( parent, id, title, pos, size, style, name );
ff7b1510 90}
c801d85f 91
ab2b3dd4 92wxMDIParentFrame::~wxMDIParentFrame()
c801d85f 93{
ff7b1510 94}
c801d85f
KB
95
96bool wxMDIParentFrame::Create( wxWindow *parent,
debe6624 97 wxWindowID id, const wxString& title,
c801d85f 98 const wxPoint& pos, const wxSize& size,
debe6624 99 long style, const wxString& name )
c801d85f 100{
83624f79 101 wxFrame::Create( parent, id, title, pos, size, style, name );
a3622daa 102
83624f79 103 OnCreateClient();
a3622daa 104
83624f79 105 return TRUE;
ff7b1510 106}
c801d85f 107
716b7364 108void wxMDIParentFrame::GtkOnSize( int x, int y, int width, int height )
c801d85f 109{
83624f79 110 wxFrame::GtkOnSize( x, y, width, height );
a0fdacee 111
ab2b3dd4
RR
112 wxMDIChildFrame *child_frame = GetActiveChild();
113 if (!child_frame) return;
a0fdacee 114
ab2b3dd4
RR
115 wxMenuBar *menu_bar = child_frame->m_menuBar;
116 if (!menu_bar) return;
a2053b27 117 if (!menu_bar->m_widget) return;
a0fdacee 118
121a3581
RR
119 menu_bar->m_x = 0;
120 menu_bar->m_y = 0;
121 menu_bar->m_width = m_width;
122 menu_bar->m_height = wxMENU_HEIGHT;
da048e3d 123 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
a2053b27 124 menu_bar->m_widget,
f03fc89f 125 0, 0, m_width, wxMENU_HEIGHT );
ab2b3dd4
RR
126}
127
128void wxMDIParentFrame::OnInternalIdle()
129{
130 /* if a an MDI child window has just been inserted
131 it has to be brought to the top in idle time. we
132 simply set the last notebook page active as new
133 pages can only be appended at the end */
134
135 if (m_justInserted)
83624f79 136 {
a2053b27 137 GtkNotebook *notebook = GTK_NOTEBOOK(m_clientWindow->m_widget);
a0fdacee
VZ
138 gtk_notebook_set_page( notebook, g_list_length( notebook->children ) - 1 );
139
140 m_justInserted = FALSE;
141 return;
83624f79 142 }
a0fdacee 143
ab2b3dd4 144 wxFrame::OnInternalIdle();
c626a8b7 145
ab2b3dd4 146 wxMDIChildFrame *active_child_frame = GetActiveChild();
a260fe6a 147 bool visible_child_menu = FALSE;
a0fdacee 148
f03fc89f 149 wxNode *node = m_clientWindow->GetChildren().First();
ab2b3dd4 150 while (node)
83624f79 151 {
ab2b3dd4 152 wxMDIChildFrame *child_frame = (wxMDIChildFrame *)node->Data();
5bd9e519 153 wxMenuBar *menu_bar = child_frame->m_menuBar;
a0fdacee
VZ
154 if (child_frame->m_menuBar)
155 {
156 if (child_frame == active_child_frame)
f03fc89f 157 {
5bd9e519
RR
158 if (menu_bar->Show(TRUE))
159 {
160 menu_bar->m_width = m_width;
161 menu_bar->m_height = wxMENU_HEIGHT;
da048e3d 162 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
5bd9e519
RR
163 menu_bar->m_widget,
164 0, 0, m_width, wxMENU_HEIGHT );
165 menu_bar->SetInvokingWindow( child_frame );
166 }
167 visible_child_menu = TRUE;
f03fc89f 168 }
a0fdacee 169 else
5bd9e519
RR
170 {
171 if (menu_bar->Show(FALSE))
172 {
173 menu_bar->UnsetInvokingWindow( child_frame );
174 }
175 }
a0fdacee 176 }
ab2b3dd4 177 node = node->Next();
83624f79 178 }
a0fdacee 179
e27ce4e9 180 /* show/hide parent menu bar as required */
5bd9e519
RR
181 if ((m_frameMenuBar) &&
182 (m_frameMenuBar->IsShown() == visible_child_menu))
183 {
184 if (visible_child_menu)
185 {
186 m_frameMenuBar->Show( FALSE );
187 m_frameMenuBar->UnsetInvokingWindow( this );
188 }
189 else
190 {
191 m_frameMenuBar->Show( TRUE );
192 m_frameMenuBar->SetInvokingWindow( this );
193
194 m_frameMenuBar->m_width = m_width;
195 m_frameMenuBar->m_height = wxMENU_HEIGHT;
da048e3d 196 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
5bd9e519
RR
197 m_frameMenuBar->m_widget,
198 0, 0, m_width, wxMENU_HEIGHT );
199 }
200 }
ff7b1510 201}
716b7364
RR
202
203void wxMDIParentFrame::GetClientSize(int *width, int *height ) const
c801d85f 204{
83624f79 205 wxFrame::GetClientSize( width, height );
ff7b1510 206}
c801d85f 207
ab2b3dd4
RR
208wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
209{
210 if (!m_clientWindow) return (wxMDIChildFrame*) NULL;
a0fdacee 211
a2053b27 212 GtkNotebook *notebook = GTK_NOTEBOOK(m_clientWindow->m_widget);
ab2b3dd4 213 if (!notebook) return (wxMDIChildFrame*) NULL;
a0fdacee
VZ
214
215#if (GTK_MINOR_VERSION > 0)
ab2b3dd4 216 gint i = gtk_notebook_get_current_page( notebook );
a0fdacee
VZ
217#else
218 gint i = gtk_notebook_current_page( notebook );
219#endif
ab2b3dd4 220 if (i < 0) return (wxMDIChildFrame*) NULL;
a0fdacee 221
ab2b3dd4
RR
222 GtkNotebookPage* page = (GtkNotebookPage*) (g_list_nth(notebook->children,i)->data);
223 if (!page) return (wxMDIChildFrame*) NULL;
a0fdacee 224
f03fc89f 225 wxNode *node = m_clientWindow->GetChildren().First();
ab2b3dd4
RR
226 while (node)
227 {
228 wxMDIChildFrame *child_frame = (wxMDIChildFrame *)node->Data();
229 if (child_frame->m_page == page)
230 return child_frame;
231 node = node->Next();
232 }
a0fdacee 233
ab2b3dd4 234 return (wxMDIChildFrame*) NULL;
ff7b1510 235}
c801d85f 236
ab2b3dd4 237wxMDIClientWindow *wxMDIParentFrame::GetClientWindow() const
c801d85f 238{
83624f79 239 return m_clientWindow;
ff7b1510 240}
c801d85f 241
ab2b3dd4 242wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
c801d85f 243{
83624f79
RR
244 m_clientWindow = new wxMDIClientWindow( this );
245 return m_clientWindow;
ff7b1510 246}
c801d85f 247
ab2b3dd4 248void wxMDIParentFrame::ActivateNext()
c801d85f 249{
83624f79 250 if (m_clientWindow)
a2053b27 251 gtk_notebook_next_page( GTK_NOTEBOOK(m_clientWindow->m_widget) );
ff7b1510 252}
c801d85f 253
ab2b3dd4 254void wxMDIParentFrame::ActivatePrevious()
716b7364 255{
83624f79 256 if (m_clientWindow)
a2053b27 257 gtk_notebook_prev_page( GTK_NOTEBOOK(m_clientWindow->m_widget) );
ff7b1510 258}
716b7364
RR
259
260void wxMDIParentFrame::OnActivate( wxActivateEvent& WXUNUSED(event) )
c801d85f 261{
ff7b1510 262}
c801d85f
KB
263
264void wxMDIParentFrame::OnSysColourChanged( wxSysColourChangedEvent& WXUNUSED(event) )
265{
ff7b1510 266}
c801d85f
KB
267
268//-----------------------------------------------------------------------------
269// wxMDIChildFrame
270//-----------------------------------------------------------------------------
271
cf4219e7 272IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame,wxFrame)
c626a8b7 273
cf4219e7 274BEGIN_EVENT_TABLE(wxMDIChildFrame, wxFrame)
83624f79 275 EVT_ACTIVATE(wxMDIChildFrame::OnActivate)
716b7364
RR
276END_EVENT_TABLE()
277
ab2b3dd4 278wxMDIChildFrame::wxMDIChildFrame()
c801d85f 279{
83624f79
RR
280 m_menuBar = (wxMenuBar *) NULL;
281 m_page = (GtkNotebookPage *) NULL;
ff7b1510 282}
c801d85f
KB
283
284wxMDIChildFrame::wxMDIChildFrame( wxMDIParentFrame *parent,
debe6624 285 wxWindowID id, const wxString& title,
33d0b396 286 const wxPoint& WXUNUSED(pos), const wxSize& size,
debe6624 287 long style, const wxString& name )
c801d85f 288{
83624f79
RR
289 m_menuBar = (wxMenuBar *) NULL;
290 m_page = (GtkNotebookPage *) NULL;
291 Create( parent, id, title, wxDefaultPosition, size, style, name );
ff7b1510 292}
c801d85f 293
ab2b3dd4 294wxMDIChildFrame::~wxMDIChildFrame()
c801d85f 295{
83624f79 296 if (m_menuBar)
83624f79 297 delete m_menuBar;
ff7b1510 298}
c801d85f
KB
299
300bool wxMDIChildFrame::Create( wxMDIParentFrame *parent,
debe6624 301 wxWindowID id, const wxString& title,
33d0b396 302 const wxPoint& WXUNUSED(pos), const wxSize& size,
debe6624 303 long style, const wxString& name )
c801d85f 304{
83624f79 305 m_title = title;
c626a8b7 306
83624f79 307 return wxWindow::Create( parent->GetClientWindow(), id, wxDefaultPosition, size, style, name );
ff7b1510 308}
c801d85f 309
cf4219e7 310void wxMDIChildFrame::GetClientSize( int *width, int *height ) const
c801d85f 311{
83624f79 312 wxWindow::GetClientSize( width, height );
cf4219e7 313}
9746a2ba 314
7a903311 315void wxMDIChildFrame::AddChild( wxWindowBase *child )
716b7364 316{
7a903311 317 wxWindow::AddChild(child);
716b7364 318}
c626a8b7 319
716b7364
RR
320void wxMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar )
321{
223d09f6 322 wxASSERT_MSG( m_menuBar == NULL, wxT("Only one menubar allowed") );
5bd9e519 323
83624f79 324 m_menuBar = menu_bar;
a3622daa 325
83624f79 326 if (m_menuBar)
716b7364 327 {
f03fc89f 328 wxMDIParentFrame *mdi_frame = (wxMDIParentFrame*)m_parent->GetParent();
83624f79 329
5bd9e519 330 m_menuBar->SetParent( mdi_frame );
c626a8b7 331
ab2b3dd4 332 /* insert the invisible menu bar into the _parent_ mdi frame */
da048e3d 333 gtk_pizza_put( GTK_PIZZA(mdi_frame->m_mainWidget),
a2053b27
RR
334 m_menuBar->m_widget,
335 0, 0, mdi_frame->m_width, wxMENU_HEIGHT );
716b7364 336 }
ff7b1510 337}
cf4219e7 338
33b64e6f 339wxMenuBar *wxMDIChildFrame::GetMenuBar() const
cf4219e7 340{
83624f79 341 return m_menuBar;
ff7b1510 342}
c801d85f 343
ab2b3dd4 344void wxMDIChildFrame::Activate()
c801d85f 345{
adde8c98
RR
346#if (GTK_MINOR_VERSION > 0)
347 wxMDIParentFrame* parent = (wxMDIParentFrame*) GetParent();
97560ce3 348 GtkNotebook* notebook = GTK_NOTEBOOK(parent->m_widget);
adde8c98
RR
349 gint pageno = gtk_notebook_page_num( notebook, m_page->child );
350 gtk_notebook_set_page( notebook, pageno );
97560ce3
RS
351#else
352 // the only way I can see to do this under gtk+ 1.0.X would
353 // be to keep track of page numbers, start at first and
354 // do "next" enough times to get to this page number - messy
355 // - J. Russell Smyth
356#endif
ff7b1510 357}
c801d85f 358
9746a2ba
RR
359void wxMDIChildFrame::OnActivate( wxActivateEvent &WXUNUSED(event) )
360{
ff7b1510 361}
9746a2ba 362
ab2b3dd4
RR
363//-----------------------------------------------------------------------------
364// "size_allocate"
365//-----------------------------------------------------------------------------
366
367static void gtk_page_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxWindow *win )
368{
acfd422a
RR
369 if (g_isIdle) wxapp_install_idle_handler();
370
a2053b27
RR
371 if ((win->m_x == alloc->x) &&
372 (win->m_y == alloc->y) &&
373 (win->m_width == alloc->width) &&
374 (win->m_height == alloc->height) &&
375 (win->m_sizeSet))
ab2b3dd4
RR
376 {
377 return;
378 }
379
380 win->SetSize( alloc->x, alloc->y, alloc->width, alloc->height );
381}
382
6ca41e57
RR
383//-----------------------------------------------------------------------------
384// InsertChild callback for wxMDIClientWindow
385//-----------------------------------------------------------------------------
386
387static void wxInsertChildInMDI( wxMDIClientWindow* parent, wxMDIChildFrame* child )
388{
83624f79
RR
389 wxString s = child->m_title;
390 if (s.IsNull()) s = _("MDI child");
6ca41e57 391
ed9b9841 392 GtkWidget *label_widget = gtk_label_new( s.mbc_str() );
83624f79 393 gtk_misc_set_alignment( GTK_MISC(label_widget), 0.0, 0.5 );
6ca41e57 394
a2053b27 395 gtk_signal_connect( GTK_OBJECT(child->m_widget), "size_allocate",
83624f79 396 GTK_SIGNAL_FUNC(gtk_page_size_callback), (gpointer)child );
c626a8b7 397
a2053b27 398 GtkNotebook *notebook = GTK_NOTEBOOK(parent->m_widget);
c626a8b7 399
a2053b27 400 gtk_notebook_append_page( notebook, child->m_widget, label_widget );
6ca41e57 401
83624f79 402 child->m_page = (GtkNotebookPage*) (g_list_last(notebook->children)->data);
a0fdacee 403
f03fc89f 404 wxMDIParentFrame *parent_frame = (wxMDIParentFrame*) parent->GetParent();
ab2b3dd4 405 parent_frame->m_justInserted = TRUE;
6ca41e57
RR
406}
407
c801d85f
KB
408//-----------------------------------------------------------------------------
409// wxMDIClientWindow
410//-----------------------------------------------------------------------------
411
412IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow,wxWindow)
413
ab2b3dd4 414wxMDIClientWindow::wxMDIClientWindow()
c801d85f 415{
ff7b1510 416}
c801d85f 417
debe6624 418wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame *parent, long style )
c801d85f 419{
83624f79 420 CreateClient( parent, style );
ff7b1510 421}
c801d85f 422
ab2b3dd4 423wxMDIClientWindow::~wxMDIClientWindow()
c801d85f 424{
ff7b1510 425}
c801d85f 426
debe6624 427bool wxMDIClientWindow::CreateClient( wxMDIParentFrame *parent, long style )
c801d85f 428{
83624f79 429 m_needParent = TRUE;
c626a8b7 430
83624f79 431 m_insertCallback = (wxInsertChildFunction)wxInsertChildInMDI;
a3622daa 432
4dcaf11a 433 if (!PreCreation( parent, wxDefaultPosition, wxDefaultSize ) ||
223d09f6 434 !CreateBase( parent, -1, wxDefaultPosition, wxDefaultSize, style, wxDefaultValidator, wxT("wxMDIClientWindow") ))
4dcaf11a 435 {
223d09f6 436 wxFAIL_MSG( wxT("wxMDIClientWindow creation failed") );
4dcaf11a
RR
437 return FALSE;
438 }
c801d85f 439
83624f79 440 m_widget = gtk_notebook_new();
a3622daa 441
5e014a0c
RR
442 gtk_signal_connect( GTK_OBJECT(m_widget), "switch_page",
443 GTK_SIGNAL_FUNC(gtk_mdi_page_change_callback), (gpointer)parent );
444
83624f79 445 gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget), 1 );
a3622daa 446
f03fc89f 447 m_parent->DoAddChild( this );
c626a8b7 448
83624f79 449 PostCreation();
a3622daa 450
83624f79 451 Show( TRUE );
a3622daa 452
83624f79 453 return TRUE;
ff7b1510 454}
c801d85f 455
dcf924a3 456#endif