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