]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/mdi.cpp
Added wxWindowBase::CentreOnParent to allow top level windows to be
[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();
5bd9e519 129 wxMenuBar *menu_bar = child_frame->m_menuBar;
a0fdacee
VZ
130 if (child_frame->m_menuBar)
131 {
132 if (child_frame == active_child_frame)
f03fc89f 133 {
5bd9e519
RR
134 if (menu_bar->Show(TRUE))
135 {
136 menu_bar->m_width = m_width;
137 menu_bar->m_height = wxMENU_HEIGHT;
138 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
139 menu_bar->m_widget,
140 0, 0, m_width, wxMENU_HEIGHT );
141 menu_bar->SetInvokingWindow( child_frame );
142 }
143 visible_child_menu = TRUE;
f03fc89f 144 }
a0fdacee 145 else
5bd9e519
RR
146 {
147 if (menu_bar->Show(FALSE))
148 {
149 menu_bar->UnsetInvokingWindow( child_frame );
150 }
151 }
a0fdacee 152 }
ab2b3dd4 153 node = node->Next();
83624f79 154 }
a0fdacee 155
e27ce4e9 156 /* show/hide parent menu bar as required */
5bd9e519
RR
157 if ((m_frameMenuBar) &&
158 (m_frameMenuBar->IsShown() == visible_child_menu))
159 {
160 if (visible_child_menu)
161 {
162 m_frameMenuBar->Show( FALSE );
163 m_frameMenuBar->UnsetInvokingWindow( this );
164 }
165 else
166 {
167 m_frameMenuBar->Show( TRUE );
168 m_frameMenuBar->SetInvokingWindow( this );
169
170 m_frameMenuBar->m_width = m_width;
171 m_frameMenuBar->m_height = wxMENU_HEIGHT;
172 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
173 m_frameMenuBar->m_widget,
174 0, 0, m_width, wxMENU_HEIGHT );
175 }
176 }
ff7b1510 177}
716b7364
RR
178
179void wxMDIParentFrame::GetClientSize(int *width, int *height ) const
c801d85f 180{
83624f79 181 wxFrame::GetClientSize( width, height );
ff7b1510 182}
c801d85f 183
ab2b3dd4
RR
184wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
185{
186 if (!m_clientWindow) return (wxMDIChildFrame*) NULL;
a0fdacee 187
a2053b27 188 GtkNotebook *notebook = GTK_NOTEBOOK(m_clientWindow->m_widget);
ab2b3dd4 189 if (!notebook) return (wxMDIChildFrame*) NULL;
a0fdacee
VZ
190
191#if (GTK_MINOR_VERSION > 0)
ab2b3dd4 192 gint i = gtk_notebook_get_current_page( notebook );
a0fdacee
VZ
193#else
194 gint i = gtk_notebook_current_page( notebook );
195#endif
ab2b3dd4 196 if (i < 0) return (wxMDIChildFrame*) NULL;
a0fdacee 197
ab2b3dd4
RR
198 GtkNotebookPage* page = (GtkNotebookPage*) (g_list_nth(notebook->children,i)->data);
199 if (!page) return (wxMDIChildFrame*) NULL;
a0fdacee 200
f03fc89f 201 wxNode *node = m_clientWindow->GetChildren().First();
ab2b3dd4
RR
202 while (node)
203 {
204 wxMDIChildFrame *child_frame = (wxMDIChildFrame *)node->Data();
205 if (child_frame->m_page == page)
206 return child_frame;
207 node = node->Next();
208 }
a0fdacee 209
ab2b3dd4 210 return (wxMDIChildFrame*) NULL;
ff7b1510 211}
c801d85f 212
ab2b3dd4 213wxMDIClientWindow *wxMDIParentFrame::GetClientWindow() const
c801d85f 214{
83624f79 215 return m_clientWindow;
ff7b1510 216}
c801d85f 217
ab2b3dd4 218wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
c801d85f 219{
83624f79
RR
220 m_clientWindow = new wxMDIClientWindow( this );
221 return m_clientWindow;
ff7b1510 222}
c801d85f 223
ab2b3dd4 224void wxMDIParentFrame::ActivateNext()
c801d85f 225{
83624f79 226 if (m_clientWindow)
a2053b27 227 gtk_notebook_next_page( GTK_NOTEBOOK(m_clientWindow->m_widget) );
ff7b1510 228}
c801d85f 229
ab2b3dd4 230void wxMDIParentFrame::ActivatePrevious()
716b7364 231{
83624f79 232 if (m_clientWindow)
a2053b27 233 gtk_notebook_prev_page( GTK_NOTEBOOK(m_clientWindow->m_widget) );
ff7b1510 234}
716b7364
RR
235
236void wxMDIParentFrame::OnActivate( wxActivateEvent& WXUNUSED(event) )
c801d85f 237{
ff7b1510 238}
c801d85f
KB
239
240void wxMDIParentFrame::OnSysColourChanged( wxSysColourChangedEvent& WXUNUSED(event) )
241{
ff7b1510 242}
c801d85f
KB
243
244//-----------------------------------------------------------------------------
245// wxMDIChildFrame
246//-----------------------------------------------------------------------------
247
cf4219e7 248IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame,wxFrame)
c626a8b7 249
cf4219e7 250BEGIN_EVENT_TABLE(wxMDIChildFrame, wxFrame)
83624f79 251 EVT_ACTIVATE(wxMDIChildFrame::OnActivate)
716b7364
RR
252END_EVENT_TABLE()
253
ab2b3dd4 254wxMDIChildFrame::wxMDIChildFrame()
c801d85f 255{
83624f79
RR
256 m_menuBar = (wxMenuBar *) NULL;
257 m_page = (GtkNotebookPage *) NULL;
ff7b1510 258}
c801d85f
KB
259
260wxMDIChildFrame::wxMDIChildFrame( wxMDIParentFrame *parent,
debe6624 261 wxWindowID id, const wxString& title,
33d0b396 262 const wxPoint& WXUNUSED(pos), const wxSize& size,
debe6624 263 long style, const wxString& name )
c801d85f 264{
83624f79
RR
265 m_menuBar = (wxMenuBar *) NULL;
266 m_page = (GtkNotebookPage *) NULL;
267 Create( parent, id, title, wxDefaultPosition, size, style, name );
ff7b1510 268}
c801d85f 269
ab2b3dd4 270wxMDIChildFrame::~wxMDIChildFrame()
c801d85f 271{
83624f79 272 if (m_menuBar)
83624f79 273 delete m_menuBar;
ff7b1510 274}
c801d85f
KB
275
276bool wxMDIChildFrame::Create( wxMDIParentFrame *parent,
debe6624 277 wxWindowID id, const wxString& title,
33d0b396 278 const wxPoint& WXUNUSED(pos), const wxSize& size,
debe6624 279 long style, const wxString& name )
c801d85f 280{
83624f79 281 m_title = title;
c626a8b7 282
83624f79 283 return wxWindow::Create( parent->GetClientWindow(), id, wxDefaultPosition, size, style, name );
ff7b1510 284}
c801d85f 285
cf4219e7 286void wxMDIChildFrame::GetClientSize( int *width, int *height ) const
c801d85f 287{
83624f79 288 wxWindow::GetClientSize( width, height );
cf4219e7 289}
9746a2ba 290
cf4219e7 291void wxMDIChildFrame::AddChild( wxWindow *child )
716b7364 292{
83624f79 293 wxWindow::AddChild( child );
716b7364 294}
c626a8b7 295
716b7364
RR
296void wxMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar )
297{
5bd9e519
RR
298 wxASSERT_MSG( m_menuBar == NULL, _T("Only one menubar allowed") );
299
83624f79 300 m_menuBar = menu_bar;
a3622daa 301
83624f79 302 if (m_menuBar)
716b7364 303 {
f03fc89f 304 wxMDIParentFrame *mdi_frame = (wxMDIParentFrame*)m_parent->GetParent();
83624f79 305
5bd9e519 306 m_menuBar->SetParent( mdi_frame );
c626a8b7 307
ab2b3dd4 308 /* insert the invisible menu bar into the _parent_ mdi frame */
fdd3ed7a 309 gtk_myfixed_put( GTK_MYFIXED(mdi_frame->m_mainWidget),
a2053b27
RR
310 m_menuBar->m_widget,
311 0, 0, mdi_frame->m_width, wxMENU_HEIGHT );
716b7364 312 }
ff7b1510 313}
cf4219e7 314
33b64e6f 315wxMenuBar *wxMDIChildFrame::GetMenuBar() const
cf4219e7 316{
83624f79 317 return m_menuBar;
ff7b1510 318}
c801d85f 319
ab2b3dd4 320void wxMDIChildFrame::Activate()
c801d85f 321{
adde8c98
RR
322#if (GTK_MINOR_VERSION > 0)
323 wxMDIParentFrame* parent = (wxMDIParentFrame*) GetParent();
97560ce3 324 GtkNotebook* notebook = GTK_NOTEBOOK(parent->m_widget);
adde8c98
RR
325 gint pageno = gtk_notebook_page_num( notebook, m_page->child );
326 gtk_notebook_set_page( notebook, pageno );
97560ce3
RS
327#else
328 // the only way I can see to do this under gtk+ 1.0.X would
329 // be to keep track of page numbers, start at first and
330 // do "next" enough times to get to this page number - messy
331 // - J. Russell Smyth
332#endif
ff7b1510 333}
c801d85f 334
9746a2ba
RR
335void wxMDIChildFrame::OnActivate( wxActivateEvent &WXUNUSED(event) )
336{
ff7b1510 337}
9746a2ba 338
ab2b3dd4
RR
339//-----------------------------------------------------------------------------
340// "size_allocate"
341//-----------------------------------------------------------------------------
342
343static void gtk_page_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxWindow *win )
344{
acfd422a
RR
345 if (g_isIdle) wxapp_install_idle_handler();
346
a2053b27
RR
347 if ((win->m_x == alloc->x) &&
348 (win->m_y == alloc->y) &&
349 (win->m_width == alloc->width) &&
350 (win->m_height == alloc->height) &&
351 (win->m_sizeSet))
ab2b3dd4
RR
352 {
353 return;
354 }
355
356 win->SetSize( alloc->x, alloc->y, alloc->width, alloc->height );
357}
358
6ca41e57
RR
359//-----------------------------------------------------------------------------
360// InsertChild callback for wxMDIClientWindow
361//-----------------------------------------------------------------------------
362
363static void wxInsertChildInMDI( wxMDIClientWindow* parent, wxMDIChildFrame* child )
364{
83624f79
RR
365 wxString s = child->m_title;
366 if (s.IsNull()) s = _("MDI child");
6ca41e57 367
ed9b9841 368 GtkWidget *label_widget = gtk_label_new( s.mbc_str() );
83624f79 369 gtk_misc_set_alignment( GTK_MISC(label_widget), 0.0, 0.5 );
6ca41e57 370
a2053b27 371 gtk_signal_connect( GTK_OBJECT(child->m_widget), "size_allocate",
83624f79 372 GTK_SIGNAL_FUNC(gtk_page_size_callback), (gpointer)child );
c626a8b7 373
a2053b27 374 GtkNotebook *notebook = GTK_NOTEBOOK(parent->m_widget);
c626a8b7 375
a2053b27 376 gtk_notebook_append_page( notebook, child->m_widget, label_widget );
6ca41e57 377
83624f79 378 child->m_page = (GtkNotebookPage*) (g_list_last(notebook->children)->data);
a0fdacee 379
f03fc89f 380 wxMDIParentFrame *parent_frame = (wxMDIParentFrame*) parent->GetParent();
ab2b3dd4 381 parent_frame->m_justInserted = TRUE;
6ca41e57
RR
382}
383
c801d85f
KB
384//-----------------------------------------------------------------------------
385// wxMDIClientWindow
386//-----------------------------------------------------------------------------
387
388IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow,wxWindow)
389
ab2b3dd4 390wxMDIClientWindow::wxMDIClientWindow()
c801d85f 391{
ff7b1510 392}
c801d85f 393
debe6624 394wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame *parent, long style )
c801d85f 395{
83624f79 396 CreateClient( parent, style );
ff7b1510 397}
c801d85f 398
ab2b3dd4 399wxMDIClientWindow::~wxMDIClientWindow()
c801d85f 400{
ff7b1510 401}
c801d85f 402
debe6624 403bool wxMDIClientWindow::CreateClient( wxMDIParentFrame *parent, long style )
c801d85f 404{
83624f79 405 m_needParent = TRUE;
c626a8b7 406
83624f79 407 m_insertCallback = (wxInsertChildFunction)wxInsertChildInMDI;
a3622daa 408
83624f79 409 PreCreation( parent, -1, wxPoint(10,10), wxSize(100,100), style, "wxMDIClientWindow" );
c801d85f 410
83624f79 411 m_widget = gtk_notebook_new();
a3622daa 412
83624f79 413 gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget), 1 );
a3622daa 414
f03fc89f 415 m_parent->DoAddChild( this );
c626a8b7 416
83624f79 417 PostCreation();
a3622daa 418
83624f79 419 Show( TRUE );
a3622daa 420
83624f79 421 return TRUE;
ff7b1510 422}
c801d85f 423