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