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 <rtl/math.hxx>
32 #include <sfx2/objsh.hxx>
35 // ugly dependencies for the OColorControl
36 #include <svx/svxids.hrc>
37 #include <svx/drawitem.hxx>
38 #include <svx/xtable.hxx>
40 #include <vcl/floatwin.hxx>
41 #include <svtools/svmedit.hxx>
42 #include <svtools/colorcfg.hxx>
43 #include <unotools/syslocale.hxx>
44 #include <unotools/datetime.hxx>
45 #include <i18nlangtag/languagetag.hxx>
46 #include <vcl/button.hxx>
47 #include <vcl/svapp.hxx>
48 #include <vcl/settings.hxx>
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
;
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
)
83 if ( !( _rValue
>>= aUNOTime
) )
85 getTypedControlWindow()->SetText( "" );
86 getTypedControlWindow()->SetEmptyTime();
90 getTypedControlWindow()->SetTime( ::tools::Time(aUNOTime
) );
95 Any SAL_CALL
OTimeControl::getValue()
98 if ( !getTypedControlWindow()->GetText().isEmpty() )
100 aPropValue
<<= getTypedControlWindow()->GetTime().GetUNOTime();
106 Type SAL_CALL
OTimeControl::getValueType()
108 return ::cppu::UnoType
<util::Time
>::get();
115 ODateControl::ODateControl( vcl::Window
* pParent
, WinBits nWinStyle
)
116 :ODateControl_Base( PropertyControlType::DateField
, pParent
, nWinStyle
| WB_DROPDOWN
)
118 CalendarField
* 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( ExtDateFieldFormat::SystemShortYYYY
);
127 pControlWindow
->EnableEmptyFieldValue( true );
131 void SAL_CALL
ODateControl::setValue( const Any
& _rValue
)
134 if ( !( _rValue
>>= aUNODate
) )
136 getTypedControlWindow()->SetText( "" );
137 getTypedControlWindow()->SetEmptyDate();
141 ::Date
aDate( aUNODate
.Day
, aUNODate
.Month
, aUNODate
.Year
);
142 getTypedControlWindow()->SetDate( aDate
);
147 Any SAL_CALL
ODateControl::getValue()
150 if ( !getTypedControlWindow()->GetText().isEmpty() )
152 ::Date
aDate( getTypedControlWindow()->GetDate() );
153 aPropValue
<<= aDate
.GetUNODate();
159 Type SAL_CALL
ODateControl::getValueType()
161 return ::cppu::UnoType
<util::Date
>::get();
168 OEditControl::OEditControl(vcl::Window
* _pParent
, bool _bPW
, WinBits _nWinStyle
)
169 :OEditControl_Base( _bPW
? PropertyControlType::CharacterField
: PropertyControlType::TextField
, _pParent
, _nWinStyle
)
171 m_bIsPassword
= _bPW
;
174 getTypedControlWindow()->SetMaxTextLen( 1 );
178 void SAL_CALL
OEditControl::setValue( const Any
& _rValue
)
183 sal_Int16 nValue
= 0;
187 sText
= OUString(static_cast<sal_Unicode
>(nValue
));
193 getTypedControlWindow()->SetText( sText
);
197 Any SAL_CALL
OEditControl::getValue()
201 OUString
sText( getTypedControlWindow()->GetText() );
204 if ( !sText
.isEmpty() )
205 aPropValue
<<= (sal_Int16
)sText
[0];
208 aPropValue
<<= sText
;
214 Type SAL_CALL
OEditControl::getValueType()
216 return m_bIsPassword
? ::cppu::UnoType
<sal_Int16
>::get() : ::cppu::UnoType
<OUString
>::get();
220 void OEditControl::setModified()
222 OEditControl_Base::setModified();
224 // for password controls, we fire a commit for every single change
226 notifyModifiedValue();
230 static long ImplCalcLongValue( double nValue
, sal_uInt16 nDigits
)
233 for ( sal_uInt16 d
= 0; d
< nDigits
; ++d
)
236 if ( n
> std::numeric_limits
< long >::max() )
237 return std::numeric_limits
< long >::max();
242 static double ImplCalcDoubleValue( long nValue
, sal_uInt16 nDigits
)
245 for ( sal_uInt16 d
= 0; d
< nDigits
; ++d
)
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
)
272 if ( !_rValue
.hasValue() )
274 getTypedControlWindow()->SetText( "" );
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()
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
);
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
309 util::DateTime aUNODateTime
;
310 ::utl::typeConvert( aDateTime
, aUNODateTime
);
312 aPropValue
<<= aUNODateTime
;
318 Type SAL_CALL
ODateTimeControl::getValueType()
320 return ::cppu::UnoType
<util::DateTime
>::get();
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( LINESTYLE_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();
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()
422 OUString sText
= getTypedControlWindow()->GetText();
423 return makeAny( sText
);
427 void SAL_CALL
OHyperlinkControl::setValue( const Any
& _value
)
431 getTypedControlWindow()->SetText( sText
);
435 Type SAL_CALL
OHyperlinkControl::getValueType()
437 return ::cppu::UnoType
<OUString
>::get();
441 void SAL_CALL
OHyperlinkControl::addActionListener( const Reference
< XActionListener
>& listener
)
444 m_aActionListeners
.addInterface( listener
);
448 void SAL_CALL
OHyperlinkControl::removeActionListener( const Reference
< XActionListener
>& listener
)
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
, void*, void )
465 ActionEvent
aEvent( *this, "clicked" );
466 m_aActionListeners
.forEach
< XActionListener
>(
467 [&aEvent
] (uno::Reference
<awt::XActionListener
> const& xListener
)
468 { return xListener
->actionPerformed(aEvent
); });
475 ONumericControl::ONumericControl( vcl::Window
* _pParent
, WinBits _nWinStyle
)
476 :ONumericControl_Base( PropertyControlType::NumericField
, _pParent
, _nWinStyle
)
477 ,m_eValueUnit( FUNIT_NONE
)
478 ,m_nFieldToUNOValueFactor( 1 )
480 MetricField::SetDefaultUnit( FUNIT_NONE
);
482 getTypedControlWindow()->EnableEmptyFieldValue( true );
483 getTypedControlWindow()->SetStrictFormat( true );
484 Optional
< double > value( getMaxValue() );
485 value
.Value
= -value
.Value
;
486 setMinValue( value
);
490 ::sal_Int16 SAL_CALL
ONumericControl::getDecimalDigits()
492 return getTypedControlWindow()->GetDecimalDigits();
496 void SAL_CALL
ONumericControl::setDecimalDigits( ::sal_Int16 _decimaldigits
)
498 getTypedControlWindow()->SetDecimalDigits( _decimaldigits
);
502 Optional
< double > SAL_CALL
ONumericControl::getMinValue()
504 Optional
< double > aReturn( true, 0 );
506 sal_Int64 minValue
= getTypedControlWindow()->GetMin();
507 if ( minValue
== std::numeric_limits
< sal_Int64
>::min() )
508 aReturn
.IsPresent
= false;
510 aReturn
.Value
= (double)minValue
;
516 void SAL_CALL
ONumericControl::setMinValue( const Optional
< double >& _minvalue
)
518 if ( !_minvalue
.IsPresent
)
519 getTypedControlWindow()->SetMin( std::numeric_limits
< sal_Int64
>::min() );
521 getTypedControlWindow()->SetMin( impl_apiValueToFieldValue_nothrow( _minvalue
.Value
) , m_eValueUnit
);
525 Optional
< double > SAL_CALL
ONumericControl::getMaxValue()
527 Optional
< double > aReturn( true, 0 );
529 sal_Int64 maxValue
= getTypedControlWindow()->GetMax();
530 if ( maxValue
== std::numeric_limits
< sal_Int64
>::max() )
531 aReturn
.IsPresent
= false;
533 aReturn
.Value
= (double)maxValue
;
539 void SAL_CALL
ONumericControl::setMaxValue( const Optional
< double >& _maxvalue
)
541 if ( !_maxvalue
.IsPresent
)
542 getTypedControlWindow()->SetMax( std::numeric_limits
< sal_Int64
>::max() );
544 getTypedControlWindow()->SetMax( impl_apiValueToFieldValue_nothrow( _maxvalue
.Value
), m_eValueUnit
);
548 ::sal_Int16 SAL_CALL
ONumericControl::getDisplayUnit()
550 return VCLUnoHelper::ConvertToMeasurementUnit( getTypedControlWindow()->GetUnit(), 1 );
554 void SAL_CALL
ONumericControl::setDisplayUnit( ::sal_Int16 _displayunit
)
556 if ( ( _displayunit
< MeasureUnit::MM_100TH
) || ( _displayunit
> MeasureUnit::PERCENT
) )
557 throw IllegalArgumentException();
558 if ( ( _displayunit
== MeasureUnit::MM_100TH
)
559 || ( _displayunit
== MeasureUnit::MM_10TH
)
560 || ( _displayunit
== MeasureUnit::INCH_1000TH
)
561 || ( _displayunit
== MeasureUnit::INCH_100TH
)
562 || ( _displayunit
== MeasureUnit::INCH_10TH
)
563 || ( _displayunit
== MeasureUnit::PERCENT
)
565 throw IllegalArgumentException();
567 sal_Int16 nDummyFactor
= 1;
568 FieldUnit eFieldUnit
= VCLUnoHelper::ConvertToFieldUnit( _displayunit
, nDummyFactor
);
569 if ( nDummyFactor
!= 1 )
570 // everything which survived the checks above should result in a factor of 1, i.e.,
571 // it should have a direct counterpart as FieldUnit
572 throw RuntimeException();
573 getTypedControlWindow()->MetricFormatter::SetUnit( eFieldUnit
);
577 ::sal_Int16 SAL_CALL
ONumericControl::getValueUnit()
579 return VCLUnoHelper::ConvertToMeasurementUnit( m_eValueUnit
, m_nFieldToUNOValueFactor
);
583 void SAL_CALL
ONumericControl::setValueUnit( ::sal_Int16 _valueunit
)
585 if ( ( _valueunit
< MeasureUnit::MM_100TH
) || ( _valueunit
> MeasureUnit::PERCENT
) )
586 throw IllegalArgumentException();
587 m_eValueUnit
= VCLUnoHelper::ConvertToFieldUnit( _valueunit
, m_nFieldToUNOValueFactor
);
591 void SAL_CALL
ONumericControl::setValue( const Any
& _rValue
)
593 if ( !_rValue
.hasValue() )
595 getTypedControlWindow()->SetText( "" );
596 getTypedControlWindow()->SetEmptyFieldValue();
601 OSL_VERIFY( _rValue
>>= nValue
);
602 long nControlValue
= impl_apiValueToFieldValue_nothrow( nValue
);
603 getTypedControlWindow()->SetValue( nControlValue
, m_eValueUnit
);
608 long ONumericControl::impl_apiValueToFieldValue_nothrow( double _nApiValue
) const
610 long nControlValue
= ImplCalcLongValue( _nApiValue
, getTypedControlWindow()->GetDecimalDigits() );
611 nControlValue
/= m_nFieldToUNOValueFactor
;
612 return nControlValue
;
616 double ONumericControl::impl_fieldValueToApiValue_nothrow( sal_Int64 _nFieldValue
) const
618 double nApiValue
= ImplCalcDoubleValue( (long)_nFieldValue
, getTypedControlWindow()->GetDecimalDigits() );
619 nApiValue
*= m_nFieldToUNOValueFactor
;
624 Any SAL_CALL
ONumericControl::getValue()
627 if ( !getTypedControlWindow()->GetText().isEmpty() )
629 double nValue
= impl_fieldValueToApiValue_nothrow( getTypedControlWindow()->GetValue( m_eValueUnit
) );
630 aPropValue
<<= nValue
;
636 Type SAL_CALL
ONumericControl::getValueType()
638 return ::cppu::UnoType
<double>::get();
644 #define LB_DEFAULT_COUNT 20
646 OColorControl::OColorControl(vcl::Window
* pParent
, WinBits nWinStyle
)
647 : OColorControl_Base(PropertyControlType::ColorListBox
, pParent
, nWinStyle
)
649 getTypedControlWindow()->SetSlotId(SID_FM_CTL_PROPERTIES
);
652 void SAL_CALL
OColorControl::setValue( const Any
& _rValue
)
654 css::util::Color nColor
= COL_TRANSPARENT
;
655 if (_rValue
.hasValue())
657 getTypedControlWindow()->SelectEntry(::Color((ColorData
)nColor
));
660 Any SAL_CALL
OColorControl::getValue()
663 ::Color aRgbCol
= getTypedControlWindow()->GetSelectEntryColor();
664 if (aRgbCol
== COL_TRANSPARENT
)
666 aPropValue
<<= (css::util::Color
)aRgbCol
.GetColor();
670 Type SAL_CALL
OColorControl::getValueType()
672 return ::cppu::UnoType
<sal_Int32
>::get();
675 void OColorControl::setModified()
677 OColorControl_Base::setModified();
680 notifyModifiedValue();
685 OListboxControl::OListboxControl( vcl::Window
* pParent
, WinBits nWinStyle
)
686 :OListboxControl_Base( PropertyControlType::ListBox
, pParent
, nWinStyle
)
688 getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT
);
689 if ( ( nWinStyle
& WB_READONLY
) != 0 )
691 getTypedControlWindow()->SetReadOnly();
692 getTypedControlWindow()->Enable();
697 Any SAL_CALL
OListboxControl::getValue()
699 OUString
sControlValue( getTypedControlWindow()->GetSelectEntry() );
702 if ( !sControlValue
.isEmpty() )
703 aPropValue
<<= sControlValue
;
708 Type SAL_CALL
OListboxControl::getValueType()
710 return ::cppu::UnoType
<OUString
>::get();
714 void SAL_CALL
OListboxControl::setValue( const Any
& _rValue
)
716 if ( !_rValue
.hasValue() )
717 getTypedControlWindow()->SetNoSelection();
721 _rValue
>>= sSelection
;
723 if ( !sSelection
.equals( getTypedControlWindow()->GetSelectEntry() ) )
724 getTypedControlWindow()->SelectEntry( sSelection
);
726 if ( !getTypedControlWindow()->IsEntrySelected( sSelection
) )
728 getTypedControlWindow()->InsertEntry( sSelection
, 0 );
729 getTypedControlWindow()->SelectEntry( sSelection
);
735 void SAL_CALL
OListboxControl::clearList()
737 getTypedControlWindow()->Clear();
741 void SAL_CALL
OListboxControl::prependListEntry( const OUString
& NewEntry
)
743 getTypedControlWindow()->InsertEntry( NewEntry
, 0 );
747 void SAL_CALL
OListboxControl::appendListEntry( const OUString
& NewEntry
)
749 getTypedControlWindow()->InsertEntry( NewEntry
);
752 Sequence
< OUString
> SAL_CALL
OListboxControl::getListEntries( )
754 const sal_Int32 nCount
= getTypedControlWindow()->GetEntryCount();
755 Sequence
< OUString
> aRet(nCount
);
756 OUString
* pIter
= aRet
.getArray();
757 for (sal_Int32 i
= 0; i
< nCount
; ++i
,++pIter
)
758 *pIter
= getTypedControlWindow()->GetEntry(i
);
764 void OListboxControl::setModified()
766 OListboxControl_Base::setModified();
768 if ( !getTypedControlWindow()->IsTravelSelect() )
770 notifyModifiedValue();
777 OComboboxControl::OComboboxControl( vcl::Window
* pParent
, WinBits nWinStyle
)
778 :OComboboxControl_Base( PropertyControlType::ComboBox
, pParent
, nWinStyle
)
780 getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT
);
781 getTypedControlWindow()->SetSelectHdl( LINK( this, OComboboxControl
, OnEntrySelected
) );
785 void SAL_CALL
OComboboxControl::setValue( const Any
& _rValue
)
789 getTypedControlWindow()->SetText( sText
);
793 Any SAL_CALL
OComboboxControl::getValue()
795 return makeAny( OUString( getTypedControlWindow()->GetText() ) );
799 Type SAL_CALL
OComboboxControl::getValueType()
801 return ::cppu::UnoType
<OUString
>::get();
805 void SAL_CALL
OComboboxControl::clearList()
807 getTypedControlWindow()->Clear();
811 void SAL_CALL
OComboboxControl::prependListEntry( const OUString
& NewEntry
)
813 getTypedControlWindow()->InsertEntry( NewEntry
, 0 );
817 void SAL_CALL
OComboboxControl::appendListEntry( const OUString
& NewEntry
)
819 getTypedControlWindow()->InsertEntry( NewEntry
);
822 Sequence
< OUString
> SAL_CALL
OComboboxControl::getListEntries( )
824 const sal_Int32 nCount
= getTypedControlWindow()->GetEntryCount();
825 Sequence
< OUString
> aRet(nCount
);
826 OUString
* pIter
= aRet
.getArray();
827 for (sal_Int32 i
= 0; i
< nCount
; ++i
,++pIter
)
828 *pIter
= getTypedControlWindow()->GetEntry(i
);
834 IMPL_LINK_NOARG( OComboboxControl
, OnEntrySelected
, ComboBox
&, void )
836 if ( !getTypedControlWindow()->IsTravelSelect() )
838 notifyModifiedValue();
842 //= OMultilineFloatingEdit
844 class OMultilineFloatingEdit
: public FloatingWindow
847 VclPtr
<MultiLineEdit
> m_aImplEdit
;
850 virtual void Resize() override
;
853 explicit OMultilineFloatingEdit(vcl::Window
* _pParen
);
854 virtual ~OMultilineFloatingEdit() override
;
855 virtual void dispose() override
;
856 MultiLineEdit
& getEdit() { return *m_aImplEdit
.get(); }
859 virtual bool PreNotify(NotifyEvent
& _rNEvt
) override
;
863 OMultilineFloatingEdit::OMultilineFloatingEdit(vcl::Window
* _pParent
)
864 :FloatingWindow(_pParent
, WB_BORDER
)
865 ,m_aImplEdit(VclPtr
<MultiLineEdit
>::Create(this, WB_VSCROLL
|WB_IGNORETAB
|WB_NOBORDER
))
870 OMultilineFloatingEdit::~OMultilineFloatingEdit()
875 void OMultilineFloatingEdit::dispose()
877 m_aImplEdit
.disposeAndClear();
878 FloatingWindow::dispose();
881 void OMultilineFloatingEdit::Resize()
883 m_aImplEdit
->SetSizePixel(GetOutputSizePixel());
887 bool OMultilineFloatingEdit::PreNotify(NotifyEvent
& _rNEvt
)
891 MouseNotifyEvent nSwitch
= _rNEvt
.GetType();
892 if (MouseNotifyEvent::KEYINPUT
== nSwitch
)
894 const vcl::KeyCode
& aKeyCode
= _rNEvt
.GetKeyEvent()->GetKeyCode();
895 sal_uInt16 nKey
= aKeyCode
.GetCode();
897 if ( ( (KEY_RETURN
== nKey
)
898 && !aKeyCode
.IsShift()
900 || ( (KEY_UP
== nKey
)
908 bResult
=FloatingWindow::PreNotify(_rNEvt
);
911 bResult
=FloatingWindow::PreNotify(_rNEvt
);
917 //= DropDownEditControl_Base
920 DropDownEditControl::DropDownEditControl( vcl::Window
* _pParent
, WinBits _nStyle
)
921 :Edit( _pParent
, _nStyle
)
922 ,m_pFloatingEdit( nullptr )
923 ,m_pDropdownButton( nullptr )
924 ,m_nOperationMode( eStringList
)
928 SetCompoundControl( true );
930 m_pImplEdit
= VclPtr
<MultiLineEdit
>::Create( this, WB_TABSTOP
| WB_IGNORETAB
| WB_NOBORDER
| (_nStyle
& WB_READONLY
) );
931 SetSubEdit( m_pImplEdit
);
934 if ( _nStyle
& WB_DROPDOWN
)
936 m_pDropdownButton
= VclPtr
<PushButton
>::Create( this, WB_NOLIGHTBORDER
| WB_RECTSTYLE
| WB_NOTABSTOP
);
937 m_pDropdownButton
->SetSymbol(SymbolType::SPIN_DOWN
);
938 m_pDropdownButton
->SetClickHdl( LINK( this, DropDownEditControl
, DropDownHdl
) );
939 m_pDropdownButton
->Show();
942 m_pFloatingEdit
= VclPtr
<OMultilineFloatingEdit
>::Create(this);
944 m_pFloatingEdit
->SetPopupModeEndHdl( LINK( this, DropDownEditControl
, ReturnHdl
) );
945 m_pFloatingEdit
->getEdit().SetReadOnly( ( _nStyle
& WB_READONLY
) != 0 );
949 void DropDownEditControl::setControlHelper( CommonBehaviourControlHelper
& _rControlHelper
)
951 m_pHelper
= &_rControlHelper
;
952 m_pFloatingEdit
->getEdit().SetModifyHdl( LINK( &_rControlHelper
, CommonBehaviourControlHelper
, EditModifiedHdl
) );
953 m_pImplEdit
->SetGetFocusHdl( LINK( &_rControlHelper
, CommonBehaviourControlHelper
, GetFocusHdl
) );
954 m_pImplEdit
->SetModifyHdl( LINK( &_rControlHelper
, CommonBehaviourControlHelper
, EditModifiedHdl
) );
955 m_pImplEdit
->SetLoseFocusHdl( LINK( &_rControlHelper
, CommonBehaviourControlHelper
, LoseFocusHdl
) );
959 DropDownEditControl::~DropDownEditControl()
964 void DropDownEditControl::dispose()
967 m_pImplEdit
.disposeAndClear();
968 m_pFloatingEdit
.disposeAndClear();
969 m_pDropdownButton
.disposeAndClear();
974 void DropDownEditControl::Resize()
976 ::Size aOutSz
= GetOutputSizePixel();
978 if (m_pDropdownButton
!=nullptr)
980 long nSBWidth
= GetSettings().GetStyleSettings().GetScrollBarSize();
981 nSBWidth
= CalcZoom( nSBWidth
);
982 m_pImplEdit
->setPosSizePixel( 0, 1, aOutSz
.Width() - nSBWidth
, aOutSz
.Height()-2 );
983 m_pDropdownButton
->setPosSizePixel( aOutSz
.Width() - nSBWidth
, 0, nSBWidth
, aOutSz
.Height() );
986 m_pImplEdit
->setPosSizePixel( 0, 1, aOutSz
.Width(), aOutSz
.Height()-2 );
990 bool DropDownEditControl::PreNotify( NotifyEvent
& rNEvt
)
994 if (rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
996 const vcl::KeyCode
& aKeyCode
= rNEvt
.GetKeyEvent()->GetKeyCode();
997 sal_uInt16 nKey
= aKeyCode
.GetCode();
999 if ( nKey
== KEY_RETURN
&& !aKeyCode
.IsShift() )
1003 m_pHelper
->LoseFocusHdl( *m_pImplEdit
.get() );
1004 m_pHelper
->activateNextControl();
1007 else if ( nKey
== KEY_DOWN
&& aKeyCode
.IsMod2() )
1010 ShowDropDown( true );
1012 else if ( KEYGROUP_CURSOR
== aKeyCode
.GetGroup()
1014 || KEYGROUP_FKEYS
== aKeyCode
.GetGroup()
1015 || m_nOperationMode
== eMultiLineText
1018 bResult
= Edit::PreNotify( rNEvt
);
1020 else if ( m_nOperationMode
== eStringList
)
1022 Selection aSel
= m_pImplEdit
->GetSelection();
1023 if ( aSel
.Min() != aSel
.Max() )
1025 aSel
.Min() = FindPos( aSel
.Min() );
1026 aSel
.Max() = FindPos( aSel
.Max() );
1030 aSel
.Min() = FindPos( aSel
.Min() );
1031 aSel
.Max() = aSel
.Min();
1034 ShowDropDown( true );
1035 m_pFloatingEdit
->getEdit().GrabFocus();
1036 m_pFloatingEdit
->getEdit().SetSelection( aSel
);
1037 vcl::Window
* pFocusWin
= Application::GetFocusWindow();
1038 pFocusWin
->KeyInput( *rNEvt
.GetKeyEvent() );
1042 bResult
= Edit::PreNotify(rNEvt
);
1051 StlSyntaxSequence
< OUString
> lcl_convertMultiLineToList( const OUString
& _rCompsedTextWithLineBreaks
)
1053 sal_Int32 nLines
= comphelper::string::getTokenCount(_rCompsedTextWithLineBreaks
, '\n');
1054 StlSyntaxSequence
< OUString
> aStrings( nLines
);
1055 StlSyntaxSequence
< OUString
>::iterator stringItem
= aStrings
.begin();
1056 for ( sal_Int32 token
= 0; token
< nLines
; ++token
, ++stringItem
)
1057 *stringItem
= _rCompsedTextWithLineBreaks
.getToken( token
, '\n' );
1061 OUString
lcl_convertListToMultiLine( const StlSyntaxSequence
< OUString
>& _rStrings
)
1063 OUString sMultiLineText
;
1064 for ( StlSyntaxSequence
< OUString
>::const_iterator item
= _rStrings
.begin();
1065 item
!= _rStrings
.end();
1068 sMultiLineText
+= *item
;
1069 if ( ++item
!= _rStrings
.end() )
1070 sMultiLineText
+= "\n";
1072 return sMultiLineText
;
1076 OUString
lcl_convertListToDisplayText( const StlSyntaxSequence
< OUString
>& _rStrings
)
1078 OUStringBuffer aComposed
;
1079 for ( StlSyntaxSequence
< OUString
>::const_iterator strings
= _rStrings
.begin();
1080 strings
!= _rStrings
.end();
1084 if ( strings
!= _rStrings
.begin() )
1085 aComposed
.append( ';' );
1086 aComposed
.append( '\"' );
1087 aComposed
.append( *strings
);
1088 aComposed
.append( '\"' );
1090 return aComposed
.makeStringAndClear();
1095 #define STD_HEIGHT 100
1096 void DropDownEditControl::ShowDropDown( bool bShow
)
1100 ::Point aMePos
= GetPosPixel();
1101 aMePos
= GetParent()->OutputToScreenPixel( aMePos
);
1102 ::Size aSize
=GetSizePixel();
1103 ::tools::Rectangle
aRect(aMePos
,aSize
);
1104 aSize
.Height() = STD_HEIGHT
;
1105 m_pFloatingEdit
->SetOutputSizePixel(aSize
);
1106 m_pFloatingEdit
->StartPopupMode( aRect
, FloatWinPopupFlags::Down
);
1108 m_pFloatingEdit
->Show();
1109 m_pFloatingEdit
->getEdit().GrabFocus();
1110 m_pFloatingEdit
->getEdit().SetSelection(Selection(m_pFloatingEdit
->getEdit().GetText().getLength()));
1112 if ( m_nOperationMode
== eMultiLineText
)
1113 m_pFloatingEdit
->getEdit().SetText( m_pImplEdit
->GetText() );
1114 m_pImplEdit
->SetText("");
1118 m_pFloatingEdit
->Hide();
1119 m_pFloatingEdit
->Invalidate();
1120 m_pFloatingEdit
->Update();
1122 // transfer the text from the floating edit to our own edit
1123 OUString
sDisplayText( m_pFloatingEdit
->getEdit().GetText() );
1124 if ( m_nOperationMode
== eStringList
)
1125 sDisplayText
= lcl_convertListToDisplayText( lcl_convertMultiLineToList( sDisplayText
) );
1127 m_pImplEdit
->SetText( sDisplayText
);
1128 GetParent()->Invalidate( InvalidateFlags::Children
);
1129 m_bDropdown
= false;
1130 m_pImplEdit
->GrabFocus();
1135 long DropDownEditControl::FindPos(long nSinglePos
)
1139 OUString aStr
= m_pFloatingEdit
->getEdit().GetText();
1140 OUString aStr1
= GetText();
1142 if ((nSinglePos
== 0) || (nSinglePos
== aStr1
.getLength()))
1147 if (!aStr
.isEmpty())
1150 sal_Int32 nCount
= comphelper::string::getTokenCount(aStr
, '\n');
1152 OUString aInput
= aStr
.getToken(0,'\n' );
1154 if (!aInput
.isEmpty())
1162 if (nSinglePos
<= aOutput
.getLength())
1164 nPos
=nSinglePos
-nDiff
;
1168 for (sal_Int32 i
=1; i
<nCount
; ++i
)
1170 aInput
=aStr
.getToken((sal_uInt16
)i
, '\n');
1171 if (!aInput
.isEmpty())
1179 if (nSinglePos
<= aOutput
.getLength())
1181 nPos
=nSinglePos
-nDiff
;
1192 IMPL_LINK_NOARG( DropDownEditControl
, ReturnHdl
, FloatingWindow
*, void)
1194 OUString aStr
= m_pFloatingEdit
->getEdit().GetText();
1195 OUString aStr2
= GetText();
1196 ShowDropDown(false);
1198 if (aStr
!=aStr2
|| ( m_nOperationMode
== eStringList
) )
1201 m_pHelper
->notifyModifiedValue();
1206 IMPL_LINK_NOARG( DropDownEditControl
, DropDownHdl
, Button
*, void )
1208 ShowDropDown(!m_bDropdown
);
1212 void DropDownEditControl::SetStringListValue( const StlSyntaxSequence
< OUString
>& _rStrings
)
1214 SetText( lcl_convertListToDisplayText( _rStrings
) );
1215 m_pFloatingEdit
->getEdit().SetText( lcl_convertListToMultiLine( _rStrings
) );
1219 StlSyntaxSequence
< OUString
> DropDownEditControl::GetStringListValue() const
1221 return lcl_convertMultiLineToList( m_pFloatingEdit
->getEdit().GetText() );
1225 void DropDownEditControl::SetTextValue( const OUString
& _rText
)
1227 OSL_PRECOND( m_nOperationMode
== eMultiLineText
, "DropDownEditControl::SetTextValue: illegal call!" );
1229 m_pFloatingEdit
->getEdit().SetText( _rText
);
1234 OUString
DropDownEditControl::GetTextValue() const
1236 OSL_PRECOND( m_nOperationMode
== eMultiLineText
, "DropDownEditControl::GetTextValue: illegal call!" );
1241 //= OMultilineEditControl
1244 OMultilineEditControl::OMultilineEditControl( vcl::Window
* pParent
, MultiLineOperationMode _eMode
, WinBits nWinStyle
)
1245 :OMultilineEditControl_Base( _eMode
== eMultiLineText
? PropertyControlType::MultiLineTextField
: PropertyControlType::StringListField
1247 , ( nWinStyle
| WB_DIALOGCONTROL
) & ( ~WB_READONLY
| ~WB_DROPDOWN
)
1250 getTypedControlWindow()->setOperationMode( _eMode
);
1251 getTypedControlWindow()->setControlHelper( *this );
1255 void SAL_CALL
OMultilineEditControl::setValue( const Any
& _rValue
)
1257 impl_checkDisposed_throw();
1259 switch ( getTypedControlWindow()->getOperationMode() )
1261 case eMultiLineText
:
1264 if ( !( _rValue
>>= sText
) && _rValue
.hasValue() )
1265 throw IllegalTypeException();
1266 getTypedControlWindow()->SetTextValue( sText
);
1271 Sequence
< OUString
> aStringLines
;
1272 if ( !( _rValue
>>= aStringLines
) && _rValue
.hasValue() )
1273 throw IllegalTypeException();
1274 getTypedControlWindow()->SetStringListValue( StlSyntaxSequence
<OUString
>(aStringLines
) );
1281 Any SAL_CALL
OMultilineEditControl::getValue()
1283 impl_checkDisposed_throw();
1286 switch ( getTypedControlWindow()->getOperationMode() )
1288 case eMultiLineText
:
1289 aValue
<<= getTypedControlWindow()->GetTextValue();
1292 aValue
<<= getTypedControlWindow()->GetStringListValue();
1299 Type SAL_CALL
OMultilineEditControl::getValueType()
1301 if ( getTypedControlWindow()->getOperationMode() == eMultiLineText
)
1302 return ::cppu::UnoType
<OUString
>::get();
1303 return cppu::UnoType
<Sequence
< OUString
>>::get();
1310 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */