xref: /AOO41X/main/framework/source/uielement/spinfieldtoolbarcontroller.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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_framework.hxx"
30 
31 #include <stdio.h>
32 #include <wchar.h>
33 
34 #ifndef __FRAMEWORK_UIELEMENT_SPINFIELDTOOLBARCONTROLLER_HXX
35 #include "uielement/spinfieldtoolbarcontroller.hxx"
36 #endif
37 
38 //_________________________________________________________________________________________________________________
39 //	my own includes
40 //_________________________________________________________________________________________________________________
41 
42 #ifndef __FRAMEWORK_TOOLBAR_HXX_
43 #include "uielement/toolbar.hxx"
44 #endif
45 
46 //_________________________________________________________________________________________________________________
47 //	interface includes
48 //_________________________________________________________________________________________________________________
49 #include <com/sun/star/util/XURLTransformer.hpp>
50 #include <com/sun/star/frame/XDispatchProvider.hpp>
51 #include <com/sun/star/beans/PropertyValue.hpp>
52 #include <com/sun/star/frame/status/ItemStatus.hpp>
53 #include <com/sun/star/frame/status/ItemState.hpp>
54 #include <com/sun/star/frame/status/Visibility.hpp>
55 #include <com/sun/star/frame/XControlNotificationListener.hpp>
56 
57 //_________________________________________________________________________________________________________________
58 //	other includes
59 //_________________________________________________________________________________________________________________
60 #include <svtools/toolboxcontroller.hxx>
61 #include <vos/mutex.hxx>
62 #include <vcl/svapp.hxx>
63 #ifndef _VCL_MNEMONIC_HXX_
64 #include <vcl/mnemonic.hxx>
65 #endif
66 #include <tools/urlobj.hxx>
67 #ifdef WINNT
68 #include <systools/win32/snprintf.h>
69 #endif
70 
71 using namespace ::com::sun::star;
72 using namespace ::com::sun::star::uno;
73 using namespace ::com::sun::star::beans;
74 using namespace ::com::sun::star::lang;
75 using namespace ::com::sun::star::frame;
76 using namespace ::com::sun::star::frame::status;
77 using namespace ::com::sun::star::util;
78 
79 namespace framework
80 {
81 
82 // ------------------------------------------------------------------
83 
84 // Wrapper class to notify controller about events from combobox.
85 // Unfortunaltly the events are notifed through virtual methods instead
86 // of Listeners.
87 
88 class SpinfieldControl : public SpinField
89 {
90     public:
91         SpinfieldControl( Window* pParent, WinBits nStyle, ISpinfieldListener* pSpinFieldListener );
92         virtual ~SpinfieldControl();
93 
94 	    virtual void Up();
95 	    virtual void Down();
96 	    virtual void First();
97 	    virtual void Last();
98         virtual void KeyInput( const ::KeyEvent& rKEvt );
99 	    virtual void Modify();
100 	    virtual void GetFocus();
101 	    virtual void LoseFocus();
102 	    virtual void StateChanged( StateChangedType nType );
103 	    virtual void DataChanged( const DataChangedEvent& rDCEvt );
104         virtual long PreNotify( NotifyEvent& rNEvt );
105 
106     private:
107         ISpinfieldListener* m_pSpinFieldListener;
108 };
109 
110 SpinfieldControl::SpinfieldControl( Window* pParent, WinBits nStyle, ISpinfieldListener* pSpinFieldListener ) :
111     SpinField( pParent, nStyle )
112     , m_pSpinFieldListener( pSpinFieldListener )
113 {
114 }
115 
116 SpinfieldControl::~SpinfieldControl()
117 {
118     m_pSpinFieldListener = 0;
119 }
120 
121 void SpinfieldControl::Up()
122 {
123     SpinField::Up();
124     if ( m_pSpinFieldListener )
125         m_pSpinFieldListener->Up();
126 }
127 
128 void SpinfieldControl::Down()
129 {
130     SpinField::Down();
131     if ( m_pSpinFieldListener )
132         m_pSpinFieldListener->Down();
133 }
134 
135 void SpinfieldControl::First()
136 {
137     SpinField::First();
138     if ( m_pSpinFieldListener )
139         m_pSpinFieldListener->First();
140 }
141 
142 void SpinfieldControl::Last()
143 {
144     SpinField::First();
145     if ( m_pSpinFieldListener )
146         m_pSpinFieldListener->Last();
147 }
148 
149 void SpinfieldControl::KeyInput( const ::KeyEvent& rKEvt )
150 {
151     SpinField::KeyInput( rKEvt );
152     if ( m_pSpinFieldListener )
153         m_pSpinFieldListener->KeyInput( rKEvt );
154 }
155 
156 void SpinfieldControl::Modify()
157 {
158     SpinField::Modify();
159     if ( m_pSpinFieldListener )
160         m_pSpinFieldListener->Modify();
161 }
162 
163 void SpinfieldControl::GetFocus()
164 {
165     SpinField::GetFocus();
166     if ( m_pSpinFieldListener )
167         m_pSpinFieldListener->GetFocus();
168 }
169 
170 void SpinfieldControl::LoseFocus()
171 {
172     SpinField::GetFocus();
173     if ( m_pSpinFieldListener )
174         m_pSpinFieldListener->GetFocus();
175 }
176 
177 void SpinfieldControl::StateChanged( StateChangedType nType )
178 {
179     SpinField::StateChanged( nType );
180     if ( m_pSpinFieldListener )
181         m_pSpinFieldListener->StateChanged( nType );
182 }
183 
184 void SpinfieldControl::DataChanged( const DataChangedEvent& rDCEvt )
185 {
186     SpinField::DataChanged( rDCEvt );
187     if ( m_pSpinFieldListener )
188         m_pSpinFieldListener->DataChanged( rDCEvt );
189 }
190 
191 long SpinfieldControl::PreNotify( NotifyEvent& rNEvt )
192 {
193     long nRet( 0 );
194     if ( m_pSpinFieldListener )
195         nRet = m_pSpinFieldListener->PreNotify( rNEvt );
196     if ( nRet == 0 )
197         nRet = SpinField::PreNotify( rNEvt );
198 
199     return nRet;
200 }
201 
202 // ------------------------------------------------------------------
203 
204 SpinfieldToolbarController::SpinfieldToolbarController(
205     const Reference< XMultiServiceFactory >& rServiceManager,
206     const Reference< XFrame >&               rFrame,
207     ToolBox*                                 pToolbar,
208     sal_uInt16                                   nID,
209     sal_Int32                                nWidth,
210     const ::rtl::OUString&                          aCommand ) :
211     ComplexToolbarController( rServiceManager, rFrame, pToolbar, nID, aCommand )
212     ,   m_bFloat( false )
213     ,   m_bMaxSet( false )
214     ,   m_bMinSet( false )
215     ,   m_nMax( 0.0 )
216     ,   m_nMin( 0.0 )
217     ,   m_nValue( 0.0 )
218     ,   m_nStep( 0.0 )
219     ,   m_pSpinfieldControl( 0 )
220 {
221     m_pSpinfieldControl = new SpinfieldControl( m_pToolbar, WB_SPIN|WB_BORDER, this );
222     if ( nWidth == 0 )
223         nWidth = 100;
224 
225     // Calculate height of the spin field according to the application font height
226     sal_Int32 nHeight = getFontSizePixel( m_pSpinfieldControl ) + 5 + 1;
227 
228     m_pSpinfieldControl->SetSizePixel( ::Size( nWidth, nHeight ));
229     m_pToolbar->SetItemWindow( m_nID, m_pSpinfieldControl );
230 }
231 
232 // ------------------------------------------------------------------
233 
234 SpinfieldToolbarController::~SpinfieldToolbarController()
235 {
236 }
237 
238 // ------------------------------------------------------------------
239 
240 void SAL_CALL SpinfieldToolbarController::dispose()
241 throw ( RuntimeException )
242 {
243     vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
244 
245     m_pToolbar->SetItemWindow( m_nID, 0 );
246     delete m_pSpinfieldControl;
247 
248     ComplexToolbarController::dispose();
249 
250     m_pSpinfieldControl = 0;
251 }
252 
253 // ------------------------------------------------------------------
254 Sequence<PropertyValue> SpinfieldToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const
255 {
256     Sequence<PropertyValue> aArgs( 2 );
257     ::rtl::OUString aSpinfieldText = m_pSpinfieldControl->GetText();
258 
259     // Add key modifier to argument list
260     aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" ));
261     aArgs[0].Value <<= KeyModifier;
262     aArgs[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Value" ));
263     if ( m_bFloat )
264         aArgs[1].Value <<= aSpinfieldText.toDouble();
265     else
266         aArgs[1].Value <<= aSpinfieldText.toInt32();
267     return aArgs;
268 }
269 
270 // ------------------------------------------------------------------
271 
272 void SpinfieldToolbarController::Up()
273 {
274     double nValue = m_nValue + m_nStep;
275     if ( m_bMaxSet && nValue > m_nMax )
276         return;
277 
278     m_nValue = nValue;
279 
280     rtl::OUString aText = impl_formatOutputString( m_nValue );
281     m_pSpinfieldControl->SetText( aText );
282     execute( 0 );
283 }
284 
285 void SpinfieldToolbarController::Down()
286 {
287     double nValue = m_nValue - m_nStep;
288     if ( m_bMinSet && nValue < m_nMin )
289         return;
290 
291     m_nValue = nValue;
292 
293     rtl::OUString aText = impl_formatOutputString( m_nValue );
294     m_pSpinfieldControl->SetText( aText );
295     execute( 0 );
296 }
297 
298 void SpinfieldToolbarController::First()
299 {
300     if ( m_bMinSet )
301     {
302         m_nValue = m_nMin;
303 
304         rtl::OUString aText = impl_formatOutputString( m_nValue );
305         m_pSpinfieldControl->SetText( aText );
306         execute( 0 );
307     }
308 }
309 
310 void SpinfieldToolbarController::Last()
311 {
312     if ( m_bMaxSet )
313     {
314         m_nValue = m_nMax;
315 
316         rtl::OUString aText = impl_formatOutputString( m_nValue );
317         m_pSpinfieldControl->SetText( aText );
318         execute( 0 );
319     }
320 }
321 
322 void SpinfieldToolbarController::Modify()
323 {
324     notifyTextChanged( m_pSpinfieldControl->GetText() );
325 }
326 
327 void SpinfieldToolbarController::KeyInput( const ::KeyEvent& /*rKEvt*/ )
328 {
329 }
330 
331 void SpinfieldToolbarController::GetFocus()
332 {
333     notifyFocusGet();
334 }
335 
336 void SpinfieldToolbarController::LoseFocus()
337 {
338     notifyFocusLost();
339 }
340 
341 void SpinfieldToolbarController::StateChanged( StateChangedType /*nType*/ )
342 {
343 }
344 
345 void SpinfieldToolbarController::DataChanged( const DataChangedEvent& /*rDCEvt*/ )
346 {
347 }
348 
349 long SpinfieldToolbarController::PreNotify( NotifyEvent& rNEvt )
350 {
351     if( rNEvt.GetType() == EVENT_KEYINPUT )
352     {
353         const ::KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
354         const KeyCode& rKeyCode = pKeyEvent->GetKeyCode();
355         if(( rKeyCode.GetModifier() | rKeyCode.GetCode()) == KEY_RETURN )
356         {
357             // Call execute only with non-empty text
358             if ( m_pSpinfieldControl->GetText().Len() > 0 )
359                 execute( rKeyCode.GetModifier() );
360             return 1;
361         }
362     }
363 
364     return 0;
365 }
366 
367 // --------------------------------------------------------
368 
369 void SpinfieldToolbarController::executeControlCommand( const ::com::sun::star::frame::ControlCommand& rControlCommand )
370 {
371     rtl::OUString aValue;
372     rtl::OUString aMax;
373     rtl::OUString aMin;
374     rtl::OUString aStep;
375     bool          bFloatValue( false );
376 
377     if ( rControlCommand.Command.equalsAsciiL( "SetStep", 7 ))
378     {
379         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
380         {
381             sal_Int32   nValue;
382             double      fValue;
383             bool        bFloat( false );
384 
385             if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Step", 4 ))
386             {
387                 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
388                     aStep = bFloat ? ::rtl::OUString::valueOf( fValue ) :
389                                      ::rtl::OUString::valueOf( nValue );
390                 break;
391             }
392         }
393     }
394     else if ( rControlCommand.Command.equalsAsciiL( "SetValue", 8 ))
395     {
396         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
397         {
398             if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Value", 5 ))
399             {
400                 sal_Int32   nValue;
401                 double      fValue;
402                 bool        bFloat( false );
403 
404                 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
405                 {
406                     aValue = bFloat ? ::rtl::OUString::valueOf( fValue ) : ::rtl::OUString::valueOf( nValue );
407                     bFloatValue = bFloat;
408                 }
409                 break;
410             }
411         }
412     }
413     else if ( rControlCommand.Command.equalsAsciiL( "SetValues", 9 ))
414     {
415         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
416         {
417             sal_Int32   nValue;
418             double      fValue;
419             bool        bFloat( false );
420 
421             rtl::OUString aName = rControlCommand.Arguments[i].Name;
422             if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
423             {
424                 if ( aName.equalsAsciiL( "Value", 5 ))
425                 {
426                     aValue = bFloat ? ::rtl::OUString::valueOf( fValue ) : ::rtl::OUString::valueOf( nValue );
427                     bFloatValue = bFloat;
428                 }
429                 else if ( aName.equalsAsciiL( "Step", 4 ))
430                     aStep = bFloat ? ::rtl::OUString::valueOf( fValue ) :
431                                      ::rtl::OUString::valueOf( nValue );
432                 else if ( aName.equalsAsciiL( "LowerLimit", 10 ))
433                     aMin = bFloat ? ::rtl::OUString::valueOf( fValue ) :
434                                     ::rtl::OUString::valueOf( nValue );
435                 else if ( aName.equalsAsciiL( "UpperLimit", 10 ))
436                     aMax = bFloat ? ::rtl::OUString::valueOf( fValue ) :
437                                     ::rtl::OUString::valueOf( nValue );
438             }
439             else if ( aName.equalsAsciiL( "OutputFormat", 12 ))
440                 rControlCommand.Arguments[i].Value >>= m_aOutFormat;
441         }
442     }
443     else if ( rControlCommand.Command.equalsAsciiL( "SetLowerLimit", 13 ))
444     {
445         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
446         {
447             sal_Int32   nValue;
448             double      fValue;
449             bool        bFloat( false );
450 
451             if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "LowerLimit", 10 ))
452             {
453                 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
454                     aMin = bFloat ? ::rtl::OUString::valueOf( fValue ) :
455                                     ::rtl::OUString::valueOf( nValue );
456                 break;
457             }
458         }
459     }
460     else if ( rControlCommand.Command.equalsAsciiL( "SetUpperLimit", 13 ))
461     {
462         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
463         {
464             sal_Int32   nValue;
465             double      fValue;
466             bool        bFloat( false );
467 
468             if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "UpperLimit", 10 ))
469             {
470                 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
471                     aMax = bFloat ? ::rtl::OUString::valueOf( fValue ) :
472                                     ::rtl::OUString::valueOf( nValue );
473                 break;
474             }
475         }
476     }
477     else if ( rControlCommand.Command.equalsAsciiL( "SetOutputFormat", 15 ))
478     {
479         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
480         {
481             if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "OutputFormat", 10 ))
482             {
483                 rControlCommand.Arguments[i].Value >>= m_aOutFormat;
484                 break;
485             }
486         }
487     }
488 
489     // Check values and set members
490     if ( aValue.getLength() > 0 )
491     {
492         m_bFloat = bFloatValue;
493         m_nValue = aValue.toDouble();
494 
495         rtl::OUString aOutString = impl_formatOutputString( m_nValue );
496         m_pSpinfieldControl->SetText( aOutString );
497         notifyTextChanged( aOutString );
498     }
499     if ( aMax.getLength() > 0 )
500     {
501         m_nMax = aMax.toDouble();
502         m_bMaxSet = true;
503     }
504     if ( aMin.getLength() > 0 )
505     {
506         m_nMin = aMin.toDouble();
507         m_bMinSet = true;
508     }
509     if ( aStep.getLength() > 0 )
510         m_nStep = aStep.toDouble();
511 }
512 
513 bool SpinfieldToolbarController::impl_getValue(
514     const Any& rAny, sal_Int32& nValue, double& fValue, bool& bFloat )
515 {
516     using ::com::sun::star::uno::TypeClass;
517 
518     bool bValueValid( false );
519 
520     bFloat = false;
521     TypeClass aTypeClass = rAny.getValueTypeClass();
522     if (( aTypeClass == TypeClass( typelib_TypeClass_LONG  )) ||
523         ( aTypeClass == TypeClass( typelib_TypeClass_SHORT )) ||
524         ( aTypeClass == TypeClass( typelib_TypeClass_BYTE  )))
525         bValueValid = rAny >>= nValue;
526     else if (( aTypeClass == TypeClass( typelib_TypeClass_FLOAT  )) ||
527              ( aTypeClass == TypeClass( typelib_TypeClass_DOUBLE )))
528     {
529         bValueValid = rAny >>= fValue;
530         bFloat = true;
531     }
532 
533     return bValueValid;
534 }
535 
536 rtl::OUString SpinfieldToolbarController::impl_formatOutputString( double fValue )
537 {
538     if ( m_aOutFormat.getLength() == 0 )
539     {
540         if ( m_bFloat )
541             return rtl::OUString::valueOf( fValue );
542         else
543             return rtl::OUString::valueOf( sal_Int32( fValue ));
544     }
545     else
546     {
547 #ifdef WNT
548         sal_Unicode aBuffer[128];
549 
550         aBuffer[0] = 0;
551         if ( m_bFloat )
552             snwprintf( reinterpret_cast<wchar_t *>(aBuffer), 128, reinterpret_cast<const wchar_t *>(m_aOutFormat.getStr()), fValue );
553         else
554             snwprintf( reinterpret_cast<wchar_t *>(aBuffer), 128, reinterpret_cast<const wchar_t *>(m_aOutFormat.getStr()), sal_Int32( fValue ));
555 
556         sal_Int32 nSize = rtl_ustr_getLength( aBuffer );
557         return rtl::OUString( aBuffer, nSize );
558 #else
559         // Currently we have no support for a format string using sal_Unicode. wchar_t
560         // is 32 bit on Unix platform!
561         char aBuffer[128];
562 
563         ::rtl::OString aFormat = OUStringToOString( m_aOutFormat, osl_getThreadTextEncoding() );
564         if ( m_bFloat )
565             snprintf( aBuffer, 128, aFormat.getStr(), fValue );
566         else
567             snprintf( aBuffer, 128, aFormat.getStr(), static_cast<long>( fValue ));
568 
569         sal_Int32 nSize = strlen( aBuffer );
570         rtl::OString aTmp( aBuffer, nSize );
571         return rtl::OStringToOUString( aTmp, osl_getThreadTextEncoding() );
572 #endif
573     }
574 }
575 
576 } // namespace
577 
578