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