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 { 201 } 202 203 void SAL_CALL ReadMenuDocumentHandlerBase::processingInstruction( 204 const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/ ) 205 { 206 } 207 208 void SAL_CALL ReadMenuDocumentHandlerBase::setDocumentLocator( 209 const Reference< XLocator > &xLocator) 210 { 211 m_xLocator = xLocator; 212 } 213 214 ::rtl::OUString ReadMenuDocumentHandlerBase::getErrorLineString() 215 { 216 char buffer[32]; 217 218 if ( m_xLocator.is() ) 219 { 220 snprintf( buffer, sizeof(buffer), "Line: %ld - ", static_cast<long>( m_xLocator->getLineNumber() )); 221 return ::rtl::OUString::createFromAscii( buffer ); 222 } 223 else 224 return ::rtl::OUString(); 225 } 226 227 void ReadMenuDocumentHandlerBase::initPropertyCommon( 228 Sequence< PropertyValue > &rProps, const rtl::OUString &rCommandURL, 229 const rtl::OUString &rHelpId, const rtl::OUString &rLabel, sal_Int16 nItemStyleBits ) 230 { 231 rProps[0].Name = m_aCommandURL; 232 rProps[1].Name = m_aHelpURL; 233 rProps[2].Name = m_aContainer; 234 rProps[3].Name = m_aLabel; 235 rProps[4].Name = m_aStyle; 236 rProps[5].Name = m_aType; 237 238 // Common values 239 rProps[0].Value <<= rCommandURL.intern(); 240 rProps[1].Value <<= rHelpId; 241 rProps[2].Value <<= Reference< XIndexContainer >(); 242 rProps[3].Value <<= rLabel; 243 rProps[4].Value <<= nItemStyleBits; 244 rProps[5].Value <<= ::com::sun::star::ui::ItemType::DEFAULT; 245 } 246 247 // ----------------------------------------------------------------------------- 248 249 OReadMenuDocumentHandler::OReadMenuDocumentHandler( 250 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, 251 const Reference< XIndexContainer >& rMenuBarContainer ) 252 : m_nElementDepth( 0 ), 253 m_bMenuBarMode( sal_False ), 254 m_xMenuBarContainer( rMenuBarContainer ), 255 m_xContainerFactory( rMenuBarContainer, UNO_QUERY ), 256 mxServiceFactory(xServiceFactory) 257 { 258 } 259 260 // #110897# 261 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& OReadMenuDocumentHandler::getServiceFactory() 262 { 263 // #110897# 264 return mxServiceFactory; 265 } 266 267 OReadMenuDocumentHandler::~OReadMenuDocumentHandler() 268 { 269 } 270 271 272 void SAL_CALL OReadMenuDocumentHandler::startDocument(void) 273 { 274 } 275 276 277 void SAL_CALL OReadMenuDocumentHandler::endDocument(void) 278 { 279 if ( m_nElementDepth > 0 ) 280 { 281 ::rtl::OUString aErrorMessage = getErrorLineString(); 282 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "A closing element is missing!" )); 283 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); 284 } 285 } 286 287 288 void SAL_CALL OReadMenuDocumentHandler::startElement( 289 const ::rtl::OUString& aName, const Reference< XAttributeList > &xAttrList ) 290 { 291 if ( m_bMenuBarMode ) 292 { 293 ++m_nElementDepth; 294 m_xReader->startElement( aName, xAttrList ); 295 } 296 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUBAR ))) 297 { 298 ++m_nElementDepth; 299 m_bMenuBarMode = sal_True; 300 301 // #110897# m_xReader = Reference< XDocumentHandler >( new OReadMenuBarHandler( m_xMenuBarContainer, m_xContainerFactory )); 302 m_xReader = Reference< XDocumentHandler >( new OReadMenuBarHandler( getServiceFactory(), m_xMenuBarContainer, m_xContainerFactory )); 303 304 m_xReader->startDocument(); 305 } 306 } 307 308 309 void SAL_CALL OReadMenuDocumentHandler::characters(const rtl::OUString&) 310 { 311 } 312 313 314 void SAL_CALL OReadMenuDocumentHandler::endElement( const ::rtl::OUString& aName ) 315 { 316 if ( m_bMenuBarMode ) 317 { 318 --m_nElementDepth; 319 m_xReader->endElement( aName ); 320 if ( 0 == m_nElementDepth ) 321 { 322 m_xReader->endDocument(); 323 m_xReader = Reference< XDocumentHandler >(); 324 m_bMenuBarMode = sal_False; 325 if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUBAR ))) 326 { 327 ::rtl::OUString aErrorMessage = getErrorLineString(); 328 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menubar expected!" )); 329 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); 330 } 331 } 332 } 333 } 334 335 336 // ----------------------------------------------------------------------------- 337 338 339 // #110897# 340 OReadMenuBarHandler::OReadMenuBarHandler( 341 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory, 342 const Reference< XIndexContainer >& rMenuBarContainer, 343 const Reference< XSingleComponentFactory >& rFactory ) 344 : m_nElementDepth( 0 ), 345 m_bMenuMode( sal_False ), 346 m_xMenuBarContainer( rMenuBarContainer ), 347 m_xContainerFactory( rFactory ), 348 mxServiceFactory( xServiceFactory ) 349 { 350 } 351 352 // #110897# 353 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& OReadMenuBarHandler::getServiceFactory() 354 { 355 // #110897# 356 return mxServiceFactory; 357 } 358 359 OReadMenuBarHandler::~OReadMenuBarHandler() 360 { 361 } 362 363 364 void SAL_CALL OReadMenuBarHandler::startDocument(void) 365 { 366 } 367 368 369 void SAL_CALL OReadMenuBarHandler::endDocument(void) 370 { 371 } 372 373 374 void SAL_CALL OReadMenuBarHandler::startElement( 375 const ::rtl::OUString& rName, const Reference< XAttributeList > &xAttrList ) 376 { 377 if ( m_bMenuMode ) 378 { 379 ++m_nElementDepth; 380 m_xReader->startElement( rName, xAttrList ); 381 } 382 else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENU ))) 383 { 384 ++m_nElementDepth; 385 386 ::rtl::OUString aHelpId; 387 ::rtl::OUString aCommandId; 388 ::rtl::OUString aLabel; 389 sal_Int16 nItemBits(0); 390 391 m_bMenuMode = sal_True; 392 393 // Container must be factory to create sub container 394 Reference< XComponentContext > xComponentContext; 395 Reference< XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY ); 396 xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= 397 xComponentContext; 398 399 Reference< XIndexContainer > xSubItemContainer; 400 if ( m_xContainerFactory.is() ) 401 xSubItemContainer = Reference< XIndexContainer >( m_xContainerFactory->createInstanceWithContext( xComponentContext ), UNO_QUERY ); 402 403 if ( xSubItemContainer.is() ) 404 { 405 // read attributes for menu 406 for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ ) 407 { 408 ::rtl::OUString aName = xAttrList->getNameByIndex( i ); 409 ::rtl::OUString aValue = xAttrList->getValueByIndex( i ); 410 if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ID ))) 411 aCommandId = aValue; 412 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_LABEL ))) 413 aLabel = aValue; 414 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_HELPID ))) 415 aHelpId = aValue; 416 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_STYLE ))) 417 { 418 ::rtl::OUString aTemp( aValue ); 419 sal_Int32 nIndex = 0; 420 do 421 { 422 ::rtl::OUString aToken = aTemp.getToken( 0, '+', nIndex ); 423 if ( aToken.getLength() > 0 ) 424 { 425 if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_TEXT ) ) ) 426 nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT; 427 else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_IMAGE ) ) ) 428 nItemBits |= ::com::sun::star::ui::ItemStyle::ICON; 429 else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_RADIO ) ) ) 430 nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK; 431 } 432 } 433 while ( nIndex >= 0 ); 434 } 435 } 436 437 if ( aCommandId.getLength() > 0 ) 438 { 439 Sequence< PropertyValue > aSubMenuProp( 6 ); 440 initPropertyCommon( aSubMenuProp, aCommandId, aHelpId, aLabel, nItemBits ); 441 aSubMenuProp[2].Value <<= xSubItemContainer; 442 443 m_xMenuBarContainer->insertByIndex( m_xMenuBarContainer->getCount(), makeAny( aSubMenuProp ) ); 444 } 445 else 446 { 447 ::rtl::OUString aErrorMessage = getErrorLineString(); 448 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "attribute id for element menu required!" )); 449 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); 450 } 451 452 m_xReader = Reference< XDocumentHandler >( new OReadMenuHandler( xSubItemContainer, m_xContainerFactory )); 453 m_xReader->startDocument(); 454 } 455 } 456 else 457 { 458 ::rtl::OUString aErrorMessage = getErrorLineString(); 459 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "element menu expected!" )); 460 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); 461 } 462 } 463 464 465 void SAL_CALL OReadMenuBarHandler::characters(const rtl::OUString&) 466 { 467 } 468 469 470 void OReadMenuBarHandler::endElement( const ::rtl::OUString& aName ) 471 { 472 if ( m_bMenuMode ) 473 { 474 --m_nElementDepth; 475 if ( 0 == m_nElementDepth ) 476 { 477 m_xReader->endDocument(); 478 m_xReader = Reference< XDocumentHandler >(); 479 m_bMenuMode = sal_False; 480 if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENU ))) 481 { 482 ::rtl::OUString aErrorMessage = getErrorLineString(); 483 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menu expected!" )); 484 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); 485 } 486 } 487 else 488 m_xReader->endElement( aName ); 489 } 490 } 491 492 493 // ----------------------------------------------------------------------------- 494 495 496 OReadMenuHandler::OReadMenuHandler( 497 const Reference< XIndexContainer >& rMenuContainer, 498 const Reference< XSingleComponentFactory >& rFactory ) : 499 m_nElementDepth( 0 ), 500 m_bMenuPopupMode( sal_False ), 501 m_xMenuContainer( rMenuContainer ), 502 m_xContainerFactory( rFactory ) 503 { 504 } 505 506 507 OReadMenuHandler::~OReadMenuHandler() 508 { 509 } 510 511 512 void SAL_CALL OReadMenuHandler::startDocument(void) 513 { 514 } 515 516 517 void SAL_CALL OReadMenuHandler::endDocument(void) 518 { 519 } 520 521 522 void SAL_CALL OReadMenuHandler::startElement( 523 const ::rtl::OUString& aName, const Reference< XAttributeList > &xAttrList ) 524 { 525 if ( m_bMenuPopupMode ) 526 { 527 ++m_nElementDepth; 528 m_xReader->startElement( aName, xAttrList ); 529 } 530 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUPOPUP ))) 531 { 532 ++m_nElementDepth; 533 m_bMenuPopupMode = sal_True; 534 m_xReader = Reference< XDocumentHandler >( new OReadMenuPopupHandler( m_xMenuContainer, m_xContainerFactory )); 535 m_xReader->startDocument(); 536 } 537 else 538 { 539 ::rtl::OUString aErrorMessage = getErrorLineString(); 540 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unknown element found!" )); 541 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); 542 } 543 } 544 545 546 void SAL_CALL OReadMenuHandler::characters(const rtl::OUString&) 547 { 548 } 549 550 551 void SAL_CALL OReadMenuHandler::endElement( const ::rtl::OUString& aName ) 552 { 553 if ( m_bMenuPopupMode ) 554 { 555 --m_nElementDepth; 556 if ( 0 == m_nElementDepth ) 557 { 558 m_xReader->endDocument(); 559 m_xReader = Reference< XDocumentHandler >(); 560 m_bMenuPopupMode = sal_False; 561 if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUPOPUP ))) 562 { 563 ::rtl::OUString aErrorMessage = getErrorLineString(); 564 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menupopup expected!" )); 565 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); 566 } 567 } 568 else 569 m_xReader->endElement( aName ); 570 } 571 } 572 573 574 // ----------------------------------------------------------------------------- 575 576 577 OReadMenuPopupHandler::OReadMenuPopupHandler( 578 const Reference< XIndexContainer >& rMenuContainer, 579 const Reference< XSingleComponentFactory >& rFactory ) : 580 m_nElementDepth( 0 ), 581 m_bMenuMode( sal_False ), 582 m_xMenuContainer( rMenuContainer ), 583 m_xContainerFactory( rFactory ), 584 m_nNextElementExpected( ELEM_CLOSE_NONE ) 585 { 586 } 587 588 589 OReadMenuPopupHandler::~OReadMenuPopupHandler() 590 { 591 } 592 593 594 void SAL_CALL OReadMenuPopupHandler::startDocument(void) 595 { 596 } 597 598 599 void SAL_CALL OReadMenuPopupHandler::endDocument(void) 600 { 601 } 602 603 void SAL_CALL OReadMenuPopupHandler::startElement( 604 const ::rtl::OUString& rName, const Reference< XAttributeList > &xAttrList ) 605 { 606 ++m_nElementDepth; 607 608 if ( m_bMenuMode ) 609 m_xReader->startElement( rName, xAttrList ); 610 else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENU ))) 611 { 612 ::rtl::OUString aHelpId; 613 ::rtl::OUString aCommandId; 614 ::rtl::OUString aLabel; 615 sal_Int16 nItemBits(0); 616 617 m_bMenuMode = sal_True; 618 619 // Container must be factory to create sub container 620 if ( !m_xComponentContext.is() ) 621 { 622 const Reference< XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW ); 623 m_xComponentContext.set(xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), UNO_QUERY_THROW ); 624 } 625 626 Reference< XIndexContainer > xSubItemContainer; 627 if ( m_xContainerFactory.is() ) 628 xSubItemContainer = Reference< XIndexContainer >( m_xContainerFactory->createInstanceWithContext( m_xComponentContext ), UNO_QUERY ); 629 630 // read attributes for menu 631 for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ ) 632 { 633 ::rtl::OUString aName = xAttrList->getNameByIndex( i ); 634 ::rtl::OUString aValue = xAttrList->getValueByIndex( i ); 635 if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ID ))) 636 aCommandId = aValue; 637 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_LABEL ))) 638 aLabel = aValue; 639 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_HELPID ))) 640 aHelpId = aValue; 641 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_STYLE ))) 642 { 643 ::rtl::OUString aTemp( aValue ); 644 sal_Int32 nIndex = 0; 645 do 646 { 647 ::rtl::OUString aToken = aTemp.getToken( 0, '+', nIndex ); 648 if ( aToken.getLength() > 0 ) 649 { 650 if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_TEXT ) ) ) 651 nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT; 652 else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_IMAGE ) ) ) 653 nItemBits |= ::com::sun::star::ui::ItemStyle::ICON; 654 else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_RADIO ) ) ) 655 nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK; 656 } 657 } 658 while ( nIndex >= 0 ); 659 } 660 661 } 662 663 if ( aCommandId.getLength() > 0 ) 664 { 665 Sequence< PropertyValue > aSubMenuProp( 6 ); 666 initPropertyCommon( aSubMenuProp, aCommandId, aHelpId, aLabel, nItemBits ); 667 aSubMenuProp[2].Value <<= xSubItemContainer; 668 669 m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aSubMenuProp ) ); 670 } 671 else 672 { 673 ::rtl::OUString aErrorMessage = getErrorLineString(); 674 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "attribute id for element menu required!" )); 675 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); 676 } 677 678 m_xReader = Reference< XDocumentHandler >( new OReadMenuHandler( xSubItemContainer, m_xContainerFactory )); 679 m_xReader->startDocument(); 680 } 681 else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUITEM ))) 682 { 683 ::rtl::OUString aHelpId; 684 ::rtl::OUString aCommandId; 685 ::rtl::OUString aLabel; 686 sal_Int16 nItemBits(0); 687 // read attributes for menu item 688 for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ ) 689 { 690 ::rtl::OUString aName = xAttrList->getNameByIndex( i ); 691 ::rtl::OUString aValue = xAttrList->getValueByIndex( i ); 692 if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ID ))) 693 aCommandId = aValue; 694 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_LABEL ))) 695 aLabel = aValue; 696 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_HELPID ))) 697 aHelpId = aValue; 698 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_STYLE ))) 699 { 700 ::rtl::OUString aTemp( aValue ); 701 sal_Int32 nIndex = 0; 702 do 703 { 704 ::rtl::OUString aToken = aTemp.getToken( 0, '+', nIndex ); 705 if ( aToken.getLength() > 0 ) 706 { 707 if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_TEXT ) ) ) 708 nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT; 709 else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_IMAGE ) ) ) 710 nItemBits |= ::com::sun::star::ui::ItemStyle::ICON; 711 else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_RADIO ) ) ) 712 nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK; 713 } 714 } 715 while ( nIndex >= 0 ); 716 } 717 718 } 719 720 if ( aCommandId.getLength() > 0 ) 721 { 722 Sequence< PropertyValue > aMenuItem( 6 ); 723 initPropertyCommon( aMenuItem, aCommandId, aHelpId, aLabel, nItemBits ); 724 aMenuItem[2].Value <<= Reference< XIndexContainer >(); 725 726 m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aMenuItem ) ); 727 } 728 729 m_nNextElementExpected = ELEM_CLOSE_MENUITEM; 730 } 731 else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUSEPARATOR ))) 732 { 733 Sequence< PropertyValue > aMenuSeparator( 1 ); 734 aMenuSeparator[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TYPE )); 735 aMenuSeparator[0].Value <<= ::com::sun::star::ui::ItemType::SEPARATOR_LINE; 736 737 m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aMenuSeparator ) ); 738 739 m_nNextElementExpected = ELEM_CLOSE_MENUSEPARATOR; 740 } 741 else 742 { 743 ::rtl::OUString aErrorMessage = getErrorLineString(); 744 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unknown element found!" )); 745 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); 746 } 747 } 748 749 750 void SAL_CALL OReadMenuPopupHandler::characters(const rtl::OUString&) 751 { 752 } 753 754 755 void SAL_CALL OReadMenuPopupHandler::endElement( const ::rtl::OUString& aName ) 756 { 757 --m_nElementDepth; 758 if ( m_bMenuMode ) 759 { 760 if ( 0 == m_nElementDepth ) 761 { 762 m_xReader->endDocument(); 763 m_xReader = Reference< XDocumentHandler >(); 764 m_bMenuMode = sal_False; 765 if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENU ))) 766 { 767 ::rtl::OUString aErrorMessage = getErrorLineString(); 768 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menu expected!" )); 769 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); 770 } 771 } 772 else 773 m_xReader->endElement( aName ); 774 } 775 else 776 { 777 if ( m_nNextElementExpected == ELEM_CLOSE_MENUITEM ) 778 { 779 if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUITEM ))) 780 { 781 ::rtl::OUString aErrorMessage = getErrorLineString(); 782 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menuitem expected!" )); 783 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); 784 } 785 } 786 else if ( m_nNextElementExpected == ELEM_CLOSE_MENUSEPARATOR ) 787 { 788 if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUSEPARATOR ))) 789 { 790 ::rtl::OUString aErrorMessage = getErrorLineString(); 791 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menuseparator expected!" )); 792 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); 793 } 794 } 795 796 m_nNextElementExpected = ELEM_CLOSE_NONE; 797 } 798 } 799 800 801 // --------------------------------- Write XML --------------------------------- 802 803 804 OWriteMenuDocumentHandler::OWriteMenuDocumentHandler( 805 const Reference< XIndexAccess >& rMenuBarContainer, 806 const Reference< XDocumentHandler >& rDocumentHandler ) : 807 m_xMenuBarContainer( rMenuBarContainer ), 808 m_xWriteDocumentHandler( rDocumentHandler ) 809 { 810 ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; 811 m_xEmptyList = Reference< XAttributeList >( (XAttributeList *) pList, UNO_QUERY ); 812 m_aAttributeType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE_CDATA )); 813 } 814 815 816 OWriteMenuDocumentHandler::~OWriteMenuDocumentHandler() 817 { 818 } 819 820 821 void OWriteMenuDocumentHandler::WriteMenuDocument() 822 { 823 ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; 824 Reference< XAttributeList > rList( (XAttributeList *) pList , UNO_QUERY ); 825 826 m_xWriteDocumentHandler->startDocument(); 827 828 // write DOCTYPE line! 829 Reference< XExtendedDocumentHandler > xExtendedDocHandler( m_xWriteDocumentHandler, UNO_QUERY ); 830 if ( xExtendedDocHandler.is() ) 831 { 832 xExtendedDocHandler->unknown( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( MENUBAR_DOCTYPE )) ); 833 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 834 } 835 836 pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_MENU )), 837 m_aAttributeType, 838 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_MENU )) ); 839 840 pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_ID )), 841 m_aAttributeType, 842 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "menubar" )) ); 843 844 m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUBAR )), pList ); 845 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 846 847 WriteMenu( m_xMenuBarContainer ); 848 849 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 850 m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUBAR )) ); 851 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 852 m_xWriteDocumentHandler->endDocument(); 853 } 854 855 856 void OWriteMenuDocumentHandler::WriteMenu( const Reference< XIndexAccess >& rMenuContainer ) 857 { 858 sal_Int32 nItemCount = rMenuContainer->getCount(); 859 sal_Bool bSeparator = sal_False; 860 Any aAny; 861 862 for ( sal_Int32 nItemPos = 0; nItemPos < nItemCount; nItemPos++ ) 863 { 864 Sequence< PropertyValue > aProps; 865 aAny = rMenuContainer->getByIndex( nItemPos ); 866 if ( aAny >>= aProps ) 867 { 868 ::rtl::OUString aCommandURL; 869 ::rtl::OUString aLabel; 870 ::rtl::OUString aHelpURL; 871 sal_Int16 nType( ::com::sun::star::ui::ItemType::DEFAULT ); 872 sal_Int16 nItemBits( 0 ); 873 Reference< XIndexAccess > xSubMenu; 874 875 ExtractMenuParameters( aProps, aCommandURL, aLabel, aHelpURL, xSubMenu, nType, nItemBits ); 876 if ( xSubMenu.is() ) 877 { 878 if ( aCommandURL.equalsAscii( ADDDIRECT_CMD ) || 879 aCommandURL.equalsAscii( AUTOPILOTMENU_CMD )) 880 { 881 WriteMenuItem( aCommandURL, aLabel, aHelpURL, nItemBits ); 882 bSeparator = sal_False; 883 } 884 else if (( aCommandURL.getLength() > 0 ) && !AddonPopupMenu::IsCommandURLPrefix ( aCommandURL )) 885 { 886 ::comphelper::AttributeList* pListMenu = new ::comphelper::AttributeList; 887 Reference< XAttributeList > xListMenu( (XAttributeList *)pListMenu , UNO_QUERY ); 888 889 pListMenu->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_ID )), 890 m_aAttributeType, 891 aCommandURL ); 892 893 if ( !( aCommandURL.copy( CMD_PROTOCOL_SIZE ).equalsAscii( CMD_PROTOCOL ))) 894 pListMenu->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_LABEL )), 895 m_aAttributeType, 896 aLabel ); 897 898 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 899 m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENU )), xListMenu ); 900 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 901 m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUPOPUP )), m_xEmptyList ); 902 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 903 904 WriteMenu( xSubMenu ); 905 906 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 907 m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUPOPUP )) ); 908 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 909 m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENU )) ); 910 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 911 bSeparator = sal_False; 912 } 913 } 914 else 915 { 916 if ( nType == ::com::sun::star::ui::ItemType::DEFAULT ) 917 { 918 if ( aCommandURL.getLength() > 0 ) 919 { 920 bSeparator = sal_False; 921 WriteMenuItem( aCommandURL, aLabel, aHelpURL, nItemBits ); 922 } 923 } 924 else if ( !bSeparator ) 925 { 926 // Don't write two separators together 927 WriteMenuSeparator(); 928 bSeparator = sal_True; 929 } 930 } 931 } 932 } 933 } 934 935 936 void OWriteMenuDocumentHandler::WriteMenuItem( const ::rtl::OUString& aCommandURL, const ::rtl::OUString& aLabel, const ::rtl::OUString& aHelpURL, sal_Int16 nStyle ) 937 { 938 ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; 939 Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY ); 940 941 pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_ID )), 942 m_aAttributeType, 943 aCommandURL ); 944 945 if ( aHelpURL.getLength() > 0 ) 946 { 947 pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_HELPID )), 948 m_aAttributeType, 949 aHelpURL ); 950 } 951 952 if (( aLabel.getLength() > 0 ) && !( aCommandURL.copy( CMD_PROTOCOL_SIZE ).equalsAscii( CMD_PROTOCOL ))) 953 { 954 pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_LABEL )), 955 m_aAttributeType, 956 aLabel ); 957 } 958 if (( nStyle > 0 ) && !( aCommandURL.copy( CMD_PROTOCOL_SIZE ).equalsAscii( CMD_PROTOCOL ))) 959 { 960 rtl::OUString aValue; 961 MenuStyleItem* pStyle = MenuItemStyles; 962 963 for ( sal_Int32 nIndex = 0; nIndex < nMenuStyleItemEntries; ++nIndex, ++pStyle ) 964 { 965 if ( nStyle & pStyle->nBit ) 966 { 967 if ( aValue.getLength() ) 968 aValue = aValue.concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("+") ) ); 969 aValue += rtl::OUString::createFromAscii( pStyle->attrName ); 970 } 971 } 972 pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_STYLE )), 973 m_aAttributeType, 974 aValue ); 975 } 976 977 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 978 m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUITEM )), xList ); 979 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 980 m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUITEM )) ); 981 } 982 983 984 void OWriteMenuDocumentHandler::WriteMenuSeparator() 985 { 986 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 987 m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUSEPARATOR )), m_xEmptyList ); 988 m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() ); 989 m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUSEPARATOR )) ); 990 } 991 992 } // namespace framework 993