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