bump product version to 6.3.0.0.beta1
[LibreOffice.git] / extensions / source / propctrlr / standardcontrol.cxx
blob948e97278adb8bbd27465a3ad1529e42c3639278
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "standardcontrol.hxx"
21 #include "pcrcommon.hxx"
23 #include <com/sun/star/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>
53 #include <cstdlib>
54 #include <limits>
55 #include <memory>
58 namespace pcr
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;
71 //= OTimeControl
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 )
85 util::Time aUNOTime;
86 if ( !( _rValue >>= aUNOTime ) )
88 getTypedControlWindow()->SetText( "" );
89 getTypedControlWindow()->SetEmptyTime();
91 else
93 getTypedControlWindow()->SetTime( ::tools::Time(aUNOTime) );
98 Any SAL_CALL OTimeControl::getValue()
100 Any aPropValue;
101 if ( !getTypedControlWindow()->GetText().isEmpty() )
103 aPropValue <<= getTypedControlWindow()->GetTime().GetUNOTime();
105 return aPropValue;
109 Type SAL_CALL OTimeControl::getValueType()
111 return ::cppu::UnoType<util::Time>::get();
115 //= ODateControl
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 )
136 util::Date aUNODate;
137 if ( !( _rValue >>= aUNODate ) )
139 getTypedControlWindow()->SetText( "" );
140 getTypedControlWindow()->SetEmptyDate();
142 else
144 ::Date aDate( aUNODate.Day, aUNODate.Month, aUNODate.Year );
145 getTypedControlWindow()->SetDate( aDate );
150 Any SAL_CALL ODateControl::getValue()
152 Any aPropValue;
153 if ( !getTypedControlWindow()->GetText().isEmpty() )
155 ::Date aDate( getTypedControlWindow()->GetDate() );
156 aPropValue <<= aDate.GetUNODate();
158 return aPropValue;
162 Type SAL_CALL ODateControl::getValueType()
164 return ::cppu::UnoType<util::Date>::get();
168 //= OEditControl
171 OEditControl::OEditControl(vcl::Window* _pParent, bool _bPW, WinBits _nWinStyle)
172 :OEditControl_Base( _bPW ? PropertyControlType::CharacterField : PropertyControlType::TextField, _pParent, _nWinStyle )
174 m_bIsPassword = _bPW;
176 if ( m_bIsPassword )
177 getTypedControlWindow()->SetMaxTextLen( 1 );
181 void SAL_CALL OEditControl::setValue( const Any& _rValue )
183 OUString sText;
184 if ( m_bIsPassword )
186 sal_Int16 nValue = 0;
187 _rValue >>= nValue;
188 if ( nValue )
190 sText = OUString(static_cast<sal_Unicode>(nValue));
193 else
194 _rValue >>= sText;
196 getTypedControlWindow()->SetText( sText );
200 Any SAL_CALL OEditControl::getValue()
202 Any aPropValue;
204 OUString sText( getTypedControlWindow()->GetText() );
205 if ( m_bIsPassword )
207 if ( !sText.isEmpty() )
208 aPropValue <<= static_cast<sal_Int16>(sText[0]);
210 else
211 aPropValue <<= sText;
213 return aPropValue;
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
228 if ( m_bIsPassword )
229 notifyModifiedValue();
233 static long ImplCalcLongValue( double nValue, sal_uInt16 nDigits )
235 double n = nValue;
236 for ( sal_uInt16 d = 0; d < nDigits; ++d )
237 n *= 10;
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 )
247 double n = nValue;
248 for ( sal_uInt16 d = 0; d < nDigits; ++d )
249 n /= 10;
250 return n;
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( "" );
279 else
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()
295 Any aPropValue;
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;
317 return aPropValue;
321 Type SAL_CALL ODateTimeControl::getValueType()
323 return ::cppu::UnoType<util::DateTime>::get();
327 //= HyperlinkInput
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();
373 else
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 )
435 OUString sText;
436 _value >>= sText;
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 )
449 if ( listener.is() )
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); });
478 //= ONumericControl
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;
515 else
516 aReturn.Value = static_cast<double>(minValue);
518 return aReturn;
522 void SAL_CALL ONumericControl::setMinValue( const Optional< double >& _minvalue )
524 if ( !_minvalue.IsPresent )
525 getTypedControlWindow()->SetMin( std::numeric_limits< sal_Int64 >::min() );
526 else
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;
538 else
539 aReturn.Value = static_cast<double>(maxValue);
541 return aReturn;
545 void SAL_CALL ONumericControl::setMaxValue( const Optional< double >& _maxvalue )
547 if ( !_maxvalue.IsPresent )
548 getTypedControlWindow()->SetMax( std::numeric_limits< sal_Int64 >::max() );
549 else
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();
604 else
606 double nValue( 0 );
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;
626 return nApiValue;
630 Any SAL_CALL ONumericControl::getValue()
632 Any aPropValue;
633 if ( !getTypedControlWindow()->GetText().isEmpty() )
635 double nValue = impl_fieldValueToApiValue_nothrow( getTypedControlWindow()->GetValue( m_eValueUnit ) );
636 aPropValue <<= nValue;
638 return aPropValue;
642 Type SAL_CALL ONumericControl::getValueType()
644 return ::cppu::UnoType<double>::get();
648 //= OColorControl
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())
662 _rValue >>= nColor;
663 getTypedControlWindow()->SelectEntry(nColor);
666 Any SAL_CALL OColorControl::getValue()
668 Any aPropValue;
669 ::Color aRgbCol = getTypedControlWindow()->GetSelectEntryColor();
670 if (aRgbCol == COL_TRANSPARENT)
671 return aPropValue;
672 aPropValue <<= aRgbCol;
673 return aPropValue;
676 Type SAL_CALL OColorControl::getValueType()
678 return ::cppu::UnoType<sal_Int32>::get();
681 void OColorControl::setModified()
683 OColorControl_Base::setModified();
685 // fire a commit
686 notifyModifiedValue();
689 //= OListboxControl
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() );
707 Any aPropValue;
708 if ( !sControlValue.isEmpty() )
709 aPropValue <<= sControlValue;
710 return aPropValue;
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();
724 else
726 OUString sSelection;
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);
766 return aRet;
770 void OListboxControl::setModified()
772 OListboxControl_Base::setModified();
774 if ( !getTypedControlWindow()->IsTravelSelect() )
775 // fire a commit
776 notifyModifiedValue();
780 //= OComboboxControl
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 )
793 OUString sText;
794 _rValue >>= sText;
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);
836 return aRet;
840 IMPL_LINK_NOARG( OComboboxControl, OnEntrySelected, ComboBox&, void )
842 if ( !getTypedControlWindow()->IsTravelSelect() )
843 // fire a commit
844 notifyModifiedValue();
848 //= OMultilineFloatingEdit
850 class OMultilineFloatingEdit : public FloatingWindow
852 private:
853 VclPtr<MultiLineEdit> m_aImplEdit;
855 protected:
856 virtual void Resize() override;
858 public:
859 explicit OMultilineFloatingEdit(vcl::Window* _pParen);
860 virtual ~OMultilineFloatingEdit() override;
861 virtual void dispose() override;
862 MultiLineEdit& getEdit() { return *m_aImplEdit.get(); }
864 protected:
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))
873 m_aImplEdit->Show();
876 OMultilineFloatingEdit::~OMultilineFloatingEdit()
878 disposeOnce();
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)
895 bool bResult = true;
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)
907 && aKeyCode.IsMod2()
911 EndPopupMode();
913 else
914 bResult=FloatingWindow::PreNotify(_rNEvt);
916 else
917 bResult=FloatingWindow::PreNotify(_rNEvt);
919 return bResult;
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 )
931 ,m_bDropdown(false)
932 ,m_pHelper(nullptr)
934 SetCompoundControl( true );
936 m_pImplEdit = VclPtr<MultiLineEdit>::Create( this, WB_TABSTOP | WB_IGNORETAB | WB_NOBORDER | (_nStyle & WB_READONLY) );
937 SetSubEdit( m_pImplEdit );
938 m_pImplEdit->Show();
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()
967 disposeOnce();
970 void DropDownEditControl::dispose()
972 SetSubEdit(nullptr);
973 m_pImplEdit.disposeAndClear();
974 m_pFloatingEdit.disposeAndClear();
975 m_pDropdownButton.disposeAndClear();
976 Edit::dispose();
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() );
991 else
992 m_pImplEdit->setPosSizePixel( 0, 1, aOutSz.Width(), aOutSz.Height()-2 );
996 bool DropDownEditControl::PreNotify( NotifyEvent& rNEvt )
998 bool bResult = true;
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() )
1007 if ( m_pHelper )
1009 m_pHelper->LoseFocusHdl( *m_pImplEdit.get() );
1010 m_pHelper->activateNextControl();
1013 else if ( nKey == KEY_DOWN && aKeyCode.IsMod2() )
1015 Invalidate();
1016 ShowDropDown( true );
1018 else if ( KEYGROUP_CURSOR == aKeyCode.GetGroup()
1019 || nKey == KEY_HELP
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() );
1034 else
1036 aSel.Min() = FindPos( aSel.Min() );
1037 aSel.Max() = aSel.Min();
1039 Invalidate();
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() );
1047 else
1048 bResult = Edit::PreNotify(rNEvt);
1050 return bResult;
1054 namespace
1057 StlSyntaxSequence< OUString > lcl_convertMultiLineToList( const OUString& _rCompsedTextWithLineBreaks )
1059 sal_Int32 nLines = comphelper::string::getTokenCount(_rCompsedTextWithLineBreaks, '\n');
1060 StlSyntaxSequence< OUString > aStrings( nLines );
1061 if (nLines)
1063 StlSyntaxSequence< OUString >::iterator stringItem = aStrings.begin();
1064 sal_Int32 nIdx {0};
1067 *stringItem = _rCompsedTextWithLineBreaks.getToken( 0, '\n', nIdx );
1068 ++stringItem;
1070 while (nIdx>0);
1072 return aStrings;
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();
1095 ++strings
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 )
1112 if (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()));
1125 m_bDropdown = true;
1126 if ( m_nOperationMode == eMultiLineText )
1127 m_pFloatingEdit->getEdit().SetText( m_pImplEdit->GetText() );
1128 m_pImplEdit->SetText("");
1130 else
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)
1151 long nPos = 0;
1152 OUString aOutput;
1153 OUString aStr = m_pFloatingEdit->getEdit().GetText();
1154 OUString aStr1 = GetText();
1156 if ((nSinglePos == 0) || (nSinglePos == aStr1.getLength()))
1158 return nSinglePos;
1161 if (!aStr.isEmpty())
1163 long nDiff=0;
1165 sal_Int32 nIdx {0};
1166 OUString aInput = aStr.getToken(0, '\n', nIdx );
1168 if (!aInput.isEmpty())
1170 aOutput += "\"";
1171 nDiff++;
1172 aOutput += aInput;
1173 aOutput += "\"";
1176 if (nSinglePos <= aOutput.getLength())
1178 nPos=nSinglePos-nDiff;
1180 else
1182 while (nIdx>0)
1184 aInput=aStr.getToken(0, '\n', nIdx);
1185 if (!aInput.isEmpty())
1187 aOutput += ";";
1188 aOutput += "\"";
1189 nDiff += 2;
1190 aOutput += aInput;
1191 aOutput += "\"";
1193 if (nSinglePos <= aOutput.getLength())
1195 nPos=nSinglePos-nDiff;
1196 break;
1202 return nPos;
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 ) )
1214 if ( m_pHelper )
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 );
1244 SetText( _rText );
1248 OUString DropDownEditControl::GetTextValue() const
1250 OSL_PRECOND( m_nOperationMode == eMultiLineText, "DropDownEditControl::GetTextValue: illegal call!" );
1251 return GetText();
1255 //= OMultilineEditControl
1258 OMultilineEditControl::OMultilineEditControl( vcl::Window* pParent, MultiLineOperationMode _eMode, WinBits nWinStyle )
1259 :OMultilineEditControl_Base( _eMode == eMultiLineText ? PropertyControlType::MultiLineTextField : PropertyControlType::StringListField
1260 , pParent
1261 , ( nWinStyle | WB_DIALOGCONTROL ) & ( ~WB_READONLY | ~WB_DROPDOWN )
1262 , false )
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:
1277 OUString sText;
1278 if ( !( _rValue >>= sText ) && _rValue.hasValue() )
1279 throw IllegalTypeException();
1280 getTypedControlWindow()->SetTextValue( sText );
1282 break;
1283 case eStringList:
1285 Sequence< OUString > aStringLines;
1286 if ( !( _rValue >>= aStringLines ) && _rValue.hasValue() )
1287 throw IllegalTypeException();
1288 getTypedControlWindow()->SetStringListValue( StlSyntaxSequence<OUString>(aStringLines) );
1290 break;
1295 Any SAL_CALL OMultilineEditControl::getValue()
1297 impl_checkDisposed_throw();
1299 Any aValue;
1300 switch ( getTypedControlWindow()->getOperationMode() )
1302 case eMultiLineText:
1303 aValue <<= getTypedControlWindow()->GetTextValue();
1304 break;
1305 case eStringList:
1306 aValue <<= getTypedControlWindow()->GetStringListValue();
1307 break;
1309 return aValue;
1313 Type SAL_CALL OMultilineEditControl::getValueType()
1315 if ( getTypedControlWindow()->getOperationMode() == eMultiLineText )
1316 return ::cppu::UnoType<OUString>::get();
1317 return cppu::UnoType<Sequence< OUString >>::get();
1321 } // namespace pcr
1324 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */