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