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 // Unfortunaltly the events are notifed 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 throw ( RuntimeException )
238 {
239     vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
240 
241     m_pToolbar->SetItemWindow( m_nID, 0 );
242     delete m_pSpinfieldControl;
243 
244     ComplexToolbarController::dispose();
245 
246     m_pSpinfieldControl = 0;
247 }
248 
249 // ------------------------------------------------------------------
getExecuteArgs(sal_Int16 KeyModifier) const250 Sequence<PropertyValue> SpinfieldToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const
251 {
252     Sequence<PropertyValue> aArgs( 2 );
253     ::rtl::OUString aSpinfieldText = m_pSpinfieldControl->GetText();
254 
255     // Add key modifier to argument list
256     aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" ));
257     aArgs[0].Value <<= KeyModifier;
258     aArgs[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Value" ));
259     if ( m_bFloat )
260         aArgs[1].Value <<= aSpinfieldText.toDouble();
261     else
262         aArgs[1].Value <<= aSpinfieldText.toInt32();
263     return aArgs;
264 }
265 
266 // ------------------------------------------------------------------
267 
Up()268 void SpinfieldToolbarController::Up()
269 {
270     double nValue = m_nValue + m_nStep;
271     if ( m_bMaxSet && nValue > m_nMax )
272         return;
273 
274     m_nValue = nValue;
275 
276     rtl::OUString aText = impl_formatOutputString( m_nValue );
277     m_pSpinfieldControl->SetText( aText );
278     execute( 0 );
279 }
280 
Down()281 void SpinfieldToolbarController::Down()
282 {
283     double nValue = m_nValue - m_nStep;
284     if ( m_bMinSet && nValue < m_nMin )
285         return;
286 
287     m_nValue = nValue;
288 
289     rtl::OUString aText = impl_formatOutputString( m_nValue );
290     m_pSpinfieldControl->SetText( aText );
291     execute( 0 );
292 }
293 
First()294 void SpinfieldToolbarController::First()
295 {
296     if ( m_bMinSet )
297     {
298         m_nValue = m_nMin;
299 
300         rtl::OUString aText = impl_formatOutputString( m_nValue );
301         m_pSpinfieldControl->SetText( aText );
302         execute( 0 );
303     }
304 }
305 
Last()306 void SpinfieldToolbarController::Last()
307 {
308     if ( m_bMaxSet )
309     {
310         m_nValue = m_nMax;
311 
312         rtl::OUString aText = impl_formatOutputString( m_nValue );
313         m_pSpinfieldControl->SetText( aText );
314         execute( 0 );
315     }
316 }
317 
Modify()318 void SpinfieldToolbarController::Modify()
319 {
320     notifyTextChanged( m_pSpinfieldControl->GetText() );
321 }
322 
KeyInput(const::KeyEvent &)323 void SpinfieldToolbarController::KeyInput( const ::KeyEvent& /*rKEvt*/ )
324 {
325 }
326 
GetFocus()327 void SpinfieldToolbarController::GetFocus()
328 {
329     notifyFocusGet();
330 }
331 
LoseFocus()332 void SpinfieldToolbarController::LoseFocus()
333 {
334     notifyFocusLost();
335 }
336 
StateChanged(StateChangedType)337 void SpinfieldToolbarController::StateChanged( StateChangedType /*nType*/ )
338 {
339 }
340 
DataChanged(const DataChangedEvent &)341 void SpinfieldToolbarController::DataChanged( const DataChangedEvent& /*rDCEvt*/ )
342 {
343 }
344 
PreNotify(NotifyEvent & rNEvt)345 long SpinfieldToolbarController::PreNotify( NotifyEvent& rNEvt )
346 {
347     if( rNEvt.GetType() == EVENT_KEYINPUT )
348     {
349         const ::KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
350         const KeyCode& rKeyCode = pKeyEvent->GetKeyCode();
351         if(( rKeyCode.GetModifier() | rKeyCode.GetCode()) == KEY_RETURN )
352         {
353             // Call execute only with non-empty text
354             if ( m_pSpinfieldControl->GetText().Len() > 0 )
355                 execute( rKeyCode.GetModifier() );
356             return 1;
357         }
358     }
359 
360     return 0;
361 }
362 
363 // --------------------------------------------------------
364 
executeControlCommand(const::com::sun::star::frame::ControlCommand & rControlCommand)365 void SpinfieldToolbarController::executeControlCommand( const ::com::sun::star::frame::ControlCommand& rControlCommand )
366 {
367     rtl::OUString aValue;
368     rtl::OUString aMax;
369     rtl::OUString aMin;
370     rtl::OUString aStep;
371     bool          bFloatValue( false );
372 
373     if ( rControlCommand.Command.equalsAsciiL( "SetStep", 7 ))
374     {
375         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
376         {
377             sal_Int32   nValue;
378             double      fValue;
379             bool        bFloat( false );
380 
381             if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Step", 4 ))
382             {
383                 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
384                     aStep = bFloat ? ::rtl::OUString::valueOf( fValue ) :
385                                      ::rtl::OUString::valueOf( nValue );
386                 break;
387             }
388         }
389     }
390     else if ( rControlCommand.Command.equalsAsciiL( "SetValue", 8 ))
391     {
392         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
393         {
394             if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "Value", 5 ))
395             {
396                 sal_Int32   nValue;
397                 double      fValue;
398                 bool        bFloat( false );
399 
400                 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
401                 {
402                     aValue = bFloat ? ::rtl::OUString::valueOf( fValue ) : ::rtl::OUString::valueOf( nValue );
403                     bFloatValue = bFloat;
404                 }
405                 break;
406             }
407         }
408     }
409     else if ( rControlCommand.Command.equalsAsciiL( "SetValues", 9 ))
410     {
411         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
412         {
413             sal_Int32   nValue;
414             double      fValue;
415             bool        bFloat( false );
416 
417             rtl::OUString aName = rControlCommand.Arguments[i].Name;
418             if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
419             {
420                 if ( aName.equalsAsciiL( "Value", 5 ))
421                 {
422                     aValue = bFloat ? ::rtl::OUString::valueOf( fValue ) : ::rtl::OUString::valueOf( nValue );
423                     bFloatValue = bFloat;
424                 }
425                 else if ( aName.equalsAsciiL( "Step", 4 ))
426                     aStep = bFloat ? ::rtl::OUString::valueOf( fValue ) :
427                                      ::rtl::OUString::valueOf( nValue );
428                 else if ( aName.equalsAsciiL( "LowerLimit", 10 ))
429                     aMin = bFloat ? ::rtl::OUString::valueOf( fValue ) :
430                                     ::rtl::OUString::valueOf( nValue );
431                 else if ( aName.equalsAsciiL( "UpperLimit", 10 ))
432                     aMax = bFloat ? ::rtl::OUString::valueOf( fValue ) :
433                                     ::rtl::OUString::valueOf( nValue );
434             }
435             else if ( aName.equalsAsciiL( "OutputFormat", 12 ))
436                 rControlCommand.Arguments[i].Value >>= m_aOutFormat;
437         }
438     }
439     else if ( rControlCommand.Command.equalsAsciiL( "SetLowerLimit", 13 ))
440     {
441         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
442         {
443             sal_Int32   nValue;
444             double      fValue;
445             bool        bFloat( false );
446 
447             if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "LowerLimit", 10 ))
448             {
449                 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
450                     aMin = bFloat ? ::rtl::OUString::valueOf( fValue ) :
451                                     ::rtl::OUString::valueOf( nValue );
452                 break;
453             }
454         }
455     }
456     else if ( rControlCommand.Command.equalsAsciiL( "SetUpperLimit", 13 ))
457     {
458         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
459         {
460             sal_Int32   nValue;
461             double      fValue;
462             bool        bFloat( false );
463 
464             if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "UpperLimit", 10 ))
465             {
466                 if ( impl_getValue( rControlCommand.Arguments[i].Value, nValue, fValue, bFloat ))
467                     aMax = bFloat ? ::rtl::OUString::valueOf( fValue ) :
468                                     ::rtl::OUString::valueOf( nValue );
469                 break;
470             }
471         }
472     }
473     else if ( rControlCommand.Command.equalsAsciiL( "SetOutputFormat", 15 ))
474     {
475         for ( sal_Int32 i = 0; i < rControlCommand.Arguments.getLength(); i++ )
476         {
477             if ( rControlCommand.Arguments[i].Name.equalsAsciiL( "OutputFormat", 10 ))
478             {
479                 rControlCommand.Arguments[i].Value >>= m_aOutFormat;
480                 break;
481             }
482         }
483     }
484 
485     // Check values and set members
486     if ( aValue.getLength() > 0 )
487     {
488         m_bFloat = bFloatValue;
489         m_nValue = aValue.toDouble();
490 
491         rtl::OUString aOutString = impl_formatOutputString( m_nValue );
492         m_pSpinfieldControl->SetText( aOutString );
493         notifyTextChanged( aOutString );
494     }
495     if ( aMax.getLength() > 0 )
496     {
497         m_nMax = aMax.toDouble();
498         m_bMaxSet = true;
499     }
500     if ( aMin.getLength() > 0 )
501     {
502         m_nMin = aMin.toDouble();
503         m_bMinSet = true;
504     }
505     if ( aStep.getLength() > 0 )
506         m_nStep = aStep.toDouble();
507 }
508 
impl_getValue(const Any & rAny,sal_Int32 & nValue,double & fValue,bool & bFloat)509 bool SpinfieldToolbarController::impl_getValue(
510     const Any& rAny, sal_Int32& nValue, double& fValue, bool& bFloat )
511 {
512     using ::com::sun::star::uno::TypeClass;
513 
514     bool bValueValid( false );
515 
516     bFloat = false;
517     TypeClass aTypeClass = rAny.getValueTypeClass();
518     if (( aTypeClass == TypeClass( typelib_TypeClass_LONG  )) ||
519         ( aTypeClass == TypeClass( typelib_TypeClass_SHORT )) ||
520         ( aTypeClass == TypeClass( typelib_TypeClass_BYTE  )))
521         bValueValid = rAny >>= nValue;
522     else if (( aTypeClass == TypeClass( typelib_TypeClass_FLOAT  )) ||
523              ( aTypeClass == TypeClass( typelib_TypeClass_DOUBLE )))
524     {
525         bValueValid = rAny >>= fValue;
526         bFloat = true;
527     }
528 
529     return bValueValid;
530 }
531 
impl_formatOutputString(double fValue)532 rtl::OUString SpinfieldToolbarController::impl_formatOutputString( double fValue )
533 {
534     if ( m_aOutFormat.getLength() == 0 )
535     {
536         if ( m_bFloat )
537             return rtl::OUString::valueOf( fValue );
538         else
539             return rtl::OUString::valueOf( sal_Int32( fValue ));
540     }
541     else
542     {
543 #ifdef WNT
544         sal_Unicode aBuffer[128];
545 
546         aBuffer[0] = 0;
547         if ( m_bFloat )
548             snwprintf( reinterpret_cast<wchar_t *>(aBuffer), 128, reinterpret_cast<const wchar_t *>(m_aOutFormat.getStr()), fValue );
549         else
550             snwprintf( reinterpret_cast<wchar_t *>(aBuffer), 128, reinterpret_cast<const wchar_t *>(m_aOutFormat.getStr()), sal_Int32( fValue ));
551 
552         sal_Int32 nSize = rtl_ustr_getLength( aBuffer );
553         return rtl::OUString( aBuffer, nSize );
554 #else
555         // Currently we have no support for a format string using sal_Unicode. wchar_t
556         // is 32 bit on Unix platform!
557         char aBuffer[128];
558 
559         ::rtl::OString aFormat = OUStringToOString( m_aOutFormat, osl_getThreadTextEncoding() );
560         if ( m_bFloat )
561             snprintf( aBuffer, 128, aFormat.getStr(), fValue );
562         else
563             snprintf( aBuffer, 128, aFormat.getStr(), static_cast<long>( fValue ));
564 
565         sal_Int32 nSize = strlen( aBuffer );
566         rtl::OString aTmp( aBuffer, nSize );
567         return rtl::OStringToOUString( aTmp, osl_getThreadTextEncoding() );
568 #endif
569     }
570 }
571 
572 } // namespace
573 
574