| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #include <tools/table.hxx> |
| #include <tools/debug.hxx> |
| #include <tools/rc.h> |
| |
| #include <vcl/decoview.hxx> |
| #include <vcl/lstbox.h> |
| #include <vcl/button.hxx> |
| #include <vcl/event.hxx> |
| #include <vcl/combobox.hxx> |
| |
| #include <svdata.hxx> |
| #include <subedit.hxx> |
| #include <ilstbox.hxx> |
| #include <controldata.hxx> |
| |
| // ======================================================================= |
| |
| inline sal_uLong ImplCreateKey( sal_uInt16 nPos ) |
| { |
| // Key = Pos+1, wegen Pos 0 |
| return nPos+1; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| static void lcl_GetSelectedEntries( Table& rSelectedPos, const XubString& rText, xub_Unicode cTokenSep, const ImplEntryList* pEntryList ) |
| { |
| for( xub_StrLen n = rText.GetTokenCount( cTokenSep ); n; ) |
| { |
| XubString aToken = rText.GetToken( --n, cTokenSep ); |
| aToken.EraseLeadingAndTrailingChars( ' ' ); |
| sal_uInt16 nPos = pEntryList->FindEntry( aToken ); |
| if ( nPos != LISTBOX_ENTRY_NOTFOUND ) |
| rSelectedPos.Insert( ImplCreateKey( nPos ), (void*)sal_IntPtr(1L) ); |
| } |
| } |
| |
| // ======================================================================= |
| |
| ComboBox::ComboBox( WindowType nType ) : |
| Edit( nType ) |
| { |
| ImplInitComboBoxData(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| ComboBox::ComboBox( Window* pParent, WinBits nStyle ) : |
| Edit( WINDOW_COMBOBOX ) |
| { |
| ImplInitComboBoxData(); |
| ImplInit( pParent, nStyle ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| ComboBox::ComboBox( Window* pParent, const ResId& rResId ) : |
| Edit( WINDOW_COMBOBOX ) |
| { |
| ImplInitComboBoxData(); |
| rResId.SetRT( RSC_COMBOBOX ); |
| WinBits nStyle = ImplInitRes( rResId ); |
| ImplInit( pParent, nStyle ); |
| ImplLoadRes( rResId ); |
| |
| if ( !(nStyle & WB_HIDE ) ) |
| Show(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| ComboBox::~ComboBox() |
| { |
| SetSubEdit( NULL ); |
| delete mpSubEdit; |
| |
| delete mpImplLB; |
| mpImplLB = NULL; |
| |
| delete mpFloatWin; |
| delete mpBtn; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::ImplInitComboBoxData() |
| { |
| mpSubEdit = NULL; |
| mpBtn = NULL; |
| mpImplLB = NULL; |
| mpFloatWin = NULL; |
| |
| mnDDHeight = 0; |
| mbDDAutoSize = sal_True; |
| mbSyntheticModify = sal_False; |
| mbMatchCase = sal_False; |
| mcMultiSep = ';'; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::ImplCalcEditHeight() |
| { |
| sal_Int32 nLeft, nTop, nRight, nBottom; |
| GetBorder( nLeft, nTop, nRight, nBottom ); |
| mnDDHeight = (sal_uInt16)(mpSubEdit->GetTextHeight() + nTop + nBottom + 4); |
| if ( !IsDropDownBox() ) |
| mnDDHeight += 4; |
| |
| Rectangle aCtrlRegion( Point( 0, 0 ), Size( 10, 10 ) ); |
| Rectangle aBoundRegion, aContentRegion; |
| ImplControlValue aControlValue; |
| ControlType aType = IsDropDownBox() ? CTRL_COMBOBOX : CTRL_EDITBOX; |
| if( GetNativeControlRegion( aType, PART_ENTIRE_CONTROL, |
| aCtrlRegion, |
| CTRL_STATE_ENABLED, |
| aControlValue, rtl::OUString(), |
| aBoundRegion, aContentRegion ) ) |
| { |
| const long nNCHeight = aBoundRegion.GetHeight(); |
| if( mnDDHeight < nNCHeight ) |
| mnDDHeight = sal::static_int_cast<sal_uInt16>( nNCHeight ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::ImplInit( Window* pParent, WinBits nStyle ) |
| { |
| ImplInitStyle( nStyle ); |
| |
| sal_Bool bNoBorder = ( nStyle & WB_NOBORDER ) ? sal_True : sal_False; |
| if ( !(nStyle & WB_DROPDOWN) ) |
| { |
| nStyle &= ~WB_BORDER; |
| nStyle |= WB_NOBORDER; |
| } |
| else |
| { |
| if ( !bNoBorder ) |
| nStyle |= WB_BORDER; |
| } |
| |
| Edit::ImplInit( pParent, nStyle ); |
| SetBackground(); |
| |
| // DropDown ? |
| WinBits nEditStyle = nStyle & ( WB_LEFT | WB_RIGHT | WB_CENTER ); |
| WinBits nListStyle = nStyle; |
| if( nStyle & WB_DROPDOWN ) |
| { |
| mpFloatWin = new ImplListBoxFloatingWindow( this ); |
| mpFloatWin->SetAutoWidth( sal_True ); |
| mpFloatWin->SetPopupModeEndHdl( LINK( this, ComboBox, ImplPopupModeEndHdl ) ); |
| |
| mpBtn = new ImplBtn( this, WB_NOLIGHTBORDER | WB_RECTSTYLE ); |
| ImplInitDropDownButton( mpBtn ); |
| mpBtn->SetMBDownHdl( LINK( this, ComboBox, ImplClickBtnHdl ) ); |
| mpBtn->Show(); |
| |
| nEditStyle |= WB_NOBORDER; |
| nListStyle &= ~WB_BORDER; |
| nListStyle |= WB_NOBORDER; |
| } |
| else |
| { |
| if ( !bNoBorder ) |
| { |
| nEditStyle |= WB_BORDER; |
| nListStyle &= ~WB_NOBORDER; |
| nListStyle |= WB_BORDER; |
| } |
| } |
| |
| mpSubEdit = new Edit( this, nEditStyle ); |
| mpSubEdit->EnableRTL( sal_False ); |
| SetSubEdit( mpSubEdit ); |
| mpSubEdit->SetPosPixel( Point() ); |
| EnableAutocomplete( sal_True ); |
| mpSubEdit->Show(); |
| |
| Window* pLBParent = this; |
| if ( mpFloatWin ) |
| pLBParent = mpFloatWin; |
| mpImplLB = new ImplListBox( pLBParent, nListStyle|WB_SIMPLEMODE ); |
| mpImplLB->SetPosPixel( Point() ); |
| mpImplLB->SetSelectHdl( LINK( this, ComboBox, ImplSelectHdl ) ); |
| mpImplLB->SetCancelHdl( LINK( this, ComboBox, ImplCancelHdl ) ); |
| mpImplLB->SetDoubleClickHdl( LINK( this, ComboBox, ImplDoubleClickHdl ) ); |
| mpImplLB->SetUserDrawHdl( LINK( this, ComboBox, ImplUserDrawHdl ) ); |
| mpImplLB->SetSelectionChangedHdl( LINK( this, ComboBox, ImplSelectionChangedHdl ) ); |
| //IAccessibility2 Implementation 2009----- |
| mpImplLB->SetListItemSelectHdl( LINK( this, ComboBox, ImplListItemSelectHdl ) ); |
| //-----IAccessibility2 Implementation 2009 |
| mpImplLB->Show(); |
| |
| if ( mpFloatWin ) |
| mpFloatWin->SetImplListBox( mpImplLB ); |
| else |
| mpImplLB->GetMainWindow()->AllowGrabFocus( sal_True ); |
| |
| ImplCalcEditHeight(); |
| |
| SetCompoundControl( sal_True ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| WinBits ComboBox::ImplInitStyle( WinBits nStyle ) |
| { |
| if ( !(nStyle & WB_NOTABSTOP) ) |
| nStyle |= WB_TABSTOP; |
| if ( !(nStyle & WB_NOGROUP) ) |
| nStyle |= WB_GROUP; |
| return nStyle; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::ImplLoadRes( const ResId& rResId ) |
| { |
| Edit::ImplLoadRes( rResId ); |
| |
| sal_uLong nNumber = ReadLongRes(); |
| |
| if( nNumber ) |
| { |
| for( sal_uInt16 i = 0; i < nNumber; i++ ) |
| { |
| InsertEntry( ReadStringRes(), LISTBOX_APPEND ); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::EnableAutocomplete( sal_Bool bEnable, sal_Bool bMatchCase ) |
| { |
| mbMatchCase = bMatchCase; |
| |
| if ( bEnable ) |
| mpSubEdit->SetAutocompleteHdl( LINK( this, ComboBox, ImplAutocompleteHdl ) ); |
| else |
| mpSubEdit->SetAutocompleteHdl( Link() ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ComboBox::IsAutocompleteEnabled() const |
| { |
| return mpSubEdit->GetAutocompleteHdl().IsSet(); |
| } |
| //IAccessibility2 Implementation 2009----- |
| void ComboBox::SetMpSubEditAccessibleName(String &aName) |
| { |
| if(mpSubEdit!=NULL) |
| mpSubEdit->SetAccessibleName(aName); |
| } |
| //-----IAccessibility2 Implementation 2009 |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( ComboBox, ImplClickBtnHdl, void*, EMPTYARG ) |
| { |
| ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN ); |
| mpSubEdit->GrabFocus(); |
| if ( !mpImplLB->GetEntryList()->GetMRUCount() ) |
| ImplUpdateFloatSelection(); |
| else |
| mpImplLB->SelectEntry( 0 , sal_True ); |
| mpBtn->SetPressed( sal_True ); |
| SetSelection( Selection( 0, SELECTION_MAX ) ); |
| mpFloatWin->StartFloat( sal_True ); |
| ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN ); |
| |
| ImplClearLayoutData(); |
| if( mpImplLB ) |
| mpImplLB->GetMainWindow()->ImplClearLayoutData(); |
| |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( ComboBox, ImplPopupModeEndHdl, void*, EMPTYARG ) |
| { |
| if( mpFloatWin->IsPopupModeCanceled() ) |
| { |
| if ( !mpImplLB->GetEntryList()->IsEntryPosSelected( mpFloatWin->GetPopupModeStartSaveSelection() ) ) |
| { |
| mpImplLB->SelectEntry( mpFloatWin->GetPopupModeStartSaveSelection(), sal_True ); |
| sal_Bool bTravelSelect = mpImplLB->IsTravelSelect(); |
| mpImplLB->SetTravelSelect( sal_True ); |
| Select(); |
| mpImplLB->SetTravelSelect( bTravelSelect ); |
| } |
| } |
| |
| ImplClearLayoutData(); |
| if( mpImplLB ) |
| mpImplLB->GetMainWindow()->ImplClearLayoutData(); |
| |
| mpBtn->SetPressed( sal_False ); |
| ImplCallEventListeners( VCLEVENT_DROPDOWN_CLOSE ); |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( ComboBox, ImplAutocompleteHdl, Edit*, pEdit ) |
| { |
| Selection aSel = pEdit->GetSelection(); |
| AutocompleteAction eAction = pEdit->GetAutocompleteAction(); |
| |
| /* If there is no current selection do not auto complete on |
| Tab/Shift-Tab since then we would not cycle to the next field. |
| */ |
| if ( aSel.Len() || |
| ((eAction != AUTOCOMPLETE_TABFORWARD) && (eAction != AUTOCOMPLETE_TABBACKWARD)) ) |
| { |
| XubString aFullText = pEdit->GetText(); |
| XubString aStartText = aFullText.Copy( 0, (xub_StrLen)aSel.Max() ); |
| sal_uInt16 nStart = mpImplLB->GetCurrentPos(); |
| |
| if ( nStart == LISTBOX_ENTRY_NOTFOUND ) |
| nStart = 0; |
| |
| sal_Bool bForward = sal_True; |
| if ( eAction == AUTOCOMPLETE_TABFORWARD ) |
| nStart++; |
| else if ( eAction == AUTOCOMPLETE_TABBACKWARD ) |
| { |
| bForward = sal_False; |
| nStart = nStart ? nStart - 1 : mpImplLB->GetEntryList()->GetEntryCount()-1; |
| } |
| |
| sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND; |
| if( ! mbMatchCase ) |
| { |
| // Try match case insensitive from current position |
| nPos = mpImplLB->GetEntryList()->FindMatchingEntry( aStartText, nStart, bForward, sal_True ); |
| if ( nPos == LISTBOX_ENTRY_NOTFOUND ) |
| // Try match case insensitive, but from start |
| nPos = mpImplLB->GetEntryList()->FindMatchingEntry( aStartText, bForward ? 0 : (mpImplLB->GetEntryList()->GetEntryCount()-1), bForward, sal_True ); |
| } |
| |
| if ( nPos == LISTBOX_ENTRY_NOTFOUND ) |
| // Try match full from current position |
| nPos = mpImplLB->GetEntryList()->FindMatchingEntry( aStartText, nStart, bForward, sal_False ); |
| if ( nPos == LISTBOX_ENTRY_NOTFOUND ) |
| // Match full, but from start |
| nPos = mpImplLB->GetEntryList()->FindMatchingEntry( aStartText, bForward ? 0 : (mpImplLB->GetEntryList()->GetEntryCount()-1), bForward, sal_False ); |
| |
| if ( nPos != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| XubString aText = mpImplLB->GetEntryList()->GetEntryText( nPos ); |
| Selection aSelection( aText.Len(), aStartText.Len() ); |
| pEdit->SetText( aText, aSelection ); |
| } |
| } |
| |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( ComboBox, ImplSelectHdl, void*, EMPTYARG ) |
| { |
| sal_Bool bPopup = IsInDropDown(); |
| sal_Bool bCallSelect = sal_False; |
| if ( mpImplLB->IsSelectionChanged() || bPopup ) |
| { |
| XubString aText; |
| if ( IsMultiSelectionEnabled() ) |
| { |
| aText = mpSubEdit->GetText(); |
| |
| // Alle Eintraege entfernen, zu denen es einen Entry gibt, der aber nicht selektiert ist. |
| xub_StrLen nIndex = 0; |
| while ( nIndex != STRING_NOTFOUND ) |
| { |
| xub_StrLen nPrevIndex = nIndex; |
| XubString aToken = aText.GetToken( 0, mcMultiSep, nIndex ); |
| xub_StrLen nTokenLen = aToken.Len(); |
| aToken.EraseLeadingAndTrailingChars( ' ' ); |
| sal_uInt16 nP = mpImplLB->GetEntryList()->FindEntry( aToken ); |
| if ( (nP != LISTBOX_ENTRY_NOTFOUND) && (!mpImplLB->GetEntryList()->IsEntryPosSelected( nP )) ) |
| { |
| aText.Erase( nPrevIndex, nTokenLen ); |
| nIndex = sal::static_int_cast<xub_StrLen>(nIndex - nTokenLen); |
| if ( (nPrevIndex < aText.Len()) && (aText.GetChar( nPrevIndex ) == mcMultiSep) ) |
| { |
| aText.Erase( nPrevIndex, 1 ); |
| nIndex--; |
| } |
| } |
| aText.EraseLeadingAndTrailingChars( ' ' ); |
| } |
| |
| // Fehlende Eintraege anhaengen... |
| Table aSelInText; |
| lcl_GetSelectedEntries( aSelInText, aText, mcMultiSep, mpImplLB->GetEntryList() ); |
| sal_uInt16 nSelectedEntries = mpImplLB->GetEntryList()->GetSelectEntryCount(); |
| for ( sal_uInt16 n = 0; n < nSelectedEntries; n++ ) |
| { |
| sal_uInt16 nP = mpImplLB->GetEntryList()->GetSelectEntryPos( n ); |
| if ( !aSelInText.IsKeyValid( ImplCreateKey( nP ) ) ) |
| { |
| if ( aText.Len() && (aText.GetChar( aText.Len()-1 ) != mcMultiSep) ) |
| aText += mcMultiSep; |
| if ( aText.Len() ) |
| aText += ' '; // etwas auflockern |
| aText += mpImplLB->GetEntryList()->GetEntryText( nP ); |
| aText += mcMultiSep; |
| } |
| } |
| if ( aText.Len() && (aText.GetChar( aText.Len()-1 ) == mcMultiSep) ) |
| aText.Erase( aText.Len()-1, 1 ); |
| } |
| else |
| { |
| aText = mpImplLB->GetEntryList()->GetSelectEntry( 0 ); |
| } |
| |
| mpSubEdit->SetText( aText ); |
| |
| Selection aNewSelection( 0, aText.Len() ); |
| if ( IsMultiSelectionEnabled() ) |
| aNewSelection.Min() = aText.Len(); |
| mpSubEdit->SetSelection( aNewSelection ); |
| |
| bCallSelect = sal_True; |
| } |
| |
| // #84652# Call GrabFocus and EndPopupMode before calling Select/Modify, but after changing the text |
| |
| if ( bPopup && !mpImplLB->IsTravelSelect() && |
| ( !IsMultiSelectionEnabled() || !mpImplLB->GetSelectModifier() ) ) |
| { |
| mpFloatWin->EndPopupMode(); |
| GrabFocus(); |
| } |
| |
| if ( bCallSelect ) |
| { |
| mpSubEdit->SetModifyFlag(); |
| mbSyntheticModify = sal_True; |
| Modify(); |
| mbSyntheticModify = sal_False; |
| Select(); |
| } |
| |
| return 0; |
| } |
| //IAccessibility2 Implementation 2009----- |
| IMPL_LINK( ComboBox, ImplListItemSelectHdl, void*, EMPTYARG ) |
| { |
| ImplCallEventListeners( VCLEVENT_LISTBOX_SELECT ); |
| return 1; |
| } |
| //-----IAccessibility2 Implementation 2009 |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( ComboBox, ImplCancelHdl, void*, EMPTYARG ) |
| { |
| if( IsInDropDown() ) |
| mpFloatWin->EndPopupMode(); |
| |
| return 1; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( ComboBox, ImplSelectionChangedHdl, void*, n ) |
| { |
| if ( !mpImplLB->IsTrackingSelect() ) |
| { |
| sal_uInt16 nChanged = (sal_uInt16)(sal_uLong)n; |
| if ( !mpSubEdit->IsReadOnly() && mpImplLB->GetEntryList()->IsEntryPosSelected( nChanged ) ) |
| mpSubEdit->SetText( mpImplLB->GetEntryList()->GetEntryText( nChanged ) ); |
| } |
| return 1; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( ComboBox, ImplDoubleClickHdl, void*, EMPTYARG ) |
| { |
| DoubleClick(); |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::ToggleDropDown() |
| { |
| if( IsDropDownBox() ) |
| { |
| if( mpFloatWin->IsInPopupMode() ) |
| mpFloatWin->EndPopupMode(); |
| else |
| { |
| mpSubEdit->GrabFocus(); |
| if ( !mpImplLB->GetEntryList()->GetMRUCount() ) |
| ImplUpdateFloatSelection(); |
| else |
| mpImplLB->SelectEntry( 0 , sal_True ); |
| ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN ); |
| mpBtn->SetPressed( sal_True ); |
| SetSelection( Selection( 0, SELECTION_MAX ) ); |
| mpFloatWin->StartFloat( sal_True ); |
| ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN ); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::Select() |
| { |
| ImplCallEventListenersAndHandler( VCLEVENT_COMBOBOX_SELECT, maSelectHdl, this ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::DoubleClick() |
| { |
| ImplCallEventListenersAndHandler( VCLEVENT_COMBOBOX_DOUBLECLICK, maDoubleClickHdl, this ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::EnableAutoSize( sal_Bool bAuto ) |
| { |
| mbDDAutoSize = bAuto; |
| if ( mpFloatWin ) |
| { |
| if ( bAuto && !mpFloatWin->GetDropDownLineCount() ) |
| { |
| // Adapt to GetListBoxMaximumLineCount here; was on fixed number of five before |
| AdaptDropDownLineCountToMaximum(); |
| } |
| else if ( !bAuto ) |
| { |
| mpFloatWin->SetDropDownLineCount( 0 ); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::EnableDDAutoWidth( sal_Bool b ) |
| { |
| if ( mpFloatWin ) |
| mpFloatWin->SetAutoWidth( b ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ComboBox::IsDDAutoWidthEnabled() const |
| { |
| return mpFloatWin ? mpFloatWin->IsAutoWidth() : sal_False; |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::SetDropDownLineCount( sal_uInt16 nLines ) |
| { |
| if ( mpFloatWin ) |
| mpFloatWin->SetDropDownLineCount( nLines ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::AdaptDropDownLineCountToMaximum() |
| { |
| // adapt to maximum allowed number |
| SetDropDownLineCount(std::min(GetEntryCount(), GetSettings().GetStyleSettings().GetListBoxMaximumLineCount())); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ComboBox::GetDropDownLineCount() const |
| { |
| sal_uInt16 nLines = 0; |
| if ( mpFloatWin ) |
| nLines = mpFloatWin->GetDropDownLineCount(); |
| return nLines; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::SetPosSizePixel( long nX, long nY, long nWidth, long nHeight, |
| sal_uInt16 nFlags ) |
| { |
| if( IsDropDownBox() && ( nFlags & WINDOW_POSSIZE_SIZE ) ) |
| { |
| Size aPrefSz = mpFloatWin->GetPrefSize(); |
| if ( ( nFlags & WINDOW_POSSIZE_HEIGHT ) && ( nHeight >= 2*mnDDHeight ) ) |
| aPrefSz.Height() = nHeight-mnDDHeight; |
| if ( nFlags & WINDOW_POSSIZE_WIDTH ) |
| aPrefSz.Width() = nWidth; |
| mpFloatWin->SetPrefSize( aPrefSz ); |
| |
| if ( IsAutoSizeEnabled() && ! (nFlags & WINDOW_POSSIZE_DROPDOWN) ) |
| nHeight = mnDDHeight; |
| } |
| |
| Edit::SetPosSizePixel( nX, nY, nWidth, nHeight, nFlags ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::Resize() |
| { |
| Control::Resize(); |
| |
| Size aOutSz = GetOutputSizePixel(); |
| if( IsDropDownBox() ) |
| { |
| long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize(); |
| long nTop = 0; |
| long nBottom = aOutSz.Height(); |
| |
| Window *pBorder = GetWindow( WINDOW_BORDER ); |
| ImplControlValue aControlValue; |
| Point aPoint; |
| Rectangle aContent, aBound; |
| |
| // use the full extent of the control |
| Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() ); |
| |
| if ( GetNativeControlRegion(CTRL_COMBOBOX, PART_BUTTON_DOWN, |
| aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) ) |
| { |
| // convert back from border space to local coordinates |
| aPoint = pBorder->ScreenToOutputPixel( OutputToScreenPixel( aPoint ) ); |
| aContent.Move(-aPoint.X(), -aPoint.Y()); |
| |
| mpBtn->SetPosSizePixel( aContent.Left(), nTop, aContent.getWidth(), (nBottom-nTop) ); |
| |
| // adjust the size of the edit field |
| if ( GetNativeControlRegion(CTRL_COMBOBOX, PART_SUB_EDIT, |
| aArea, 0, aControlValue, rtl::OUString(), aBound, aContent) ) |
| { |
| // convert back from border space to local coordinates |
| aContent.Move(-aPoint.X(), -aPoint.Y()); |
| |
| // use the themes drop down size |
| mpSubEdit->SetPosSizePixel( aContent.TopLeft(), aContent.GetSize() ); |
| } |
| else |
| { |
| // use the themes drop down size for the button |
| aOutSz.Width() -= aContent.getWidth(); |
| mpSubEdit->SetSizePixel( aOutSz ); |
| } |
| } |
| else |
| { |
| nSBWidth = CalcZoom( nSBWidth ); |
| mpSubEdit->SetPosSizePixel( Point( 0, 0 ), Size( aOutSz.Width() - nSBWidth, aOutSz.Height() ) ); |
| mpBtn->SetPosSizePixel( aOutSz.Width() - nSBWidth, nTop, nSBWidth, (nBottom-nTop) ); |
| } |
| } |
| else |
| { |
| mpSubEdit->SetSizePixel( Size( aOutSz.Width(), mnDDHeight ) ); |
| mpImplLB->SetPosSizePixel( 0, mnDDHeight, aOutSz.Width(), aOutSz.Height() - mnDDHeight ); |
| if ( GetText().Len() ) |
| ImplUpdateFloatSelection(); |
| } |
| |
| // FloatingWindow-Groesse auch im unsichtbare Zustand auf Stand halten, |
| // weil KEY_PGUP/DOWN ausgewertet wird... |
| if ( mpFloatWin ) |
| mpFloatWin->SetSizePixel( mpFloatWin->CalcFloatSize() ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::FillLayoutData() const |
| { |
| mpControlData->mpLayoutData = new vcl::ControlLayoutData(); |
| AppendLayoutData( *mpSubEdit ); |
| mpSubEdit->SetLayoutDataParent( this ); |
| Control* pMainWindow = mpImplLB->GetMainWindow(); |
| if( mpFloatWin ) |
| { |
| // dropdown mode |
| if( mpFloatWin->IsReallyVisible() ) |
| { |
| AppendLayoutData( *pMainWindow ); |
| pMainWindow->SetLayoutDataParent( this ); |
| } |
| } |
| else |
| { |
| AppendLayoutData( *pMainWindow ); |
| pMainWindow->SetLayoutDataParent( this ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::StateChanged( StateChangedType nType ) |
| { |
| Edit::StateChanged( nType ); |
| |
| if ( nType == STATE_CHANGE_READONLY ) |
| { |
| mpImplLB->SetReadOnly( IsReadOnly() ); |
| if ( mpBtn ) |
| mpBtn->Enable( IsEnabled() && !IsReadOnly() ); |
| } |
| else if ( nType == STATE_CHANGE_ENABLE ) |
| { |
| mpSubEdit->Enable( IsEnabled() ); |
| mpImplLB->Enable( IsEnabled() && !IsReadOnly() ); |
| if ( mpBtn ) |
| mpBtn->Enable( IsEnabled() && !IsReadOnly() ); |
| Invalidate(); |
| } |
| else if( nType == STATE_CHANGE_UPDATEMODE ) |
| { |
| mpImplLB->SetUpdateMode( IsUpdateMode() ); |
| } |
| else if ( nType == STATE_CHANGE_ZOOM ) |
| { |
| mpImplLB->SetZoom( GetZoom() ); |
| mpSubEdit->SetZoom( GetZoom() ); |
| ImplCalcEditHeight(); |
| Resize(); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLFONT ) |
| { |
| mpImplLB->SetControlFont( GetControlFont() ); |
| mpSubEdit->SetControlFont( GetControlFont() ); |
| ImplCalcEditHeight(); |
| Resize(); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) |
| { |
| mpImplLB->SetControlForeground( GetControlForeground() ); |
| mpSubEdit->SetControlForeground( GetControlForeground() ); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) |
| { |
| mpImplLB->SetControlBackground( GetControlBackground() ); |
| mpSubEdit->SetControlBackground( GetControlBackground() ); |
| } |
| else if ( nType == STATE_CHANGE_STYLE ) |
| { |
| SetStyle( ImplInitStyle( GetStyle() ) ); |
| mpImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) ? sal_True : sal_False ); |
| } |
| else if( nType == STATE_CHANGE_MIRRORING ) |
| { |
| if( mpBtn ) |
| { |
| mpBtn->EnableRTL( IsRTLEnabled() ); |
| ImplInitDropDownButton( mpBtn ); |
| } |
| mpSubEdit->StateChanged( STATE_CHANGE_MIRRORING ); |
| mpImplLB->EnableRTL( IsRTLEnabled() ); |
| Resize(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::DataChanged( const DataChangedEvent& rDCEvt ) |
| { |
| Control::DataChanged( rDCEvt ); |
| |
| if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || |
| (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || |
| ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && |
| (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) |
| { |
| if ( mpBtn ) |
| { |
| mpBtn->SetSettings( GetSettings() ); |
| ImplInitDropDownButton( mpBtn ); |
| } |
| Resize(); |
| mpImplLB->Resize(); // Wird nicht durch ComboBox::Resize() gerufen, wenn sich die ImplLB nicht aendert. |
| SetBackground(); // due to a hack in Window::UpdateSettings the background must be reset |
| // otherwise it will overpaint NWF drawn comboboxes |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long ComboBox::PreNotify( NotifyEvent& rNEvt ) |
| { |
| |
| return Edit::PreNotify( rNEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long ComboBox::Notify( NotifyEvent& rNEvt ) |
| { |
| long nDone = 0; |
| if( ( rNEvt.GetType() == EVENT_KEYINPUT ) && ( rNEvt.GetWindow() == mpSubEdit ) |
| && !IsReadOnly() ) |
| { |
| KeyEvent aKeyEvt = *rNEvt.GetKeyEvent(); |
| sal_uInt16 nKeyCode = aKeyEvt.GetKeyCode().GetCode(); |
| switch( nKeyCode ) |
| { |
| case KEY_UP: |
| case KEY_DOWN: |
| case KEY_PAGEUP: |
| case KEY_PAGEDOWN: |
| { |
| ImplUpdateFloatSelection(); |
| if( ( nKeyCode == KEY_DOWN ) && mpFloatWin && !mpFloatWin->IsInPopupMode() && aKeyEvt.GetKeyCode().IsMod2() ) |
| { |
| ImplCallEventListeners( VCLEVENT_DROPDOWN_PRE_OPEN ); |
| mpBtn->SetPressed( sal_True ); |
| if ( mpImplLB->GetEntryList()->GetMRUCount() ) |
| mpImplLB->SelectEntry( 0 , sal_True ); |
| SetSelection( Selection( 0, SELECTION_MAX ) ); |
| mpFloatWin->StartFloat( sal_False ); |
| ImplCallEventListeners( VCLEVENT_DROPDOWN_OPEN ); |
| nDone = 1; |
| } |
| else if( ( nKeyCode == KEY_UP ) && mpFloatWin && mpFloatWin->IsInPopupMode() && aKeyEvt.GetKeyCode().IsMod2() ) |
| { |
| mpFloatWin->EndPopupMode(); |
| nDone = 1; |
| } |
| else |
| { |
| nDone = mpImplLB->ProcessKeyInput( aKeyEvt ); |
| } |
| } |
| break; |
| |
| case KEY_RETURN: |
| { |
| if( ( rNEvt.GetWindow() == mpSubEdit ) && IsInDropDown() ) |
| { |
| mpImplLB->ProcessKeyInput( aKeyEvt ); |
| nDone = 1; |
| } |
| } |
| break; |
| } |
| } |
| else if ( (rNEvt.GetType() == EVENT_LOSEFOCUS) && mpFloatWin ) |
| { |
| if( mpFloatWin->HasChildPathFocus() ) |
| mpSubEdit->GrabFocus(); |
| else if ( mpFloatWin->IsInPopupMode() && !HasChildPathFocus( sal_True ) ) |
| mpFloatWin->EndPopupMode(); |
| } |
| else if( (rNEvt.GetType() == EVENT_COMMAND) && |
| (rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL) && |
| (rNEvt.GetWindow() == mpSubEdit) ) |
| { |
| sal_uInt16 nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() ); |
| if ( ( nWheelBehavior == MOUSE_WHEEL_ALWAYS ) |
| || ( ( nWheelBehavior == MOUSE_WHEEL_FOCUS_ONLY ) |
| && HasChildPathFocus() |
| ) |
| ) |
| { |
| nDone = mpImplLB->HandleWheelAsCursorTravel( *rNEvt.GetCommandEvent() ); |
| } |
| else |
| { |
| nDone = 0; // don't eat this event, let the default handling happen (i.e. scroll the context) |
| } |
| } |
| else if( ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN ) && ( rNEvt.GetWindow() == mpImplLB->GetMainWindow() ) ) |
| { |
| mpSubEdit->GrabFocus(); |
| } |
| |
| return nDone ? nDone : Edit::Notify( rNEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::SetText( const XubString& rStr ) |
| { |
| ImplCallEventListeners( VCLEVENT_COMBOBOX_SETTEXT ); |
| |
| Edit::SetText( rStr ); |
| ImplUpdateFloatSelection(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::SetText( const XubString& rStr, const Selection& rNewSelection ) |
| { |
| ImplCallEventListeners( VCLEVENT_COMBOBOX_SETTEXT ); |
| |
| Edit::SetText( rStr, rNewSelection ); |
| ImplUpdateFloatSelection(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::Modify() |
| { |
| if ( !mbSyntheticModify ) |
| ImplUpdateFloatSelection(); |
| |
| Edit::Modify(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::ImplUpdateFloatSelection() |
| { |
| // Text in der ListBox in den sichtbaren Bereich bringen |
| mpImplLB->SetCallSelectionChangedHdl( sal_False ); |
| if ( !IsMultiSelectionEnabled() ) |
| { |
| XubString aSearchStr( mpSubEdit->GetText() ); |
| sal_uInt16 nSelect = LISTBOX_ENTRY_NOTFOUND; |
| sal_Bool bSelect = sal_True; |
| |
| if ( mpImplLB->GetCurrentPos() != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| XubString aCurrent = mpImplLB->GetEntryList()->GetEntryText( mpImplLB->GetCurrentPos() ); |
| if ( aCurrent == aSearchStr ) |
| nSelect = mpImplLB->GetCurrentPos(); |
| } |
| |
| if ( nSelect == LISTBOX_ENTRY_NOTFOUND ) |
| nSelect = mpImplLB->GetEntryList()->FindEntry( aSearchStr ); |
| if ( nSelect == LISTBOX_ENTRY_NOTFOUND ) |
| { |
| nSelect = mpImplLB->GetEntryList()->FindMatchingEntry( aSearchStr ); |
| bSelect = sal_False; |
| } |
| |
| if( nSelect != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| if ( !mpImplLB->IsVisible( nSelect ) ) |
| mpImplLB->ShowProminentEntry( nSelect ); |
| mpImplLB->SelectEntry( nSelect, bSelect ); |
| } |
| else |
| { |
| nSelect = mpImplLB->GetEntryList()->GetSelectEntryPos( 0 ); |
| if( nSelect != LISTBOX_ENTRY_NOTFOUND ) |
| mpImplLB->SelectEntry( nSelect, sal_False ); |
| mpImplLB->ResetCurrentPos(); |
| } |
| } |
| else |
| { |
| Table aSelInText; |
| lcl_GetSelectedEntries( aSelInText, mpSubEdit->GetText(), mcMultiSep, mpImplLB->GetEntryList() ); |
| for ( sal_uInt16 n = 0; n < mpImplLB->GetEntryList()->GetEntryCount(); n++ ) |
| mpImplLB->SelectEntry( n, aSelInText.IsKeyValid( ImplCreateKey( n ) ) ); |
| } |
| mpImplLB->SetCallSelectionChangedHdl( sal_True ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ComboBox::InsertEntry( const XubString& rStr, sal_uInt16 nPos ) |
| { |
| sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr ); |
| nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount()); |
| CallEventListeners( VCLEVENT_COMBOBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) ); |
| return nRealPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ComboBox::InsertEntry( const XubString& rStr, const Image& rImage, sal_uInt16 nPos ) |
| { |
| sal_uInt16 nRealPos = mpImplLB->InsertEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), rStr, rImage ); |
| nRealPos = sal::static_int_cast<sal_uInt16>(nRealPos - mpImplLB->GetEntryList()->GetMRUCount()); |
| CallEventListeners( VCLEVENT_COMBOBOX_ITEMADDED, (void*) sal_IntPtr(nRealPos) ); |
| return nRealPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::RemoveEntry( const XubString& rStr ) |
| { |
| RemoveEntry( GetEntryPos( rStr ) ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::RemoveEntry( sal_uInt16 nPos ) |
| { |
| mpImplLB->RemoveEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); |
| CallEventListeners( VCLEVENT_COMBOBOX_ITEMREMOVED, (void*) sal_IntPtr(nPos) ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::Clear() |
| { |
| mpImplLB->Clear(); |
| CallEventListeners( VCLEVENT_COMBOBOX_ITEMREMOVED, (void*) sal_IntPtr(-1) ); |
| } |
| // ----------------------------------------------------------------------- |
| |
| Image ComboBox::GetEntryImage( sal_uInt16 nPos ) const |
| { |
| if ( mpImplLB->GetEntryList()->HasEntryImage( nPos ) ) |
| return mpImplLB->GetEntryList()->GetEntryImage( nPos ); |
| return Image(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ComboBox::GetEntryPos( const XubString& rStr ) const |
| { |
| sal_uInt16 nPos = mpImplLB->GetEntryList()->FindEntry( rStr ); |
| if ( nPos != LISTBOX_ENTRY_NOTFOUND ) |
| nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount()); |
| return nPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ComboBox::GetEntryPos( const void* pData ) const |
| { |
| sal_uInt16 nPos = mpImplLB->GetEntryList()->FindEntry( pData ); |
| if ( nPos != LISTBOX_ENTRY_NOTFOUND ) |
| nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount()); |
| return nPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| XubString ComboBox::GetEntry( sal_uInt16 nPos ) const |
| { |
| return mpImplLB->GetEntryList()->GetEntryText( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ComboBox::GetEntryCount() const |
| { |
| return mpImplLB->GetEntryList()->GetEntryCount() - mpImplLB->GetEntryList()->GetMRUCount(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ComboBox::IsTravelSelect() const |
| { |
| return mpImplLB->IsTravelSelect(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ComboBox::IsInDropDown() const |
| { |
| return mpFloatWin && mpFloatWin->IsInPopupMode(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::EnableMultiSelection( sal_Bool bMulti ) |
| { |
| mpImplLB->EnableMultiSelection( bMulti, sal_False ); |
| mpImplLB->SetMultiSelectionSimpleMode( sal_True ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ComboBox::IsMultiSelectionEnabled() const |
| { |
| return mpImplLB->IsMultiSelectionEnabled(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long ComboBox::CalcWindowSizePixel( sal_uInt16 nLines ) const |
| { |
| return mpImplLB->GetEntryHeight() * nLines; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size ComboBox::GetOptimalSize(WindowSizeType eType) const |
| { |
| switch (eType) { |
| case WINDOWSIZE_MINIMUM: |
| return CalcMinimumSize(); |
| default: |
| return Edit::GetOptimalSize( eType ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size ComboBox::CalcMinimumSize() const |
| { |
| Size aSz; |
| if ( !IsDropDownBox() ) |
| { |
| aSz = mpImplLB->CalcSize( mpImplLB->GetEntryList()->GetEntryCount() ); |
| aSz.Height() += mnDDHeight; |
| } |
| else |
| { |
| aSz.Height() = mpImplLB->CalcSize( 1 ).Height(); |
| aSz.Width() = mpImplLB->GetMaxEntryWidth(); |
| aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize(); |
| } |
| |
| aSz = CalcWindowSize( aSz ); |
| return aSz; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size ComboBox::CalcAdjustedSize( const Size& rPrefSize ) const |
| { |
| Size aSz = rPrefSize; |
| sal_Int32 nLeft, nTop, nRight, nBottom; |
| ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom ); |
| aSz.Height() -= nTop+nBottom; |
| if ( !IsDropDownBox() ) |
| { |
| long nEntryHeight = CalcSize( 1, 1 ).Height(); |
| long nLines = aSz.Height() / nEntryHeight; |
| if ( nLines < 1 ) |
| nLines = 1; |
| aSz.Height() = nLines * nEntryHeight; |
| aSz.Height() += mnDDHeight; |
| } |
| else |
| { |
| aSz.Height() = mnDDHeight; |
| } |
| aSz.Height() += nTop+nBottom; |
| |
| aSz = CalcWindowSize( aSz ); |
| return aSz; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size ComboBox::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const |
| { |
| // ggf. werden ScrollBars eingeblendet |
| Size aMinSz = CalcMinimumSize(); |
| Size aSz; |
| |
| // Hoehe |
| if ( nLines ) |
| { |
| if ( !IsDropDownBox() ) |
| aSz.Height() = mpImplLB->CalcSize( nLines ).Height() + mnDDHeight; |
| else |
| aSz.Height() = mnDDHeight; |
| } |
| else |
| aSz.Height() = aMinSz.Height(); |
| |
| // Breite |
| if ( nColumns ) |
| aSz.Width() = nColumns * GetTextWidth( UniString( 'X' ) ); |
| else |
| aSz.Width() = aMinSz.Width(); |
| |
| if ( IsDropDownBox() ) |
| aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize(); |
| |
| if ( !IsDropDownBox() ) |
| { |
| if ( aSz.Width() < aMinSz.Width() ) |
| aSz.Height() += GetSettings().GetStyleSettings().GetScrollBarSize(); |
| if ( aSz.Height() < aMinSz.Height() ) |
| aSz.Width() += GetSettings().GetStyleSettings().GetScrollBarSize(); |
| } |
| |
| aSz = CalcWindowSize( aSz ); |
| return aSz; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const |
| { |
| long nCharWidth = GetTextWidth( UniString( 'x' ) ); |
| if ( !IsDropDownBox() ) |
| { |
| Size aOutSz = mpImplLB->GetMainWindow()->GetOutputSizePixel(); |
| rnCols = (sal_uInt16)(aOutSz.Width()/nCharWidth); |
| rnLines = (sal_uInt16)(aOutSz.Height()/mpImplLB->GetEntryHeight()); |
| } |
| else |
| { |
| Size aOutSz = mpSubEdit->GetOutputSizePixel(); |
| rnCols = (sal_uInt16)(aOutSz.Width()/nCharWidth); |
| rnLines = 1; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ) |
| { |
| mpImplLB->GetMainWindow()->ImplInitSettings( sal_True, sal_True, sal_True ); |
| |
| Point aPos = pDev->LogicToPixel( rPos ); |
| Size aSize = pDev->LogicToPixel( rSize ); |
| Font aFont = mpImplLB->GetMainWindow()->GetDrawPixelFont( pDev ); |
| OutDevType eOutDevType = pDev->GetOutDevType(); |
| |
| pDev->Push(); |
| pDev->SetMapMode(); |
| pDev->SetFont( aFont ); |
| pDev->SetTextFillColor(); |
| |
| // Border/Background |
| pDev->SetLineColor(); |
| pDev->SetFillColor(); |
| sal_Bool bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER); |
| sal_Bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground(); |
| if ( bBorder || bBackground ) |
| { |
| Rectangle aRect( aPos, aSize ); |
| // aRect.Top() += nEditHeight; |
| if ( bBorder ) |
| { |
| ImplDrawFrame( pDev, aRect ); |
| } |
| if ( bBackground ) |
| { |
| pDev->SetFillColor( GetControlBackground() ); |
| pDev->DrawRect( aRect ); |
| } |
| } |
| |
| // Inhalt |
| if ( !IsDropDownBox() ) |
| { |
| long nOnePixel = GetDrawPixel( pDev, 1 ); |
| long nTextHeight = pDev->GetTextHeight(); |
| long nEditHeight = nTextHeight + 6*nOnePixel; |
| sal_uInt16 nTextStyle = TEXT_DRAW_VCENTER; |
| |
| // First, draw the edit part |
| mpSubEdit->Draw( pDev, aPos, Size( aSize.Width(), nEditHeight ), nFlags ); |
| |
| // Second, draw the listbox |
| if ( GetStyle() & WB_CENTER ) |
| nTextStyle |= TEXT_DRAW_CENTER; |
| else if ( GetStyle() & WB_RIGHT ) |
| nTextStyle |= TEXT_DRAW_RIGHT; |
| else |
| nTextStyle |= TEXT_DRAW_LEFT; |
| |
| if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) ) |
| { |
| pDev->SetTextColor( Color( COL_BLACK ) ); |
| } |
| else |
| { |
| if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() ) |
| { |
| const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
| pDev->SetTextColor( rStyleSettings.GetDisableColor() ); |
| } |
| else |
| { |
| pDev->SetTextColor( GetTextColor() ); |
| } |
| } |
| |
| Rectangle aClip( aPos, aSize ); |
| pDev->IntersectClipRegion( aClip ); |
| sal_uInt16 nLines = (sal_uInt16) ( (aSize.Height()-nEditHeight) / nTextHeight ); |
| if ( !nLines ) |
| nLines = 1; |
| sal_uInt16 nTEntry = IsReallyVisible() ? mpImplLB->GetTopEntry() : 0; |
| |
| Rectangle aTextRect( aPos, aSize ); |
| |
| aTextRect.Left() += 3*nOnePixel; |
| aTextRect.Right() -= 3*nOnePixel; |
| aTextRect.Top() += nEditHeight + nOnePixel; |
| aTextRect.Bottom() = aTextRect.Top() + nTextHeight; |
| |
| // the drawing starts here |
| for ( sal_uInt16 n = 0; n < nLines; n++ ) |
| { |
| pDev->DrawText( aTextRect, mpImplLB->GetEntryList()->GetEntryText( n+nTEntry ), nTextStyle ); |
| aTextRect.Top() += nTextHeight; |
| aTextRect.Bottom() += nTextHeight; |
| } |
| } |
| |
| pDev->Pop(); |
| |
| // Call Edit::Draw after restoring the MapMode... |
| if ( IsDropDownBox() ) |
| { |
| mpSubEdit->Draw( pDev, rPos, rSize, nFlags ); |
| // DD-Button ? |
| } |
| |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( ComboBox, ImplUserDrawHdl, UserDrawEvent*, pEvent ) |
| { |
| UserDraw( *pEvent ); |
| return 1; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::UserDraw( const UserDrawEvent& ) |
| { |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::SetUserItemSize( const Size& rSz ) |
| { |
| mpImplLB->GetMainWindow()->SetUserItemSize( rSz ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| const Size& ComboBox::GetUserItemSize() const |
| { |
| return mpImplLB->GetMainWindow()->GetUserItemSize(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::EnableUserDraw( sal_Bool bUserDraw ) |
| { |
| mpImplLB->GetMainWindow()->EnableUserDraw( bUserDraw ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool ComboBox::IsUserDrawEnabled() const |
| { |
| return mpImplLB->GetMainWindow()->IsUserDrawEnabled(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::DrawEntry( const UserDrawEvent& rEvt, sal_Bool bDrawImage, sal_Bool bDrawText, sal_Bool bDrawTextAtImagePos ) |
| { |
| DBG_ASSERT( rEvt.GetDevice() == mpImplLB->GetMainWindow(), "DrawEntry?!" ); |
| mpImplLB->GetMainWindow()->DrawEntry( rEvt.GetItemId(), bDrawImage, bDrawText, bDrawTextAtImagePos ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::SetSeparatorPos( sal_uInt16 n ) |
| { |
| mpImplLB->SetSeparatorPos( n ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::SetSeparatorPos() |
| { |
| mpImplLB->SetSeparatorPos( LISTBOX_ENTRY_NOTFOUND ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ComboBox::GetSeparatorPos() const |
| { |
| return mpImplLB->GetSeparatorPos(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::SetMRUEntries( const XubString& rEntries, xub_Unicode cSep ) |
| { |
| mpImplLB->SetMRUEntries( rEntries, cSep ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| XubString ComboBox::GetMRUEntries( xub_Unicode cSep ) const |
| { |
| return mpImplLB->GetMRUEntries( cSep ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::SetMaxMRUCount( sal_uInt16 n ) |
| { |
| mpImplLB->SetMaxMRUCount( n ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ComboBox::GetMaxMRUCount() const |
| { |
| return mpImplLB->GetMaxMRUCount(); |
| } |
| |
| //IAccessibility2 Implementation 2009----- |
| sal_uInt16 ComboBox::GetMRUCount() const |
| { |
| return mpImplLB->GetEntryList()->GetMRUCount(); |
| } |
| //-----IAccessibility2 Implementation 2009 |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ComboBox::GetDisplayLineCount() const |
| { |
| return mpImplLB->GetDisplayLineCount(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::SetEntryData( sal_uInt16 nPos, void* pNewData ) |
| { |
| mpImplLB->SetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount(), pNewData ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void* ComboBox::GetEntryData( sal_uInt16 nPos ) const |
| { |
| return mpImplLB->GetEntryList()->GetEntryData( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::SetTopEntry( sal_uInt16 nPos ) |
| { |
| mpImplLB->SetTopEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::ShowProminentEntry( sal_uInt16 nPos ) |
| { |
| mpImplLB->ShowProminentEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 ComboBox::GetTopEntry() const |
| { |
| sal_uInt16 nPos = GetEntryCount() ? mpImplLB->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND; |
| if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() ) |
| nPos = 0; |
| return nPos; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ComboBox::SetProminentEntryType( ProminentEntry eType ) |
| { |
| mpImplLB->SetProminentEntryType( eType ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| ProminentEntry ComboBox::GetProminentEntryType() const |
| { |
| return mpImplLB->GetProminentEntryType(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Rectangle ComboBox::GetDropDownPosSizePixel() const |
| { |
| return mpFloatWin ? mpFloatWin->GetWindowExtentsRelative( const_cast<ComboBox*>(this) ) : Rectangle(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Rectangle ComboBox::GetListPosSizePixel() const |
| { |
| return mpFloatWin ? Rectangle() : mpImplLB->GetMainWindow()->GetWindowExtentsRelative( const_cast<ComboBox*>(this) ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| const Wallpaper& ComboBox::GetDisplayBackground() const |
| { |
| if( ! mpSubEdit->IsBackground() ) |
| return Control::GetDisplayBackground(); |
| |
| const Wallpaper& rBack = mpSubEdit->GetBackground(); |
| if( ! rBack.IsBitmap() && |
| ! rBack.IsGradient() && |
| rBack.GetColor().GetColor() == COL_TRANSPARENT |
| ) |
| return Control::GetDisplayBackground(); |
| return rBack; |
| } |
| // ----------------------------------------------------------------------------- |
| sal_uInt16 ComboBox::GetSelectEntryCount() const |
| { |
| return mpImplLB->GetEntryList()->GetSelectEntryCount(); |
| } |
| // ----------------------------------------------------------------------------- |
| sal_uInt16 ComboBox::GetSelectEntryPos( sal_uInt16 nIndex ) const |
| { |
| sal_uInt16 nPos = mpImplLB->GetEntryList()->GetSelectEntryPos( nIndex ); |
| if ( nPos != LISTBOX_ENTRY_NOTFOUND ) |
| { |
| if ( nPos < mpImplLB->GetEntryList()->GetMRUCount() ) |
| nPos = mpImplLB->GetEntryList()->FindEntry( mpImplLB->GetEntryList()->GetEntryText( nPos ) ); |
| nPos = sal::static_int_cast<sal_uInt16>(nPos - mpImplLB->GetEntryList()->GetMRUCount()); |
| } |
| return nPos; |
| } |
| // ----------------------------------------------------------------------------- |
| sal_Bool ComboBox::IsEntryPosSelected( sal_uInt16 nPos ) const |
| { |
| return mpImplLB->GetEntryList()->IsEntryPosSelected( nPos + mpImplLB->GetEntryList()->GetMRUCount() ); |
| } |
| // ----------------------------------------------------------------------------- |
| void ComboBox::SelectEntryPos( sal_uInt16 nPos, sal_Bool bSelect) |
| { |
| if ( nPos < mpImplLB->GetEntryList()->GetEntryCount() ) |
| mpImplLB->SelectEntry( nPos + mpImplLB->GetEntryList()->GetMRUCount(), bSelect ); |
| } |
| // ----------------------------------------------------------------------------- |
| void ComboBox::SetNoSelection() |
| { |
| mpImplLB->SetNoSelection(); |
| mpSubEdit->SetText( String() ); |
| } |
| // ----------------------------------------------------------------------------- |
| Rectangle ComboBox::GetBoundingRectangle( sal_uInt16 nItem ) const |
| { |
| Rectangle aRect = mpImplLB->GetMainWindow()->GetBoundingRectangle( nItem ); |
| Rectangle aOffset = mpImplLB->GetMainWindow()->GetWindowExtentsRelative( (Window*)this ); |
| aRect.Move( aOffset.TopLeft().X(), aOffset.TopLeft().Y() ); |
| return aRect; |
| } |
| // ----------------------------------------------------------------------------- |
| |
| void ComboBox::SetBorderStyle( sal_uInt16 nBorderStyle ) |
| { |
| Window::SetBorderStyle( nBorderStyle ); |
| if ( !IsDropDownBox() ) |
| { |
| mpSubEdit->SetBorderStyle( nBorderStyle ); |
| mpImplLB->SetBorderStyle( nBorderStyle ); |
| } |
| } |
| // ----------------------------------------------------------------------------- |
| |
| long ComboBox::GetIndexForPoint( const Point& rPoint, sal_uInt16& rPos ) const |
| { |
| if( !HasLayoutData() ) |
| FillLayoutData(); |
| |
| // check whether rPoint fits at all |
| long nIndex = Control::GetIndexForPoint( rPoint ); |
| if( nIndex != -1 ) |
| { |
| // point must be either in main list window |
| // or in impl window (dropdown case) |
| ImplListBoxWindow* pMain = mpImplLB->GetMainWindow(); |
| |
| // convert coordinates to ImplListBoxWindow pixel coordinate space |
| Point aConvPoint = LogicToPixel( rPoint ); |
| aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint ); |
| aConvPoint = pMain->AbsoluteScreenToOutputPixel( aConvPoint ); |
| aConvPoint = pMain->PixelToLogic( aConvPoint ); |
| |
| // try to find entry |
| sal_uInt16 nEntry = pMain->GetEntryPosForPoint( aConvPoint ); |
| if( nEntry == LISTBOX_ENTRY_NOTFOUND ) |
| nIndex = -1; |
| else |
| rPos = nEntry; |
| } |
| |
| // get line relative index |
| if( nIndex != -1 ) |
| nIndex = ToRelativeLineIndex( nIndex ); |
| |
| return nIndex; |
| } |