1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_extensions.hxx"
26 #include "standardcontrol.hxx"
27 #include "pcrcommon.hxx"
28 
29 /** === begin UNO includes === **/
30 #include <com/sun/star/util/DateTime.hpp>
31 #include <com/sun/star/util/Date.hpp>
32 #include <com/sun/star/util/Time.hpp>
33 #include <com/sun/star/util/Color.hpp>
34 #include <com/sun/star/util/MeasureUnit.hpp>
35 #include <com/sun/star/inspection/PropertyControlType.hpp>
36 /** === end UNO includes === **/
37 #include <rtl/math.hxx>
38 #include <sfx2/objsh.hxx>
39 
40 //==================================================================
41 // ugly dependencies for the OColorControl
42 #ifndef _SVX_SVXIDS_HRC
43 #include <svx/svxids.hrc>
44 #endif
45 #include <svx/drawitem.hxx>
46 #include <svx/xtable.hxx>
47 //==================================================================
48 #include <vcl/floatwin.hxx>
49 #include <svtools/svmedit.hxx>
50 #include <svtools/colorcfg.hxx>
51 #include <unotools/syslocale.hxx>
52 #include <unotools/datetime.hxx>
53 #include <i18npool/mslangid.hxx>
54 #ifndef _SV_BUTTON_HXX
55 #include <vcl/button.hxx>
56 #endif
57 #include <vcl/svapp.hxx>
58 //==================================================================
59 
60 #include <memory>
61 #include <limits>
62 #include <boost/bind.hpp>
63 
64 //............................................................................
65 namespace pcr
66 {
67 //............................................................................
68 
69     using namespace ::com::sun::star;
70     using namespace ::com::sun::star::uno;
71     using namespace ::com::sun::star::awt;
72     using namespace ::com::sun::star::lang;
73     using namespace ::com::sun::star::util;
74     using namespace ::com::sun::star::beans;
75     using namespace ::com::sun::star::inspection;
76 
77 	//==================================================================
78 	//= OTimeControl
79 	//==================================================================
80 	//------------------------------------------------------------------
OTimeControl(Window * pParent,WinBits nWinStyle)81 	OTimeControl::OTimeControl( Window* pParent, WinBits nWinStyle )
82         :OTimeControl_Base( PropertyControlType::TimeField, pParent, nWinStyle )
83     {
84 		getTypedControlWindow()->SetStrictFormat( sal_True );
85 		getTypedControlWindow()->SetFormat( TIMEF_SEC );
86 		getTypedControlWindow()->EnableEmptyFieldValue( sal_True );
87 	}
88 
89 	//------------------------------------------------------------------
setValue(const Any & _rValue)90 	void SAL_CALL OTimeControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
91 	{
92         util::Time aUNOTime;
93         if ( !( _rValue >>= aUNOTime ) )
94 		{
95 			getTypedControlWindow()->SetText( String() );
96 			getTypedControlWindow()->SetEmptyTime();
97 		}
98 		else
99 		{
100             ::Time aTime( aUNOTime.Hours, aUNOTime.Minutes, aUNOTime.Seconds, aUNOTime.HundredthSeconds );
101             getTypedControlWindow()->SetTime( aTime );
102 		}
103 	}
104 
105 	//------------------------------------------------------------------
getValue()106 	Any SAL_CALL OTimeControl::getValue() throw (RuntimeException)
107 	{
108         Any aPropValue;
109 		if ( getTypedControlWindow()->GetText().Len()>0 )
110         {
111             ::Time aTime( getTypedControlWindow()->GetTime() );
112             util::Time aUNOTime( aTime.Get100Sec(), aTime.GetSec(), aTime.GetMin(), aTime.GetHour() );
113             aPropValue <<= aUNOTime;
114         }
115         return aPropValue;
116 	}
117 
118 	//------------------------------------------------------------------
getValueType()119     Type SAL_CALL OTimeControl::getValueType() throw (RuntimeException)
120     {
121         return ::getCppuType( static_cast< util::Time* >( NULL ) );
122     }
123 
124 	//==================================================================
125 	//= ODateControl
126 	//==================================================================
127 	//------------------------------------------------------------------
ODateControl(Window * pParent,WinBits nWinStyle)128 	ODateControl::ODateControl( Window* pParent, WinBits nWinStyle )
129         :ODateControl_Base( PropertyControlType::DateField, pParent, nWinStyle | WB_DROPDOWN )
130 	{
131         WindowType* pControlWindow = getTypedControlWindow();
132 		pControlWindow->SetStrictFormat(sal_True);
133 
134         pControlWindow->SetMin( ::Date( 1,1,1600 ) );
135         pControlWindow->SetFirst( ::Date( 1,1,1600 ) );
136         pControlWindow->SetLast( ::Date( 1, 1, 9999 ) );
137         pControlWindow->SetMax( ::Date( 1, 1, 9999 ) );
138 
139 		pControlWindow->SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY );
140 		pControlWindow->EnableEmptyFieldValue( sal_True );
141 	}
142 
143 	//------------------------------------------------------------------
setValue(const Any & _rValue)144 	void SAL_CALL ODateControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
145 	{
146         util::Date aUNODate;
147         if ( !( _rValue >>= aUNODate ) )
148 		{
149 			getTypedControlWindow()->SetText( String() );
150 			getTypedControlWindow()->SetEmptyDate();
151 		}
152 		else
153 		{
154             ::Date aDate( aUNODate.Day, aUNODate.Month, aUNODate.Year );
155             getTypedControlWindow()->SetDate( aDate );
156 		}
157 	}
158 
159 	//------------------------------------------------------------------
getValue()160 	Any SAL_CALL ODateControl::getValue() throw (RuntimeException)
161 	{
162         Any aPropValue;
163 		if ( getTypedControlWindow()->GetText().Len() > 0 )
164         {
165             ::Date aDate( getTypedControlWindow()->GetDate() );
166             util::Date aUNODate( aDate.GetDay(), aDate.GetMonth(), aDate.GetYear() );
167             aPropValue <<= aUNODate;
168         }
169         return aPropValue;
170 	}
171 
172 	//------------------------------------------------------------------
getValueType()173     Type SAL_CALL ODateControl::getValueType() throw (RuntimeException)
174     {
175         return ::getCppuType( static_cast< util::Date* >( NULL ) );
176     }
177 
178 	//==================================================================
179 	//= OEditControl
180 	//==================================================================
181 	//------------------------------------------------------------------
OEditControl(Window * _pParent,sal_Bool _bPW,WinBits _nWinStyle)182 	OEditControl::OEditControl(Window* _pParent, sal_Bool _bPW, WinBits _nWinStyle)
183         :OEditControl_Base( _bPW ? PropertyControlType::CharacterField : PropertyControlType::TextField, _pParent, _nWinStyle )
184 	{
185 		m_bIsPassword = _bPW;
186 
187 		if ( m_bIsPassword )
188 		   getTypedControlWindow()->SetMaxTextLen( 1 );
189 	}
190 
191 	//------------------------------------------------------------------
setValue(const Any & _rValue)192 	void SAL_CALL OEditControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
193 	{
194         ::rtl::OUString sText;
195 		if ( m_bIsPassword )
196         {
197             sal_Int16 nValue = 0;
198             _rValue >>= nValue;
199             if ( nValue )
200             {
201 			    sal_Unicode nCharacter = nValue;
202                 sText = String( &nCharacter, 1 );
203             }
204         }
205         else
206             _rValue >>= sText;
207 
208 		getTypedControlWindow()->SetText( sText );
209 	}
210 
211 	//------------------------------------------------------------------
getValue()212 	Any SAL_CALL OEditControl::getValue() throw (RuntimeException)
213 	{
214         Any aPropValue;
215 
216         ::rtl::OUString sText( getTypedControlWindow()->GetText() );
217 		if ( m_bIsPassword )
218 		{
219 			if ( sText.getLength() )
220                 aPropValue <<= (sal_Int16)sText.getStr()[0];
221 		}
222         else
223             aPropValue <<= sText;
224 
225 		return aPropValue;
226 	}
227 
228 	//------------------------------------------------------------------
getValueType()229     Type SAL_CALL OEditControl::getValueType() throw (RuntimeException)
230     {
231         return m_bIsPassword ? ::getCppuType( static_cast< sal_Int16* >( NULL ) ) : ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
232     }
233 
234 	//------------------------------------------------------------------
modified()235 	void OEditControl::modified()
236 	{
237 		OEditControl_Base::modified();
238 
239 		// for pasword controls, we fire a commit for every single change
240 		if ( m_bIsPassword )
241 			m_aImplControl.notifyModifiedValue();
242 	}
243 
244 	//------------------------------------------------------------------
ImplCalcLongValue(double nValue,sal_uInt16 nDigits)245 	static long ImplCalcLongValue( double nValue, sal_uInt16 nDigits )
246 	{
247 		double n = nValue;
248 		for ( sal_uInt16 d = 0; d < nDigits; ++d )
249 			n *= 10;
250 
251         if ( n > ::std::numeric_limits< long >::max() )
252             return ::std::numeric_limits< long >::max();
253 		return (long)n;
254 	}
255 
256 	//------------------------------------------------------------------
ImplCalcDoubleValue(long nValue,sal_uInt16 nDigits)257 	static double ImplCalcDoubleValue( long nValue, sal_uInt16 nDigits )
258 	{
259 		double n = nValue;
260 		for ( sal_uInt16 d = 0; d < nDigits; ++d )
261 			n /= 10;
262 		return n;
263 	}
264 
265     //==================================================================
266 	// class ODateTimeControl
267 	//==================================================================
268 	//------------------------------------------------------------------
ODateTimeControl(Window * _pParent,WinBits _nWinStyle)269 	ODateTimeControl::ODateTimeControl( Window* _pParent, WinBits _nWinStyle)
270         :ODateTimeControl_Base( PropertyControlType::DateTimeField, _pParent, _nWinStyle )
271 	{
272 		getTypedControlWindow()->EnableEmptyField( sal_True );
273 
274         // determine a default format
275         Locale aSysLocale = SvtSysLocale().GetLocaleData().getLocale();
276         LanguageType eSysLanguage = MsLangId::convertLocaleToLanguage( aSysLocale );
277 
278         getTypedControlWindow()->SetFormatter( getTypedControlWindow()->StandardFormatter() );
279         SvNumberFormatter* pFormatter = getTypedControlWindow()->GetFormatter();
280         sal_uLong nStandardDateTimeFormat = pFormatter->GetStandardFormat( NUMBERFORMAT_DATETIME, eSysLanguage );
281 
282         getTypedControlWindow()->SetFormatKey( nStandardDateTimeFormat );
283 	}
284 
285 	//------------------------------------------------------------------
setValue(const Any & _rValue)286     void SAL_CALL ODateTimeControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
287     {
288 		if ( !_rValue.hasValue() )
289         {
290             getTypedControlWindow()->SetText( String() );
291         }
292         else
293         {
294             util::DateTime aUNODateTime;
295             OSL_VERIFY( _rValue >>= aUNODateTime );
296 
297             ::DateTime aDateTime;
298             ::utl::typeConvert( aUNODateTime, aDateTime );
299 
300             double nValue = aDateTime - ::DateTime( *getTypedControlWindow()->GetFormatter()->GetNullDate() );
301             getTypedControlWindow()->SetValue( nValue );
302         }
303     }
304 
305 	//------------------------------------------------------------------
getValue()306     Any SAL_CALL ODateTimeControl::getValue() throw (RuntimeException)
307     {
308         Any aPropValue;
309         if ( getTypedControlWindow()->GetText().Len() )
310         {
311             double nValue = getTypedControlWindow()->GetValue();
312 
313             ::DateTime aDateTime( *getTypedControlWindow()->GetFormatter()->GetNullDate() );
314 
315             // add the "days" part
316             double nDays = floor( nValue );
317             aDateTime += nDays;
318 
319             // add the "time" part
320             double nTime = nValue - nDays;
321             nTime = ::rtl::math::round( nTime * 86400.0 ) / 86400.0;
322                 // we're not interested in 100th seconds, and this here prevents rounding errors
323             aDateTime += nTime;
324 
325             util::DateTime aUNODateTime;
326             ::utl::typeConvert( aDateTime, aUNODateTime );
327 
328             aPropValue <<= aUNODateTime;
329         }
330         return aPropValue;
331     }
332 
333 	//------------------------------------------------------------------
getValueType()334     Type SAL_CALL ODateTimeControl::getValueType() throw (RuntimeException)
335     {
336         return ::getCppuType( static_cast< util::DateTime* >( NULL ) );
337     }
338 
339     //========================================================================
340     //= HyperlinkInput
341     //========================================================================
342     //--------------------------------------------------------------------
HyperlinkInput(Window * _pParent,WinBits _nWinStyle)343     HyperlinkInput::HyperlinkInput( Window* _pParent, WinBits _nWinStyle )
344         :Edit( _pParent, _nWinStyle )
345     {
346         ::svtools::ColorConfig aColorConfig;
347         ::svtools::ColorConfigValue aLinkColor( aColorConfig.GetColorValue( ::svtools::LINKS ) );
348 
349         AllSettings aAllSettings( GetSettings() );
350         StyleSettings aStyleSettings( aAllSettings.GetStyleSettings() );
351 
352         Font aFieldFont( aStyleSettings.GetFieldFont() );
353         aFieldFont.SetUnderline( UNDERLINE_SINGLE );
354         aFieldFont.SetColor( aLinkColor.nColor );
355         aStyleSettings.SetFieldFont( aFieldFont );
356 
357         aStyleSettings.SetFieldTextColor( aLinkColor.nColor );
358 
359         aAllSettings.SetStyleSettings( aStyleSettings );
360         SetSettings( aAllSettings );
361     }
362 
363     //--------------------------------------------------------------------
MouseMove(const::MouseEvent & rMEvt)364     void HyperlinkInput::MouseMove( const ::MouseEvent& rMEvt )
365     {
366         Edit::MouseMove( rMEvt );
367 
368         PointerStyle ePointerStyle( POINTER_TEXT );
369 
370         if ( !rMEvt.IsLeaveWindow() )
371         {
372             if ( impl_textHitTest( rMEvt.GetPosPixel() ) )
373                 ePointerStyle = POINTER_REFHAND;
374         }
375 
376         SetPointer( Pointer( ePointerStyle ) );
377     }
378 
379     //--------------------------------------------------------------------
MouseButtonDown(const::MouseEvent & rMEvt)380     void HyperlinkInput::MouseButtonDown( const ::MouseEvent& rMEvt )
381     {
382         Edit::MouseButtonDown( rMEvt );
383 
384         if ( impl_textHitTest( rMEvt.GetPosPixel() ) )
385             m_aMouseButtonDownPos = rMEvt.GetPosPixel();
386         else
387             m_aMouseButtonDownPos.X() = m_aMouseButtonDownPos.Y() = -1;
388     }
389 
390     //--------------------------------------------------------------------
MouseButtonUp(const::MouseEvent & rMEvt)391     void HyperlinkInput::MouseButtonUp( const ::MouseEvent& rMEvt )
392     {
393         Edit::MouseButtonUp( rMEvt );
394 
395         impl_checkEndClick( rMEvt );
396     }
397 
398     //--------------------------------------------------------------------
impl_textHitTest(const::Point & _rWindowPos)399     bool HyperlinkInput::impl_textHitTest( const ::Point& _rWindowPos )
400     {
401         xub_StrLen nPos = GetCharPos( _rWindowPos );
402         return ( ( nPos != STRING_LEN ) && ( nPos < GetText().Len() ) );
403     }
404 
405     //--------------------------------------------------------------------
impl_checkEndClick(const::MouseEvent rMEvt)406     void HyperlinkInput::impl_checkEndClick( const ::MouseEvent rMEvt )
407     {
408         const MouseSettings& rMouseSettings( GetSettings().GetMouseSettings() );
409         if  (   ( abs( rMEvt.GetPosPixel().X() - m_aMouseButtonDownPos.X() ) < rMouseSettings.GetStartDragWidth() )
410             &&  ( abs( rMEvt.GetPosPixel().Y() - m_aMouseButtonDownPos.Y() ) < rMouseSettings.GetStartDragHeight() )
411             )
412             Application::PostUserEvent( m_aClickHandler );
413     }
414 
415     //--------------------------------------------------------------------
Tracking(const TrackingEvent & rTEvt)416     void HyperlinkInput::Tracking( const TrackingEvent& rTEvt )
417     {
418         Edit::Tracking( rTEvt );
419 
420         if ( rTEvt.IsTrackingEnded() )
421             impl_checkEndClick( rTEvt.GetMouseEvent() );
422     }
423 
424     //========================================================================
425     //= OHyperlinkControl
426     //========================================================================
427     //--------------------------------------------------------------------
OHyperlinkControl(Window * _pParent,WinBits _nWinStyle)428     OHyperlinkControl::OHyperlinkControl( Window* _pParent, WinBits _nWinStyle )
429         :OHyperlinkControl_Base( PropertyControlType::HyperlinkField, _pParent, _nWinStyle )
430         ,m_aActionListeners( m_aMutex )
431     {
432         getTypedControlWindow()->SetClickHdl( LINK( this, OHyperlinkControl, OnHyperlinkClicked ) );
433     }
434 
435     //--------------------------------------------------------------------
getValue()436     Any SAL_CALL OHyperlinkControl::getValue() throw (RuntimeException)
437     {
438         ::rtl::OUString sText = getTypedControlWindow()->GetText();
439         return makeAny( sText );
440     }
441 
442     //--------------------------------------------------------------------
setValue(const Any & _value)443     void SAL_CALL OHyperlinkControl::setValue( const Any& _value ) throw (IllegalTypeException, RuntimeException)
444     {
445         ::rtl::OUString sText;
446         _value >>= sText;
447         getTypedControlWindow()->SetText( sText );
448     }
449 
450     //--------------------------------------------------------------------
getValueType()451     Type SAL_CALL OHyperlinkControl::getValueType() throw (RuntimeException)
452     {
453         return ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
454     }
455 
456     //--------------------------------------------------------------------
addActionListener(const Reference<XActionListener> & listener)457     void SAL_CALL OHyperlinkControl::addActionListener( const Reference< XActionListener >& listener ) throw (RuntimeException)
458     {
459         if ( listener.is() )
460             m_aActionListeners.addInterface( listener );
461     }
462 
463     //--------------------------------------------------------------------
removeActionListener(const Reference<XActionListener> & listener)464     void SAL_CALL OHyperlinkControl::removeActionListener( const Reference< XActionListener >& listener ) throw (RuntimeException)
465     {
466         m_aActionListeners.removeInterface( listener );
467     }
468 
469 	//------------------------------------------------------------------
disposing()470     void SAL_CALL OHyperlinkControl::disposing()
471     {
472         OHyperlinkControl_Base::disposing();
473 
474         EventObject aEvent( *this );
475         m_aActionListeners.disposeAndClear( aEvent );
476     }
477 
478 	//------------------------------------------------------------------
479     IMPL_LINK( OHyperlinkControl, OnHyperlinkClicked, void*, /*_NotInterestedIn*/ )
480     {
481         ActionEvent aEvent( *this, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "clicked" ) ) );
482         m_aActionListeners.forEach< XActionListener >(
483             boost::bind(
484                 &XActionListener::actionPerformed,
485                 _1, boost::cref(aEvent) ) );
486 
487         return 0;
488     }
489 
490     //==================================================================
491 	//= ONumericControl
492 	//==================================================================
493 	//------------------------------------------------------------------
ONumericControl(Window * _pParent,WinBits _nWinStyle)494 	ONumericControl::ONumericControl( Window* _pParent, WinBits _nWinStyle )
495         :ONumericControl_Base( PropertyControlType::NumericField, _pParent, _nWinStyle )
496         ,m_eValueUnit( FUNIT_NONE )
497         ,m_nFieldToUNOValueFactor( 1 )
498 	{
499         getTypedControlWindow()->SetDefaultUnit( FUNIT_NONE );
500 
501 		getTypedControlWindow()->EnableEmptyFieldValue( sal_True );
502 		getTypedControlWindow()->SetStrictFormat( sal_True );
503         Optional< double > value( getMaxValue() );
504         value.Value = -value.Value;
505         setMinValue( value );
506 	}
507 
508     //--------------------------------------------------------------------
getDecimalDigits()509     ::sal_Int16 SAL_CALL ONumericControl::getDecimalDigits() throw (RuntimeException)
510     {
511         return getTypedControlWindow()->GetDecimalDigits();
512     }
513 
514     //--------------------------------------------------------------------
setDecimalDigits(::sal_Int16 _decimaldigits)515     void SAL_CALL ONumericControl::setDecimalDigits( ::sal_Int16 _decimaldigits ) throw (RuntimeException)
516     {
517         getTypedControlWindow()->SetDecimalDigits( _decimaldigits );
518     }
519 
520     //--------------------------------------------------------------------
getMinValue()521     Optional< double > SAL_CALL ONumericControl::getMinValue() throw (RuntimeException)
522     {
523         Optional< double > aReturn( sal_True, 0 );
524 
525         sal_Int64 minValue = getTypedControlWindow()->GetMin();
526         if ( minValue == ::std::numeric_limits< sal_Int64 >::min() )
527             aReturn.IsPresent = sal_False;
528         else
529             aReturn.Value = (double)minValue;
530 
531         return aReturn;
532     }
533 
534     //--------------------------------------------------------------------
setMinValue(const Optional<double> & _minvalue)535     void SAL_CALL ONumericControl::setMinValue( const Optional< double >& _minvalue ) throw (RuntimeException)
536     {
537         if ( !_minvalue.IsPresent )
538             getTypedControlWindow()->SetMin( ::std::numeric_limits< sal_Int64 >::min() );
539         else
540             getTypedControlWindow()->SetMin( impl_apiValueToFieldValue_nothrow( _minvalue.Value ) , m_eValueUnit);
541     }
542 
543     //--------------------------------------------------------------------
getMaxValue()544     Optional< double > SAL_CALL ONumericControl::getMaxValue() throw (RuntimeException)
545     {
546         Optional< double > aReturn( sal_True, 0 );
547 
548         sal_Int64 maxValue = getTypedControlWindow()->GetMax();
549         if ( maxValue == ::std::numeric_limits< sal_Int64 >::max() )
550             aReturn.IsPresent = sal_False;
551         else
552             aReturn.Value = (double)maxValue;
553 
554         return aReturn;
555     }
556 
557     //--------------------------------------------------------------------
setMaxValue(const Optional<double> & _maxvalue)558     void SAL_CALL ONumericControl::setMaxValue( const Optional< double >& _maxvalue ) throw (RuntimeException)
559     {
560         if ( !_maxvalue.IsPresent )
561             getTypedControlWindow()->SetMax( ::std::numeric_limits< sal_Int64 >::max() );
562         else
563             getTypedControlWindow()->SetMax( impl_apiValueToFieldValue_nothrow( _maxvalue.Value ), m_eValueUnit );
564     }
565 
566     //--------------------------------------------------------------------
getDisplayUnit()567     ::sal_Int16 SAL_CALL ONumericControl::getDisplayUnit() throw (RuntimeException)
568     {
569         return VCLUnoHelper::ConvertToMeasurementUnit( getTypedControlWindow()->GetUnit(), 1 );
570     }
571 
572     //--------------------------------------------------------------------
setDisplayUnit(::sal_Int16 _displayunit)573     void SAL_CALL ONumericControl::setDisplayUnit( ::sal_Int16 _displayunit ) throw (IllegalArgumentException, RuntimeException)
574     {
575         if ( ( _displayunit < MeasureUnit::MM_100TH ) || ( _displayunit > MeasureUnit::PERCENT ) )
576             throw IllegalArgumentException();
577         if  (   ( _displayunit == MeasureUnit::MM_100TH )
578             ||  ( _displayunit == MeasureUnit::MM_10TH )
579             ||  ( _displayunit == MeasureUnit::INCH_1000TH )
580             ||  ( _displayunit == MeasureUnit::INCH_100TH )
581             ||  ( _displayunit == MeasureUnit::INCH_10TH )
582             ||  ( _displayunit == MeasureUnit::PERCENT )
583             )
584             throw IllegalArgumentException();
585 
586         sal_Int16 nDummyFactor = 1;
587         FieldUnit eFieldUnit = VCLUnoHelper::ConvertToFieldUnit( _displayunit, nDummyFactor );
588         if ( nDummyFactor != 1 )
589             // everything which survived the checks above should result in a factor of 1, i.e.,
590             // it should have a direct counterpart as FieldUnit
591             throw RuntimeException();
592         getTypedControlWindow()->SetUnit( eFieldUnit );
593     }
594 
595     //--------------------------------------------------------------------
getValueUnit()596     ::sal_Int16 SAL_CALL ONumericControl::getValueUnit() throw (RuntimeException)
597     {
598         return VCLUnoHelper::ConvertToMeasurementUnit( m_eValueUnit, m_nFieldToUNOValueFactor );
599     }
600 
601     //--------------------------------------------------------------------
setValueUnit(::sal_Int16 _valueunit)602     void SAL_CALL ONumericControl::setValueUnit( ::sal_Int16 _valueunit ) throw (RuntimeException)
603     {
604         if ( ( _valueunit < MeasureUnit::MM_100TH ) || ( _valueunit > MeasureUnit::PERCENT ) )
605             throw IllegalArgumentException();
606         m_eValueUnit = VCLUnoHelper::ConvertToFieldUnit( _valueunit, m_nFieldToUNOValueFactor );
607     }
608 
609     //--------------------------------------------------------------------
setValue(const Any & _rValue)610     void SAL_CALL ONumericControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
611 	{
612 		if ( !_rValue.hasValue() )
613 		{
614 			getTypedControlWindow()->SetText( String() );
615 			getTypedControlWindow()->SetEmptyFieldValue();
616 		}
617 		else
618 		{
619             double nValue( 0 );
620             OSL_VERIFY( _rValue >>= nValue );
621             long nControlValue = impl_apiValueToFieldValue_nothrow( nValue );
622             getTypedControlWindow()->SetValue( nControlValue, m_eValueUnit );
623 		}
624 	}
625 
626 	//------------------------------------------------------------------
impl_apiValueToFieldValue_nothrow(double _nApiValue) const627     long ONumericControl::impl_apiValueToFieldValue_nothrow( double _nApiValue ) const
628     {
629         long nControlValue = ImplCalcLongValue( _nApiValue, getTypedControlWindow()->GetDecimalDigits() );
630         nControlValue /= m_nFieldToUNOValueFactor;
631         return nControlValue;
632     }
633 
634 	//------------------------------------------------------------------
impl_fieldValueToApiValue_nothrow(sal_Int64 _nFieldValue) const635     double ONumericControl::impl_fieldValueToApiValue_nothrow( sal_Int64 _nFieldValue ) const
636     {
637 		double nApiValue = ImplCalcDoubleValue( (long)_nFieldValue, getTypedControlWindow()->GetDecimalDigits() );
638         nApiValue *= m_nFieldToUNOValueFactor;
639         return nApiValue;
640     }
641 
642 	//------------------------------------------------------------------
getValue()643 	Any SAL_CALL ONumericControl::getValue() throw (RuntimeException)
644 	{
645         Any aPropValue;
646 		if ( getTypedControlWindow()->GetText().Len() )
647         {
648             double nValue = impl_fieldValueToApiValue_nothrow( getTypedControlWindow()->GetValue( m_eValueUnit ) );
649             aPropValue <<= nValue;
650         }
651         return aPropValue;
652 	}
653 
654 	//------------------------------------------------------------------
getValueType()655     Type SAL_CALL ONumericControl::getValueType() throw (RuntimeException)
656     {
657         return ::getCppuType( static_cast< double* >( NULL ) );
658     }
659 
660 	//==================================================================
661 	//= OColorControl
662 	//==================================================================
663 	#define LB_DEFAULT_COUNT 20
664 	//------------------------------------------------------------------
MakeHexStr(sal_uInt32 nVal,sal_uInt32 nLength)665 	String MakeHexStr(sal_uInt32 nVal, sal_uInt32 nLength)
666 	{
667 		String aStr;
668 		while (nVal>0)
669 		{
670 			char c=char(nVal & 0x000F);
671 			nVal>>=4;
672 			if (c<=9) c+='0';
673 			else c+='A'-10;
674 			aStr.Insert(c,0);
675 		}
676 		while (aStr.Len() < nLength) aStr.Insert('0',0);
677 		return aStr;
678 	}
679 
680 	//------------------------------------------------------------------
OColorControl(Window * pParent,WinBits nWinStyle)681 	OColorControl::OColorControl(Window* pParent, WinBits nWinStyle)
682         :OColorControl_Base( PropertyControlType::ColorListBox, pParent, nWinStyle )
683 	{
684 		// initialize the color listbox
685         XColorListSharedPtr aColorTable;
686         SfxObjectShell* pDocSh = SfxObjectShell::Current();
687         const SfxPoolItem* pItem = pDocSh ? pDocSh->GetItem( SID_COLOR_TABLE ) : NULL;
688         if ( pItem )
689         {
690             DBG_ASSERT(pItem->ISA(SvxColorTableItem), "OColorControl::OColorControl: invalid color item!");
691 		    aColorTable = static_cast< const SvxColorTableItem* >(pItem)->GetColorTable();
692         }
693 
694         if ( !aColorTable.get() )
695 	    {
696 		    aColorTable = XColorList::GetStdColorList();
697 	    }
698 
699 		DBG_ASSERT(aColorTable.get(), "OColorControl::OColorControl: no color table!");
700 
701 		if (aColorTable.get())
702 		{
703 			for (sal_uInt16 i = 0; i < aColorTable->Count(); ++i)
704 			{
705 				XColorEntry* pEntry = aColorTable->GetColor( i );
706 				getTypedControlWindow()->InsertEntry( pEntry->GetColor(), pEntry->GetName() );
707 			}
708 		}
709 
710 		getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT );
711         if ( ( nWinStyle & WB_READONLY ) != 0 )
712         {
713             getTypedControlWindow()->SetReadOnly( sal_True );
714             getTypedControlWindow()->Enable( sal_True );
715         }
716 	}
717 
718 	//------------------------------------------------------------------
setValue(const Any & _rValue)719 	void SAL_CALL OColorControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
720 	{
721 		if ( _rValue.hasValue() )
722         {
723             ::com::sun::star::util::Color nColor = COL_TRANSPARENT;
724             if ( _rValue >>= nColor )
725             {
726                 ::Color aRgbCol((ColorData)nColor);
727 
728 				getTypedControlWindow()->SelectEntry( aRgbCol );
729 				if ( !getTypedControlWindow()->IsEntrySelected( aRgbCol ) )
730 				{	// the given color is not part of the list -> insert a new entry with the hex code of the color
731 					String aStr = String::CreateFromAscii("0x");
732 					aStr += MakeHexStr(nColor,8);
733 					getTypedControlWindow()->InsertEntry( aRgbCol, aStr );
734 					getTypedControlWindow()->SelectEntry( aRgbCol );
735 				}
736             }
737             else
738             {
739                 ::rtl::OUString sNonColorValue;
740                 if ( !( _rValue >>= sNonColorValue ) )
741                     throw IllegalTypeException();
742                 getTypedControlWindow()->SelectEntry( sNonColorValue );
743                 if ( !getTypedControlWindow()->IsEntrySelected( sNonColorValue ) )
744                     getTypedControlWindow()->SetNoSelection();
745             }
746 		}
747 		else
748 			getTypedControlWindow()->SetNoSelection();
749 	}
750 
751 	//------------------------------------------------------------------
getValue()752 	Any SAL_CALL OColorControl::getValue() throw (RuntimeException)
753 	{
754         Any aPropValue;
755 		if ( getTypedControlWindow()->GetSelectEntryCount() > 0 )
756 		{
757             ::rtl::OUString sSelectedEntry = getTypedControlWindow()->GetSelectEntry();
758             if ( m_aNonColorEntries.find( sSelectedEntry ) != m_aNonColorEntries.end() )
759                 aPropValue <<= sSelectedEntry;
760             else
761 			{
762                 ::Color aRgbCol = getTypedControlWindow()->GetSelectEntryColor();
763                 aPropValue <<= (::com::sun::star::util::Color)aRgbCol.GetColor();
764 			}
765 		}
766 		return aPropValue;
767 	}
768 
769 	//------------------------------------------------------------------
getValueType()770     Type SAL_CALL OColorControl::getValueType() throw (RuntimeException)
771     {
772         return ::getCppuType( static_cast< sal_Int32* >( NULL ) );
773     }
774 
775 	//------------------------------------------------------------------
clearList()776 	void SAL_CALL OColorControl::clearList() throw (RuntimeException)
777 	{
778 		getTypedControlWindow()->Clear();
779 	}
780 
781 	//------------------------------------------------------------------
prependListEntry(const::rtl::OUString & NewEntry)782 	void SAL_CALL OColorControl::prependListEntry( const ::rtl::OUString& NewEntry ) throw (RuntimeException)
783 	{
784 		getTypedControlWindow()->InsertEntry( NewEntry, 0 );
785         m_aNonColorEntries.insert( NewEntry );
786 	}
787 
788 	//------------------------------------------------------------------
appendListEntry(const::rtl::OUString & NewEntry)789 	void SAL_CALL OColorControl::appendListEntry( const ::rtl::OUString& NewEntry ) throw (RuntimeException)
790 	{
791 		getTypedControlWindow()->InsertEntry( NewEntry );
792         m_aNonColorEntries.insert( NewEntry );
793 	}
794     //------------------------------------------------------------------
getListEntries()795     Sequence< ::rtl::OUString > SAL_CALL OColorControl::getListEntries(  ) throw (RuntimeException)
796     {
797         if ( !m_aNonColorEntries.empty() )
798             return Sequence< ::rtl::OUString >(&(*m_aNonColorEntries.begin()),m_aNonColorEntries.size());
799         return Sequence< ::rtl::OUString >();
800     }
801 
802 	//------------------------------------------------------------------
modified()803 	void OColorControl::modified()
804 	{
805 		OColorControl_Base::modified();
806 
807 		if ( !getTypedControlWindow()->IsTravelSelect() )
808 			// fire a commit
809 			m_aImplControl.notifyModifiedValue();
810 	}
811 
812 	//==================================================================
813 	//= OListboxControl
814 	//==================================================================
815 	//------------------------------------------------------------------
OListboxControl(Window * pParent,WinBits nWinStyle)816 	OListboxControl::OListboxControl( Window* pParent, WinBits nWinStyle)
817         :OListboxControl_Base( PropertyControlType::ListBox, pParent, nWinStyle )
818 	{
819 		getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT );
820         if ( ( nWinStyle & WB_READONLY ) != 0 )
821         {
822             getTypedControlWindow()->SetReadOnly( sal_True );
823             getTypedControlWindow()->Enable( sal_True );
824         }
825 	}
826 
827 	//------------------------------------------------------------------
getValue()828 	Any SAL_CALL OListboxControl::getValue() throw (RuntimeException)
829 	{
830         ::rtl::OUString sControlValue( getTypedControlWindow()->GetSelectEntry() );
831 
832         Any aPropValue;
833         if ( sControlValue.getLength() )
834             aPropValue <<= sControlValue;
835 		return aPropValue;
836 	}
837 
838 	//------------------------------------------------------------------
getValueType()839     Type SAL_CALL OListboxControl::getValueType() throw (RuntimeException)
840     {
841         return ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
842     }
843 
844 	//------------------------------------------------------------------
setValue(const Any & _rValue)845 	void SAL_CALL OListboxControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
846 	{
847 		if ( !_rValue.hasValue() )
848             getTypedControlWindow()->SetNoSelection();
849         else
850 		{
851             ::rtl::OUString sSelection;
852             _rValue >>= sSelection;
853 
854             if ( !sSelection.equals( getTypedControlWindow()->GetSelectEntry() ) )
855 				getTypedControlWindow()->SelectEntry( sSelection );
856 
857 			if ( !getTypedControlWindow()->IsEntrySelected( sSelection ) )
858 			{
859 				getTypedControlWindow()->InsertEntry( sSelection, 0 );
860 				getTypedControlWindow()->SelectEntry( sSelection );
861 			}
862 		}
863 	}
864 
865 	//------------------------------------------------------------------
clearList()866 	void SAL_CALL OListboxControl::clearList() throw (RuntimeException)
867 	{
868 		getTypedControlWindow()->Clear();
869 	}
870 
871 	//------------------------------------------------------------------
prependListEntry(const::rtl::OUString & NewEntry)872 	void SAL_CALL OListboxControl::prependListEntry( const ::rtl::OUString& NewEntry ) throw (RuntimeException)
873 	{
874 		getTypedControlWindow()->InsertEntry( NewEntry, 0 );
875 	}
876 
877 	//------------------------------------------------------------------
appendListEntry(const::rtl::OUString & NewEntry)878 	void SAL_CALL OListboxControl::appendListEntry( const ::rtl::OUString& NewEntry ) throw (RuntimeException)
879 	{
880 		getTypedControlWindow()->InsertEntry( NewEntry );
881 	}
882     //------------------------------------------------------------------
getListEntries()883     Sequence< ::rtl::OUString > SAL_CALL OListboxControl::getListEntries(  ) throw (RuntimeException)
884     {
885         const sal_uInt16 nCount = getTypedControlWindow()->GetEntryCount();
886         Sequence< ::rtl::OUString > aRet(nCount);
887         ::rtl::OUString* pIter = aRet.getArray();
888         for (sal_uInt16 i = 0; i < nCount ; ++i,++pIter)
889             *pIter = getTypedControlWindow()->GetEntry(i);
890 
891         return aRet;
892     }
893 
894 	//------------------------------------------------------------------
modified()895 	void OListboxControl::modified()
896 	{
897 		OListboxControl_Base::modified();
898 
899 		if ( !getTypedControlWindow()->IsTravelSelect() )
900 			// fire a commit
901 			m_aImplControl.notifyModifiedValue();
902 	}
903 
904 	//==================================================================
905 	//= OComboboxControl
906 	//==================================================================
907 	//------------------------------------------------------------------
OComboboxControl(Window * pParent,WinBits nWinStyle)908 	OComboboxControl::OComboboxControl( Window* pParent, WinBits nWinStyle)
909         :OComboboxControl_Base( PropertyControlType::ComboBox, pParent, nWinStyle )
910     {
911 		getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT );
912         getTypedControlWindow()->SetSelectHdl( LINK( this, OComboboxControl, OnEntrySelected ) );
913 	}
914 
915 	//------------------------------------------------------------------
setValue(const Any & _rValue)916 	void SAL_CALL OComboboxControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
917 	{
918 		::rtl::OUString sText;
919         _rValue >>= sText;
920 		getTypedControlWindow()->SetText( sText );
921 	}
922 
923 	//------------------------------------------------------------------
getValue()924 	Any SAL_CALL OComboboxControl::getValue() throw (RuntimeException)
925 	{
926         return makeAny( ::rtl::OUString( getTypedControlWindow()->GetText() ) );
927 	}
928 
929 	//------------------------------------------------------------------
getValueType()930     Type SAL_CALL OComboboxControl::getValueType() throw (RuntimeException)
931     {
932         return ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
933     }
934 
935 	//------------------------------------------------------------------
clearList()936 	void SAL_CALL OComboboxControl::clearList() throw (RuntimeException)
937 	{
938 		getTypedControlWindow()->Clear();
939 	}
940 
941 	//------------------------------------------------------------------
prependListEntry(const::rtl::OUString & NewEntry)942 	void SAL_CALL OComboboxControl::prependListEntry( const ::rtl::OUString& NewEntry ) throw (RuntimeException)
943 	{
944 		getTypedControlWindow()->InsertEntry( NewEntry, 0 );
945 	}
946 
947 	//------------------------------------------------------------------
appendListEntry(const::rtl::OUString & NewEntry)948 	void SAL_CALL OComboboxControl::appendListEntry( const ::rtl::OUString& NewEntry ) throw (RuntimeException)
949 	{
950 		getTypedControlWindow()->InsertEntry( NewEntry );
951 	}
952     //------------------------------------------------------------------
getListEntries()953     Sequence< ::rtl::OUString > SAL_CALL OComboboxControl::getListEntries(  ) throw (RuntimeException)
954     {
955         const sal_uInt16 nCount = getTypedControlWindow()->GetEntryCount();
956         Sequence< ::rtl::OUString > aRet(nCount);
957         ::rtl::OUString* pIter = aRet.getArray();
958         for (sal_uInt16 i = 0; i < nCount ; ++i,++pIter)
959             *pIter = getTypedControlWindow()->GetEntry(i);
960 
961         return aRet;
962     }
963 
964 	//------------------------------------------------------------------
965     IMPL_LINK( OComboboxControl, OnEntrySelected, void*, /*_pNothing*/ )
966 	{
967 		if ( !getTypedControlWindow()->IsTravelSelect() )
968 			// fire a commit
969 			m_aImplControl.notifyModifiedValue();
970         return 0L;
971 	}
972 
973 	//==================================================================
974 	//= OMultilineFloatingEdit
975 	//==================================================================
976 	class OMultilineFloatingEdit : public FloatingWindow
977 	{
978 	private:
979 		MultiLineEdit	m_aImplEdit;
980 
981 	protected:
982 		virtual void	Resize();
983 
984 	public:
985 						OMultilineFloatingEdit(Window* _pParen);
getEdit()986 		MultiLineEdit*  getEdit() { return &m_aImplEdit; }
987 
988 	protected:
989 		virtual long	PreNotify(NotifyEvent& _rNEvt);
990 	};
991 
992 	//------------------------------------------------------------------
OMultilineFloatingEdit(Window * _pParent)993 	OMultilineFloatingEdit::OMultilineFloatingEdit(Window* _pParent)
994 		:FloatingWindow(_pParent, WB_BORDER)
995 		,m_aImplEdit(this, WB_VSCROLL|WB_IGNORETAB|WB_NOBORDER)
996 	{
997 		m_aImplEdit.Show();
998 	}
999 
1000 	//------------------------------------------------------------------
Resize()1001 	void OMultilineFloatingEdit::Resize()
1002 	{
1003 		m_aImplEdit.SetSizePixel(GetOutputSizePixel());
1004 	}
1005 
1006 	//------------------------------------------------------------------
PreNotify(NotifyEvent & _rNEvt)1007 	long OMultilineFloatingEdit::PreNotify(NotifyEvent& _rNEvt)
1008 	{
1009 		long nResult = sal_True;
1010 
1011 		sal_uInt16 nSwitch = _rNEvt.GetType();
1012 		if (EVENT_KEYINPUT == nSwitch)
1013 		{
1014 			const KeyCode& aKeyCode = _rNEvt.GetKeyEvent()->GetKeyCode();
1015 			sal_uInt16 nKey = aKeyCode.GetCode();
1016 
1017 			if	(	(	(KEY_RETURN == nKey)
1018 					&& !aKeyCode.IsShift()
1019 					)
1020 				||	(	(KEY_UP == nKey)
1021 					&&	aKeyCode.IsMod2()
1022 					)
1023 				)
1024 			{
1025 				EndPopupMode();
1026 			}
1027 			else
1028 				nResult=FloatingWindow::PreNotify(_rNEvt);
1029 		}
1030 		else
1031 			nResult=FloatingWindow::PreNotify(_rNEvt);
1032 
1033 		return nResult;
1034 	}
1035 
1036 	//==================================================================
1037 	//= DropDownEditControl_Base
1038 	//==================================================================
1039 	//------------------------------------------------------------------
DropDownEditControl(Window * _pParent,WinBits _nStyle)1040     DropDownEditControl::DropDownEditControl( Window* _pParent, WinBits _nStyle )
1041         :DropDownEditControl_Base( _pParent, _nStyle )
1042 		,m_pFloatingEdit( NULL )
1043 		,m_pImplEdit( NULL )
1044 		,m_pDropdownButton( NULL )
1045         ,m_nOperationMode( eStringList )
1046 		,m_bDropdown( sal_False )
1047     {
1048         SetCompoundControl( sal_True );
1049 
1050 		m_pImplEdit = new MultiLineEdit( this, WB_TABSTOP | WB_IGNORETAB | WB_NOBORDER | (_nStyle & WB_READONLY) );
1051         SetSubEdit( m_pImplEdit );
1052 		m_pImplEdit->Show();
1053 
1054 		if ( _nStyle & WB_DROPDOWN )
1055 		{
1056 			m_pDropdownButton = new PushButton( this, WB_NOLIGHTBORDER | WB_RECTSTYLE | WB_NOTABSTOP);
1057 			m_pDropdownButton->SetSymbol(SYMBOL_SPIN_DOWN);
1058 			m_pDropdownButton->SetClickHdl( LINK( this, DropDownEditControl, DropDownHdl ) );
1059 			m_pDropdownButton->Show();
1060 		}
1061 
1062 		m_pFloatingEdit = new OMultilineFloatingEdit(this); //FloatingWindow
1063 
1064 		m_pFloatingEdit->SetPopupModeEndHdl( LINK( this, DropDownEditControl, ReturnHdl ) );
1065         m_pFloatingEdit->getEdit()->SetReadOnly( ( _nStyle & WB_READONLY ) != 0 );
1066     }
1067 
1068 	//------------------------------------------------------------------
setControlHelper(ControlHelper & _rControlHelper)1069     void DropDownEditControl::setControlHelper( ControlHelper& _rControlHelper )
1070     {
1071         DropDownEditControl_Base::setControlHelper( _rControlHelper );
1072 		m_pFloatingEdit->getEdit()->SetModifyHdl( LINK( &_rControlHelper, ControlHelper, ModifiedHdl ) );
1073 		m_pImplEdit->SetGetFocusHdl( LINK( &_rControlHelper, ControlHelper, GetFocusHdl ) );
1074 		m_pImplEdit->SetModifyHdl( LINK( &_rControlHelper, ControlHelper, ModifiedHdl ) );
1075 		m_pImplEdit->SetLoseFocusHdl( LINK( &_rControlHelper, ControlHelper, LoseFocusHdl ) );
1076     }
1077 
1078 	//------------------------------------------------------------------
~DropDownEditControl()1079 	DropDownEditControl::~DropDownEditControl()
1080 	{
1081 		{
1082 			::std::auto_ptr<Window> aTemp(m_pFloatingEdit);
1083 			m_pFloatingEdit = NULL;
1084 		}
1085 		{
1086 			::std::auto_ptr<Window> aTemp(m_pImplEdit);
1087             SetSubEdit( NULL );
1088 			m_pImplEdit = NULL;
1089 		}
1090 		{
1091 			::std::auto_ptr<Window> aTemp(m_pDropdownButton);
1092 			m_pDropdownButton = NULL;
1093 		}
1094 	}
1095 
1096 	//------------------------------------------------------------------
Resize()1097 	void DropDownEditControl::Resize()
1098 	{
1099         ::Size aOutSz = GetOutputSizePixel();
1100 
1101 		if (m_pDropdownButton!=NULL)
1102 		{
1103 			long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
1104 			nSBWidth = CalcZoom( nSBWidth );
1105 			m_pImplEdit->SetPosSizePixel( 0, 1, aOutSz.Width() - nSBWidth, aOutSz.Height()-2 );
1106 			m_pDropdownButton->SetPosSizePixel( aOutSz.Width() - nSBWidth, 0, nSBWidth, aOutSz.Height() );
1107 		}
1108 		else
1109 			m_pImplEdit->SetPosSizePixel( 0, 1, aOutSz.Width(), aOutSz.Height()-2 );
1110 	}
1111 
1112 	//------------------------------------------------------------------
PreNotify(NotifyEvent & rNEvt)1113 	long DropDownEditControl::PreNotify( NotifyEvent& rNEvt )
1114 	{
1115 		long nResult = 1;
1116 
1117 		if (rNEvt.GetType() == EVENT_KEYINPUT)
1118 		{
1119 			const KeyCode& aKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
1120 			sal_uInt16 nKey = aKeyCode.GetCode();
1121 
1122 			if ( nKey == KEY_RETURN && !aKeyCode.IsShift() )
1123 			{
1124                 if ( m_pHelper )
1125                 {
1126 				    m_pHelper->LoseFocusHdl( m_pImplEdit );
1127                     m_pHelper->activateNextControl();
1128                 }
1129 			}
1130 			else if ( nKey == KEY_DOWN && aKeyCode.IsMod2() )
1131 			{
1132 				Invalidate();
1133 				ShowDropDown( sal_True );
1134 			}
1135 			else if (   KEYGROUP_CURSOR == aKeyCode.GetGroup()
1136                     ||  nKey == KEY_HELP
1137                     ||  KEYGROUP_FKEYS == aKeyCode.GetGroup()
1138                     ||  m_nOperationMode == eMultiLineText
1139                     )
1140 			{
1141                 nResult = DropDownEditControl_Base::PreNotify( rNEvt );
1142 			}
1143 			else if ( m_nOperationMode == eStringList )
1144 			{
1145 				Selection aSel = m_pImplEdit->GetSelection();
1146 				if ( aSel.Min() != aSel.Max() )
1147 				{
1148 					aSel.Min() = FindPos( aSel.Min() );
1149 					aSel.Max() = FindPos( aSel.Max() );
1150 				}
1151 				else
1152 				{
1153 					aSel.Min() = FindPos( aSel.Min() );
1154 					aSel.Max() = aSel.Min();
1155 				}
1156 				Invalidate();
1157 				ShowDropDown( sal_True );
1158 				m_pFloatingEdit->getEdit()->GrabFocus();
1159 				m_pFloatingEdit->getEdit()->SetSelection( aSel );
1160 				Window*	pFocusWin = Application::GetFocusWindow();
1161 				pFocusWin->KeyInput( *rNEvt.GetKeyEvent() );
1162 			}
1163 		}
1164 		else
1165 			nResult = DropDownEditControl_Base::PreNotify(rNEvt);
1166 
1167 		return nResult;
1168 	}
1169 
1170 	//------------------------------------------------------------------
1171     namespace
1172     {
1173 	    //..............................................................
lcl_convertMultiLineToList(const String & _rCompsedTextWithLineBreaks)1174         StlSyntaxSequence< ::rtl::OUString > lcl_convertMultiLineToList( const String& _rCompsedTextWithLineBreaks )
1175         {
1176             xub_StrLen nLines( _rCompsedTextWithLineBreaks.GetTokenCount( '\n' ) );
1177             StlSyntaxSequence< ::rtl::OUString > aStrings( nLines );
1178             StlSyntaxSequence< ::rtl::OUString >::iterator stringItem = aStrings.begin();
1179             for ( xub_StrLen token = 0; token < nLines; ++token, ++stringItem )
1180                 *stringItem = _rCompsedTextWithLineBreaks.GetToken( token, '\n' );
1181             return aStrings;
1182         }
1183 
lcl_convertListToMultiLine(const StlSyntaxSequence<::rtl::OUString> & _rStrings)1184         String lcl_convertListToMultiLine( const StlSyntaxSequence< ::rtl::OUString >& _rStrings )
1185         {
1186             String sMultiLineText;
1187             for (   StlSyntaxSequence< ::rtl::OUString >::const_iterator item = _rStrings.begin();
1188                     item != _rStrings.end();
1189                 )
1190             {
1191                 sMultiLineText += String( *item );
1192                 if ( ++item != _rStrings.end() )
1193                     sMultiLineText += '\n';
1194             }
1195             return sMultiLineText;
1196         }
1197 
1198         //..............................................................
lcl_convertListToDisplayText(const StlSyntaxSequence<::rtl::OUString> & _rStrings)1199         String lcl_convertListToDisplayText( const StlSyntaxSequence< ::rtl::OUString >& _rStrings )
1200         {
1201             ::rtl::OUStringBuffer aComposed;
1202             for (   StlSyntaxSequence< ::rtl::OUString >::const_iterator strings = _rStrings.begin();
1203                     strings != _rStrings.end();
1204                     ++strings
1205                 )
1206             {
1207                 if ( strings != _rStrings.begin() )
1208                     aComposed.append( (sal_Unicode)';' );
1209                 aComposed.append( (sal_Unicode)'\"' );
1210                 aComposed.append( *strings );
1211                 aComposed.append( (sal_Unicode)'\"' );
1212             }
1213             return aComposed.makeStringAndClear();
1214         }
1215     }
1216 
1217 	//------------------------------------------------------------------
1218 	#define STD_HEIGHT	100
ShowDropDown(sal_Bool bShow)1219 	sal_Bool DropDownEditControl::ShowDropDown( sal_Bool bShow )
1220 	{
1221 		if (bShow)
1222 		{
1223             ::Point aMePos= GetPosPixel();
1224 			aMePos = GetParent()->OutputToScreenPixel( aMePos );
1225             ::Size aSize=GetSizePixel();
1226             ::Rectangle aRect(aMePos,aSize);
1227 			aSize.Height() = STD_HEIGHT;
1228 			m_pFloatingEdit->SetOutputSizePixel(aSize);
1229 			m_pFloatingEdit->StartPopupMode( aRect, FLOATWIN_POPUPMODE_DOWN );
1230 
1231 			m_pFloatingEdit->Show();
1232 			m_pFloatingEdit->getEdit()->GrabFocus();
1233 			m_pFloatingEdit->getEdit()->SetSelection(Selection(m_pFloatingEdit->getEdit()->GetText().Len()));
1234 			m_bDropdown=sal_True;
1235 			if ( m_nOperationMode == eMultiLineText )
1236 				m_pFloatingEdit->getEdit()->SetText( m_pImplEdit->GetText() );
1237 			m_pImplEdit->SetText(String());
1238 		}
1239 		else
1240 		{
1241 			m_pFloatingEdit->Hide();
1242 			m_pFloatingEdit->Invalidate();
1243 			m_pFloatingEdit->Update();
1244 
1245             // transfer the text from the floating edit to our own edit
1246 			String sDisplayText( m_pFloatingEdit->getEdit()->GetText() );
1247             if ( m_nOperationMode == eStringList )
1248                 sDisplayText = lcl_convertListToDisplayText( lcl_convertMultiLineToList( sDisplayText ) );
1249 
1250 			m_pImplEdit->SetText( sDisplayText );
1251 			GetParent()->Invalidate( INVALIDATE_CHILDREN );
1252 			m_bDropdown = sal_False;
1253 			m_pImplEdit->GrabFocus();
1254 		}
1255 		return m_bDropdown;
1256 
1257 	}
1258 
1259 	//------------------------------------------------------------------
FindPos(long nSinglePos)1260 	long DropDownEditControl::FindPos(long nSinglePos)
1261 	{
1262 		long nPos=0;
1263 		long nDiff=0;
1264 		String aOutput;
1265 		String aStr=m_pFloatingEdit->getEdit()->GetText();
1266 		String aStr1 = GetText();
1267 
1268 		if ((nSinglePos == 0) || (nSinglePos == aStr1.Len()))
1269 		{
1270 			return nSinglePos;
1271 		}
1272 
1273 		if (aStr.Len()>0)
1274 		{
1275 			sal_Int32 nCount = aStr.GetTokenCount('\n');
1276 
1277 			String aInput = aStr.GetToken(0,'\n' );
1278 
1279 			if (aInput.Len()>0)
1280 			{
1281 				aOutput+='\"';
1282 				nDiff++;
1283 				aOutput+=aInput;
1284 				aOutput+='\"';
1285 			}
1286 
1287 			if (nSinglePos <= aOutput.Len())
1288 			{
1289 				nPos=nSinglePos-nDiff;
1290 			}
1291 			else
1292 			{
1293 				for (sal_Int32 i=1; i<nCount; ++i)
1294 				{
1295 					aInput=aStr.GetToken((sal_uInt16)i, '\n');
1296 					if (aInput.Len()>0)
1297 					{
1298 						aOutput += ';';
1299 						aOutput += '\"';
1300 						nDiff += 2;
1301 						aOutput += aInput;
1302 						aOutput += '\"';
1303 
1304 						if (nSinglePos <= aOutput.Len())
1305 						{
1306 							nPos=nSinglePos-nDiff;
1307 							break;
1308 						}
1309 					}
1310 				}
1311 			}
1312 		}
1313 		return nPos;
1314 	}
1315 
1316 	//------------------------------------------------------------------
1317 	IMPL_LINK( DropDownEditControl, ReturnHdl, OMultilineFloatingEdit*, /*pMEd*/)
1318 	{
1319 
1320 		String aStr = m_pFloatingEdit->getEdit()->GetText();
1321 		String aStr2 = GetText();
1322 		ShowDropDown(sal_False);
1323 
1324 		if (aStr!=aStr2 || ( m_nOperationMode == eStringList ) )
1325 		{
1326 			if ( m_pHelper )
1327 			    m_pHelper->notifyModifiedValue();
1328 		}
1329 
1330 		return 0;
1331 	}
1332 
1333 	//------------------------------------------------------------------
1334 	IMPL_LINK( DropDownEditControl, DropDownHdl, PushButton*, /*pPb*/ )
1335 	{
1336 		ShowDropDown(!m_bDropdown);
1337 		return 0;
1338 	}
1339 
1340 	//------------------------------------------------------------------
SetStringListValue(const StlSyntaxSequence<::rtl::OUString> & _rStrings)1341     void DropDownEditControl::SetStringListValue( const StlSyntaxSequence< ::rtl::OUString >& _rStrings )
1342     {
1343 		SetText( lcl_convertListToDisplayText( _rStrings ) );
1344         m_pFloatingEdit->getEdit()->SetText( lcl_convertListToMultiLine( _rStrings ) );
1345     }
1346 
1347 	//------------------------------------------------------------------
GetStringListValue() const1348     StlSyntaxSequence< ::rtl::OUString > DropDownEditControl::GetStringListValue() const
1349     {
1350         return lcl_convertMultiLineToList( m_pFloatingEdit->getEdit()->GetText() );
1351     }
1352 
1353 	//------------------------------------------------------------------
SetTextValue(const::rtl::OUString & _rText)1354     void DropDownEditControl::SetTextValue( const ::rtl::OUString& _rText )
1355     {
1356         OSL_PRECOND( m_nOperationMode == eMultiLineText, "DropDownEditControl::SetTextValue: illegal call!" );
1357 
1358         m_pFloatingEdit->getEdit()->SetText( _rText );
1359 		SetText( _rText );
1360     }
1361 
1362 	//------------------------------------------------------------------
GetTextValue() const1363     ::rtl::OUString DropDownEditControl::GetTextValue() const
1364     {
1365         OSL_PRECOND( m_nOperationMode == eMultiLineText, "DropDownEditControl::GetTextValue: illegal call!" );
1366         return GetText();
1367     }
1368 
1369     //==================================================================
1370 	//= OMultilineEditControl
1371 	//==================================================================
1372 	//------------------------------------------------------------------
OMultilineEditControl(Window * pParent,MultiLineOperationMode _eMode,WinBits nWinStyle)1373 	OMultilineEditControl::OMultilineEditControl( Window* pParent, MultiLineOperationMode _eMode, WinBits nWinStyle )
1374         :OMultilineEditControl_Base( _eMode == eMultiLineText ? PropertyControlType::MultiLineTextField : PropertyControlType::StringListField
1375                                    , pParent
1376                                    , ( nWinStyle | WB_DIALOGCONTROL ) & ( ~WB_READONLY | ~WB_DROPDOWN )
1377                                    , false )
1378 	{
1379         getTypedControlWindow()->setOperationMode( _eMode );
1380 	}
1381 
1382 	//------------------------------------------------------------------
setValue(const Any & _rValue)1383 	void SAL_CALL OMultilineEditControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
1384 	{
1385         impl_checkDisposed_throw();
1386 
1387         switch ( getTypedControlWindow()->getOperationMode() )
1388         {
1389         case eMultiLineText:
1390         {
1391             ::rtl::OUString sText;
1392             if ( !( _rValue >>= sText ) && _rValue.hasValue() )
1393                 throw IllegalTypeException();
1394             getTypedControlWindow()->SetTextValue( sText );
1395         }
1396         break;
1397         case eStringList:
1398         {
1399             Sequence< ::rtl::OUString > aStringLines;
1400             if ( !( _rValue >>= aStringLines ) && _rValue.hasValue() )
1401                 throw IllegalTypeException();
1402             getTypedControlWindow()->SetStringListValue( aStringLines );
1403         }
1404         break;
1405         }
1406 	}
1407 
1408 	//------------------------------------------------------------------
getValue()1409 	Any SAL_CALL OMultilineEditControl::getValue() throw (RuntimeException)
1410 	{
1411         impl_checkDisposed_throw();
1412 
1413         Any aValue;
1414         switch ( getTypedControlWindow()->getOperationMode() )
1415         {
1416         case eMultiLineText:
1417             aValue <<= getTypedControlWindow()->GetTextValue();
1418             break;
1419         case eStringList:
1420             aValue <<= getTypedControlWindow()->GetStringListValue();
1421             break;
1422         }
1423         return aValue;
1424 	}
1425 
1426 	//------------------------------------------------------------------
getValueType()1427     Type SAL_CALL OMultilineEditControl::getValueType() throw (RuntimeException)
1428     {
1429         if ( getTypedControlWindow()->getOperationMode() == eMultiLineText )
1430             return ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
1431         return ::getCppuType( static_cast< Sequence< ::rtl::OUString >* >( NULL ) );
1432     }
1433 
1434 //............................................................................
1435 } // namespace pcr
1436 //............................................................................
1437 
1438