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