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 
~ElementBase()46 ElementBase::~ElementBase()
47 SAL_THROW( () )
48 {
49     //delete mpImport;
50     //mpImport = 0;
51 }
52 
53 //** parser
WidgetElement(sal_Int32 nUid,const OUString & rName,uno::Reference<xml::input::XAttributes> const & attributes,ElementBase * pParent,ImportContext * pImport)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 
~WidgetElement()132 WidgetElement::~WidgetElement()
133 {
134     //delete mpWidget;
135     //mpWidget = 0;
136 }
137 
138 uno::Reference <xml::input::XElement>
startChildElement(sal_Int32 nUid,OUString const & name,uno::Reference<xml::input::XAttributes> const & attributes)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
characters(OUString const & rChars)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 
ElementBase(sal_Int32 nUid,OUString const & rLocalName,uno::Reference<xml::input::XAttributes> const & xAttributes,ElementBase * pParent,ImportContext * pImport)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 
startDocument(uno::Reference<xml::input::XNamespaceMapping> const & xNamespaceMapping)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 
ToplevelElement(OUString const & rName,uno::Reference<xml::input::XAttributes> const & xAttributes,ImportContext * pImport)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 
~ToplevelElement()212 ToplevelElement::~ToplevelElement()
213 {
214 }
215 
startRootElement(sal_Int32 nUid,OUString const & rLocalName,uno::Reference<xml::input::XAttributes> const & xAttributes)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 
RadioGroups()228 RadioGroups::RadioGroups()
229 {
230 }
231 
addItem(rtl::OUString id,uno::Reference<awt::XRadioButton> xRadio)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 
RadioGroup()250 RadioGroups::RadioGroup::RadioGroup()
251 {
252 }
253 
addItem(uno::Reference<awt::XRadioButton> xRadio)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 
handleSelected()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
itemStateChanged(const awt::ItemEvent & e)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
actionPerformed(const awt::ActionEvent &)309 void RadioGroups::RadioGroup::actionPerformed( const awt::ActionEvent& )
310     throw (uno::RuntimeException)
311 {
312     handleSelected ();
313 }
314 
315 // lang::XEventListener
disposing(const lang::EventObject &)316 void SAL_CALL RadioGroups::RadioGroup::disposing( const lang::EventObject& )
317     throw (uno::RuntimeException)
318 {
319 }
320 
321 } // namespace layoutimpl
322