merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / control / combobox.cxx
blob92a653670335de4cfa28d60508e6753da51a9eeb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: combobox.cxx,v $
10 * $Revision: 1.50 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <tools/table.hxx>
34 #include <tools/debug.hxx>
36 #ifndef _SV_RC_H
37 #include <tools/rc.h>
38 #endif
39 #include <vcl/svdata.hxx>
40 #include <vcl/decoview.hxx>
41 #include <vcl/ilstbox.hxx>
42 #include <vcl/lstbox.h>
43 #include <vcl/button.hxx>
44 #include <vcl/subedit.hxx>
45 #include <vcl/event.hxx>
46 #include <vcl/combobox.hxx>
47 #include <vcl/controllayout.hxx>
51 // =======================================================================
53 inline ULONG ImplCreateKey( USHORT nPos )
55 // Key = Pos+1, wegen Pos 0
56 return nPos+1;
59 // -----------------------------------------------------------------------
61 static void lcl_GetSelectedEntries( Table& rSelectedPos, const XubString& rText, xub_Unicode cTokenSep, const ImplEntryList* pEntryList )
63 for( xub_StrLen n = rText.GetTokenCount( cTokenSep ); n; )
65 XubString aToken = rText.GetToken( --n, cTokenSep );
66 aToken.EraseLeadingAndTrailingChars( ' ' );
67 USHORT nPos = pEntryList->FindEntry( aToken );
68 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
69 rSelectedPos.Insert( ImplCreateKey( nPos ), (void*)sal_IntPtr(1L) );
73 // =======================================================================
75 ComboBox::ComboBox( WindowType nType ) :
76 Edit( nType )
78 ImplInitComboBoxData();
81 // -----------------------------------------------------------------------
83 ComboBox::ComboBox( Window* pParent, WinBits nStyle ) :
84 Edit( WINDOW_COMBOBOX )
86 ImplInitComboBoxData();
87 ImplInit( pParent, nStyle );
90 // -----------------------------------------------------------------------
92 ComboBox::ComboBox( Window* pParent, const ResId& rResId ) :
93 Edit( WINDOW_COMBOBOX )
95 ImplInitComboBoxData();
96 rResId.SetRT( RSC_COMBOBOX );
97 WinBits nStyle = ImplInitRes( rResId );
98 ImplInit( pParent, nStyle );
99 ImplLoadRes( rResId );
101 if ( !(nStyle & WB_HIDE ) )
102 Show();
105 // -----------------------------------------------------------------------
107 ComboBox::~ComboBox()
109 SetSubEdit( NULL );
110 delete mpSubEdit;
112 delete mpImplLB;
113 mpImplLB = NULL;
115 delete mpFloatWin;
116 delete mpBtn;
119 // -----------------------------------------------------------------------
121 void ComboBox::ImplInitComboBoxData()
123 mpSubEdit = NULL;
124 mpBtn = NULL;
125 mpImplLB = NULL;
126 mpFloatWin = NULL;
128 mnDDHeight = 0;
129 mbDDAutoSize = TRUE;
130 mbSyntheticModify = FALSE;
131 mbMatchCase = FALSE;
132 mcMultiSep = ';';
135 // -----------------------------------------------------------------------
137 void ComboBox::ImplCalcEditHeight()
139 sal_Int32 nLeft, nTop, nRight, nBottom;
140 GetBorder( nLeft, nTop, nRight, nBottom );
141 mnDDHeight = (USHORT)(mpSubEdit->GetTextHeight() + nTop + nBottom + 4);
142 if ( !IsDropDownBox() )
143 mnDDHeight += 4;
145 Region aCtrlRegion( Rectangle( (const Point&)Point(), Size( 10, 10 ) ) );
146 Region aBoundRegion, aContentRegion;
147 ImplControlValue aControlValue;
148 ControlType aType = IsDropDownBox() ? CTRL_COMBOBOX : CTRL_EDITBOX;
149 if( GetNativeControlRegion( aType, PART_ENTIRE_CONTROL,
150 aCtrlRegion,
151 CTRL_STATE_ENABLED,
152 aControlValue, rtl::OUString(),
153 aBoundRegion, aContentRegion ) )
155 const long nNCHeight = aBoundRegion.GetBoundRect().GetHeight();
156 if( mnDDHeight < nNCHeight )
157 mnDDHeight = sal::static_int_cast<USHORT>( nNCHeight );
161 // -----------------------------------------------------------------------
163 void ComboBox::ImplInit( Window* pParent, WinBits nStyle )
165 ImplInitStyle( nStyle );
167 BOOL bNoBorder = ( nStyle & WB_NOBORDER ) ? TRUE : FALSE;
168 if ( !(nStyle & WB_DROPDOWN) )
170 nStyle &= ~WB_BORDER;
171 nStyle |= WB_NOBORDER;
173 else
175 if ( !bNoBorder )
176 nStyle |= WB_BORDER;
179 Edit::ImplInit( pParent, nStyle );
180 SetBackground();
182 // DropDown ?
183 WinBits nEditStyle = nStyle & ( WB_LEFT | WB_RIGHT | WB_CENTER );
184 WinBits nListStyle = nStyle;
185 if( nStyle & WB_DROPDOWN )
187 mpFloatWin = new ImplListBoxFloatingWindow( this );
188 mpFloatWin->SetAutoWidth( TRUE );
189 mpFloatWin->SetPopupModeEndHdl( LINK( this, ComboBox, ImplPopupModeEndHdl ) );
191 mpBtn = new ImplBtn( this, WB_NOLIGHTBORDER | WB_RECTSTYLE );
192 ImplInitDropDownButton( mpBtn );
193 mpBtn->SetMBDownHdl( LINK( this, ComboBox, ImplClickBtnHdl ) );
194 mpBtn->Show();
196 nEditStyle |= WB_NOBORDER;
197 nListStyle &= ~WB_BORDER;
198 nListStyle |= WB_NOBORDER;
200 else
202 if ( !bNoBorder )
204 nEditStyle |= WB_BORDER;
205 nListStyle &= ~WB_NOBORDER;
206 nListStyle |= WB_BORDER;
210 mpSubEdit = new Edit( this, nEditStyle );
211 mpSubEdit->EnableRTL( FALSE );
212 SetSubEdit( mpSubEdit );
213 mpSubEdit->SetPosPixel( Point() );
214 EnableAutocomplete( TRUE );
215 mpSubEdit->Show();
217 Window* pLBParent = this;
218 if ( mpFloatWin )
219 pLBParent = mpFloatWin;
220 mpImplLB = new ImplListBox( pLBParent, nListStyle|WB_SIMPLEMODE );
221 mpImplLB->SetPosPixel( Point() );
222 mpImplLB->SetSelectHdl( LINK( this, ComboBox, ImplSelectHdl ) );
223 mpImplLB->SetCancelHdl( LINK( this, ComboBox, ImplCancelHdl ) );
224 mpImplLB->SetDoubleClickHdl( LINK( this, ComboBox, ImplDoubleClickHdl ) );
225 mpImplLB->SetUserDrawHdl( LINK( this, ComboBox, ImplUserDrawHdl ) );
226 mpImplLB->SetSelectionChangedHdl( LINK( this, ComboBox, ImplSelectionChangedHdl ) );
227 mpImplLB->Show();
229 if ( mpFloatWin )
230 mpFloatWin->SetImplListBox( mpImplLB );
231 else
232 mpImplLB->GetMainWindow()->AllowGrabFocus( TRUE );
234 ImplCalcEditHeight();
236 SetCompoundControl( TRUE );
239 // -----------------------------------------------------------------------
241 WinBits ComboBox::ImplInitStyle( WinBits nStyle )
243 if ( !(nStyle & WB_NOTABSTOP) )
244 nStyle |= WB_TABSTOP;
245 if ( !(nStyle & WB_NOGROUP) )
246 nStyle |= WB_GROUP;
247 return nStyle;
250 // -----------------------------------------------------------------------
252 void ComboBox::ImplLoadRes( const ResId& rResId )
254 Edit::ImplLoadRes( rResId );
256 ULONG nNumber = ReadLongRes();
258 if( nNumber )
260 for( USHORT i = 0; i < nNumber; i++ )
262 InsertEntry( ReadStringRes(), LISTBOX_APPEND );
267 // -----------------------------------------------------------------------
269 void ComboBox::EnableAutocomplete( BOOL bEnable, BOOL bMatchCase )
271 mbMatchCase = bMatchCase;
273 if ( bEnable )
274 mpSubEdit->SetAutocompleteHdl( LINK( this, ComboBox, ImplAutocompleteHdl ) );
275 else
276 mpSubEdit->SetAutocompleteHdl( Link() );
279 // -----------------------------------------------------------------------
281 BOOL ComboBox::IsAutocompleteEnabled() const
283 return mpSubEdit->GetAutocompleteHdl().IsSet();
286 // -----------------------------------------------------------------------
288 IMPL_LINK( ComboBox, ImplClickBtnHdl, void*, EMPTYARG )
290 ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
291 mpSubEdit->GrabFocus();
292 if ( !mpImplLB->GetEntryList()->GetMRUCount() )
293 ImplUpdateFloatSelection();
294 else
295 mpImplLB->SelectEntry( 0 , TRUE );
296 mpBtn->SetPressed( TRUE );
297 SetSelection( Selection( 0, SELECTION_MAX ) );
298 mpFloatWin->StartFloat( TRUE );
299 ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
301 ImplClearLayoutData();
302 if( mpImplLB )
303 mpImplLB->GetMainWindow()->ImplClearLayoutData();
305 return 0;
308 // -----------------------------------------------------------------------
310 IMPL_LINK( ComboBox, ImplPopupModeEndHdl, void*, EMPTYARG )
312 if( mpFloatWin->IsPopupModeCanceled() )
314 if ( !mpImplLB->GetEntryList()->IsEntryPosSelected( mpFloatWin->GetPopupModeStartSaveSelection() ) )
316 mpImplLB->SelectEntry( mpFloatWin->GetPopupModeStartSaveSelection(), TRUE );
317 BOOL bTravelSelect = mpImplLB->IsTravelSelect();
318 mpImplLB->SetTravelSelect( TRUE );
319 Select();
320 mpImplLB->SetTravelSelect( bTravelSelect );
324 ImplClearLayoutData();
325 if( mpImplLB )
326 mpImplLB->GetMainWindow()->ImplClearLayoutData();
328 mpBtn->SetPressed( FALSE );
329 ImplCallEventListeners( VCLEVENT_DROPDOWN_CLOSE );
330 return 0;
333 // -----------------------------------------------------------------------
335 IMPL_LINK( ComboBox, ImplAutocompleteHdl, Edit*, pEdit )
337 Selection aSel = pEdit->GetSelection();
338 AutocompleteAction eAction = pEdit->GetAutocompleteAction();
340 /* If there is no current selection do not auto complete on
341 Tab/Shift-Tab since then we would not cycle to the next field.
343 if ( aSel.Len() ||
344 ((eAction != AUTOCOMPLETE_TABFORWARD) && (eAction != AUTOCOMPLETE_TABBACKWARD)) )
346 XubString aFullText = pEdit->GetText();
347 XubString aStartText = aFullText.Copy( 0, (xub_StrLen)aSel.Max() );
348 USHORT nStart = mpImplLB->GetCurrentPos();
350 if ( nStart == LISTBOX_ENTRY_NOTFOUND )
351 nStart = 0;
353 BOOL bForward = TRUE;
354 if ( eAction == AUTOCOMPLETE_TABFORWARD )
355 nStart++;
356 else if ( eAction == AUTOCOMPLETE_TABBACKWARD )
358 bForward = FALSE;
359 nStart = nStart ? nStart - 1 : mpImplLB->GetEntryList()->GetEntryCount()-1;
362 USHORT nPos = LISTBOX_ENTRY_NOTFOUND;
363 if( ! mbMatchCase )
365 // Try match case insensitive from current position
366 nPos = mpImplLB->GetEntryList()->FindMatchingEntry( aStartText, nStart, bForward, TRUE );
367 if ( nPos == LISTBOX_ENTRY_NOTFOUND )
368 // Try match case insensitive, but from start
369 nPos = mpImplLB->GetEntryList()->FindMatchingEntry( aStartText, bForward ? 0 : (mpImplLB->GetEntryList()->GetEntryCount()-1), bForward, TRUE );
372 if ( nPos == LISTBOX_ENTRY_NOTFOUND )
373 // Try match full from current position
374 nPos = mpImplLB->GetEntryList()->FindMatchingEntry( aStartText, nStart, bForward, FALSE );
375 if ( nPos == LISTBOX_ENTRY_NOTFOUND )
376 // Match full, but from start
377 nPos = mpImplLB->GetEntryList()->FindMatchingEntry( aStartText, bForward ? 0 : (mpImplLB->GetEntryList()->GetEntryCount()-1), bForward, FALSE );
379 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
381 XubString aText = mpImplLB->GetEntryList()->GetEntryText( nPos );
382 Selection aSelection( aText.Len(), aStartText.Len() );
383 pEdit->SetText( aText, aSelection );
387 return 0;
390 // -----------------------------------------------------------------------
392 IMPL_LINK( ComboBox, ImplSelectHdl, void*, EMPTYARG )
394 BOOL bPopup = IsInDropDown();
395 BOOL bCallSelect = FALSE;
396 if ( mpImplLB->IsSelectionChanged() || bPopup )
398 XubString aText;
399 if ( IsMultiSelectionEnabled() )
401 aText = mpSubEdit->GetText();
403 // Alle Eintraege entfernen, zu denen es einen Entry gibt, der aber nicht selektiert ist.
404 xub_StrLen nIndex = 0;
405 while ( nIndex != STRING_NOTFOUND )
407 xub_StrLen nPrevIndex = nIndex;
408 XubString aToken = aText.GetToken( 0, mcMultiSep, nIndex );
409 xub_StrLen nTokenLen = aToken.Len();
410 aToken.EraseLeadingAndTrailingChars( ' ' );
411 USHORT nP = mpImplLB->GetEntryList()->FindEntry( aToken );
412 if ( (nP != LISTBOX_ENTRY_NOTFOUND) && (!mpImplLB->GetEntryList()->IsEntryPosSelected( nP )) )
414 aText.Erase( nPrevIndex, nTokenLen );
415 nIndex = sal::static_int_cast<xub_StrLen>(nIndex - nTokenLen);
416 if ( (nPrevIndex < aText.Len()) && (aText.GetChar( nPrevIndex ) == mcMultiSep) )
418 aText.Erase( nPrevIndex, 1 );
419 nIndex--;
422 aText.EraseLeadingAndTrailingChars( ' ' );
425 // Fehlende Eintraege anhaengen...
426 Table aSelInText;
427 lcl_GetSelectedEntries( aSelInText, aText, mcMultiSep, mpImplLB->GetEntryList() );
428 USHORT nSelectedEntries = mpImplLB->GetEntryList()->GetSelectEntryCount();
429 for ( USHORT n = 0; n < nSelectedEntries; n++ )
431 USHORT nP = mpImplLB->GetEntryList()->GetSelectEntryPos( n );
432 if ( !aSelInText.IsKeyValid( ImplCreateKey( nP ) ) )
434 if ( aText.Len() && (aText.GetChar( aText.Len()-1 ) != mcMultiSep) )
435 aText += mcMultiSep;
436 if ( aText.Len() )
437 aText += ' '; // etwas auflockern
438 aText += mpImplLB->GetEntryList()->GetEntryText( nP );
439 aText += mcMultiSep;
442 if ( aText.Len() && (aText.GetChar( aText.Len()-1 ) == mcMultiSep) )
443 aText.Erase( aText.Len()-1, 1 );
445 else
447 aText = mpImplLB->GetEntryList()->GetSelectEntry( 0 );
450 mpSubEdit->SetText( aText );
452 Selection aNewSelection( 0, aText.Len() );
453 if ( IsMultiSelectionEnabled() )
454 aNewSelection.Min() = aText.Len();
455 mpSubEdit->SetSelection( aNewSelection );
457 bCallSelect = TRUE;
460 // #84652# Call GrabFocus and EndPopupMode before calling Select/Modify, but after changing the text
462 if ( bPopup && !mpImplLB->IsTravelSelect() &&
463 ( !IsMultiSelectionEnabled() || !mpImplLB->GetSelectModifier() ) )
465 mpFloatWin->EndPopupMode();
466 GrabFocus();
469 if ( bCallSelect )
471 mpSubEdit->SetModifyFlag();
472 mbSyntheticModify = TRUE;
473 Modify();
474 mbSyntheticModify = FALSE;
475 if (ImplGetWindowImpl() != NULL) //liuchen 2009-7-28, resolve the problem that soffice get crashed if in ComboBox_Change event a Worksheets("SheetX").Activate sentence needs to be executed
477 Select();
481 return 0;
484 // -----------------------------------------------------------------------
486 IMPL_LINK( ComboBox, ImplCancelHdl, void*, EMPTYARG )
488 if( IsInDropDown() )
489 mpFloatWin->EndPopupMode();
491 return 1;
494 // -----------------------------------------------------------------------
496 IMPL_LINK( ComboBox, ImplSelectionChangedHdl, void*, n )
498 if ( !mpImplLB->IsTrackingSelect() )
500 USHORT nChanged = (USHORT)(ULONG)n;
501 if ( !mpSubEdit->IsReadOnly() && mpImplLB->GetEntryList()->IsEntryPosSelected( nChanged ) )
502 mpSubEdit->SetText( mpImplLB->GetEntryList()->GetEntryText( nChanged ) );
504 return 1;
507 // -----------------------------------------------------------------------
509 IMPL_LINK( ComboBox, ImplDoubleClickHdl, void*, EMPTYARG )
511 DoubleClick();
512 return 0;
515 // -----------------------------------------------------------------------
517 void ComboBox::ToggleDropDown()
519 if( IsDropDownBox() )
521 if( mpFloatWin->IsInPopupMode() )
522 mpFloatWin->EndPopupMode();
523 else
525 mpSubEdit->GrabFocus();
526 if ( !mpImplLB->GetEntryList()->GetMRUCount() )
527 ImplUpdateFloatSelection();
528 else
529 mpImplLB->SelectEntry( 0 , TRUE );
530 ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
531 mpBtn->SetPressed( TRUE );
532 SetSelection( Selection( 0, SELECTION_MAX ) );
533 mpFloatWin->StartFloat( TRUE );
534 ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
539 // -----------------------------------------------------------------------
541 void ComboBox::Select()
543 ImplCallEventListenersAndHandler( VCLEVENT_COMBOBOX_SELECT, maSelectHdl, this );
546 // -----------------------------------------------------------------------
548 void ComboBox::DoubleClick()
550 ImplCallEventListenersAndHandler( VCLEVENT_COMBOBOX_DOUBLECLICK, maDoubleClickHdl, this );
553 // -----------------------------------------------------------------------
555 void ComboBox::EnableAutoSize( BOOL bAuto )
557 mbDDAutoSize = bAuto;
558 if ( mpFloatWin )
560 if ( bAuto && !mpFloatWin->GetDropDownLineCount() )
561 mpFloatWin->SetDropDownLineCount( 5 );
562 else if ( !bAuto )
563 mpFloatWin->SetDropDownLineCount( 0 );
567 // -----------------------------------------------------------------------
569 void ComboBox::EnableDDAutoWidth( BOOL b )
571 if ( mpFloatWin )
572 mpFloatWin->SetAutoWidth( b );
575 // -----------------------------------------------------------------------
577 BOOL ComboBox::IsDDAutoWidthEnabled() const
579 return mpFloatWin ? mpFloatWin->IsAutoWidth() : FALSE;
583 // -----------------------------------------------------------------------
585 void ComboBox::SetDropDownLineCount( USHORT nLines )
587 if ( mpFloatWin )
588 mpFloatWin->SetDropDownLineCount( nLines );
591 // -----------------------------------------------------------------------
593 USHORT ComboBox::GetDropDownLineCount() const
595 USHORT nLines = 0;
596 if ( mpFloatWin )
597 nLines = mpFloatWin->GetDropDownLineCount();
598 return nLines;
601 // -----------------------------------------------------------------------
603 void ComboBox::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight,
604 USHORT nFlags )
606 if( IsDropDownBox() && ( nFlags & WINDOW_POSSIZE_SIZE ) )
608 Size aPrefSz = mpFloatWin->GetPrefSize();
609 if ( ( nFlags & WINDOW_POSSIZE_HEIGHT ) && ( nHeight >= 2*mnDDHeight ) )
610 aPrefSz.Height() = nHeight-mnDDHeight;
611 if ( nFlags & WINDOW_POSSIZE_WIDTH )
612 aPrefSz.Width() = nWidth;
613 mpFloatWin->SetPrefSize( aPrefSz );
615 if ( IsAutoSizeEnabled() && ! (nFlags & WINDOW_POSSIZE_DROPDOWN) )
616 nHeight = mnDDHeight;
619 Edit::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
622 // -----------------------------------------------------------------------
624 void ComboBox::Resize()
626 Control::Resize();
628 Size aOutSz = GetOutputSizePixel();
629 if( IsDropDownBox() )
631 long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
632 long nTop = 0;
633 long nBottom = aOutSz.Height();
635 Window *pBorder = GetWindow( WINDOW_BORDER );
636 ImplControlValue aControlValue;
637 Point aPoint;
638 Region aContent, aBound;
640 // use the full extent of the control
641 Region aArea( Rectangle(aPoint, pBorder->GetOutputSizePixel()) );
643 if ( GetNativeControlRegion(CTRL_COMBOBOX, PART_BUTTON_DOWN,
644 aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) )
646 // convert back from border space to local coordinates
647 aPoint = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aPoint ) );
648 aContent.Move(-aPoint.X(), -aPoint.Y());
650 mpBtn->SetPosSizePixel( aContent.GetBoundRect().Left(), nTop, aContent.GetBoundRect().getWidth(), (nBottom-nTop) );
652 // adjust the size of the edit field
653 if ( GetNativeControlRegion(CTRL_COMBOBOX, PART_SUB_EDIT,
654 aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) )
656 // convert back from border space to local coordinates
657 aContent.Move(-aPoint.X(), -aPoint.Y());
659 // use the themes drop down size
660 Rectangle aContentRect = aContent.GetBoundRect();
661 mpSubEdit->SetPosSizePixel( aContentRect.TopLeft(), aContentRect.GetSize() );
663 else
665 // use the themes drop down size for the button
666 aOutSz.Width() -= aContent.GetBoundRect().getWidth();
667 mpSubEdit->SetSizePixel( aOutSz );
670 else
672 nSBWidth = CalcZoom( nSBWidth );
673 mpSubEdit->SetPosSizePixel( Point( 0, 0 ), Size( aOutSz.Width() - nSBWidth, aOutSz.Height() ) );
674 mpBtn->SetPosSizePixel( aOutSz.Width() - nSBWidth, nTop, nSBWidth, (nBottom-nTop) );
677 else
679 mpSubEdit->SetSizePixel( Size( aOutSz.Width(), mnDDHeight ) );
680 mpImplLB->SetPosSizePixel( 0, mnDDHeight, aOutSz.Width(), aOutSz.Height() - mnDDHeight );
681 if ( GetText().Len() )
682 ImplUpdateFloatSelection();
685 // FloatingWindow-Groesse auch im unsichtbare Zustand auf Stand halten,
686 // weil KEY_PGUP/DOWN ausgewertet wird...
687 if ( mpFloatWin )
688 mpFloatWin->SetSizePixel( mpFloatWin->CalcFloatSize() );
691 // -----------------------------------------------------------------------
693 void ComboBox::FillLayoutData() const
695 mpLayoutData = new vcl::ControlLayoutData();
696 AppendLayoutData( *mpSubEdit );
697 mpSubEdit->SetLayoutDataParent( this );
698 Control* pMainWindow = mpImplLB->GetMainWindow();
699 if( mpFloatWin )
701 // dropdown mode
702 if( mpFloatWin->IsReallyVisible() )
704 AppendLayoutData( *pMainWindow );
705 pMainWindow->SetLayoutDataParent( this );
708 else
710 AppendLayoutData( *pMainWindow );
711 pMainWindow->SetLayoutDataParent( this );
715 // -----------------------------------------------------------------------
717 void ComboBox::StateChanged( StateChangedType nType )
719 Edit::StateChanged( nType );
721 if ( nType == STATE_CHANGE_READONLY )
723 mpImplLB->SetReadOnly( IsReadOnly() );
724 if ( mpBtn )
725 mpBtn->Enable( IsEnabled() && !IsReadOnly() );
727 else if ( nType == STATE_CHANGE_ENABLE )
729 mpSubEdit->Enable( IsEnabled() );
730 mpImplLB->Enable( IsEnabled() && !IsReadOnly() );
731 if ( mpBtn )
732 mpBtn->Enable( IsEnabled() && !IsReadOnly() );
733 Invalidate();
735 else if( nType == STATE_CHANGE_UPDATEMODE )
737 mpImplLB->SetUpdateMode( IsUpdateMode() );
739 else if ( nType == STATE_CHANGE_ZOOM )
741 mpImplLB->SetZoom( GetZoom() );
742 mpSubEdit->SetZoom( GetZoom() );
743 ImplCalcEditHeight();
744 Resize();
746 else if ( nType == STATE_CHANGE_CONTROLFONT )
748 mpImplLB->SetControlFont( GetControlFont() );
749 mpSubEdit->SetControlFont( GetControlFont() );
750 ImplCalcEditHeight();
751 Resize();
753 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
755 mpImplLB->SetControlForeground( GetControlForeground() );
756 mpSubEdit->SetControlForeground( GetControlForeground() );
758 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
760 mpImplLB->SetControlBackground( GetControlBackground() );
761 mpSubEdit->SetControlBackground( GetControlBackground() );
763 else if ( nType == STATE_CHANGE_STYLE )
765 SetStyle( ImplInitStyle( GetStyle() ) );
766 mpImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) ? TRUE : FALSE );
768 else if( nType == STATE_CHANGE_MIRRORING )
770 if( mpBtn )
772 mpBtn->EnableRTL( IsRTLEnabled() );
773 ImplInitDropDownButton( mpBtn );
775 mpSubEdit->StateChanged( STATE_CHANGE_MIRRORING );
776 mpImplLB->EnableRTL( IsRTLEnabled() );
777 Resize();
781 // -----------------------------------------------------------------------
783 void ComboBox::DataChanged( const DataChangedEvent& rDCEvt )
785 Control::DataChanged( rDCEvt );
787 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
788 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
789 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
790 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
792 if ( mpBtn )
794 mpBtn->SetSettings( GetSettings() );
795 ImplInitDropDownButton( mpBtn );
797 Resize();
798 mpImplLB->Resize(); // Wird nicht durch ComboBox::Resize() gerufen, wenn sich die ImplLB nicht aendert.
799 SetBackground(); // due to a hack in Window::UpdateSettings the background must be reset
800 // otherwise it will overpaint NWF drawn comboboxes
804 // -----------------------------------------------------------------------
806 long ComboBox::PreNotify( NotifyEvent& rNEvt )
809 return Edit::PreNotify( rNEvt );
812 // -----------------------------------------------------------------------
814 long ComboBox::Notify( NotifyEvent& rNEvt )
816 long nDone = 0;
817 if( ( rNEvt.GetType() == EVENT_KEYINPUT ) && ( rNEvt.GetWindow() == mpSubEdit )
818 && !IsReadOnly() )
820 KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
821 USHORT nKeyCode = aKeyEvt.GetKeyCode().GetCode();
822 switch( nKeyCode )
824 case KEY_UP:
825 case KEY_DOWN:
826 case KEY_PAGEUP:
827 case KEY_PAGEDOWN:
829 ImplUpdateFloatSelection();
830 if( ( nKeyCode == KEY_DOWN ) && mpFloatWin && !mpFloatWin->IsInPopupMode() && aKeyEvt.GetKeyCode().IsMod2() )
832 ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN );
833 mpBtn->SetPressed( TRUE );
834 if ( mpImplLB->GetEntryList()->GetMRUCount() )
835 mpImplLB->SelectEntry( 0 , TRUE );
836 SetSelection( Selection( 0, SELECTION_MAX ) );
837 mpFloatWin->StartFloat( FALSE );
838 ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN );
839 nDone = 1;
841 else if( ( nKeyCode == KEY_UP ) && mpFloatWin && mpFloatWin->IsInPopupMode() && aKeyEvt.GetKeyCode().IsMod2() )
843 mpFloatWin->EndPopupMode();
844 nDone = 1;
846 else
848 nDone = mpImplLB->ProcessKeyInput( aKeyEvt );
851 break;
853 case KEY_RETURN:
855 if( ( rNEvt.GetWindow() == mpSubEdit ) && IsInDropDown() )
857 mpImplLB->ProcessKeyInput( aKeyEvt );
858 nDone = 1;
861 break;
864 else if ( (rNEvt.GetType() == EVENT_LOSEFOCUS) && mpFloatWin )
866 if( mpFloatWin->HasChildPathFocus() )
867 mpSubEdit->GrabFocus();
868 else if ( mpFloatWin->IsInPopupMode() && !HasChildPathFocus( TRUE ) )
869 mpFloatWin->EndPopupMode();
871 else if( (rNEvt.GetType() == EVENT_COMMAND) &&
872 (rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL) &&
873 (rNEvt.GetWindow() == mpSubEdit) )
875 USHORT nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
876 if ( ( nWheelBehavior == MOUSE_WHEEL_ALWAYS )
877 || ( ( nWheelBehavior == MOUSE_WHEEL_FOCUS_ONLY )
878 && HasChildPathFocus()
882 nDone = mpImplLB->HandleWheelAsCursorTravel( *rNEvt.GetCommandEvent() );
884 else
886 nDone = 0; // don't eat this event, let the default handling happen (i.e. scroll the context)
889 else if( ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN ) && ( rNEvt.GetWindow() == mpImplLB->GetMainWindow() ) )
891 mpSubEdit->GrabFocus();
894 return nDone ? nDone : Edit::Notify( rNEvt );
897 // -----------------------------------------------------------------------
899 void ComboBox::SetText( const XubString& rStr )
901 ImplCallEventListeners( VCLEVENT_COMBOBOX_SETTEXT );
903 Edit::SetText( rStr );
904 ImplUpdateFloatSelection();
907 // -----------------------------------------------------------------------
909 void ComboBox::SetText( const XubString& rStr, const Selection& rNewSelection )
911 ImplCallEventListeners( VCLEVENT_COMBOBOX_SETTEXT );
913 Edit::SetText( rStr, rNewSelection );
914 ImplUpdateFloatSelection();
917 // -----------------------------------------------------------------------
919 void ComboBox::Modify()
921 if ( !mbSyntheticModify )
922 ImplUpdateFloatSelection();
924 Edit::Modify();
927 // -----------------------------------------------------------------------
929 void ComboBox::ImplUpdateFloatSelection()
931 // Text in der ListBox in den sichtbaren Bereich bringen
932 mpImplLB->SetCallSelectionChangedHdl( FALSE );
933 if ( !IsMultiSelectionEnabled() )
935 XubString aSearchStr( mpSubEdit->GetText() );
936 USHORT nSelect = LISTBOX_ENTRY_NOTFOUND;
937 BOOL bSelect = TRUE;
939 if ( mpImplLB->GetCurrentPos() != LISTBOX_ENTRY_NOTFOUND )
941 XubString aCurrent = mpImplLB->GetEntryList()->GetEntryText( mpImplLB->GetCurrentPos() );
942 if ( aCurrent == aSearchStr )
943 nSelect = mpImplLB->GetCurrentPos();
946 if ( nSelect == LISTBOX_ENTRY_NOTFOUND )
947 nSelect = mpImplLB->GetEntryList()->FindEntry( aSearchStr );
948 if ( nSelect == LISTBOX_ENTRY_NOTFOUND )
950 nSelect = mpImplLB->GetEntryList()->FindMatchingEntry( aSearchStr );
951 bSelect = FALSE;
954 if( nSelect != LISTBOX_ENTRY_NOTFOUND )
956 if ( !mpImplLB->IsVisible( nSelect ) )
957 mpImplLB->SetTopEntry( nSelect );
958 mpImplLB->SelectEntry( nSelect, bSelect );
960 else
962 nSelect = mpImplLB->GetEntryList()->GetSelectEntryPos( 0 );
963 if( nSelect != LISTBOX_ENTRY_NOTFOUND )
964 mpImplLB->SelectEntry( nSelect, FALSE );
965 // mpImplLB->SetTopEntry( 0 ); #92555# Ugly....
966 mpImplLB->ResetCurrentPos();
969 else
971 Table aSelInText;
972 lcl_GetSelectedEntries( aSelInText, mpSubEdit->GetText(), mcMultiSep, mpImplLB->GetEntryList() );
973 for ( USHORT n = 0; n < mpImplLB->GetEntryList()->GetEntryCount(); n++ )
974 mpImplLB->SelectEntry( n, aSelInText.IsKeyValid( ImplCreateKey( n ) ) );
976 mpImplLB->SetCallSelectionChangedHdl( TRUE );
979 // -----------------------------------------------------------------------
981 USHORT ComboBox::InsertEntry( const XubString& rStr, USHORT nPos )
983 USHORT nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr );
984 nRealPos = sal::static_int_cast<USHORT>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
985 CallEventListeners( VCLEVENT_COMBOBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) );
986 return nRealPos;
989 // -----------------------------------------------------------------------
991 USHORT ComboBox::InsertEntry( const XubString& rStr, const Image& rImage, USHORT nPos )
993 USHORT nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr, rImage );
994 nRealPos = sal::static_int_cast<USHORT>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount());
995 CallEventListeners( VCLEVENT_COMBOBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) );
996 return nRealPos;
999 // -----------------------------------------------------------------------
1001 void ComboBox::RemoveEntry( const XubString& rStr )
1003 RemoveEntry( GetEntryPos( rStr ) );
1006 // -----------------------------------------------------------------------
1008 void ComboBox::RemoveEntry( USHORT nPos )
1010 mpImplLB->RemoveEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1011 CallEventListeners( VCLEVENT_COMBOBOX_ITEMREMOVED, (void*) sal_IntPtr(nPos) );
1014 // -----------------------------------------------------------------------
1016 void ComboBox::Clear()
1018 mpImplLB->Clear();
1019 CallEventListeners( VCLEVENT_COMBOBOX_ITEMREMOVED, (void*) sal_IntPtr(-1) );
1022 // -----------------------------------------------------------------------
1024 USHORT ComboBox::GetEntryPos( const XubString& rStr ) const
1026 USHORT nPos = mpImplLB->GetEntryList()->FindEntry( rStr );
1027 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1028 nPos = sal::static_int_cast<USHORT>(nPos - mpImplLB->GetEntryList()->GetMRUCount());
1029 return nPos;
1032 // -----------------------------------------------------------------------
1034 USHORT ComboBox::GetEntryPos( const void* pData ) const
1036 USHORT nPos = mpImplLB->GetEntryList()->FindEntry( pData );
1037 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1038 nPos = sal::static_int_cast<USHORT>(nPos - mpImplLB->GetEntryList()->GetMRUCount());
1039 return nPos;
1042 // -----------------------------------------------------------------------
1044 XubString ComboBox::GetEntry( USHORT nPos ) const
1046 return mpImplLB->GetEntryList()->GetEntryText( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1049 // -----------------------------------------------------------------------
1051 USHORT ComboBox::GetEntryCount() const
1053 return mpImplLB->GetEntryList()->GetEntryCount() - mpImplLB->GetEntryList()->GetMRUCount();
1056 // -----------------------------------------------------------------------
1058 BOOL ComboBox::IsTravelSelect() const
1060 return mpImplLB->IsTravelSelect();
1063 // -----------------------------------------------------------------------
1065 BOOL ComboBox::IsInDropDown() const
1067 return mpFloatWin && mpFloatWin->IsInPopupMode();
1070 // -----------------------------------------------------------------------
1072 void ComboBox::EnableMultiSelection( BOOL bMulti )
1074 mpImplLB->EnableMultiSelection( bMulti, FALSE );
1075 mpImplLB->SetMultiSelectionSimpleMode( TRUE );
1078 // -----------------------------------------------------------------------
1080 BOOL ComboBox::IsMultiSelectionEnabled() const
1082 return mpImplLB->IsMultiSelectionEnabled();
1085 // -----------------------------------------------------------------------
1087 long ComboBox::CalcWindowSizePixel( USHORT nLines ) const
1089 return mpImplLB->GetEntryHeight() * nLines;
1092 // -----------------------------------------------------------------------
1094 Size ComboBox::GetOptimalSize(WindowSizeType eType) const
1096 switch (eType) {
1097 case WINDOWSIZE_MINIMUM:
1098 return CalcMinimumSize();
1099 default:
1100 return Edit::GetOptimalSize( eType );
1104 // -----------------------------------------------------------------------
1106 Size ComboBox::CalcMinimumSize() const
1108 Size aSz;
1109 if ( !IsDropDownBox() )
1111 aSz = mpImplLB->CalcSize( mpImplLB->GetEntryList()->GetEntryCount() );
1112 aSz.Height() += mnDDHeight;
1114 else
1116 aSz.Height() = mpImplLB->CalcSize( 1 ).Height();
1117 aSz.Width() = mpImplLB->GetMaxEntryWidth();
1118 aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1121 aSz = CalcWindowSize( aSz );
1122 return aSz;
1125 // -----------------------------------------------------------------------
1127 Size ComboBox::CalcAdjustedSize( const Size& rPrefSize ) const
1129 Size aSz = rPrefSize;
1130 sal_Int32 nLeft, nTop, nRight, nBottom;
1131 ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom );
1132 aSz.Height() -= nTop+nBottom;
1133 if ( !IsDropDownBox() )
1135 long nEntryHeight = CalcSize( 1, 1 ).Height();
1136 long nLines = aSz.Height() / nEntryHeight;
1137 if ( nLines < 1 )
1138 nLines = 1;
1139 aSz.Height() = nLines * nEntryHeight;
1140 aSz.Height() += mnDDHeight;
1142 else
1144 aSz.Height() = mnDDHeight;
1146 aSz.Height() += nTop+nBottom;
1148 aSz = CalcWindowSize( aSz );
1149 return aSz;
1152 // -----------------------------------------------------------------------
1154 Size ComboBox::CalcSize( USHORT nColumns, USHORT nLines ) const
1156 // ggf. werden ScrollBars eingeblendet
1157 Size aMinSz = CalcMinimumSize();
1158 Size aSz;
1160 // Hoehe
1161 if ( nLines )
1163 if ( !IsDropDownBox() )
1164 aSz.Height() = mpImplLB->CalcSize( nLines ).Height() + mnDDHeight;
1165 else
1166 aSz.Height() = mnDDHeight;
1168 else
1169 aSz.Height() = aMinSz.Height();
1171 // Breite
1172 if ( nColumns )
1173 aSz.Width() = nColumns * GetTextWidth( UniString( 'X' ) );
1174 else
1175 aSz.Width() = aMinSz.Width();
1177 if ( IsDropDownBox() )
1178 aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1180 if ( !IsDropDownBox() )
1182 if ( aSz.Width() < aMinSz.Width() )
1183 aSz.Height() += GetSettings().GetStyleSettings().GetScrollBarSize();
1184 if ( aSz.Height() < aMinSz.Height() )
1185 aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize();
1188 aSz = CalcWindowSize( aSz );
1189 return aSz;
1192 // -----------------------------------------------------------------------
1194 void ComboBox::GetMaxVisColumnsAndLines( USHORT& rnCols, USHORT& rnLines ) const
1196 long nCharWidth = GetTextWidth( UniString( 'x' ) );
1197 if ( !IsDropDownBox() )
1199 Size aOutSz = mpImplLB->GetMainWindow()->GetOutputSizePixel();
1200 rnCols = (USHORT)(aOutSz.Width()/nCharWidth);
1201 rnLines = (USHORT)(aOutSz.Height()/mpImplLB->GetEntryHeight());
1203 else
1205 Size aOutSz = mpSubEdit->GetOutputSizePixel();
1206 rnCols = (USHORT)(aOutSz.Width()/nCharWidth);
1207 rnLines = 1;
1211 // -----------------------------------------------------------------------
1213 void ComboBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, ULONG nFlags )
1215 mpImplLB->GetMainWindow()->ImplInitSettings( TRUE, TRUE, TRUE );
1217 Point aPos = pDev->LogicToPixel( rPos );
1218 Size aSize = pDev->LogicToPixel( rSize );
1219 Font aFont = mpImplLB->GetMainWindow()->GetDrawPixelFont( pDev );
1220 OutDevType eOutDevType = pDev->GetOutDevType();
1222 pDev->Push();
1223 pDev->SetMapMode();
1224 pDev->SetFont( aFont );
1225 pDev->SetTextFillColor();
1227 // Border/Background
1228 pDev->SetLineColor();
1229 pDev->SetFillColor();
1230 BOOL bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER);
1231 BOOL bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground();
1232 if ( bBorder || bBackground )
1234 Rectangle aRect( aPos, aSize );
1235 // aRect.Top() += nEditHeight;
1236 if ( bBorder )
1238 ImplDrawFrame( pDev, aRect );
1240 if ( bBackground )
1242 pDev->SetFillColor( GetControlBackground() );
1243 pDev->DrawRect( aRect );
1247 // Inhalt
1248 if ( !IsDropDownBox() )
1250 long nOnePixel = GetDrawPixel( pDev, 1 );
1251 long nTextHeight = pDev->GetTextHeight();
1252 long nEditHeight = nTextHeight + 6*nOnePixel;
1253 USHORT nTextStyle = TEXT_DRAW_VCENTER;
1255 // First, draw the edit part
1256 mpSubEdit->Draw( pDev, aPos, Size( aSize.Width(), nEditHeight ), nFlags );
1258 // Second, draw the listbox
1259 if ( GetStyle() & WB_CENTER )
1260 nTextStyle |= TEXT_DRAW_CENTER;
1261 else if ( GetStyle() & WB_RIGHT )
1262 nTextStyle |= TEXT_DRAW_RIGHT;
1263 else
1264 nTextStyle |= TEXT_DRAW_LEFT;
1266 if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) )
1268 pDev->SetTextColor( Color( COL_BLACK ) );
1270 else
1272 if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() )
1274 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1275 pDev->SetTextColor( rStyleSettings.GetDisableColor() );
1277 else
1279 pDev->SetTextColor( GetTextColor() );
1283 Rectangle aClip( aPos, aSize );
1284 pDev->IntersectClipRegion( aClip );
1285 USHORT nLines = (USHORT) ( (aSize.Height()-nEditHeight) / nTextHeight );
1286 if ( !nLines )
1287 nLines = 1;
1288 USHORT nTEntry = IsReallyVisible() ? mpImplLB->GetTopEntry() : 0;
1290 Rectangle aTextRect( aPos, aSize );
1292 aTextRect.Left() += 3*nOnePixel;
1293 aTextRect.Right() -= 3*nOnePixel;
1294 aTextRect.Top() += nEditHeight + nOnePixel;
1295 aTextRect.Bottom() = aTextRect.Top() + nTextHeight;
1297 // the drawing starts here
1298 for ( USHORT n = 0; n < nLines; n++ )
1300 pDev->DrawText( aTextRect, mpImplLB->GetEntryList()->GetEntryText( n+nTEntry ), nTextStyle );
1301 aTextRect.Top() += nTextHeight;
1302 aTextRect.Bottom() += nTextHeight;
1306 pDev->Pop();
1308 // Call Edit::Draw after restoring the MapMode...
1309 if ( IsDropDownBox() )
1311 mpSubEdit->Draw( pDev, rPos, rSize, nFlags );
1312 // DD-Button ?
1317 // -----------------------------------------------------------------------
1319 IMPL_LINK( ComboBox, ImplUserDrawHdl, UserDrawEvent*, pEvent )
1321 UserDraw( *pEvent );
1322 return 1;
1325 // -----------------------------------------------------------------------
1327 void ComboBox::UserDraw( const UserDrawEvent& )
1331 // -----------------------------------------------------------------------
1333 void ComboBox::SetUserItemSize( const Size& rSz )
1335 mpImplLB->GetMainWindow()->SetUserItemSize( rSz );
1338 // -----------------------------------------------------------------------
1340 const Size& ComboBox::GetUserItemSize() const
1342 return mpImplLB->GetMainWindow()->GetUserItemSize();
1345 // -----------------------------------------------------------------------
1347 void ComboBox::EnableUserDraw( BOOL bUserDraw )
1349 mpImplLB->GetMainWindow()->EnableUserDraw( bUserDraw );
1352 // -----------------------------------------------------------------------
1354 BOOL ComboBox::IsUserDrawEnabled() const
1356 return mpImplLB->GetMainWindow()->IsUserDrawEnabled();
1359 // -----------------------------------------------------------------------
1361 void ComboBox::DrawEntry( const UserDrawEvent& rEvt, BOOL bDrawImage, BOOL bDrawText, BOOL bDrawTextAtImagePos )
1363 DBG_ASSERT( rEvt.GetDevice() == mpImplLB->GetMainWindow(), "DrawEntry?!" );
1364 mpImplLB->GetMainWindow()->DrawEntry( rEvt.GetItemId(), bDrawImage, bDrawText, bDrawTextAtImagePos );
1367 // -----------------------------------------------------------------------
1369 void ComboBox::SetSeparatorPos( USHORT n )
1371 mpImplLB->SetSeparatorPos( n );
1374 // -----------------------------------------------------------------------
1376 void ComboBox::SetSeparatorPos()
1378 mpImplLB->SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND );
1381 // -----------------------------------------------------------------------
1383 USHORT ComboBox::GetSeparatorPos() const
1385 return mpImplLB->GetSeparatorPos();
1388 // -----------------------------------------------------------------------
1390 void ComboBox::SetMRUEntries( const XubString& rEntries, xub_Unicode cSep )
1392 mpImplLB->SetMRUEntries( rEntries, cSep );
1395 // -----------------------------------------------------------------------
1397 XubString ComboBox::GetMRUEntries( xub_Unicode cSep ) const
1399 return mpImplLB->GetMRUEntries( cSep );
1402 // -----------------------------------------------------------------------
1404 void ComboBox::SetMaxMRUCount( USHORT n )
1406 mpImplLB->SetMaxMRUCount( n );
1409 // -----------------------------------------------------------------------
1411 USHORT ComboBox::GetMaxMRUCount() const
1413 return mpImplLB->GetMaxMRUCount();
1416 // -----------------------------------------------------------------------
1418 USHORT ComboBox::GetDisplayLineCount() const
1420 return mpImplLB->GetDisplayLineCount();
1423 // -----------------------------------------------------------------------
1425 void ComboBox::SetEntryData( USHORT nPos, void* pNewData )
1427 mpImplLB->SetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount(), pNewData );
1430 // -----------------------------------------------------------------------
1432 void* ComboBox::GetEntryData( USHORT nPos ) const
1434 return mpImplLB->GetEntryList()->GetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1437 // -----------------------------------------------------------------------
1439 void ComboBox::SetTopEntry( USHORT nPos )
1441 mpImplLB->SetTopEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1444 // -----------------------------------------------------------------------
1446 USHORT ComboBox::GetTopEntry() const
1448 USHORT nPos = GetEntryCount() ? mpImplLB->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND;
1449 if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
1450 nPos = 0;
1451 return nPos;
1454 // -----------------------------------------------------------------------
1456 Rectangle ComboBox::GetDropDownPosSizePixel() const
1458 return mpFloatWin ? mpFloatWin->GetWindowExtentsRelative( const_cast<ComboBox*>(this) ) : Rectangle();
1461 // -----------------------------------------------------------------------
1463 Rectangle ComboBox::GetListPosSizePixel() const
1465 return mpFloatWin ? Rectangle() : mpImplLB->GetMainWindow()->GetWindowExtentsRelative( const_cast<ComboBox*>(this) );
1468 // -----------------------------------------------------------------------
1470 const Wallpaper& ComboBox::GetDisplayBackground() const
1472 if( ! mpSubEdit->IsBackground() )
1473 return Control::GetDisplayBackground();
1475 const Wallpaper& rBack = mpSubEdit->GetBackground();
1476 if( ! rBack.IsBitmap() &&
1477 ! rBack.IsGradient() &&
1478 rBack.GetColor().GetColor() == COL_TRANSPARENT
1480 return Control::GetDisplayBackground();
1481 return rBack;
1483 // -----------------------------------------------------------------------------
1484 USHORT ComboBox::GetSelectEntryCount() const
1486 return mpImplLB->GetEntryList()->GetSelectEntryCount();
1488 // -----------------------------------------------------------------------------
1489 USHORT ComboBox::GetSelectEntryPos( USHORT nIndex ) const
1491 USHORT nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( nIndex );
1492 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1494 if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() )
1495 nPos = mpImplLB->GetEntryList()->FindEntry( mpImplLB->GetEntryList()->GetEntryText( nPos ) );
1496 nPos = sal::static_int_cast<USHORT>(nPos - mpImplLB->GetEntryList()->GetMRUCount());
1498 return nPos;
1500 // -----------------------------------------------------------------------------
1501 BOOL ComboBox::IsEntryPosSelected( USHORT nPos ) const
1503 return mpImplLB->GetEntryList()->IsEntryPosSelected( nPos + mpImplLB->GetEntryList()->GetMRUCount() );
1505 // -----------------------------------------------------------------------------
1506 void ComboBox::SelectEntryPos( USHORT nPos, BOOL bSelect)
1508 if ( nPos < mpImplLB->GetEntryList()->GetEntryCount() )
1509 mpImplLB->SelectEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), bSelect );
1511 // -----------------------------------------------------------------------------
1512 void ComboBox::SetNoSelection()
1514 mpImplLB->SetNoSelection();
1515 mpSubEdit->SetText( String() );
1517 // -----------------------------------------------------------------------------
1518 Rectangle ComboBox::GetBoundingRectangle( USHORT nItem ) const
1520 Rectangle aRect = mpImplLB->GetMainWindow()->GetBoundingRectangle( nItem );
1521 Rectangle aOffset = mpImplLB->GetMainWindow()->GetWindowExtentsRelative( (Window*)this );
1522 aRect.Move( aOffset.TopLeft().X(), aOffset.TopLeft().Y() );
1523 return aRect;
1525 // -----------------------------------------------------------------------------
1527 void ComboBox::SetBorderStyle( USHORT nBorderStyle )
1529 Window::SetBorderStyle( nBorderStyle );
1530 if ( !IsDropDownBox() )
1532 mpSubEdit->SetBorderStyle( nBorderStyle );
1533 mpImplLB->SetBorderStyle( nBorderStyle );
1536 // -----------------------------------------------------------------------------
1538 long ComboBox::GetIndexForPoint( const Point& rPoint, USHORT& rPos ) const
1540 if( ! mpLayoutData )
1541 FillLayoutData();
1543 // check whether rPoint fits at all
1544 long nIndex = Control::GetIndexForPoint( rPoint );
1545 if( nIndex != -1 )
1547 // point must be either in main list window
1548 // or in impl window (dropdown case)
1549 ImplListBoxWindow* pMain = mpImplLB->GetMainWindow();
1551 // convert coordinates to ImplListBoxWindow pixel coordinate space
1552 Point aConvPoint = LogicToPixel( rPoint );
1553 aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
1554 aConvPoint = pMain->AbsoluteScreenToOutputPixel( aConvPoint );
1555 aConvPoint = pMain->PixelToLogic( aConvPoint );
1557 // try to find entry
1558 USHORT nEntry = pMain->GetEntryPosForPoint( aConvPoint );
1559 if( nEntry == LISTBOX_ENTRY_NOTFOUND )
1560 nIndex = -1;
1561 else
1562 rPos = nEntry;
1565 // get line relative index
1566 if( nIndex != -1 )
1567 nIndex = ToRelativeLineIndex( nIndex );
1569 return nIndex;