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