1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/mdi.h
3 // Purpose: wxMDI base header
4 // Author: Julian Smart (original)
5 // Vadim Zeitlin (base MDI classes refactoring)
6 // Copyright: (c) 1998 Julian Smart
7 // (c) 2008 Vadim Zeitlin
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #ifndef _WX_MDI_H_BASE_
12 #define _WX_MDI_H_BASE_
13
14 #include "wx/defs.h"
15
16 #if wxUSE_MDI
17
18 #include "wx/frame.h"
19 #include "wx/menu.h"
20
21 // forward declarations
22 class WXDLLIMPEXP_FWD_CORE wxMDIParentFrame;
23 class WXDLLIMPEXP_FWD_CORE wxMDIChildFrame;
24 class WXDLLIMPEXP_FWD_CORE wxMDIClientWindowBase;
25 class WXDLLIMPEXP_FWD_CORE wxMDIClientWindow;
26
27 // ----------------------------------------------------------------------------
28 // wxMDIParentFrameBase: base class for parent frame for MDI children
29 // ----------------------------------------------------------------------------
30
31 class WXDLLIMPEXP_CORE wxMDIParentFrameBase : public wxFrame
32 {
33 public:
wxMDIParentFrameBase()34 wxMDIParentFrameBase()
35 {
36 m_clientWindow = NULL;
37 m_currentChild = NULL;
38 #if wxUSE_MENUS
39 m_windowMenu = NULL;
40 #endif // wxUSE_MENUS
41 }
42
43 /*
44 Derived classes should provide ctor and Create() with the following
45 declaration:
46
47 bool Create(wxWindow *parent,
48 wxWindowID winid,
49 const wxString& title,
50 const wxPoint& pos = wxDefaultPosition,
51 const wxSize& size = wxDefaultSize,
52 long style = wxDEFAULT_FRAME_STYLE | wxVSCROLL | wxHSCROLL,
53 const wxString& name = wxFrameNameStr);
54 */
55
56 #if wxUSE_MENUS
~wxMDIParentFrameBase()57 virtual ~wxMDIParentFrameBase()
58 {
59 delete m_windowMenu;
60 }
61 #endif // wxUSE_MENUS
62
63 // accessors
64 // ---------
65
66 // Get or change the active MDI child window
GetActiveChild()67 virtual wxMDIChildFrame *GetActiveChild() const
68 { return m_currentChild; }
SetActiveChild(wxMDIChildFrame * child)69 virtual void SetActiveChild(wxMDIChildFrame *child)
70 { m_currentChild = child; }
71
72
73 // Get the client window
GetClientWindow()74 wxMDIClientWindowBase *GetClientWindow() const { return m_clientWindow; }
75
76
77 // MDI windows menu functions
78 // --------------------------
79
80 #if wxUSE_MENUS
81 // return the pointer to the current window menu or NULL if we don't have
82 // because of wxFRAME_NO_WINDOW_MENU style
GetWindowMenu()83 wxMenu* GetWindowMenu() const { return m_windowMenu; }
84
85 // use the given menu instead of the default window menu
86 //
87 // menu can be NULL to disable the window menu completely
SetWindowMenu(wxMenu * menu)88 virtual void SetWindowMenu(wxMenu *menu)
89 {
90 if ( menu != m_windowMenu )
91 {
92 delete m_windowMenu;
93 m_windowMenu = menu;
94 }
95 }
96 #endif // wxUSE_MENUS
97
98
99 // standard MDI window management functions
100 // ----------------------------------------
101
Cascade()102 virtual void Cascade() { }
103 virtual void Tile(wxOrientation WXUNUSED(orient) = wxHORIZONTAL) { }
ArrangeIcons()104 virtual void ArrangeIcons() { }
105 virtual void ActivateNext() = 0;
106 virtual void ActivatePrevious() = 0;
107
108 /*
109 Derived classes must provide the following function:
110
111 static bool IsTDI();
112 */
113
114 // Create the client window class (don't Create() the window here, just
115 // return a new object of a wxMDIClientWindow-derived class)
116 //
117 // Notice that if you override this method you should use the default
118 // constructor and Create() and not the constructor creating the window
119 // when creating the frame or your overridden version is not going to be
120 // called (as the call to a virtual function from ctor will be dispatched
121 // to this class version)
122 virtual wxMDIClientWindow *OnCreateClient();
123
124 protected:
125 // Override to pass menu/toolbar events to the active child first.
126 virtual bool TryBefore(wxEvent& event);
127
128
129 // This is wxMDIClientWindow for all the native implementations but not for
130 // the generic MDI version which has its own wxGenericMDIClientWindow and
131 // so we store it as just a base class pointer because we don't need its
132 // exact type anyhow
133 wxMDIClientWindowBase *m_clientWindow;
134 wxMDIChildFrame *m_currentChild;
135
136 #if wxUSE_MENUS
137 // the current window menu or NULL if we are not using it
138 wxMenu *m_windowMenu;
139 #endif // wxUSE_MENUS
140 };
141
142 // ----------------------------------------------------------------------------
143 // wxMDIChildFrameBase: child frame managed by wxMDIParentFrame
144 // ----------------------------------------------------------------------------
145
146 class WXDLLIMPEXP_CORE wxMDIChildFrameBase : public wxFrame
147 {
148 public:
wxMDIChildFrameBase()149 wxMDIChildFrameBase() { m_mdiParent = NULL; }
150
151 /*
152 Derived classes should provide Create() with the following signature:
153
154 bool Create(wxMDIParentFrame *parent,
155 wxWindowID id,
156 const wxString& title,
157 const wxPoint& pos = wxDefaultPosition,
158 const wxSize& size = wxDefaultSize,
159 long style = wxDEFAULT_FRAME_STYLE,
160 const wxString& name = wxFrameNameStr);
161
162 And setting m_mdiParent to parent parameter.
163 */
164
165 // MDI children specific methods
166 virtual void Activate() = 0;
167
168 // Return the MDI parent frame: notice that it may not be the same as
169 // GetParent() (our parent may be the client window or even its subwindow
170 // in some implementations)
GetMDIParent()171 wxMDIParentFrame *GetMDIParent() const { return m_mdiParent; }
172
173 // Synonym for GetMDIParent(), was used in some other ports
GetMDIParentFrame()174 wxMDIParentFrame *GetMDIParentFrame() const { return GetMDIParent(); }
175
176
177 // in most ports MDI children frames are not really top-level, the only
178 // exception are the Mac ports in which MDI children are just normal top
179 // level windows too
IsTopLevel()180 virtual bool IsTopLevel() const { return false; }
181
182 // In all ports keyboard navigation must stop at MDI child frame level and
183 // can't cross its boundary. Indicate this by overriding this function to
184 // return true.
IsTopNavigationDomain()185 virtual bool IsTopNavigationDomain() const { return true; }
186
187 // Raising any frame is supposed to show it but wxFrame Raise()
188 // implementation doesn't work for MDI child frames in most forms so
189 // forward this to Activate() which serves the same purpose by default.
Raise()190 virtual void Raise() { Activate(); }
191
192 protected:
193 wxMDIParentFrame *m_mdiParent;
194 };
195
196 // ----------------------------------------------------------------------------
197 // wxTDIChildFrame: child frame used by TDI implementations
198 // ----------------------------------------------------------------------------
199
200 class WXDLLIMPEXP_CORE wxTDIChildFrame : public wxMDIChildFrameBase
201 {
202 public:
203 // override wxFrame methods for this non top-level window
204
205 #if wxUSE_STATUSBAR
206 // no status bars
207 //
208 // TODO: MDI children should have their own status bars, why not?
WXUNUSED(number)209 virtual wxStatusBar* CreateStatusBar(int WXUNUSED(number) = 1,
210 long WXUNUSED(style) = 1,
211 wxWindowID WXUNUSED(id) = 1,
212 const wxString& WXUNUSED(name)
213 = wxEmptyString)
214 { return NULL; }
215
GetStatusBar()216 virtual wxStatusBar *GetStatusBar() const
217 { return NULL; }
218 virtual void SetStatusText(const wxString &WXUNUSED(text),
219 int WXUNUSED(number)=0)
220 { }
SetStatusWidths(int WXUNUSED (n),const int WXUNUSED (widths)[])221 virtual void SetStatusWidths(int WXUNUSED(n),
222 const int WXUNUSED(widths)[])
223 { }
224 #endif // wxUSE_STATUSBAR
225
226 #if wxUSE_TOOLBAR
227 // no toolbar
228 //
229 // TODO: again, it should be possible to have tool bars
CreateToolBar(long WXUNUSED (style),wxWindowID WXUNUSED (id),const wxString & WXUNUSED (name))230 virtual wxToolBar *CreateToolBar(long WXUNUSED(style),
231 wxWindowID WXUNUSED(id),
232 const wxString& WXUNUSED(name))
233 { return NULL; }
GetToolBar()234 virtual wxToolBar *GetToolBar() const { return NULL; }
235 #endif // wxUSE_TOOLBAR
236
237 // no icon
SetIcons(const wxIconBundle & WXUNUSED (icons))238 virtual void SetIcons(const wxIconBundle& WXUNUSED(icons)) { }
239
240 // title is used as the tab label
GetTitle()241 virtual wxString GetTitle() const { return m_title; }
242 virtual void SetTitle(const wxString& title) = 0;
243
244 // no maximize etc
WXUNUSED(maximize)245 virtual void Maximize(bool WXUNUSED(maximize) = true) { }
IsMaximized()246 virtual bool IsMaximized() const { return true; }
IsAlwaysMaximized()247 virtual bool IsAlwaysMaximized() const { return true; }
WXUNUSED(iconize)248 virtual void Iconize(bool WXUNUSED(iconize) = true) { }
IsIconized()249 virtual bool IsIconized() const { return false; }
Restore()250 virtual void Restore() { }
251
ShowFullScreen(bool WXUNUSED (show),long WXUNUSED (style))252 virtual bool ShowFullScreen(bool WXUNUSED(show),
253 long WXUNUSED(style)) { return false; }
IsFullScreen()254 virtual bool IsFullScreen() const { return false; }
255
256
257 // we need to override these functions to ensure that a child window is
258 // created even though we derive from wxFrame -- basically we make it
259 // behave as just a wxWindow by short-circuiting wxTLW changes to the base
260 // class behaviour
261
AddChild(wxWindowBase * child)262 virtual void AddChild(wxWindowBase *child) { wxWindow::AddChild(child); }
263
Destroy()264 virtual bool Destroy() { return wxWindow::Destroy(); }
265
266 // extra platform-specific hacks
267 #ifdef __WXMSW__
268 virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle = NULL) const
269 {
270 return wxWindow::MSWGetStyle(flags, exstyle);
271 }
272
MSWGetParent()273 virtual WXHWND MSWGetParent() const
274 {
275 return wxWindow::MSWGetParent();
276 }
277
MSWWindowProc(WXUINT message,WXWPARAM wParam,WXLPARAM lParam)278 WXLRESULT MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
279 {
280 return wxWindow::MSWWindowProc(message, wParam, lParam);
281 }
282 #endif // __WXMSW__
283
284 protected:
DoGetSize(int * width,int * height)285 virtual void DoGetSize(int *width, int *height) const
286 {
287 wxWindow::DoGetSize(width, height);
288 }
289
DoSetSize(int x,int y,int width,int height,int sizeFlags)290 virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags)
291 {
292 wxWindow::DoSetSize(x, y, width, height, sizeFlags);
293 }
294
DoGetClientSize(int * width,int * height)295 virtual void DoGetClientSize(int *width, int *height) const
296 {
297 wxWindow::DoGetClientSize(width, height);
298 }
299
DoSetClientSize(int width,int height)300 virtual void DoSetClientSize(int width, int height)
301 {
302 wxWindow::DoSetClientSize(width, height);
303 }
304
DoMoveWindow(int x,int y,int width,int height)305 virtual void DoMoveWindow(int x, int y, int width, int height)
306 {
307 wxWindow::DoMoveWindow(x, y, width, height);
308 }
309
310 // no size hints
DoSetSizeHints(int WXUNUSED (minW),int WXUNUSED (minH),int WXUNUSED (maxW),int WXUNUSED (maxH),int WXUNUSED (incW),int WXUNUSED (incH))311 virtual void DoSetSizeHints(int WXUNUSED(minW), int WXUNUSED(minH),
312 int WXUNUSED(maxW), int WXUNUSED(maxH),
313 int WXUNUSED(incW), int WXUNUSED(incH)) { }
314
315 wxString m_title;
316 };
317
318 // ----------------------------------------------------------------------------
319 // wxMDIClientWindowBase: child of parent frame, parent of children frames
320 // ----------------------------------------------------------------------------
321
322 class WXDLLIMPEXP_CORE wxMDIClientWindowBase : public wxWindow
323 {
324 public:
325 /*
326 The derived class must provide the default ctor only (CreateClient()
327 will be called later).
328 */
329
330 // Can be overridden in the derived classes but the base class version must
331 // be usually called first to really create the client window.
332 virtual bool CreateClient(wxMDIParentFrame *parent,
333 long style = wxVSCROLL | wxHSCROLL) = 0;
334 };
335
336 // ----------------------------------------------------------------------------
337 // Include the port-specific implementation of the base classes defined above
338 // ----------------------------------------------------------------------------
339
340 // wxUSE_GENERIC_MDI_AS_NATIVE may be predefined to force the generic MDI
341 // implementation use even on the platforms which usually don't use it
342 //
343 // notice that generic MDI can still be used without this, but you would need
344 // to explicitly use wxGenericMDIXXX classes in your code (and currently also
345 // add src/generic/mdig.cpp to your build as it's not compiled in if generic
346 // MDI is not used by default -- but this may change later...)
347 #ifndef wxUSE_GENERIC_MDI_AS_NATIVE
348 // wxUniv always uses the generic MDI implementation and so do the ports
349 // without native version (although wxCocoa seems to have one -- but it's
350 // probably not functional?)
351 #if defined(__WXCOCOA__) || \
352 defined(__WXMOTIF__) || \
353 defined(__WXPM__) || \
354 defined(__WXUNIVERSAL__)
355 #define wxUSE_GENERIC_MDI_AS_NATIVE 1
356 #else
357 #define wxUSE_GENERIC_MDI_AS_NATIVE 0
358 #endif
359 #endif // wxUSE_GENERIC_MDI_AS_NATIVE
360
361 #if wxUSE_GENERIC_MDI_AS_NATIVE
362 #include "wx/generic/mdig.h"
363 #elif defined(__WXMSW__)
364 #include "wx/msw/mdi.h"
365 #elif defined(__WXGTK20__)
366 #include "wx/gtk/mdi.h"
367 #elif defined(__WXGTK__)
368 #include "wx/gtk1/mdi.h"
369 #elif defined(__WXMAC__)
370 #include "wx/osx/mdi.h"
371 #elif defined(__WXCOCOA__)
372 #include "wx/cocoa/mdi.h"
373 #endif
374
OnCreateClient()375 inline wxMDIClientWindow *wxMDIParentFrameBase::OnCreateClient()
376 {
377 return new wxMDIClientWindow;
378 }
379
TryBefore(wxEvent & event)380 inline bool wxMDIParentFrameBase::TryBefore(wxEvent& event)
381 {
382 // Menu (and toolbar) events should be sent to the active child frame
383 // first, if any.
384 if ( event.GetEventType() == wxEVT_MENU ||
385 event.GetEventType() == wxEVT_UPDATE_UI )
386 {
387 wxMDIChildFrame * const child = GetActiveChild();
388 if ( child )
389 {
390 // However avoid sending the event back to the child if it's
391 // currently being propagated to us from it.
392 wxWindow* const
393 from = static_cast<wxWindow*>(event.GetPropagatedFrom());
394 if ( !from || !from->IsDescendant(child) )
395 {
396 if ( child->ProcessWindowEventLocally(event) )
397 return true;
398 }
399 }
400 }
401
402 return wxFrame::TryBefore(event);
403 }
404
405 #endif // wxUSE_MDI
406
407 #endif // _WX_MDI_H_BASE_
408