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_extensions.hxx"
26 #include "pushbuttonnavigation.hxx"
27 #include <com/sun/star/form/FormButtonType.hpp>
28 #include <com/sun/star/beans/XPropertyState.hpp>
29 #include "formstrings.hxx"
30 #include <comphelper/extract.hxx>
31 #include <comphelper/property.hxx>
32 #include <osl/diagnose.h>
33 #include <tools/diagnose_ex.h>
34 
35 //............................................................................
36 namespace pcr
37 {
38 //............................................................................
39 
40     using namespace ::com::sun::star::uno;
41     using namespace ::com::sun::star::beans;
42     using namespace ::com::sun::star::form;
43 
44     //------------------------------------------------------------------------
45     namespace
46     {
47         static const sal_Int32 s_nFirstVirtualButtonType = 1 + (sal_Int32)FormButtonType_URL;
48 
49         static const sal_Char* pNavigationURLs[] =
50         {
51 	        ".uno:FormController/moveToFirst",
52 	        ".uno:FormController/moveToPrev",
53 	        ".uno:FormController/moveToNext",
54 	        ".uno:FormController/moveToLast",
55 	        ".uno:FormController/saveRecord",
56 	        ".uno:FormController/undoRecord",
57 	        ".uno:FormController/moveToNew",
58 	        ".uno:FormController/deleteRecord",
59 	        ".uno:FormController/refreshForm",
60             NULL
61         };
62 
lcl_getNavigationURLIndex(const::rtl::OUString & _rNavURL)63         static sal_Int32 lcl_getNavigationURLIndex( const ::rtl::OUString& _rNavURL )
64         {
65             const sal_Char** pLookup = pNavigationURLs;
66             while ( *pLookup )
67             {
68                 if ( _rNavURL.equalsAscii( *pLookup ) )
69                     return pLookup - pNavigationURLs;
70                 ++pLookup;
71             }
72             return -1;
73         }
74 
lcl_getNavigationURL(sal_Int32 _nButtonTypeIndex)75         static const sal_Char* lcl_getNavigationURL( sal_Int32 _nButtonTypeIndex )
76         {
77             const sal_Char** pLookup = pNavigationURLs;
78             while ( _nButtonTypeIndex-- && *pLookup++ )
79                 ;
80             OSL_ENSURE( *pLookup, "lcl_getNavigationURL: invalid index!" );
81             return *pLookup;
82         }
83     }
84 
85     //========================================================================
86     //= PushButtonNavigation
87     //========================================================================
88     //------------------------------------------------------------------------
PushButtonNavigation(const Reference<XPropertySet> & _rxControlModel)89     PushButtonNavigation::PushButtonNavigation( const Reference< XPropertySet >& _rxControlModel )
90         :m_xControlModel( _rxControlModel )
91         ,m_bIsPushButton( sal_False )
92     {
93         OSL_ENSURE( m_xControlModel.is(), "PushButtonNavigation::PushButtonNavigation: invalid control model!" );
94 
95         try
96         {
97 			m_bIsPushButton = ::comphelper::hasProperty( PROPERTY_BUTTONTYPE, m_xControlModel );
98         }
99         catch( const Exception& )
100         {
101             OSL_ENSURE( sal_False, "PushButtonNavigation::PushButtonNavigation: caught an exception!" );
102         }
103     }
104 
105     //------------------------------------------------------------------------
implGetCurrentButtonType() const106     sal_Int32 PushButtonNavigation::implGetCurrentButtonType() const SAL_THROW((Exception))
107     {
108         sal_Int32 nButtonType = FormButtonType_PUSH;
109         if ( !m_xControlModel.is() )
110             return nButtonType;
111         OSL_VERIFY( ::cppu::enum2int( nButtonType, m_xControlModel->getPropertyValue( PROPERTY_BUTTONTYPE ) ) );
112 
113         if ( nButtonType == FormButtonType_URL )
114         {
115             // there's a chance that this is a "virtual" button type
116             // (which are realized by special URLs)
117             ::rtl::OUString sTargetURL;
118             m_xControlModel->getPropertyValue( PROPERTY_TARGET_URL ) >>= sTargetURL;
119 
120             sal_Int32 nNavigationURLIndex = lcl_getNavigationURLIndex( sTargetURL );
121             if ( nNavigationURLIndex >= 0)
122                 // it actually *is* a virtual button type
123                 nButtonType = s_nFirstVirtualButtonType + nNavigationURLIndex;
124         }
125         return nButtonType;
126     }
127 
128     //------------------------------------------------------------------------
getCurrentButtonType() const129     Any PushButtonNavigation::getCurrentButtonType() const SAL_THROW(())
130     {
131         OSL_ENSURE( m_bIsPushButton, "PushButtonNavigation::getCurrentButtonType: not expected to be called for forms!" );
132         Any aReturn;
133 
134         try
135         {
136             aReturn <<= implGetCurrentButtonType();
137         }
138         catch( const Exception& )
139         {
140             OSL_ENSURE( sal_False, "PushButtonNavigation::getCurrentButtonType: caught an exception!" );
141         }
142         return aReturn;
143     }
144 
145     //------------------------------------------------------------------------
setCurrentButtonType(const Any & _rValue) const146     void PushButtonNavigation::setCurrentButtonType( const Any& _rValue ) const SAL_THROW(())
147     {
148         OSL_ENSURE( m_bIsPushButton, "PushButtonNavigation::setCurrentButtonType: not expected to be called for forms!" );
149         if ( !m_xControlModel.is() )
150             return;
151 
152         try
153         {
154             sal_Int32 nButtonType = FormButtonType_PUSH;
155             OSL_VERIFY( ::cppu::enum2int( nButtonType, _rValue ) );
156             ::rtl::OUString sTargetURL;
157 
158             bool bIsVirtualButtonType = nButtonType >= s_nFirstVirtualButtonType;
159             if ( bIsVirtualButtonType )
160             {
161                 const sal_Char* pURL = lcl_getNavigationURL( nButtonType - s_nFirstVirtualButtonType );
162                 sTargetURL = ::rtl::OUString::createFromAscii( pURL );
163 
164                 nButtonType = FormButtonType_URL;
165             }
166 
167             m_xControlModel->setPropertyValue( PROPERTY_BUTTONTYPE, makeAny( static_cast< FormButtonType >( nButtonType ) ) );
168             m_xControlModel->setPropertyValue( PROPERTY_TARGET_URL, makeAny( sTargetURL ) );
169         }
170         catch( const Exception& )
171         {
172             OSL_ENSURE( sal_False, "PushButtonNavigation::setCurrentButtonType: caught an exception!" );
173         }
174     }
175 
176     //------------------------------------------------------------------------
getCurrentButtonTypeState() const177     PropertyState PushButtonNavigation::getCurrentButtonTypeState( ) const SAL_THROW(())
178     {
179         OSL_ENSURE( m_bIsPushButton, "PushButtonNavigation::getCurrentButtonTypeState: not expected to be called for forms!" );
180         PropertyState eState = PropertyState_DIRECT_VALUE;
181 
182         try
183         {
184             Reference< XPropertyState > xStateAccess( m_xControlModel, UNO_QUERY );
185             if ( xStateAccess.is() )
186             {
187                 // let's see what the model says about the ButtonType property
188                 eState = xStateAccess->getPropertyState( PROPERTY_BUTTONTYPE );
189                 if ( eState == PropertyState_DIRECT_VALUE )
190                 {
191                     sal_Int32 nRealButtonType = FormButtonType_PUSH;
192                     OSL_VERIFY( ::cppu::enum2int( nRealButtonType, m_xControlModel->getPropertyValue( PROPERTY_BUTTONTYPE ) ) );
193                     // perhaps it's one of the virtual button types?
194                     if ( FormButtonType_URL == nRealButtonType )
195                     {
196                         // yes, it is -> rely on the state of the URL property
197                         eState = xStateAccess->getPropertyState( PROPERTY_TARGET_URL );
198                     }
199                 }
200             }
201         }
202         catch( const Exception& )
203         {
204             OSL_ENSURE( sal_False, "PushButtonNavigation::getCurrentButtonTypeState: caught an exception!" );
205         }
206 
207         return eState;
208     }
209 
210     //------------------------------------------------------------------------
getCurrentTargetURL() const211     Any PushButtonNavigation::getCurrentTargetURL() const SAL_THROW(())
212     {
213         Any aReturn;
214         if ( !m_xControlModel.is() )
215             return aReturn;
216 
217         try
218         {
219             aReturn = m_xControlModel->getPropertyValue( PROPERTY_TARGET_URL );
220             if ( m_bIsPushButton )
221             {
222                 sal_Int32 nCurrentButtonType = implGetCurrentButtonType();
223                 bool bIsVirtualButtonType = nCurrentButtonType >= s_nFirstVirtualButtonType;
224                 if ( bIsVirtualButtonType )
225                 {
226                     // pretend (to the user) that there's no URL set - since
227                     // virtual button types imply a special (technical) URL which
228                     // the user should not see
229                     aReturn <<= ::rtl::OUString();
230                 }
231             }
232         }
233         catch( const Exception& )
234         {
235             OSL_ENSURE( sal_False, "PushButtonNavigation::getCurrentTargetURL: caught an exception!" );
236         }
237         return aReturn;
238     }
239 
240     //------------------------------------------------------------------------
setCurrentTargetURL(const Any & _rValue) const241     void PushButtonNavigation::setCurrentTargetURL( const Any& _rValue ) const SAL_THROW(())
242     {
243         if ( !m_xControlModel.is() )
244             return;
245 
246         try
247         {
248             m_xControlModel->setPropertyValue( PROPERTY_TARGET_URL, _rValue );
249         }
250         catch( const Exception& )
251         {
252             OSL_ENSURE( sal_False, "PushButtonNavigation::setCurrentTargetURL: caught an exception!" );
253         }
254     }
255 
256     //------------------------------------------------------------------------
getCurrentTargetURLState() const257     PropertyState PushButtonNavigation::getCurrentTargetURLState( ) const SAL_THROW(())
258     {
259         PropertyState eState = PropertyState_DIRECT_VALUE;
260 
261         try
262         {
263             Reference< XPropertyState > xStateAccess( m_xControlModel, UNO_QUERY );
264             if ( xStateAccess.is() )
265             {
266                 eState = xStateAccess->getPropertyState( PROPERTY_TARGET_URL );
267             }
268         }
269         catch( const Exception& )
270         {
271             OSL_ENSURE( sal_False, "PushButtonNavigation::setCurrentTargetURL: caught an exception!" );
272         }
273 
274         return eState;
275     }
276 
277     //------------------------------------------------------------------------
currentButtonTypeIsOpenURL() const278     bool PushButtonNavigation::currentButtonTypeIsOpenURL() const
279     {
280         sal_Int32 nButtonType( FormButtonType_PUSH );
281         try
282         {
283             nButtonType = implGetCurrentButtonType();
284         }
285         catch( const Exception& )
286         {
287         	DBG_UNHANDLED_EXCEPTION();
288         }
289         return nButtonType == FormButtonType_URL;
290     }
291 
292     //------------------------------------------------------------------------
hasNonEmptyCurrentTargetURL() const293     bool PushButtonNavigation::hasNonEmptyCurrentTargetURL() const
294     {
295         ::rtl::OUString sTargetURL;
296         OSL_VERIFY( getCurrentTargetURL() >>= sTargetURL );
297         return sTargetURL.getLength() != 0;
298     }
299 
300 //............................................................................
301 }   // namespace pcr
302 //............................................................................
303