bump product version to 5.0.4.1
[LibreOffice.git] / extensions / source / propctrlr / standardcontrol.cxx
blob03db0ce9e895dc0c90ae92b0d25d68a84c0f33b6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include "standardcontrol.hxx"
21 #include "pcrcommon.hxx"
23 #include <com/sun/star/util/DateTime.hpp>
24 #include <com/sun/star/util/Date.hpp>
25 #include <com/sun/star/util/Time.hpp>
26 #include <com/sun/star/util/Color.hpp>
27 #include <com/sun/star/util/MeasureUnit.hpp>
28 #include <com/sun/star/inspection/PropertyControlType.hpp>
29 #include <comphelper/string.hxx>
30 #include <rtl/math.hxx>
31 #include <sfx2/objsh.hxx>
34 // ugly dependencies for the OColorControl
35 #include <svx/svxids.hrc>
36 #include <svx/drawitem.hxx>
37 #include <svx/xtable.hxx>
39 #include <vcl/floatwin.hxx>
40 #include <svtools/svmedit.hxx>
41 #include <svtools/colorcfg.hxx>
42 #include <unotools/syslocale.hxx>
43 #include <unotools/datetime.hxx>
44 #include <i18nlangtag/languagetag.hxx>
45 #include <vcl/button.hxx>
46 #include <vcl/svapp.hxx>
47 #include <vcl/settings.hxx>
49 #include <cstdlib>
50 #include <limits>
51 #include <boost/bind.hpp>
52 #include <boost/scoped_ptr.hpp>
55 namespace pcr
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::uno;
61 using namespace ::com::sun::star::awt;
62 using namespace ::com::sun::star::lang;
63 using namespace ::com::sun::star::util;
64 using namespace ::com::sun::star::beans;
65 using namespace ::com::sun::star::inspection;
68 //= OTimeControl
71 OTimeControl::OTimeControl( vcl::Window* pParent, WinBits nWinStyle )
72 :OTimeControl_Base( PropertyControlType::TimeField, pParent, nWinStyle )
74 getTypedControlWindow()->SetStrictFormat( true );
75 getTypedControlWindow()->SetFormat( TimeFieldFormat::F_SEC );
76 getTypedControlWindow()->EnableEmptyFieldValue( true );
80 void SAL_CALL OTimeControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException, std::exception)
82 util::Time aUNOTime;
83 if ( !( _rValue >>= aUNOTime ) )
85 getTypedControlWindow()->SetText( "" );
86 getTypedControlWindow()->SetEmptyTime();
88 else
90 getTypedControlWindow()->SetTime( ::tools::Time(aUNOTime) );
95 Any SAL_CALL OTimeControl::getValue() throw (RuntimeException, std::exception)
97 Any aPropValue;
98 if ( !getTypedControlWindow()->GetText().isEmpty() )
100 aPropValue <<= getTypedControlWindow()->GetTime().GetUNOTime();
102 return aPropValue;
106 Type SAL_CALL OTimeControl::getValueType() throw (RuntimeException, std::exception)
108 return ::cppu::UnoType<util::Time>::get();
112 //= ODateControl
115 ODateControl::ODateControl( vcl::Window* pParent, WinBits nWinStyle )
116 :ODateControl_Base( PropertyControlType::DateField, pParent, nWinStyle | WB_DROPDOWN )
118 WindowType* pControlWindow = getTypedControlWindow();
119 pControlWindow->SetStrictFormat(true);
121 pControlWindow->SetMin( ::Date( 1,1,1600 ) );
122 pControlWindow->SetFirst( ::Date( 1,1,1600 ) );
123 pControlWindow->SetLast( ::Date( 1, 1, 9999 ) );
124 pControlWindow->SetMax( ::Date( 1, 1, 9999 ) );
126 pControlWindow->SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY );
127 pControlWindow->EnableEmptyFieldValue( true );
131 void SAL_CALL ODateControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException, std::exception)
133 util::Date aUNODate;
134 if ( !( _rValue >>= aUNODate ) )
136 getTypedControlWindow()->SetText( "" );
137 getTypedControlWindow()->SetEmptyDate();
139 else
141 ::Date aDate( aUNODate.Day, aUNODate.Month, aUNODate.Year );
142 getTypedControlWindow()->SetDate( aDate );
147 Any SAL_CALL ODateControl::getValue() throw (RuntimeException, std::exception)
149 Any aPropValue;
150 if ( !getTypedControlWindow()->GetText().isEmpty() )
152 ::Date aDate( getTypedControlWindow()->GetDate() );
153 aPropValue <<= aDate.GetUNODate();
155 return aPropValue;
159 Type SAL_CALL ODateControl::getValueType() throw (RuntimeException, std::exception)
161 return ::cppu::UnoType<util::Date>::get();
165 //= OEditControl
168 OEditControl::OEditControl(vcl::Window* _pParent, bool _bPW, WinBits _nWinStyle)
169 :OEditControl_Base( _bPW ? PropertyControlType::CharacterField : PropertyControlType::TextField, _pParent, _nWinStyle )
171 m_bIsPassword = _bPW;
173 if ( m_bIsPassword )
174 getTypedControlWindow()->SetMaxTextLen( 1 );
178 void SAL_CALL OEditControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException, std::exception)
180 OUString sText;
181 if ( m_bIsPassword )
183 sal_Int16 nValue = 0;
184 _rValue >>= nValue;
185 if ( nValue )
187 sText = OUString(static_cast<sal_Unicode>(nValue));
190 else
191 _rValue >>= sText;
193 getTypedControlWindow()->SetText( sText );
197 Any SAL_CALL OEditControl::getValue() throw (RuntimeException, std::exception)
199 Any aPropValue;
201 OUString sText( getTypedControlWindow()->GetText() );
202 if ( m_bIsPassword )
204 if ( !sText.isEmpty() )
205 aPropValue <<= (sal_Int16)sText[0];
207 else
208 aPropValue <<= sText;
210 return aPropValue;
214 Type SAL_CALL OEditControl::getValueType() throw (RuntimeException, std::exception)
216 return m_bIsPassword ? ::cppu::UnoType<sal_Int16>::get() : ::cppu::UnoType<OUString>::get();
220 void OEditControl::modified()
222 OEditControl_Base::modified();
224 // for password controls, we fire a commit for every single change
225 if ( m_bIsPassword )
226 m_aImplControl.notifyModifiedValue();
230 static long ImplCalcLongValue( double nValue, sal_uInt16 nDigits )
232 double n = nValue;
233 for ( sal_uInt16 d = 0; d < nDigits; ++d )
234 n *= 10;
236 if ( n > ::std::numeric_limits< long >::max() )
237 return ::std::numeric_limits< long >::max();
238 return (long)n;
242 static double ImplCalcDoubleValue( long nValue, sal_uInt16 nDigits )
244 double n = nValue;
245 for ( sal_uInt16 d = 0; d < nDigits; ++d )
246 n /= 10;
247 return n;
251 // class ODateTimeControl
254 ODateTimeControl::ODateTimeControl( vcl::Window* _pParent, WinBits _nWinStyle)
255 :ODateTimeControl_Base( PropertyControlType::DateTimeField, _pParent, _nWinStyle )
257 getTypedControlWindow()->EnableEmptyField( true );
259 // determine a default format
260 LanguageType eSysLanguage = SvtSysLocale().GetLanguageTag().getLanguageType( false);
262 getTypedControlWindow()->SetFormatter( getTypedControlWindow()->StandardFormatter() );
263 SvNumberFormatter* pFormatter = getTypedControlWindow()->GetFormatter();
264 sal_uLong nStandardDateTimeFormat = pFormatter->GetStandardFormat( css::util::NumberFormat::DATETIME, eSysLanguage );
266 getTypedControlWindow()->SetFormatKey( nStandardDateTimeFormat );
270 void SAL_CALL ODateTimeControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException, std::exception)
272 if ( !_rValue.hasValue() )
274 getTypedControlWindow()->SetText( "" );
276 else
278 util::DateTime aUNODateTime;
279 OSL_VERIFY( _rValue >>= aUNODateTime );
281 ::DateTime aDateTime( ::DateTime::EMPTY );
282 ::utl::typeConvert( aUNODateTime, aDateTime );
284 double nValue = aDateTime - ::DateTime( *getTypedControlWindow()->GetFormatter()->GetNullDate() );
285 getTypedControlWindow()->SetValue( nValue );
290 Any SAL_CALL ODateTimeControl::getValue() throw (RuntimeException, std::exception)
292 Any aPropValue;
293 if ( !getTypedControlWindow()->GetText().isEmpty() )
295 double nValue = getTypedControlWindow()->GetValue();
297 ::DateTime aDateTime( *getTypedControlWindow()->GetFormatter()->GetNullDate() );
299 // add the "days" part
300 double nDays = floor( nValue );
301 aDateTime += nDays;
303 // add the "time" part
304 double nTime = nValue - nDays;
305 nTime = ::rtl::math::round( nTime * 86400.0 ) / 86400.0;
306 // we're not interested in 100th seconds, and this here prevents rounding errors
307 aDateTime += nTime;
309 util::DateTime aUNODateTime;
310 ::utl::typeConvert( aDateTime, aUNODateTime );
312 aPropValue <<= aUNODateTime;
314 return aPropValue;
318 Type SAL_CALL ODateTimeControl::getValueType() throw (RuntimeException, std::exception)
320 return ::cppu::UnoType<util::DateTime>::get();
324 //= HyperlinkInput
327 HyperlinkInput::HyperlinkInput( vcl::Window* _pParent, WinBits _nWinStyle )
328 :Edit( _pParent, _nWinStyle )
330 ::svtools::ColorConfig aColorConfig;
331 ::svtools::ColorConfigValue aLinkColor( aColorConfig.GetColorValue( ::svtools::LINKS ) );
333 AllSettings aAllSettings( GetSettings() );
334 StyleSettings aStyleSettings( aAllSettings.GetStyleSettings() );
336 vcl::Font aFieldFont( aStyleSettings.GetFieldFont() );
337 aFieldFont.SetUnderline( UNDERLINE_SINGLE );
338 aFieldFont.SetColor( aLinkColor.nColor );
339 aStyleSettings.SetFieldFont( aFieldFont );
341 aStyleSettings.SetFieldTextColor( aLinkColor.nColor );
343 aAllSettings.SetStyleSettings( aStyleSettings );
344 SetSettings( aAllSettings );
348 void HyperlinkInput::MouseMove( const ::MouseEvent& rMEvt )
350 Edit::MouseMove( rMEvt );
352 PointerStyle ePointerStyle( PointerStyle::Text );
354 if ( !rMEvt.IsLeaveWindow() )
356 if ( impl_textHitTest( rMEvt.GetPosPixel() ) )
357 ePointerStyle = PointerStyle::RefHand;
360 SetPointer( Pointer( ePointerStyle ) );
364 void HyperlinkInput::MouseButtonDown( const ::MouseEvent& rMEvt )
366 Edit::MouseButtonDown( rMEvt );
368 if ( impl_textHitTest( rMEvt.GetPosPixel() ) )
369 m_aMouseButtonDownPos = rMEvt.GetPosPixel();
370 else
371 m_aMouseButtonDownPos.X() = m_aMouseButtonDownPos.Y() = -1;
375 void HyperlinkInput::MouseButtonUp( const ::MouseEvent& rMEvt )
377 Edit::MouseButtonUp( rMEvt );
379 impl_checkEndClick( rMEvt );
383 bool HyperlinkInput::impl_textHitTest( const ::Point& _rWindowPos )
385 sal_Int32 nPos = GetCharPos( _rWindowPos );
386 return ( ( nPos != EDIT_NOLIMIT ) && ( nPos < GetText().getLength() ) );
390 void HyperlinkInput::impl_checkEndClick( const ::MouseEvent& rMEvt )
392 const MouseSettings& rMouseSettings( GetSettings().GetMouseSettings() );
393 if ( ( std::abs( rMEvt.GetPosPixel().X() - m_aMouseButtonDownPos.X() ) < rMouseSettings.GetStartDragWidth() )
394 && ( std::abs( rMEvt.GetPosPixel().Y() - m_aMouseButtonDownPos.Y() ) < rMouseSettings.GetStartDragHeight() )
396 Application::PostUserEvent( m_aClickHandler );
400 void HyperlinkInput::Tracking( const TrackingEvent& rTEvt )
402 Edit::Tracking( rTEvt );
404 if ( rTEvt.IsTrackingEnded() )
405 impl_checkEndClick( rTEvt.GetMouseEvent() );
409 //= OHyperlinkControl
412 OHyperlinkControl::OHyperlinkControl( vcl::Window* _pParent, WinBits _nWinStyle )
413 :OHyperlinkControl_Base( PropertyControlType::HyperlinkField, _pParent, _nWinStyle )
414 ,m_aActionListeners( m_aMutex )
416 getTypedControlWindow()->SetClickHdl( LINK( this, OHyperlinkControl, OnHyperlinkClicked ) );
420 Any SAL_CALL OHyperlinkControl::getValue() throw (RuntimeException, std::exception)
422 OUString sText = getTypedControlWindow()->GetText();
423 return makeAny( sText );
427 void SAL_CALL OHyperlinkControl::setValue( const Any& _value ) throw (IllegalTypeException, RuntimeException, std::exception)
429 OUString sText;
430 _value >>= sText;
431 getTypedControlWindow()->SetText( sText );
435 Type SAL_CALL OHyperlinkControl::getValueType() throw (RuntimeException, std::exception)
437 return ::cppu::UnoType<OUString>::get();
441 void SAL_CALL OHyperlinkControl::addActionListener( const Reference< XActionListener >& listener ) throw (RuntimeException, std::exception)
443 if ( listener.is() )
444 m_aActionListeners.addInterface( listener );
448 void SAL_CALL OHyperlinkControl::removeActionListener( const Reference< XActionListener >& listener ) throw (RuntimeException, std::exception)
450 m_aActionListeners.removeInterface( listener );
454 void SAL_CALL OHyperlinkControl::disposing()
456 OHyperlinkControl_Base::disposing();
458 EventObject aEvent( *this );
459 m_aActionListeners.disposeAndClear( aEvent );
463 IMPL_LINK_NOARG( OHyperlinkControl, OnHyperlinkClicked )
465 ActionEvent aEvent( *this, OUString( "clicked" ) );
466 m_aActionListeners.forEach< XActionListener >(
467 boost::bind(
468 &XActionListener::actionPerformed,
469 _1, boost::cref(aEvent) ) );
471 return 0;
475 //= ONumericControl
478 ONumericControl::ONumericControl( vcl::Window* _pParent, WinBits _nWinStyle )
479 :ONumericControl_Base( PropertyControlType::NumericField, _pParent, _nWinStyle )
480 ,m_eValueUnit( FUNIT_NONE )
481 ,m_nFieldToUNOValueFactor( 1 )
483 MetricField::SetDefaultUnit( FUNIT_NONE );
485 getTypedControlWindow()->EnableEmptyFieldValue( true );
486 getTypedControlWindow()->SetStrictFormat( true );
487 Optional< double > value( getMaxValue() );
488 value.Value = -value.Value;
489 setMinValue( value );
493 ::sal_Int16 SAL_CALL ONumericControl::getDecimalDigits() throw (RuntimeException, std::exception)
495 return getTypedControlWindow()->GetDecimalDigits();
499 void SAL_CALL ONumericControl::setDecimalDigits( ::sal_Int16 _decimaldigits ) throw (RuntimeException, std::exception)
501 getTypedControlWindow()->SetDecimalDigits( _decimaldigits );
505 Optional< double > SAL_CALL ONumericControl::getMinValue() throw (RuntimeException, std::exception)
507 Optional< double > aReturn( sal_True, 0 );
509 sal_Int64 minValue = getTypedControlWindow()->GetMin();
510 if ( minValue == ::std::numeric_limits< sal_Int64 >::min() )
511 aReturn.IsPresent = sal_False;
512 else
513 aReturn.Value = (double)minValue;
515 return aReturn;
519 void SAL_CALL ONumericControl::setMinValue( const Optional< double >& _minvalue ) throw (RuntimeException, std::exception)
521 if ( !_minvalue.IsPresent )
522 getTypedControlWindow()->SetMin( ::std::numeric_limits< sal_Int64 >::min() );
523 else
524 getTypedControlWindow()->SetMin( impl_apiValueToFieldValue_nothrow( _minvalue.Value ) , m_eValueUnit);
528 Optional< double > SAL_CALL ONumericControl::getMaxValue() throw (RuntimeException, std::exception)
530 Optional< double > aReturn( sal_True, 0 );
532 sal_Int64 maxValue = getTypedControlWindow()->GetMax();
533 if ( maxValue == ::std::numeric_limits< sal_Int64 >::max() )
534 aReturn.IsPresent = sal_False;
535 else
536 aReturn.Value = (double)maxValue;
538 return aReturn;
542 void SAL_CALL ONumericControl::setMaxValue( const Optional< double >& _maxvalue ) throw (RuntimeException, std::exception)
544 if ( !_maxvalue.IsPresent )
545 getTypedControlWindow()->SetMax( ::std::numeric_limits< sal_Int64 >::max() );
546 else
547 getTypedControlWindow()->SetMax( impl_apiValueToFieldValue_nothrow( _maxvalue.Value ), m_eValueUnit );
551 ::sal_Int16 SAL_CALL ONumericControl::getDisplayUnit() throw (RuntimeException, std::exception)
553 return VCLUnoHelper::ConvertToMeasurementUnit( getTypedControlWindow()->GetUnit(), 1 );
557 void SAL_CALL ONumericControl::setDisplayUnit( ::sal_Int16 _displayunit ) throw (IllegalArgumentException, RuntimeException, std::exception)
559 if ( ( _displayunit < MeasureUnit::MM_100TH ) || ( _displayunit > MeasureUnit::PERCENT ) )
560 throw IllegalArgumentException();
561 if ( ( _displayunit == MeasureUnit::MM_100TH )
562 || ( _displayunit == MeasureUnit::MM_10TH )
563 || ( _displayunit == MeasureUnit::INCH_1000TH )
564 || ( _displayunit == MeasureUnit::INCH_100TH )
565 || ( _displayunit == MeasureUnit::INCH_10TH )
566 || ( _displayunit == MeasureUnit::PERCENT )
568 throw IllegalArgumentException();
570 sal_Int16 nDummyFactor = 1;
571 FieldUnit eFieldUnit = VCLUnoHelper::ConvertToFieldUnit( _displayunit, nDummyFactor );
572 if ( nDummyFactor != 1 )
573 // everything which survived the checks above should result in a factor of 1, i.e.,
574 // it should have a direct counterpart as FieldUnit
575 throw RuntimeException();
576 getTypedControlWindow()->MetricFormatter::SetUnit( eFieldUnit );
580 ::sal_Int16 SAL_CALL ONumericControl::getValueUnit() throw (RuntimeException, std::exception)
582 return VCLUnoHelper::ConvertToMeasurementUnit( m_eValueUnit, m_nFieldToUNOValueFactor );
586 void SAL_CALL ONumericControl::setValueUnit( ::sal_Int16 _valueunit ) throw (RuntimeException, std::exception)
588 if ( ( _valueunit < MeasureUnit::MM_100TH ) || ( _valueunit > MeasureUnit::PERCENT ) )
589 throw IllegalArgumentException();
590 m_eValueUnit = VCLUnoHelper::ConvertToFieldUnit( _valueunit, m_nFieldToUNOValueFactor );
594 void SAL_CALL ONumericControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException, std::exception)
596 if ( !_rValue.hasValue() )
598 getTypedControlWindow()->SetText( "" );
599 getTypedControlWindow()->SetEmptyFieldValue();
601 else
603 double nValue( 0 );
604 OSL_VERIFY( _rValue >>= nValue );
605 long nControlValue = impl_apiValueToFieldValue_nothrow( nValue );
606 getTypedControlWindow()->SetValue( nControlValue, m_eValueUnit );
611 long ONumericControl::impl_apiValueToFieldValue_nothrow( double _nApiValue ) const
613 long nControlValue = ImplCalcLongValue( _nApiValue, getTypedControlWindow()->GetDecimalDigits() );
614 nControlValue /= m_nFieldToUNOValueFactor;
615 return nControlValue;
619 double ONumericControl::impl_fieldValueToApiValue_nothrow( sal_Int64 _nFieldValue ) const
621 double nApiValue = ImplCalcDoubleValue( (long)_nFieldValue, getTypedControlWindow()->GetDecimalDigits() );
622 nApiValue *= m_nFieldToUNOValueFactor;
623 return nApiValue;
627 Any SAL_CALL ONumericControl::getValue() throw (RuntimeException, std::exception)
629 Any aPropValue;
630 if ( !getTypedControlWindow()->GetText().isEmpty() )
632 double nValue = impl_fieldValueToApiValue_nothrow( getTypedControlWindow()->GetValue( m_eValueUnit ) );
633 aPropValue <<= nValue;
635 return aPropValue;
639 Type SAL_CALL ONumericControl::getValueType() throw (RuntimeException, std::exception)
641 return ::cppu::UnoType<double>::get();
645 //= OColorControl
647 #define LB_DEFAULT_COUNT 20
649 OUString MakeHexStr(sal_uInt32 nVal, sal_Int32 nLength)
651 OUStringBuffer aStr;
652 while (nVal>0)
654 char c = char(nVal & 0x000F);
655 nVal >>= 4;
656 if (c<=9) c += '0';
657 else c += 'A' - 10;
658 aStr.insert(0, c);
660 while (aStr.getLength() < nLength) aStr.insert(0, '0');
661 return aStr.makeStringAndClear();
665 OColorControl::OColorControl(vcl::Window* pParent, WinBits nWinStyle)
666 :OColorControl_Base( PropertyControlType::ColorListBox, pParent, nWinStyle )
668 // initialize the color listbox
669 XColorListRef pColorList;
670 SfxObjectShell* pDocSh = SfxObjectShell::Current();
671 const SfxPoolItem* pItem = pDocSh ? pDocSh->GetItem( SID_COLOR_TABLE ) : NULL;
672 if ( pItem )
674 DBG_ASSERT(pItem->ISA(SvxColorListItem), "OColorControl::OColorControl: invalid color item!");
675 pColorList = static_cast<const SvxColorListItem*>( pItem )->GetColorList();
678 if ( !pColorList.is() )
679 pColorList = XColorList::GetStdColorList();
682 DBG_ASSERT(pColorList.is(), "OColorControl::OColorControl: no color table!");
684 if ( pColorList.is() )
686 for (sal_uInt16 i = 0; i < pColorList->Count(); ++i)
688 XColorEntry* pEntry = pColorList->GetColor( i );
689 getTypedControlWindow()->InsertEntry( pEntry->GetColor(), pEntry->GetName() );
693 getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT );
694 if ( ( nWinStyle & WB_READONLY ) != 0 )
696 getTypedControlWindow()->SetReadOnly( true );
697 getTypedControlWindow()->Enable( true );
702 void SAL_CALL OColorControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException, std::exception)
704 if ( _rValue.hasValue() )
706 ::com::sun::star::util::Color nColor = COL_TRANSPARENT;
707 if ( _rValue >>= nColor )
709 ::Color aRgbCol((ColorData)nColor);
711 getTypedControlWindow()->SelectEntry( aRgbCol );
712 if ( !getTypedControlWindow()->IsEntrySelected( aRgbCol ) )
713 { // the given color is not part of the list -> insert a new entry with the hex code of the color
714 OUString aStr("0x");
715 aStr += MakeHexStr(nColor,8);
716 getTypedControlWindow()->InsertEntry( aRgbCol, aStr );
717 getTypedControlWindow()->SelectEntry( aRgbCol );
720 else
722 OUString sNonColorValue;
723 if ( !( _rValue >>= sNonColorValue ) )
724 throw IllegalTypeException();
725 getTypedControlWindow()->SelectEntry( sNonColorValue );
726 if ( !getTypedControlWindow()->IsEntrySelected( sNonColorValue ) )
727 getTypedControlWindow()->SetNoSelection();
730 else
731 getTypedControlWindow()->SetNoSelection();
735 Any SAL_CALL OColorControl::getValue() throw (RuntimeException, std::exception)
737 Any aPropValue;
738 if ( getTypedControlWindow()->GetSelectEntryCount() > 0 )
740 OUString sSelectedEntry = getTypedControlWindow()->GetSelectEntry();
741 if ( m_aNonColorEntries.find( sSelectedEntry ) != m_aNonColorEntries.end() )
742 aPropValue <<= sSelectedEntry;
743 else
745 ::Color aRgbCol = getTypedControlWindow()->GetSelectEntryColor();
746 aPropValue <<= (::com::sun::star::util::Color)aRgbCol.GetColor();
749 return aPropValue;
753 Type SAL_CALL OColorControl::getValueType() throw (RuntimeException, std::exception)
755 return ::cppu::UnoType<sal_Int32>::get();
759 void SAL_CALL OColorControl::clearList() throw (RuntimeException, std::exception)
761 getTypedControlWindow()->Clear();
765 void SAL_CALL OColorControl::prependListEntry( const OUString& NewEntry ) throw (RuntimeException, std::exception)
767 getTypedControlWindow()->InsertEntry( NewEntry, 0 );
768 m_aNonColorEntries.insert( NewEntry );
772 void SAL_CALL OColorControl::appendListEntry( const OUString& NewEntry ) throw (RuntimeException, std::exception)
774 getTypedControlWindow()->InsertEntry( NewEntry );
775 m_aNonColorEntries.insert( NewEntry );
778 Sequence< OUString > SAL_CALL OColorControl::getListEntries( ) throw (RuntimeException, std::exception)
780 if ( !m_aNonColorEntries.empty() )
781 return Sequence< OUString >(&(*m_aNonColorEntries.begin()),m_aNonColorEntries.size());
782 return Sequence< OUString >();
786 void OColorControl::modified()
788 OColorControl_Base::modified();
790 if ( !getTypedControlWindow()->IsTravelSelect() )
791 // fire a commit
792 m_aImplControl.notifyModifiedValue();
796 //= OListboxControl
799 OListboxControl::OListboxControl( vcl::Window* pParent, WinBits nWinStyle)
800 :OListboxControl_Base( PropertyControlType::ListBox, pParent, nWinStyle )
802 getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT );
803 if ( ( nWinStyle & WB_READONLY ) != 0 )
805 getTypedControlWindow()->SetReadOnly( true );
806 getTypedControlWindow()->Enable( true );
811 Any SAL_CALL OListboxControl::getValue() throw (RuntimeException, std::exception)
813 OUString sControlValue( getTypedControlWindow()->GetSelectEntry() );
815 Any aPropValue;
816 if ( !sControlValue.isEmpty() )
817 aPropValue <<= sControlValue;
818 return aPropValue;
822 Type SAL_CALL OListboxControl::getValueType() throw (RuntimeException, std::exception)
824 return ::cppu::UnoType<OUString>::get();
828 void SAL_CALL OListboxControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException, std::exception)
830 if ( !_rValue.hasValue() )
831 getTypedControlWindow()->SetNoSelection();
832 else
834 OUString sSelection;
835 _rValue >>= sSelection;
837 if ( !sSelection.equals( getTypedControlWindow()->GetSelectEntry() ) )
838 getTypedControlWindow()->SelectEntry( sSelection );
840 if ( !getTypedControlWindow()->IsEntrySelected( sSelection ) )
842 getTypedControlWindow()->InsertEntry( sSelection, 0 );
843 getTypedControlWindow()->SelectEntry( sSelection );
849 void SAL_CALL OListboxControl::clearList() throw (RuntimeException, std::exception)
851 getTypedControlWindow()->Clear();
855 void SAL_CALL OListboxControl::prependListEntry( const OUString& NewEntry ) throw (RuntimeException, std::exception)
857 getTypedControlWindow()->InsertEntry( NewEntry, 0 );
861 void SAL_CALL OListboxControl::appendListEntry( const OUString& NewEntry ) throw (RuntimeException, std::exception)
863 getTypedControlWindow()->InsertEntry( NewEntry );
866 Sequence< OUString > SAL_CALL OListboxControl::getListEntries( ) throw (RuntimeException, std::exception)
868 const sal_uInt16 nCount = getTypedControlWindow()->GetEntryCount();
869 Sequence< OUString > aRet(nCount);
870 OUString* pIter = aRet.getArray();
871 for (sal_uInt16 i = 0; i < nCount ; ++i,++pIter)
872 *pIter = getTypedControlWindow()->GetEntry(i);
874 return aRet;
878 void OListboxControl::modified()
880 OListboxControl_Base::modified();
882 if ( !getTypedControlWindow()->IsTravelSelect() )
883 // fire a commit
884 m_aImplControl.notifyModifiedValue();
888 //= OComboboxControl
891 OComboboxControl::OComboboxControl( vcl::Window* pParent, WinBits nWinStyle)
892 :OComboboxControl_Base( PropertyControlType::ComboBox, pParent, nWinStyle )
894 getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT );
895 getTypedControlWindow()->SetSelectHdl( LINK( this, OComboboxControl, OnEntrySelected ) );
899 void SAL_CALL OComboboxControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException, std::exception)
901 OUString sText;
902 _rValue >>= sText;
903 getTypedControlWindow()->SetText( sText );
907 Any SAL_CALL OComboboxControl::getValue() throw (RuntimeException, std::exception)
909 return makeAny( OUString( getTypedControlWindow()->GetText() ) );
913 Type SAL_CALL OComboboxControl::getValueType() throw (RuntimeException, std::exception)
915 return ::cppu::UnoType<OUString>::get();
919 void SAL_CALL OComboboxControl::clearList() throw (RuntimeException, std::exception)
921 getTypedControlWindow()->Clear();
925 void SAL_CALL OComboboxControl::prependListEntry( const OUString& NewEntry ) throw (RuntimeException, std::exception)
927 getTypedControlWindow()->InsertEntry( NewEntry, 0 );
931 void SAL_CALL OComboboxControl::appendListEntry( const OUString& NewEntry ) throw (RuntimeException, std::exception)
933 getTypedControlWindow()->InsertEntry( NewEntry );
936 Sequence< OUString > SAL_CALL OComboboxControl::getListEntries( ) throw (RuntimeException, std::exception)
938 const sal_uInt16 nCount = getTypedControlWindow()->GetEntryCount();
939 Sequence< OUString > aRet(nCount);
940 OUString* pIter = aRet.getArray();
941 for (sal_uInt16 i = 0; i < nCount ; ++i,++pIter)
942 *pIter = getTypedControlWindow()->GetEntry(i);
944 return aRet;
948 IMPL_LINK_NOARG( OComboboxControl, OnEntrySelected )
950 if ( !getTypedControlWindow()->IsTravelSelect() )
951 // fire a commit
952 m_aImplControl.notifyModifiedValue();
953 return 0L;
957 //= OMultilineFloatingEdit
959 class OMultilineFloatingEdit : public FloatingWindow
961 private:
962 VclPtr<MultiLineEdit> m_aImplEdit;
964 protected:
965 virtual void Resize() SAL_OVERRIDE;
967 public:
968 OMultilineFloatingEdit(vcl::Window* _pParen);
969 virtual ~OMultilineFloatingEdit();
970 virtual void dispose() SAL_OVERRIDE;
971 MultiLineEdit& getEdit() { return *m_aImplEdit.get(); }
973 protected:
974 virtual bool PreNotify(NotifyEvent& _rNEvt) SAL_OVERRIDE;
978 OMultilineFloatingEdit::OMultilineFloatingEdit(vcl::Window* _pParent)
979 :FloatingWindow(_pParent, WB_BORDER)
980 ,m_aImplEdit(VclPtr<MultiLineEdit>::Create(this, WB_VSCROLL|WB_IGNORETAB|WB_NOBORDER))
982 m_aImplEdit->Show();
985 OMultilineFloatingEdit::~OMultilineFloatingEdit()
987 disposeOnce();
990 void OMultilineFloatingEdit::dispose()
992 m_aImplEdit.disposeAndClear();
993 FloatingWindow::dispose();
996 void OMultilineFloatingEdit::Resize()
998 m_aImplEdit->SetSizePixel(GetOutputSizePixel());
1002 bool OMultilineFloatingEdit::PreNotify(NotifyEvent& _rNEvt)
1004 bool nResult = true;
1006 MouseNotifyEvent nSwitch = _rNEvt.GetType();
1007 if (MouseNotifyEvent::KEYINPUT == nSwitch)
1009 const vcl::KeyCode& aKeyCode = _rNEvt.GetKeyEvent()->GetKeyCode();
1010 sal_uInt16 nKey = aKeyCode.GetCode();
1012 if ( ( (KEY_RETURN == nKey)
1013 && !aKeyCode.IsShift()
1015 || ( (KEY_UP == nKey)
1016 && aKeyCode.IsMod2()
1020 EndPopupMode();
1022 else
1023 nResult=FloatingWindow::PreNotify(_rNEvt);
1025 else
1026 nResult=FloatingWindow::PreNotify(_rNEvt);
1028 return nResult;
1032 //= DropDownEditControl_Base
1035 DropDownEditControl::DropDownEditControl( vcl::Window* _pParent, WinBits _nStyle )
1036 :DropDownEditControl_Base( _pParent, _nStyle )
1037 ,m_pFloatingEdit( NULL )
1038 ,m_pDropdownButton( NULL )
1039 ,m_nOperationMode( eStringList )
1040 ,m_bDropdown( false )
1042 SetCompoundControl( true );
1044 m_pImplEdit = VclPtr<MultiLineEdit>::Create( this, WB_TABSTOP | WB_IGNORETAB | WB_NOBORDER | (_nStyle & WB_READONLY) );
1045 SetSubEdit( m_pImplEdit );
1046 m_pImplEdit->Show();
1048 if ( _nStyle & WB_DROPDOWN )
1050 m_pDropdownButton = VclPtr<PushButton>::Create( this, WB_NOLIGHTBORDER | WB_RECTSTYLE | WB_NOTABSTOP);
1051 m_pDropdownButton->SetSymbol(SymbolType::SPIN_DOWN);
1052 m_pDropdownButton->SetClickHdl( LINK( this, DropDownEditControl, DropDownHdl ) );
1053 m_pDropdownButton->Show();
1056 m_pFloatingEdit = VclPtr<OMultilineFloatingEdit>::Create(this);
1058 m_pFloatingEdit->SetPopupModeEndHdl( LINK( this, DropDownEditControl, ReturnHdl ) );
1059 m_pFloatingEdit->getEdit().SetReadOnly( ( _nStyle & WB_READONLY ) != 0 );
1063 void DropDownEditControl::setControlHelper( ControlHelper& _rControlHelper )
1065 DropDownEditControl_Base::setControlHelper( _rControlHelper );
1066 m_pFloatingEdit->getEdit().SetModifyHdl( LINK( &_rControlHelper, ControlHelper, ModifiedHdl ) );
1067 m_pImplEdit->SetGetFocusHdl( LINK( &_rControlHelper, ControlHelper, GetFocusHdl ) );
1068 m_pImplEdit->SetModifyHdl( LINK( &_rControlHelper, ControlHelper, ModifiedHdl ) );
1069 m_pImplEdit->SetLoseFocusHdl( LINK( &_rControlHelper, ControlHelper, LoseFocusHdl ) );
1073 DropDownEditControl::~DropDownEditControl()
1075 disposeOnce();
1078 void DropDownEditControl::dispose()
1080 SetSubEdit(nullptr);
1081 m_pImplEdit.disposeAndClear();
1082 m_pFloatingEdit.disposeAndClear();
1083 m_pDropdownButton.disposeAndClear();
1084 DropDownEditControl_Base::dispose();
1088 void DropDownEditControl::Resize()
1090 ::Size aOutSz = GetOutputSizePixel();
1092 if (m_pDropdownButton!=nullptr)
1094 long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
1095 nSBWidth = CalcZoom( nSBWidth );
1096 m_pImplEdit->setPosSizePixel( 0, 1, aOutSz.Width() - nSBWidth, aOutSz.Height()-2 );
1097 m_pDropdownButton->setPosSizePixel( aOutSz.Width() - nSBWidth, 0, nSBWidth, aOutSz.Height() );
1099 else
1100 m_pImplEdit->setPosSizePixel( 0, 1, aOutSz.Width(), aOutSz.Height()-2 );
1104 bool DropDownEditControl::PreNotify( NotifyEvent& rNEvt )
1106 bool nResult = true;
1108 if (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT)
1110 const vcl::KeyCode& aKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
1111 sal_uInt16 nKey = aKeyCode.GetCode();
1113 if ( nKey == KEY_RETURN && !aKeyCode.IsShift() )
1115 if ( m_pHelper )
1117 m_pHelper->LoseFocusHdl( m_pImplEdit.get() );
1118 m_pHelper->activateNextControl();
1121 else if ( nKey == KEY_DOWN && aKeyCode.IsMod2() )
1123 Invalidate();
1124 ShowDropDown( true );
1126 else if ( KEYGROUP_CURSOR == aKeyCode.GetGroup()
1127 || nKey == KEY_HELP
1128 || KEYGROUP_FKEYS == aKeyCode.GetGroup()
1129 || m_nOperationMode == eMultiLineText
1132 nResult = DropDownEditControl_Base::PreNotify( rNEvt );
1134 else if ( m_nOperationMode == eStringList )
1136 Selection aSel = m_pImplEdit->GetSelection();
1137 if ( aSel.Min() != aSel.Max() )
1139 aSel.Min() = FindPos( aSel.Min() );
1140 aSel.Max() = FindPos( aSel.Max() );
1142 else
1144 aSel.Min() = FindPos( aSel.Min() );
1145 aSel.Max() = aSel.Min();
1147 Invalidate();
1148 ShowDropDown( true );
1149 m_pFloatingEdit->getEdit().GrabFocus();
1150 m_pFloatingEdit->getEdit().SetSelection( aSel );
1151 vcl::Window* pFocusWin = Application::GetFocusWindow();
1152 pFocusWin->KeyInput( *rNEvt.GetKeyEvent() );
1155 else
1156 nResult = DropDownEditControl_Base::PreNotify(rNEvt);
1158 return nResult;
1162 namespace
1165 StlSyntaxSequence< OUString > lcl_convertMultiLineToList( const OUString& _rCompsedTextWithLineBreaks )
1167 sal_Int32 nLines = comphelper::string::getTokenCount(_rCompsedTextWithLineBreaks, '\n');
1168 StlSyntaxSequence< OUString > aStrings( nLines );
1169 StlSyntaxSequence< OUString >::iterator stringItem = aStrings.begin();
1170 for ( sal_Int32 token = 0; token < nLines; ++token, ++stringItem )
1171 *stringItem = _rCompsedTextWithLineBreaks.getToken( token, '\n' );
1172 return aStrings;
1175 OUString lcl_convertListToMultiLine( const StlSyntaxSequence< OUString >& _rStrings )
1177 OUString sMultiLineText;
1178 for ( StlSyntaxSequence< OUString >::const_iterator item = _rStrings.begin();
1179 item != _rStrings.end();
1182 sMultiLineText += *item;
1183 if ( ++item != _rStrings.end() )
1184 sMultiLineText += "\n";
1186 return sMultiLineText;
1190 OUString lcl_convertListToDisplayText( const StlSyntaxSequence< OUString >& _rStrings )
1192 OUStringBuffer aComposed;
1193 for ( StlSyntaxSequence< OUString >::const_iterator strings = _rStrings.begin();
1194 strings != _rStrings.end();
1195 ++strings
1198 if ( strings != _rStrings.begin() )
1199 aComposed.append( ';' );
1200 aComposed.append( '\"' );
1201 aComposed.append( *strings );
1202 aComposed.append( '\"' );
1204 return aComposed.makeStringAndClear();
1209 #define STD_HEIGHT 100
1210 bool DropDownEditControl::ShowDropDown( bool bShow )
1212 if (bShow)
1214 ::Point aMePos= GetPosPixel();
1215 aMePos = GetParent()->OutputToScreenPixel( aMePos );
1216 ::Size aSize=GetSizePixel();
1217 ::Rectangle aRect(aMePos,aSize);
1218 aSize.Height() = STD_HEIGHT;
1219 m_pFloatingEdit->SetOutputSizePixel(aSize);
1220 m_pFloatingEdit->StartPopupMode( aRect, FloatWinPopupFlags::Down );
1222 m_pFloatingEdit->Show();
1223 m_pFloatingEdit->getEdit().GrabFocus();
1224 m_pFloatingEdit->getEdit().SetSelection(Selection(m_pFloatingEdit->getEdit().GetText().getLength()));
1225 m_bDropdown = true;
1226 if ( m_nOperationMode == eMultiLineText )
1227 m_pFloatingEdit->getEdit().SetText( m_pImplEdit->GetText() );
1228 m_pImplEdit->SetText("");
1230 else
1232 m_pFloatingEdit->Hide();
1233 m_pFloatingEdit->Invalidate();
1234 m_pFloatingEdit->Update();
1236 // transfer the text from the floating edit to our own edit
1237 OUString sDisplayText( m_pFloatingEdit->getEdit().GetText() );
1238 if ( m_nOperationMode == eStringList )
1239 sDisplayText = lcl_convertListToDisplayText( lcl_convertMultiLineToList( sDisplayText ) );
1241 m_pImplEdit->SetText( sDisplayText );
1242 GetParent()->Invalidate( INVALIDATE_CHILDREN );
1243 m_bDropdown = false;
1244 m_pImplEdit->GrabFocus();
1246 return m_bDropdown;
1251 long DropDownEditControl::FindPos(long nSinglePos)
1253 long nPos = 0;
1254 OUString aOutput;
1255 OUString aStr = m_pFloatingEdit->getEdit().GetText();
1256 OUString aStr1 = GetText();
1258 if ((nSinglePos == 0) || (nSinglePos == aStr1.getLength()))
1260 return nSinglePos;
1263 if (!aStr.isEmpty())
1265 long nDiff=0;
1266 sal_Int32 nCount = comphelper::string::getTokenCount(aStr, '\n');
1268 OUString aInput = aStr.getToken(0,'\n' );
1270 if (!aInput.isEmpty())
1272 aOutput += "\"";
1273 nDiff++;
1274 aOutput += aInput;
1275 aOutput += "\"";
1278 if (nSinglePos <= aOutput.getLength())
1280 nPos=nSinglePos-nDiff;
1282 else
1284 for (sal_Int32 i=1; i<nCount; ++i)
1286 aInput=aStr.getToken((sal_uInt16)i, '\n');
1287 if (!aInput.isEmpty())
1289 aOutput += ";";
1290 aOutput += "\"";
1291 nDiff += 2;
1292 aOutput += aInput;
1293 aOutput += "\"";
1295 if (nSinglePos <= aOutput.getLength())
1297 nPos=nSinglePos-nDiff;
1298 break;
1304 return nPos;
1308 IMPL_LINK( DropDownEditControl, ReturnHdl, OMultilineFloatingEdit*, /*pMEd*/)
1311 OUString aStr = m_pFloatingEdit->getEdit().GetText();
1312 OUString aStr2 = GetText();
1313 ShowDropDown(false);
1315 if (aStr!=aStr2 || ( m_nOperationMode == eStringList ) )
1317 if ( m_pHelper )
1318 m_pHelper->notifyModifiedValue();
1321 return 0;
1325 IMPL_LINK( DropDownEditControl, DropDownHdl, PushButton*, /*pPb*/ )
1327 ShowDropDown(!m_bDropdown);
1328 return 0;
1332 void DropDownEditControl::SetStringListValue( const StlSyntaxSequence< OUString >& _rStrings )
1334 SetText( lcl_convertListToDisplayText( _rStrings ) );
1335 m_pFloatingEdit->getEdit().SetText( lcl_convertListToMultiLine( _rStrings ) );
1339 StlSyntaxSequence< OUString > DropDownEditControl::GetStringListValue() const
1341 return lcl_convertMultiLineToList( m_pFloatingEdit->getEdit().GetText() );
1345 void DropDownEditControl::SetTextValue( const OUString& _rText )
1347 OSL_PRECOND( m_nOperationMode == eMultiLineText, "DropDownEditControl::SetTextValue: illegal call!" );
1349 m_pFloatingEdit->getEdit().SetText( _rText );
1350 SetText( _rText );
1354 OUString DropDownEditControl::GetTextValue() const
1356 OSL_PRECOND( m_nOperationMode == eMultiLineText, "DropDownEditControl::GetTextValue: illegal call!" );
1357 return GetText();
1361 //= OMultilineEditControl
1364 OMultilineEditControl::OMultilineEditControl( vcl::Window* pParent, MultiLineOperationMode _eMode, WinBits nWinStyle )
1365 :OMultilineEditControl_Base( _eMode == eMultiLineText ? PropertyControlType::MultiLineTextField : PropertyControlType::StringListField
1366 , pParent
1367 , ( nWinStyle | WB_DIALOGCONTROL ) & ( ~WB_READONLY | ~WB_DROPDOWN )
1368 , false )
1370 getTypedControlWindow()->setOperationMode( _eMode );
1374 void SAL_CALL OMultilineEditControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException, std::exception)
1376 impl_checkDisposed_throw();
1378 switch ( getTypedControlWindow()->getOperationMode() )
1380 case eMultiLineText:
1382 OUString sText;
1383 if ( !( _rValue >>= sText ) && _rValue.hasValue() )
1384 throw IllegalTypeException();
1385 getTypedControlWindow()->SetTextValue( sText );
1387 break;
1388 case eStringList:
1390 Sequence< OUString > aStringLines;
1391 if ( !( _rValue >>= aStringLines ) && _rValue.hasValue() )
1392 throw IllegalTypeException();
1393 getTypedControlWindow()->SetStringListValue( aStringLines );
1395 break;
1400 Any SAL_CALL OMultilineEditControl::getValue() throw (RuntimeException, std::exception)
1402 impl_checkDisposed_throw();
1404 Any aValue;
1405 switch ( getTypedControlWindow()->getOperationMode() )
1407 case eMultiLineText:
1408 aValue <<= getTypedControlWindow()->GetTextValue();
1409 break;
1410 case eStringList:
1411 aValue <<= getTypedControlWindow()->GetStringListValue();
1412 break;
1414 return aValue;
1418 Type SAL_CALL OMultilineEditControl::getValueType() throw (RuntimeException, std::exception)
1420 if ( getTypedControlWindow()->getOperationMode() == eMultiLineText )
1421 return ::cppu::UnoType<OUString>::get();
1422 return cppu::UnoType<Sequence< OUString >>::get();
1426 } // namespace pcr
1429 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */