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