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 .
22 #include <comphelper/string.hxx>
23 #include <tools/debug.hxx>
25 #include <vcl/decoview.hxx>
26 #include <vcl/lstbox.h>
27 #include <vcl/button.hxx>
28 #include <vcl/event.hxx>
29 #include <vcl/combobox.hxx>
32 #include <ilstbox.hxx>
33 #include <controldata.hxx>
35 // =======================================================================
37 static void lcl_GetSelectedEntries( ::std::set
< sal_uInt16
>& rSelectedPos
, const OUString
& rText
, sal_Unicode cTokenSep
, const ImplEntryList
* pEntryList
)
39 for (sal_Int32 n
= comphelper::string::getTokenCount(rText
, cTokenSep
); n
;)
41 OUString aToken
= rText
.getToken( --n
, cTokenSep
);
42 aToken
= comphelper::string::strip(aToken
, ' ');
43 sal_uInt16 nPos
= pEntryList
->FindEntry( aToken
);
44 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
45 rSelectedPos
.insert( nPos
);
49 // =======================================================================
51 ComboBox::ComboBox( WindowType nType
) :
54 ImplInitComboBoxData();
58 // -----------------------------------------------------------------------
60 ComboBox::ComboBox( Window
* pParent
, WinBits nStyle
) :
61 Edit( WINDOW_COMBOBOX
)
63 ImplInitComboBoxData();
64 ImplInit( pParent
, nStyle
);
68 // -----------------------------------------------------------------------
70 ComboBox::ComboBox( Window
* pParent
, const ResId
& rResId
) :
71 Edit( WINDOW_COMBOBOX
)
73 ImplInitComboBoxData();
74 rResId
.SetRT( RSC_COMBOBOX
);
75 WinBits nStyle
= ImplInitRes( rResId
);
76 ImplInit( pParent
, nStyle
);
77 ImplLoadRes( rResId
);
80 if ( !(nStyle
& WB_HIDE
) )
84 // -----------------------------------------------------------------------
91 ImplListBox
*pImplLB
= mpImplLB
;
99 // -----------------------------------------------------------------------
101 void ComboBox::ImplInitComboBoxData()
109 mbDDAutoSize
= sal_True
;
110 mbSyntheticModify
= sal_False
;
111 mbMatchCase
= sal_False
;
113 m_nMaxWidthChars
= -1;
116 // -----------------------------------------------------------------------
118 void ComboBox::ImplCalcEditHeight()
120 sal_Int32 nLeft
, nTop
, nRight
, nBottom
;
121 GetBorder( nLeft
, nTop
, nRight
, nBottom
);
122 mnDDHeight
= (sal_uInt16
)(mpSubEdit
->GetTextHeight() + nTop
+ nBottom
+ 4);
123 if ( !IsDropDownBox() )
126 Rectangle
aCtrlRegion( Point( 0, 0 ), Size( 10, 10 ) );
127 Rectangle aBoundRegion
, aContentRegion
;
128 ImplControlValue aControlValue
;
129 ControlType aType
= IsDropDownBox() ? CTRL_COMBOBOX
: CTRL_EDITBOX
;
130 if( GetNativeControlRegion( aType
, PART_ENTIRE_CONTROL
,
133 aControlValue
, OUString(),
134 aBoundRegion
, aContentRegion
) )
136 const long nNCHeight
= aBoundRegion
.GetHeight();
137 if( mnDDHeight
< nNCHeight
)
138 mnDDHeight
= sal::static_int_cast
<sal_uInt16
>( nNCHeight
);
142 // -----------------------------------------------------------------------
144 void ComboBox::ImplInit( Window
* pParent
, WinBits nStyle
)
146 ImplInitStyle( nStyle
);
148 bool bNoBorder
= ( nStyle
& WB_NOBORDER
) ? true : false;
149 if ( !(nStyle
& WB_DROPDOWN
) )
151 nStyle
&= ~WB_BORDER
;
152 nStyle
|= WB_NOBORDER
;
160 Edit::ImplInit( pParent
, nStyle
);
164 WinBits nEditStyle
= nStyle
& ( WB_LEFT
| WB_RIGHT
| WB_CENTER
);
165 WinBits nListStyle
= nStyle
;
166 if( nStyle
& WB_DROPDOWN
)
168 mpFloatWin
= new ImplListBoxFloatingWindow( this );
169 mpFloatWin
->SetAutoWidth( sal_True
);
170 mpFloatWin
->SetPopupModeEndHdl( LINK( this, ComboBox
, ImplPopupModeEndHdl
) );
172 mpBtn
= new ImplBtn( this, WB_NOLIGHTBORDER
| WB_RECTSTYLE
);
173 ImplInitDropDownButton( mpBtn
);
174 mpBtn
->SetMBDownHdl( LINK( this, ComboBox
, ImplClickBtnHdl
) );
177 nEditStyle
|= WB_NOBORDER
;
178 nListStyle
&= ~WB_BORDER
;
179 nListStyle
|= WB_NOBORDER
;
185 nEditStyle
|= WB_BORDER
;
186 nListStyle
&= ~WB_NOBORDER
;
187 nListStyle
|= WB_BORDER
;
191 mpSubEdit
= new Edit( this, nEditStyle
);
192 mpSubEdit
->EnableRTL( sal_False
);
193 SetSubEdit( mpSubEdit
);
194 mpSubEdit
->SetPosPixel( Point() );
195 EnableAutocomplete( sal_True
);
198 Window
* pLBParent
= this;
200 pLBParent
= mpFloatWin
;
201 mpImplLB
= new ImplListBox( pLBParent
, nListStyle
|WB_SIMPLEMODE
|WB_AUTOHSCROLL
);
202 mpImplLB
->SetPosPixel( Point() );
203 mpImplLB
->SetSelectHdl( LINK( this, ComboBox
, ImplSelectHdl
) );
204 mpImplLB
->SetCancelHdl( LINK( this, ComboBox
, ImplCancelHdl
) );
205 mpImplLB
->SetDoubleClickHdl( LINK( this, ComboBox
, ImplDoubleClickHdl
) );
206 mpImplLB
->SetUserDrawHdl( LINK( this, ComboBox
, ImplUserDrawHdl
) );
207 mpImplLB
->SetSelectionChangedHdl( LINK( this, ComboBox
, ImplSelectionChangedHdl
) );
211 mpFloatWin
->SetImplListBox( mpImplLB
);
213 mpImplLB
->GetMainWindow()->AllowGrabFocus( sal_True
);
215 ImplCalcEditHeight();
217 SetCompoundControl( sal_True
);
220 // -----------------------------------------------------------------------
222 WinBits
ComboBox::ImplInitStyle( WinBits nStyle
)
224 if ( !(nStyle
& WB_NOTABSTOP
) )
225 nStyle
|= WB_TABSTOP
;
226 if ( !(nStyle
& WB_NOGROUP
) )
231 // -----------------------------------------------------------------------
233 void ComboBox::ImplLoadRes( const ResId
& rResId
)
235 Edit::ImplLoadRes( rResId
);
237 sal_uLong nNumber
= ReadLongRes();
241 for( sal_uInt16 i
= 0; i
< nNumber
; i
++ )
243 InsertEntry( ReadStringRes(), LISTBOX_APPEND
);
248 // -----------------------------------------------------------------------
250 void ComboBox::EnableAutocomplete( sal_Bool bEnable
, sal_Bool bMatchCase
)
252 mbMatchCase
= bMatchCase
;
255 mpSubEdit
->SetAutocompleteHdl( LINK( this, ComboBox
, ImplAutocompleteHdl
) );
257 mpSubEdit
->SetAutocompleteHdl( Link() );
260 // -----------------------------------------------------------------------
262 sal_Bool
ComboBox::IsAutocompleteEnabled() const
264 return mpSubEdit
->GetAutocompleteHdl().IsSet();
267 // -----------------------------------------------------------------------
269 IMPL_LINK_NOARG(ComboBox
, ImplClickBtnHdl
)
271 ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN
);
272 mpSubEdit
->GrabFocus();
273 if ( !mpImplLB
->GetEntryList()->GetMRUCount() )
274 ImplUpdateFloatSelection();
276 mpImplLB
->SelectEntry( 0 , sal_True
);
277 mpBtn
->SetPressed( sal_True
);
278 SetSelection( Selection( 0, SELECTION_MAX
) );
279 mpFloatWin
->StartFloat( sal_True
);
280 ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN
);
282 ImplClearLayoutData();
284 mpImplLB
->GetMainWindow()->ImplClearLayoutData();
289 // -----------------------------------------------------------------------
291 IMPL_LINK_NOARG(ComboBox
, ImplPopupModeEndHdl
)
293 if( mpFloatWin
->IsPopupModeCanceled() )
295 if ( !mpImplLB
->GetEntryList()->IsEntryPosSelected( mpFloatWin
->GetPopupModeStartSaveSelection() ) )
297 mpImplLB
->SelectEntry( mpFloatWin
->GetPopupModeStartSaveSelection(), sal_True
);
298 sal_Bool bTravelSelect
= mpImplLB
->IsTravelSelect();
299 mpImplLB
->SetTravelSelect( sal_True
);
301 mpImplLB
->SetTravelSelect( bTravelSelect
);
305 ImplClearLayoutData();
307 mpImplLB
->GetMainWindow()->ImplClearLayoutData();
309 mpBtn
->SetPressed( sal_False
);
310 ImplCallEventListeners( VCLEVENT_DROPDOWN_CLOSE
);
314 // -----------------------------------------------------------------------
316 IMPL_LINK( ComboBox
, ImplAutocompleteHdl
, Edit
*, pEdit
)
318 Selection aSel
= pEdit
->GetSelection();
319 AutocompleteAction eAction
= pEdit
->GetAutocompleteAction();
321 /* If there is no current selection do not auto complete on
322 Tab/Shift-Tab since then we would not cycle to the next field.
325 ((eAction
!= AUTOCOMPLETE_TABFORWARD
) && (eAction
!= AUTOCOMPLETE_TABBACKWARD
)) )
327 OUString aFullText
= pEdit
->GetText();
328 OUString aStartText
= aFullText
.copy( 0, (sal_Int32
)aSel
.Max() );
329 sal_uInt16 nStart
= mpImplLB
->GetCurrentPos();
331 if ( nStart
== LISTBOX_ENTRY_NOTFOUND
)
334 sal_Bool bForward
= sal_True
;
335 if ( eAction
== AUTOCOMPLETE_TABFORWARD
)
337 else if ( eAction
== AUTOCOMPLETE_TABBACKWARD
)
339 bForward
= sal_False
;
340 nStart
= nStart
? nStart
- 1 : mpImplLB
->GetEntryList()->GetEntryCount()-1;
343 sal_uInt16 nPos
= LISTBOX_ENTRY_NOTFOUND
;
346 // Try match case insensitive from current position
347 nPos
= mpImplLB
->GetEntryList()->FindMatchingEntry( aStartText
, nStart
, bForward
, sal_True
);
348 if ( nPos
== LISTBOX_ENTRY_NOTFOUND
)
349 // Try match case insensitive, but from start
350 nPos
= mpImplLB
->GetEntryList()->FindMatchingEntry( aStartText
, bForward
? 0 : (mpImplLB
->GetEntryList()->GetEntryCount()-1), bForward
, sal_True
);
353 if ( nPos
== LISTBOX_ENTRY_NOTFOUND
)
354 // Try match full from current position
355 nPos
= mpImplLB
->GetEntryList()->FindMatchingEntry( aStartText
, nStart
, bForward
, sal_False
);
356 if ( nPos
== LISTBOX_ENTRY_NOTFOUND
)
357 // Match full, but from start
358 nPos
= mpImplLB
->GetEntryList()->FindMatchingEntry( aStartText
, bForward
? 0 : (mpImplLB
->GetEntryList()->GetEntryCount()-1), bForward
, sal_False
);
360 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
362 OUString aText
= mpImplLB
->GetEntryList()->GetEntryText( nPos
);
363 Selection
aSelection( aText
.getLength(), aStartText
.getLength() );
364 pEdit
->SetText( aText
, aSelection
);
371 // -----------------------------------------------------------------------
373 IMPL_LINK_NOARG(ComboBox
, ImplSelectHdl
)
375 sal_Bool bPopup
= IsInDropDown();
376 bool bCallSelect
= false;
377 if ( mpImplLB
->IsSelectionChanged() || bPopup
)
380 if ( IsMultiSelectionEnabled() )
382 aText
= mpSubEdit
->GetText();
384 // remove all entries to which there is an entry, but which is not selected
385 sal_Int32 nIndex
= 0;
386 while ( nIndex
>= 0 )
388 sal_Int32 nPrevIndex
= nIndex
;
389 OUString aToken
= aText
.getToken( 0, mcMultiSep
, nIndex
);
390 sal_Int32 nTokenLen
= aToken
.getLength();
391 aToken
= comphelper::string::strip(aToken
, ' ');
392 sal_uInt16 nP
= mpImplLB
->GetEntryList()->FindEntry( aToken
);
393 if ( (nP
!= LISTBOX_ENTRY_NOTFOUND
) && (!mpImplLB
->GetEntryList()->IsEntryPosSelected( nP
)) )
395 aText
= aText
.replaceAt( nPrevIndex
, nTokenLen
, "" );
396 nIndex
= sal::static_int_cast
<xub_StrLen
>(nIndex
- nTokenLen
);
397 sal_Int32 nSepCount
=0;
398 if ( (nPrevIndex
+nSepCount
< aText
.getLength()) && (aText
[nPrevIndex
+nSepCount
] == mcMultiSep
) )
403 aText
= aText
.replaceAt( nPrevIndex
, nSepCount
, "" );
405 aText
= comphelper::string::strip(aText
, ' ');
408 // attach missing entries
409 ::std::set
< sal_uInt16
> aSelInText
;
410 lcl_GetSelectedEntries( aSelInText
, aText
, mcMultiSep
, mpImplLB
->GetEntryList() );
411 sal_uInt16 nSelectedEntries
= mpImplLB
->GetEntryList()->GetSelectEntryCount();
412 for ( sal_uInt16 n
= 0; n
< nSelectedEntries
; n
++ )
414 sal_uInt16 nP
= mpImplLB
->GetEntryList()->GetSelectEntryPos( n
);
415 if ( !aSelInText
.count( nP
) )
417 if ( !aText
.isEmpty() && (aText
[ aText
.getLength()-1 ] != mcMultiSep
) )
418 aText
+= OUString(mcMultiSep
);
419 if ( !aText
.isEmpty() )
420 aText
+= " "; // slightly loosen
421 aText
+= mpImplLB
->GetEntryList()->GetEntryText( nP
);
422 aText
+= OUString(mcMultiSep
);
425 aText
= comphelper::string::stripEnd( aText
, mcMultiSep
);
429 aText
= mpImplLB
->GetEntryList()->GetSelectEntry( 0 );
432 mpSubEdit
->SetText( aText
);
434 Selection
aNewSelection( 0, aText
.getLength() );
435 if ( IsMultiSelectionEnabled() )
436 aNewSelection
.Min() = aText
.getLength();
437 mpSubEdit
->SetSelection( aNewSelection
);
442 // #84652# Call GrabFocus and EndPopupMode before calling Select/Modify, but after changing the text
444 if ( bPopup
&& !mpImplLB
->IsTravelSelect() &&
445 ( !IsMultiSelectionEnabled() || !mpImplLB
->GetSelectModifier() ) )
447 mpFloatWin
->EndPopupMode();
453 mpSubEdit
->SetModifyFlag();
454 mbSyntheticModify
= sal_True
;
456 mbSyntheticModify
= sal_False
;
463 // -----------------------------------------------------------------------
465 IMPL_LINK_NOARG(ComboBox
, ImplCancelHdl
)
468 mpFloatWin
->EndPopupMode();
473 // -----------------------------------------------------------------------
475 IMPL_LINK( ComboBox
, ImplSelectionChangedHdl
, void*, n
)
477 if ( !mpImplLB
->IsTrackingSelect() )
479 sal_uInt16 nChanged
= (sal_uInt16
)(sal_uLong
)n
;
480 if ( !mpSubEdit
->IsReadOnly() && mpImplLB
->GetEntryList()->IsEntryPosSelected( nChanged
) )
481 mpSubEdit
->SetText( mpImplLB
->GetEntryList()->GetEntryText( nChanged
) );
486 // -----------------------------------------------------------------------
488 IMPL_LINK_NOARG(ComboBox
, ImplDoubleClickHdl
)
494 // -----------------------------------------------------------------------
496 void ComboBox::ToggleDropDown()
498 if( IsDropDownBox() )
500 if( mpFloatWin
->IsInPopupMode() )
501 mpFloatWin
->EndPopupMode();
504 mpSubEdit
->GrabFocus();
505 if ( !mpImplLB
->GetEntryList()->GetMRUCount() )
506 ImplUpdateFloatSelection();
508 mpImplLB
->SelectEntry( 0 , sal_True
);
509 ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN
);
510 mpBtn
->SetPressed( sal_True
);
511 SetSelection( Selection( 0, SELECTION_MAX
) );
512 mpFloatWin
->StartFloat( sal_True
);
513 ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN
);
518 // -----------------------------------------------------------------------
520 void ComboBox::Select()
522 ImplCallEventListenersAndHandler( VCLEVENT_COMBOBOX_SELECT
, maSelectHdl
, this );
525 // -----------------------------------------------------------------------
527 void ComboBox::DoubleClick()
529 ImplCallEventListenersAndHandler( VCLEVENT_COMBOBOX_DOUBLECLICK
, maDoubleClickHdl
, this );
532 // -----------------------------------------------------------------------
534 void ComboBox::EnableAutoSize( bool bAuto
)
536 mbDDAutoSize
= bAuto
;
539 if ( bAuto
&& !mpFloatWin
->GetDropDownLineCount() )
541 // Adapt to GetListBoxMaximumLineCount here; was on fixed number of five before
542 AdaptDropDownLineCountToMaximum();
546 mpFloatWin
->SetDropDownLineCount( 0 );
551 // -----------------------------------------------------------------------
553 void ComboBox::EnableDDAutoWidth( sal_Bool b
)
556 mpFloatWin
->SetAutoWidth( b
);
559 // -----------------------------------------------------------------------
561 void ComboBox::SetDropDownLineCount( sal_uInt16 nLines
)
564 mpFloatWin
->SetDropDownLineCount( nLines
);
567 // -----------------------------------------------------------------------
569 void ComboBox::AdaptDropDownLineCountToMaximum()
571 // adapt to maximum allowed number
572 SetDropDownLineCount(GetSettings().GetStyleSettings().GetListBoxMaximumLineCount());
575 // -----------------------------------------------------------------------
577 sal_uInt16
ComboBox::GetDropDownLineCount() const
579 sal_uInt16 nLines
= 0;
581 nLines
= mpFloatWin
->GetDropDownLineCount();
585 // -----------------------------------------------------------------------
587 void ComboBox::setPosSizePixel( long nX
, long nY
, long nWidth
, long nHeight
,
590 if( IsDropDownBox() && ( nFlags
& WINDOW_POSSIZE_SIZE
) )
592 Size aPrefSz
= mpFloatWin
->GetPrefSize();
593 if ( ( nFlags
& WINDOW_POSSIZE_HEIGHT
) && ( nHeight
>= 2*mnDDHeight
) )
594 aPrefSz
.Height() = nHeight
-mnDDHeight
;
595 if ( nFlags
& WINDOW_POSSIZE_WIDTH
)
596 aPrefSz
.Width() = nWidth
;
597 mpFloatWin
->SetPrefSize( aPrefSz
);
599 if ( IsAutoSizeEnabled() && ! (nFlags
& WINDOW_POSSIZE_DROPDOWN
) )
600 nHeight
= mnDDHeight
;
603 Edit::setPosSizePixel( nX
, nY
, nWidth
, nHeight
, nFlags
);
606 // -----------------------------------------------------------------------
608 void ComboBox::Resize()
612 Size aOutSz
= GetOutputSizePixel();
613 if( IsDropDownBox() )
615 ComboBoxBounds
aBounds(calcComboBoxDropDownComponentBounds(aOutSz
,
616 GetWindow(WINDOW_BORDER
)->GetOutputSizePixel()));
617 mpSubEdit
->SetPosSizePixel(aBounds
.aSubEditPos
, aBounds
.aSubEditSize
);
618 mpBtn
->SetPosSizePixel(aBounds
.aButtonPos
, aBounds
.aButtonSize
);
622 mpSubEdit
->SetSizePixel( Size( aOutSz
.Width(), mnDDHeight
) );
623 mpImplLB
->setPosSizePixel( 0, mnDDHeight
, aOutSz
.Width(), aOutSz
.Height() - mnDDHeight
);
624 if ( !GetText().isEmpty() )
625 ImplUpdateFloatSelection();
628 // adjust the size of the FloatingWindow even when invisible
629 // as KEY_PGUP/DOWN is being processed...
631 mpFloatWin
->SetSizePixel( mpFloatWin
->CalcFloatSize() );
634 // -----------------------------------------------------------------------
636 void ComboBox::FillLayoutData() const
638 mpControlData
->mpLayoutData
= new vcl::ControlLayoutData();
639 AppendLayoutData( *mpSubEdit
);
640 mpSubEdit
->SetLayoutDataParent( this );
641 Control
* pMainWindow
= mpImplLB
->GetMainWindow();
645 if( mpFloatWin
->IsReallyVisible() )
647 AppendLayoutData( *pMainWindow
);
648 pMainWindow
->SetLayoutDataParent( this );
653 AppendLayoutData( *pMainWindow
);
654 pMainWindow
->SetLayoutDataParent( this );
658 // -----------------------------------------------------------------------
660 void ComboBox::StateChanged( StateChangedType nType
)
662 Edit::StateChanged( nType
);
664 if ( nType
== STATE_CHANGE_READONLY
)
666 mpImplLB
->SetReadOnly( IsReadOnly() );
668 mpBtn
->Enable( IsEnabled() && !IsReadOnly() );
670 else if ( nType
== STATE_CHANGE_ENABLE
)
672 mpSubEdit
->Enable( IsEnabled() );
673 mpImplLB
->Enable( IsEnabled() && !IsReadOnly() );
675 mpBtn
->Enable( IsEnabled() && !IsReadOnly() );
678 else if( nType
== STATE_CHANGE_UPDATEMODE
)
680 mpImplLB
->SetUpdateMode( IsUpdateMode() );
682 else if ( nType
== STATE_CHANGE_ZOOM
)
684 mpImplLB
->SetZoom( GetZoom() );
685 mpSubEdit
->SetZoom( GetZoom() );
686 ImplCalcEditHeight();
689 else if ( nType
== STATE_CHANGE_CONTROLFONT
)
691 mpImplLB
->SetControlFont( GetControlFont() );
692 mpSubEdit
->SetControlFont( GetControlFont() );
693 ImplCalcEditHeight();
696 else if ( nType
== STATE_CHANGE_CONTROLFOREGROUND
)
698 mpImplLB
->SetControlForeground( GetControlForeground() );
699 mpSubEdit
->SetControlForeground( GetControlForeground() );
701 else if ( nType
== STATE_CHANGE_CONTROLBACKGROUND
)
703 mpImplLB
->SetControlBackground( GetControlBackground() );
704 mpSubEdit
->SetControlBackground( GetControlBackground() );
706 else if ( nType
== STATE_CHANGE_STYLE
)
708 SetStyle( ImplInitStyle( GetStyle() ) );
709 mpImplLB
->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT
) ? sal_True
: sal_False
);
711 else if( nType
== STATE_CHANGE_MIRRORING
)
715 mpBtn
->EnableRTL( IsRTLEnabled() );
716 ImplInitDropDownButton( mpBtn
);
718 mpSubEdit
->StateChanged( STATE_CHANGE_MIRRORING
);
719 mpImplLB
->EnableRTL( IsRTLEnabled() );
724 // -----------------------------------------------------------------------
726 void ComboBox::DataChanged( const DataChangedEvent
& rDCEvt
)
728 Control::DataChanged( rDCEvt
);
730 if ( (rDCEvt
.GetType() == DATACHANGED_FONTS
) ||
731 (rDCEvt
.GetType() == DATACHANGED_FONTSUBSTITUTION
) ||
732 ((rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
733 (rDCEvt
.GetFlags() & SETTINGS_STYLE
)) )
737 mpBtn
->SetSettings( GetSettings() );
738 ImplInitDropDownButton( mpBtn
);
741 mpImplLB
->Resize(); // not called by ComboBox::Resize() if ImplLB is unchanged
743 SetBackground(); // due to a hack in Window::UpdateSettings the background must be reset
744 // otherwise it will overpaint NWF drawn comboboxes
748 // -----------------------------------------------------------------------
750 long ComboBox::PreNotify( NotifyEvent
& rNEvt
)
753 return Edit::PreNotify( rNEvt
);
756 // -----------------------------------------------------------------------
758 long ComboBox::Notify( NotifyEvent
& rNEvt
)
761 if( ( rNEvt
.GetType() == EVENT_KEYINPUT
) && ( rNEvt
.GetWindow() == mpSubEdit
)
764 KeyEvent aKeyEvt
= *rNEvt
.GetKeyEvent();
765 sal_uInt16 nKeyCode
= aKeyEvt
.GetKeyCode().GetCode();
773 ImplUpdateFloatSelection();
774 if( ( nKeyCode
== KEY_DOWN
) && mpFloatWin
&& !mpFloatWin
->IsInPopupMode() && aKeyEvt
.GetKeyCode().IsMod2() )
776 ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN
);
777 mpBtn
->SetPressed( sal_True
);
778 if ( mpImplLB
->GetEntryList()->GetMRUCount() )
779 mpImplLB
->SelectEntry( 0 , sal_True
);
780 SetSelection( Selection( 0, SELECTION_MAX
) );
781 mpFloatWin
->StartFloat( sal_False
);
782 ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN
);
785 else if( ( nKeyCode
== KEY_UP
) && mpFloatWin
&& mpFloatWin
->IsInPopupMode() && aKeyEvt
.GetKeyCode().IsMod2() )
787 mpFloatWin
->EndPopupMode();
792 nDone
= mpImplLB
->ProcessKeyInput( aKeyEvt
);
799 if( ( rNEvt
.GetWindow() == mpSubEdit
) && IsInDropDown() )
801 mpImplLB
->ProcessKeyInput( aKeyEvt
);
808 else if ( (rNEvt
.GetType() == EVENT_LOSEFOCUS
) && mpFloatWin
)
810 if( mpFloatWin
->HasChildPathFocus() )
811 mpSubEdit
->GrabFocus();
812 else if ( mpFloatWin
->IsInPopupMode() && !HasChildPathFocus( sal_True
) )
813 mpFloatWin
->EndPopupMode();
815 else if( (rNEvt
.GetType() == EVENT_COMMAND
) &&
816 (rNEvt
.GetCommandEvent()->GetCommand() == COMMAND_WHEEL
) &&
817 (rNEvt
.GetWindow() == mpSubEdit
) )
819 sal_uInt16
nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
820 if ( ( nWheelBehavior
== MOUSE_WHEEL_ALWAYS
)
821 || ( ( nWheelBehavior
== MOUSE_WHEEL_FOCUS_ONLY
)
822 && HasChildPathFocus()
826 nDone
= mpImplLB
->HandleWheelAsCursorTravel( *rNEvt
.GetCommandEvent() );
830 nDone
= 0; // don't eat this event, let the default handling happen (i.e. scroll the context)
833 else if( ( rNEvt
.GetType() == EVENT_MOUSEBUTTONDOWN
) && ( rNEvt
.GetWindow() == mpImplLB
->GetMainWindow() ) )
835 mpSubEdit
->GrabFocus();
838 return nDone
? nDone
: Edit::Notify( rNEvt
);
841 // -----------------------------------------------------------------------
843 void ComboBox::SetText( const OUString
& rStr
)
845 ImplCallEventListeners( VCLEVENT_COMBOBOX_SETTEXT
);
847 Edit::SetText( rStr
);
848 ImplUpdateFloatSelection();
851 // -----------------------------------------------------------------------
853 void ComboBox::SetText( const OUString
& rStr
, const Selection
& rNewSelection
)
855 ImplCallEventListeners( VCLEVENT_COMBOBOX_SETTEXT
);
857 Edit::SetText( rStr
, rNewSelection
);
858 ImplUpdateFloatSelection();
861 // -----------------------------------------------------------------------
863 void ComboBox::Modify()
865 if ( !mbSyntheticModify
)
866 ImplUpdateFloatSelection();
871 // -----------------------------------------------------------------------
873 void ComboBox::ImplUpdateFloatSelection()
875 // move text in the ListBox into the visible region
876 mpImplLB
->SetCallSelectionChangedHdl( sal_False
);
877 if ( !IsMultiSelectionEnabled() )
879 XubString
aSearchStr( mpSubEdit
->GetText() );
880 sal_uInt16 nSelect
= LISTBOX_ENTRY_NOTFOUND
;
881 sal_Bool bSelect
= sal_True
;
883 if ( mpImplLB
->GetCurrentPos() != LISTBOX_ENTRY_NOTFOUND
)
885 XubString aCurrent
= mpImplLB
->GetEntryList()->GetEntryText( mpImplLB
->GetCurrentPos() );
886 if ( aCurrent
== aSearchStr
)
887 nSelect
= mpImplLB
->GetCurrentPos();
890 if ( nSelect
== LISTBOX_ENTRY_NOTFOUND
)
891 nSelect
= mpImplLB
->GetEntryList()->FindEntry( aSearchStr
);
892 if ( nSelect
== LISTBOX_ENTRY_NOTFOUND
)
894 nSelect
= mpImplLB
->GetEntryList()->FindMatchingEntry( aSearchStr
);
898 if( nSelect
!= LISTBOX_ENTRY_NOTFOUND
)
900 if ( !mpImplLB
->IsVisible( nSelect
) )
901 mpImplLB
->ShowProminentEntry( nSelect
);
902 mpImplLB
->SelectEntry( nSelect
, bSelect
);
906 nSelect
= mpImplLB
->GetEntryList()->GetSelectEntryPos( 0 );
907 if( nSelect
!= LISTBOX_ENTRY_NOTFOUND
)
908 mpImplLB
->SelectEntry( nSelect
, sal_False
);
909 mpImplLB
->ResetCurrentPos();
914 ::std::set
< sal_uInt16
> aSelInText
;
915 lcl_GetSelectedEntries( aSelInText
, mpSubEdit
->GetText(), mcMultiSep
, mpImplLB
->GetEntryList() );
916 for ( sal_uInt16 n
= 0; n
< mpImplLB
->GetEntryList()->GetEntryCount(); n
++ )
917 mpImplLB
->SelectEntry( n
, aSelInText
.count( n
) );
919 mpImplLB
->SetCallSelectionChangedHdl( sal_True
);
922 // -----------------------------------------------------------------------
924 sal_uInt16
ComboBox::InsertEntry( const OUString
& rStr
, sal_uInt16 nPos
)
926 sal_uInt16 nRealPos
= mpImplLB
->InsertEntry( nPos
+ mpImplLB
->GetEntryList()->GetMRUCount(), rStr
);
927 nRealPos
= sal::static_int_cast
<sal_uInt16
>(nRealPos
- mpImplLB
->GetEntryList()->GetMRUCount());
928 CallEventListeners( VCLEVENT_COMBOBOX_ITEMADDED
, (void*) sal_IntPtr(nRealPos
) );
932 // -----------------------------------------------------------------------
934 sal_uInt16
ComboBox::InsertEntry( const OUString
& rStr
, const Image
& rImage
, sal_uInt16 nPos
)
936 sal_uInt16 nRealPos
= mpImplLB
->InsertEntry( nPos
+ mpImplLB
->GetEntryList()->GetMRUCount(), rStr
, rImage
);
937 nRealPos
= sal::static_int_cast
<sal_uInt16
>(nRealPos
- mpImplLB
->GetEntryList()->GetMRUCount());
938 CallEventListeners( VCLEVENT_COMBOBOX_ITEMADDED
, (void*) sal_IntPtr(nRealPos
) );
942 // -----------------------------------------------------------------------
944 void ComboBox::RemoveEntry( const OUString
& rStr
)
946 RemoveEntry( GetEntryPos( rStr
) );
949 // -----------------------------------------------------------------------
951 void ComboBox::RemoveEntry( sal_uInt16 nPos
)
953 mpImplLB
->RemoveEntry( nPos
+ mpImplLB
->GetEntryList()->GetMRUCount() );
954 CallEventListeners( VCLEVENT_COMBOBOX_ITEMREMOVED
, (void*) sal_IntPtr(nPos
) );
957 // -----------------------------------------------------------------------
959 void ComboBox::Clear()
962 CallEventListeners( VCLEVENT_COMBOBOX_ITEMREMOVED
, (void*) sal_IntPtr(-1) );
964 // -----------------------------------------------------------------------
966 Image
ComboBox::GetEntryImage( sal_uInt16 nPos
) const
968 if ( mpImplLB
->GetEntryList()->HasEntryImage( nPos
) )
969 return mpImplLB
->GetEntryList()->GetEntryImage( nPos
);
973 // -----------------------------------------------------------------------
975 sal_uInt16
ComboBox::GetEntryPos( const OUString
& rStr
) const
977 sal_uInt16 nPos
= mpImplLB
->GetEntryList()->FindEntry( rStr
);
978 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
979 nPos
= sal::static_int_cast
<sal_uInt16
>(nPos
- mpImplLB
->GetEntryList()->GetMRUCount());
983 // -----------------------------------------------------------------------
985 OUString
ComboBox::GetEntry( sal_uInt16 nPos
) const
987 return mpImplLB
->GetEntryList()->GetEntryText( nPos
+ mpImplLB
->GetEntryList()->GetMRUCount() );
990 // -----------------------------------------------------------------------
992 sal_uInt16
ComboBox::GetEntryCount() const
994 return mpImplLB
->GetEntryList()->GetEntryCount() - mpImplLB
->GetEntryList()->GetMRUCount();
997 // -----------------------------------------------------------------------
999 sal_Bool
ComboBox::IsTravelSelect() const
1001 return mpImplLB
->IsTravelSelect();
1004 // -----------------------------------------------------------------------
1006 sal_Bool
ComboBox::IsInDropDown() const
1008 return mpFloatWin
&& mpFloatWin
->IsInPopupMode();
1011 // -----------------------------------------------------------------------
1013 void ComboBox::EnableMultiSelection( sal_Bool bMulti
)
1015 mpImplLB
->EnableMultiSelection( bMulti
, sal_False
);
1016 mpImplLB
->SetMultiSelectionSimpleMode( sal_True
);
1019 // -----------------------------------------------------------------------
1021 sal_Bool
ComboBox::IsMultiSelectionEnabled() const
1023 return mpImplLB
->IsMultiSelectionEnabled();
1026 // -----------------------------------------------------------------------
1028 long ComboBox::CalcWindowSizePixel( sal_uInt16 nLines
) const
1030 return mpImplLB
->GetEntryHeight() * nLines
;
1033 // -----------------------------------------------------------------------
1035 Size
ComboBox::GetOptimalSize() const
1037 return CalcMinimumSize();
1040 // -----------------------------------------------------------------------
1042 long ComboBox::getMaxWidthScrollBarAndDownButton() const
1044 long nButtonDownWidth
= 0;
1046 Window
*pBorder
= GetWindow( WINDOW_BORDER
);
1047 ImplControlValue aControlValue
;
1049 Rectangle aContent
, aBound
;
1051 // use the full extent of the control
1052 Rectangle
aArea( aPoint
, pBorder
->GetOutputSizePixel() );
1054 if ( GetNativeControlRegion(CTRL_COMBOBOX
, PART_BUTTON_DOWN
,
1055 aArea
, 0, aControlValue
, OUString(), aBound
, aContent
) )
1057 nButtonDownWidth
= aContent
.getWidth();
1060 long nScrollBarWidth
= GetSettings().GetStyleSettings().GetScrollBarSize();
1062 return std::max(nScrollBarWidth
, nButtonDownWidth
);
1065 Size
ComboBox::CalcMinimumSize() const
1072 if ( !IsDropDownBox() )
1074 aSz
= mpImplLB
->CalcSize( mpImplLB
->GetEntryList()->GetEntryCount() );
1075 aSz
.Height() += mnDDHeight
;
1079 aSz
.Height() = Edit::CalcMinimumSizeForText(GetText()).Height();
1081 aSz
.Width() = mpImplLB
->GetMaxEntryWidth();
1082 if (m_nMaxWidthChars
!= -1)
1084 long nMaxWidth
= m_nMaxWidthChars
* approximate_char_width();
1085 aSz
.Width() = std::min(aSz
.Width(), nMaxWidth
);
1087 aSz
.Width() += getMaxWidthScrollBarAndDownButton();
1088 ComboBoxBounds
aBounds(calcComboBoxDropDownComponentBounds(
1089 Size(0xFFFF, 0xFFFF), Size(0xFFFF, 0xFFFF)));
1090 aSz
.Width() += aBounds
.aSubEditPos
.X()*2;
1093 aSz
.Width() += ImplGetExtraOffset() * 2;
1095 aSz
= CalcWindowSize( aSz
);
1099 // -----------------------------------------------------------------------
1101 Size
ComboBox::CalcAdjustedSize( const Size
& rPrefSize
) const
1103 Size aSz
= rPrefSize
;
1104 sal_Int32 nLeft
, nTop
, nRight
, nBottom
;
1105 ((Window
*)this)->GetBorder( nLeft
, nTop
, nRight
, nBottom
);
1106 aSz
.Height() -= nTop
+nBottom
;
1107 if ( !IsDropDownBox() )
1109 long nEntryHeight
= CalcSize( 1, 1 ).Height();
1110 long nLines
= aSz
.Height() / nEntryHeight
;
1113 aSz
.Height() = nLines
* nEntryHeight
;
1114 aSz
.Height() += mnDDHeight
;
1118 aSz
.Height() = mnDDHeight
;
1120 aSz
.Height() += nTop
+nBottom
;
1122 aSz
= CalcWindowSize( aSz
);
1126 // -----------------------------------------------------------------------
1128 Size
ComboBox::CalcSize( sal_uInt16 nColumns
, sal_uInt16 nLines
) const
1130 // show ScrollBars where appropriate
1131 Size aMinSz
= CalcMinimumSize();
1137 if ( !IsDropDownBox() )
1138 aSz
.Height() = mpImplLB
->CalcSize( nLines
).Height() + mnDDHeight
;
1140 aSz
.Height() = mnDDHeight
;
1143 aSz
.Height() = aMinSz
.Height();
1147 aSz
.Width() = nColumns
* approximate_char_width();
1149 aSz
.Width() = aMinSz
.Width();
1151 if ( IsDropDownBox() )
1152 aSz
.Width() += getMaxWidthScrollBarAndDownButton();
1154 if ( !IsDropDownBox() )
1156 if ( aSz
.Width() < aMinSz
.Width() )
1157 aSz
.Height() += GetSettings().GetStyleSettings().GetScrollBarSize();
1158 if ( aSz
.Height() < aMinSz
.Height() )
1159 aSz
.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1162 aSz
.Width() += ImplGetExtraOffset() * 2;
1164 aSz
= CalcWindowSize( aSz
);
1168 // -----------------------------------------------------------------------
1170 void ComboBox::GetMaxVisColumnsAndLines( sal_uInt16
& rnCols
, sal_uInt16
& rnLines
) const
1172 long nCharWidth
= GetTextWidth(OUString(static_cast<sal_Unicode
>('x')));
1173 if ( !IsDropDownBox() )
1175 Size aOutSz
= mpImplLB
->GetMainWindow()->GetOutputSizePixel();
1176 rnCols
= (sal_uInt16
)(aOutSz
.Width()/nCharWidth
);
1177 rnLines
= (sal_uInt16
)(aOutSz
.Height()/mpImplLB
->GetEntryHeight());
1181 Size aOutSz
= mpSubEdit
->GetOutputSizePixel();
1182 rnCols
= (sal_uInt16
)(aOutSz
.Width()/nCharWidth
);
1187 // -----------------------------------------------------------------------
1189 void ComboBox::Draw( OutputDevice
* pDev
, const Point
& rPos
, const Size
& rSize
, sal_uLong nFlags
)
1191 mpImplLB
->GetMainWindow()->ImplInitSettings( sal_True
, sal_True
, sal_True
);
1193 Point aPos
= pDev
->LogicToPixel( rPos
);
1194 Size aSize
= pDev
->LogicToPixel( rSize
);
1195 Font aFont
= mpImplLB
->GetMainWindow()->GetDrawPixelFont( pDev
);
1196 OutDevType eOutDevType
= pDev
->GetOutDevType();
1200 pDev
->SetFont( aFont
);
1201 pDev
->SetTextFillColor();
1203 // Border/Background
1204 pDev
->SetLineColor();
1205 pDev
->SetFillColor();
1206 sal_Bool bBorder
= !(nFlags
& WINDOW_DRAW_NOBORDER
) && (GetStyle() & WB_BORDER
);
1207 sal_Bool bBackground
= !(nFlags
& WINDOW_DRAW_NOBACKGROUND
) && IsControlBackground();
1208 if ( bBorder
|| bBackground
)
1210 Rectangle
aRect( aPos
, aSize
);
1211 // aRect.Top() += nEditHeight;
1214 ImplDrawFrame( pDev
, aRect
);
1218 pDev
->SetFillColor( GetControlBackground() );
1219 pDev
->DrawRect( aRect
);
1224 if ( !IsDropDownBox() )
1226 long nOnePixel
= GetDrawPixel( pDev
, 1 );
1227 long nTextHeight
= pDev
->GetTextHeight();
1228 long nEditHeight
= nTextHeight
+ 6*nOnePixel
;
1229 sal_uInt16 nTextStyle
= TEXT_DRAW_VCENTER
;
1231 // First, draw the edit part
1232 mpSubEdit
->Draw( pDev
, aPos
, Size( aSize
.Width(), nEditHeight
), nFlags
);
1234 // Second, draw the listbox
1235 if ( GetStyle() & WB_CENTER
)
1236 nTextStyle
|= TEXT_DRAW_CENTER
;
1237 else if ( GetStyle() & WB_RIGHT
)
1238 nTextStyle
|= TEXT_DRAW_RIGHT
;
1240 nTextStyle
|= TEXT_DRAW_LEFT
;
1242 if ( ( nFlags
& WINDOW_DRAW_MONO
) || ( eOutDevType
== OUTDEV_PRINTER
) )
1244 pDev
->SetTextColor( Color( COL_BLACK
) );
1248 if ( !(nFlags
& WINDOW_DRAW_NODISABLE
) && !IsEnabled() )
1250 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
1251 pDev
->SetTextColor( rStyleSettings
.GetDisableColor() );
1255 pDev
->SetTextColor( GetTextColor() );
1259 Rectangle
aClip( aPos
, aSize
);
1260 pDev
->IntersectClipRegion( aClip
);
1261 sal_uInt16 nLines
= (sal_uInt16
) ( (aSize
.Height()-nEditHeight
) / nTextHeight
);
1264 sal_uInt16 nTEntry
= IsReallyVisible() ? mpImplLB
->GetTopEntry() : 0;
1266 Rectangle
aTextRect( aPos
, aSize
);
1268 aTextRect
.Left() += 3*nOnePixel
;
1269 aTextRect
.Right() -= 3*nOnePixel
;
1270 aTextRect
.Top() += nEditHeight
+ nOnePixel
;
1271 aTextRect
.Bottom() = aTextRect
.Top() + nTextHeight
;
1273 // the drawing starts here
1274 for ( sal_uInt16 n
= 0; n
< nLines
; n
++ )
1276 pDev
->DrawText( aTextRect
, mpImplLB
->GetEntryList()->GetEntryText( n
+nTEntry
), nTextStyle
);
1277 aTextRect
.Top() += nTextHeight
;
1278 aTextRect
.Bottom() += nTextHeight
;
1284 // Call Edit::Draw after restoring the MapMode...
1285 if ( IsDropDownBox() )
1287 mpSubEdit
->Draw( pDev
, rPos
, rSize
, nFlags
);
1293 // -----------------------------------------------------------------------
1295 IMPL_LINK( ComboBox
, ImplUserDrawHdl
, UserDrawEvent
*, pEvent
)
1297 UserDraw( *pEvent
);
1301 // -----------------------------------------------------------------------
1303 void ComboBox::UserDraw( const UserDrawEvent
& )
1307 // -----------------------------------------------------------------------
1309 void ComboBox::SetUserItemSize( const Size
& rSz
)
1311 mpImplLB
->GetMainWindow()->SetUserItemSize( rSz
);
1314 // -----------------------------------------------------------------------
1316 void ComboBox::EnableUserDraw( sal_Bool bUserDraw
)
1318 mpImplLB
->GetMainWindow()->EnableUserDraw( bUserDraw
);
1321 // -----------------------------------------------------------------------
1323 void ComboBox::DrawEntry( const UserDrawEvent
& rEvt
, sal_Bool bDrawImage
, sal_Bool bDrawText
, sal_Bool bDrawTextAtImagePos
)
1325 DBG_ASSERT( rEvt
.GetDevice() == mpImplLB
->GetMainWindow(), "DrawEntry?!" );
1326 mpImplLB
->GetMainWindow()->DrawEntry( rEvt
.GetItemId(), bDrawImage
, bDrawText
, bDrawTextAtImagePos
);
1329 // -----------------------------------------------------------------------
1331 void ComboBox::SetSeparatorPos( sal_uInt16 n
)
1333 mpImplLB
->SetSeparatorPos( n
);
1336 // -----------------------------------------------------------------------
1338 void ComboBox::SetMRUEntries( const OUString
& rEntries
, sal_Unicode cSep
)
1340 mpImplLB
->SetMRUEntries( rEntries
, cSep
);
1343 // -----------------------------------------------------------------------
1345 OUString
ComboBox::GetMRUEntries( sal_Unicode cSep
) const
1347 return mpImplLB
->GetMRUEntries( cSep
);
1350 // -----------------------------------------------------------------------
1352 void ComboBox::SetMaxMRUCount( sal_uInt16 n
)
1354 mpImplLB
->SetMaxMRUCount( n
);
1357 // -----------------------------------------------------------------------
1359 sal_uInt16
ComboBox::GetMaxMRUCount() const
1361 return mpImplLB
->GetMaxMRUCount();
1364 // -----------------------------------------------------------------------
1366 sal_uInt16
ComboBox::GetDisplayLineCount() const
1368 return mpImplLB
->GetDisplayLineCount();
1371 // -----------------------------------------------------------------------
1373 void ComboBox::SetEntryData( sal_uInt16 nPos
, void* pNewData
)
1375 mpImplLB
->SetEntryData( nPos
+ mpImplLB
->GetEntryList()->GetMRUCount(), pNewData
);
1378 // -----------------------------------------------------------------------
1380 void* ComboBox::GetEntryData( sal_uInt16 nPos
) const
1382 return mpImplLB
->GetEntryList()->GetEntryData( nPos
+ mpImplLB
->GetEntryList()->GetMRUCount() );
1385 // -----------------------------------------------------------------------
1387 sal_uInt16
ComboBox::GetTopEntry() const
1389 sal_uInt16 nPos
= GetEntryCount() ? mpImplLB
->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND
;
1390 if ( nPos
< mpImplLB
->GetEntryList()->GetMRUCount() )
1395 // -----------------------------------------------------------------------
1397 void ComboBox::SetProminentEntryType( ProminentEntry eType
)
1399 mpImplLB
->SetProminentEntryType( eType
);
1402 // -----------------------------------------------------------------------
1404 Rectangle
ComboBox::GetDropDownPosSizePixel() const
1406 return mpFloatWin
? mpFloatWin
->GetWindowExtentsRelative( const_cast<ComboBox
*>(this) ) : Rectangle();
1409 // -----------------------------------------------------------------------
1411 const Wallpaper
& ComboBox::GetDisplayBackground() const
1413 if( ! mpSubEdit
->IsBackground() )
1414 return Control::GetDisplayBackground();
1416 const Wallpaper
& rBack
= mpSubEdit
->GetBackground();
1417 if( ! rBack
.IsBitmap() &&
1418 ! rBack
.IsGradient() &&
1419 rBack
.GetColor().GetColor() == COL_TRANSPARENT
1421 return Control::GetDisplayBackground();
1424 // -----------------------------------------------------------------------------
1425 sal_uInt16
ComboBox::GetSelectEntryCount() const
1427 return mpImplLB
->GetEntryList()->GetSelectEntryCount();
1429 // -----------------------------------------------------------------------------
1430 sal_uInt16
ComboBox::GetSelectEntryPos( sal_uInt16 nIndex
) const
1432 sal_uInt16 nPos
= mpImplLB
->GetEntryList()->GetSelectEntryPos( nIndex
);
1433 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
1435 if ( nPos
< mpImplLB
->GetEntryList()->GetMRUCount() )
1436 nPos
= mpImplLB
->GetEntryList()->FindEntry( mpImplLB
->GetEntryList()->GetEntryText( nPos
) );
1437 nPos
= sal::static_int_cast
<sal_uInt16
>(nPos
- mpImplLB
->GetEntryList()->GetMRUCount());
1441 // -----------------------------------------------------------------------------
1442 sal_Bool
ComboBox::IsEntryPosSelected( sal_uInt16 nPos
) const
1444 return mpImplLB
->GetEntryList()->IsEntryPosSelected( nPos
+ mpImplLB
->GetEntryList()->GetMRUCount() );
1446 // -----------------------------------------------------------------------------
1447 void ComboBox::SelectEntryPos( sal_uInt16 nPos
, sal_Bool bSelect
)
1449 if ( nPos
< mpImplLB
->GetEntryList()->GetEntryCount() )
1450 mpImplLB
->SelectEntry( nPos
+ mpImplLB
->GetEntryList()->GetMRUCount(), bSelect
);
1452 // -----------------------------------------------------------------------------
1453 void ComboBox::SetNoSelection()
1455 mpImplLB
->SetNoSelection();
1456 mpSubEdit
->SetText( String() );
1458 // -----------------------------------------------------------------------------
1459 Rectangle
ComboBox::GetBoundingRectangle( sal_uInt16 nItem
) const
1461 Rectangle aRect
= mpImplLB
->GetMainWindow()->GetBoundingRectangle( nItem
);
1462 Rectangle aOffset
= mpImplLB
->GetMainWindow()->GetWindowExtentsRelative( (Window
*)this );
1463 aRect
.Move( aOffset
.TopLeft().X(), aOffset
.TopLeft().Y() );
1466 // -----------------------------------------------------------------------------
1468 void ComboBox::SetBorderStyle( sal_uInt16 nBorderStyle
)
1470 Window::SetBorderStyle( nBorderStyle
);
1471 if ( !IsDropDownBox() )
1473 mpSubEdit
->SetBorderStyle( nBorderStyle
);
1474 mpImplLB
->SetBorderStyle( nBorderStyle
);
1477 // -----------------------------------------------------------------------------
1479 long ComboBox::GetIndexForPoint( const Point
& rPoint
, sal_uInt16
& rPos
) const
1481 if( !HasLayoutData() )
1484 // check whether rPoint fits at all
1485 long nIndex
= Control::GetIndexForPoint( rPoint
);
1488 // point must be either in main list window
1489 // or in impl window (dropdown case)
1490 ImplListBoxWindow
* pMain
= mpImplLB
->GetMainWindow();
1492 // convert coordinates to ImplListBoxWindow pixel coordinate space
1493 Point aConvPoint
= LogicToPixel( rPoint
);
1494 aConvPoint
= OutputToAbsoluteScreenPixel( aConvPoint
);
1495 aConvPoint
= pMain
->AbsoluteScreenToOutputPixel( aConvPoint
);
1496 aConvPoint
= pMain
->PixelToLogic( aConvPoint
);
1498 // try to find entry
1499 sal_uInt16 nEntry
= pMain
->GetEntryPosForPoint( aConvPoint
);
1500 if( nEntry
== LISTBOX_ENTRY_NOTFOUND
)
1506 // get line relative index
1508 nIndex
= ToRelativeLineIndex( nIndex
);
1513 ComboBox::ComboBoxBounds
ComboBox::calcComboBoxDropDownComponentBounds(const Size
&rOutSz
,
1514 const Size
&rBorderOutSz
) const
1516 ComboBoxBounds aBounds
;
1519 long nBottom
= rOutSz
.Height();
1521 Window
*pBorder
= GetWindow( WINDOW_BORDER
);
1522 ImplControlValue aControlValue
;
1524 Rectangle aContent
, aBound
;
1526 // use the full extent of the control
1527 Rectangle
aArea( aPoint
, rBorderOutSz
);
1529 if ( GetNativeControlRegion(CTRL_COMBOBOX
, PART_BUTTON_DOWN
,
1530 aArea
, 0, aControlValue
, OUString(), aBound
, aContent
) )
1532 // convert back from border space to local coordinates
1533 aPoint
= pBorder
->ScreenToOutputPixel( OutputToScreenPixel( aPoint
) );
1534 aContent
.Move(-aPoint
.X(), -aPoint
.Y());
1536 aBounds
.aButtonPos
= Point(aContent
.Left(), nTop
);
1537 aBounds
.aButtonSize
= Size(aContent
.getWidth(), (nBottom
-nTop
));
1539 // adjust the size of the edit field
1540 if ( GetNativeControlRegion(CTRL_COMBOBOX
, PART_SUB_EDIT
,
1541 aArea
, 0, aControlValue
, OUString(), aBound
, aContent
) )
1543 // convert back from border space to local coordinates
1544 aContent
.Move(-aPoint
.X(), -aPoint
.Y());
1546 // use the themes drop down size
1547 aBounds
.aSubEditPos
= aContent
.TopLeft();
1548 aBounds
.aSubEditSize
= aContent
.GetSize();
1552 // use the themes drop down size for the button
1553 aBounds
.aSubEditSize
= Size(rOutSz
.Width() - aContent
.getWidth(), rOutSz
.Height());
1558 long nSBWidth
= GetSettings().GetStyleSettings().GetScrollBarSize();
1559 nSBWidth
= CalcZoom( nSBWidth
);
1560 aBounds
.aSubEditSize
= Size(rOutSz
.Width() - nSBWidth
, rOutSz
.Height());
1561 aBounds
.aButtonPos
= Point(rOutSz
.Width() - nSBWidth
, nTop
);
1562 aBounds
.aButtonSize
= Size(nSBWidth
, (nBottom
-nTop
));
1567 void ComboBox::setMaxWidthChars(sal_Int32 nWidth
)
1569 if (nWidth
!= m_nMaxWidthChars
)
1571 m_nMaxWidthChars
= nWidth
;
1576 bool ComboBox::set_property(const OString
&rKey
, const OString
&rValue
)
1578 if (rKey
== "max-width-chars")
1579 setMaxWidthChars(rValue
.toInt32());
1581 return Control::set_property(rKey
, rValue
);
1585 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */