1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
23 #include "uielement/spinfieldtoolbarcontroller.hxx"
25 #include <com/sun/star/util/XURLTransformer.hpp>
26 #include <com/sun/star/frame/XDispatchProvider.hpp>
27 #include <com/sun/star/beans/PropertyValue.hpp>
28 #include <com/sun/star/frame/status/ItemStatus.hpp>
29 #include <com/sun/star/frame/status/ItemState.hpp>
30 #include <com/sun/star/frame/status/Visibility.hpp>
31 #include <com/sun/star/frame/XControlNotificationListener.hpp>
33 #include <svtools/toolboxcontroller.hxx>
34 #include <osl/mutex.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/mnemonic.hxx>
37 #include <vcl/toolbox.hxx>
39 #include <systools/win32/snprintf.h>
42 using namespace ::com::sun::star
;
43 using namespace ::com::sun::star::uno
;
44 using namespace ::com::sun::star::beans
;
45 using namespace ::com::sun::star::lang
;
46 using namespace ::com::sun::star::frame
;
47 using namespace ::com::sun::star::frame::status
;
48 using namespace ::com::sun::star::util
;
53 // Wrapper class to notify controller about events from combobox.
54 // Unfortunaltly the events are notifed through virtual methods instead
57 class SpinfieldControl
: public SpinField
60 SpinfieldControl( vcl::Window
* pParent
, WinBits nStyle
, ISpinfieldListener
* pSpinFieldListener
);
61 virtual ~SpinfieldControl();
62 virtual void dispose() SAL_OVERRIDE
;
64 virtual void Up() SAL_OVERRIDE
;
65 virtual void Down() SAL_OVERRIDE
;
66 virtual void First() SAL_OVERRIDE
;
67 virtual void Last() SAL_OVERRIDE
;
68 virtual void KeyInput( const ::KeyEvent
& rKEvt
) SAL_OVERRIDE
;
69 virtual void Modify() SAL_OVERRIDE
;
70 virtual void GetFocus() SAL_OVERRIDE
;
71 virtual void LoseFocus() SAL_OVERRIDE
;
72 virtual void StateChanged( StateChangedType nType
) SAL_OVERRIDE
;
73 virtual void DataChanged( const DataChangedEvent
& rDCEvt
) SAL_OVERRIDE
;
74 virtual bool PreNotify( NotifyEvent
& rNEvt
) SAL_OVERRIDE
;
77 ISpinfieldListener
* m_pSpinFieldListener
;
80 SpinfieldControl::SpinfieldControl( vcl::Window
* pParent
, WinBits nStyle
, ISpinfieldListener
* pSpinFieldListener
) :
81 SpinField( pParent
, nStyle
)
82 , m_pSpinFieldListener( pSpinFieldListener
)
86 SpinfieldControl::~SpinfieldControl()
91 void SpinfieldControl::dispose()
93 m_pSpinFieldListener
= 0;
97 void SpinfieldControl::Up()
100 if ( m_pSpinFieldListener
)
101 m_pSpinFieldListener
->Up();
104 void SpinfieldControl::Down()
107 if ( m_pSpinFieldListener
)
108 m_pSpinFieldListener
->Down();
111 void SpinfieldControl::First()
114 if ( m_pSpinFieldListener
)
115 m_pSpinFieldListener
->First();
118 void SpinfieldControl::Last()
121 if ( m_pSpinFieldListener
)
122 m_pSpinFieldListener
->Last();
125 void SpinfieldControl::KeyInput( const ::KeyEvent
& rKEvt
)
127 SpinField::KeyInput( rKEvt
);
128 if ( m_pSpinFieldListener
)
129 m_pSpinFieldListener
->KeyInput( rKEvt
);
132 void SpinfieldControl::Modify()
135 if ( m_pSpinFieldListener
)
136 m_pSpinFieldListener
->Modify();
139 void SpinfieldControl::GetFocus()
141 SpinField::GetFocus();
142 if ( m_pSpinFieldListener
)
143 m_pSpinFieldListener
->GetFocus();
146 void SpinfieldControl::LoseFocus()
148 SpinField::GetFocus();
149 if ( m_pSpinFieldListener
)
150 m_pSpinFieldListener
->GetFocus();
153 void SpinfieldControl::StateChanged( StateChangedType nType
)
155 SpinField::StateChanged( nType
);
156 if ( m_pSpinFieldListener
)
157 m_pSpinFieldListener
->StateChanged( nType
);
160 void SpinfieldControl::DataChanged( const DataChangedEvent
& rDCEvt
)
162 SpinField::DataChanged( rDCEvt
);
163 if ( m_pSpinFieldListener
)
164 m_pSpinFieldListener
->DataChanged( rDCEvt
);
167 bool SpinfieldControl::PreNotify( NotifyEvent
& rNEvt
)
170 if ( m_pSpinFieldListener
)
171 nRet
= m_pSpinFieldListener
->PreNotify( rNEvt
);
173 nRet
= SpinField::PreNotify( rNEvt
);
178 SpinfieldToolbarController::SpinfieldToolbarController(
179 const Reference
< XComponentContext
>& rxContext
,
180 const Reference
< XFrame
>& rFrame
,
184 const OUString
& aCommand
) :
185 ComplexToolbarController( rxContext
, rFrame
, pToolbar
, nID
, aCommand
)
193 , m_pSpinfieldControl( 0 )
195 m_pSpinfieldControl
= VclPtr
<SpinfieldControl
>::Create( m_pToolbar
, WB_SPIN
|WB_BORDER
, this );
199 // Calculate height of the spin field according to the application font height
200 sal_Int32 nHeight
= getFontSizePixel( m_pSpinfieldControl
) + 5 + 1;
202 m_pSpinfieldControl
->SetSizePixel( ::Size( nWidth
, nHeight
));
203 m_pToolbar
->SetItemWindow( m_nID
, m_pSpinfieldControl
);
206 SpinfieldToolbarController::~SpinfieldToolbarController()
210 void SAL_CALL
SpinfieldToolbarController::dispose()
211 throw ( RuntimeException
, std::exception
)
213 SolarMutexGuard aSolarMutexGuard
;
215 m_pToolbar
->SetItemWindow( m_nID
, 0 );
216 m_pSpinfieldControl
.disposeAndClear();
218 ComplexToolbarController::dispose();
221 Sequence
<PropertyValue
> SpinfieldToolbarController::getExecuteArgs(sal_Int16 KeyModifier
) const
223 Sequence
<PropertyValue
> aArgs( 2 );
224 OUString aSpinfieldText
= m_pSpinfieldControl
->GetText();
226 // Add key modifier to argument list
227 aArgs
[0].Name
= "KeyModifier";
228 aArgs
[0].Value
<<= KeyModifier
;
229 aArgs
[1].Name
= "Value";
231 aArgs
[1].Value
<<= aSpinfieldText
.toDouble();
233 aArgs
[1].Value
<<= aSpinfieldText
.toInt32();
237 void SpinfieldToolbarController::Up()
239 double nValue
= m_nValue
+ m_nStep
;
240 if ( m_bMaxSet
&& nValue
> m_nMax
)
245 OUString aText
= impl_formatOutputString( m_nValue
);
246 m_pSpinfieldControl
->SetText( aText
);
250 void SpinfieldToolbarController::Down()
252 double nValue
= m_nValue
- m_nStep
;
253 if ( m_bMinSet
&& nValue
< m_nMin
)
258 OUString aText
= impl_formatOutputString( m_nValue
);
259 m_pSpinfieldControl
->SetText( aText
);
263 void SpinfieldToolbarController::First()
269 OUString aText
= impl_formatOutputString( m_nValue
);
270 m_pSpinfieldControl
->SetText( aText
);
275 void SpinfieldToolbarController::Last()
281 OUString aText
= impl_formatOutputString( m_nValue
);
282 m_pSpinfieldControl
->SetText( aText
);
287 void SpinfieldToolbarController::Modify()
289 notifyTextChanged( m_pSpinfieldControl
->GetText() );
292 void SpinfieldToolbarController::KeyInput( const ::KeyEvent
& /*rKEvt*/ )
296 void SpinfieldToolbarController::GetFocus()
301 void SpinfieldToolbarController::LoseFocus()
306 void SpinfieldToolbarController::StateChanged( StateChangedType
/*nType*/ )
310 void SpinfieldToolbarController::DataChanged( const DataChangedEvent
& /*rDCEvt*/ )
314 bool SpinfieldToolbarController::PreNotify( NotifyEvent
& rNEvt
)
316 if( rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
318 const ::KeyEvent
* pKeyEvent
= rNEvt
.GetKeyEvent();
319 const vcl::KeyCode
& rKeyCode
= pKeyEvent
->GetKeyCode();
320 if(( rKeyCode
.GetModifier() | rKeyCode
.GetCode()) == KEY_RETURN
)
322 // Call execute only with non-empty text
323 if ( !m_pSpinfieldControl
->GetText().isEmpty() )
324 execute( rKeyCode
.GetModifier() );
332 void SpinfieldToolbarController::executeControlCommand( const ::com::sun::star::frame::ControlCommand
& rControlCommand
)
338 bool bFloatValue( false );
340 if ( rControlCommand
.Command
== "SetStep" )
342 for ( sal_Int32 i
= 0; i
< rControlCommand
.Arguments
.getLength(); i
++ )
344 if ( rControlCommand
.Arguments
[i
].Name
== "Step" )
348 bool bFloat( false );
349 if ( impl_getValue( rControlCommand
.Arguments
[i
].Value
, nValue
, fValue
, bFloat
))
350 aStep
= bFloat
? OUString::number( fValue
) :
351 OUString::number( nValue
);
356 else if ( rControlCommand
.Command
== "SetValue" )
358 for ( sal_Int32 i
= 0; i
< rControlCommand
.Arguments
.getLength(); i
++ )
360 if ( rControlCommand
.Arguments
[i
].Name
== "Value" )
364 bool bFloat( false );
366 if ( impl_getValue( rControlCommand
.Arguments
[i
].Value
, nValue
, fValue
, bFloat
))
368 aValue
= bFloat
? OUString::number( fValue
) : OUString::number( nValue
);
369 bFloatValue
= bFloat
;
375 else if ( rControlCommand
.Command
== "SetValues" )
377 for ( sal_Int32 i
= 0; i
< rControlCommand
.Arguments
.getLength(); i
++ )
381 bool bFloat( false );
383 OUString aName
= rControlCommand
.Arguments
[i
].Name
;
384 if ( impl_getValue( rControlCommand
.Arguments
[i
].Value
, nValue
, fValue
, bFloat
))
386 if ( aName
== "Value" )
388 aValue
= bFloat
? OUString::number( fValue
) : OUString::number( nValue
);
389 bFloatValue
= bFloat
;
391 else if ( aName
== "Step" )
392 aStep
= bFloat
? OUString::number( fValue
) :
393 OUString::number( nValue
);
394 else if ( aName
== "LowerLimit" )
395 aMin
= bFloat
? OUString::number( fValue
) :
396 OUString::number( nValue
);
397 else if ( aName
== "UpperLimit" )
398 aMax
= bFloat
? OUString::number( fValue
) :
399 OUString::number( nValue
);
401 else if ( aName
== "OutputFormat" )
402 rControlCommand
.Arguments
[i
].Value
>>= m_aOutFormat
;
405 else if ( rControlCommand
.Command
== "SetLowerLimit" )
407 for ( sal_Int32 i
= 0; i
< rControlCommand
.Arguments
.getLength(); i
++ )
409 if ( rControlCommand
.Arguments
[i
].Name
== "LowerLimit" )
413 bool bFloat( false );
414 if ( impl_getValue( rControlCommand
.Arguments
[i
].Value
, nValue
, fValue
, bFloat
))
415 aMin
= bFloat
? OUString::number( fValue
) :
416 OUString::number( nValue
);
421 else if ( rControlCommand
.Command
== "SetUpperLimit" )
423 for ( sal_Int32 i
= 0; i
< rControlCommand
.Arguments
.getLength(); i
++ )
425 if ( rControlCommand
.Arguments
[i
].Name
== "UpperLimit" )
429 bool bFloat( false );
430 if ( impl_getValue( rControlCommand
.Arguments
[i
].Value
, nValue
, fValue
, bFloat
))
431 aMax
= bFloat
? OUString::number( fValue
) :
432 OUString::number( nValue
);
437 else if ( rControlCommand
.Command
== "SetOutputFormat" )
439 for ( sal_Int32 i
= 0; i
< rControlCommand
.Arguments
.getLength(); i
++ )
441 if ( rControlCommand
.Arguments
[i
].Name
== "OutputFormat" )
443 rControlCommand
.Arguments
[i
].Value
>>= m_aOutFormat
;
449 // Check values and set members
450 if ( !aValue
.isEmpty() )
452 m_bFloat
= bFloatValue
;
453 m_nValue
= aValue
.toDouble();
455 OUString aOutString
= impl_formatOutputString( m_nValue
);
456 m_pSpinfieldControl
->SetText( aOutString
);
457 notifyTextChanged( aOutString
);
459 if ( !aMax
.isEmpty() )
461 m_nMax
= aMax
.toDouble();
464 if ( !aMin
.isEmpty() )
466 m_nMin
= aMin
.toDouble();
469 if ( !aStep
.isEmpty() )
470 m_nStep
= aStep
.toDouble();
473 bool SpinfieldToolbarController::impl_getValue(
474 const Any
& rAny
, sal_Int32
& nValue
, double& fValue
, bool& bFloat
)
476 using ::com::sun::star::uno::TypeClass
;
478 bool bValueValid( false );
481 TypeClass aTypeClass
= rAny
.getValueTypeClass();
482 if (( aTypeClass
== TypeClass( typelib_TypeClass_LONG
)) ||
483 ( aTypeClass
== TypeClass( typelib_TypeClass_SHORT
)) ||
484 ( aTypeClass
== TypeClass( typelib_TypeClass_BYTE
)))
485 bValueValid
= rAny
>>= nValue
;
486 else if (( aTypeClass
== TypeClass( typelib_TypeClass_FLOAT
)) ||
487 ( aTypeClass
== TypeClass( typelib_TypeClass_DOUBLE
)))
489 bValueValid
= rAny
>>= fValue
;
496 OUString
SpinfieldToolbarController::impl_formatOutputString( double fValue
)
498 if ( m_aOutFormat
.isEmpty() )
501 return OUString::number( fValue
);
503 return OUString::number( sal_Int32( fValue
));
508 sal_Unicode aBuffer
[128];
512 snwprintf( reinterpret_cast<wchar_t *>(aBuffer
), 128, reinterpret_cast<const wchar_t *>(m_aOutFormat
.getStr()), fValue
);
514 snwprintf( reinterpret_cast<wchar_t *>(aBuffer
), 128, reinterpret_cast<const wchar_t *>(m_aOutFormat
.getStr()), sal_Int32( fValue
));
516 sal_Int32 nSize
= rtl_ustr_getLength( aBuffer
);
517 return OUString( aBuffer
, nSize
);
519 // Currently we have no support for a format string using sal_Unicode. wchar_t
520 // is 32 bit on Unix platform!
523 OString aFormat
= OUStringToOString( m_aOutFormat
, osl_getThreadTextEncoding() );
525 snprintf( aBuffer
, 128, aFormat
.getStr(), fValue
);
527 snprintf( aBuffer
, 128, aFormat
.getStr(), static_cast<long>( fValue
));
529 sal_Int32 nSize
= strlen( aBuffer
);
530 OString
aTmp( aBuffer
, nSize
);
531 return OStringToOUString( aTmp
, osl_getThreadTextEncoding() );
538 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */