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