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/lang/IllegalArgumentException.hpp>
25 #include <com/sun/star/util/DateTime.hpp>
26 #include <com/sun/star/util/Date.hpp>
27 #include <com/sun/star/util/Time.hpp>
28 #include <com/sun/star/util/Color.hpp>
29 #include <com/sun/star/util/MeasureUnit.hpp>
30 #include <com/sun/star/inspection/PropertyControlType.hpp>
31 #include <comphelper/string.hxx>
32 #include <o3tl/float_int_conversion.hxx>
33 #include <toolkit/helper/vclunohelper.hxx>
36 // ugly dependencies for the OColorControl
37 #include <svx/svxids.hrc>
39 #include <tools/datetime.hxx>
40 #include <unotools/datetime.hxx>
41 #include <o3tl/string_view.hxx>
48 using namespace ::com::sun::star
;
49 using namespace ::com::sun::star::uno
;
50 using namespace ::com::sun::star::awt
;
51 using namespace ::com::sun::star::lang
;
52 using namespace ::com::sun::star::util
;
53 using namespace ::com::sun::star::beans
;
54 using namespace ::com::sun::star::inspection
;
57 OTimeControl::OTimeControl(std::unique_ptr
<weld::FormattedSpinButton
> xWidget
, std::unique_ptr
<weld::Builder
> xBuilder
, bool bReadOnly
)
58 : OTimeControl_Base(PropertyControlType::TimeField
, std::move(xBuilder
), std::move(xWidget
), bReadOnly
)
59 , m_xFormatter(new weld::TimeFormatter(*getTypedControlWindow()))
61 m_xFormatter
->SetExtFormat(ExtTimeFieldFormat::LongDuration
);
64 void SAL_CALL
OTimeControl::setValue( const Any
& _rValue
)
67 if ( !( _rValue
>>= aUNOTime
) )
69 getTypedControlWindow()->set_text(u
""_ustr
);
70 m_xFormatter
->SetTime(tools::Time(tools::Time::EMPTY
));
74 m_xFormatter
->SetTime(::tools::Time(aUNOTime
));
78 Any SAL_CALL
OTimeControl::getValue()
81 if ( !getTypedControlWindow()->get_text().isEmpty() )
83 aPropValue
<<= m_xFormatter
->GetTime().GetUNOTime();
88 Type SAL_CALL
OTimeControl::getValueType()
90 return ::cppu::UnoType
<util::Time
>::get();
94 ODateControl::ODateControl(std::unique_ptr
<weld::Container
> xWidget
, std::unique_ptr
<weld::Builder
> xBuilder
, bool bReadOnly
)
95 : ODateControl_Base(PropertyControlType::DateField
, std::move(xBuilder
), std::move(xWidget
), bReadOnly
)
96 , m_xEntry(m_xBuilder
->weld_entry(u
"entry"_ustr
))
97 , m_xCalendarBox(std::make_unique
<SvtCalendarBox
>(m_xBuilder
->weld_menu_button(u
"button"_ustr
), false))
99 m_xEntryFormatter
.reset(new weld::DateFormatter(*m_xEntry
));
101 m_xEntryFormatter
->SetStrictFormat(true);
102 m_xEntryFormatter
->SetMin(::Date(1, 1, 1600));
103 m_xEntryFormatter
->SetMax(::Date(1, 1, 9999));
105 m_xEntryFormatter
->SetExtDateFormat(ExtDateFieldFormat::SystemShortYYYY
);
106 m_xEntryFormatter
->EnableEmptyField(true);
108 m_xCalendarBox
->connect_activated(LINK(this, ODateControl
, ActivateHdl
));
110 m_xCalendarBox
->get_button().connect_toggled(LINK(this, ODateControl
, ToggleHdl
));
113 void SAL_CALL
ODateControl::disposing()
115 m_xEntryFormatter
.reset();
117 m_xCalendarBox
.reset();
118 ODateControl_Base::disposing();
121 void SAL_CALL
ODateControl::setValue( const Any
& _rValue
)
124 if ( !( _rValue
>>= aUNODate
) )
126 m_xEntry
->set_text(OUString());
130 ::Date
aDate( aUNODate
.Day
, aUNODate
.Month
, aUNODate
.Year
);
131 m_xEntryFormatter
->SetDate(aDate
);
135 IMPL_LINK_NOARG(ODateControl
, ActivateHdl
, SvtCalendarBox
&, void)
137 m_xEntryFormatter
->SetDate(m_xCalendarBox
->get_date());
139 m_xEntry
->grab_focus();
142 IMPL_LINK(ODateControl
, ToggleHdl
, weld::Toggleable
&, rToggle
, void)
144 if (!rToggle
.get_active())
146 ::Date aDate
= m_xEntryFormatter
->GetDate();
149 // with an empty date preselect today in the calendar
150 aDate
= ::Date(::Date::SYSTEM
);
152 m_xCalendarBox
->set_date(aDate
);
155 Any SAL_CALL
ODateControl::getValue()
158 if (!m_xEntry
->get_text().isEmpty())
160 ::Date
aDate(m_xEntryFormatter
->GetDate());
161 aPropValue
<<= aDate
.GetUNODate();
166 Type SAL_CALL
ODateControl::getValueType()
168 return ::cppu::UnoType
<util::Date
>::get();
172 OEditControl::OEditControl(std::unique_ptr
<weld::Entry
> xWidget
, std::unique_ptr
<weld::Builder
> xBuilder
, bool bPW
, bool bReadOnly
)
173 : OEditControl_Base( bPW
? PropertyControlType::CharacterField
: PropertyControlType::TextField
, std::move(xBuilder
), std::move(xWidget
), bReadOnly
)
177 auto pWidget
= getTypedControlWindow();
178 pWidget
->set_sensitive(true);
179 pWidget
->set_editable(!bReadOnly
);
182 pWidget
->set_max_length( 1 );
185 void SAL_CALL
OEditControl::setValue( const Any
& _rValue
)
190 sal_Int16 nValue
= 0;
194 sText
= OUString(static_cast<sal_Unicode
>(nValue
));
200 getTypedControlWindow()->set_text( sText
);
203 Any SAL_CALL
OEditControl::getValue()
207 OUString
sText( getTypedControlWindow()->get_text() );
210 if ( !sText
.isEmpty() )
211 aPropValue
<<= static_cast<sal_Int16
>(sText
[0]);
214 aPropValue
<<= sText
;
219 Type SAL_CALL
OEditControl::getValueType()
221 return m_bIsPassword
? ::cppu::UnoType
<sal_Int16
>::get() : ::cppu::UnoType
<OUString
>::get();
224 void OEditControl::setModified()
226 OEditControl_Base::setModified();
228 // for password controls, we fire a commit for every single change
230 notifyModifiedValue();
233 static sal_Int64
ImplCalcLongValue( double nValue
, sal_uInt16 nDigits
)
236 for ( sal_uInt16 d
= 0; d
< nDigits
; ++d
)
239 return o3tl::saturating_cast
<sal_Int64
>(n
);
242 static double ImplCalcDoubleValue(sal_Int64 nValue
, sal_uInt16 nDigits
)
245 for ( sal_uInt16 d
= 0; d
< nDigits
; ++d
)
250 ODateTimeControl::ODateTimeControl(std::unique_ptr
<weld::Container
> xWidget
, std::unique_ptr
<weld::Builder
> xBuilder
, bool bReadOnly
)
251 : ODateTimeControl_Base(PropertyControlType::DateTimeField
, std::move(xBuilder
), std::move(xWidget
), bReadOnly
)
252 , m_xDate(std::make_unique
<SvtCalendarBox
>(m_xBuilder
->weld_menu_button(u
"datefield"_ustr
)))
253 , m_xTime(m_xBuilder
->weld_formatted_spin_button(u
"timefield"_ustr
))
254 , m_xFormatter(new weld::TimeFormatter(*m_xTime
))
256 m_xFormatter
->SetExtFormat(ExtTimeFieldFormat::LongDuration
);
259 void SAL_CALL
ODateTimeControl::setValue( const Any
& _rValue
)
261 if ( !_rValue
.hasValue() )
263 m_xDate
->set_date(::Date(::Date::SYSTEM
));
264 m_xTime
->set_text(u
""_ustr
);
265 m_xFormatter
->SetTime(tools::Time(tools::Time::EMPTY
));
269 util::DateTime aUNODateTime
;
270 OSL_VERIFY( _rValue
>>= aUNODateTime
);
272 ::DateTime
aDateTime( ::DateTime::EMPTY
);
273 ::utl::typeConvert( aUNODateTime
, aDateTime
);
275 m_xDate
->set_date(aDateTime
);
276 m_xFormatter
->SetTime(aDateTime
);
280 Any SAL_CALL
ODateTimeControl::getValue()
283 if (!m_xTime
->get_text().isEmpty())
285 ::DateTime
aDateTime(m_xDate
->get_date(), m_xFormatter
->GetTime());
287 util::DateTime aUNODateTime
;
288 ::utl::typeConvert( aDateTime
, aUNODateTime
);
290 aPropValue
<<= aUNODateTime
;
295 Type SAL_CALL
ODateTimeControl::getValueType()
297 return ::cppu::UnoType
<util::DateTime
>::get();
300 //= OHyperlinkControl
301 OHyperlinkControl::OHyperlinkControl(std::unique_ptr
<weld::Container
> xWidget
, std::unique_ptr
<weld::Builder
> xBuilder
, bool bReadOnly
)
302 : OHyperlinkControl_Base(PropertyControlType::HyperlinkField
, std::move(xBuilder
), std::move(xWidget
), bReadOnly
)
303 , m_xEntry(m_xBuilder
->weld_entry(u
"entry"_ustr
))
304 , m_xButton(m_xBuilder
->weld_button(u
"button"_ustr
))
305 , m_aActionListeners(m_aMutex
)
307 auto pWidget
= getTypedControlWindow();
308 pWidget
->set_sensitive(true);
309 m_xEntry
->set_editable(!bReadOnly
);
311 m_xButton
->connect_clicked(LINK(this, OHyperlinkControl
, OnHyperlinkClicked
));
314 Any SAL_CALL
OHyperlinkControl::getValue()
316 OUString sText
= m_xEntry
->get_text();
320 void SAL_CALL
OHyperlinkControl::setValue( const Any
& _value
)
324 m_xEntry
->set_text( sText
);
327 Type SAL_CALL
OHyperlinkControl::getValueType()
329 return ::cppu::UnoType
<OUString
>::get();
332 void SAL_CALL
OHyperlinkControl::addActionListener( const Reference
< XActionListener
>& listener
)
335 m_aActionListeners
.addInterface( listener
);
338 void SAL_CALL
OHyperlinkControl::removeActionListener( const Reference
< XActionListener
>& listener
)
340 m_aActionListeners
.removeInterface( listener
);
343 void SAL_CALL
OHyperlinkControl::disposing()
347 OHyperlinkControl_Base::disposing();
349 EventObject
aEvent( *this );
350 m_aActionListeners
.disposeAndClear( aEvent
);
353 IMPL_LINK_NOARG( OHyperlinkControl
, OnHyperlinkClicked
, weld::Button
&, void )
355 ActionEvent
aEvent( *this, u
"clicked"_ustr
);
356 m_aActionListeners
.forEach
< XActionListener
>(
357 [&aEvent
] (uno::Reference
<awt::XActionListener
> const& xListener
)
358 { return xListener
->actionPerformed(aEvent
); });
362 ONumericControl::ONumericControl(std::unique_ptr
<weld::MetricSpinButton
> xWidget
, std::unique_ptr
<weld::Builder
> xBuilder
, bool bReadOnly
)
363 : ONumericControl_Base(PropertyControlType::NumericField
, std::move(xBuilder
), std::move(xWidget
), bReadOnly
)
364 , m_eValueUnit( FieldUnit::NONE
)
365 , m_nFieldToUNOValueFactor( 1 )
367 Optional
< double > value( getMaxValue() );
368 value
.Value
= -value
.Value
;
369 setMinValue( value
);
372 ::sal_Int16 SAL_CALL
ONumericControl::getDecimalDigits()
374 return getTypedControlWindow()->get_digits();
377 void SAL_CALL
ONumericControl::setDecimalDigits( ::sal_Int16 decimaldigits
)
379 weld::MetricSpinButton
* pControlWindow
= getTypedControlWindow();
381 pControlWindow
->get_range(min
, max
, FieldUnit::NONE
);
382 pControlWindow
->set_digits(decimaldigits
);
383 pControlWindow
->set_range(min
, max
, FieldUnit::NONE
);
386 Optional
< double > SAL_CALL
ONumericControl::getMinValue()
388 Optional
< double > aReturn( true, 0 );
390 sal_Int64 minValue
= getTypedControlWindow()->get_min(FieldUnit::NONE
);
391 if ( minValue
== std::numeric_limits
<sal_Int64
>::min() )
392 aReturn
.IsPresent
= false;
394 aReturn
.Value
= static_cast<double>(minValue
);
399 void SAL_CALL
ONumericControl::setMinValue( const Optional
< double >& _minvalue
)
401 if ( !_minvalue
.IsPresent
)
402 getTypedControlWindow()->set_min( std::numeric_limits
<sal_Int64
>::min(), FieldUnit::NONE
);
404 getTypedControlWindow()->set_min( impl_apiValueToFieldValue_nothrow( _minvalue
.Value
) , m_eValueUnit
);
407 Optional
< double > SAL_CALL
ONumericControl::getMaxValue()
409 Optional
< double > aReturn( true, 0 );
411 sal_Int64 maxValue
= getTypedControlWindow()->get_max(FieldUnit::NONE
);
412 if ( maxValue
== std::numeric_limits
<sal_Int64
>::max() )
413 aReturn
.IsPresent
= false;
415 aReturn
.Value
= static_cast<double>(maxValue
);
420 void SAL_CALL
ONumericControl::setMaxValue( const Optional
< double >& _maxvalue
)
422 if ( !_maxvalue
.IsPresent
)
423 getTypedControlWindow()->set_max( std::numeric_limits
<sal_Int64
>::max(), FieldUnit::NONE
);
425 getTypedControlWindow()->set_max( impl_apiValueToFieldValue_nothrow( _maxvalue
.Value
), m_eValueUnit
);
428 ::sal_Int16 SAL_CALL
ONumericControl::getDisplayUnit()
430 return VCLUnoHelper::ConvertToMeasurementUnit( getTypedControlWindow()->get_unit(), 1 );
433 void SAL_CALL
ONumericControl::setDisplayUnit( ::sal_Int16 _displayunit
)
435 if ( ( _displayunit
< MeasureUnit::MM_100TH
) || ( _displayunit
> MeasureUnit::PERCENT
) )
436 throw IllegalArgumentException();
437 if ( ( _displayunit
== MeasureUnit::MM_100TH
)
438 || ( _displayunit
== MeasureUnit::MM_10TH
)
439 || ( _displayunit
== MeasureUnit::INCH_1000TH
)
440 || ( _displayunit
== MeasureUnit::INCH_100TH
)
441 || ( _displayunit
== MeasureUnit::INCH_10TH
)
442 || ( _displayunit
== MeasureUnit::PERCENT
)
444 throw IllegalArgumentException();
446 sal_Int16 nDummyFactor
= 1;
447 FieldUnit eFieldUnit
= VCLUnoHelper::ConvertToFieldUnit( _displayunit
, nDummyFactor
);
448 if ( nDummyFactor
!= 1 )
449 // everything which survived the checks above should result in a factor of 1, i.e.,
450 // it should have a direct counterpart as FieldUnit
451 throw RuntimeException();
452 getTypedControlWindow()->set_unit(eFieldUnit
);
455 ::sal_Int16 SAL_CALL
ONumericControl::getValueUnit()
457 return VCLUnoHelper::ConvertToMeasurementUnit( m_eValueUnit
, m_nFieldToUNOValueFactor
);
460 void SAL_CALL
ONumericControl::setValueUnit( ::sal_Int16 _valueunit
)
462 if ( ( _valueunit
< MeasureUnit::MM_100TH
) || ( _valueunit
> MeasureUnit::PERCENT
) )
463 throw IllegalArgumentException();
464 m_eValueUnit
= VCLUnoHelper::ConvertToFieldUnit( _valueunit
, m_nFieldToUNOValueFactor
);
467 void SAL_CALL
ONumericControl::setValue( const Any
& _rValue
)
469 if ( !_rValue
.hasValue() )
471 getTypedControlWindow()->set_text( u
""_ustr
);
476 OSL_VERIFY( _rValue
>>= nValue
);
477 auto nControlValue
= impl_apiValueToFieldValue_nothrow( nValue
);
478 getTypedControlWindow()->set_value( nControlValue
, m_eValueUnit
);
482 sal_Int64
ONumericControl::impl_apiValueToFieldValue_nothrow( double _nApiValue
) const
484 sal_Int64 nControlValue
= ImplCalcLongValue( _nApiValue
, getTypedControlWindow()->get_digits() );
485 nControlValue
/= m_nFieldToUNOValueFactor
;
486 return nControlValue
;
489 double ONumericControl::impl_fieldValueToApiValue_nothrow(sal_Int64 nFieldValue
) const
491 double nApiValue
= ImplCalcDoubleValue( nFieldValue
, getTypedControlWindow()->get_digits() );
492 nApiValue
*= m_nFieldToUNOValueFactor
;
496 Any SAL_CALL
ONumericControl::getValue()
499 if ( !getTypedControlWindow()->get_text().isEmpty() )
501 double nValue
= impl_fieldValueToApiValue_nothrow( getTypedControlWindow()->get_value( m_eValueUnit
) );
503 aPropValue
<<= nValue
;
508 Type SAL_CALL
ONumericControl::getValueType()
510 return ::cppu::UnoType
<double>::get();
514 OColorControl::OColorControl(std::unique_ptr
<ColorListBox
> xWidget
, std::unique_ptr
<weld::Builder
> xBuilder
, bool bReadOnly
)
515 : OColorControl_Base(PropertyControlType::ColorListBox
, std::move(xBuilder
), std::move(xWidget
), bReadOnly
)
517 getTypedControlWindow()->SetSlotId(SID_FM_CTL_PROPERTIES
);
520 void SAL_CALL
OColorControl::setValue( const Any
& _rValue
)
522 css::util::Color nColor
= sal_uInt32(COL_TRANSPARENT
);
523 if (_rValue
.hasValue())
525 getTypedControlWindow()->SelectEntry(::Color(ColorTransparency
, nColor
));
528 Any SAL_CALL
OColorControl::getValue()
531 ::Color aRgbCol
= getTypedControlWindow()->GetSelectEntryColor();
532 if (aRgbCol
== COL_TRANSPARENT
)
534 aPropValue
<<= aRgbCol
;
538 Type SAL_CALL
OColorControl::getValueType()
540 return ::cppu::UnoType
<sal_Int32
>::get();
543 void OColorControl::setModified()
545 OColorControl_Base::setModified();
548 notifyModifiedValue();
552 OListboxControl::OListboxControl(std::unique_ptr
<weld::ComboBox
> xWidget
, std::unique_ptr
<weld::Builder
> xBuilder
, bool bReadOnly
)
553 : OListboxControl_Base(PropertyControlType::ListBox
, std::move(xBuilder
), std::move(xWidget
), bReadOnly
)
557 Any SAL_CALL
OListboxControl::getValue()
559 OUString
sControlValue( getTypedControlWindow()->get_active_text() );
562 if ( !sControlValue
.isEmpty() )
563 aPropValue
<<= sControlValue
;
567 Type SAL_CALL
OListboxControl::getValueType()
569 return ::cppu::UnoType
<OUString
>::get();
572 void SAL_CALL
OListboxControl::setValue( const Any
& _rValue
)
574 if ( !_rValue
.hasValue() )
575 getTypedControlWindow()->set_active(-1);
579 _rValue
>>= sSelection
;
581 if (getTypedControlWindow()->find_text(sSelection
) == -1)
582 getTypedControlWindow()->insert_text(0, sSelection
);
584 if (sSelection
!= getTypedControlWindow()->get_active_text())
585 getTypedControlWindow()->set_active_text(sSelection
);
589 void SAL_CALL
OListboxControl::clearList()
591 getTypedControlWindow()->clear();
594 void SAL_CALL
OListboxControl::prependListEntry( const OUString
& NewEntry
)
596 getTypedControlWindow()->insert_text(0, NewEntry
);
599 void SAL_CALL
OListboxControl::appendListEntry( const OUString
& NewEntry
)
601 getTypedControlWindow()->append_text(NewEntry
);
604 Sequence
< OUString
> SAL_CALL
OListboxControl::getListEntries()
606 const sal_Int32 nCount
= getTypedControlWindow()->get_count();
607 Sequence
< OUString
> aRet(nCount
);
608 OUString
* pIter
= aRet
.getArray();
609 for (sal_Int32 i
= 0; i
< nCount
; ++i
,++pIter
)
610 *pIter
= getTypedControlWindow()->get_text(i
);
615 void OListboxControl::setModified()
617 OListboxControl_Base::setModified();
620 notifyModifiedValue();
624 OComboboxControl::OComboboxControl(std::unique_ptr
<weld::ComboBox
> xWidget
, std::unique_ptr
<weld::Builder
> xBuilder
, bool bReadOnly
)
625 : OComboboxControl_Base(PropertyControlType::ComboBox
, std::move(xBuilder
), std::move(xWidget
), bReadOnly
)
627 getTypedControlWindow()->connect_changed( LINK( this, OComboboxControl
, OnEntrySelected
) );
630 void SAL_CALL
OComboboxControl::setValue( const Any
& _rValue
)
634 weld::ComboBox
* pControlWindow
= getTypedControlWindow();
635 // tdf#138701 leave current cursor valid if the contents won't change
636 if (pControlWindow
->get_active_text() != sText
)
637 pControlWindow
->set_entry_text(sText
);
640 Any SAL_CALL
OComboboxControl::getValue()
642 return Any( getTypedControlWindow()->get_active_text() );
645 Type SAL_CALL
OComboboxControl::getValueType()
647 return ::cppu::UnoType
<OUString
>::get();
650 void SAL_CALL
OComboboxControl::clearList()
652 getTypedControlWindow()->clear();
655 void SAL_CALL
OComboboxControl::prependListEntry( const OUString
& NewEntry
)
657 getTypedControlWindow()->insert_text(0, NewEntry
);
660 void SAL_CALL
OComboboxControl::appendListEntry( const OUString
& NewEntry
)
662 getTypedControlWindow()->append_text( NewEntry
);
665 Sequence
< OUString
> SAL_CALL
OComboboxControl::getListEntries( )
667 const sal_Int32 nCount
= getTypedControlWindow()->get_count();
668 Sequence
< OUString
> aRet(nCount
);
669 OUString
* pIter
= aRet
.getArray();
670 for (sal_Int32 i
= 0; i
< nCount
; ++i
,++pIter
)
671 *pIter
= getTypedControlWindow()->get_text(i
);
676 IMPL_LINK_NOARG( OComboboxControl
, OnEntrySelected
, weld::ComboBox
&, void )
679 notifyModifiedValue();
685 StlSyntaxSequence
< OUString
> lcl_convertMultiLineToList( std::u16string_view _rCompsedTextWithLineBreaks
)
687 sal_Int32 nLines
= comphelper::string::getTokenCount(_rCompsedTextWithLineBreaks
, '\n');
688 StlSyntaxSequence
< OUString
> aStrings( nLines
);
691 StlSyntaxSequence
< OUString
>::iterator stringItem
= aStrings
.begin();
695 *stringItem
= o3tl::getToken(_rCompsedTextWithLineBreaks
, 0, '\n', nIdx
);
703 OUString
lcl_convertListToMultiLine( const StlSyntaxSequence
< OUString
>& _rStrings
)
705 OUStringBuffer sMultiLineText
;
706 for ( StlSyntaxSequence
< OUString
>::const_iterator item
= _rStrings
.begin();
707 item
!= _rStrings
.end();
710 sMultiLineText
.append(*item
);
711 if ( ++item
!= _rStrings
.end() )
712 sMultiLineText
.append("\n");
714 return sMultiLineText
.makeStringAndClear();
718 OUString
lcl_convertListToDisplayText( const StlSyntaxSequence
< OUString
>& _rStrings
)
720 OUStringBuffer aComposed
;
721 for ( StlSyntaxSequence
< OUString
>::const_iterator strings
= _rStrings
.begin();
722 strings
!= _rStrings
.end();
726 if ( strings
!= _rStrings
.begin() )
727 aComposed
.append( ';' );
728 aComposed
.append( "\"" + *strings
+ "\"" );
730 return aComposed
.makeStringAndClear();
734 void OMultilineEditControl::CheckEntryTextViewMisMatch()
736 // if there are newlines or something else which the entry cannot show, then make
737 // just the multiline dropdown editable as the canonical source for text
738 m_xEntry
->set_sensitive(m_xEntry
->get_text() == m_xTextView
->get_text());
741 void OMultilineEditControl::SetStringListValue(const StlSyntaxSequence
<OUString
>& rStrings
)
743 m_xEntry
->set_text(lcl_convertListToDisplayText(rStrings
));
744 m_xTextView
->set_text(lcl_convertListToMultiLine(rStrings
));
745 CheckEntryTextViewMisMatch();
748 StlSyntaxSequence
<OUString
> OMultilineEditControl::GetStringListValue() const
750 return lcl_convertMultiLineToList(m_xTextView
->get_text());
753 void OMultilineEditControl::SetTextValue(const OUString
& rText
)
755 OSL_PRECOND( m_nOperationMode
== eMultiLineText
, "OMultilineEditControl::SetTextValue: illegal call!" );
757 m_xTextView
->set_text(rText
);
758 m_xEntry
->set_text(rText
);
759 CheckEntryTextViewMisMatch();
762 OUString
OMultilineEditControl::GetTextValue() const
764 OSL_PRECOND( m_nOperationMode
== eMultiLineText
, "OMultilineEditControl::GetTextValue: illegal call!" );
765 return m_xTextView
->get_text();
768 //= OMultilineEditControl
769 OMultilineEditControl::OMultilineEditControl(std::unique_ptr
<weld::Container
> xWidget
, std::unique_ptr
<weld::Builder
> xBuilder
, MultiLineOperationMode eMode
, bool bReadOnly
)
770 : OMultilineEditControl_Base(eMode
== eMultiLineText
? PropertyControlType::MultiLineTextField
: PropertyControlType::StringListField
,
771 std::move(xBuilder
), std::move(xWidget
), bReadOnly
)
772 , m_nOperationMode(eMode
)
773 , m_xEntry(m_xBuilder
->weld_entry(u
"entry"_ustr
))
774 , m_xButton(m_xBuilder
->weld_menu_button(u
"button"_ustr
))
775 , m_xPopover(m_xBuilder
->weld_widget(u
"popover"_ustr
))
776 , m_xTextView(m_xBuilder
->weld_text_view(u
"textview"_ustr
))
777 , m_xOk(m_xBuilder
->weld_button(u
"ok"_ustr
))
779 m_xButton
->set_popover(m_xPopover
.get());
780 m_xTextView
->set_size_request(m_xTextView
->get_approximate_digit_width() * 30, m_xTextView
->get_height_rows(8));
781 m_xOk
->connect_clicked(LINK(this, OMultilineEditControl
, ButtonHandler
));
784 IMPL_LINK_NOARG(OMultilineEditControl
, TextViewModifiedHdl
, weld::TextView
&, void)
786 // tdf#139070 during editing update the entry to look like how it will
787 // look once editing is finished so that the default behaviour of vcl
788 // to strip newlines and the default behaviour of gtk to show a newline
789 // symbol is suppressed
790 OUString sText
= m_xTextView
->get_text();
791 auto aSeq
= lcl_convertMultiLineToList(sText
);
792 if (aSeq
.getLength() > 1)
793 m_xEntry
->set_text(lcl_convertListToDisplayText(aSeq
));
795 m_xEntry
->set_text(sText
);
796 CheckEntryTextViewMisMatch();
800 void OMultilineEditControl::editChanged()
802 m_xTextView
->set_text(m_xEntry
->get_text());
803 CheckEntryTextViewMisMatch();
807 IMPL_LINK_NOARG(OMultilineEditControl
, ButtonHandler
, weld::Button
&, void)
809 m_xButton
->set_active(false);
810 notifyModifiedValue();
813 void SAL_CALL
OMultilineEditControl::setValue( const Any
& _rValue
)
815 impl_checkDisposed_throw();
817 switch (m_nOperationMode
)
822 if ( !( _rValue
>>= sText
) && _rValue
.hasValue() )
823 throw IllegalTypeException();
829 Sequence
< OUString
> aStringLines
;
830 if ( !( _rValue
>>= aStringLines
) && _rValue
.hasValue() )
831 throw IllegalTypeException();
832 SetStringListValue( StlSyntaxSequence
<OUString
>(aStringLines
) );
838 Any SAL_CALL
OMultilineEditControl::getValue()
840 impl_checkDisposed_throw();
843 switch (m_nOperationMode
)
846 aValue
<<= GetTextValue();
849 aValue
<<= GetStringListValue();
855 Type SAL_CALL
OMultilineEditControl::getValueType()
857 if (m_nOperationMode
== eMultiLineText
)
858 return ::cppu::UnoType
<OUString
>::get();
859 return cppu::UnoType
<Sequence
< OUString
>>::get();
864 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */