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