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