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 .
20 #include "standardcontrol.hxx"
21 #include "pcrcommon.hxx"
23 #include <com/sun/star/beans/IllegalTypeException.hpp>
24 #include <com/sun/star/util/DateTime.hpp>
25 #include <com/sun/star/util/Date.hpp>
26 #include <com/sun/star/util/Time.hpp>
27 #include <com/sun/star/util/Color.hpp>
28 #include <com/sun/star/util/MeasureUnit.hpp>
29 #include <com/sun/star/inspection/PropertyControlType.hpp>
30 #include <comphelper/string.hxx>
31 #include <o3tl/float_int_conversion.hxx>
32 #include <rtl/math.hxx>
33 #include <sfx2/objsh.hxx>
36 // ugly dependencies for the OColorControl
37 #include <svx/svxids.hrc>
38 #include <svx/drawitem.hxx>
39 #include <svx/xtable.hxx>
41 #include <vcl/floatwin.hxx>
42 #include <svtools/svmedit.hxx>
43 #include <svtools/colorcfg.hxx>
44 #include <svl/zforlist.hxx>
45 #include <unotools/syslocale.hxx>
46 #include <unotools/datetime.hxx>
47 #include <i18nlangtag/languagetag.hxx>
48 #include <vcl/button.hxx>
49 #include <vcl/event.hxx>
50 #include <vcl/svapp.hxx>
51 #include <vcl/settings.hxx>
52 #include <vcl/ptrstyle.hxx>
63 using namespace ::com::sun::star
;
64 using namespace ::com::sun::star::uno
;
65 using namespace ::com::sun::star::awt
;
66 using namespace ::com::sun::star::lang
;
67 using namespace ::com::sun::star::util
;
68 using namespace ::com::sun::star::beans
;
69 using namespace ::com::sun::star::inspection
;
75 OTimeControl::OTimeControl( vcl::Window
* pParent
, WinBits nWinStyle
)
76 :OTimeControl_Base( PropertyControlType::TimeField
, pParent
, nWinStyle
)
78 getTypedControlWindow()->SetStrictFormat( true );
79 getTypedControlWindow()->SetFormat( TimeFieldFormat::F_SEC
);
80 getTypedControlWindow()->EnableEmptyFieldValue( true );
84 void SAL_CALL
OTimeControl::setValue( const Any
& _rValue
)
87 if ( !( _rValue
>>= aUNOTime
) )
89 getTypedControlWindow()->SetText( "" );
90 getTypedControlWindow()->SetEmptyTime();
94 getTypedControlWindow()->SetTime( ::tools::Time(aUNOTime
) );
99 Any SAL_CALL
OTimeControl::getValue()
102 if ( !getTypedControlWindow()->GetText().isEmpty() )
104 aPropValue
<<= getTypedControlWindow()->GetTime().GetUNOTime();
110 Type SAL_CALL
OTimeControl::getValueType()
112 return ::cppu::UnoType
<util::Time
>::get();
119 ODateControl::ODateControl( vcl::Window
* pParent
, WinBits nWinStyle
)
120 :ODateControl_Base( PropertyControlType::DateField
, pParent
, nWinStyle
| WB_DROPDOWN
)
122 CalendarField
* pControlWindow
= getTypedControlWindow();
123 pControlWindow
->SetStrictFormat(true);
125 pControlWindow
->SetMin( ::Date( 1,1,1600 ) );
126 pControlWindow
->SetFirst( ::Date( 1,1,1600 ) );
127 pControlWindow
->SetLast( ::Date( 1, 1, 9999 ) );
128 pControlWindow
->SetMax( ::Date( 1, 1, 9999 ) );
130 pControlWindow
->SetExtDateFormat( ExtDateFieldFormat::SystemShortYYYY
);
131 pControlWindow
->EnableEmptyFieldValue( true );
135 void SAL_CALL
ODateControl::setValue( const Any
& _rValue
)
138 if ( !( _rValue
>>= aUNODate
) )
140 getTypedControlWindow()->SetText( "" );
141 getTypedControlWindow()->SetEmptyDate();
145 ::Date
aDate( aUNODate
.Day
, aUNODate
.Month
, aUNODate
.Year
);
146 getTypedControlWindow()->SetDate( aDate
);
151 Any SAL_CALL
ODateControl::getValue()
154 if ( !getTypedControlWindow()->GetText().isEmpty() )
156 ::Date
aDate( getTypedControlWindow()->GetDate() );
157 aPropValue
<<= aDate
.GetUNODate();
163 Type SAL_CALL
ODateControl::getValueType()
165 return ::cppu::UnoType
<util::Date
>::get();
172 OEditControl::OEditControl(vcl::Window
* _pParent
, bool _bPW
, WinBits _nWinStyle
)
173 :OEditControl_Base( _bPW
? PropertyControlType::CharacterField
: PropertyControlType::TextField
, _pParent
, _nWinStyle
)
175 m_bIsPassword
= _bPW
;
178 getTypedControlWindow()->SetMaxTextLen( 1 );
182 void SAL_CALL
OEditControl::setValue( const Any
& _rValue
)
187 sal_Int16 nValue
= 0;
191 sText
= OUString(static_cast<sal_Unicode
>(nValue
));
197 getTypedControlWindow()->SetText( sText
);
201 Any SAL_CALL
OEditControl::getValue()
205 OUString
sText( getTypedControlWindow()->GetText() );
208 if ( !sText
.isEmpty() )
209 aPropValue
<<= static_cast<sal_Int16
>(sText
[0]);
212 aPropValue
<<= sText
;
218 Type SAL_CALL
OEditControl::getValueType()
220 return m_bIsPassword
? ::cppu::UnoType
<sal_Int16
>::get() : ::cppu::UnoType
<OUString
>::get();
224 void OEditControl::setModified()
226 OEditControl_Base::setModified();
228 // for password controls, we fire a commit for every single change
230 notifyModifiedValue();
234 static long ImplCalcLongValue( double nValue
, sal_uInt16 nDigits
)
237 for ( sal_uInt16 d
= 0; d
< nDigits
; ++d
)
240 if ( !o3tl::convertsToAtMost(n
, std::numeric_limits
< long >::max()) )
241 return std::numeric_limits
< long >::max();
242 return static_cast<long>(n
);
246 static double ImplCalcDoubleValue( long nValue
, sal_uInt16 nDigits
)
249 for ( sal_uInt16 d
= 0; d
< nDigits
; ++d
)
255 // class ODateTimeControl
258 ODateTimeControl::ODateTimeControl( vcl::Window
* _pParent
, WinBits _nWinStyle
)
259 :ODateTimeControl_Base( PropertyControlType::DateTimeField
, _pParent
, _nWinStyle
)
261 getTypedControlWindow()->EnableEmptyField( true );
263 // determine a default format
264 LanguageType eSysLanguage
= SvtSysLocale().GetLanguageTag().getLanguageType( false);
266 getTypedControlWindow()->SetFormatter( getTypedControlWindow()->StandardFormatter() );
267 SvNumberFormatter
* pFormatter
= getTypedControlWindow()->GetFormatter();
268 sal_uLong nStandardDateTimeFormat
= pFormatter
->GetStandardFormat( SvNumFormatType::DATETIME
, eSysLanguage
);
270 getTypedControlWindow()->SetFormatKey( nStandardDateTimeFormat
);
274 void SAL_CALL
ODateTimeControl::setValue( const Any
& _rValue
)
276 if ( !_rValue
.hasValue() )
278 getTypedControlWindow()->SetText( "" );
282 util::DateTime aUNODateTime
;
283 OSL_VERIFY( _rValue
>>= aUNODateTime
);
285 ::DateTime
aDateTime( ::DateTime::EMPTY
);
286 ::utl::typeConvert( aUNODateTime
, aDateTime
);
288 double nValue
= aDateTime
- ::DateTime( getTypedControlWindow()->GetFormatter()->GetNullDate() );
289 getTypedControlWindow()->SetValue( nValue
);
294 Any SAL_CALL
ODateTimeControl::getValue()
297 if ( !getTypedControlWindow()->GetText().isEmpty() )
299 double nValue
= getTypedControlWindow()->GetValue();
301 ::DateTime
aDateTime( getTypedControlWindow()->GetFormatter()->GetNullDate() );
303 // add the "days" part
304 double nDays
= floor( nValue
);
305 aDateTime
.AddDays( nDays
);
307 // add the "time" part
308 double nTime
= nValue
- nDays
;
309 nTime
= ::rtl::math::round( nTime
* 86400.0 ) / 86400.0;
310 // we're not interested in 100th seconds, and this here prevents rounding errors
311 aDateTime
.AddTime( nTime
);
313 util::DateTime aUNODateTime
;
314 ::utl::typeConvert( aDateTime
, aUNODateTime
);
316 aPropValue
<<= aUNODateTime
;
322 Type SAL_CALL
ODateTimeControl::getValueType()
324 return ::cppu::UnoType
<util::DateTime
>::get();
331 HyperlinkInput::HyperlinkInput( vcl::Window
* _pParent
, WinBits _nWinStyle
)
332 :Edit( _pParent
, _nWinStyle
)
334 ::svtools::ColorConfig aColorConfig
;
335 ::svtools::ColorConfigValue
aLinkColor( aColorConfig
.GetColorValue( ::svtools::LINKS
) );
337 AllSettings
aAllSettings( GetSettings() );
338 StyleSettings
aStyleSettings( aAllSettings
.GetStyleSettings() );
340 vcl::Font
aFieldFont( aStyleSettings
.GetFieldFont() );
341 aFieldFont
.SetUnderline( LINESTYLE_SINGLE
);
342 aFieldFont
.SetColor( aLinkColor
.nColor
);
343 aStyleSettings
.SetFieldFont( aFieldFont
);
345 aStyleSettings
.SetFieldTextColor( aLinkColor
.nColor
);
347 aAllSettings
.SetStyleSettings( aStyleSettings
);
348 SetSettings( aAllSettings
);
352 void HyperlinkInput::MouseMove( const ::MouseEvent
& rMEvt
)
354 Edit::MouseMove( rMEvt
);
356 PointerStyle
ePointerStyle( PointerStyle::Text
);
358 if ( !rMEvt
.IsLeaveWindow() )
360 if ( impl_textHitTest( rMEvt
.GetPosPixel() ) )
361 ePointerStyle
= PointerStyle::RefHand
;
364 SetPointer( ePointerStyle
);
368 void HyperlinkInput::MouseButtonDown( const ::MouseEvent
& rMEvt
)
370 Edit::MouseButtonDown( rMEvt
);
372 if ( impl_textHitTest( rMEvt
.GetPosPixel() ) )
373 m_aMouseButtonDownPos
= rMEvt
.GetPosPixel();
376 m_aMouseButtonDownPos
.setX(-1);
377 m_aMouseButtonDownPos
.setY(-1);
382 void HyperlinkInput::MouseButtonUp( const ::MouseEvent
& rMEvt
)
384 Edit::MouseButtonUp( rMEvt
);
386 impl_checkEndClick( rMEvt
);
390 bool HyperlinkInput::impl_textHitTest( const ::Point
& _rWindowPos
)
392 sal_Int32 nPos
= GetCharPos( _rWindowPos
);
393 return ( ( nPos
!= EDIT_NOLIMIT
) && ( nPos
< GetText().getLength() ) );
397 void HyperlinkInput::impl_checkEndClick( const ::MouseEvent
& rMEvt
)
399 const MouseSettings
& rMouseSettings( GetSettings().GetMouseSettings() );
400 if ( ( std::abs( rMEvt
.GetPosPixel().X() - m_aMouseButtonDownPos
.X() ) < rMouseSettings
.GetStartDragWidth() )
401 && ( std::abs( rMEvt
.GetPosPixel().Y() - m_aMouseButtonDownPos
.Y() ) < rMouseSettings
.GetStartDragHeight() )
403 Application::PostUserEvent( m_aClickHandler
);
407 void HyperlinkInput::Tracking( const TrackingEvent
& rTEvt
)
409 Edit::Tracking( rTEvt
);
411 if ( rTEvt
.IsTrackingEnded() )
412 impl_checkEndClick( rTEvt
.GetMouseEvent() );
416 //= OHyperlinkControl
419 OHyperlinkControl::OHyperlinkControl( vcl::Window
* _pParent
, WinBits _nWinStyle
)
420 :OHyperlinkControl_Base( PropertyControlType::HyperlinkField
, _pParent
, _nWinStyle
)
421 ,m_aActionListeners( m_aMutex
)
423 getTypedControlWindow()->SetClickHdl( LINK( this, OHyperlinkControl
, OnHyperlinkClicked
) );
427 Any SAL_CALL
OHyperlinkControl::getValue()
429 OUString sText
= getTypedControlWindow()->GetText();
430 return makeAny( sText
);
434 void SAL_CALL
OHyperlinkControl::setValue( const Any
& _value
)
438 getTypedControlWindow()->SetText( sText
);
442 Type SAL_CALL
OHyperlinkControl::getValueType()
444 return ::cppu::UnoType
<OUString
>::get();
448 void SAL_CALL
OHyperlinkControl::addActionListener( const Reference
< XActionListener
>& listener
)
451 m_aActionListeners
.addInterface( listener
);
455 void SAL_CALL
OHyperlinkControl::removeActionListener( const Reference
< XActionListener
>& listener
)
457 m_aActionListeners
.removeInterface( listener
);
461 void SAL_CALL
OHyperlinkControl::disposing()
463 OHyperlinkControl_Base::disposing();
465 EventObject
aEvent( *this );
466 m_aActionListeners
.disposeAndClear( aEvent
);
470 IMPL_LINK_NOARG( OHyperlinkControl
, OnHyperlinkClicked
, void*, void )
472 ActionEvent
aEvent( *this, "clicked" );
473 m_aActionListeners
.forEach
< XActionListener
>(
474 [&aEvent
] (uno::Reference
<awt::XActionListener
> const& xListener
)
475 { return xListener
->actionPerformed(aEvent
); });
482 ONumericControl::ONumericControl( vcl::Window
* _pParent
, WinBits _nWinStyle
)
483 :ONumericControl_Base( PropertyControlType::NumericField
, _pParent
, _nWinStyle
)
484 ,m_eValueUnit( FieldUnit::NONE
)
485 ,m_nFieldToUNOValueFactor( 1 )
487 MetricField::SetDefaultUnit( FieldUnit::NONE
);
489 getTypedControlWindow()->EnableEmptyFieldValue( true );
490 getTypedControlWindow()->SetStrictFormat( true );
491 Optional
< double > value( getMaxValue() );
492 value
.Value
= -value
.Value
;
493 setMinValue( value
);
497 ::sal_Int16 SAL_CALL
ONumericControl::getDecimalDigits()
499 return getTypedControlWindow()->GetDecimalDigits();
503 void SAL_CALL
ONumericControl::setDecimalDigits( ::sal_Int16 _decimaldigits
)
505 getTypedControlWindow()->SetDecimalDigits( _decimaldigits
);
509 Optional
< double > SAL_CALL
ONumericControl::getMinValue()
511 Optional
< double > aReturn( true, 0 );
513 sal_Int64 minValue
= getTypedControlWindow()->GetMin();
514 if ( minValue
== std::numeric_limits
< sal_Int64
>::min() )
515 aReturn
.IsPresent
= false;
517 aReturn
.Value
= static_cast<double>(minValue
);
523 void SAL_CALL
ONumericControl::setMinValue( const Optional
< double >& _minvalue
)
525 if ( !_minvalue
.IsPresent
)
526 getTypedControlWindow()->SetMin( std::numeric_limits
< sal_Int64
>::min() );
528 getTypedControlWindow()->SetMin( impl_apiValueToFieldValue_nothrow( _minvalue
.Value
) , m_eValueUnit
);
532 Optional
< double > SAL_CALL
ONumericControl::getMaxValue()
534 Optional
< double > aReturn( true, 0 );
536 sal_Int64 maxValue
= getTypedControlWindow()->GetMax();
537 if ( maxValue
== std::numeric_limits
< sal_Int64
>::max() )
538 aReturn
.IsPresent
= false;
540 aReturn
.Value
= static_cast<double>(maxValue
);
546 void SAL_CALL
ONumericControl::setMaxValue( const Optional
< double >& _maxvalue
)
548 if ( !_maxvalue
.IsPresent
)
549 getTypedControlWindow()->SetMax( std::numeric_limits
< sal_Int64
>::max() );
551 getTypedControlWindow()->SetMax( impl_apiValueToFieldValue_nothrow( _maxvalue
.Value
), m_eValueUnit
);
555 ::sal_Int16 SAL_CALL
ONumericControl::getDisplayUnit()
557 return VCLUnoHelper::ConvertToMeasurementUnit( getTypedControlWindow()->GetUnit(), 1 );
561 void SAL_CALL
ONumericControl::setDisplayUnit( ::sal_Int16 _displayunit
)
563 if ( ( _displayunit
< MeasureUnit::MM_100TH
) || ( _displayunit
> MeasureUnit::PERCENT
) )
564 throw IllegalArgumentException();
565 if ( ( _displayunit
== MeasureUnit::MM_100TH
)
566 || ( _displayunit
== MeasureUnit::MM_10TH
)
567 || ( _displayunit
== MeasureUnit::INCH_1000TH
)
568 || ( _displayunit
== MeasureUnit::INCH_100TH
)
569 || ( _displayunit
== MeasureUnit::INCH_10TH
)
570 || ( _displayunit
== MeasureUnit::PERCENT
)
572 throw IllegalArgumentException();
574 sal_Int16 nDummyFactor
= 1;
575 FieldUnit eFieldUnit
= VCLUnoHelper::ConvertToFieldUnit( _displayunit
, nDummyFactor
);
576 if ( nDummyFactor
!= 1 )
577 // everything which survived the checks above should result in a factor of 1, i.e.,
578 // it should have a direct counterpart as FieldUnit
579 throw RuntimeException();
580 getTypedControlWindow()->MetricFormatter::SetUnit( eFieldUnit
);
584 ::sal_Int16 SAL_CALL
ONumericControl::getValueUnit()
586 return VCLUnoHelper::ConvertToMeasurementUnit( m_eValueUnit
, m_nFieldToUNOValueFactor
);
590 void SAL_CALL
ONumericControl::setValueUnit( ::sal_Int16 _valueunit
)
592 if ( ( _valueunit
< MeasureUnit::MM_100TH
) || ( _valueunit
> MeasureUnit::PERCENT
) )
593 throw IllegalArgumentException();
594 m_eValueUnit
= VCLUnoHelper::ConvertToFieldUnit( _valueunit
, m_nFieldToUNOValueFactor
);
598 void SAL_CALL
ONumericControl::setValue( const Any
& _rValue
)
600 if ( !_rValue
.hasValue() )
602 getTypedControlWindow()->SetText( "" );
603 getTypedControlWindow()->SetEmptyFieldValue();
608 OSL_VERIFY( _rValue
>>= nValue
);
609 long nControlValue
= impl_apiValueToFieldValue_nothrow( nValue
);
610 getTypedControlWindow()->SetValue( nControlValue
, m_eValueUnit
);
615 long ONumericControl::impl_apiValueToFieldValue_nothrow( double _nApiValue
) const
617 long nControlValue
= ImplCalcLongValue( _nApiValue
, getTypedControlWindow()->GetDecimalDigits() );
618 nControlValue
/= m_nFieldToUNOValueFactor
;
619 return nControlValue
;
623 double ONumericControl::impl_fieldValueToApiValue_nothrow( sal_Int64 _nFieldValue
) const
625 double nApiValue
= ImplCalcDoubleValue( static_cast<long>(_nFieldValue
), getTypedControlWindow()->GetDecimalDigits() );
626 nApiValue
*= m_nFieldToUNOValueFactor
;
631 Any SAL_CALL
ONumericControl::getValue()
634 if ( !getTypedControlWindow()->GetText().isEmpty() )
636 double nValue
= impl_fieldValueToApiValue_nothrow( getTypedControlWindow()->GetValue( m_eValueUnit
) );
637 aPropValue
<<= nValue
;
643 Type SAL_CALL
ONumericControl::getValueType()
645 return ::cppu::UnoType
<double>::get();
651 #define LB_DEFAULT_COUNT 20
653 OColorControl::OColorControl(vcl::Window
* pParent
, WinBits nWinStyle
)
654 : OColorControl_Base(PropertyControlType::ColorListBox
, pParent
, nWinStyle
)
656 getTypedControlWindow()->SetSlotId(SID_FM_CTL_PROPERTIES
);
659 void SAL_CALL
OColorControl::setValue( const Any
& _rValue
)
661 css::util::Color nColor
= sal_uInt32(COL_TRANSPARENT
);
662 if (_rValue
.hasValue())
664 getTypedControlWindow()->SelectEntry(nColor
);
667 Any SAL_CALL
OColorControl::getValue()
670 ::Color aRgbCol
= getTypedControlWindow()->GetSelectEntryColor();
671 if (aRgbCol
== COL_TRANSPARENT
)
673 aPropValue
<<= aRgbCol
;
677 Type SAL_CALL
OColorControl::getValueType()
679 return ::cppu::UnoType
<sal_Int32
>::get();
682 void OColorControl::setModified()
684 OColorControl_Base::setModified();
687 notifyModifiedValue();
692 OListboxControl::OListboxControl( vcl::Window
* pParent
, WinBits nWinStyle
)
693 :OListboxControl_Base( PropertyControlType::ListBox
, pParent
, nWinStyle
)
695 getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT
);
696 if ( ( nWinStyle
& WB_READONLY
) != 0 )
698 getTypedControlWindow()->SetReadOnly();
699 getTypedControlWindow()->Enable();
704 Any SAL_CALL
OListboxControl::getValue()
706 OUString
sControlValue( getTypedControlWindow()->GetSelectedEntry() );
709 if ( !sControlValue
.isEmpty() )
710 aPropValue
<<= sControlValue
;
715 Type SAL_CALL
OListboxControl::getValueType()
717 return ::cppu::UnoType
<OUString
>::get();
721 void SAL_CALL
OListboxControl::setValue( const Any
& _rValue
)
723 if ( !_rValue
.hasValue() )
724 getTypedControlWindow()->SetNoSelection();
728 _rValue
>>= sSelection
;
730 if ( sSelection
!= getTypedControlWindow()->GetSelectedEntry() )
731 getTypedControlWindow()->SelectEntry( sSelection
);
733 if ( !getTypedControlWindow()->IsEntrySelected( sSelection
) )
735 getTypedControlWindow()->InsertEntry( sSelection
, 0 );
736 getTypedControlWindow()->SelectEntry( sSelection
);
742 void SAL_CALL
OListboxControl::clearList()
744 getTypedControlWindow()->Clear();
748 void SAL_CALL
OListboxControl::prependListEntry( const OUString
& NewEntry
)
750 getTypedControlWindow()->InsertEntry( NewEntry
, 0 );
754 void SAL_CALL
OListboxControl::appendListEntry( const OUString
& NewEntry
)
756 getTypedControlWindow()->InsertEntry( NewEntry
);
759 Sequence
< OUString
> SAL_CALL
OListboxControl::getListEntries( )
761 const sal_Int32 nCount
= getTypedControlWindow()->GetEntryCount();
762 Sequence
< OUString
> aRet(nCount
);
763 OUString
* pIter
= aRet
.getArray();
764 for (sal_Int32 i
= 0; i
< nCount
; ++i
,++pIter
)
765 *pIter
= getTypedControlWindow()->GetEntry(i
);
771 void OListboxControl::setModified()
773 OListboxControl_Base::setModified();
775 if ( !getTypedControlWindow()->IsTravelSelect() )
777 notifyModifiedValue();
784 OComboboxControl::OComboboxControl( vcl::Window
* pParent
, WinBits nWinStyle
)
785 :OComboboxControl_Base( PropertyControlType::ComboBox
, pParent
, nWinStyle
)
787 getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT
);
788 getTypedControlWindow()->SetSelectHdl( LINK( this, OComboboxControl
, OnEntrySelected
) );
792 void SAL_CALL
OComboboxControl::setValue( const Any
& _rValue
)
796 getTypedControlWindow()->SetText( sText
);
800 Any SAL_CALL
OComboboxControl::getValue()
802 return makeAny( getTypedControlWindow()->GetText() );
806 Type SAL_CALL
OComboboxControl::getValueType()
808 return ::cppu::UnoType
<OUString
>::get();
812 void SAL_CALL
OComboboxControl::clearList()
814 getTypedControlWindow()->Clear();
818 void SAL_CALL
OComboboxControl::prependListEntry( const OUString
& NewEntry
)
820 getTypedControlWindow()->InsertEntry( NewEntry
, 0 );
824 void SAL_CALL
OComboboxControl::appendListEntry( const OUString
& NewEntry
)
826 getTypedControlWindow()->InsertEntry( NewEntry
);
829 Sequence
< OUString
> SAL_CALL
OComboboxControl::getListEntries( )
831 const sal_Int32 nCount
= getTypedControlWindow()->GetEntryCount();
832 Sequence
< OUString
> aRet(nCount
);
833 OUString
* pIter
= aRet
.getArray();
834 for (sal_Int32 i
= 0; i
< nCount
; ++i
,++pIter
)
835 *pIter
= getTypedControlWindow()->GetEntry(i
);
841 IMPL_LINK_NOARG( OComboboxControl
, OnEntrySelected
, ComboBox
&, void )
843 if ( !getTypedControlWindow()->IsTravelSelect() )
845 notifyModifiedValue();
849 //= OMultilineFloatingEdit
851 class OMultilineFloatingEdit
: public FloatingWindow
854 VclPtr
<MultiLineEdit
> m_aImplEdit
;
857 virtual void Resize() override
;
860 explicit OMultilineFloatingEdit(vcl::Window
* _pParen
);
861 virtual ~OMultilineFloatingEdit() override
;
862 virtual void dispose() override
;
863 MultiLineEdit
& getEdit() { return *m_aImplEdit
.get(); }
866 virtual bool PreNotify(NotifyEvent
& _rNEvt
) override
;
870 OMultilineFloatingEdit::OMultilineFloatingEdit(vcl::Window
* _pParent
)
871 :FloatingWindow(_pParent
, WB_BORDER
)
872 ,m_aImplEdit(VclPtr
<MultiLineEdit
>::Create(this, WB_VSCROLL
|WB_IGNORETAB
|WB_NOBORDER
))
877 OMultilineFloatingEdit::~OMultilineFloatingEdit()
882 void OMultilineFloatingEdit::dispose()
884 m_aImplEdit
.disposeAndClear();
885 FloatingWindow::dispose();
888 void OMultilineFloatingEdit::Resize()
890 m_aImplEdit
->SetSizePixel(GetOutputSizePixel());
894 bool OMultilineFloatingEdit::PreNotify(NotifyEvent
& _rNEvt
)
898 MouseNotifyEvent nSwitch
= _rNEvt
.GetType();
899 if (MouseNotifyEvent::KEYINPUT
== nSwitch
)
901 const vcl::KeyCode
& aKeyCode
= _rNEvt
.GetKeyEvent()->GetKeyCode();
902 sal_uInt16 nKey
= aKeyCode
.GetCode();
904 if ( ( (KEY_RETURN
== nKey
)
905 && !aKeyCode
.IsShift()
907 || ( (KEY_UP
== nKey
)
915 bResult
=FloatingWindow::PreNotify(_rNEvt
);
918 bResult
=FloatingWindow::PreNotify(_rNEvt
);
924 //= DropDownEditControl_Base
927 DropDownEditControl::DropDownEditControl( vcl::Window
* _pParent
, WinBits _nStyle
)
928 :Edit( _pParent
, _nStyle
)
929 ,m_pFloatingEdit( nullptr )
930 ,m_pDropdownButton( nullptr )
931 ,m_nOperationMode( eStringList
)
935 SetCompoundControl( true );
937 m_pImplEdit
= VclPtr
<MultiLineEdit
>::Create( this, WB_TABSTOP
| WB_IGNORETAB
| WB_NOBORDER
| (_nStyle
& WB_READONLY
) );
938 SetSubEdit( m_pImplEdit
);
941 if ( _nStyle
& WB_DROPDOWN
)
943 m_pDropdownButton
= VclPtr
<PushButton
>::Create( this, WB_NOLIGHTBORDER
| WB_RECTSTYLE
| WB_NOTABSTOP
);
944 m_pDropdownButton
->SetSymbol(SymbolType::SPIN_DOWN
);
945 m_pDropdownButton
->SetClickHdl( LINK( this, DropDownEditControl
, DropDownHdl
) );
946 m_pDropdownButton
->Show();
949 m_pFloatingEdit
= VclPtr
<OMultilineFloatingEdit
>::Create(this);
951 m_pFloatingEdit
->SetPopupModeEndHdl( LINK( this, DropDownEditControl
, ReturnHdl
) );
952 m_pFloatingEdit
->getEdit().SetReadOnly( ( _nStyle
& WB_READONLY
) != 0 );
956 void DropDownEditControl::setControlHelper( CommonBehaviourControlHelper
& _rControlHelper
)
958 m_pHelper
= &_rControlHelper
;
959 m_pFloatingEdit
->getEdit().SetModifyHdl( LINK( &_rControlHelper
, CommonBehaviourControlHelper
, EditModifiedHdl
) );
960 m_pImplEdit
->SetGetFocusHdl( LINK( &_rControlHelper
, CommonBehaviourControlHelper
, GetFocusHdl
) );
961 m_pImplEdit
->SetModifyHdl( LINK( &_rControlHelper
, CommonBehaviourControlHelper
, EditModifiedHdl
) );
962 m_pImplEdit
->SetLoseFocusHdl( LINK( &_rControlHelper
, CommonBehaviourControlHelper
, LoseFocusHdl
) );
966 DropDownEditControl::~DropDownEditControl()
971 void DropDownEditControl::dispose()
974 m_pImplEdit
.disposeAndClear();
975 m_pFloatingEdit
.disposeAndClear();
976 m_pDropdownButton
.disposeAndClear();
981 void DropDownEditControl::Resize()
983 ::Size aOutSz
= GetOutputSizePixel();
985 if (m_pDropdownButton
!=nullptr)
987 long nSBWidth
= GetSettings().GetStyleSettings().GetScrollBarSize();
988 nSBWidth
= CalcZoom( nSBWidth
);
989 m_pImplEdit
->setPosSizePixel( 0, 1, aOutSz
.Width() - nSBWidth
, aOutSz
.Height()-2 );
990 m_pDropdownButton
->setPosSizePixel( aOutSz
.Width() - nSBWidth
, 0, nSBWidth
, aOutSz
.Height() );
993 m_pImplEdit
->setPosSizePixel( 0, 1, aOutSz
.Width(), aOutSz
.Height()-2 );
997 bool DropDownEditControl::PreNotify( NotifyEvent
& rNEvt
)
1001 if (rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
1003 const vcl::KeyCode
& aKeyCode
= rNEvt
.GetKeyEvent()->GetKeyCode();
1004 sal_uInt16 nKey
= aKeyCode
.GetCode();
1006 if ( nKey
== KEY_RETURN
&& !aKeyCode
.IsShift() )
1010 m_pHelper
->LoseFocusHdl( *m_pImplEdit
.get() );
1011 m_pHelper
->activateNextControl();
1014 else if ( nKey
== KEY_DOWN
&& aKeyCode
.IsMod2() )
1017 ShowDropDown( true );
1019 else if ( KEYGROUP_CURSOR
== aKeyCode
.GetGroup()
1021 || KEYGROUP_FKEYS
== aKeyCode
.GetGroup()
1022 || m_nOperationMode
== eMultiLineText
1025 bResult
= Edit::PreNotify( rNEvt
);
1027 else if ( m_nOperationMode
== eStringList
)
1029 Selection aSel
= m_pImplEdit
->GetSelection();
1030 if ( aSel
.Min() != aSel
.Max() )
1032 aSel
.Min() = FindPos( aSel
.Min() );
1033 aSel
.Max() = FindPos( aSel
.Max() );
1037 aSel
.Min() = FindPos( aSel
.Min() );
1038 aSel
.Max() = aSel
.Min();
1041 ShowDropDown( true );
1042 m_pFloatingEdit
->getEdit().GrabFocus();
1043 m_pFloatingEdit
->getEdit().SetSelection( aSel
);
1044 vcl::Window
* pFocusWin
= Application::GetFocusWindow();
1045 pFocusWin
->KeyInput( *rNEvt
.GetKeyEvent() );
1049 bResult
= Edit::PreNotify(rNEvt
);
1058 StlSyntaxSequence
< OUString
> lcl_convertMultiLineToList( const OUString
& _rCompsedTextWithLineBreaks
)
1060 sal_Int32 nLines
= comphelper::string::getTokenCount(_rCompsedTextWithLineBreaks
, '\n');
1061 StlSyntaxSequence
< OUString
> aStrings( nLines
);
1064 StlSyntaxSequence
< OUString
>::iterator stringItem
= aStrings
.begin();
1068 *stringItem
= _rCompsedTextWithLineBreaks
.getToken( 0, '\n', nIdx
);
1076 OUString
lcl_convertListToMultiLine( const StlSyntaxSequence
< OUString
>& _rStrings
)
1078 OUStringBuffer sMultiLineText
;
1079 for ( StlSyntaxSequence
< OUString
>::const_iterator item
= _rStrings
.begin();
1080 item
!= _rStrings
.end();
1083 sMultiLineText
.append(*item
);
1084 if ( ++item
!= _rStrings
.end() )
1085 sMultiLineText
.append("\n");
1087 return sMultiLineText
.makeStringAndClear();
1091 OUString
lcl_convertListToDisplayText( const StlSyntaxSequence
< OUString
>& _rStrings
)
1093 OUStringBuffer aComposed
;
1094 for ( StlSyntaxSequence
< OUString
>::const_iterator strings
= _rStrings
.begin();
1095 strings
!= _rStrings
.end();
1099 if ( strings
!= _rStrings
.begin() )
1100 aComposed
.append( ';' );
1101 aComposed
.append( '\"' );
1102 aComposed
.append( *strings
);
1103 aComposed
.append( '\"' );
1105 return aComposed
.makeStringAndClear();
1110 #define STD_HEIGHT 100
1111 void DropDownEditControl::ShowDropDown( bool bShow
)
1115 ::Point aMePos
= GetPosPixel();
1116 aMePos
= GetParent()->OutputToScreenPixel( aMePos
);
1117 ::Size aSize
=GetSizePixel();
1118 ::tools::Rectangle
aRect(aMePos
,aSize
);
1119 aSize
.setHeight( STD_HEIGHT
);
1120 m_pFloatingEdit
->SetOutputSizePixel(aSize
);
1121 m_pFloatingEdit
->StartPopupMode( aRect
, FloatWinPopupFlags::Down
);
1123 m_pFloatingEdit
->Show();
1124 m_pFloatingEdit
->getEdit().GrabFocus();
1125 m_pFloatingEdit
->getEdit().SetSelection(Selection(m_pFloatingEdit
->getEdit().GetText().getLength()));
1127 if ( m_nOperationMode
== eMultiLineText
)
1128 m_pFloatingEdit
->getEdit().SetText( m_pImplEdit
->GetText() );
1129 m_pImplEdit
->SetText("");
1133 m_pFloatingEdit
->Hide();
1134 m_pFloatingEdit
->Invalidate();
1135 m_pFloatingEdit
->Update();
1137 // transfer the text from the floating edit to our own edit
1138 OUString
sDisplayText( m_pFloatingEdit
->getEdit().GetText() );
1139 if ( m_nOperationMode
== eStringList
)
1140 sDisplayText
= lcl_convertListToDisplayText( lcl_convertMultiLineToList( sDisplayText
) );
1142 m_pImplEdit
->SetText( sDisplayText
);
1143 GetParent()->Invalidate( InvalidateFlags::Children
);
1144 m_bDropdown
= false;
1145 m_pImplEdit
->GrabFocus();
1150 long DropDownEditControl::FindPos(long nSinglePos
)
1154 OUString aStr
= m_pFloatingEdit
->getEdit().GetText();
1155 OUString aStr1
= GetText();
1157 if ((nSinglePos
== 0) || (nSinglePos
== aStr1
.getLength()))
1162 if (!aStr
.isEmpty())
1167 OUString aInput
= aStr
.getToken(0, '\n', nIdx
);
1169 if (!aInput
.isEmpty())
1171 aOutput
+= "\"" + aInput
+ "\"";
1175 if (nSinglePos
<= aOutput
.getLength())
1177 nPos
=nSinglePos
-nDiff
;
1183 aInput
=aStr
.getToken(0, '\n', nIdx
);
1184 if (!aInput
.isEmpty())
1186 aOutput
+= ";\"" + aInput
+ "\"";
1189 if (nSinglePos
<= aOutput
.getLength())
1191 nPos
=nSinglePos
-nDiff
;
1202 IMPL_LINK_NOARG( DropDownEditControl
, ReturnHdl
, FloatingWindow
*, void)
1204 OUString aStr
= m_pFloatingEdit
->getEdit().GetText();
1205 OUString aStr2
= GetText();
1206 ShowDropDown(false);
1208 if (aStr
!=aStr2
|| ( m_nOperationMode
== eStringList
) )
1211 m_pHelper
->notifyModifiedValue();
1216 IMPL_LINK_NOARG( DropDownEditControl
, DropDownHdl
, Button
*, void )
1218 ShowDropDown(!m_bDropdown
);
1222 void DropDownEditControl::SetStringListValue( const StlSyntaxSequence
< OUString
>& _rStrings
)
1224 SetText( lcl_convertListToDisplayText( _rStrings
) );
1225 m_pFloatingEdit
->getEdit().SetText( lcl_convertListToMultiLine( _rStrings
) );
1229 StlSyntaxSequence
< OUString
> DropDownEditControl::GetStringListValue() const
1231 return lcl_convertMultiLineToList( m_pFloatingEdit
->getEdit().GetText() );
1235 void DropDownEditControl::SetTextValue( const OUString
& _rText
)
1237 OSL_PRECOND( m_nOperationMode
== eMultiLineText
, "DropDownEditControl::SetTextValue: illegal call!" );
1239 m_pFloatingEdit
->getEdit().SetText( _rText
);
1244 OUString
DropDownEditControl::GetTextValue() const
1246 OSL_PRECOND( m_nOperationMode
== eMultiLineText
, "DropDownEditControl::GetTextValue: illegal call!" );
1251 //= OMultilineEditControl
1254 OMultilineEditControl::OMultilineEditControl( vcl::Window
* pParent
, MultiLineOperationMode _eMode
, WinBits nWinStyle
)
1255 :OMultilineEditControl_Base( _eMode
== eMultiLineText
? PropertyControlType::MultiLineTextField
: PropertyControlType::StringListField
1257 , ( nWinStyle
| WB_DIALOGCONTROL
) & ( ~WB_READONLY
| ~WB_DROPDOWN
)
1260 getTypedControlWindow()->setOperationMode( _eMode
);
1261 getTypedControlWindow()->setControlHelper( *this );
1265 void SAL_CALL
OMultilineEditControl::setValue( const Any
& _rValue
)
1267 impl_checkDisposed_throw();
1269 switch ( getTypedControlWindow()->getOperationMode() )
1271 case eMultiLineText
:
1274 if ( !( _rValue
>>= sText
) && _rValue
.hasValue() )
1275 throw IllegalTypeException();
1276 getTypedControlWindow()->SetTextValue( sText
);
1281 Sequence
< OUString
> aStringLines
;
1282 if ( !( _rValue
>>= aStringLines
) && _rValue
.hasValue() )
1283 throw IllegalTypeException();
1284 getTypedControlWindow()->SetStringListValue( StlSyntaxSequence
<OUString
>(aStringLines
) );
1291 Any SAL_CALL
OMultilineEditControl::getValue()
1293 impl_checkDisposed_throw();
1296 switch ( getTypedControlWindow()->getOperationMode() )
1298 case eMultiLineText
:
1299 aValue
<<= getTypedControlWindow()->GetTextValue();
1302 aValue
<<= getTypedControlWindow()->GetStringListValue();
1309 Type SAL_CALL
OMultilineEditControl::getValueType()
1311 if ( getTypedControlWindow()->getOperationMode() == eMultiLineText
)
1312 return ::cppu::UnoType
<OUString
>::get();
1313 return cppu::UnoType
<Sequence
< OUString
>>::get();
1320 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */