Fix for PCH-less compilation of 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 #if wxUSE_MENUS
150 // check whether we have dropdown tag inside
151 wxMenu *menu = NULL; // menu for drop down items
152 wxXmlNode * const nodeDropdown = GetParamNode("dropdown");
153 if ( nodeDropdown )
154 {
155 if (kind == wxRIBBON_BUTTON_NORMAL)
156 kind = wxRIBBON_BUTTON_DROPDOWN;
157
158 // also check for the menu specified inside dropdown (it is
159 // optional and may be absent for e.g. dynamically-created
160 // menus)
161 wxXmlNode * const nodeMenu = nodeDropdown->GetChildren();
162 if ( nodeMenu )
163 {
164 wxObject *res = CreateResFromNode(nodeMenu, NULL);
165 menu = wxDynamicCast(res, wxMenu);
166 if ( !menu )
167 {
168 ReportError
169 (
170 nodeMenu,
171 "drop-down tool contents can only be a wxMenu"
172 );
173 }
174
175 if ( nodeMenu->GetNext() )
176 {
177 ReportError
178 (
179 nodeMenu->GetNext(),
180 "unexpected extra contents under drop-down tool"
181 );
182 }
183 }
184 }
185 #endif // wxUSE_MENUS
186
187 if (!buttonBar->AddButton(GetID(),
188 GetText("label"),
189 GetBitmap ("bitmap"),
190 GetBitmap ("small-bitmap"),
191 GetBitmap ("disabled-bitmap"),
192 GetBitmap ("small-disabled-bitmap"),
193 kind,
194 GetText("help")))
195 {
196 ReportError ("could not create button");
197 }
198
199 if ( GetBool(wxT("disabled")) )
200 buttonBar->EnableButton(GetID(), false);
201
202 return NULL; // nothing to return
203 }
204
205 wxObject* wxRibbonXmlHandler::Handle_control()
206 {
207 wxRibbonControl *control = wxDynamicCast (m_instance, wxRibbonControl);
208
209 if (!m_instance)
210 ReportError("wxRibbonControl must be subclassed");
211 else if (!control)
212 ReportError("controls must derive from wxRibbonControl");
213
214 control->Create(wxDynamicCast(m_parent, wxWindow), GetID(),
215 GetPosition(), GetSize(), GetStyle());
216
217 return m_instance;
218 }
219
220 wxObject* wxRibbonXmlHandler::Handle_page()
221 {
222 XRC_MAKE_INSTANCE (ribbonPage, wxRibbonPage);
223
224 if (!ribbonPage->Create (wxDynamicCast(m_parent, wxRibbonBar), GetID(),
225 GetText ("label"), GetBitmap ("icon"), GetStyle()))
226 {
227 ReportError("could not create ribbon page");
228 }
229 else
230 {
231 const wxClassInfo* const wasInside = m_isInside;
232 wxON_BLOCK_EXIT_SET(m_isInside, wasInside);
233 m_isInside = &wxRibbonPage::ms_classInfo;
234
235 CreateChildren (ribbonPage);
236
237 ribbonPage->Realize();
238 }
239
240 return ribbonPage;
241 }
242
243 wxObject* wxRibbonXmlHandler::Handle_gallery()
244 {
245 XRC_MAKE_INSTANCE (ribbonGallery, wxRibbonGallery);
246
247 if (!ribbonGallery->Create (wxDynamicCast(m_parent, wxWindow), GetID(),
248 GetPosition(), GetSize(), GetStyle()))
249 {
250 ReportError("could not create ribbon gallery");
251 }
252 else
253 {
254 const wxClassInfo* const wasInside = m_isInside;
255 wxON_BLOCK_EXIT_SET(m_isInside, wasInside);
256 m_isInside = &wxRibbonGallery::ms_classInfo;
257
258 CreateChildren (ribbonGallery);
259
260 ribbonGallery->Realize();
261 }
262
263 return ribbonGallery;
264 }
265
266 wxObject* wxRibbonXmlHandler::Handle_galleryitem()
267 {
268 wxRibbonGallery *gallery = wxStaticCast(m_parent, wxRibbonGallery);
269 wxCHECK (gallery, NULL);
270
271 gallery->Append (GetBitmap(), GetID());
272
273 return NULL; // nothing to return
274 }
275
276 wxObject* wxRibbonXmlHandler::Handle_panel()
277 {
278 XRC_MAKE_INSTANCE (ribbonPanel, wxRibbonPanel);
279
280 if (!ribbonPanel->Create (wxDynamicCast(m_parent, wxWindow), GetID(),
281 GetText ("label"), GetBitmap ("icon"), GetPosition(), GetSize(),
282 GetStyle("style", wxRIBBON_PANEL_DEFAULT_STYLE)))
283 {
284 ReportError("could not create ribbon panel");
285 }
286 else
287 {
288 CreateChildren (ribbonPanel);
289
290 ribbonPanel->Realize();
291 }
292
293 return ribbonPanel;
294 }
295
296 wxObject* wxRibbonXmlHandler::Handle_bar()
297 {
298 XRC_MAKE_INSTANCE (ribbonBar, wxRibbonBar);
299
300 Handle_RibbonArtProvider (ribbonBar);
301
302 if ( !ribbonBar->Create(wxDynamicCast(m_parent, wxWindow),
303 GetID(),
304 GetPosition(),
305 GetSize(),
306 GetStyle("style", wxRIBBON_BAR_DEFAULT_STYLE)) )
307 {
308 ReportError ("could not create ribbonbar");
309 }
310 else
311 {
312 // Currently the art provider style must be explicitly set to the
313 // ribbon style too.
314 ribbonBar->GetArtProvider()
315 ->SetFlags(GetStyle("style", wxRIBBON_BAR_DEFAULT_STYLE));
316
317 const wxClassInfo* const wasInside = m_isInside;
318 wxON_BLOCK_EXIT_SET(m_isInside, wasInside);
319 m_isInside = &wxRibbonBar::ms_classInfo;
320
321 CreateChildren (ribbonBar, true);
322
323 ribbonBar->Realize();
324 }
325
326 return ribbonBar;
327 }
328
329 #endif // wxUSE_XRC && wxUSE_RIBBON