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 <svl/zforlist.hxx>
44 #include <unotools/syslocale.hxx>
45 #include <unotools/datetime.hxx>
46 #include <i18nlangtag/languagetag.hxx>
47 #include <vcl/button.hxx>
48 #include <vcl/event.hxx>
49 #include <vcl/svapp.hxx>
50 #include <vcl/settings.hxx>
51 #include <vcl/ptrstyle.hxx>
62 using namespace ::com::sun::star
;
63 using namespace ::com::sun::star::uno
;
64 using namespace ::com::sun::star::awt
;
65 using namespace ::com::sun::star::lang
;
66 using namespace ::com::sun::star::util
;
67 using namespace ::com::sun::star::beans
;
68 using namespace ::com::sun::star::inspection
;
74 OTimeControl::OTimeControl( vcl::Window
* pParent
, WinBits nWinStyle
)
75 :OTimeControl_Base( PropertyControlType::TimeField
, pParent
, nWinStyle
)
77 getTypedControlWindow()->SetStrictFormat( true );
78 getTypedControlWindow()->SetFormat( TimeFieldFormat::F_SEC
);
79 getTypedControlWindow()->EnableEmptyFieldValue( true );
83 void SAL_CALL
OTimeControl::setValue( const Any
& _rValue
)
86 if ( !( _rValue
>>= aUNOTime
) )
88 getTypedControlWindow()->SetText( "" );
89 getTypedControlWindow()->SetEmptyTime();
93 getTypedControlWindow()->SetTime( ::tools::Time(aUNOTime
) );
98 Any SAL_CALL
OTimeControl::getValue()
101 if ( !getTypedControlWindow()->GetText().isEmpty() )
103 aPropValue
<<= getTypedControlWindow()->GetTime().GetUNOTime();
109 Type SAL_CALL
OTimeControl::getValueType()
111 return ::cppu::UnoType
<util::Time
>::get();
118 ODateControl::ODateControl( vcl::Window
* pParent
, WinBits nWinStyle
)
119 :ODateControl_Base( PropertyControlType::DateField
, pParent
, nWinStyle
| WB_DROPDOWN
)
121 CalendarField
* pControlWindow
= getTypedControlWindow();
122 pControlWindow
->SetStrictFormat(true);
124 pControlWindow
->SetMin( ::Date( 1,1,1600 ) );
125 pControlWindow
->SetFirst( ::Date( 1,1,1600 ) );
126 pControlWindow
->SetLast( ::Date( 1, 1, 9999 ) );
127 pControlWindow
->SetMax( ::Date( 1, 1, 9999 ) );
129 pControlWindow
->SetExtDateFormat( ExtDateFieldFormat::SystemShortYYYY
);
130 pControlWindow
->EnableEmptyFieldValue( true );
134 void SAL_CALL
ODateControl::setValue( const Any
& _rValue
)
137 if ( !( _rValue
>>= aUNODate
) )
139 getTypedControlWindow()->SetText( "" );
140 getTypedControlWindow()->SetEmptyDate();
144 ::Date
aDate( aUNODate
.Day
, aUNODate
.Month
, aUNODate
.Year
);
145 getTypedControlWindow()->SetDate( aDate
);
150 Any SAL_CALL
ODateControl::getValue()
153 if ( !getTypedControlWindow()->GetText().isEmpty() )
155 ::Date
aDate( getTypedControlWindow()->GetDate() );
156 aPropValue
<<= aDate
.GetUNODate();
162 Type SAL_CALL
ODateControl::getValueType()
164 return ::cppu::UnoType
<util::Date
>::get();
171 OEditControl::OEditControl(vcl::Window
* _pParent
, bool _bPW
, WinBits _nWinStyle
)
172 :OEditControl_Base( _bPW
? PropertyControlType::CharacterField
: PropertyControlType::TextField
, _pParent
, _nWinStyle
)
174 m_bIsPassword
= _bPW
;
177 getTypedControlWindow()->SetMaxTextLen( 1 );
181 void SAL_CALL
OEditControl::setValue( const Any
& _rValue
)
186 sal_Int16 nValue
= 0;
190 sText
= OUString(static_cast<sal_Unicode
>(nValue
));
196 getTypedControlWindow()->SetText( sText
);
200 Any SAL_CALL
OEditControl::getValue()
204 OUString
sText( getTypedControlWindow()->GetText() );
207 if ( !sText
.isEmpty() )
208 aPropValue
<<= static_cast<sal_Int16
>(sText
[0]);
211 aPropValue
<<= sText
;
217 Type SAL_CALL
OEditControl::getValueType()
219 return m_bIsPassword
? ::cppu::UnoType
<sal_Int16
>::get() : ::cppu::UnoType
<OUString
>::get();
223 void OEditControl::setModified()
225 OEditControl_Base::setModified();
227 // for password controls, we fire a commit for every single change
229 notifyModifiedValue();
233 static long ImplCalcLongValue( double nValue
, sal_uInt16 nDigits
)
236 for ( sal_uInt16 d
= 0; d
< nDigits
; ++d
)
239 if ( n
> std::numeric_limits
< long >::max() )
240 return std::numeric_limits
< long >::max();
241 return static_cast<long>(n
);
245 static double ImplCalcDoubleValue( long nValue
, sal_uInt16 nDigits
)
248 for ( sal_uInt16 d
= 0; d
< nDigits
; ++d
)
254 // class ODateTimeControl
257 ODateTimeControl::ODateTimeControl( vcl::Window
* _pParent
, WinBits _nWinStyle
)
258 :ODateTimeControl_Base( PropertyControlType::DateTimeField
, _pParent
, _nWinStyle
)
260 getTypedControlWindow()->EnableEmptyField( true );
262 // determine a default format
263 LanguageType eSysLanguage
= SvtSysLocale().GetLanguageTag().getLanguageType( false);
265 getTypedControlWindow()->SetFormatter( getTypedControlWindow()->StandardFormatter() );
266 SvNumberFormatter
* pFormatter
= getTypedControlWindow()->GetFormatter();
267 sal_uLong nStandardDateTimeFormat
= pFormatter
->GetStandardFormat( SvNumFormatType::DATETIME
, eSysLanguage
);
269 getTypedControlWindow()->SetFormatKey( nStandardDateTimeFormat
);
273 void SAL_CALL
ODateTimeControl::setValue( const Any
& _rValue
)
275 if ( !_rValue
.hasValue() )
277 getTypedControlWindow()->SetText( "" );
281 util::DateTime aUNODateTime
;
282 OSL_VERIFY( _rValue
>>= aUNODateTime
);
284 ::DateTime
aDateTime( ::DateTime::EMPTY
);
285 ::utl::typeConvert( aUNODateTime
, aDateTime
);
287 double nValue
= aDateTime
- ::DateTime( getTypedControlWindow()->GetFormatter()->GetNullDate() );
288 getTypedControlWindow()->SetValue( nValue
);
293 Any SAL_CALL
ODateTimeControl::getValue()
296 if ( !getTypedControlWindow()->GetText().isEmpty() )
298 double nValue
= getTypedControlWindow()->GetValue();
300 ::DateTime
aDateTime( getTypedControlWindow()->GetFormatter()->GetNullDate() );
302 // add the "days" part
303 double nDays
= floor( nValue
);
304 aDateTime
.AddDays( nDays
);
306 // add the "time" part
307 double nTime
= nValue
- nDays
;
308 nTime
= ::rtl::math::round( nTime
* 86400.0 ) / 86400.0;
309 // we're not interested in 100th seconds, and this here prevents rounding errors
310 aDateTime
.AddTime( nTime
);
312 util::DateTime aUNODateTime
;
313 ::utl::typeConvert( aDateTime
, aUNODateTime
);
315 aPropValue
<<= aUNODateTime
;
321 Type SAL_CALL
ODateTimeControl::getValueType()
323 return ::cppu::UnoType
<util::DateTime
>::get();
330 HyperlinkInput::HyperlinkInput( vcl::Window
* _pParent
, WinBits _nWinStyle
)
331 :Edit( _pParent
, _nWinStyle
)
333 ::svtools::ColorConfig aColorConfig
;
334 ::svtools::ColorConfigValue
aLinkColor( aColorConfig
.GetColorValue( ::svtools::LINKS
) );
336 AllSettings
aAllSettings( GetSettings() );
337 StyleSettings
aStyleSettings( aAllSettings
.GetStyleSettings() );
339 vcl::Font
aFieldFont( aStyleSettings
.GetFieldFont() );
340 aFieldFont
.SetUnderline( LINESTYLE_SINGLE
);
341 aFieldFont
.SetColor( aLinkColor
.nColor
);
342 aStyleSettings
.SetFieldFont( aFieldFont
);
344 aStyleSettings
.SetFieldTextColor( aLinkColor
.nColor
);
346 aAllSettings
.SetStyleSettings( aStyleSettings
);
347 SetSettings( aAllSettings
);
351 void HyperlinkInput::MouseMove( const ::MouseEvent
& rMEvt
)
353 Edit::MouseMove( rMEvt
);
355 PointerStyle
ePointerStyle( PointerStyle::Text
);
357 if ( !rMEvt
.IsLeaveWindow() )
359 if ( impl_textHitTest( rMEvt
.GetPosPixel() ) )
360 ePointerStyle
= PointerStyle::RefHand
;
363 SetPointer( ePointerStyle
);
367 void HyperlinkInput::MouseButtonDown( const ::MouseEvent
& rMEvt
)
369 Edit::MouseButtonDown( rMEvt
);
371 if ( impl_textHitTest( rMEvt
.GetPosPixel() ) )
372 m_aMouseButtonDownPos
= rMEvt
.GetPosPixel();
375 m_aMouseButtonDownPos
.setX(-1);
376 m_aMouseButtonDownPos
.setY(-1);
381 void HyperlinkInput::MouseButtonUp( const ::MouseEvent
& rMEvt
)
383 Edit::MouseButtonUp( rMEvt
);
385 impl_checkEndClick( rMEvt
);
389 bool HyperlinkInput::impl_textHitTest( const ::Point
& _rWindowPos
)
391 sal_Int32 nPos
= GetCharPos( _rWindowPos
);
392 return ( ( nPos
!= EDIT_NOLIMIT
) && ( nPos
< GetText().getLength() ) );
396 void HyperlinkInput::impl_checkEndClick( const ::MouseEvent
& rMEvt
)
398 const MouseSettings
& rMouseSettings( GetSettings().GetMouseSettings() );
399 if ( ( std::abs( rMEvt
.GetPosPixel().X() - m_aMouseButtonDownPos
.X() ) < rMouseSettings
.GetStartDragWidth() )
400 && ( std::abs( rMEvt
.GetPosPixel().Y() - m_aMouseButtonDownPos
.Y() ) < rMouseSettings
.GetStartDragHeight() )
402 Application::PostUserEvent( m_aClickHandler
);
406 void HyperlinkInput::Tracking( const TrackingEvent
& rTEvt
)
408 Edit::Tracking( rTEvt
);
410 if ( rTEvt
.IsTrackingEnded() )
411 impl_checkEndClick( rTEvt
.GetMouseEvent() );
415 //= OHyperlinkControl
418 OHyperlinkControl::OHyperlinkControl( vcl::Window
* _pParent
, WinBits _nWinStyle
)
419 :OHyperlinkControl_Base( PropertyControlType::HyperlinkField
, _pParent
, _nWinStyle
)
420 ,m_aActionListeners( m_aMutex
)
422 getTypedControlWindow()->SetClickHdl( LINK( this, OHyperlinkControl
, OnHyperlinkClicked
) );
426 Any SAL_CALL
OHyperlinkControl::getValue()
428 OUString sText
= getTypedControlWindow()->GetText();
429 return makeAny( sText
);
433 void SAL_CALL
OHyperlinkControl::setValue( const Any
& _value
)
437 getTypedControlWindow()->SetText( sText
);
441 Type SAL_CALL
OHyperlinkControl::getValueType()
443 return ::cppu::UnoType
<OUString
>::get();
447 void SAL_CALL
OHyperlinkControl::addActionListener( const Reference
< XActionListener
>& listener
)
450 m_aActionListeners
.addInterface( listener
);
454 void SAL_CALL
OHyperlinkControl::removeActionListener( const Reference
< XActionListener
>& listener
)
456 m_aActionListeners
.removeInterface( listener
);
460 void SAL_CALL
OHyperlinkControl::disposing()
462 OHyperlinkControl_Base::disposing();
464 EventObject
aEvent( *this );
465 m_aActionListeners
.disposeAndClear( aEvent
);
469 IMPL_LINK_NOARG( OHyperlinkControl
, OnHyperlinkClicked
, void*, void )
471 ActionEvent
aEvent( *this, "clicked" );
472 m_aActionListeners
.forEach
< XActionListener
>(
473 [&aEvent
] (uno::Reference
<awt::XActionListener
> const& xListener
)
474 { return xListener
->actionPerformed(aEvent
); });
481 ONumericControl::ONumericControl( vcl::Window
* _pParent
, WinBits _nWinStyle
)
482 :ONumericControl_Base( PropertyControlType::NumericField
, _pParent
, _nWinStyle
)
483 ,m_eValueUnit( FieldUnit::NONE
)
484 ,m_nFieldToUNOValueFactor( 1 )
486 MetricField::SetDefaultUnit( FieldUnit::NONE
);
488 getTypedControlWindow()->EnableEmptyFieldValue( true );
489 getTypedControlWindow()->SetStrictFormat( true );
490 Optional
< double > value( getMaxValue() );
491 value
.Value
= -value
.Value
;
492 setMinValue( value
);
496 ::sal_Int16 SAL_CALL
ONumericControl::getDecimalDigits()
498 return getTypedControlWindow()->GetDecimalDigits();
502 void SAL_CALL
ONumericControl::setDecimalDigits( ::sal_Int16 _decimaldigits
)
504 getTypedControlWindow()->SetDecimalDigits( _decimaldigits
);
508 Optional
< double > SAL_CALL
ONumericControl::getMinValue()
510 Optional
< double > aReturn( true, 0 );
512 sal_Int64 minValue
= getTypedControlWindow()->GetMin();
513 if ( minValue
== std::numeric_limits
< sal_Int64
>::min() )
514 aReturn
.IsPresent
= false;
516 aReturn
.Value
= static_cast<double>(minValue
);
522 void SAL_CALL
ONumericControl::setMinValue( const Optional
< double >& _minvalue
)
524 if ( !_minvalue
.IsPresent
)
525 getTypedControlWindow()->SetMin( std::numeric_limits
< sal_Int64
>::min() );
527 getTypedControlWindow()->SetMin( impl_apiValueToFieldValue_nothrow( _minvalue
.Value
) , m_eValueUnit
);
531 Optional
< double > SAL_CALL
ONumericControl::getMaxValue()
533 Optional
< double > aReturn( true, 0 );
535 sal_Int64 maxValue
= getTypedControlWindow()->GetMax();
536 if ( maxValue
== std::numeric_limits
< sal_Int64
>::max() )
537 aReturn
.IsPresent
= false;
539 aReturn
.Value
= static_cast<double>(maxValue
);
545 void SAL_CALL
ONumericControl::setMaxValue( const Optional
< double >& _maxvalue
)
547 if ( !_maxvalue
.IsPresent
)
548 getTypedControlWindow()->SetMax( std::numeric_limits
< sal_Int64
>::max() );
550 getTypedControlWindow()->SetMax( impl_apiValueToFieldValue_nothrow( _maxvalue
.Value
), m_eValueUnit
);
554 ::sal_Int16 SAL_CALL
ONumericControl::getDisplayUnit()
556 return VCLUnoHelper::ConvertToMeasurementUnit( getTypedControlWindow()->GetUnit(), 1 );
560 void SAL_CALL
ONumericControl::setDisplayUnit( ::sal_Int16 _displayunit
)
562 if ( ( _displayunit
< MeasureUnit::MM_100TH
) || ( _displayunit
> MeasureUnit::PERCENT
) )
563 throw IllegalArgumentException();
564 if ( ( _displayunit
== MeasureUnit::MM_100TH
)
565 || ( _displayunit
== MeasureUnit::MM_10TH
)
566 || ( _displayunit
== MeasureUnit::INCH_1000TH
)
567 || ( _displayunit
== MeasureUnit::INCH_100TH
)
568 || ( _displayunit
== MeasureUnit::INCH_10TH
)
569 || ( _displayunit
== MeasureUnit::PERCENT
)
571 throw IllegalArgumentException();
573 sal_Int16 nDummyFactor
= 1;
574 FieldUnit eFieldUnit
= VCLUnoHelper::ConvertToFieldUnit( _displayunit
, nDummyFactor
);
575 if ( nDummyFactor
!= 1 )
576 // everything which survived the checks above should result in a factor of 1, i.e.,
577 // it should have a direct counterpart as FieldUnit
578 throw RuntimeException();
579 getTypedControlWindow()->MetricFormatter::SetUnit( eFieldUnit
);
583 ::sal_Int16 SAL_CALL
ONumericControl::getValueUnit()
585 return VCLUnoHelper::ConvertToMeasurementUnit( m_eValueUnit
, m_nFieldToUNOValueFactor
);
589 void SAL_CALL
ONumericControl::setValueUnit( ::sal_Int16 _valueunit
)
591 if ( ( _valueunit
< MeasureUnit::MM_100TH
) || ( _valueunit
> MeasureUnit::PERCENT
) )
592 throw IllegalArgumentException();
593 m_eValueUnit
= VCLUnoHelper::ConvertToFieldUnit( _valueunit
, m_nFieldToUNOValueFactor
);
597 void SAL_CALL
ONumericControl::setValue( const Any
& _rValue
)
599 if ( !_rValue
.hasValue() )
601 getTypedControlWindow()->SetText( "" );
602 getTypedControlWindow()->SetEmptyFieldValue();
607 OSL_VERIFY( _rValue
>>= nValue
);
608 long nControlValue
= impl_apiValueToFieldValue_nothrow( nValue
);
609 getTypedControlWindow()->SetValue( nControlValue
, m_eValueUnit
);
614 long ONumericControl::impl_apiValueToFieldValue_nothrow( double _nApiValue
) const
616 long nControlValue
= ImplCalcLongValue( _nApiValue
, getTypedControlWindow()->GetDecimalDigits() );
617 nControlValue
/= m_nFieldToUNOValueFactor
;
618 return nControlValue
;
622 double ONumericControl::impl_fieldValueToApiValue_nothrow( sal_Int64 _nFieldValue
) const
624 double nApiValue
= ImplCalcDoubleValue( static_cast<long>(_nFieldValue
), getTypedControlWindow()->GetDecimalDigits() );
625 nApiValue
*= m_nFieldToUNOValueFactor
;
630 Any SAL_CALL
ONumericControl::getValue()
633 if ( !getTypedControlWindow()->GetText().isEmpty() )
635 double nValue
= impl_fieldValueToApiValue_nothrow( getTypedControlWindow()->GetValue( m_eValueUnit
) );
636 aPropValue
<<= nValue
;
642 Type SAL_CALL
ONumericControl::getValueType()
644 return ::cppu::UnoType
<double>::get();
650 #define LB_DEFAULT_COUNT 20
652 OColorControl::OColorControl(vcl::Window
* pParent
, WinBits nWinStyle
)
653 : OColorControl_Base(PropertyControlType::ColorListBox
, pParent
, nWinStyle
)
655 getTypedControlWindow()->SetSlotId(SID_FM_CTL_PROPERTIES
);
658 void SAL_CALL
OColorControl::setValue( const Any
& _rValue
)
660 css::util::Color nColor
= sal_uInt32(COL_TRANSPARENT
);
661 if (_rValue
.hasValue())
663 getTypedControlWindow()->SelectEntry(nColor
);
666 Any SAL_CALL
OColorControl::getValue()
669 ::Color aRgbCol
= getTypedControlWindow()->GetSelectEntryColor();
670 if (aRgbCol
== COL_TRANSPARENT
)
672 aPropValue
<<= aRgbCol
;
676 Type SAL_CALL
OColorControl::getValueType()
678 return ::cppu::UnoType
<sal_Int32
>::get();
681 void OColorControl::setModified()
683 OColorControl_Base::setModified();
686 notifyModifiedValue();
691 OListboxControl::OListboxControl( vcl::Window
* pParent
, WinBits nWinStyle
)
692 :OListboxControl_Base( PropertyControlType::ListBox
, pParent
, nWinStyle
)
694 getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT
);
695 if ( ( nWinStyle
& WB_READONLY
) != 0 )
697 getTypedControlWindow()->SetReadOnly();
698 getTypedControlWindow()->Enable();
703 Any SAL_CALL
OListboxControl::getValue()
705 OUString
sControlValue( getTypedControlWindow()->GetSelectedEntry() );
708 if ( !sControlValue
.isEmpty() )
709 aPropValue
<<= sControlValue
;
714 Type SAL_CALL
OListboxControl::getValueType()
716 return ::cppu::UnoType
<OUString
>::get();
720 void SAL_CALL
OListboxControl::setValue( const Any
& _rValue
)
722 if ( !_rValue
.hasValue() )
723 getTypedControlWindow()->SetNoSelection();
727 _rValue
>>= sSelection
;
729 if ( sSelection
!= getTypedControlWindow()->GetSelectedEntry() )
730 getTypedControlWindow()->SelectEntry( sSelection
);
732 if ( !getTypedControlWindow()->IsEntrySelected( sSelection
) )
734 getTypedControlWindow()->InsertEntry( sSelection
, 0 );
735 getTypedControlWindow()->SelectEntry( sSelection
);
741 void SAL_CALL
OListboxControl::clearList()
743 getTypedControlWindow()->Clear();
747 void SAL_CALL
OListboxControl::prependListEntry( const OUString
& NewEntry
)
749 getTypedControlWindow()->InsertEntry( NewEntry
, 0 );
753 void SAL_CALL
OListboxControl::appendListEntry( const OUString
& NewEntry
)
755 getTypedControlWindow()->InsertEntry( NewEntry
);
758 Sequence
< OUString
> SAL_CALL
OListboxControl::getListEntries( )
760 const sal_Int32 nCount
= getTypedControlWindow()->GetEntryCount();
761 Sequence
< OUString
> aRet(nCount
);
762 OUString
* pIter
= aRet
.getArray();
763 for (sal_Int32 i
= 0; i
< nCount
; ++i
,++pIter
)
764 *pIter
= getTypedControlWindow()->GetEntry(i
);
770 void OListboxControl::setModified()
772 OListboxControl_Base::setModified();
774 if ( !getTypedControlWindow()->IsTravelSelect() )
776 notifyModifiedValue();
783 OComboboxControl::OComboboxControl( vcl::Window
* pParent
, WinBits nWinStyle
)
784 :OComboboxControl_Base( PropertyControlType::ComboBox
, pParent
, nWinStyle
)
786 getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT
);
787 getTypedControlWindow()->SetSelectHdl( LINK( this, OComboboxControl
, OnEntrySelected
) );
791 void SAL_CALL
OComboboxControl::setValue( const Any
& _rValue
)
795 getTypedControlWindow()->SetText( sText
);
799 Any SAL_CALL
OComboboxControl::getValue()
801 return makeAny( getTypedControlWindow()->GetText() );
805 Type SAL_CALL
OComboboxControl::getValueType()
807 return ::cppu::UnoType
<OUString
>::get();
811 void SAL_CALL
OComboboxControl::clearList()
813 getTypedControlWindow()->Clear();
817 void SAL_CALL
OComboboxControl::prependListEntry( const OUString
& NewEntry
)
819 getTypedControlWindow()->InsertEntry( NewEntry
, 0 );
823 void SAL_CALL
OComboboxControl::appendListEntry( const OUString
& NewEntry
)
825 getTypedControlWindow()->InsertEntry( NewEntry
);
828 Sequence
< OUString
> SAL_CALL
OComboboxControl::getListEntries( )
830 const sal_Int32 nCount
= getTypedControlWindow()->GetEntryCount();
831 Sequence
< OUString
> aRet(nCount
);
832 OUString
* pIter
= aRet
.getArray();
833 for (sal_Int32 i
= 0; i
< nCount
; ++i
,++pIter
)
834 *pIter
= getTypedControlWindow()->GetEntry(i
);
840 IMPL_LINK_NOARG( OComboboxControl
, OnEntrySelected
, ComboBox
&, void )
842 if ( !getTypedControlWindow()->IsTravelSelect() )
844 notifyModifiedValue();
848 //= OMultilineFloatingEdit
850 class OMultilineFloatingEdit
: public FloatingWindow
853 VclPtr
<MultiLineEdit
> m_aImplEdit
;
856 virtual void Resize() override
;
859 explicit OMultilineFloatingEdit(vcl::Window
* _pParen
);
860 virtual ~OMultilineFloatingEdit() override
;
861 virtual void dispose() override
;
862 MultiLineEdit
& getEdit() { return *m_aImplEdit
.get(); }
865 virtual bool PreNotify(NotifyEvent
& _rNEvt
) override
;
869 OMultilineFloatingEdit::OMultilineFloatingEdit(vcl::Window
* _pParent
)
870 :FloatingWindow(_pParent
, WB_BORDER
)
871 ,m_aImplEdit(VclPtr
<MultiLineEdit
>::Create(this, WB_VSCROLL
|WB_IGNORETAB
|WB_NOBORDER
))
876 OMultilineFloatingEdit::~OMultilineFloatingEdit()
881 void OMultilineFloatingEdit::dispose()
883 m_aImplEdit
.disposeAndClear();
884 FloatingWindow::dispose();
887 void OMultilineFloatingEdit::Resize()
889 m_aImplEdit
->SetSizePixel(GetOutputSizePixel());
893 bool OMultilineFloatingEdit::PreNotify(NotifyEvent
& _rNEvt
)
897 MouseNotifyEvent nSwitch
= _rNEvt
.GetType();
898 if (MouseNotifyEvent::KEYINPUT
== nSwitch
)
900 const vcl::KeyCode
& aKeyCode
= _rNEvt
.GetKeyEvent()->GetKeyCode();
901 sal_uInt16 nKey
= aKeyCode
.GetCode();
903 if ( ( (KEY_RETURN
== nKey
)
904 && !aKeyCode
.IsShift()
906 || ( (KEY_UP
== nKey
)
914 bResult
=FloatingWindow::PreNotify(_rNEvt
);
917 bResult
=FloatingWindow::PreNotify(_rNEvt
);
923 //= DropDownEditControl_Base
926 DropDownEditControl::DropDownEditControl( vcl::Window
* _pParent
, WinBits _nStyle
)
927 :Edit( _pParent
, _nStyle
)
928 ,m_pFloatingEdit( nullptr )
929 ,m_pDropdownButton( nullptr )
930 ,m_nOperationMode( eStringList
)
934 SetCompoundControl( true );
936 m_pImplEdit
= VclPtr
<MultiLineEdit
>::Create( this, WB_TABSTOP
| WB_IGNORETAB
| WB_NOBORDER
| (_nStyle
& WB_READONLY
) );
937 SetSubEdit( m_pImplEdit
);
940 if ( _nStyle
& WB_DROPDOWN
)
942 m_pDropdownButton
= VclPtr
<PushButton
>::Create( this, WB_NOLIGHTBORDER
| WB_RECTSTYLE
| WB_NOTABSTOP
);
943 m_pDropdownButton
->SetSymbol(SymbolType::SPIN_DOWN
);
944 m_pDropdownButton
->SetClickHdl( LINK( this, DropDownEditControl
, DropDownHdl
) );
945 m_pDropdownButton
->Show();
948 m_pFloatingEdit
= VclPtr
<OMultilineFloatingEdit
>::Create(this);
950 m_pFloatingEdit
->SetPopupModeEndHdl( LINK( this, DropDownEditControl
, ReturnHdl
) );
951 m_pFloatingEdit
->getEdit().SetReadOnly( ( _nStyle
& WB_READONLY
) != 0 );
955 void DropDownEditControl::setControlHelper( CommonBehaviourControlHelper
& _rControlHelper
)
957 m_pHelper
= &_rControlHelper
;
958 m_pFloatingEdit
->getEdit().SetModifyHdl( LINK( &_rControlHelper
, CommonBehaviourControlHelper
, EditModifiedHdl
) );
959 m_pImplEdit
->SetGetFocusHdl( LINK( &_rControlHelper
, CommonBehaviourControlHelper
, GetFocusHdl
) );
960 m_pImplEdit
->SetModifyHdl( LINK( &_rControlHelper
, CommonBehaviourControlHelper
, EditModifiedHdl
) );
961 m_pImplEdit
->SetLoseFocusHdl( LINK( &_rControlHelper
, CommonBehaviourControlHelper
, LoseFocusHdl
) );
965 DropDownEditControl::~DropDownEditControl()
970 void DropDownEditControl::dispose()
973 m_pImplEdit
.disposeAndClear();
974 m_pFloatingEdit
.disposeAndClear();
975 m_pDropdownButton
.disposeAndClear();
980 void DropDownEditControl::Resize()
982 ::Size aOutSz
= GetOutputSizePixel();
984 if (m_pDropdownButton
!=nullptr)
986 long nSBWidth
= GetSettings().GetStyleSettings().GetScrollBarSize();
987 nSBWidth
= CalcZoom( nSBWidth
);
988 m_pImplEdit
->setPosSizePixel( 0, 1, aOutSz
.Width() - nSBWidth
, aOutSz
.Height()-2 );
989 m_pDropdownButton
->setPosSizePixel( aOutSz
.Width() - nSBWidth
, 0, nSBWidth
, aOutSz
.Height() );
992 m_pImplEdit
->setPosSizePixel( 0, 1, aOutSz
.Width(), aOutSz
.Height()-2 );
996 bool DropDownEditControl::PreNotify( NotifyEvent
& rNEvt
)
1000 if (rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
1002 const vcl::KeyCode
& aKeyCode
= rNEvt
.GetKeyEvent()->GetKeyCode();
1003 sal_uInt16 nKey
= aKeyCode
.GetCode();
1005 if ( nKey
== KEY_RETURN
&& !aKeyCode
.IsShift() )
1009 m_pHelper
->LoseFocusHdl( *m_pImplEdit
.get() );
1010 m_pHelper
->activateNextControl();
1013 else if ( nKey
== KEY_DOWN
&& aKeyCode
.IsMod2() )
1016 ShowDropDown( true );
1018 else if ( KEYGROUP_CURSOR
== aKeyCode
.GetGroup()
1020 || KEYGROUP_FKEYS
== aKeyCode
.GetGroup()
1021 || m_nOperationMode
== eMultiLineText
1024 bResult
= Edit::PreNotify( rNEvt
);
1026 else if ( m_nOperationMode
== eStringList
)
1028 Selection aSel
= m_pImplEdit
->GetSelection();
1029 if ( aSel
.Min() != aSel
.Max() )
1031 aSel
.Min() = FindPos( aSel
.Min() );
1032 aSel
.Max() = FindPos( aSel
.Max() );
1036 aSel
.Min() = FindPos( aSel
.Min() );
1037 aSel
.Max() = aSel
.Min();
1040 ShowDropDown( true );
1041 m_pFloatingEdit
->getEdit().GrabFocus();
1042 m_pFloatingEdit
->getEdit().SetSelection( aSel
);
1043 vcl::Window
* pFocusWin
= Application::GetFocusWindow();
1044 pFocusWin
->KeyInput( *rNEvt
.GetKeyEvent() );
1048 bResult
= Edit::PreNotify(rNEvt
);
1057 StlSyntaxSequence
< OUString
> lcl_convertMultiLineToList( const OUString
& _rCompsedTextWithLineBreaks
)
1059 sal_Int32 nLines
= comphelper::string::getTokenCount(_rCompsedTextWithLineBreaks
, '\n');
1060 StlSyntaxSequence
< OUString
> aStrings( nLines
);
1063 StlSyntaxSequence
< OUString
>::iterator stringItem
= aStrings
.begin();
1067 *stringItem
= _rCompsedTextWithLineBreaks
.getToken( 0, '\n', nIdx
);
1075 OUString
lcl_convertListToMultiLine( const StlSyntaxSequence
< OUString
>& _rStrings
)
1077 OUStringBuffer sMultiLineText
;
1078 for ( StlSyntaxSequence
< OUString
>::const_iterator item
= _rStrings
.begin();
1079 item
!= _rStrings
.end();
1082 sMultiLineText
.append(*item
);
1083 if ( ++item
!= _rStrings
.end() )
1084 sMultiLineText
.append("\n");
1086 return sMultiLineText
.makeStringAndClear();
1090 OUString
lcl_convertListToDisplayText( const StlSyntaxSequence
< OUString
>& _rStrings
)
1092 OUStringBuffer aComposed
;
1093 for ( StlSyntaxSequence
< OUString
>::const_iterator strings
= _rStrings
.begin();
1094 strings
!= _rStrings
.end();
1098 if ( strings
!= _rStrings
.begin() )
1099 aComposed
.append( ';' );
1100 aComposed
.append( '\"' );
1101 aComposed
.append( *strings
);
1102 aComposed
.append( '\"' );
1104 return aComposed
.makeStringAndClear();
1109 #define STD_HEIGHT 100
1110 void DropDownEditControl::ShowDropDown( bool bShow
)
1114 ::Point aMePos
= GetPosPixel();
1115 aMePos
= GetParent()->OutputToScreenPixel( aMePos
);
1116 ::Size aSize
=GetSizePixel();
1117 ::tools::Rectangle
aRect(aMePos
,aSize
);
1118 aSize
.setHeight( STD_HEIGHT
);
1119 m_pFloatingEdit
->SetOutputSizePixel(aSize
);
1120 m_pFloatingEdit
->StartPopupMode( aRect
, FloatWinPopupFlags::Down
);
1122 m_pFloatingEdit
->Show();
1123 m_pFloatingEdit
->getEdit().GrabFocus();
1124 m_pFloatingEdit
->getEdit().SetSelection(Selection(m_pFloatingEdit
->getEdit().GetText().getLength()));
1126 if ( m_nOperationMode
== eMultiLineText
)
1127 m_pFloatingEdit
->getEdit().SetText( m_pImplEdit
->GetText() );
1128 m_pImplEdit
->SetText("");
1132 m_pFloatingEdit
->Hide();
1133 m_pFloatingEdit
->Invalidate();
1134 m_pFloatingEdit
->Update();
1136 // transfer the text from the floating edit to our own edit
1137 OUString
sDisplayText( m_pFloatingEdit
->getEdit().GetText() );
1138 if ( m_nOperationMode
== eStringList
)
1139 sDisplayText
= lcl_convertListToDisplayText( lcl_convertMultiLineToList( sDisplayText
) );
1141 m_pImplEdit
->SetText( sDisplayText
);
1142 GetParent()->Invalidate( InvalidateFlags::Children
);
1143 m_bDropdown
= false;
1144 m_pImplEdit
->GrabFocus();
1149 long DropDownEditControl::FindPos(long nSinglePos
)
1153 OUString aStr
= m_pFloatingEdit
->getEdit().GetText();
1154 OUString aStr1
= GetText();
1156 if ((nSinglePos
== 0) || (nSinglePos
== aStr1
.getLength()))
1161 if (!aStr
.isEmpty())
1166 OUString aInput
= aStr
.getToken(0, '\n', nIdx
);
1168 if (!aInput
.isEmpty())
1176 if (nSinglePos
<= aOutput
.getLength())
1178 nPos
=nSinglePos
-nDiff
;
1184 aInput
=aStr
.getToken(0, '\n', nIdx
);
1185 if (!aInput
.isEmpty())
1193 if (nSinglePos
<= aOutput
.getLength())
1195 nPos
=nSinglePos
-nDiff
;
1206 IMPL_LINK_NOARG( DropDownEditControl
, ReturnHdl
, FloatingWindow
*, void)
1208 OUString aStr
= m_pFloatingEdit
->getEdit().GetText();
1209 OUString aStr2
= GetText();
1210 ShowDropDown(false);
1212 if (aStr
!=aStr2
|| ( m_nOperationMode
== eStringList
) )
1215 m_pHelper
->notifyModifiedValue();
1220 IMPL_LINK_NOARG( DropDownEditControl
, DropDownHdl
, Button
*, void )
1222 ShowDropDown(!m_bDropdown
);
1226 void DropDownEditControl::SetStringListValue( const StlSyntaxSequence
< OUString
>& _rStrings
)
1228 SetText( lcl_convertListToDisplayText( _rStrings
) );
1229 m_pFloatingEdit
->getEdit().SetText( lcl_convertListToMultiLine( _rStrings
) );
1233 StlSyntaxSequence
< OUString
> DropDownEditControl::GetStringListValue() const
1235 return lcl_convertMultiLineToList( m_pFloatingEdit
->getEdit().GetText() );
1239 void DropDownEditControl::SetTextValue( const OUString
& _rText
)
1241 OSL_PRECOND( m_nOperationMode
== eMultiLineText
, "DropDownEditControl::SetTextValue: illegal call!" );
1243 m_pFloatingEdit
->getEdit().SetText( _rText
);
1248 OUString
DropDownEditControl::GetTextValue() const
1250 OSL_PRECOND( m_nOperationMode
== eMultiLineText
, "DropDownEditControl::GetTextValue: illegal call!" );
1255 //= OMultilineEditControl
1258 OMultilineEditControl::OMultilineEditControl( vcl::Window
* pParent
, MultiLineOperationMode _eMode
, WinBits nWinStyle
)
1259 :OMultilineEditControl_Base( _eMode
== eMultiLineText
? PropertyControlType::MultiLineTextField
: PropertyControlType::StringListField
1261 , ( nWinStyle
| WB_DIALOGCONTROL
) & ( ~WB_READONLY
| ~WB_DROPDOWN
)
1264 getTypedControlWindow()->setOperationMode( _eMode
);
1265 getTypedControlWindow()->setControlHelper( *this );
1269 void SAL_CALL
OMultilineEditControl::setValue( const Any
& _rValue
)
1271 impl_checkDisposed_throw();
1273 switch ( getTypedControlWindow()->getOperationMode() )
1275 case eMultiLineText
:
1278 if ( !( _rValue
>>= sText
) && _rValue
.hasValue() )
1279 throw IllegalTypeException();
1280 getTypedControlWindow()->SetTextValue( sText
);
1285 Sequence
< OUString
> aStringLines
;
1286 if ( !( _rValue
>>= aStringLines
) && _rValue
.hasValue() )
1287 throw IllegalTypeException();
1288 getTypedControlWindow()->SetStringListValue( StlSyntaxSequence
<OUString
>(aStringLines
) );
1295 Any SAL_CALL
OMultilineEditControl::getValue()
1297 impl_checkDisposed_throw();
1300 switch ( getTypedControlWindow()->getOperationMode() )
1302 case eMultiLineText
:
1303 aValue
<<= getTypedControlWindow()->GetTextValue();
1306 aValue
<<= getTypedControlWindow()->GetStringListValue();
1313 Type SAL_CALL
OMultilineEditControl::getValueType()
1315 if ( getTypedControlWindow()->getOperationMode() == eMultiLineText
)
1316 return ::cppu::UnoType
<OUString
>::get();
1317 return cppu::UnoType
<Sequence
< OUString
>>::get();
1324 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */