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