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