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 #include "import.hxx" 29 30 #include <com/sun/star/awt/XButton.hpp> 31 #include <com/sun/star/awt/XDialog2.hpp> 32 #include <vcl/image.hxx> 33 #include <tools/debug.hxx> 34 #include <layout/layout.hxx> 35 36 #include "root.hxx" 37 #include "helper.hxx" 38 #include "dialogbuttonhbox.hxx" 39 40 41 #define XMLNS_LAYOUT_URI "http://openoffice.org/2007/layout" 42 #define XMLNS_CONTAINER_URI "http://openoffice.org/2007/layout/container" 43 44 namespace layoutimpl 45 { 46 using namespace css; 47 48 using ::rtl::OUString; 49 50 ElementBase::~ElementBase() 51 SAL_THROW( () ) 52 { 53 //delete mpImport; 54 //mpImport = 0; 55 } 56 57 //** parser 58 WidgetElement::WidgetElement ( sal_Int32 nUid, const OUString &rName, 59 uno::Reference <xml::input::XAttributes> const &attributes, 60 ElementBase *pParent, 61 ImportContext *pImport) 62 SAL_THROW (()) 63 : ElementBase( nUid, rName, attributes, pParent, pImport ) 64 { 65 OUString name = rName.toAsciiLowerCase(); 66 67 PropList aProps; 68 propsFromAttributes( attributes, aProps, pImport->XMLNS_LAYOUT_UID ); 69 70 OUString aId; 71 findAndRemove( "id", aProps, aId ); 72 OUString aLang; 73 findAndRemove( "xml-lang", aProps, aLang ); 74 75 { 76 //DEBUG 77 uno::Reference< awt::XLayoutConstrains > xParent; 78 if ( pParent ) 79 xParent = ((WidgetElement *) pParent)->mpWidget->getPeer(); 80 81 82 mpWidget = pImport->mrRoot.create( aId, name, 83 getAttributeProps( aProps ), uno::Reference< awt::XLayoutContainer >( xParent, uno::UNO_QUERY ) ); 84 85 } 86 87 // TODO: handle with non-existing widgets 88 89 mpWidget->setProperties( aProps ); 90 91 uno::Reference< awt::XDialog2 > xDialog( mpWidget->getPeer(), uno::UNO_QUERY ); 92 if ( xDialog.is() ) 93 { 94 OUString aTitle; 95 if ( findAndRemove( "title", aProps, aTitle ) ) 96 { 97 OSL_TRACE("Setting title: %s", OUSTRING_CSTR( aTitle ) ); 98 xDialog->setTitle( aTitle ); 99 } 100 OUString aHelpId; 101 if ( findAndRemove( "help-id", aProps, aHelpId ) ) 102 { 103 OSL_TRACE("Setting help-id: %s", OUSTRING_CSTR( aHelpId ) ); 104 xDialog->setHelpId( aHelpId ); 105 } 106 } // DEBUG: 107 else if ( pParent == NULL ) 108 { 109 DBG_ERROR( "Fatal error: top node isn't a dialog" ); 110 } 111 112 OUString aOrdering; 113 if ( findAndRemove( "ordering", aProps, aOrdering ) ) 114 if ( DialogButtonHBox *b = dynamic_cast<DialogButtonHBox *> ( mpWidget->getPeer().get() ) ) 115 b->setOrdering ( aOrdering ); 116 117 bool bSetRadioGroup; 118 OUString aRadioGroup; 119 bSetRadioGroup = findAndRemove( "radiogroup", aProps, aRadioGroup ); 120 121 mpWidget->setProperties( aProps ); 122 123 // we need to add radio buttons to the group after their properties are 124 // set, so we can check if they should be the one selected by default or not. 125 // And the state changed event isn't fired when changing properties. 126 127 uno::Reference< awt::XRadioButton > xRadio( mpWidget->getPeer(), uno::UNO_QUERY ); 128 if ( xRadio.is() ) 129 { 130 if (!bSetRadioGroup) 131 aRadioGroup = OUString::createFromAscii ("default"); 132 pImport->mxRadioGroups.addItem( aRadioGroup, xRadio ); 133 } 134 } 135 136 WidgetElement::~WidgetElement() 137 { 138 //delete mpWidget; 139 //mpWidget = 0; 140 } 141 142 uno::Reference <xml::input::XElement> 143 WidgetElement::startChildElement ( sal_Int32 nUid, OUString const &name, 144 uno::Reference <xml::input::XAttributes> const &attributes ) 145 throw( xml::sax::SAXException, uno::RuntimeException ) 146 { 147 // Adding a child to the widget 148 WidgetElement *pChild = new WidgetElement ( nUid, name, attributes, this, mpImport ); 149 150 if ( !mpWidget->addChild( pChild->mpWidget ) ) 151 { 152 DBG_ERROR2( "ERROR: cannot add %s to container %s, container full", OUSTRING_CSTR( name ), OUSTRING_CSTR( getLocalName() ) ); 153 throw xml::sax::SAXException(); 154 } 155 156 PropList aProps; 157 propsFromAttributes( attributes, aProps, mpImport->XMLNS_CONTAINER_UID ); 158 mpWidget->setChildProperties( pChild->mpWidget, aProps ); 159 160 return pChild; 161 } 162 163 // Support Ivo Hinkelmann's move label/text/title attribute to CONTENT 164 // transex3 hack. 165 void SAL_CALL 166 WidgetElement::characters( OUString const& rChars ) 167 throw (xml::sax::SAXException, uno::RuntimeException) 168 { 169 if ( mpWidget && rChars.trim().getLength() ) 170 { 171 uno::Reference< awt::XDialog2 > xDialog( mpWidget->getPeer(), uno::UNO_QUERY ); 172 uno::Reference< awt::XButton > xButton( mpWidget->getPeer(), uno::UNO_QUERY ); 173 if ( xDialog.is() ) 174 xDialog->setTitle( rChars ); 175 else if ( xButton.is() ) 176 mpWidget->setProperty( OUString::createFromAscii( "label" ), rChars ); 177 else 178 mpWidget->setProperty( OUString::createFromAscii( "text" ), rChars ); 179 } 180 } 181 // ---- ElementBase ---- 182 183 ElementBase::ElementBase( sal_Int32 nUid, OUString const & rLocalName, 184 uno::Reference< xml::input::XAttributes > const & xAttributes, 185 ElementBase* pParent, 186 ImportContext* pImport ) 187 SAL_THROW(()) 188 : mpImport( pImport ) 189 , mpParent( pParent ) 190 , mnUid( nUid ) 191 , maLocalName( rLocalName ) 192 , mxAttributes( xAttributes ) 193 { 194 } 195 196 // ---- ImportContext ---- 197 198 void ImportContext::startDocument( 199 uno::Reference< xml::input::XNamespaceMapping > const & xNamespaceMapping ) 200 throw (xml::sax::SAXException, uno::RuntimeException) 201 { 202 XMLNS_LAYOUT_UID = xNamespaceMapping->getUidByUri( 203 OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_LAYOUT_URI ) ) ); 204 XMLNS_CONTAINER_UID = xNamespaceMapping->getUidByUri( 205 OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_CONTAINER_URI ) ) ); 206 } 207 208 ToplevelElement::ToplevelElement (OUString const &rName, 209 uno::Reference <xml::input::XAttributes> const &xAttributes, 210 ImportContext *pImport) 211 SAL_THROW(()) 212 : WidgetElement( 0, rName, xAttributes, NULL, pImport ) 213 { 214 } 215 216 ToplevelElement::~ToplevelElement() 217 { 218 } 219 220 uno::Reference< xml::input::XElement > ImportContext::startRootElement( 221 sal_Int32 nUid, OUString const & rLocalName, 222 uno::Reference< xml::input::XAttributes > const & xAttributes ) 223 throw (xml::sax::SAXException, uno::RuntimeException) 224 { 225 if ( XMLNS_LAYOUT_UID != nUid ) 226 throw xml::sax::SAXException( 227 OUString( RTL_CONSTASCII_USTRINGPARAM( "invalid namespace!" ) ), 228 uno::Reference< uno::XInterface >(), uno::Any() ); 229 return new ToplevelElement( rLocalName, xAttributes, this ); 230 } 231 232 RadioGroups::RadioGroups() 233 { 234 } 235 236 void RadioGroups::addItem( rtl::OUString id, uno::Reference< awt::XRadioButton > xRadio ) 237 throw (uno::RuntimeException) 238 { 239 if ( ! xRadio.is() ) 240 throw uno::RuntimeException(); 241 242 uno::Reference< RadioGroup > group; 243 RadioGroupsMap::iterator it = mxRadioGroups.find( id ); 244 if ( it == mxRadioGroups.end() ) 245 { 246 group = uno::Reference< RadioGroup > ( new RadioGroup() ); 247 mxRadioGroups [id] = group; 248 } 249 else 250 group = it->second; 251 group->addItem( xRadio ); 252 } 253 254 RadioGroups::RadioGroup::RadioGroup() 255 { 256 } 257 258 void RadioGroups::RadioGroup::addItem( uno::Reference< awt::XRadioButton > xRadio ) 259 { 260 if ( ! mxSelectedRadio.is() ) 261 { 262 xRadio->setState( true ); 263 mxSelectedRadio = xRadio; 264 } 265 else if ( xRadio->getState() ) 266 { 267 #if 1 268 xRadio->setState( false ); 269 #else // huh, why select last added? 270 mxSelectedRadio->setState( false ); 271 mxSelectedRadio = xRadio; 272 #endif 273 } 274 275 // TOO late: actionPerformed is called before itemStateChanged. 276 // If client code (wrongly?) uses actionPerformed, it will see 277 // the previous RadioButtons' state. 278 xRadio->addItemListener( this ); 279 280 uno::Reference< awt::XButton > xButton = uno::Reference< awt::XButton > ( xRadio, uno::UNO_QUERY ); 281 xButton->addActionListener( this ); 282 283 mxRadios.push_back (xRadio); 284 } 285 286 void RadioGroups::RadioGroup::handleSelected () 287 throw (uno::RuntimeException) 288 { 289 for ( RadioButtonsList::iterator it = mxRadios.begin(); 290 it != mxRadios.end(); it++ ) 291 if ( *it != mxSelectedRadio && (*it)->getState() ) 292 { 293 mxSelectedRadio->setState( false ); 294 mxSelectedRadio = *it; 295 break; 296 } 297 } 298 299 // awt::XItemListener 300 void RadioGroups::RadioGroup::itemStateChanged( const awt::ItemEvent& e ) 301 throw (uno::RuntimeException) 302 { 303 // TOO late: actionPerformed is called before itemStateChanged. 304 // If client code (wrongly?) uses actionPerformed, it will see 305 // the previous RadioButtons' state. 306 307 // Need this for initialization, though. 308 if ( e.Selected ) 309 handleSelected (); 310 } 311 312 // awt::XActionListener 313 void RadioGroups::RadioGroup::actionPerformed( const awt::ActionEvent& ) 314 throw (uno::RuntimeException) 315 { 316 handleSelected (); 317 } 318 319 // lang::XEventListener 320 void SAL_CALL RadioGroups::RadioGroup::disposing( const lang::EventObject& ) 321 throw (uno::RuntimeException) 322 { 323 } 324 325 } // namespace layoutimpl 326