Change-Id: I4ca101ba838afecbbc8e841a6a9fa6c9c0460f14 Reviewed-on: https://gerrit.libreoffice.org/65497 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
1568 lines
50 KiB
C++
1568 lines
50 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* 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 .
|
|
*/
|
|
|
|
#include <vcl/combobox.hxx>
|
|
|
|
#include <set>
|
|
|
|
#include <comphelper/string.hxx>
|
|
#include <vcl/decoview.hxx>
|
|
#include <vcl/lstbox.hxx>
|
|
#include <vcl/button.hxx>
|
|
#include <vcl/commandevent.hxx>
|
|
#include <vcl/event.hxx>
|
|
#include <vcl/settings.hxx>
|
|
#include <vcl/uitest/uiobject.hxx>
|
|
#include <sal/log.hxx>
|
|
|
|
#include <svdata.hxx>
|
|
#include <listbox.hxx>
|
|
#include <controldata.hxx>
|
|
#include <comphelper/lok.hxx>
|
|
|
|
struct ComboBoxBounds
|
|
{
|
|
Point aSubEditPos;
|
|
Size aSubEditSize;
|
|
|
|
Point aButtonPos;
|
|
Size aButtonSize;
|
|
};
|
|
|
|
struct ComboBox::Impl
|
|
{
|
|
ComboBox & m_rThis;
|
|
VclPtr<Edit> m_pSubEdit;
|
|
VclPtr<ImplListBox> m_pImplLB;
|
|
VclPtr<ImplBtn> m_pBtn;
|
|
VclPtr<ImplListBoxFloatingWindow> m_pFloatWin;
|
|
sal_uInt16 m_nDDHeight;
|
|
sal_Unicode m_cMultiSep;
|
|
bool m_isDDAutoSize : 1;
|
|
bool m_isSyntheticModify : 1;
|
|
bool m_isMatchCase : 1;
|
|
sal_Int32 m_nMaxWidthChars;
|
|
sal_Int32 m_nWidthInChars;
|
|
Link<ComboBox&,void> m_SelectHdl;
|
|
Link<ComboBox&,void> m_DoubleClickHdl;
|
|
|
|
explicit Impl(ComboBox & rThis)
|
|
: m_rThis(rThis)
|
|
, m_nDDHeight(0)
|
|
, m_cMultiSep(0)
|
|
, m_isDDAutoSize(false)
|
|
, m_isSyntheticModify(false)
|
|
, m_isMatchCase(false)
|
|
, m_nMaxWidthChars(0)
|
|
, m_nWidthInChars(-1)
|
|
{
|
|
}
|
|
|
|
void ImplInitComboBoxData();
|
|
void ImplUpdateFloatSelection();
|
|
ComboBoxBounds calcComboBoxDropDownComponentBounds(
|
|
const Size &rOutSize, const Size &rBorderOutSize) const;
|
|
|
|
DECL_DLLPRIVATE_LINK( ImplSelectHdl, LinkParamNone*, void );
|
|
DECL_DLLPRIVATE_LINK( ImplCancelHdl, LinkParamNone*, void );
|
|
DECL_DLLPRIVATE_LINK( ImplDoubleClickHdl, ImplListBoxWindow*, void );
|
|
DECL_DLLPRIVATE_LINK( ImplClickBtnHdl, void*, void );
|
|
DECL_DLLPRIVATE_LINK( ImplPopupModeEndHdl, FloatingWindow*, void );
|
|
DECL_DLLPRIVATE_LINK( ImplSelectionChangedHdl, sal_Int32, void );
|
|
DECL_DLLPRIVATE_LINK( ImplUserDrawHdl, UserDrawEvent*, void );
|
|
DECL_DLLPRIVATE_LINK( ImplAutocompleteHdl, Edit&, void );
|
|
DECL_DLLPRIVATE_LINK( ImplListItemSelectHdl , LinkParamNone*, void );
|
|
};
|
|
|
|
|
|
static void lcl_GetSelectedEntries( ::std::set< sal_Int32 >& rSelectedPos, const OUString& rText, sal_Unicode cTokenSep, const ImplEntryList* pEntryList )
|
|
{
|
|
if (rText.isEmpty())
|
|
return;
|
|
|
|
sal_Int32 nIdx{0};
|
|
do {
|
|
const sal_Int32 nPos = pEntryList->FindEntry(comphelper::string::strip(rText.getToken(0, cTokenSep, nIdx), ' '));
|
|
if ( nPos != LISTBOX_ENTRY_NOTFOUND )
|
|
rSelectedPos.insert( nPos );
|
|
} while (nIdx>=0);
|
|
}
|
|
|
|
ComboBox::ComboBox(vcl::Window *const pParent, WinBits const nStyle)
|
|
: Edit( WindowType::COMBOBOX )
|
|
, m_pImpl(new Impl(*this))
|
|
{
|
|
m_pImpl->ImplInitComboBoxData();
|
|
ImplInit( pParent, nStyle );
|
|
SetWidthInChars(-1);
|
|
}
|
|
|
|
ComboBox::~ComboBox()
|
|
{
|
|
disposeOnce();
|
|
}
|
|
|
|
void ComboBox::dispose()
|
|
{
|
|
m_pImpl->m_pSubEdit.disposeAndClear();
|
|
|
|
VclPtr< ImplListBox > pImplLB = m_pImpl->m_pImplLB;
|
|
m_pImpl->m_pImplLB.clear();
|
|
pImplLB.disposeAndClear();
|
|
|
|
m_pImpl->m_pFloatWin.disposeAndClear();
|
|
m_pImpl->m_pBtn.disposeAndClear();
|
|
Edit::dispose();
|
|
}
|
|
|
|
void ComboBox::Impl::ImplInitComboBoxData()
|
|
{
|
|
m_pSubEdit.disposeAndClear();
|
|
m_pBtn = nullptr;
|
|
m_pImplLB = nullptr;
|
|
m_pFloatWin = nullptr;
|
|
|
|
m_nDDHeight = 0;
|
|
m_isDDAutoSize = true;
|
|
m_isSyntheticModify = false;
|
|
m_isMatchCase = false;
|
|
m_cMultiSep = ';';
|
|
m_nMaxWidthChars = -1;
|
|
m_nWidthInChars = -1;
|
|
}
|
|
|
|
void ComboBox::ImplCalcEditHeight()
|
|
{
|
|
sal_Int32 nLeft, nTop, nRight, nBottom;
|
|
GetBorder( nLeft, nTop, nRight, nBottom );
|
|
m_pImpl->m_nDDHeight = static_cast<sal_uInt16>(m_pImpl->m_pSubEdit->GetTextHeight() + nTop + nBottom + 4);
|
|
if ( !IsDropDownBox() )
|
|
m_pImpl->m_nDDHeight += 4;
|
|
|
|
tools::Rectangle aCtrlRegion( Point( 0, 0 ), Size( 10, 10 ) );
|
|
tools::Rectangle aBoundRegion, aContentRegion;
|
|
ImplControlValue aControlValue;
|
|
ControlType aType = IsDropDownBox() ? ControlType::Combobox : ControlType::Editbox;
|
|
if( GetNativeControlRegion( aType, ControlPart::Entire,
|
|
aCtrlRegion,
|
|
ControlState::ENABLED,
|
|
aControlValue,
|
|
aBoundRegion, aContentRegion ) )
|
|
{
|
|
const long nNCHeight = aBoundRegion.GetHeight();
|
|
if (m_pImpl->m_nDDHeight < nNCHeight)
|
|
m_pImpl->m_nDDHeight = sal::static_int_cast<sal_uInt16>(nNCHeight);
|
|
}
|
|
}
|
|
|
|
void ComboBox::ImplInit( vcl::Window* pParent, WinBits nStyle )
|
|
{
|
|
bool bNoBorder = ( nStyle & WB_NOBORDER ) != 0;
|
|
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 )
|
|
{
|
|
m_pImpl->m_pFloatWin = VclPtr<ImplListBoxFloatingWindow>::Create( this );
|
|
m_pImpl->m_pFloatWin->SetAutoWidth( true );
|
|
m_pImpl->m_pFloatWin->SetPopupModeEndHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplPopupModeEndHdl) );
|
|
|
|
m_pImpl->m_pBtn = VclPtr<ImplBtn>::Create( this, WB_NOLIGHTBORDER | WB_RECTSTYLE );
|
|
ImplInitDropDownButton( m_pImpl->m_pBtn );
|
|
m_pImpl->m_pBtn->SetMBDownHdl( LINK( m_pImpl.get(), ComboBox::Impl, ImplClickBtnHdl ) );
|
|
m_pImpl->m_pBtn->Show();
|
|
|
|
nEditStyle |= WB_NOBORDER;
|
|
nListStyle &= ~WB_BORDER;
|
|
nListStyle |= WB_NOBORDER;
|
|
}
|
|
else
|
|
{
|
|
if ( !bNoBorder )
|
|
{
|
|
nEditStyle |= WB_BORDER;
|
|
nListStyle &= ~WB_NOBORDER;
|
|
nListStyle |= WB_BORDER;
|
|
}
|
|
}
|
|
|
|
m_pImpl->m_pSubEdit.set( VclPtr<Edit>::Create( this, nEditStyle ) );
|
|
m_pImpl->m_pSubEdit->EnableRTL( false );
|
|
SetSubEdit( m_pImpl->m_pSubEdit );
|
|
m_pImpl->m_pSubEdit->SetPosPixel( Point() );
|
|
EnableAutocomplete( true );
|
|
m_pImpl->m_pSubEdit->Show();
|
|
|
|
vcl::Window* pLBParent = this;
|
|
if (m_pImpl->m_pFloatWin)
|
|
pLBParent = m_pImpl->m_pFloatWin;
|
|
m_pImpl->m_pImplLB = VclPtr<ImplListBox>::Create( pLBParent, nListStyle|WB_SIMPLEMODE|WB_AUTOHSCROLL );
|
|
m_pImpl->m_pImplLB->SetPosPixel( Point() );
|
|
m_pImpl->m_pImplLB->SetSelectHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplSelectHdl) );
|
|
m_pImpl->m_pImplLB->SetCancelHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplCancelHdl) );
|
|
m_pImpl->m_pImplLB->SetDoubleClickHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplDoubleClickHdl) );
|
|
m_pImpl->m_pImplLB->SetUserDrawHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplUserDrawHdl) );
|
|
m_pImpl->m_pImplLB->SetSelectionChangedHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplSelectionChangedHdl) );
|
|
m_pImpl->m_pImplLB->SetListItemSelectHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplListItemSelectHdl) );
|
|
m_pImpl->m_pImplLB->Show();
|
|
|
|
if (m_pImpl->m_pFloatWin)
|
|
m_pImpl->m_pFloatWin->SetImplListBox( m_pImpl->m_pImplLB );
|
|
else
|
|
m_pImpl->m_pImplLB->GetMainWindow()->AllowGrabFocus( true );
|
|
|
|
ImplCalcEditHeight();
|
|
|
|
SetCompoundControl( true );
|
|
}
|
|
|
|
WinBits ComboBox::ImplInitStyle( WinBits nStyle )
|
|
{
|
|
if ( !(nStyle & WB_NOTABSTOP) )
|
|
nStyle |= WB_TABSTOP;
|
|
if ( !(nStyle & WB_NOGROUP) )
|
|
nStyle |= WB_GROUP;
|
|
return nStyle;
|
|
}
|
|
|
|
void ComboBox::EnableAutocomplete( bool bEnable, bool bMatchCase )
|
|
{
|
|
m_pImpl->m_isMatchCase = bMatchCase;
|
|
|
|
if ( bEnable )
|
|
m_pImpl->m_pSubEdit->SetAutocompleteHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplAutocompleteHdl) );
|
|
else
|
|
m_pImpl->m_pSubEdit->SetAutocompleteHdl( Link<Edit&,void>() );
|
|
}
|
|
|
|
bool ComboBox::IsAutocompleteEnabled() const
|
|
{
|
|
return m_pImpl->m_pSubEdit->GetAutocompleteHdl().IsSet();
|
|
}
|
|
|
|
IMPL_LINK_NOARG(ComboBox::Impl, ImplClickBtnHdl, void*, void)
|
|
{
|
|
m_rThis.CallEventListeners( VclEventId::DropdownPreOpen );
|
|
m_pSubEdit->GrabFocus();
|
|
if (!m_pImplLB->GetEntryList()->GetMRUCount())
|
|
ImplUpdateFloatSelection();
|
|
else
|
|
m_pImplLB->SelectEntry( 0 , true );
|
|
m_pBtn->SetPressed( true );
|
|
m_rThis.SetSelection( Selection( 0, SELECTION_MAX ) );
|
|
m_pFloatWin->StartFloat( true );
|
|
m_rThis.CallEventListeners( VclEventId::DropdownOpen );
|
|
|
|
m_rThis.ImplClearLayoutData();
|
|
if (m_pImplLB)
|
|
m_pImplLB->GetMainWindow()->ImplClearLayoutData();
|
|
}
|
|
|
|
IMPL_LINK_NOARG(ComboBox::Impl, ImplPopupModeEndHdl, FloatingWindow*, void)
|
|
{
|
|
if (m_pFloatWin->IsPopupModeCanceled())
|
|
{
|
|
if (!m_pImplLB->GetEntryList()->IsEntryPosSelected(
|
|
m_pFloatWin->GetPopupModeStartSaveSelection()))
|
|
{
|
|
m_pImplLB->SelectEntry(m_pFloatWin->GetPopupModeStartSaveSelection(), true);
|
|
bool bTravelSelect = m_pImplLB->IsTravelSelect();
|
|
m_pImplLB->SetTravelSelect( true );
|
|
m_rThis.Select();
|
|
m_pImplLB->SetTravelSelect( bTravelSelect );
|
|
}
|
|
}
|
|
|
|
m_rThis.ImplClearLayoutData();
|
|
if (m_pImplLB)
|
|
m_pImplLB->GetMainWindow()->ImplClearLayoutData();
|
|
|
|
m_pBtn->SetPressed( false );
|
|
m_rThis.CallEventListeners( VclEventId::DropdownClose );
|
|
}
|
|
|
|
IMPL_LINK(ComboBox::Impl, ImplAutocompleteHdl, Edit&, rEdit, void)
|
|
{
|
|
Selection aSel = rEdit.GetSelection();
|
|
|
|
{
|
|
OUString aFullText = rEdit.GetText();
|
|
OUString aStartText = aFullText.copy( 0, static_cast<sal_Int32>(aSel.Max()) );
|
|
sal_Int32 nStart = m_pImplLB->GetCurrentPos();
|
|
|
|
if ( nStart == LISTBOX_ENTRY_NOTFOUND )
|
|
nStart = 0;
|
|
|
|
sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND;
|
|
if (!m_isMatchCase)
|
|
{
|
|
// Try match case insensitive from current position
|
|
nPos = m_pImplLB->GetEntryList()->FindMatchingEntry(aStartText, nStart, true);
|
|
if ( nPos == LISTBOX_ENTRY_NOTFOUND )
|
|
// Try match case insensitive, but from start
|
|
nPos = m_pImplLB->GetEntryList()->FindMatchingEntry(aStartText, 0, true);
|
|
}
|
|
|
|
if ( nPos == LISTBOX_ENTRY_NOTFOUND )
|
|
// Try match full from current position
|
|
nPos = m_pImplLB->GetEntryList()->FindMatchingEntry(aStartText, nStart, false);
|
|
if ( nPos == LISTBOX_ENTRY_NOTFOUND )
|
|
// Match full, but from start
|
|
nPos = m_pImplLB->GetEntryList()->FindMatchingEntry(aStartText, 0, false);
|
|
|
|
if ( nPos != LISTBOX_ENTRY_NOTFOUND )
|
|
{
|
|
OUString aText = m_pImplLB->GetEntryList()->GetEntryText( nPos );
|
|
Selection aSelection( aText.getLength(), aStartText.getLength() );
|
|
rEdit.SetText( aText, aSelection );
|
|
}
|
|
}
|
|
}
|
|
|
|
IMPL_LINK_NOARG(ComboBox::Impl, ImplSelectHdl, LinkParamNone*, void)
|
|
{
|
|
bool bPopup = m_rThis.IsInDropDown();
|
|
bool bCallSelect = false;
|
|
if (m_pImplLB->IsSelectionChanged() || bPopup)
|
|
{
|
|
OUString aText;
|
|
if (m_rThis.IsMultiSelectionEnabled())
|
|
{
|
|
aText = m_pSubEdit->GetText();
|
|
|
|
// remove all entries to which there is an entry, but which is not selected
|
|
sal_Int32 nIndex = 0;
|
|
while ( nIndex >= 0 )
|
|
{
|
|
sal_Int32 nPrevIndex = nIndex;
|
|
OUString aToken = aText.getToken( 0, m_cMultiSep, nIndex );
|
|
sal_Int32 nTokenLen = aToken.getLength();
|
|
aToken = comphelper::string::strip(aToken, ' ');
|
|
sal_Int32 nP = m_pImplLB->GetEntryList()->FindEntry( aToken );
|
|
if ((nP != LISTBOX_ENTRY_NOTFOUND) && (!m_pImplLB->GetEntryList()->IsEntryPosSelected(nP)))
|
|
{
|
|
aText = aText.replaceAt( nPrevIndex, nTokenLen, "" );
|
|
nIndex = nIndex - nTokenLen;
|
|
sal_Int32 nSepCount=0;
|
|
if ((nPrevIndex+nSepCount < aText.getLength()) && (aText[nPrevIndex+nSepCount] == m_cMultiSep))
|
|
{
|
|
nIndex--;
|
|
++nSepCount;
|
|
}
|
|
aText = aText.replaceAt( nPrevIndex, nSepCount, "" );
|
|
}
|
|
aText = comphelper::string::strip(aText, ' ');
|
|
}
|
|
|
|
// attach missing entries
|
|
::std::set< sal_Int32 > aSelInText;
|
|
lcl_GetSelectedEntries( aSelInText, aText, m_cMultiSep, m_pImplLB->GetEntryList() );
|
|
sal_Int32 nSelectedEntries = m_pImplLB->GetEntryList()->GetSelectedEntryCount();
|
|
for ( sal_Int32 n = 0; n < nSelectedEntries; n++ )
|
|
{
|
|
sal_Int32 nP = m_pImplLB->GetEntryList()->GetSelectedEntryPos( n );
|
|
if ( !aSelInText.count( nP ) )
|
|
{
|
|
if (!aText.isEmpty() && (aText[aText.getLength()-1] != m_cMultiSep))
|
|
aText += OUStringLiteral1(m_cMultiSep);
|
|
if ( !aText.isEmpty() )
|
|
aText += " "; // slightly loosen
|
|
aText += m_pImplLB->GetEntryList()->GetEntryText( nP );
|
|
aText += OUStringLiteral1(m_cMultiSep);
|
|
}
|
|
}
|
|
aText = comphelper::string::stripEnd( aText, m_cMultiSep );
|
|
}
|
|
else
|
|
{
|
|
aText = m_pImplLB->GetEntryList()->GetSelectedEntry( 0 );
|
|
}
|
|
|
|
m_pSubEdit->SetText( aText );
|
|
|
|
Selection aNewSelection( 0, aText.getLength() );
|
|
if (m_rThis.IsMultiSelectionEnabled())
|
|
aNewSelection.Min() = aText.getLength();
|
|
m_pSubEdit->SetSelection( aNewSelection );
|
|
|
|
bCallSelect = true;
|
|
}
|
|
|
|
// #84652# Call GrabFocus and EndPopupMode before calling Select/Modify, but after changing the text
|
|
|
|
if (bPopup && !m_pImplLB->IsTravelSelect() &&
|
|
(!m_rThis.IsMultiSelectionEnabled() || !m_pImplLB->GetSelectModifier()))
|
|
{
|
|
m_pFloatWin->EndPopupMode();
|
|
m_rThis.GrabFocus();
|
|
}
|
|
|
|
if ( bCallSelect )
|
|
{
|
|
m_pSubEdit->SetModifyFlag();
|
|
m_isSyntheticModify = true;
|
|
m_rThis.Modify();
|
|
m_isSyntheticModify = false;
|
|
m_rThis.Select();
|
|
}
|
|
}
|
|
|
|
IMPL_LINK_NOARG( ComboBox::Impl, ImplListItemSelectHdl, LinkParamNone*, void )
|
|
{
|
|
m_rThis.CallEventListeners( VclEventId::DropdownSelect );
|
|
}
|
|
|
|
IMPL_LINK_NOARG(ComboBox::Impl, ImplCancelHdl, LinkParamNone*, void)
|
|
{
|
|
if (m_rThis.IsInDropDown())
|
|
m_pFloatWin->EndPopupMode();
|
|
}
|
|
|
|
IMPL_LINK( ComboBox::Impl, ImplSelectionChangedHdl, sal_Int32, nChanged, void )
|
|
{
|
|
if (!m_pImplLB->IsTrackingSelect())
|
|
{
|
|
if (!m_pSubEdit->IsReadOnly() && m_pImplLB->GetEntryList()->IsEntryPosSelected(nChanged))
|
|
m_pSubEdit->SetText(m_pImplLB->GetEntryList()->GetEntryText(nChanged));
|
|
}
|
|
}
|
|
|
|
IMPL_LINK_NOARG(ComboBox::Impl, ImplDoubleClickHdl, ImplListBoxWindow*, void)
|
|
{
|
|
m_rThis.DoubleClick();
|
|
}
|
|
|
|
void ComboBox::ToggleDropDown()
|
|
{
|
|
if( IsDropDownBox() )
|
|
{
|
|
if (m_pImpl->m_pFloatWin->IsInPopupMode())
|
|
m_pImpl->m_pFloatWin->EndPopupMode();
|
|
else
|
|
{
|
|
m_pImpl->m_pSubEdit->GrabFocus();
|
|
if (!m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount())
|
|
m_pImpl->ImplUpdateFloatSelection();
|
|
else
|
|
m_pImpl->m_pImplLB->SelectEntry( 0 , true );
|
|
CallEventListeners( VclEventId::DropdownPreOpen );
|
|
m_pImpl->m_pBtn->SetPressed( true );
|
|
SetSelection( Selection( 0, SELECTION_MAX ) );
|
|
m_pImpl->m_pFloatWin->StartFloat( true );
|
|
CallEventListeners( VclEventId::DropdownOpen );
|
|
}
|
|
}
|
|
}
|
|
|
|
void ComboBox::Select()
|
|
{
|
|
ImplCallEventListenersAndHandler( VclEventId::ComboboxSelect, [this] () { m_pImpl->m_SelectHdl.Call(*this); } );
|
|
}
|
|
|
|
void ComboBox::DoubleClick()
|
|
{
|
|
ImplCallEventListenersAndHandler( VclEventId::ComboboxDoubleClick, [this] () { m_pImpl->m_DoubleClickHdl.Call(*this); } );
|
|
}
|
|
|
|
bool ComboBox::IsAutoSizeEnabled() const { return m_pImpl->m_isDDAutoSize; }
|
|
|
|
void ComboBox::EnableAutoSize( bool bAuto )
|
|
{
|
|
m_pImpl->m_isDDAutoSize = bAuto;
|
|
if (m_pImpl->m_pFloatWin)
|
|
{
|
|
if (bAuto && !m_pImpl->m_pFloatWin->GetDropDownLineCount())
|
|
{
|
|
// Adapt to GetListBoxMaximumLineCount here; was on fixed number of five before
|
|
AdaptDropDownLineCountToMaximum();
|
|
}
|
|
else if ( !bAuto )
|
|
{
|
|
m_pImpl->m_pFloatWin->SetDropDownLineCount( 0 );
|
|
}
|
|
}
|
|
}
|
|
void ComboBox::EnableSelectAll()
|
|
{
|
|
m_pImpl->m_pSubEdit->SetSelectAllSingleClick(true);
|
|
}
|
|
void ComboBox::EnableDDAutoWidth( bool b )
|
|
{
|
|
if (m_pImpl->m_pFloatWin)
|
|
m_pImpl->m_pFloatWin->SetAutoWidth( b );
|
|
}
|
|
|
|
void ComboBox::SetDropDownLineCount( sal_uInt16 nLines )
|
|
{
|
|
if (m_pImpl->m_pFloatWin)
|
|
m_pImpl->m_pFloatWin->SetDropDownLineCount( nLines );
|
|
}
|
|
|
|
void ComboBox::AdaptDropDownLineCountToMaximum()
|
|
{
|
|
// Adapt to maximum allowed number.
|
|
// Limit for LOK as we can't render outside of the dialog canvas.
|
|
if (comphelper::LibreOfficeKit::isActive())
|
|
SetDropDownLineCount(11);
|
|
else
|
|
SetDropDownLineCount(GetSettings().GetStyleSettings().GetListBoxMaximumLineCount());
|
|
}
|
|
|
|
sal_uInt16 ComboBox::GetDropDownLineCount() const
|
|
{
|
|
sal_uInt16 nLines = 0;
|
|
if (m_pImpl->m_pFloatWin)
|
|
nLines = m_pImpl->m_pFloatWin->GetDropDownLineCount();
|
|
return nLines;
|
|
}
|
|
|
|
void ComboBox::setPosSizePixel( long nX, long nY, long nWidth, long nHeight,
|
|
PosSizeFlags nFlags )
|
|
{
|
|
if( IsDropDownBox() && ( nFlags & PosSizeFlags::Size ) )
|
|
{
|
|
Size aPrefSz = m_pImpl->m_pFloatWin->GetPrefSize();
|
|
if ((nFlags & PosSizeFlags::Height) && (nHeight >= 2*m_pImpl->m_nDDHeight))
|
|
aPrefSz.setHeight( nHeight-m_pImpl->m_nDDHeight );
|
|
if ( nFlags & PosSizeFlags::Width )
|
|
aPrefSz.setWidth( nWidth );
|
|
m_pImpl->m_pFloatWin->SetPrefSize( aPrefSz );
|
|
|
|
if (IsAutoSizeEnabled())
|
|
nHeight = m_pImpl->m_nDDHeight;
|
|
}
|
|
|
|
Edit::setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
|
|
}
|
|
|
|
void ComboBox::Resize()
|
|
{
|
|
Control::Resize();
|
|
|
|
if (m_pImpl->m_pSubEdit)
|
|
{
|
|
Size aOutSz = GetOutputSizePixel();
|
|
if( IsDropDownBox() )
|
|
{
|
|
ComboBoxBounds aBounds(m_pImpl->calcComboBoxDropDownComponentBounds(aOutSz,
|
|
GetWindow(GetWindowType::Border)->GetOutputSizePixel()));
|
|
m_pImpl->m_pSubEdit->SetPosSizePixel(aBounds.aSubEditPos, aBounds.aSubEditSize);
|
|
m_pImpl->m_pBtn->SetPosSizePixel(aBounds.aButtonPos, aBounds.aButtonSize);
|
|
}
|
|
else
|
|
{
|
|
m_pImpl->m_pSubEdit->SetSizePixel(Size(aOutSz.Width(), m_pImpl->m_nDDHeight));
|
|
m_pImpl->m_pImplLB->setPosSizePixel(0, m_pImpl->m_nDDHeight,
|
|
aOutSz.Width(), aOutSz.Height() - m_pImpl->m_nDDHeight);
|
|
if ( !GetText().isEmpty() )
|
|
m_pImpl->ImplUpdateFloatSelection();
|
|
}
|
|
}
|
|
|
|
// adjust the size of the FloatingWindow even when invisible
|
|
// as KEY_PGUP/DOWN is being processed...
|
|
if (m_pImpl->m_pFloatWin)
|
|
m_pImpl->m_pFloatWin->SetSizePixel(m_pImpl->m_pFloatWin->CalcFloatSize());
|
|
}
|
|
|
|
bool ComboBox::IsDropDownBox() const { return m_pImpl->m_pFloatWin != nullptr; }
|
|
|
|
void ComboBox::FillLayoutData() const
|
|
{
|
|
mpControlData->mpLayoutData.reset( new vcl::ControlLayoutData );
|
|
AppendLayoutData( *m_pImpl->m_pSubEdit );
|
|
m_pImpl->m_pSubEdit->SetLayoutDataParent( this );
|
|
ImplListBoxWindow* rMainWindow = m_pImpl->m_pImplLB->GetMainWindow();
|
|
if (m_pImpl->m_pFloatWin)
|
|
{
|
|
// dropdown mode
|
|
if (m_pImpl->m_pFloatWin->IsReallyVisible())
|
|
{
|
|
AppendLayoutData( *rMainWindow );
|
|
rMainWindow->SetLayoutDataParent( this );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AppendLayoutData( *rMainWindow );
|
|
rMainWindow->SetLayoutDataParent( this );
|
|
}
|
|
}
|
|
|
|
void ComboBox::StateChanged( StateChangedType nType )
|
|
{
|
|
Edit::StateChanged( nType );
|
|
|
|
if ( nType == StateChangedType::ReadOnly )
|
|
{
|
|
m_pImpl->m_pImplLB->SetReadOnly( IsReadOnly() );
|
|
if (m_pImpl->m_pBtn)
|
|
m_pImpl->m_pBtn->Enable( IsEnabled() && !IsReadOnly() );
|
|
}
|
|
else if ( nType == StateChangedType::Enable )
|
|
{
|
|
m_pImpl->m_pSubEdit->Enable( IsEnabled() );
|
|
m_pImpl->m_pImplLB->Enable( IsEnabled() && !IsReadOnly() );
|
|
if (m_pImpl->m_pBtn)
|
|
m_pImpl->m_pBtn->Enable( IsEnabled() && !IsReadOnly() );
|
|
Invalidate();
|
|
}
|
|
else if( nType == StateChangedType::UpdateMode )
|
|
{
|
|
m_pImpl->m_pImplLB->SetUpdateMode( IsUpdateMode() );
|
|
}
|
|
else if ( nType == StateChangedType::Zoom )
|
|
{
|
|
m_pImpl->m_pImplLB->SetZoom( GetZoom() );
|
|
m_pImpl->m_pSubEdit->SetZoom( GetZoom() );
|
|
ImplCalcEditHeight();
|
|
Resize();
|
|
}
|
|
else if ( nType == StateChangedType::ControlFont )
|
|
{
|
|
m_pImpl->m_pImplLB->SetControlFont( GetControlFont() );
|
|
m_pImpl->m_pSubEdit->SetControlFont( GetControlFont() );
|
|
ImplCalcEditHeight();
|
|
Resize();
|
|
}
|
|
else if ( nType == StateChangedType::ControlForeground )
|
|
{
|
|
m_pImpl->m_pImplLB->SetControlForeground( GetControlForeground() );
|
|
m_pImpl->m_pSubEdit->SetControlForeground( GetControlForeground() );
|
|
}
|
|
else if ( nType == StateChangedType::ControlBackground )
|
|
{
|
|
m_pImpl->m_pImplLB->SetControlBackground( GetControlBackground() );
|
|
m_pImpl->m_pSubEdit->SetControlBackground( GetControlBackground() );
|
|
}
|
|
else if ( nType == StateChangedType::Style )
|
|
{
|
|
SetStyle( ImplInitStyle( GetStyle() ) );
|
|
m_pImpl->m_pImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) != 0 );
|
|
}
|
|
else if( nType == StateChangedType::Mirroring )
|
|
{
|
|
if (m_pImpl->m_pBtn)
|
|
{
|
|
m_pImpl->m_pBtn->EnableRTL( IsRTLEnabled() );
|
|
ImplInitDropDownButton( m_pImpl->m_pBtn );
|
|
}
|
|
m_pImpl->m_pSubEdit->CompatStateChanged( StateChangedType::Mirroring );
|
|
m_pImpl->m_pImplLB->EnableRTL( IsRTLEnabled() );
|
|
Resize();
|
|
}
|
|
}
|
|
|
|
void ComboBox::DataChanged( const DataChangedEvent& rDCEvt )
|
|
{
|
|
Control::DataChanged( rDCEvt );
|
|
|
|
if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
|
|
(rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
|
|
((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
|
|
(rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
|
|
{
|
|
if (m_pImpl->m_pBtn)
|
|
{
|
|
m_pImpl->m_pBtn->SetSettings( GetSettings() );
|
|
ImplInitDropDownButton( m_pImpl->m_pBtn );
|
|
}
|
|
Resize();
|
|
m_pImpl->m_pImplLB->Resize(); // not called by ComboBox::Resize() if ImplLB is unchanged
|
|
|
|
SetBackground(); // due to a hack in Window::UpdateSettings the background must be reset
|
|
// otherwise it will overpaint NWF drawn comboboxes
|
|
}
|
|
}
|
|
|
|
bool ComboBox::EventNotify( NotifyEvent& rNEvt )
|
|
{
|
|
bool bDone = false;
|
|
if ((rNEvt.GetType() == MouseNotifyEvent::KEYINPUT)
|
|
&& (rNEvt.GetWindow() == m_pImpl->m_pSubEdit)
|
|
&& !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:
|
|
{
|
|
m_pImpl->ImplUpdateFloatSelection();
|
|
if ((nKeyCode == KEY_DOWN) && m_pImpl->m_pFloatWin
|
|
&& !m_pImpl->m_pFloatWin->IsInPopupMode()
|
|
&& aKeyEvt.GetKeyCode().IsMod2())
|
|
{
|
|
CallEventListeners( VclEventId::DropdownPreOpen );
|
|
m_pImpl->m_pBtn->SetPressed( true );
|
|
if (m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount())
|
|
m_pImpl->m_pImplLB->SelectEntry( 0 , true );
|
|
SetSelection( Selection( 0, SELECTION_MAX ) );
|
|
m_pImpl->m_pFloatWin->StartFloat( false );
|
|
CallEventListeners( VclEventId::DropdownOpen );
|
|
bDone = true;
|
|
}
|
|
else if ((nKeyCode == KEY_UP) && m_pImpl->m_pFloatWin
|
|
&& m_pImpl->m_pFloatWin->IsInPopupMode()
|
|
&& aKeyEvt.GetKeyCode().IsMod2())
|
|
{
|
|
m_pImpl->m_pFloatWin->EndPopupMode();
|
|
bDone = true;
|
|
}
|
|
else
|
|
{
|
|
bDone = m_pImpl->m_pImplLB->ProcessKeyInput( aKeyEvt );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_RETURN:
|
|
{
|
|
if ((rNEvt.GetWindow() == m_pImpl->m_pSubEdit) && IsInDropDown())
|
|
{
|
|
m_pImpl->m_pImplLB->ProcessKeyInput( aKeyEvt );
|
|
bDone = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if ((rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS) && m_pImpl->m_pFloatWin)
|
|
{
|
|
if (m_pImpl->m_pFloatWin->HasChildPathFocus())
|
|
m_pImpl->m_pSubEdit->GrabFocus();
|
|
else if (m_pImpl->m_pFloatWin->IsInPopupMode() && !HasChildPathFocus(true))
|
|
m_pImpl->m_pFloatWin->EndPopupMode();
|
|
}
|
|
else if( (rNEvt.GetType() == MouseNotifyEvent::COMMAND) &&
|
|
(rNEvt.GetCommandEvent()->GetCommand() == CommandEventId::Wheel) &&
|
|
(rNEvt.GetWindow() == m_pImpl->m_pSubEdit) )
|
|
{
|
|
MouseWheelBehaviour nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
|
|
if ( ( nWheelBehavior == MouseWheelBehaviour::ALWAYS )
|
|
|| ( ( nWheelBehavior == MouseWheelBehaviour::FocusOnly )
|
|
&& HasChildPathFocus()
|
|
)
|
|
)
|
|
{
|
|
bDone = m_pImpl->m_pImplLB->HandleWheelAsCursorTravel( *rNEvt.GetCommandEvent() );
|
|
}
|
|
else
|
|
{
|
|
bDone = false; // don't eat this event, let the default handling happen (i.e. scroll the context)
|
|
}
|
|
}
|
|
else if ((rNEvt.GetType() == MouseNotifyEvent::MOUSEBUTTONDOWN)
|
|
&& (rNEvt.GetWindow() == m_pImpl->m_pImplLB->GetMainWindow()))
|
|
{
|
|
m_pImpl->m_pSubEdit->GrabFocus();
|
|
}
|
|
|
|
return bDone || Edit::EventNotify( rNEvt );
|
|
}
|
|
|
|
void ComboBox::SetText( const OUString& rStr )
|
|
{
|
|
CallEventListeners( VclEventId::ComboboxSetText );
|
|
|
|
Edit::SetText( rStr );
|
|
m_pImpl->ImplUpdateFloatSelection();
|
|
}
|
|
|
|
void ComboBox::SetText( const OUString& rStr, const Selection& rNewSelection )
|
|
{
|
|
CallEventListeners( VclEventId::ComboboxSetText );
|
|
|
|
Edit::SetText( rStr, rNewSelection );
|
|
m_pImpl->ImplUpdateFloatSelection();
|
|
}
|
|
|
|
void ComboBox::Modify()
|
|
{
|
|
if (!m_pImpl->m_isSyntheticModify)
|
|
m_pImpl->ImplUpdateFloatSelection();
|
|
|
|
Edit::Modify();
|
|
}
|
|
|
|
void ComboBox::Impl::ImplUpdateFloatSelection()
|
|
{
|
|
if (!m_pImplLB || !m_pSubEdit)
|
|
return;
|
|
|
|
// move text in the ListBox into the visible region
|
|
m_pImplLB->SetCallSelectionChangedHdl( false );
|
|
if (!m_rThis.IsMultiSelectionEnabled())
|
|
{
|
|
OUString aSearchStr( m_pSubEdit->GetText() );
|
|
sal_Int32 nSelect = LISTBOX_ENTRY_NOTFOUND;
|
|
bool bSelect = true;
|
|
|
|
if (m_pImplLB->GetCurrentPos() != LISTBOX_ENTRY_NOTFOUND)
|
|
{
|
|
OUString aCurrent = m_pImplLB->GetEntryList()->GetEntryText(
|
|
m_pImplLB->GetCurrentPos());
|
|
if ( aCurrent == aSearchStr )
|
|
nSelect = m_pImplLB->GetCurrentPos();
|
|
}
|
|
|
|
if ( nSelect == LISTBOX_ENTRY_NOTFOUND )
|
|
nSelect = m_pImplLB->GetEntryList()->FindEntry( aSearchStr );
|
|
if ( nSelect == LISTBOX_ENTRY_NOTFOUND )
|
|
{
|
|
nSelect = m_pImplLB->GetEntryList()->FindMatchingEntry( aSearchStr, 0, true );
|
|
bSelect = false;
|
|
}
|
|
|
|
if( nSelect != LISTBOX_ENTRY_NOTFOUND )
|
|
{
|
|
if (!m_pImplLB->IsVisible(nSelect))
|
|
m_pImplLB->ShowProminentEntry( nSelect );
|
|
m_pImplLB->SelectEntry( nSelect, bSelect );
|
|
}
|
|
else
|
|
{
|
|
nSelect = m_pImplLB->GetEntryList()->GetSelectedEntryPos( 0 );
|
|
if( nSelect != LISTBOX_ENTRY_NOTFOUND )
|
|
m_pImplLB->SelectEntry( nSelect, false );
|
|
m_pImplLB->ResetCurrentPos();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
::std::set< sal_Int32 > aSelInText;
|
|
lcl_GetSelectedEntries(aSelInText, m_pSubEdit->GetText(), m_cMultiSep, m_pImplLB->GetEntryList());
|
|
for (sal_Int32 n = 0; n < m_pImplLB->GetEntryList()->GetEntryCount(); n++)
|
|
m_pImplLB->SelectEntry( n, aSelInText.count( n ) != 0 );
|
|
}
|
|
m_pImplLB->SetCallSelectionChangedHdl( true );
|
|
}
|
|
|
|
sal_Int32 ComboBox::InsertEntry(const OUString& rStr, sal_Int32 const nPos)
|
|
{
|
|
assert(nPos >= 0 && COMBOBOX_MAX_ENTRIES > m_pImpl->m_pImplLB->GetEntryList()->GetEntryCount());
|
|
|
|
sal_Int32 nRealPos;
|
|
if (nPos == COMBOBOX_APPEND)
|
|
nRealPos = nPos;
|
|
else
|
|
{
|
|
const sal_Int32 nMRUCount = m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
|
|
assert(nPos <= COMBOBOX_MAX_ENTRIES - nMRUCount);
|
|
nRealPos = nPos + nMRUCount;
|
|
}
|
|
|
|
nRealPos = m_pImpl->m_pImplLB->InsertEntry( nRealPos, rStr );
|
|
nRealPos -= m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
|
|
CallEventListeners( VclEventId::ComboboxItemAdded, reinterpret_cast<void*>(nRealPos) );
|
|
return nRealPos;
|
|
}
|
|
|
|
sal_Int32 ComboBox::InsertEntryWithImage(
|
|
const OUString& rStr, const Image& rImage, sal_Int32 const nPos)
|
|
{
|
|
assert(nPos >= 0 && COMBOBOX_MAX_ENTRIES > m_pImpl->m_pImplLB->GetEntryList()->GetEntryCount());
|
|
|
|
sal_Int32 nRealPos;
|
|
if (nPos == COMBOBOX_APPEND)
|
|
nRealPos = nPos;
|
|
else
|
|
{
|
|
const sal_Int32 nMRUCount = m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
|
|
assert(nPos <= COMBOBOX_MAX_ENTRIES - nMRUCount);
|
|
nRealPos = nPos + nMRUCount;
|
|
}
|
|
|
|
nRealPos = m_pImpl->m_pImplLB->InsertEntry( nRealPos, rStr, rImage );
|
|
nRealPos -= m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
|
|
CallEventListeners( VclEventId::ComboboxItemAdded, reinterpret_cast<void*>(nRealPos) );
|
|
return nRealPos;
|
|
}
|
|
|
|
void ComboBox::RemoveEntry( const OUString& rStr )
|
|
{
|
|
RemoveEntryAt(GetEntryPos(rStr));
|
|
}
|
|
|
|
void ComboBox::RemoveEntryAt(sal_Int32 const nPos)
|
|
{
|
|
const sal_Int32 nMRUCount = m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
|
|
if (nPos < 0 || nPos > COMBOBOX_MAX_ENTRIES - nMRUCount)
|
|
{
|
|
assert("bad position");
|
|
return;
|
|
}
|
|
m_pImpl->m_pImplLB->RemoveEntry( nPos + nMRUCount );
|
|
CallEventListeners( VclEventId::ComboboxItemRemoved, reinterpret_cast<void*>(nPos) );
|
|
}
|
|
|
|
void ComboBox::Clear()
|
|
{
|
|
if (!m_pImpl->m_pImplLB)
|
|
return;
|
|
m_pImpl->m_pImplLB->Clear();
|
|
CallEventListeners( VclEventId::ComboboxItemRemoved, reinterpret_cast<void*>(-1) );
|
|
}
|
|
|
|
Image ComboBox::GetEntryImage( sal_Int32 nPos ) const
|
|
{
|
|
if (m_pImpl->m_pImplLB->GetEntryList()->HasEntryImage(nPos))
|
|
return m_pImpl->m_pImplLB->GetEntryList()->GetEntryImage( nPos );
|
|
return Image();
|
|
}
|
|
|
|
sal_Int32 ComboBox::GetEntryPos( const OUString& rStr ) const
|
|
{
|
|
sal_Int32 nPos = m_pImpl->m_pImplLB->GetEntryList()->FindEntry( rStr );
|
|
if ( nPos != LISTBOX_ENTRY_NOTFOUND )
|
|
nPos -= m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
|
|
return nPos;
|
|
}
|
|
|
|
sal_Int32 ComboBox::GetEntryPos( const void* pData ) const
|
|
{
|
|
sal_Int32 nPos = m_pImpl->m_pImplLB->GetEntryList()->FindEntry( pData );
|
|
if ( nPos != LISTBOX_ENTRY_NOTFOUND )
|
|
nPos = nPos - m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
|
|
return nPos;
|
|
}
|
|
|
|
OUString ComboBox::GetEntry( sal_Int32 nPos ) const
|
|
{
|
|
const sal_Int32 nMRUCount = m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
|
|
if (nPos < 0 || nPos > COMBOBOX_MAX_ENTRIES - nMRUCount)
|
|
return OUString();
|
|
|
|
return m_pImpl->m_pImplLB->GetEntryList()->GetEntryText( nPos + nMRUCount );
|
|
}
|
|
|
|
sal_Int32 ComboBox::GetEntryCount() const
|
|
{
|
|
if (!m_pImpl->m_pImplLB)
|
|
return 0;
|
|
return m_pImpl->m_pImplLB->GetEntryList()->GetEntryCount() - m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
|
|
}
|
|
|
|
bool ComboBox::IsTravelSelect() const
|
|
{
|
|
return m_pImpl->m_pImplLB->IsTravelSelect();
|
|
}
|
|
|
|
bool ComboBox::IsInDropDown() const
|
|
{
|
|
return m_pImpl->m_pFloatWin && m_pImpl->m_pFloatWin->IsInPopupMode();
|
|
}
|
|
|
|
void ComboBox::EnableMultiSelection( bool bMulti )
|
|
{
|
|
m_pImpl->m_pImplLB->EnableMultiSelection( bMulti, false );
|
|
m_pImpl->m_pImplLB->SetMultiSelectionSimpleMode( true );
|
|
}
|
|
|
|
bool ComboBox::IsMultiSelectionEnabled() const
|
|
{
|
|
return m_pImpl->m_pImplLB->IsMultiSelectionEnabled();
|
|
}
|
|
|
|
void ComboBox::SetSelectHdl(const Link<ComboBox&,void>& rLink) { m_pImpl->m_SelectHdl = rLink; }
|
|
|
|
const Link<ComboBox&,void>& ComboBox::GetSelectHdl() const { return m_pImpl->m_SelectHdl; }
|
|
|
|
void ComboBox::SetDoubleClickHdl(const Link<ComboBox&,void>& rLink) { m_pImpl->m_DoubleClickHdl = rLink; }
|
|
|
|
const Link<ComboBox&,void>& ComboBox::GetDoubleClickHdl() const { return m_pImpl->m_DoubleClickHdl; }
|
|
|
|
void ComboBox::SetEntryActivateHdl(const Link<Edit&,bool>& rLink)
|
|
{
|
|
if (!m_pImpl->m_pSubEdit)
|
|
return;
|
|
m_pImpl->m_pSubEdit->SetActivateHdl(rLink);
|
|
}
|
|
|
|
long ComboBox::CalcWindowSizePixel(sal_uInt16 nLines) const
|
|
{
|
|
return m_pImpl->m_pImplLB->GetEntryHeight() * nLines;
|
|
}
|
|
|
|
Size ComboBox::GetOptimalSize() const
|
|
{
|
|
return CalcMinimumSize();
|
|
}
|
|
|
|
long ComboBox::getMaxWidthScrollBarAndDownButton() const
|
|
{
|
|
long nButtonDownWidth = 0;
|
|
|
|
vcl::Window *pBorder = GetWindow( GetWindowType::Border );
|
|
ImplControlValue aControlValue;
|
|
tools::Rectangle aContent, aBound;
|
|
|
|
// use the full extent of the control
|
|
tools::Rectangle aArea( Point(), pBorder->GetOutputSizePixel() );
|
|
|
|
if ( GetNativeControlRegion(ControlType::Combobox, ControlPart::ButtonDown,
|
|
aArea, ControlState::NONE, aControlValue, aBound, aContent) )
|
|
{
|
|
nButtonDownWidth = aContent.getWidth();
|
|
}
|
|
|
|
long nScrollBarWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
|
|
|
|
return std::max(nScrollBarWidth, nButtonDownWidth);
|
|
}
|
|
|
|
Size ComboBox::CalcMinimumSize() const
|
|
{
|
|
Size aSz;
|
|
|
|
if (!m_pImpl->m_pImplLB)
|
|
return aSz;
|
|
|
|
if (!IsDropDownBox())
|
|
{
|
|
aSz = m_pImpl->m_pImplLB->CalcSize( m_pImpl->m_pImplLB->GetEntryList()->GetEntryCount() );
|
|
aSz.AdjustHeight(m_pImpl->m_nDDHeight );
|
|
}
|
|
else
|
|
{
|
|
aSz.setHeight( Edit::CalcMinimumSizeForText(GetText()).Height() );
|
|
|
|
if (m_pImpl->m_nWidthInChars!= -1)
|
|
aSz.setWidth(m_pImpl->m_nWidthInChars * approximate_digit_width());
|
|
else
|
|
aSz.setWidth(m_pImpl->m_pImplLB->GetMaxEntryWidth());
|
|
}
|
|
|
|
if (m_pImpl->m_nMaxWidthChars != -1)
|
|
{
|
|
long nMaxWidth = m_pImpl->m_nMaxWidthChars * approximate_char_width();
|
|
aSz.setWidth( std::min(aSz.Width(), nMaxWidth) );
|
|
}
|
|
|
|
if (IsDropDownBox())
|
|
aSz.AdjustWidth(getMaxWidthScrollBarAndDownButton() );
|
|
|
|
ComboBoxBounds aBounds(m_pImpl->calcComboBoxDropDownComponentBounds(
|
|
Size(0xFFFF, 0xFFFF), Size(0xFFFF, 0xFFFF)));
|
|
aSz.AdjustWidth(aBounds.aSubEditPos.X()*2 );
|
|
|
|
aSz.AdjustWidth(ImplGetExtraXOffset() * 2 );
|
|
|
|
aSz = CalcWindowSize( aSz );
|
|
return aSz;
|
|
}
|
|
|
|
Size ComboBox::CalcAdjustedSize( const Size& rPrefSize ) const
|
|
{
|
|
Size aSz = rPrefSize;
|
|
sal_Int32 nLeft, nTop, nRight, nBottom;
|
|
static_cast<vcl::Window*>(const_cast<ComboBox *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
|
|
aSz.AdjustHeight( -(nTop+nBottom) );
|
|
if ( !IsDropDownBox() )
|
|
{
|
|
long nEntryHeight = CalcBlockSize( 1, 1 ).Height();
|
|
long nLines = aSz.Height() / nEntryHeight;
|
|
if ( nLines < 1 )
|
|
nLines = 1;
|
|
aSz.setHeight( nLines * nEntryHeight );
|
|
aSz.AdjustHeight(m_pImpl->m_nDDHeight );
|
|
}
|
|
else
|
|
{
|
|
aSz.setHeight( m_pImpl->m_nDDHeight );
|
|
}
|
|
aSz.AdjustHeight(nTop+nBottom );
|
|
|
|
aSz = CalcWindowSize( aSz );
|
|
return aSz;
|
|
}
|
|
|
|
Size ComboBox::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
|
|
{
|
|
// show ScrollBars where appropriate
|
|
Size aMinSz = CalcMinimumSize();
|
|
Size aSz;
|
|
|
|
// height
|
|
if ( nLines )
|
|
{
|
|
if ( !IsDropDownBox() )
|
|
aSz.setHeight( m_pImpl->m_pImplLB->CalcSize( nLines ).Height() + m_pImpl->m_nDDHeight );
|
|
else
|
|
aSz.setHeight( m_pImpl->m_nDDHeight );
|
|
}
|
|
else
|
|
aSz.setHeight( aMinSz.Height() );
|
|
|
|
// width
|
|
if ( nColumns )
|
|
aSz.setWidth( nColumns * approximate_char_width() );
|
|
else
|
|
aSz.setWidth( aMinSz.Width() );
|
|
|
|
if ( IsDropDownBox() )
|
|
aSz.AdjustWidth(getMaxWidthScrollBarAndDownButton() );
|
|
|
|
if ( !IsDropDownBox() )
|
|
{
|
|
if ( aSz.Width() < aMinSz.Width() )
|
|
aSz.AdjustHeight(GetSettings().GetStyleSettings().GetScrollBarSize() );
|
|
if ( aSz.Height() < aMinSz.Height() )
|
|
aSz.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() );
|
|
}
|
|
|
|
aSz.AdjustWidth(ImplGetExtraXOffset() * 2 );
|
|
|
|
aSz = CalcWindowSize( aSz );
|
|
return aSz;
|
|
}
|
|
|
|
void ComboBox::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
|
|
{
|
|
long nCharWidth = GetTextWidth(OUString(u'x'));
|
|
if ( !IsDropDownBox() )
|
|
{
|
|
Size aOutSz = m_pImpl->m_pImplLB->GetMainWindow()->GetOutputSizePixel();
|
|
rnCols = (nCharWidth > 0) ? static_cast<sal_uInt16>(aOutSz.Width()/nCharWidth) : 1;
|
|
rnLines = static_cast<sal_uInt16>(aOutSz.Height()/m_pImpl->m_pImplLB->GetEntryHeight());
|
|
}
|
|
else
|
|
{
|
|
Size aOutSz = m_pImpl->m_pSubEdit->GetOutputSizePixel();
|
|
rnCols = (nCharWidth > 0) ? static_cast<sal_uInt16>(aOutSz.Width()/nCharWidth) : 1;
|
|
rnLines = 1;
|
|
}
|
|
}
|
|
|
|
void ComboBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, DrawFlags nFlags )
|
|
{
|
|
m_pImpl->m_pImplLB->GetMainWindow()->ApplySettings(*pDev);
|
|
|
|
Point aPos = pDev->LogicToPixel( rPos );
|
|
Size aSize = pDev->LogicToPixel( rSize );
|
|
vcl::Font aFont = m_pImpl->m_pImplLB->GetMainWindow()->GetDrawPixelFont( pDev );
|
|
OutDevType eOutDevType = pDev->GetOutDevType();
|
|
|
|
pDev->Push();
|
|
pDev->SetMapMode();
|
|
pDev->SetFont( aFont );
|
|
pDev->SetTextFillColor();
|
|
|
|
// Border/Background
|
|
pDev->SetLineColor();
|
|
pDev->SetFillColor();
|
|
bool bBorder = (GetStyle() & WB_BORDER);
|
|
bool bBackground = IsControlBackground();
|
|
if ( bBorder || bBackground )
|
|
{
|
|
tools::Rectangle aRect( aPos, aSize );
|
|
// aRect.Top() += nEditHeight;
|
|
if ( bBorder )
|
|
{
|
|
ImplDrawFrame( pDev, aRect );
|
|
}
|
|
if ( bBackground )
|
|
{
|
|
pDev->SetFillColor( GetControlBackground() );
|
|
pDev->DrawRect( aRect );
|
|
}
|
|
}
|
|
|
|
// contents
|
|
if ( !IsDropDownBox() )
|
|
{
|
|
long nOnePixel = GetDrawPixel( pDev, 1 );
|
|
long nTextHeight = pDev->GetTextHeight();
|
|
long nEditHeight = nTextHeight + 6*nOnePixel;
|
|
DrawTextFlags nTextStyle = DrawTextFlags::VCenter;
|
|
|
|
// First, draw the edit part
|
|
m_pImpl->m_pSubEdit->Draw( pDev, aPos, Size( aSize.Width(), nEditHeight ), nFlags );
|
|
|
|
// Second, draw the listbox
|
|
if ( GetStyle() & WB_CENTER )
|
|
nTextStyle |= DrawTextFlags::Center;
|
|
else if ( GetStyle() & WB_RIGHT )
|
|
nTextStyle |= DrawTextFlags::Right;
|
|
else
|
|
nTextStyle |= DrawTextFlags::Left;
|
|
|
|
if ( ( nFlags & DrawFlags::Mono ) || ( eOutDevType == OUTDEV_PRINTER ) )
|
|
{
|
|
pDev->SetTextColor( COL_BLACK );
|
|
}
|
|
else
|
|
{
|
|
if ( !IsEnabled() )
|
|
{
|
|
const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
|
|
pDev->SetTextColor( rStyleSettings.GetDisableColor() );
|
|
}
|
|
else
|
|
{
|
|
pDev->SetTextColor( GetTextColor() );
|
|
}
|
|
}
|
|
|
|
tools::Rectangle aClip( aPos, aSize );
|
|
pDev->IntersectClipRegion( aClip );
|
|
sal_Int32 nLines = static_cast<sal_Int32>( nTextHeight > 0 ? (aSize.Height()-nEditHeight)/nTextHeight : 1 );
|
|
if ( !nLines )
|
|
nLines = 1;
|
|
const sal_Int32 nTEntry = IsReallyVisible() ? m_pImpl->m_pImplLB->GetTopEntry() : 0;
|
|
|
|
tools::Rectangle aTextRect( aPos, aSize );
|
|
|
|
aTextRect.AdjustLeft(3*nOnePixel );
|
|
aTextRect.AdjustRight( -(3*nOnePixel) );
|
|
aTextRect.AdjustTop(nEditHeight + nOnePixel );
|
|
aTextRect.SetBottom( aTextRect.Top() + nTextHeight );
|
|
|
|
// the drawing starts here
|
|
for ( sal_Int32 n = 0; n < nLines; ++n )
|
|
{
|
|
pDev->DrawText( aTextRect, m_pImpl->m_pImplLB->GetEntryList()->GetEntryText( n+nTEntry ), nTextStyle );
|
|
aTextRect.AdjustTop(nTextHeight );
|
|
aTextRect.AdjustBottom(nTextHeight );
|
|
}
|
|
}
|
|
|
|
pDev->Pop();
|
|
|
|
// Call Edit::Draw after restoring the MapMode...
|
|
if ( IsDropDownBox() )
|
|
{
|
|
m_pImpl->m_pSubEdit->Draw( pDev, rPos, rSize, nFlags );
|
|
// DD-Button ?
|
|
}
|
|
|
|
}
|
|
|
|
IMPL_LINK(ComboBox::Impl, ImplUserDrawHdl, UserDrawEvent*, pEvent, void)
|
|
{
|
|
m_rThis.UserDraw(*pEvent);
|
|
}
|
|
|
|
void ComboBox::UserDraw( const UserDrawEvent& )
|
|
{
|
|
}
|
|
|
|
void ComboBox::SetUserItemSize( const Size& rSz )
|
|
{
|
|
m_pImpl->m_pImplLB->GetMainWindow()->SetUserItemSize( rSz );
|
|
}
|
|
|
|
void ComboBox::EnableUserDraw( bool bUserDraw )
|
|
{
|
|
m_pImpl->m_pImplLB->GetMainWindow()->EnableUserDraw( bUserDraw );
|
|
}
|
|
|
|
void ComboBox::DrawEntry(const UserDrawEvent& rEvt, bool bDrawImage, bool bDrawText, bool bDrawTextAtImagePos)
|
|
{
|
|
SAL_WARN_IF(rEvt.GetWindow() != m_pImpl->m_pImplLB->GetMainWindow(), "vcl", "DrawEntry?!");
|
|
m_pImpl->m_pImplLB->GetMainWindow()->DrawEntry(*rEvt.GetRenderContext(), rEvt.GetItemId(), bDrawImage, bDrawText, bDrawTextAtImagePos);
|
|
}
|
|
|
|
void ComboBox::SetSeparatorPos( sal_Int32 n )
|
|
{
|
|
m_pImpl->m_pImplLB->SetSeparatorPos( n );
|
|
}
|
|
|
|
void ComboBox::AddSeparator( sal_Int32 n )
|
|
{
|
|
m_pImpl->m_pImplLB->AddSeparator( n );
|
|
}
|
|
|
|
void ComboBox::SetMRUEntries( const OUString& rEntries )
|
|
{
|
|
m_pImpl->m_pImplLB->SetMRUEntries( rEntries, ';' );
|
|
}
|
|
|
|
OUString ComboBox::GetMRUEntries() const
|
|
{
|
|
return m_pImpl->m_pImplLB ? m_pImpl->m_pImplLB->GetMRUEntries( ';' ) : OUString();
|
|
}
|
|
|
|
void ComboBox::SetMaxMRUCount( sal_Int32 n )
|
|
{
|
|
m_pImpl->m_pImplLB->SetMaxMRUCount( n );
|
|
}
|
|
|
|
sal_Int32 ComboBox::GetMaxMRUCount() const
|
|
{
|
|
return m_pImpl->m_pImplLB ? m_pImpl->m_pImplLB->GetMaxMRUCount() : 0;
|
|
}
|
|
|
|
sal_uInt16 ComboBox::GetDisplayLineCount() const
|
|
{
|
|
return m_pImpl->m_pImplLB ? m_pImpl->m_pImplLB->GetDisplayLineCount() : 0;
|
|
}
|
|
|
|
void ComboBox::SetEntryData( sal_Int32 nPos, void* pNewData )
|
|
{
|
|
m_pImpl->m_pImplLB->SetEntryData( nPos + m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount(), pNewData );
|
|
}
|
|
|
|
void* ComboBox::GetEntryData( sal_Int32 nPos ) const
|
|
{
|
|
return m_pImpl->m_pImplLB->GetEntryList()->GetEntryData(
|
|
nPos + m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount() );
|
|
}
|
|
|
|
sal_Int32 ComboBox::GetTopEntry() const
|
|
{
|
|
sal_Int32 nPos = GetEntryCount() ? m_pImpl->m_pImplLB->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND;
|
|
if (nPos < m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount())
|
|
nPos = 0;
|
|
return nPos;
|
|
}
|
|
|
|
void ComboBox::SetProminentEntryType( ProminentEntry eType )
|
|
{
|
|
m_pImpl->m_pImplLB->SetProminentEntryType( eType );
|
|
}
|
|
|
|
tools::Rectangle ComboBox::GetDropDownPosSizePixel() const
|
|
{
|
|
return m_pImpl->m_pFloatWin
|
|
? m_pImpl->m_pFloatWin->GetWindowExtentsRelative(const_cast<ComboBox*>(this))
|
|
: tools::Rectangle();
|
|
}
|
|
|
|
const Wallpaper& ComboBox::GetDisplayBackground() const
|
|
{
|
|
if (!m_pImpl->m_pSubEdit->IsBackground())
|
|
return Control::GetDisplayBackground();
|
|
|
|
const Wallpaper& rBack = m_pImpl->m_pSubEdit->GetBackground();
|
|
if( ! rBack.IsBitmap() &&
|
|
! rBack.IsGradient() &&
|
|
rBack.GetColor() == COL_TRANSPARENT
|
|
)
|
|
return Control::GetDisplayBackground();
|
|
return rBack;
|
|
}
|
|
|
|
sal_Int32 ComboBox::GetSelectedEntryCount() const
|
|
{
|
|
return m_pImpl->m_pImplLB->GetEntryList()->GetSelectedEntryCount();
|
|
}
|
|
|
|
sal_Int32 ComboBox::GetSelectedEntryPos( sal_Int32 nIndex ) const
|
|
{
|
|
sal_Int32 nPos = m_pImpl->m_pImplLB->GetEntryList()->GetSelectedEntryPos( nIndex );
|
|
if ( nPos != LISTBOX_ENTRY_NOTFOUND )
|
|
{
|
|
if (nPos < m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount())
|
|
nPos = m_pImpl->m_pImplLB->GetEntryList()->FindEntry(m_pImpl->m_pImplLB->GetEntryList()->GetEntryText(nPos));
|
|
nPos = sal::static_int_cast<sal_Int32>(nPos - m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount());
|
|
}
|
|
return nPos;
|
|
}
|
|
|
|
bool ComboBox::IsEntryPosSelected( sal_Int32 nPos ) const
|
|
{
|
|
return m_pImpl->m_pImplLB->GetEntryList()->IsEntryPosSelected(
|
|
nPos + m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount() );
|
|
}
|
|
|
|
void ComboBox::SelectEntryPos( sal_Int32 nPos, bool bSelect)
|
|
{
|
|
if (nPos < m_pImpl->m_pImplLB->GetEntryList()->GetEntryCount())
|
|
m_pImpl->m_pImplLB->SelectEntry(
|
|
nPos + m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount(), bSelect);
|
|
}
|
|
|
|
void ComboBox::SetNoSelection()
|
|
{
|
|
m_pImpl->m_pImplLB->SetNoSelection();
|
|
m_pImpl->m_pSubEdit->SetText( OUString() );
|
|
}
|
|
|
|
tools::Rectangle ComboBox::GetBoundingRectangle( sal_Int32 nItem ) const
|
|
{
|
|
tools::Rectangle aRect = m_pImpl->m_pImplLB->GetMainWindow()->GetBoundingRectangle( nItem );
|
|
tools::Rectangle aOffset = m_pImpl->m_pImplLB->GetMainWindow()->GetWindowExtentsRelative( static_cast<vcl::Window*>(const_cast<ComboBox *>(this)) );
|
|
aRect.Move( aOffset.TopLeft().X(), aOffset.TopLeft().Y() );
|
|
return aRect;
|
|
}
|
|
|
|
void ComboBox::SetBorderStyle( WindowBorderStyle nBorderStyle )
|
|
{
|
|
Window::SetBorderStyle( nBorderStyle );
|
|
if ( !IsDropDownBox() )
|
|
{
|
|
m_pImpl->m_pSubEdit->SetBorderStyle( nBorderStyle );
|
|
m_pImpl->m_pImplLB->SetBorderStyle( nBorderStyle );
|
|
}
|
|
}
|
|
|
|
long ComboBox::GetIndexForPoint( const Point& rPoint, sal_Int32& 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* rMain = m_pImpl->m_pImplLB->GetMainWindow();
|
|
|
|
// convert coordinates to ImplListBoxWindow pixel coordinate space
|
|
Point aConvPoint = LogicToPixel( rPoint );
|
|
aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
|
|
aConvPoint = rMain->AbsoluteScreenToOutputPixel( aConvPoint );
|
|
aConvPoint = rMain->PixelToLogic( aConvPoint );
|
|
|
|
// try to find entry
|
|
sal_Int32 nEntry = rMain->GetEntryPosForPoint( aConvPoint );
|
|
if( nEntry == LISTBOX_ENTRY_NOTFOUND )
|
|
nIndex = -1;
|
|
else
|
|
rPos = nEntry;
|
|
}
|
|
|
|
// get line relative index
|
|
if( nIndex != -1 )
|
|
nIndex = ToRelativeLineIndex( nIndex );
|
|
|
|
return nIndex;
|
|
}
|
|
|
|
ComboBoxBounds ComboBox::Impl::calcComboBoxDropDownComponentBounds(
|
|
const Size &rOutSz, const Size &rBorderOutSz) const
|
|
{
|
|
ComboBoxBounds aBounds;
|
|
|
|
long nTop = 0;
|
|
long nBottom = rOutSz.Height();
|
|
|
|
vcl::Window *pBorder = m_rThis.GetWindow( GetWindowType::Border );
|
|
ImplControlValue aControlValue;
|
|
Point aPoint;
|
|
tools::Rectangle aContent, aBound;
|
|
|
|
// use the full extent of the control
|
|
tools::Rectangle aArea( aPoint, rBorderOutSz );
|
|
|
|
if (m_rThis.GetNativeControlRegion(ControlType::Combobox, ControlPart::ButtonDown,
|
|
aArea, ControlState::NONE, aControlValue, aBound, aContent) )
|
|
{
|
|
// convert back from border space to local coordinates
|
|
aPoint = pBorder->ScreenToOutputPixel(m_rThis.OutputToScreenPixel(aPoint));
|
|
aContent.Move(-aPoint.X(), -aPoint.Y());
|
|
|
|
aBounds.aButtonPos = Point(aContent.Left(), nTop);
|
|
aBounds.aButtonSize = Size(aContent.getWidth(), (nBottom-nTop));
|
|
|
|
// adjust the size of the edit field
|
|
if (m_rThis.GetNativeControlRegion(ControlType::Combobox, ControlPart::SubEdit,
|
|
aArea, ControlState::NONE, aControlValue, aBound, aContent) )
|
|
{
|
|
// convert back from border space to local coordinates
|
|
aContent.Move(-aPoint.X(), -aPoint.Y());
|
|
|
|
// use the themes drop down size
|
|
aBounds.aSubEditPos = aContent.TopLeft();
|
|
aBounds.aSubEditSize = aContent.GetSize();
|
|
}
|
|
else
|
|
{
|
|
// use the themes drop down size for the button
|
|
aBounds.aSubEditSize = Size(rOutSz.Width() - aContent.getWidth(), rOutSz.Height());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
long nSBWidth = m_rThis.GetSettings().GetStyleSettings().GetScrollBarSize();
|
|
nSBWidth = m_rThis.CalcZoom( nSBWidth );
|
|
aBounds.aSubEditSize = Size(rOutSz.Width() - nSBWidth, rOutSz.Height());
|
|
aBounds.aButtonPos = Point(rOutSz.Width() - nSBWidth, nTop);
|
|
aBounds.aButtonSize = Size(nSBWidth, (nBottom-nTop));
|
|
}
|
|
return aBounds;
|
|
}
|
|
|
|
void ComboBox::SetWidthInChars(sal_Int32 nWidthInChars)
|
|
{
|
|
if (nWidthInChars != m_pImpl->m_nWidthInChars)
|
|
{
|
|
m_pImpl->m_nWidthInChars = nWidthInChars;
|
|
queue_resize();
|
|
}
|
|
}
|
|
|
|
void ComboBox::setMaxWidthChars(sal_Int32 nWidth)
|
|
{
|
|
if (nWidth != m_pImpl->m_nMaxWidthChars)
|
|
{
|
|
m_pImpl->m_nMaxWidthChars = nWidth;
|
|
queue_resize();
|
|
}
|
|
}
|
|
|
|
bool ComboBox::set_property(const OString &rKey, const OUString &rValue)
|
|
{
|
|
if (rKey == "width-chars")
|
|
SetWidthInChars(rValue.toInt32());
|
|
else if (rKey == "max-width-chars")
|
|
setMaxWidthChars(rValue.toInt32());
|
|
else if (rKey == "can-focus")
|
|
{
|
|
// as far as I can see in Gtk, setting a ComboBox as can.focus means
|
|
// the focus gets stuck in it, so try here to behave like gtk does
|
|
// with the settings that work, i.e. can.focus of false doesn't
|
|
// set the hard WB_NOTABSTOP
|
|
WinBits nBits = GetStyle();
|
|
nBits &= ~(WB_TABSTOP|WB_NOTABSTOP);
|
|
if (toBool(rValue))
|
|
nBits |= WB_TABSTOP;
|
|
SetStyle(nBits);
|
|
}
|
|
else
|
|
return Control::set_property(rKey, rValue);
|
|
return true;
|
|
}
|
|
|
|
FactoryFunction ComboBox::GetUITestFactory() const
|
|
{
|
|
return ComboBoxUIObject::create;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|