Disable dropdown menu support in wxRibbonXmlHandler.
[wxWidgets.git] / src / xrc / xh_ribbon.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/xrc/xh_ribbon.cpp
3 // Purpose: XML resource handler for wxRibbon related classes
4 // Author: Armel Asselin
5 // Created: 2010-04-23
6 // RCS-ID: $Id$
7 // Copyright: (c) 2010 Armel Asselin
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #if wxUSE_XRC && wxUSE_RIBBON
19
20 #include "wx/xrc/xh_ribbon.h"
21
22 #include "wx/ribbon/bar.h"
23 #include "wx/ribbon/buttonbar.h"
24 #include "wx/ribbon/gallery.h"
25
26 #include "wx/scopeguard.h"
27
28 #ifndef WX_PRECOMP
29 #include "wx/menu.h"
30 #endif
31
32 // Ribbon bars can contain only pages which are usually panels but may contain
33 // any wxWindow.
34 //
35 // Panels are usually for wxRibbonControls but may as well contain any
36 // wxWindow.
37 //
38 // Galleries are wxRibbonControl and simply contain bitmaps with IDs.
39 //
40 // Button bars are wxRibbonControl and contain buttons (normal/dropdown/mixed),
41 // with id/bitmap/label/short help.
42
43 wxIMPLEMENT_DYNAMIC_CLASS(wxRibbonXmlHandler, wxXmlResourceHandler);
44
45 wxRibbonXmlHandler::wxRibbonXmlHandler()
46 : wxXmlResourceHandler(),
47 m_isInside(NULL)
48 {
49 XRC_ADD_STYLE(wxRIBBON_BAR_SHOW_PAGE_LABELS);
50 XRC_ADD_STYLE(wxRIBBON_BAR_SHOW_PAGE_ICONS);
51 XRC_ADD_STYLE(wxRIBBON_BAR_FLOW_HORIZONTAL);
52 XRC_ADD_STYLE(wxRIBBON_BAR_FLOW_VERTICAL);
53 XRC_ADD_STYLE(wxRIBBON_BAR_SHOW_PANEL_EXT_BUTTONS);
54 XRC_ADD_STYLE(wxRIBBON_BAR_SHOW_PANEL_MINIMISE_BUTTONS);
55 XRC_ADD_STYLE(wxRIBBON_BAR_ALWAYS_SHOW_TABS);
56 XRC_ADD_STYLE(wxRIBBON_BAR_DEFAULT_STYLE);
57 XRC_ADD_STYLE(wxRIBBON_BAR_FOLDBAR_STYLE);
58 }
59
60 wxObject *wxRibbonXmlHandler::DoCreateResource()
61 {
62 if (m_class == wxT("button"))
63 return Handle_button();
64 if (m_class == wxT("wxRibbonButtonBar"))
65 return Handle_buttonbar();
66 else if (m_class == wxT("item"))
67 return Handle_galleryitem();
68 else if (m_class == wxT("wxRibbonGallery"))
69 return Handle_gallery();
70 else if (m_class == wxT("wxRibbonPanel") || m_class == wxT("panel"))
71 return Handle_panel();
72 else if (m_class == wxT("wxRibbonPage") || m_class == wxT("page"))
73 return Handle_page();
74 else if (m_class == wxT("wxRibbonBar"))
75 return Handle_bar();
76 else
77 return Handle_control ();
78 }
79
80 bool wxRibbonXmlHandler::CanHandle(wxXmlNode *node)
81 {
82 return IsRibbonControl(node) ||
83 (m_isInside == &wxRibbonButtonBar::ms_classInfo &&
84 IsOfClass(node, wxT("button"))) ||
85 (m_isInside == &wxRibbonBar::ms_classInfo &&
86 IsOfClass(node, wxT("page"))) ||
87 (m_isInside == &wxRibbonPage::ms_classInfo &&
88 IsOfClass(node, wxT("panel"))) ||
89 (m_isInside == &wxRibbonGallery::ms_classInfo &&
90 IsOfClass(node, wxT("item")));
91 }
92
93 bool wxRibbonXmlHandler::IsRibbonControl (wxXmlNode *node)
94 {
95 return IsOfClass(node, wxT("wxRibbonBar")) ||
96 IsOfClass(node, wxT("wxRibbonButtonBar")) ||
97 IsOfClass(node, wxT("wxRibbonPage")) ||
98 IsOfClass(node, wxT("wxRibbonPanel")) ||
99 IsOfClass(node, wxT("wxRibbonGallery")) ||
100 IsOfClass(node, wxT("wxRibbonControl"));
101 }
102
103 void wxRibbonXmlHandler::Handle_RibbonArtProvider(wxRibbonControl *control)
104 {
105 wxString provider = GetText("art-provider", false);
106
107 if (provider == "default" || provider.IsEmpty())
108 control->SetArtProvider(new wxRibbonDefaultArtProvider);
109 else if (provider.CmpNoCase("aui") == 0)
110 control->SetArtProvider(new wxRibbonAUIArtProvider);
111 else if (provider.CmpNoCase("msw") == 0)
112 control->SetArtProvider(new wxRibbonMSWArtProvider);
113 else
114 ReportError("invalid ribbon art provider");
115 }
116
117 wxObject* wxRibbonXmlHandler::Handle_buttonbar()
118 {
119 XRC_MAKE_INSTANCE (buttonBar, wxRibbonButtonBar);
120
121 if (!buttonBar->Create (wxDynamicCast(m_parent, wxWindow), GetID(),
122 GetPosition(), GetSize(), GetStyle()))
123 {
124 ReportError("could not create ribbon panel");
125 }
126 else
127 {
128 const wxClassInfo* const wasInside = m_isInside;
129 wxON_BLOCK_EXIT_SET(m_isInside, wasInside);
130 m_isInside = &wxRibbonButtonBar::ms_classInfo;
131
132 CreateChildren (buttonBar, true);
133
134 buttonBar->Realize();
135 }
136
137 return buttonBar;
138 }
139
140 wxObject* wxRibbonXmlHandler::Handle_button()
141 {
142 wxRibbonButtonBar *buttonBar = wxStaticCast(m_parent, wxRibbonButtonBar);
143
144 wxRibbonButtonKind kind = wxRIBBON_BUTTON_NORMAL;
145
146 if (GetBool(wxT("hybrid")))
147 kind = wxRIBBON_BUTTON_HYBRID;
148
149 // FIXME: The code below uses wxXmlNode directly but this can't be done
150 // in the ribbon library code as it would force it to always link
151 // with the xml library. Disable it for now but the real solution
152 // would be to virtualize GetChildren() and GetNext() methods via
153 // wxXmlResourceHandler, just as we already do for many others.
154 #if 0 // wxUSE_MENUS
155 // check whether we have dropdown tag inside
156 wxMenu *menu = NULL; // menu for drop down items
157 wxXmlNode * const nodeDropdown = GetParamNode("dropdown");
158 if ( nodeDropdown )
159 {
160 if (kind == wxRIBBON_BUTTON_NORMAL)
161 kind = wxRIBBON_BUTTON_DROPDOWN;
162
163 // also check for the menu specified inside dropdown (it is
164 // optional and may be absent for e.g. dynamically-created
165 // menus)
166 wxXmlNode * const nodeMenu = nodeDropdown->GetChildren();
167 if ( nodeMenu )
168 {
169 wxObject *res = CreateResFromNode(nodeMenu, NULL);
170 menu = wxDynamicCast(res, wxMenu);
171 if ( !menu )
172 {
173 ReportError
174 (
175 nodeMenu,
176 "drop-down tool contents can only be a wxMenu"
177 );
178 }
179
180 if ( nodeMenu->GetNext() )
181 {
182 ReportError
183 (
184 nodeMenu->GetNext(),
185 "unexpected extra contents under drop-down tool"
186 );
187 }
188 }
189 }
190 #endif // wxUSE_MENUS
191
192 if (!buttonBar->AddButton(GetID(),
193 GetText("label"),
194 GetBitmap ("bitmap"),
195 GetBitmap ("small-bitmap"),
196 GetBitmap ("disabled-bitmap"),
197 GetBitmap ("small-disabled-bitmap"),
198 kind,
199 GetText("help")))
200 {
201 ReportError ("could not create button");
202 }
203
204 if ( GetBool(wxT("disabled")) )
205 buttonBar->EnableButton(GetID(), false);
206
207 return NULL; // nothing to return
208 }
209
210 wxObject* wxRibbonXmlHandler::Handle_control()
211 {
212 wxRibbonControl *control = wxDynamicCast (m_instance, wxRibbonControl);
213
214 if (!m_instance)
215 ReportError("wxRibbonControl must be subclassed");
216 else if (!control)
217 ReportError("controls must derive from wxRibbonControl");
218
219 control->Create(wxDynamicCast(m_parent, wxWindow), GetID(),
220 GetPosition(), GetSize(), GetStyle());
221
222 return m_instance;
223 }
224
225 wxObject* wxRibbonXmlHandler::Handle_page()
226 {
227 XRC_MAKE_INSTANCE (ribbonPage, wxRibbonPage);
228
229 if (!ribbonPage->Create (wxDynamicCast(m_parent, wxRibbonBar), GetID(),
230 GetText ("label"), GetBitmap ("icon"), GetStyle()))
231 {
232 ReportError("could not create ribbon page");
233 }
234 else
235 {
236 const wxClassInfo* const wasInside = m_isInside;
237 wxON_BLOCK_EXIT_SET(m_isInside, wasInside);
238 m_isInside = &wxRibbonPage::ms_classInfo;
239
240 CreateChildren (ribbonPage);
241
242 ribbonPage->Realize();
243 }
244
245 return ribbonPage;
246 }
247
248 wxObject* wxRibbonXmlHandler::Handle_gallery()
249 {
250 XRC_MAKE_INSTANCE (ribbonGallery, wxRibbonGallery);
251
252 if (!ribbonGallery->Create (wxDynamicCast(m_parent, wxWindow), GetID(),
253 GetPosition(), GetSize(), GetStyle()))
254 {
255 ReportError("could not create ribbon gallery");
256 }
257 else
258 {
259 const wxClassInfo* const wasInside = m_isInside;
260 wxON_BLOCK_EXIT_SET(m_isInside, wasInside);
261 m_isInside = &wxRibbonGallery::ms_classInfo;
262
263 CreateChildren (ribbonGallery);
264
265 ribbonGallery->Realize();
266 }
267
268 return ribbonGallery;
269 }
270
271 wxObject* wxRibbonXmlHandler::Handle_galleryitem()
272 {
273 wxRibbonGallery *gallery = wxStaticCast(m_parent, wxRibbonGallery);
274 wxCHECK (gallery, NULL);
275
276 gallery->Append (GetBitmap(), GetID());
277
278 return NULL; // nothing to return
279 }
280
281 wxObject* wxRibbonXmlHandler::Handle_panel()
282 {
283 XRC_MAKE_INSTANCE (ribbonPanel, wxRibbonPanel);
284
285 if (!ribbonPanel->Create (wxDynamicCast(m_parent, wxWindow), GetID(),
286 GetText ("label"), GetBitmap ("icon"), GetPosition(), GetSize(),
287 GetStyle("style", wxRIBBON_PANEL_DEFAULT_STYLE)))
288 {
289 ReportError("could not create ribbon panel");
290 }
291 else
292 {
293 CreateChildren (ribbonPanel);
294
295 ribbonPanel->Realize();
296 }
297
298 return ribbonPanel;
299 }
300
301 wxObject* wxRibbonXmlHandler::Handle_bar()
302 {
303 XRC_MAKE_INSTANCE (ribbonBar, wxRibbonBar);
304
305 Handle_RibbonArtProvider (ribbonBar);
306
307 if ( !ribbonBar->Create(wxDynamicCast(m_parent, wxWindow),
308 GetID(),
309 GetPosition(),
310 GetSize(),
311 GetStyle("style", wxRIBBON_BAR_DEFAULT_STYLE)) )
312 {
313 ReportError ("could not create ribbonbar");
314 }
315 else
316 {
317 // Currently the art provider style must be explicitly set to the
318 // ribbon style too.
319 ribbonBar->GetArtProvider()
320 ->SetFlags(GetStyle("style", wxRIBBON_BAR_DEFAULT_STYLE));
321
322 const wxClassInfo* const wasInside = m_isInside;
323 wxON_BLOCK_EXIT_SET(m_isInside, wasInside);
324 m_isInside = &wxRibbonBar::ms_classInfo;
325
326 CreateChildren (ribbonBar, true);
327
328 ribbonBar->Realize();
329 }
330
331 return ribbonBar;
332 }
333
334 #endif // wxUSE_XRC && wxUSE_RIBBON