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