Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <stdio.h>
21 : #include <sal/macros.h>
22 :
23 : #include <xml/menudocumenthandler.hxx>
24 : #include <framework/menuconfiguration.hxx>
25 : #include <framework/addonmenu.hxx>
26 :
27 : #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
28 : #include <com/sun/star/lang/XSingleComponentFactory.hpp>
29 : #include <com/sun/star/ui/ItemType.hpp>
30 : #include <com/sun/star/ui/ItemStyle.hpp>
31 : #include <com/sun/star/beans/PropertyValue.hpp>
32 :
33 : #include <comphelper/processfactory.hxx>
34 : #include <comphelper/attributelist.hxx>
35 :
36 : #define XMLNS_MENU "http://openoffice.org/2001/menu"
37 :
38 : #define ELEMENT_MENUBAR "http://openoffice.org/2001/menu^menubar"
39 : #define ELEMENT_MENU "http://openoffice.org/2001/menu^menu"
40 : #define ELEMENT_MENUPOPUP "http://openoffice.org/2001/menu^menupopup"
41 : #define ELEMENT_MENUITEM "http://openoffice.org/2001/menu^menuitem"
42 : #define ELEMENT_MENUSEPARATOR "http://openoffice.org/2001/menu^menuseparator"
43 :
44 : #define ELEMENT_NS_MENUBAR "menu:menubar"
45 : #define ELEMENT_NS_MENU "menu:menu"
46 : #define ELEMENT_NS_MENUPOPUP "menu:menupopup"
47 : #define ELEMENT_NS_MENUITEM "menu:menuitem"
48 : #define ELEMENT_NS_MENUSEPARATOR "menu:menuseparator"
49 :
50 : #define ATTRIBUTE_ID "http://openoffice.org/2001/menu^id"
51 : #define ATTRIBUTE_LABEL "http://openoffice.org/2001/menu^label"
52 : #define ATTRIBUTE_HELPID "http://openoffice.org/2001/menu^helpid"
53 : #define ATTRIBUTE_STYLE "http://openoffice.org/2001/menu^style"
54 :
55 : #define ATTRIBUTE_NS_ID "menu:id"
56 : #define ATTRIBUTE_NS_LABEL "menu:label"
57 : #define ATTRIBUTE_NS_HELPID "menu:helpid"
58 : #define ATTRIBUTE_NS_STYLE "menu:style"
59 :
60 : #define ATTRIBUTE_XMLNS_MENU "xmlns:menu"
61 :
62 : #define ATTRIBUTE_TYPE_CDATA "CDATA"
63 :
64 : #define MENUBAR_DOCTYPE "<!DOCTYPE menu:menubar PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"menubar.dtd\">"
65 :
66 : #define ATTRIBUTE_ITEMSTYLE_TEXT "text"
67 : #define ATTRIBUTE_ITEMSTYLE_IMAGE "image"
68 : #define ATTRIBUTE_ITEMSTYLE_RADIO "radio"
69 :
70 : // Property names of a menu/menu item ItemDescriptor
71 : static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL";
72 : static const char ITEM_DESCRIPTOR_HELPURL[] = "HelpURL";
73 : static const char ITEM_DESCRIPTOR_CONTAINER[] = "ItemDescriptorContainer";
74 : static const char ITEM_DESCRIPTOR_LABEL[] = "Label";
75 : static const char ITEM_DESCRIPTOR_TYPE[] = "Type";
76 : static const char ITEM_DESCRIPTOR_STYLE[] = "Style";
77 :
78 : // special popup menus (filled during runtime) must be saved as an empty popup menu or menuitem!!!
79 : static const sal_Int32 CMD_PROTOCOL_SIZE = 5;
80 : static const char CMD_PROTOCOL[] = ".uno:";
81 : static const char ADDDIRECT_CMD[] = ".uno:AddDirect";
82 : static const char AUTOPILOTMENU_CMD[] = ".uno:AutoPilotMenu";
83 :
84 : // using namespaces
85 :
86 : using namespace ::com::sun::star::uno;
87 : using namespace ::com::sun::star::lang;
88 : using namespace ::com::sun::star::beans;
89 : using namespace ::com::sun::star::xml::sax;
90 : using namespace ::com::sun::star::container;
91 : using namespace ::com::sun::star::ui;
92 :
93 : namespace framework
94 : {
95 :
96 : struct MenuStyleItem
97 : {
98 : sal_Int16 nBit;
99 : const char* attrName;
100 : };
101 :
102 : MenuStyleItem MenuItemStyles[ ] = {
103 : { ::com::sun::star::ui::ItemStyle::ICON, ATTRIBUTE_ITEMSTYLE_IMAGE },
104 : { ::com::sun::star::ui::ItemStyle::TEXT, ATTRIBUTE_ITEMSTYLE_TEXT },
105 : { ::com::sun::star::ui::ItemStyle::RADIO_CHECK, ATTRIBUTE_ITEMSTYLE_RADIO }
106 : };
107 :
108 : sal_Int32 nMenuStyleItemEntries = (sizeof (MenuItemStyles) / sizeof (MenuItemStyles[0]));
109 :
110 0 : static void ExtractMenuParameters( const Sequence< PropertyValue >& rProp,
111 : OUString& rCommandURL,
112 : OUString& rLabel,
113 : OUString& rHelpURL,
114 : Reference< XIndexAccess >& rSubMenu,
115 : sal_Int16& rType,
116 : sal_Int16& rStyle )
117 : {
118 0 : for ( sal_Int32 i = 0; i < rProp.getLength(); i++ )
119 : {
120 0 : if ( rProp[i].Name == ITEM_DESCRIPTOR_COMMANDURL )
121 : {
122 0 : rProp[i].Value >>= rCommandURL;
123 0 : rCommandURL = rCommandURL.intern();
124 : }
125 0 : else if ( rProp[i].Name == ITEM_DESCRIPTOR_HELPURL )
126 : {
127 0 : rProp[i].Value >>= rHelpURL;
128 : }
129 0 : else if ( rProp[i].Name == ITEM_DESCRIPTOR_CONTAINER )
130 : {
131 0 : rProp[i].Value >>= rSubMenu;
132 : }
133 0 : else if ( rProp[i].Name == ITEM_DESCRIPTOR_LABEL )
134 : {
135 0 : rProp[i].Value >>= rLabel;
136 : }
137 0 : else if ( rProp[i].Name == ITEM_DESCRIPTOR_TYPE )
138 : {
139 0 : rProp[i].Value >>= rType;
140 : }
141 0 : else if ( rProp[i].Name == ITEM_DESCRIPTOR_STYLE )
142 : {
143 0 : rProp[i].Value >>= rStyle;
144 : }
145 : }
146 0 : }
147 :
148 : // Base class implementation
149 :
150 5499 : ReadMenuDocumentHandlerBase::ReadMenuDocumentHandlerBase() :
151 : m_xLocator( 0 ),
152 : m_xReader( 0 ),
153 : m_aType( ITEM_DESCRIPTOR_TYPE ),
154 : m_aLabel( ITEM_DESCRIPTOR_LABEL ),
155 : m_aContainer( ITEM_DESCRIPTOR_CONTAINER ),
156 : m_aHelpURL( ITEM_DESCRIPTOR_HELPURL ),
157 : m_aCommandURL( ITEM_DESCRIPTOR_COMMANDURL ),
158 5499 : m_aStyle( ITEM_DESCRIPTOR_STYLE )
159 : {
160 5499 : }
161 :
162 5499 : ReadMenuDocumentHandlerBase::~ReadMenuDocumentHandlerBase()
163 : {
164 5499 : }
165 :
166 0 : void SAL_CALL ReadMenuDocumentHandlerBase::ignorableWhitespace(
167 : const OUString& )
168 : throw( SAXException, RuntimeException, std::exception )
169 : {
170 0 : }
171 :
172 0 : void SAL_CALL ReadMenuDocumentHandlerBase::processingInstruction(
173 : const OUString& /*aTarget*/, const OUString& /*aData*/ )
174 : throw( SAXException, RuntimeException, std::exception )
175 : {
176 0 : }
177 :
178 61 : void SAL_CALL ReadMenuDocumentHandlerBase::setDocumentLocator(
179 : const Reference< XLocator > &xLocator)
180 : throw( SAXException, RuntimeException, std::exception )
181 : {
182 61 : m_xLocator = xLocator;
183 61 : }
184 :
185 0 : OUString ReadMenuDocumentHandlerBase::getErrorLineString()
186 : {
187 0 : if ( m_xLocator.is() )
188 : {
189 : char buffer[32];
190 0 : snprintf( buffer, sizeof(buffer), "Line: %ld - ", static_cast<long>( m_xLocator->getLineNumber() ));
191 0 : return OUString::createFromAscii( buffer );
192 : }
193 : else
194 0 : return OUString();
195 : }
196 :
197 21113 : void ReadMenuDocumentHandlerBase::initPropertyCommon(
198 : Sequence< PropertyValue > &rProps, const OUString &rCommandURL,
199 : const OUString &rHelpId, const OUString &rLabel, sal_Int16 nItemStyleBits )
200 : {
201 21113 : rProps[0].Name = m_aCommandURL;
202 21113 : rProps[1].Name = m_aHelpURL;
203 21113 : rProps[2].Name = m_aContainer;
204 21113 : rProps[3].Name = m_aLabel;
205 21113 : rProps[4].Name = m_aStyle;
206 21113 : rProps[5].Name = m_aType;
207 :
208 : // Common values
209 21113 : rProps[0].Value <<= rCommandURL.intern();
210 21113 : rProps[1].Value <<= rHelpId;
211 21113 : rProps[2].Value <<= Reference< XIndexContainer >();
212 21113 : rProps[3].Value <<= rLabel;
213 21113 : rProps[4].Value <<= nItemStyleBits;
214 21113 : rProps[5].Value <<= ::com::sun::star::ui::ItemType::DEFAULT;
215 21113 : }
216 :
217 61 : OReadMenuDocumentHandler::OReadMenuDocumentHandler(
218 : const Reference< XIndexContainer >& rMenuBarContainer )
219 : : m_nElementDepth( 0 ),
220 : m_bMenuBarMode( false ),
221 : m_xMenuBarContainer( rMenuBarContainer ),
222 61 : m_xContainerFactory( rMenuBarContainer, UNO_QUERY )
223 : {
224 61 : }
225 :
226 122 : OReadMenuDocumentHandler::~OReadMenuDocumentHandler()
227 : {
228 122 : }
229 :
230 0 : void SAL_CALL OReadMenuDocumentHandler::startDocument()
231 : throw ( SAXException, RuntimeException, std::exception )
232 : {
233 0 : }
234 :
235 0 : void SAL_CALL OReadMenuDocumentHandler::endDocument()
236 : throw( SAXException, RuntimeException, std::exception )
237 : {
238 0 : if ( m_nElementDepth > 0 )
239 : {
240 0 : OUString aErrorMessage = getErrorLineString();
241 0 : aErrorMessage += "A closing element is missing!";
242 0 : throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
243 : }
244 0 : }
245 :
246 27863 : void SAL_CALL OReadMenuDocumentHandler::startElement(
247 : const OUString& aName, const Reference< XAttributeList > &xAttrList )
248 : throw( SAXException, RuntimeException, std::exception )
249 : {
250 27863 : if ( m_bMenuBarMode )
251 : {
252 27802 : ++m_nElementDepth;
253 27802 : m_xReader->startElement( aName, xAttrList );
254 : }
255 61 : else if ( aName == ELEMENT_MENUBAR )
256 : {
257 61 : ++m_nElementDepth;
258 61 : m_bMenuBarMode = true;
259 61 : m_xReader = Reference< XDocumentHandler >( new OReadMenuBarHandler( m_xMenuBarContainer, m_xContainerFactory ));
260 :
261 61 : m_xReader->startDocument();
262 : }
263 27863 : }
264 :
265 66338 : void SAL_CALL OReadMenuDocumentHandler::characters(const OUString&)
266 : throw( SAXException, RuntimeException, std::exception )
267 : {
268 66338 : }
269 :
270 27863 : void SAL_CALL OReadMenuDocumentHandler::endElement( const OUString& aName )
271 : throw( SAXException, RuntimeException, std::exception )
272 : {
273 27863 : if ( m_bMenuBarMode )
274 : {
275 27863 : --m_nElementDepth;
276 27863 : m_xReader->endElement( aName );
277 27863 : if ( 0 == m_nElementDepth )
278 : {
279 61 : m_xReader->endDocument();
280 61 : m_xReader.clear();
281 61 : m_bMenuBarMode = false;
282 61 : if ( aName != ELEMENT_MENUBAR )
283 : {
284 0 : OUString aErrorMessage = getErrorLineString();
285 0 : aErrorMessage += "closing element menubar expected!";
286 0 : throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
287 : }
288 : }
289 : }
290 27863 : }
291 :
292 61 : OReadMenuBarHandler::OReadMenuBarHandler(
293 : const Reference< XIndexContainer >& rMenuBarContainer,
294 : const Reference< XSingleComponentFactory >& rFactory )
295 : : m_nElementDepth( 0 ),
296 : m_bMenuMode( false ),
297 : m_xMenuBarContainer( rMenuBarContainer ),
298 61 : m_xContainerFactory( rFactory )
299 : {
300 61 : }
301 :
302 122 : OReadMenuBarHandler::~OReadMenuBarHandler()
303 : {
304 122 : }
305 :
306 61 : void SAL_CALL OReadMenuBarHandler::startDocument()
307 : throw ( SAXException, RuntimeException, std::exception )
308 : {
309 61 : }
310 :
311 61 : void SAL_CALL OReadMenuBarHandler::endDocument()
312 : throw( SAXException, RuntimeException, std::exception )
313 : {
314 61 : }
315 :
316 27802 : void SAL_CALL OReadMenuBarHandler::startElement(
317 : const OUString& rName, const Reference< XAttributeList > &xAttrList )
318 : throw( SAXException, RuntimeException, std::exception )
319 : {
320 27802 : if ( m_bMenuMode )
321 : {
322 27251 : ++m_nElementDepth;
323 27251 : m_xReader->startElement( rName, xAttrList );
324 : }
325 551 : else if ( rName == ELEMENT_MENU )
326 : {
327 551 : ++m_nElementDepth;
328 :
329 551 : OUString aHelpId;
330 1102 : OUString aCommandId;
331 1102 : OUString aLabel;
332 551 : sal_Int16 nItemBits(0);
333 :
334 551 : m_bMenuMode = true;
335 :
336 : // Container must be factory to create sub container
337 : Reference< XComponentContext > xComponentContext(
338 1102 : comphelper::getProcessComponentContext() );
339 :
340 1102 : Reference< XIndexContainer > xSubItemContainer;
341 551 : if ( m_xContainerFactory.is() )
342 551 : xSubItemContainer = Reference< XIndexContainer >( m_xContainerFactory->createInstanceWithContext( xComponentContext ), UNO_QUERY );
343 :
344 551 : if ( xSubItemContainer.is() )
345 : {
346 : // read attributes for menu
347 1109 : for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ )
348 : {
349 558 : OUString aName = xAttrList->getNameByIndex( i );
350 1116 : OUString aValue = xAttrList->getValueByIndex( i );
351 558 : if ( aName == ATTRIBUTE_ID )
352 551 : aCommandId = aValue;
353 7 : else if ( aName == ATTRIBUTE_LABEL )
354 7 : aLabel = aValue;
355 0 : else if ( aName == ATTRIBUTE_HELPID )
356 0 : aHelpId = aValue;
357 0 : else if ( aName == ATTRIBUTE_STYLE )
358 : {
359 0 : OUString aTemp( aValue );
360 0 : sal_Int32 nIndex = 0;
361 0 : do
362 : {
363 0 : OUString aToken = aTemp.getToken( 0, '+', nIndex );
364 0 : if ( !aToken.isEmpty() )
365 : {
366 0 : if ( aToken == ATTRIBUTE_ITEMSTYLE_TEXT )
367 0 : nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT;
368 0 : else if ( aToken == ATTRIBUTE_ITEMSTYLE_IMAGE )
369 0 : nItemBits |= ::com::sun::star::ui::ItemStyle::ICON;
370 0 : else if ( aToken == ATTRIBUTE_ITEMSTYLE_RADIO )
371 0 : nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK;
372 0 : }
373 : }
374 0 : while ( nIndex >= 0 );
375 : }
376 558 : }
377 :
378 551 : if ( !aCommandId.isEmpty() )
379 : {
380 551 : Sequence< PropertyValue > aSubMenuProp( 6 );
381 551 : initPropertyCommon( aSubMenuProp, aCommandId, aHelpId, aLabel, nItemBits );
382 551 : aSubMenuProp[2].Value <<= xSubItemContainer;
383 :
384 551 : m_xMenuBarContainer->insertByIndex( m_xMenuBarContainer->getCount(), makeAny( aSubMenuProp ) );
385 : }
386 : else
387 : {
388 0 : OUString aErrorMessage = getErrorLineString();
389 0 : aErrorMessage += "attribute id for element menu required!";
390 0 : throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
391 : }
392 :
393 551 : m_xReader = Reference< XDocumentHandler >( new OReadMenuHandler( xSubItemContainer, m_xContainerFactory ));
394 551 : m_xReader->startDocument();
395 551 : }
396 : }
397 : else
398 : {
399 0 : OUString aErrorMessage = getErrorLineString();
400 0 : aErrorMessage += "element menu expected!";
401 0 : throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
402 : }
403 27802 : }
404 :
405 0 : void SAL_CALL OReadMenuBarHandler::characters(const OUString&)
406 : throw( SAXException, RuntimeException, std::exception )
407 : {
408 0 : }
409 :
410 27863 : void OReadMenuBarHandler::endElement( const OUString& aName )
411 : throw( SAXException, RuntimeException, std::exception )
412 : {
413 27863 : if ( m_bMenuMode )
414 : {
415 27802 : --m_nElementDepth;
416 27802 : if ( 0 == m_nElementDepth )
417 : {
418 551 : m_xReader->endDocument();
419 551 : m_xReader.clear();
420 551 : m_bMenuMode = false;
421 551 : if ( aName != ELEMENT_MENU )
422 : {
423 0 : OUString aErrorMessage = getErrorLineString();
424 0 : aErrorMessage += "closing element menu expected!";
425 0 : throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
426 : }
427 : }
428 : else
429 27251 : m_xReader->endElement( aName );
430 : }
431 27863 : }
432 :
433 2719 : OReadMenuHandler::OReadMenuHandler(
434 : const Reference< XIndexContainer >& rMenuContainer,
435 : const Reference< XSingleComponentFactory >& rFactory ) :
436 : m_nElementDepth( 0 ),
437 : m_bMenuPopupMode( false ),
438 : m_xMenuContainer( rMenuContainer ),
439 2719 : m_xContainerFactory( rFactory )
440 : {
441 2719 : }
442 :
443 5438 : OReadMenuHandler::~OReadMenuHandler()
444 : {
445 5438 : }
446 :
447 2719 : void SAL_CALL OReadMenuHandler::startDocument()
448 : throw ( SAXException, RuntimeException, std::exception )
449 : {
450 2719 : }
451 :
452 2719 : void SAL_CALL OReadMenuHandler::endDocument()
453 : throw( SAXException, RuntimeException, std::exception)
454 : {
455 2719 : }
456 :
457 43085 : void SAL_CALL OReadMenuHandler::startElement(
458 : const OUString& aName, const Reference< XAttributeList > &xAttrList )
459 : throw( SAXException, RuntimeException, std::exception )
460 : {
461 43085 : if ( m_bMenuPopupMode )
462 : {
463 40427 : ++m_nElementDepth;
464 40427 : m_xReader->startElement( aName, xAttrList );
465 : }
466 2658 : else if ( aName == ELEMENT_MENUPOPUP )
467 : {
468 2658 : ++m_nElementDepth;
469 2658 : m_bMenuPopupMode = true;
470 2658 : m_xReader = Reference< XDocumentHandler >( new OReadMenuPopupHandler( m_xMenuContainer, m_xContainerFactory ));
471 2658 : m_xReader->startDocument();
472 : }
473 : else
474 : {
475 0 : OUString aErrorMessage = getErrorLineString();
476 0 : aErrorMessage += "unknown element found!";
477 0 : throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
478 : }
479 43085 : }
480 :
481 0 : void SAL_CALL OReadMenuHandler::characters(const OUString&)
482 : throw( SAXException, RuntimeException, std::exception )
483 : {
484 0 : }
485 :
486 43085 : void SAL_CALL OReadMenuHandler::endElement( const OUString& aName )
487 : throw( SAXException, RuntimeException, std::exception )
488 : {
489 43085 : if ( m_bMenuPopupMode )
490 : {
491 43085 : --m_nElementDepth;
492 43085 : if ( 0 == m_nElementDepth )
493 : {
494 2658 : m_xReader->endDocument();
495 2658 : m_xReader.clear();
496 2658 : m_bMenuPopupMode = false;
497 2658 : if ( aName != ELEMENT_MENUPOPUP )
498 : {
499 0 : OUString aErrorMessage = getErrorLineString();
500 0 : aErrorMessage += "closing element menupopup expected!";
501 0 : throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
502 : }
503 : }
504 : else
505 40427 : m_xReader->endElement( aName );
506 : }
507 43085 : }
508 :
509 2658 : OReadMenuPopupHandler::OReadMenuPopupHandler(
510 : const Reference< XIndexContainer >& rMenuContainer,
511 : const Reference< XSingleComponentFactory >& rFactory ) :
512 : m_nElementDepth( 0 ),
513 : m_bMenuMode( false ),
514 : m_xMenuContainer( rMenuContainer ),
515 : m_xContainerFactory( rFactory ),
516 : m_xComponentContext( comphelper::getProcessComponentContext() ),
517 2658 : m_nNextElementExpected( ELEM_CLOSE_NONE )
518 : {
519 2658 : }
520 :
521 5316 : OReadMenuPopupHandler::~OReadMenuPopupHandler()
522 : {
523 5316 : }
524 :
525 2658 : void SAL_CALL OReadMenuPopupHandler::startDocument()
526 : throw ( SAXException, RuntimeException, std::exception )
527 : {
528 2658 : }
529 :
530 2658 : void SAL_CALL OReadMenuPopupHandler::endDocument()
531 : throw( SAXException, RuntimeException, std::exception)
532 : {
533 2658 : }
534 :
535 40427 : void SAL_CALL OReadMenuPopupHandler::startElement(
536 : const OUString& rName, const Reference< XAttributeList > &xAttrList )
537 : throw( SAXException, RuntimeException, std::exception )
538 : {
539 40427 : ++m_nElementDepth;
540 :
541 40427 : if ( m_bMenuMode )
542 15834 : m_xReader->startElement( rName, xAttrList );
543 24593 : else if ( rName == ELEMENT_MENU )
544 : {
545 2168 : OUString aHelpId;
546 4336 : OUString aCommandId;
547 4336 : OUString aLabel;
548 2168 : sal_Int16 nItemBits(0);
549 :
550 2168 : m_bMenuMode = true;
551 :
552 : // Container must be factory to create sub container
553 4336 : Reference< XIndexContainer > xSubItemContainer;
554 2168 : if ( m_xContainerFactory.is() )
555 2168 : xSubItemContainer = Reference< XIndexContainer >( m_xContainerFactory->createInstanceWithContext( m_xComponentContext ), UNO_QUERY );
556 :
557 : // read attributes for menu
558 4342 : for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ )
559 : {
560 2174 : OUString aName = xAttrList->getNameByIndex( i );
561 4348 : OUString aValue = xAttrList->getValueByIndex( i );
562 2174 : if ( aName == ATTRIBUTE_ID )
563 2168 : aCommandId = aValue;
564 6 : else if ( aName == ATTRIBUTE_LABEL )
565 6 : aLabel = aValue;
566 0 : else if ( aName == ATTRIBUTE_HELPID )
567 0 : aHelpId = aValue;
568 0 : else if ( aName == ATTRIBUTE_STYLE )
569 : {
570 0 : OUString aTemp( aValue );
571 0 : sal_Int32 nIndex = 0;
572 0 : do
573 : {
574 0 : OUString aToken = aTemp.getToken( 0, '+', nIndex );
575 0 : if ( !aToken.isEmpty() )
576 : {
577 0 : if ( aToken == ATTRIBUTE_ITEMSTYLE_TEXT )
578 0 : nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT;
579 0 : else if ( aToken == ATTRIBUTE_ITEMSTYLE_IMAGE )
580 0 : nItemBits |= ::com::sun::star::ui::ItemStyle::ICON;
581 0 : else if ( aToken == ATTRIBUTE_ITEMSTYLE_RADIO )
582 0 : nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK;
583 0 : }
584 : }
585 0 : while ( nIndex >= 0 );
586 : }
587 :
588 2174 : }
589 :
590 2168 : if ( !aCommandId.isEmpty() )
591 : {
592 2168 : Sequence< PropertyValue > aSubMenuProp( 6 );
593 2168 : initPropertyCommon( aSubMenuProp, aCommandId, aHelpId, aLabel, nItemBits );
594 2168 : aSubMenuProp[2].Value <<= xSubItemContainer;
595 :
596 2168 : m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aSubMenuProp ) );
597 : }
598 : else
599 : {
600 0 : OUString aErrorMessage = getErrorLineString();
601 0 : aErrorMessage += "attribute id for element menu required!";
602 0 : throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
603 : }
604 :
605 2168 : m_xReader = Reference< XDocumentHandler >( new OReadMenuHandler( xSubItemContainer, m_xContainerFactory ));
606 4336 : m_xReader->startDocument();
607 : }
608 22425 : else if ( rName == ELEMENT_MENUITEM )
609 : {
610 18394 : OUString aHelpId;
611 36788 : OUString aCommandId;
612 36788 : OUString aLabel;
613 18394 : sal_Int16 nItemBits(0);
614 : // read attributes for menu item
615 37625 : for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ )
616 : {
617 19231 : OUString aName = xAttrList->getNameByIndex( i );
618 38462 : OUString aValue = xAttrList->getValueByIndex( i );
619 19231 : if ( aName == ATTRIBUTE_ID )
620 18394 : aCommandId = aValue;
621 837 : else if ( aName == ATTRIBUTE_LABEL )
622 76 : aLabel = aValue;
623 761 : else if ( aName == ATTRIBUTE_HELPID )
624 1 : aHelpId = aValue;
625 760 : else if ( aName == ATTRIBUTE_STYLE )
626 : {
627 760 : OUString aTemp( aValue );
628 760 : sal_Int32 nIndex = 0;
629 760 : do
630 : {
631 760 : OUString aToken = aTemp.getToken( 0, '+', nIndex );
632 760 : if ( !aToken.isEmpty() )
633 : {
634 760 : if ( aToken == ATTRIBUTE_ITEMSTYLE_TEXT )
635 0 : nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT;
636 760 : else if ( aToken == ATTRIBUTE_ITEMSTYLE_IMAGE )
637 0 : nItemBits |= ::com::sun::star::ui::ItemStyle::ICON;
638 760 : else if ( aToken == ATTRIBUTE_ITEMSTYLE_RADIO )
639 760 : nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK;
640 760 : }
641 : }
642 1520 : while ( nIndex >= 0 );
643 : }
644 :
645 19231 : }
646 :
647 18394 : if ( !aCommandId.isEmpty() )
648 : {
649 18394 : Sequence< PropertyValue > aMenuItem( 6 );
650 18394 : initPropertyCommon( aMenuItem, aCommandId, aHelpId, aLabel, nItemBits );
651 18394 : aMenuItem[2].Value <<= Reference< XIndexContainer >();
652 :
653 18394 : m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aMenuItem ) );
654 : }
655 :
656 36788 : m_nNextElementExpected = ELEM_CLOSE_MENUITEM;
657 : }
658 4031 : else if ( rName == ELEMENT_MENUSEPARATOR )
659 : {
660 4031 : Sequence< PropertyValue > aMenuSeparator( 1 );
661 4031 : aMenuSeparator[0].Name = ITEM_DESCRIPTOR_TYPE;
662 4031 : aMenuSeparator[0].Value <<= ::com::sun::star::ui::ItemType::SEPARATOR_LINE;
663 :
664 4031 : m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aMenuSeparator ) );
665 :
666 4031 : m_nNextElementExpected = ELEM_CLOSE_MENUSEPARATOR;
667 : }
668 : else
669 : {
670 0 : OUString aErrorMessage = getErrorLineString();
671 0 : aErrorMessage += "unknown element found!";
672 0 : throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
673 : }
674 40427 : }
675 :
676 0 : void SAL_CALL OReadMenuPopupHandler::characters(const OUString&)
677 : throw( SAXException, RuntimeException, std::exception )
678 : {
679 0 : }
680 :
681 40427 : void SAL_CALL OReadMenuPopupHandler::endElement( const OUString& aName )
682 : throw( SAXException, RuntimeException, std::exception )
683 : {
684 40427 : --m_nElementDepth;
685 40427 : if ( m_bMenuMode )
686 : {
687 18002 : if ( 0 == m_nElementDepth )
688 : {
689 2168 : m_xReader->endDocument();
690 2168 : m_xReader.clear();
691 2168 : m_bMenuMode = false;
692 2168 : if ( aName != ELEMENT_MENU )
693 : {
694 0 : OUString aErrorMessage = getErrorLineString();
695 0 : aErrorMessage += "closing element menu expected!";
696 0 : throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
697 : }
698 : }
699 : else
700 15834 : m_xReader->endElement( aName );
701 : }
702 : else
703 : {
704 22425 : if ( m_nNextElementExpected == ELEM_CLOSE_MENUITEM )
705 : {
706 18394 : if ( aName != ELEMENT_MENUITEM )
707 : {
708 0 : OUString aErrorMessage = getErrorLineString();
709 0 : aErrorMessage += "closing element menuitem expected!";
710 0 : throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
711 : }
712 : }
713 4031 : else if ( m_nNextElementExpected == ELEM_CLOSE_MENUSEPARATOR )
714 : {
715 4031 : if ( aName != ELEMENT_MENUSEPARATOR )
716 : {
717 0 : OUString aErrorMessage = getErrorLineString();
718 0 : aErrorMessage += "closing element menuseparator expected!";
719 0 : throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
720 : }
721 : }
722 :
723 22425 : m_nNextElementExpected = ELEM_CLOSE_NONE;
724 : }
725 40427 : }
726 :
727 : // --------------------------------- Write XML ---------------------------------
728 :
729 0 : OWriteMenuDocumentHandler::OWriteMenuDocumentHandler(
730 : const Reference< XIndexAccess >& rMenuBarContainer,
731 : const Reference< XDocumentHandler >& rDocumentHandler ) :
732 : m_xMenuBarContainer( rMenuBarContainer ),
733 0 : m_xWriteDocumentHandler( rDocumentHandler )
734 : {
735 0 : ::comphelper::AttributeList* pList = new ::comphelper::AttributeList;
736 0 : m_xEmptyList = Reference< XAttributeList >( static_cast<XAttributeList *>(pList), UNO_QUERY );
737 0 : m_aAttributeType = ATTRIBUTE_TYPE_CDATA;
738 0 : }
739 :
740 0 : OWriteMenuDocumentHandler::~OWriteMenuDocumentHandler()
741 : {
742 0 : }
743 :
744 0 : void OWriteMenuDocumentHandler::WriteMenuDocument()
745 : throw ( SAXException, RuntimeException )
746 : {
747 0 : ::comphelper::AttributeList* pList = new ::comphelper::AttributeList;
748 0 : Reference< XAttributeList > rList( static_cast<XAttributeList *>(pList) , UNO_QUERY );
749 :
750 0 : m_xWriteDocumentHandler->startDocument();
751 :
752 : // write DOCTYPE line!
753 0 : Reference< XExtendedDocumentHandler > xExtendedDocHandler( m_xWriteDocumentHandler, UNO_QUERY );
754 0 : if ( xExtendedDocHandler.is() )
755 : {
756 0 : xExtendedDocHandler->unknown( OUString( MENUBAR_DOCTYPE ) );
757 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
758 : }
759 :
760 : pList->AddAttribute( OUString( ATTRIBUTE_XMLNS_MENU ),
761 : m_aAttributeType,
762 0 : OUString( XMLNS_MENU ) );
763 :
764 : pList->AddAttribute( OUString( ATTRIBUTE_NS_ID ),
765 : m_aAttributeType,
766 0 : OUString( "menubar" ) );
767 :
768 0 : m_xWriteDocumentHandler->startElement( OUString( ELEMENT_NS_MENUBAR ), pList );
769 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
770 :
771 0 : WriteMenu( m_xMenuBarContainer );
772 :
773 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
774 0 : m_xWriteDocumentHandler->endElement( OUString( ELEMENT_NS_MENUBAR ) );
775 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
776 0 : m_xWriteDocumentHandler->endDocument();
777 0 : }
778 :
779 0 : void OWriteMenuDocumentHandler::WriteMenu( const Reference< XIndexAccess >& rMenuContainer )
780 : throw ( SAXException, RuntimeException )
781 : {
782 0 : sal_Int32 nItemCount = rMenuContainer->getCount();
783 0 : bool bSeparator = false;
784 0 : Any aAny;
785 :
786 0 : for ( sal_Int32 nItemPos = 0; nItemPos < nItemCount; nItemPos++ )
787 : {
788 0 : Sequence< PropertyValue > aProps;
789 0 : aAny = rMenuContainer->getByIndex( nItemPos );
790 0 : if ( aAny >>= aProps )
791 : {
792 0 : OUString aCommandURL;
793 0 : OUString aLabel;
794 0 : OUString aHelpURL;
795 0 : sal_Int16 nType( ::com::sun::star::ui::ItemType::DEFAULT );
796 0 : sal_Int16 nItemBits( 0 );
797 0 : Reference< XIndexAccess > xSubMenu;
798 :
799 0 : ExtractMenuParameters( aProps, aCommandURL, aLabel, aHelpURL, xSubMenu, nType, nItemBits );
800 0 : if ( xSubMenu.is() )
801 : {
802 0 : if ( aCommandURL == ADDDIRECT_CMD ||
803 0 : aCommandURL == AUTOPILOTMENU_CMD )
804 : {
805 0 : WriteMenuItem( aCommandURL, aLabel, aHelpURL, nItemBits );
806 0 : bSeparator = false;
807 : }
808 0 : else if ( !aCommandURL.isEmpty() && !AddonPopupMenu::IsCommandURLPrefix( aCommandURL ))
809 : {
810 0 : ::comphelper::AttributeList* pListMenu = new ::comphelper::AttributeList;
811 0 : Reference< XAttributeList > xListMenu( static_cast<XAttributeList *>(pListMenu) , UNO_QUERY );
812 :
813 : pListMenu->AddAttribute( OUString( ATTRIBUTE_NS_ID ),
814 : m_aAttributeType,
815 0 : aCommandURL );
816 :
817 0 : if ( aCommandURL.copy( CMD_PROTOCOL_SIZE ) != CMD_PROTOCOL )
818 : pListMenu->AddAttribute( OUString( ATTRIBUTE_NS_LABEL ),
819 : m_aAttributeType,
820 0 : aLabel );
821 :
822 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
823 0 : m_xWriteDocumentHandler->startElement( OUString( ELEMENT_NS_MENU ), xListMenu );
824 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
825 0 : m_xWriteDocumentHandler->startElement( OUString( ELEMENT_NS_MENUPOPUP ), m_xEmptyList );
826 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
827 :
828 0 : WriteMenu( xSubMenu );
829 :
830 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
831 0 : m_xWriteDocumentHandler->endElement( OUString( ELEMENT_NS_MENUPOPUP ) );
832 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
833 0 : m_xWriteDocumentHandler->endElement( OUString( ELEMENT_NS_MENU ) );
834 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
835 0 : bSeparator = false;
836 : }
837 : }
838 : else
839 : {
840 0 : if ( nType == ::com::sun::star::ui::ItemType::DEFAULT )
841 : {
842 0 : if ( !aCommandURL.isEmpty() )
843 : {
844 0 : bSeparator = false;
845 0 : WriteMenuItem( aCommandURL, aLabel, aHelpURL, nItemBits );
846 : }
847 : }
848 0 : else if ( !bSeparator )
849 : {
850 : // Don't write two separators together
851 0 : WriteMenuSeparator();
852 0 : bSeparator = true;
853 : }
854 0 : }
855 : }
856 0 : }
857 0 : }
858 :
859 0 : void OWriteMenuDocumentHandler::WriteMenuItem( const OUString& aCommandURL, const OUString& aLabel, const OUString& aHelpURL, sal_Int16 nStyle )
860 : {
861 0 : ::comphelper::AttributeList* pList = new ::comphelper::AttributeList;
862 0 : Reference< XAttributeList > xList( static_cast<XAttributeList *>(pList) , UNO_QUERY );
863 :
864 : pList->AddAttribute( OUString( ATTRIBUTE_NS_ID ),
865 : m_aAttributeType,
866 0 : aCommandURL );
867 :
868 0 : if ( !aHelpURL.isEmpty() )
869 : {
870 : pList->AddAttribute( OUString( ATTRIBUTE_NS_HELPID ),
871 : m_aAttributeType,
872 0 : aHelpURL );
873 : }
874 :
875 0 : if ( !aLabel.isEmpty() && aCommandURL.copy( CMD_PROTOCOL_SIZE ) != CMD_PROTOCOL )
876 : {
877 : pList->AddAttribute( OUString( ATTRIBUTE_NS_LABEL ),
878 : m_aAttributeType,
879 0 : aLabel );
880 : }
881 0 : if (( nStyle > 0 ) && aCommandURL.copy( CMD_PROTOCOL_SIZE ) != CMD_PROTOCOL )
882 : {
883 0 : OUString aValue;
884 0 : MenuStyleItem* pStyle = MenuItemStyles;
885 :
886 0 : for ( sal_Int32 nIndex = 0; nIndex < nMenuStyleItemEntries; ++nIndex, ++pStyle )
887 : {
888 0 : if ( nStyle & pStyle->nBit )
889 : {
890 0 : if ( !aValue.isEmpty() )
891 0 : aValue = aValue.concat( OUString( "+" ) );
892 0 : aValue += OUString::createFromAscii( pStyle->attrName );
893 : }
894 : }
895 : pList->AddAttribute( OUString( ATTRIBUTE_NS_STYLE ),
896 : m_aAttributeType,
897 0 : aValue );
898 : }
899 :
900 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
901 0 : m_xWriteDocumentHandler->startElement( OUString( ELEMENT_NS_MENUITEM ), xList );
902 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
903 0 : m_xWriteDocumentHandler->endElement( OUString( ELEMENT_NS_MENUITEM ) );
904 0 : }
905 :
906 0 : void OWriteMenuDocumentHandler::WriteMenuSeparator()
907 : {
908 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
909 0 : m_xWriteDocumentHandler->startElement( OUString( ELEMENT_NS_MENUSEPARATOR ), m_xEmptyList );
910 0 : m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
911 0 : m_xWriteDocumentHandler->endElement( OUString( ELEMENT_NS_MENUSEPARATOR ) );
912 0 : }
913 :
914 : } // namespace framework
915 :
916 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|