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