LibreOffice Module vcl (master)  1
combobox.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <vcl/combobox.hxx>
21 
22 #include <set>
23 
24 #include <comphelper/string.hxx>
25 #include <vcl/lstbox.hxx>
26 #include <vcl/commandevent.hxx>
27 #include <vcl/event.hxx>
28 #include <vcl/settings.hxx>
29 #include <vcl/uitest/uiobject.hxx>
30 #include <sal/log.hxx>
31 
32 #include <listbox.hxx>
33 #include <controldata.hxx>
34 #include <comphelper/lok.hxx>
35 
36 namespace {
37 
38 struct ComboBoxBounds
39 {
40  Point aSubEditPos;
41  Size aSubEditSize;
42 
43  Point aButtonPos;
44  Size aButtonSize;
45 };
46 
47 }
48 
50 {
56  sal_uInt16 m_nDDHeight;
58  bool m_isDDAutoSize : 1;
60  bool m_isMatchCase : 1;
61  sal_Int32 m_nMaxWidthChars;
62  sal_Int32 m_nWidthInChars;
65 
66  explicit Impl(ComboBox & rThis)
67  : m_rThis(rThis)
68  , m_nDDHeight(0)
69  , m_cMultiSep(0)
70  , m_isDDAutoSize(false)
71  , m_isSyntheticModify(false)
72  , m_isMatchCase(false)
73  , m_nMaxWidthChars(0)
74  , m_nWidthInChars(-1)
75  {
76  }
77 
78  void ImplInitComboBoxData();
81  const Size &rOutSize, const Size &rBorderOutSize) const;
82 
83  DECL_LINK( ImplSelectHdl, LinkParamNone*, void );
84  DECL_LINK( ImplCancelHdl, LinkParamNone*, void );
85  DECL_LINK( ImplDoubleClickHdl, ImplListBoxWindow*, void );
86  DECL_LINK( ImplClickBtnHdl, void*, void );
87  DECL_LINK( ImplPopupModeEndHdl, FloatingWindow*, void );
88  DECL_LINK( ImplSelectionChangedHdl, sal_Int32, void );
89  DECL_LINK( ImplUserDrawHdl, UserDrawEvent*, void );
90  DECL_LINK( ImplAutocompleteHdl, Edit&, void );
91  DECL_LINK( ImplListItemSelectHdl , LinkParamNone*, void );
92 };
93 
94 
95 static void lcl_GetSelectedEntries( ::std::set< sal_Int32 >& rSelectedPos, const OUString& rText, sal_Unicode cTokenSep, const ImplEntryList* pEntryList )
96 {
97  if (rText.isEmpty())
98  return;
99 
100  sal_Int32 nIdx{0};
101  do {
102  const sal_Int32 nPos = pEntryList->FindEntry(comphelper::string::strip(rText.getToken(0, cTokenSep, nIdx), ' '));
103  if ( nPos != LISTBOX_ENTRY_NOTFOUND )
104  rSelectedPos.insert( nPos );
105  } while (nIdx>=0);
106 }
107 
108 ComboBox::ComboBox(vcl::Window *const pParent, WinBits const nStyle)
109  : Edit( WindowType::COMBOBOX )
110  , m_pImpl(new Impl(*this))
111 {
112  m_pImpl->ImplInitComboBoxData();
113  ImplInit( pParent, nStyle );
114  SetWidthInChars(-1);
115 }
116 
118 {
119  disposeOnce();
120 }
121 
123 {
124  m_pImpl->m_pSubEdit.disposeAndClear();
125 
126  VclPtr< ImplListBox > pImplLB = m_pImpl->m_pImplLB;
127  m_pImpl->m_pImplLB.clear();
128  pImplLB.disposeAndClear();
129 
130  m_pImpl->m_pFloatWin.disposeAndClear();
131  m_pImpl->m_pBtn.disposeAndClear();
132  Edit::dispose();
133 }
134 
136 {
138  m_pBtn = nullptr;
139  m_pImplLB = nullptr;
140  m_pFloatWin = nullptr;
141 
142  m_nDDHeight = 0;
143  m_isDDAutoSize = true;
144  m_isSyntheticModify = false;
145  m_isMatchCase = false;
146  m_cMultiSep = ';';
147  m_nMaxWidthChars = -1;
148  m_nWidthInChars = -1;
149 }
150 
152 {
153  sal_Int32 nLeft, nTop, nRight, nBottom;
154  GetBorder( nLeft, nTop, nRight, nBottom );
155  m_pImpl->m_nDDHeight = static_cast<sal_uInt16>(m_pImpl->m_pSubEdit->GetTextHeight() + nTop + nBottom + 4);
156  if ( !IsDropDownBox() )
157  m_pImpl->m_nDDHeight += 4;
158 
159  tools::Rectangle aCtrlRegion( Point( 0, 0 ), Size( 10, 10 ) );
160  tools::Rectangle aBoundRegion, aContentRegion;
161  ImplControlValue aControlValue;
164  aCtrlRegion,
166  aControlValue,
167  aBoundRegion, aContentRegion ) )
168  {
169  const long nNCHeight = aBoundRegion.GetHeight();
170  if (m_pImpl->m_nDDHeight < nNCHeight)
171  m_pImpl->m_nDDHeight = sal::static_int_cast<sal_uInt16>(nNCHeight);
172  }
173 }
174 
175 void ComboBox::ImplInit( vcl::Window* pParent, WinBits nStyle )
176 {
177  bool bNoBorder = ( nStyle & WB_NOBORDER ) != 0;
178  if ( !(nStyle & WB_DROPDOWN) )
179  {
180  nStyle &= ~WB_BORDER;
181  nStyle |= WB_NOBORDER;
182  }
183  else
184  {
185  if ( !bNoBorder )
186  nStyle |= WB_BORDER;
187  }
188 
189  Edit::ImplInit( pParent, nStyle );
190  SetBackground();
191 
192  // DropDown ?
193  WinBits nEditStyle = nStyle & ( WB_LEFT | WB_RIGHT | WB_CENTER );
194  WinBits nListStyle = nStyle;
195  if( nStyle & WB_DROPDOWN )
196  {
197  m_pImpl->m_pFloatWin = VclPtr<ImplListBoxFloatingWindow>::Create( this );
199  m_pImpl->m_pFloatWin->RequestDoubleBuffering(true);
200  m_pImpl->m_pFloatWin->SetAutoWidth( true );
201  m_pImpl->m_pFloatWin->SetPopupModeEndHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplPopupModeEndHdl) );
202 
204  ImplInitDropDownButton( m_pImpl->m_pBtn );
205  m_pImpl->m_pBtn->SetMBDownHdl( LINK( m_pImpl.get(), ComboBox::Impl, ImplClickBtnHdl ) );
206  m_pImpl->m_pBtn->Show();
207 
208  nEditStyle |= WB_NOBORDER;
209  nListStyle &= ~WB_BORDER;
210  nListStyle |= WB_NOBORDER;
211  }
212  else
213  {
214  if ( !bNoBorder )
215  {
216  nEditStyle |= WB_BORDER;
217  nListStyle &= ~WB_NOBORDER;
218  nListStyle |= WB_BORDER;
219  }
220  }
221 
222  m_pImpl->m_pSubEdit.set( VclPtr<Edit>::Create( this, nEditStyle ) );
223  m_pImpl->m_pSubEdit->EnableRTL( false );
224  SetSubEdit( m_pImpl->m_pSubEdit );
225  m_pImpl->m_pSubEdit->SetPosPixel( Point() );
226  EnableAutocomplete( true );
227  m_pImpl->m_pSubEdit->Show();
228 
229  vcl::Window* pLBParent = this;
230  if (m_pImpl->m_pFloatWin)
231  pLBParent = m_pImpl->m_pFloatWin;
232  m_pImpl->m_pImplLB = VclPtr<ImplListBox>::Create( pLBParent, nListStyle|WB_SIMPLEMODE|WB_AUTOHSCROLL );
233  m_pImpl->m_pImplLB->SetPosPixel( Point() );
234  m_pImpl->m_pImplLB->SetSelectHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplSelectHdl) );
235  m_pImpl->m_pImplLB->SetCancelHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplCancelHdl) );
236  m_pImpl->m_pImplLB->SetDoubleClickHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplDoubleClickHdl) );
237  m_pImpl->m_pImplLB->SetUserDrawHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplUserDrawHdl) );
238  m_pImpl->m_pImplLB->SetSelectionChangedHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplSelectionChangedHdl) );
239  m_pImpl->m_pImplLB->SetListItemSelectHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplListItemSelectHdl) );
240  m_pImpl->m_pImplLB->Show();
241 
242  if (m_pImpl->m_pFloatWin)
243  m_pImpl->m_pFloatWin->SetImplListBox( m_pImpl->m_pImplLB );
244  else
245  m_pImpl->m_pImplLB->GetMainWindow()->AllowGrabFocus( true );
246 
248 
249  SetCompoundControl( true );
250 }
251 
253 {
254  if ( !(nStyle & WB_NOTABSTOP) )
255  nStyle |= WB_TABSTOP;
256  if ( !(nStyle & WB_NOGROUP) )
257  nStyle |= WB_GROUP;
258  return nStyle;
259 }
260 
261 void ComboBox::EnableAutocomplete( bool bEnable, bool bMatchCase )
262 {
263  m_pImpl->m_isMatchCase = bMatchCase;
264 
265  if ( bEnable )
266  m_pImpl->m_pSubEdit->SetAutocompleteHdl( LINK(m_pImpl.get(), ComboBox::Impl, ImplAutocompleteHdl) );
267  else
268  m_pImpl->m_pSubEdit->SetAutocompleteHdl( Link<Edit&,void>() );
269 }
270 
272 {
273  return m_pImpl->m_pSubEdit->GetAutocompleteHdl().IsSet();
274 }
275 
276 IMPL_LINK_NOARG(ComboBox::Impl, ImplClickBtnHdl, void*, void)
277 {
278  m_rThis.CallEventListeners( VclEventId::DropdownPreOpen );
279  m_pSubEdit->GrabFocus();
280  if (!m_pImplLB->GetEntryList()->GetMRUCount())
281  ImplUpdateFloatSelection();
282  else
283  m_pImplLB->SelectEntry( 0 , true );
284  m_pBtn->SetPressed( true );
285  m_rThis.SetSelection( Selection( 0, SELECTION_MAX ) );
286  m_pFloatWin->StartFloat( true );
287  m_rThis.CallEventListeners( VclEventId::DropdownOpen );
288 
289  m_rThis.ImplClearLayoutData();
290  if (m_pImplLB)
291  m_pImplLB->GetMainWindow()->ImplClearLayoutData();
292 }
293 
294 IMPL_LINK_NOARG(ComboBox::Impl, ImplPopupModeEndHdl, FloatingWindow*, void)
295 {
296  if (m_pFloatWin->IsPopupModeCanceled())
297  {
298  if (!m_pImplLB->GetEntryList()->IsEntryPosSelected(
299  m_pFloatWin->GetPopupModeStartSaveSelection()))
300  {
301  m_pImplLB->SelectEntry(m_pFloatWin->GetPopupModeStartSaveSelection(), true);
302  bool bTravelSelect = m_pImplLB->IsTravelSelect();
303  m_pImplLB->SetTravelSelect( true );
304  m_rThis.Select();
305  m_pImplLB->SetTravelSelect( bTravelSelect );
306  }
307  }
308 
309  m_rThis.ImplClearLayoutData();
310  if (m_pImplLB)
311  m_pImplLB->GetMainWindow()->ImplClearLayoutData();
312 
313  m_pBtn->SetPressed( false );
314  m_rThis.CallEventListeners( VclEventId::DropdownClose );
315 }
316 
317 IMPL_LINK(ComboBox::Impl, ImplAutocompleteHdl, Edit&, rEdit, void)
318 {
319  Selection aSel = rEdit.GetSelection();
320 
321  {
322  OUString aFullText = rEdit.GetText();
323  OUString aStartText = aFullText.copy( 0, static_cast<sal_Int32>(aSel.Max()) );
324  sal_Int32 nStart = m_pImplLB->GetCurrentPos();
325 
326  if ( nStart == LISTBOX_ENTRY_NOTFOUND )
327  nStart = 0;
328 
329  sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND;
330  if (!m_isMatchCase)
331  {
332  // Try match case insensitive from current position
333  nPos = m_pImplLB->GetEntryList()->FindMatchingEntry(aStartText, nStart, true);
334  if ( nPos == LISTBOX_ENTRY_NOTFOUND )
335  // Try match case insensitive, but from start
336  nPos = m_pImplLB->GetEntryList()->FindMatchingEntry(aStartText, 0, true);
337  }
338 
339  if ( nPos == LISTBOX_ENTRY_NOTFOUND )
340  // Try match full from current position
341  nPos = m_pImplLB->GetEntryList()->FindMatchingEntry(aStartText, nStart, false);
342  if ( nPos == LISTBOX_ENTRY_NOTFOUND )
343  // Match full, but from start
344  nPos = m_pImplLB->GetEntryList()->FindMatchingEntry(aStartText, 0, false);
345 
346  if ( nPos != LISTBOX_ENTRY_NOTFOUND )
347  {
348  OUString aText = m_pImplLB->GetEntryList()->GetEntryText( nPos );
349  Selection aSelection( aText.getLength(), aStartText.getLength() );
350  rEdit.SetText( aText, aSelection );
351  }
352  }
353 }
354 
356 {
357  bool bPopup = m_rThis.IsInDropDown();
358  bool bCallSelect = false;
359  if (m_pImplLB->IsSelectionChanged() || bPopup)
360  {
361  OUString aText;
362  if (m_rThis.IsMultiSelectionEnabled())
363  {
364  aText = m_pSubEdit->GetText();
365 
366  // remove all entries to which there is an entry, but which is not selected
367  sal_Int32 nIndex = 0;
368  while ( nIndex >= 0 )
369  {
370  sal_Int32 nPrevIndex = nIndex;
371  OUString aToken = aText.getToken( 0, m_cMultiSep, nIndex );
372  sal_Int32 nTokenLen = aToken.getLength();
373  aToken = comphelper::string::strip(aToken, ' ');
374  sal_Int32 nP = m_pImplLB->GetEntryList()->FindEntry( aToken );
375  if ((nP != LISTBOX_ENTRY_NOTFOUND) && (!m_pImplLB->GetEntryList()->IsEntryPosSelected(nP)))
376  {
377  aText = aText.replaceAt( nPrevIndex, nTokenLen, "" );
378  nIndex = nIndex - nTokenLen;
379  sal_Int32 nSepCount=0;
380  if ((nPrevIndex+nSepCount < aText.getLength()) && (aText[nPrevIndex+nSepCount] == m_cMultiSep))
381  {
382  nIndex--;
383  ++nSepCount;
384  }
385  aText = aText.replaceAt( nPrevIndex, nSepCount, "" );
386  }
387  aText = comphelper::string::strip(aText, ' ');
388  }
389 
390  // attach missing entries
391  ::std::set< sal_Int32 > aSelInText;
392  lcl_GetSelectedEntries( aSelInText, aText, m_cMultiSep, m_pImplLB->GetEntryList() );
393  sal_Int32 nSelectedEntries = m_pImplLB->GetEntryList()->GetSelectedEntryCount();
394  for ( sal_Int32 n = 0; n < nSelectedEntries; n++ )
395  {
396  sal_Int32 nP = m_pImplLB->GetEntryList()->GetSelectedEntryPos( n );
397  if ( !aSelInText.count( nP ) )
398  {
399  if (!aText.isEmpty() && (aText[aText.getLength()-1] != m_cMultiSep))
400  aText += OUStringChar(m_cMultiSep);
401  if ( !aText.isEmpty() )
402  aText += " "; // slightly loosen
403  aText += m_pImplLB->GetEntryList()->GetEntryText( nP ) +
404  OUStringChar(m_cMultiSep);
405  }
406  }
407  aText = comphelper::string::stripEnd( aText, m_cMultiSep );
408  }
409  else
410  {
411  aText = m_pImplLB->GetEntryList()->GetSelectedEntry( 0 );
412  }
413 
414  m_pSubEdit->SetText( aText );
415 
416  Selection aNewSelection( 0, aText.getLength() );
417  if (m_rThis.IsMultiSelectionEnabled())
418  aNewSelection.Min() = aText.getLength();
419  m_pSubEdit->SetSelection( aNewSelection );
420 
421  bCallSelect = true;
422  }
423 
424  // #84652# Call GrabFocus and EndPopupMode before calling Select/Modify, but after changing the text
425 
426  if (bPopup && !m_pImplLB->IsTravelSelect() &&
427  (!m_rThis.IsMultiSelectionEnabled() || !m_pImplLB->GetSelectModifier()))
428  {
429  m_pFloatWin->EndPopupMode();
430  m_rThis.GrabFocus();
431  }
432 
433  if ( bCallSelect )
434  {
435  m_pSubEdit->SetModifyFlag();
436  m_isSyntheticModify = true;
437  m_rThis.Modify();
438  m_isSyntheticModify = false;
439  m_rThis.Select();
440  }
441 }
442 
443 IMPL_LINK_NOARG( ComboBox::Impl, ImplListItemSelectHdl, LinkParamNone*, void )
444 {
445  m_rThis.CallEventListeners( VclEventId::DropdownSelect );
446 }
447 
449 {
450  if (m_rThis.IsInDropDown())
451  m_pFloatWin->EndPopupMode();
452 }
453 
454 IMPL_LINK( ComboBox::Impl, ImplSelectionChangedHdl, sal_Int32, nChanged, void )
455 {
456  if (!m_pImplLB->IsTrackingSelect())
457  {
458  if (!m_pSubEdit->IsReadOnly() && m_pImplLB->GetEntryList()->IsEntryPosSelected(nChanged))
459  m_pSubEdit->SetText(m_pImplLB->GetEntryList()->GetEntryText(nChanged));
460  }
461 }
462 
464 {
465  m_rThis.DoubleClick();
466 }
467 
469 {
470  if( IsDropDownBox() )
471  {
472  if (m_pImpl->m_pFloatWin->IsInPopupMode())
473  m_pImpl->m_pFloatWin->EndPopupMode();
474  else
475  {
476  m_pImpl->m_pSubEdit->GrabFocus();
477  if (!m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount())
478  m_pImpl->ImplUpdateFloatSelection();
479  else
480  m_pImpl->m_pImplLB->SelectEntry( 0 , true );
482  m_pImpl->m_pBtn->SetPressed( true );
484  m_pImpl->m_pFloatWin->StartFloat( true );
486  }
487  }
488 }
489 
491 {
492  ImplCallEventListenersAndHandler( VclEventId::ComboboxSelect, [this] () { m_pImpl->m_SelectHdl.Call(*this); } );
493 }
494 
496 {
497  ImplCallEventListenersAndHandler( VclEventId::ComboboxDoubleClick, [this] () { m_pImpl->m_DoubleClickHdl.Call(*this); } );
498 }
499 
500 bool ComboBox::IsAutoSizeEnabled() const { return m_pImpl->m_isDDAutoSize; }
501 
502 void ComboBox::EnableAutoSize( bool bAuto )
503 {
504  m_pImpl->m_isDDAutoSize = bAuto;
505  if (m_pImpl->m_pFloatWin)
506  {
507  if (bAuto && !m_pImpl->m_pFloatWin->GetDropDownLineCount())
508  {
509  // Adapt to GetListBoxMaximumLineCount here; was on fixed number of five before
511  }
512  else if ( !bAuto )
513  {
514  m_pImpl->m_pFloatWin->SetDropDownLineCount( 0 );
515  }
516  }
517 }
519 {
520  m_pImpl->m_pSubEdit->SetSelectAllSingleClick(true);
521 }
522 
523 void ComboBox::SetDropDownLineCount( sal_uInt16 nLines )
524 {
525  if (m_pImpl->m_pFloatWin)
526  m_pImpl->m_pFloatWin->SetDropDownLineCount( nLines );
527 }
528 
530 {
531  // Adapt to maximum allowed number.
532  // Limit for LOK as we can't render outside of the dialog canvas.
535  else
536  SetDropDownLineCount(GetSettings().GetStyleSettings().GetListBoxMaximumLineCount());
537 }
538 
540 {
541  sal_uInt16 nLines = 0;
542  if (m_pImpl->m_pFloatWin)
543  nLines = m_pImpl->m_pFloatWin->GetDropDownLineCount();
544  return nLines;
545 }
546 
547 void ComboBox::setPosSizePixel( long nX, long nY, long nWidth, long nHeight,
548  PosSizeFlags nFlags )
549 {
550  if( IsDropDownBox() && ( nFlags & PosSizeFlags::Size ) )
551  {
552  Size aPrefSz = m_pImpl->m_pFloatWin->GetPrefSize();
553  if ((nFlags & PosSizeFlags::Height) && (nHeight >= 2*m_pImpl->m_nDDHeight))
554  aPrefSz.setHeight( nHeight-m_pImpl->m_nDDHeight );
555  if ( nFlags & PosSizeFlags::Width )
556  aPrefSz.setWidth( nWidth );
557  m_pImpl->m_pFloatWin->SetPrefSize( aPrefSz );
558 
559  if (IsAutoSizeEnabled())
560  nHeight = m_pImpl->m_nDDHeight;
561  }
562 
563  Edit::setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
564 }
565 
567 {
568  Control::Resize();
569 
570  if (m_pImpl->m_pSubEdit)
571  {
572  Size aOutSz = GetOutputSizePixel();
573  if( IsDropDownBox() )
574  {
575  ComboBoxBounds aBounds(m_pImpl->calcComboBoxDropDownComponentBounds(aOutSz,
577  m_pImpl->m_pSubEdit->SetPosSizePixel(aBounds.aSubEditPos, aBounds.aSubEditSize);
578  m_pImpl->m_pBtn->SetPosSizePixel(aBounds.aButtonPos, aBounds.aButtonSize);
579  }
580  else
581  {
582  m_pImpl->m_pSubEdit->SetSizePixel(Size(aOutSz.Width(), m_pImpl->m_nDDHeight));
583  m_pImpl->m_pImplLB->setPosSizePixel(0, m_pImpl->m_nDDHeight,
584  aOutSz.Width(), aOutSz.Height() - m_pImpl->m_nDDHeight);
585  if ( !GetText().isEmpty() )
586  m_pImpl->ImplUpdateFloatSelection();
587  }
588  }
589 
590  // adjust the size of the FloatingWindow even when invisible
591  // as KEY_PGUP/DOWN is being processed...
592  if (m_pImpl->m_pFloatWin)
593  m_pImpl->m_pFloatWin->SetSizePixel(m_pImpl->m_pFloatWin->CalcFloatSize());
594 }
595 
596 bool ComboBox::IsDropDownBox() const { return m_pImpl->m_pFloatWin != nullptr; }
597 
599 {
600  mpControlData->mpLayoutData.reset( new vcl::ControlLayoutData );
601  AppendLayoutData( *m_pImpl->m_pSubEdit );
602  m_pImpl->m_pSubEdit->SetLayoutDataParent( this );
603  ImplListBoxWindow* rMainWindow = m_pImpl->m_pImplLB->GetMainWindow();
604  if (m_pImpl->m_pFloatWin)
605  {
606  // dropdown mode
607  if (m_pImpl->m_pFloatWin->IsReallyVisible())
608  {
609  AppendLayoutData( *rMainWindow );
610  rMainWindow->SetLayoutDataParent( this );
611  }
612  }
613  else
614  {
615  AppendLayoutData( *rMainWindow );
616  rMainWindow->SetLayoutDataParent( this );
617  }
618 }
619 
621 {
622  Edit::StateChanged( nType );
623 
624  if ( nType == StateChangedType::ReadOnly )
625  {
626  m_pImpl->m_pImplLB->SetReadOnly( IsReadOnly() );
627  if (m_pImpl->m_pBtn)
628  m_pImpl->m_pBtn->Enable( IsEnabled() && !IsReadOnly() );
629  }
630  else if ( nType == StateChangedType::Enable )
631  {
632  m_pImpl->m_pSubEdit->Enable( IsEnabled() );
633  m_pImpl->m_pImplLB->Enable( IsEnabled() && !IsReadOnly() );
634  if (m_pImpl->m_pBtn)
635  m_pImpl->m_pBtn->Enable( IsEnabled() && !IsReadOnly() );
636  Invalidate();
637  }
638  else if( nType == StateChangedType::UpdateMode )
639  {
640  m_pImpl->m_pImplLB->SetUpdateMode( IsUpdateMode() );
641  }
642  else if ( nType == StateChangedType::Zoom )
643  {
644  m_pImpl->m_pImplLB->SetZoom( GetZoom() );
645  m_pImpl->m_pSubEdit->SetZoom( GetZoom() );
647  Resize();
648  }
649  else if ( nType == StateChangedType::ControlFont )
650  {
651  m_pImpl->m_pImplLB->SetControlFont( GetControlFont() );
652  m_pImpl->m_pSubEdit->SetControlFont( GetControlFont() );
654  Resize();
655  }
656  else if ( nType == StateChangedType::ControlForeground )
657  {
658  m_pImpl->m_pImplLB->SetControlForeground( GetControlForeground() );
659  m_pImpl->m_pSubEdit->SetControlForeground( GetControlForeground() );
660  }
661  else if ( nType == StateChangedType::ControlBackground )
662  {
663  m_pImpl->m_pImplLB->SetControlBackground( GetControlBackground() );
664  m_pImpl->m_pSubEdit->SetControlBackground( GetControlBackground() );
665  }
666  else if ( nType == StateChangedType::Style )
667  {
669  m_pImpl->m_pImplLB->GetMainWindow()->EnableSort( ( GetStyle() & WB_SORT ) != 0 );
670  }
671  else if( nType == StateChangedType::Mirroring )
672  {
673  if (m_pImpl->m_pBtn)
674  {
675  m_pImpl->m_pBtn->EnableRTL( IsRTLEnabled() );
676  ImplInitDropDownButton( m_pImpl->m_pBtn );
677  }
678  m_pImpl->m_pSubEdit->CompatStateChanged( StateChangedType::Mirroring );
679  m_pImpl->m_pImplLB->EnableRTL( IsRTLEnabled() );
680  Resize();
681  }
682 }
683 
685 {
686  Control::DataChanged( rDCEvt );
687 
688  if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
690  ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
691  (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
692  {
693  if (m_pImpl->m_pBtn)
694  {
695  m_pImpl->m_pBtn->SetSettings( GetSettings() );
696  ImplInitDropDownButton( m_pImpl->m_pBtn );
697  }
698  Resize();
699  m_pImpl->m_pImplLB->Resize(); // not called by ComboBox::Resize() if ImplLB is unchanged
700 
701  SetBackground(); // due to a hack in Window::UpdateSettings the background must be reset
702  // otherwise it will overpaint NWF drawn comboboxes
703  }
704 }
705 
707 {
708  bool bDone = false;
709  if ((rNEvt.GetType() == MouseNotifyEvent::KEYINPUT)
710  && (rNEvt.GetWindow() == m_pImpl->m_pSubEdit)
711  && !IsReadOnly())
712  {
713  KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
714  sal_uInt16 nKeyCode = aKeyEvt.GetKeyCode().GetCode();
715  switch( nKeyCode )
716  {
717  case KEY_UP:
718  case KEY_DOWN:
719  case KEY_PAGEUP:
720  case KEY_PAGEDOWN:
721  {
722  m_pImpl->ImplUpdateFloatSelection();
723  if ((nKeyCode == KEY_DOWN) && m_pImpl->m_pFloatWin
724  && !m_pImpl->m_pFloatWin->IsInPopupMode()
725  && aKeyEvt.GetKeyCode().IsMod2())
726  {
728  m_pImpl->m_pBtn->SetPressed( true );
729  if (m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount())
730  m_pImpl->m_pImplLB->SelectEntry( 0 , true );
732  m_pImpl->m_pFloatWin->StartFloat( false );
734  bDone = true;
735  }
736  else if ((nKeyCode == KEY_UP) && m_pImpl->m_pFloatWin
737  && m_pImpl->m_pFloatWin->IsInPopupMode()
738  && aKeyEvt.GetKeyCode().IsMod2())
739  {
740  m_pImpl->m_pFloatWin->EndPopupMode();
741  bDone = true;
742  }
743  else
744  {
745  bDone = m_pImpl->m_pImplLB->ProcessKeyInput( aKeyEvt );
746  }
747  }
748  break;
749 
750  case KEY_RETURN:
751  {
752  if ((rNEvt.GetWindow() == m_pImpl->m_pSubEdit) && IsInDropDown())
753  {
754  m_pImpl->m_pImplLB->ProcessKeyInput( aKeyEvt );
755  bDone = true;
756  }
757  }
758  break;
759  }
760  }
761  else if ((rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS) && m_pImpl->m_pFloatWin)
762  {
763  if (m_pImpl->m_pFloatWin->HasChildPathFocus())
764  m_pImpl->m_pSubEdit->GrabFocus();
765  else if (m_pImpl->m_pFloatWin->IsInPopupMode() && !HasChildPathFocus(true))
766  m_pImpl->m_pFloatWin->EndPopupMode();
767  }
768  else if( (rNEvt.GetType() == MouseNotifyEvent::COMMAND) &&
770  (rNEvt.GetWindow() == m_pImpl->m_pSubEdit) )
771  {
772  MouseWheelBehaviour nWheelBehavior( GetSettings().GetMouseSettings().GetWheelBehavior() );
773  if ( ( nWheelBehavior == MouseWheelBehaviour::ALWAYS )
774  || ( ( nWheelBehavior == MouseWheelBehaviour::FocusOnly )
775  && HasChildPathFocus()
776  )
777  )
778  {
779  bDone = m_pImpl->m_pImplLB->HandleWheelAsCursorTravel( *rNEvt.GetCommandEvent() );
780  }
781  else
782  {
783  bDone = false; // don't eat this event, let the default handling happen (i.e. scroll the context)
784  }
785  }
786  else if ((rNEvt.GetType() == MouseNotifyEvent::MOUSEBUTTONDOWN)
787  && (rNEvt.GetWindow() == m_pImpl->m_pImplLB->GetMainWindow()))
788  {
789  m_pImpl->m_pSubEdit->GrabFocus();
790  }
791 
792  return bDone || Edit::EventNotify( rNEvt );
793 }
794 
795 void ComboBox::SetText( const OUString& rStr )
796 {
798 
799  Edit::SetText( rStr );
800  m_pImpl->ImplUpdateFloatSelection();
801 }
802 
803 void ComboBox::SetText( const OUString& rStr, const Selection& rNewSelection )
804 {
806 
807  Edit::SetText( rStr, rNewSelection );
808  m_pImpl->ImplUpdateFloatSelection();
809 }
810 
812 {
813  if (!m_pImpl->m_isSyntheticModify)
814  m_pImpl->ImplUpdateFloatSelection();
815 
816  Edit::Modify();
817 }
818 
820 {
821  if (!m_pImplLB || !m_pSubEdit)
822  return;
823 
824  // move text in the ListBox into the visible region
825  m_pImplLB->SetCallSelectionChangedHdl( false );
826  if (!m_rThis.IsMultiSelectionEnabled())
827  {
828  OUString aSearchStr( m_pSubEdit->GetText() );
829  sal_Int32 nSelect = LISTBOX_ENTRY_NOTFOUND;
830  bool bSelect = true;
831 
832  if (m_pImplLB->GetCurrentPos() != LISTBOX_ENTRY_NOTFOUND)
833  {
834  OUString aCurrent = m_pImplLB->GetEntryList()->GetEntryText(
835  m_pImplLB->GetCurrentPos());
836  if ( aCurrent == aSearchStr )
837  nSelect = m_pImplLB->GetCurrentPos();
838  }
839 
840  if ( nSelect == LISTBOX_ENTRY_NOTFOUND )
841  nSelect = m_pImplLB->GetEntryList()->FindEntry( aSearchStr );
842  if ( nSelect == LISTBOX_ENTRY_NOTFOUND )
843  {
844  nSelect = m_pImplLB->GetEntryList()->FindMatchingEntry( aSearchStr, 0, true );
845  bSelect = false;
846  }
847 
848  if( nSelect != LISTBOX_ENTRY_NOTFOUND )
849  {
850  if (!m_pImplLB->IsVisible(nSelect))
851  m_pImplLB->ShowProminentEntry( nSelect );
852  m_pImplLB->SelectEntry( nSelect, bSelect );
853  }
854  else
855  {
856  nSelect = m_pImplLB->GetEntryList()->GetSelectedEntryPos( 0 );
857  if( nSelect != LISTBOX_ENTRY_NOTFOUND )
858  m_pImplLB->SelectEntry( nSelect, false );
859  m_pImplLB->ResetCurrentPos();
860  }
861  }
862  else
863  {
864  ::std::set< sal_Int32 > aSelInText;
865  lcl_GetSelectedEntries(aSelInText, m_pSubEdit->GetText(), m_cMultiSep, m_pImplLB->GetEntryList());
866  for (sal_Int32 n = 0; n < m_pImplLB->GetEntryList()->GetEntryCount(); n++)
867  m_pImplLB->SelectEntry( n, aSelInText.count( n ) != 0 );
868  }
869  m_pImplLB->SetCallSelectionChangedHdl( true );
870 }
871 
872 sal_Int32 ComboBox::InsertEntry(const OUString& rStr, sal_Int32 const nPos)
873 {
874  assert(nPos >= 0 && COMBOBOX_MAX_ENTRIES > m_pImpl->m_pImplLB->GetEntryList()->GetEntryCount());
875 
876  sal_Int32 nRealPos;
877  if (nPos == COMBOBOX_APPEND)
878  nRealPos = nPos;
879  else
880  {
881  const sal_Int32 nMRUCount = m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
882  assert(nPos <= COMBOBOX_MAX_ENTRIES - nMRUCount);
883  nRealPos = nPos + nMRUCount;
884  }
885 
886  nRealPos = m_pImpl->m_pImplLB->InsertEntry( nRealPos, rStr );
887  nRealPos -= m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
888  CallEventListeners( VclEventId::ComboboxItemAdded, reinterpret_cast<void*>(nRealPos) );
889  return nRealPos;
890 }
891 
893  const OUString& rStr, const Image& rImage, sal_Int32 const nPos)
894 {
895  assert(nPos >= 0 && COMBOBOX_MAX_ENTRIES > m_pImpl->m_pImplLB->GetEntryList()->GetEntryCount());
896 
897  sal_Int32 nRealPos;
898  if (nPos == COMBOBOX_APPEND)
899  nRealPos = nPos;
900  else
901  {
902  const sal_Int32 nMRUCount = m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
903  assert(nPos <= COMBOBOX_MAX_ENTRIES - nMRUCount);
904  nRealPos = nPos + nMRUCount;
905  }
906 
907  nRealPos = m_pImpl->m_pImplLB->InsertEntry( nRealPos, rStr, rImage );
908  nRealPos -= m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
909  CallEventListeners( VclEventId::ComboboxItemAdded, reinterpret_cast<void*>(nRealPos) );
910  return nRealPos;
911 }
912 
913 void ComboBox::RemoveEntry( const OUString& rStr )
914 {
915  RemoveEntryAt(GetEntryPos(rStr));
916 }
917 
918 void ComboBox::RemoveEntryAt(sal_Int32 const nPos)
919 {
920  const sal_Int32 nMRUCount = m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
921  assert(nPos >= 0 && nPos <= COMBOBOX_MAX_ENTRIES - nMRUCount);
922  m_pImpl->m_pImplLB->RemoveEntry( nPos + nMRUCount );
923  CallEventListeners( VclEventId::ComboboxItemRemoved, reinterpret_cast<void*>(nPos) );
924 }
925 
927 {
928  if (!m_pImpl->m_pImplLB)
929  return;
930  m_pImpl->m_pImplLB->Clear();
931  CallEventListeners( VclEventId::ComboboxItemRemoved, reinterpret_cast<void*>(-1) );
932 }
933 
934 Image ComboBox::GetEntryImage( sal_Int32 nPos ) const
935 {
936  if (m_pImpl->m_pImplLB->GetEntryList()->HasEntryImage(nPos))
937  return m_pImpl->m_pImplLB->GetEntryList()->GetEntryImage( nPos );
938  return Image();
939 }
940 
941 sal_Int32 ComboBox::GetEntryPos( const OUString& rStr ) const
942 {
943  sal_Int32 nPos = m_pImpl->m_pImplLB->GetEntryList()->FindEntry( rStr );
944  if ( nPos != LISTBOX_ENTRY_NOTFOUND )
945  nPos -= m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
946  return nPos;
947 }
948 
949 OUString ComboBox::GetEntry( sal_Int32 nPos ) const
950 {
951  const sal_Int32 nMRUCount = m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
952  if (nPos < 0 || nPos > COMBOBOX_MAX_ENTRIES - nMRUCount)
953  return OUString();
954 
955  return m_pImpl->m_pImplLB->GetEntryList()->GetEntryText( nPos + nMRUCount );
956 }
957 
958 sal_Int32 ComboBox::GetEntryCount() const
959 {
960  if (!m_pImpl->m_pImplLB)
961  return 0;
962  return m_pImpl->m_pImplLB->GetEntryList()->GetEntryCount() - m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount();
963 }
964 
966 {
967  return m_pImpl->m_pImplLB->IsTravelSelect();
968 }
969 
971 {
972  // when the dropdown is dismissed, first mbInPopupMode is set to false, and on the next event iteration then
973  // mbPopupMode is set to false
974  return m_pImpl->m_pFloatWin && m_pImpl->m_pFloatWin->IsInPopupMode() && m_pImpl->m_pFloatWin->ImplIsInPrivatePopupMode();
975 }
976 
978 {
979  return m_pImpl->m_pImplLB->IsMultiSelectionEnabled();
980 }
981 
982 void ComboBox::SetSelectHdl(const Link<ComboBox&,void>& rLink) { m_pImpl->m_SelectHdl = rLink; }
983 
984 const Link<ComboBox&,void>& ComboBox::GetSelectHdl() const { return m_pImpl->m_SelectHdl; }
985 
986 void ComboBox::SetDoubleClickHdl(const Link<ComboBox&,void>& rLink) { m_pImpl->m_DoubleClickHdl = rLink; }
987 
988 const Link<ComboBox&,void>& ComboBox::GetDoubleClickHdl() const { return m_pImpl->m_DoubleClickHdl; }
989 
991 {
992  if (!m_pImpl->m_pSubEdit)
993  return;
994  m_pImpl->m_pSubEdit->SetActivateHdl(rLink);
995 }
996 
997 long ComboBox::CalcWindowSizePixel(sal_uInt16 nLines) const
998 {
999  return m_pImpl->m_pImplLB->GetEntryHeight() * nLines;
1000 }
1001 
1003 {
1004  return CalcMinimumSize();
1005 }
1006 
1008 {
1009  long nButtonDownWidth = 0;
1010 
1012  ImplControlValue aControlValue;
1013  tools::Rectangle aContent, aBound;
1014 
1015  // use the full extent of the control
1016  tools::Rectangle aArea( Point(), pBorder->GetOutputSizePixel() );
1017 
1019  aArea, ControlState::NONE, aControlValue, aBound, aContent) )
1020  {
1021  nButtonDownWidth = aContent.getWidth();
1022  }
1023 
1024  long nScrollBarWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
1025 
1026  return std::max(nScrollBarWidth, nButtonDownWidth);
1027 }
1028 
1030 {
1031  Size aSz;
1032 
1033  if (!m_pImpl->m_pImplLB)
1034  return aSz;
1035 
1036  if (!IsDropDownBox())
1037  {
1038  aSz = m_pImpl->m_pImplLB->CalcSize( m_pImpl->m_pImplLB->GetEntryList()->GetEntryCount() );
1039  aSz.AdjustHeight(m_pImpl->m_nDDHeight );
1040  }
1041  else
1042  {
1044 
1045  if (m_pImpl->m_nWidthInChars!= -1)
1046  aSz.setWidth(m_pImpl->m_nWidthInChars * approximate_digit_width());
1047  else
1048  aSz.setWidth(m_pImpl->m_pImplLB->GetMaxEntryWidth());
1049  }
1050 
1051  if (m_pImpl->m_nMaxWidthChars != -1)
1052  {
1053  long nMaxWidth = m_pImpl->m_nMaxWidthChars * approximate_char_width();
1054  aSz.setWidth( std::min(aSz.Width(), nMaxWidth) );
1055  }
1056 
1057  if (IsDropDownBox())
1059 
1060  ComboBoxBounds aBounds(m_pImpl->calcComboBoxDropDownComponentBounds(
1061  Size(0xFFFF, 0xFFFF), Size(0xFFFF, 0xFFFF)));
1062  aSz.AdjustWidth(aBounds.aSubEditPos.X()*2 );
1063 
1064  aSz.AdjustWidth(ImplGetExtraXOffset() * 2 );
1065 
1066  aSz = CalcWindowSize( aSz );
1067  return aSz;
1068 }
1069 
1070 Size ComboBox::CalcAdjustedSize( const Size& rPrefSize ) const
1071 {
1072  Size aSz = rPrefSize;
1073  sal_Int32 nLeft, nTop, nRight, nBottom;
1074  static_cast<vcl::Window*>(const_cast<ComboBox *>(this))->GetBorder( nLeft, nTop, nRight, nBottom );
1075  aSz.AdjustHeight( -(nTop+nBottom) );
1076  if ( !IsDropDownBox() )
1077  {
1078  long nEntryHeight = CalcBlockSize( 1, 1 ).Height();
1079  long nLines = aSz.Height() / nEntryHeight;
1080  if ( nLines < 1 )
1081  nLines = 1;
1082  aSz.setHeight( nLines * nEntryHeight );
1083  aSz.AdjustHeight(m_pImpl->m_nDDHeight );
1084  }
1085  else
1086  {
1087  aSz.setHeight( m_pImpl->m_nDDHeight );
1088  }
1089  aSz.AdjustHeight(nTop+nBottom );
1090 
1091  aSz = CalcWindowSize( aSz );
1092  return aSz;
1093 }
1094 
1095 Size ComboBox::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
1096 {
1097  // show ScrollBars where appropriate
1098  Size aMinSz = CalcMinimumSize();
1099  Size aSz;
1100 
1101  // height
1102  if ( nLines )
1103  {
1104  if ( !IsDropDownBox() )
1105  aSz.setHeight( m_pImpl->m_pImplLB->CalcSize( nLines ).Height() + m_pImpl->m_nDDHeight );
1106  else
1107  aSz.setHeight( m_pImpl->m_nDDHeight );
1108  }
1109  else
1110  aSz.setHeight( aMinSz.Height() );
1111 
1112  // width
1113  if ( nColumns )
1114  aSz.setWidth( nColumns * approximate_char_width() );
1115  else
1116  aSz.setWidth( aMinSz.Width() );
1117 
1118  if ( IsDropDownBox() )
1120 
1121  if ( !IsDropDownBox() )
1122  {
1123  if ( aSz.Width() < aMinSz.Width() )
1124  aSz.AdjustHeight(GetSettings().GetStyleSettings().GetScrollBarSize() );
1125  if ( aSz.Height() < aMinSz.Height() )
1126  aSz.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() );
1127  }
1128 
1129  aSz.AdjustWidth(ImplGetExtraXOffset() * 2 );
1130 
1131  aSz = CalcWindowSize( aSz );
1132  return aSz;
1133 }
1134 
1135 void ComboBox::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
1136 {
1137  long nCharWidth = GetTextWidth(OUString(u'x'));
1138  if ( !IsDropDownBox() )
1139  {
1140  Size aOutSz = m_pImpl->m_pImplLB->GetMainWindow()->GetOutputSizePixel();
1141  rnCols = (nCharWidth > 0) ? static_cast<sal_uInt16>(aOutSz.Width()/nCharWidth) : 1;
1142  rnLines = static_cast<sal_uInt16>(aOutSz.Height()/m_pImpl->m_pImplLB->GetEntryHeight());
1143  }
1144  else
1145  {
1146  Size aOutSz = m_pImpl->m_pSubEdit->GetOutputSizePixel();
1147  rnCols = (nCharWidth > 0) ? static_cast<sal_uInt16>(aOutSz.Width()/nCharWidth) : 1;
1148  rnLines = 1;
1149  }
1150 }
1151 
1152 void ComboBox::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, DrawFlags nFlags )
1153 {
1154  m_pImpl->m_pImplLB->GetMainWindow()->ApplySettings(*pDev);
1155 
1156  Point aPos = pDev->LogicToPixel( rPos );
1157  Size aSize = pDev->LogicToPixel( rSize );
1158  vcl::Font aFont = m_pImpl->m_pImplLB->GetMainWindow()->GetDrawPixelFont( pDev );
1159  OutDevType eOutDevType = pDev->GetOutDevType();
1160 
1161  pDev->Push();
1162  pDev->SetMapMode();
1163  pDev->SetFont( aFont );
1164  pDev->SetTextFillColor();
1165 
1166  // Border/Background
1167  pDev->SetLineColor();
1168  pDev->SetFillColor();
1169  bool bBorder = (GetStyle() & WB_BORDER);
1170  bool bBackground = IsControlBackground();
1171  if ( bBorder || bBackground )
1172  {
1173  tools::Rectangle aRect( aPos, aSize );
1174  // aRect.Top() += nEditHeight;
1175  if ( bBorder )
1176  {
1177  ImplDrawFrame( pDev, aRect );
1178  }
1179  if ( bBackground )
1180  {
1182  pDev->DrawRect( aRect );
1183  }
1184  }
1185 
1186  // contents
1187  if ( !IsDropDownBox() )
1188  {
1189  long nOnePixel = GetDrawPixel( pDev, 1 );
1190  long nTextHeight = pDev->GetTextHeight();
1191  long nEditHeight = nTextHeight + 6*nOnePixel;
1193 
1194  // First, draw the edit part
1195  m_pImpl->m_pSubEdit->Draw( pDev, aPos, Size( aSize.Width(), nEditHeight ), nFlags );
1196 
1197  // Second, draw the listbox
1198  if ( GetStyle() & WB_CENTER )
1199  nTextStyle |= DrawTextFlags::Center;
1200  else if ( GetStyle() & WB_RIGHT )
1201  nTextStyle |= DrawTextFlags::Right;
1202  else
1203  nTextStyle |= DrawTextFlags::Left;
1204 
1205  if ( ( nFlags & DrawFlags::Mono ) || ( eOutDevType == OUTDEV_PRINTER ) )
1206  {
1207  pDev->SetTextColor( COL_BLACK );
1208  }
1209  else
1210  {
1211  if ( !IsEnabled() )
1212  {
1213  const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1214  pDev->SetTextColor( rStyleSettings.GetDisableColor() );
1215  }
1216  else
1217  {
1218  pDev->SetTextColor( GetTextColor() );
1219  }
1220  }
1221 
1222  tools::Rectangle aClip( aPos, aSize );
1223  pDev->IntersectClipRegion( aClip );
1224  sal_Int32 nLines = static_cast<sal_Int32>( nTextHeight > 0 ? (aSize.Height()-nEditHeight)/nTextHeight : 1 );
1225  if ( !nLines )
1226  nLines = 1;
1227  const sal_Int32 nTEntry = IsReallyVisible() ? m_pImpl->m_pImplLB->GetTopEntry() : 0;
1228 
1229  tools::Rectangle aTextRect( aPos, aSize );
1230 
1231  aTextRect.AdjustLeft(3*nOnePixel );
1232  aTextRect.AdjustRight( -(3*nOnePixel) );
1233  aTextRect.AdjustTop(nEditHeight + nOnePixel );
1234  aTextRect.SetBottom( aTextRect.Top() + nTextHeight );
1235 
1236  // the drawing starts here
1237  for ( sal_Int32 n = 0; n < nLines; ++n )
1238  {
1239  pDev->DrawText( aTextRect, m_pImpl->m_pImplLB->GetEntryList()->GetEntryText( n+nTEntry ), nTextStyle );
1240  aTextRect.AdjustTop(nTextHeight );
1241  aTextRect.AdjustBottom(nTextHeight );
1242  }
1243  }
1244 
1245  pDev->Pop();
1246 
1247  // Call Edit::Draw after restoring the MapMode...
1248  if ( IsDropDownBox() )
1249  {
1250  m_pImpl->m_pSubEdit->Draw( pDev, rPos, rSize, nFlags );
1251  // DD-Button ?
1252  }
1253 
1254 }
1255 
1256 IMPL_LINK(ComboBox::Impl, ImplUserDrawHdl, UserDrawEvent*, pEvent, void)
1257 {
1258  m_rThis.UserDraw(*pEvent);
1259 }
1260 
1262 {
1263 }
1264 
1266 {
1267  m_pImpl->m_pImplLB->GetMainWindow()->SetUserItemSize( rSz );
1268 }
1269 
1270 void ComboBox::EnableUserDraw( bool bUserDraw )
1271 {
1272  m_pImpl->m_pImplLB->GetMainWindow()->EnableUserDraw( bUserDraw );
1273 }
1274 
1275 void ComboBox::DrawEntry(const UserDrawEvent& rEvt, bool bDrawImage, bool bDrawText, bool bDrawTextAtImagePos)
1276 {
1277  SAL_WARN_IF(rEvt.GetWindow() != m_pImpl->m_pImplLB->GetMainWindow(), "vcl", "DrawEntry?!");
1278  m_pImpl->m_pImplLB->GetMainWindow()->DrawEntry(*rEvt.GetRenderContext(), rEvt.GetItemId(), bDrawImage, bDrawText, bDrawTextAtImagePos);
1279 }
1280 
1281 void ComboBox::SetSeparatorPos( sal_Int32 n )
1282 {
1283  m_pImpl->m_pImplLB->SetSeparatorPos( n );
1284 }
1285 
1286 void ComboBox::AddSeparator( sal_Int32 n )
1287 {
1288  m_pImpl->m_pImplLB->AddSeparator( n );
1289 }
1290 
1291 void ComboBox::SetMRUEntries( const OUString& rEntries )
1292 {
1293  m_pImpl->m_pImplLB->SetMRUEntries( rEntries, ';' );
1294 }
1295 
1296 OUString ComboBox::GetMRUEntries() const
1297 {
1298  return m_pImpl->m_pImplLB ? m_pImpl->m_pImplLB->GetMRUEntries( ';' ) : OUString();
1299 }
1300 
1301 void ComboBox::SetMaxMRUCount( sal_Int32 n )
1302 {
1303  m_pImpl->m_pImplLB->SetMaxMRUCount( n );
1304 }
1305 
1306 sal_Int32 ComboBox::GetMaxMRUCount() const
1307 {
1308  return m_pImpl->m_pImplLB ? m_pImpl->m_pImplLB->GetMaxMRUCount() : 0;
1309 }
1310 
1312 {
1313  return m_pImpl->m_pImplLB ? m_pImpl->m_pImplLB->GetDisplayLineCount() : 0;
1314 }
1315 
1316 void ComboBox::SetEntryData( sal_Int32 nPos, void* pNewData )
1317 {
1318  m_pImpl->m_pImplLB->SetEntryData( nPos + m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount(), pNewData );
1319 }
1320 
1321 void* ComboBox::GetEntryData( sal_Int32 nPos ) const
1322 {
1323  return m_pImpl->m_pImplLB->GetEntryList()->GetEntryData(
1324  nPos + m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount() );
1325 }
1326 
1327 sal_Int32 ComboBox::GetTopEntry() const
1328 {
1329  sal_Int32 nPos = GetEntryCount() ? m_pImpl->m_pImplLB->GetTopEntry() : LISTBOX_ENTRY_NOTFOUND;
1330  if (nPos < m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount())
1331  nPos = 0;
1332  return nPos;
1333 }
1334 
1336 {
1337  m_pImpl->m_pImplLB->SetProminentEntryType( eType );
1338 }
1339 
1341 {
1342  return m_pImpl->m_pFloatWin
1343  ? m_pImpl->m_pFloatWin->GetWindowExtentsRelative(const_cast<ComboBox*>(this))
1344  : tools::Rectangle();
1345 }
1346 
1348 {
1349  if (!m_pImpl->m_pSubEdit->IsBackground())
1351 
1352  const Wallpaper& rBack = m_pImpl->m_pSubEdit->GetBackground();
1353  if( ! rBack.IsBitmap() &&
1354  ! rBack.IsGradient() &&
1355  rBack == COL_TRANSPARENT
1356  )
1358  return rBack;
1359 }
1360 
1362 {
1363  return m_pImpl->m_pImplLB->GetEntryList()->GetSelectedEntryCount();
1364 }
1365 
1366 sal_Int32 ComboBox::GetSelectedEntryPos( sal_Int32 nIndex ) const
1367 {
1368  sal_Int32 nPos = m_pImpl->m_pImplLB->GetEntryList()->GetSelectedEntryPos( nIndex );
1369  if ( nPos != LISTBOX_ENTRY_NOTFOUND )
1370  {
1371  if (nPos < m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount())
1372  nPos = m_pImpl->m_pImplLB->GetEntryList()->FindEntry(m_pImpl->m_pImplLB->GetEntryList()->GetEntryText(nPos));
1373  nPos = sal::static_int_cast<sal_Int32>(nPos - m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount());
1374  }
1375  return nPos;
1376 }
1377 
1378 bool ComboBox::IsEntryPosSelected( sal_Int32 nPos ) const
1379 {
1380  return m_pImpl->m_pImplLB->GetEntryList()->IsEntryPosSelected(
1381  nPos + m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount() );
1382 }
1383 
1384 void ComboBox::SelectEntryPos( sal_Int32 nPos, bool bSelect)
1385 {
1386  if (nPos < m_pImpl->m_pImplLB->GetEntryList()->GetEntryCount())
1387  m_pImpl->m_pImplLB->SelectEntry(
1388  nPos + m_pImpl->m_pImplLB->GetEntryList()->GetMRUCount(), bSelect);
1389 }
1390 
1392 {
1393  m_pImpl->m_pImplLB->SetNoSelection();
1394  m_pImpl->m_pSubEdit->SetText( OUString() );
1395 }
1396 
1398 {
1399  tools::Rectangle aRect = m_pImpl->m_pImplLB->GetMainWindow()->GetBoundingRectangle( nItem );
1400  tools::Rectangle aOffset = m_pImpl->m_pImplLB->GetMainWindow()->GetWindowExtentsRelative( static_cast<vcl::Window*>(const_cast<ComboBox *>(this)) );
1401  aRect.Move( aOffset.TopLeft().X(), aOffset.TopLeft().Y() );
1402  return aRect;
1403 }
1404 
1406 {
1407  Window::SetBorderStyle( nBorderStyle );
1408  if ( !IsDropDownBox() )
1409  {
1410  m_pImpl->m_pSubEdit->SetBorderStyle( nBorderStyle );
1411  m_pImpl->m_pImplLB->SetBorderStyle( nBorderStyle );
1412  }
1413 }
1414 
1415 long ComboBox::GetIndexForPoint( const Point& rPoint, sal_Int32& rPos ) const
1416 {
1417  if( !HasLayoutData() )
1418  FillLayoutData();
1419 
1420  // check whether rPoint fits at all
1421  long nIndex = Control::GetIndexForPoint( rPoint );
1422  if( nIndex != -1 )
1423  {
1424  // point must be either in main list window
1425  // or in impl window (dropdown case)
1426  ImplListBoxWindow* rMain = m_pImpl->m_pImplLB->GetMainWindow();
1427 
1428  // convert coordinates to ImplListBoxWindow pixel coordinate space
1429  Point aConvPoint = LogicToPixel( rPoint );
1430  aConvPoint = OutputToAbsoluteScreenPixel( aConvPoint );
1431  aConvPoint = rMain->AbsoluteScreenToOutputPixel( aConvPoint );
1432  aConvPoint = rMain->PixelToLogic( aConvPoint );
1433 
1434  // try to find entry
1435  sal_Int32 nEntry = rMain->GetEntryPosForPoint( aConvPoint );
1436  if( nEntry == LISTBOX_ENTRY_NOTFOUND )
1437  nIndex = -1;
1438  else
1439  rPos = nEntry;
1440  }
1441 
1442  // get line relative index
1443  if( nIndex != -1 )
1444  nIndex = ToRelativeLineIndex( nIndex );
1445 
1446  return nIndex;
1447 }
1448 
1450  const Size &rOutSz, const Size &rBorderOutSz) const
1451 {
1452  ComboBoxBounds aBounds;
1453 
1454  long nTop = 0;
1455  long nBottom = rOutSz.Height();
1456 
1457  vcl::Window *pBorder = m_rThis.GetWindow( GetWindowType::Border );
1458  ImplControlValue aControlValue;
1459  Point aPoint;
1460  tools::Rectangle aContent, aBound;
1461 
1462  // use the full extent of the control
1463  tools::Rectangle aArea( aPoint, rBorderOutSz );
1464 
1465  if (m_rThis.GetNativeControlRegion(ControlType::Combobox, ControlPart::ButtonDown,
1466  aArea, ControlState::NONE, aControlValue, aBound, aContent) )
1467  {
1468  // convert back from border space to local coordinates
1469  aPoint = pBorder->ScreenToOutputPixel(m_rThis.OutputToScreenPixel(aPoint));
1470  aContent.Move(-aPoint.X(), -aPoint.Y());
1471 
1472  aBounds.aButtonPos = Point(aContent.Left(), nTop);
1473  aBounds.aButtonSize = Size(aContent.getWidth(), (nBottom-nTop));
1474 
1475  // adjust the size of the edit field
1476  if (m_rThis.GetNativeControlRegion(ControlType::Combobox, ControlPart::SubEdit,
1477  aArea, ControlState::NONE, aControlValue, aBound, aContent) )
1478  {
1479  // convert back from border space to local coordinates
1480  aContent.Move(-aPoint.X(), -aPoint.Y());
1481 
1482  // use the themes drop down size
1483  aBounds.aSubEditPos = aContent.TopLeft();
1484  aBounds.aSubEditSize = aContent.GetSize();
1485  }
1486  else
1487  {
1488  // use the themes drop down size for the button
1489  aBounds.aSubEditSize = Size(rOutSz.Width() - aContent.getWidth(), rOutSz.Height());
1490  }
1491  }
1492  else
1493  {
1494  long nSBWidth = m_rThis.GetSettings().GetStyleSettings().GetScrollBarSize();
1495  nSBWidth = m_rThis.CalcZoom( nSBWidth );
1496  aBounds.aSubEditSize = Size(rOutSz.Width() - nSBWidth, rOutSz.Height());
1497  aBounds.aButtonPos = Point(rOutSz.Width() - nSBWidth, nTop);
1498  aBounds.aButtonSize = Size(nSBWidth, (nBottom-nTop));
1499  }
1500  return aBounds;
1501 }
1502 
1503 void ComboBox::SetWidthInChars(sal_Int32 nWidthInChars)
1504 {
1505  if (nWidthInChars != m_pImpl->m_nWidthInChars)
1506  {
1507  m_pImpl->m_nWidthInChars = nWidthInChars;
1508  queue_resize();
1509  }
1510 }
1511 
1512 void ComboBox::setMaxWidthChars(sal_Int32 nWidth)
1513 {
1514  if (nWidth != m_pImpl->m_nMaxWidthChars)
1515  {
1516  m_pImpl->m_nMaxWidthChars = nWidth;
1517  queue_resize();
1518  }
1519 }
1520 
1521 bool ComboBox::set_property(const OString &rKey, const OUString &rValue)
1522 {
1523  if (rKey == "width-chars")
1524  SetWidthInChars(rValue.toInt32());
1525  else if (rKey == "max-width-chars")
1526  setMaxWidthChars(rValue.toInt32());
1527  else if (rKey == "can-focus")
1528  {
1529  // as far as I can see in Gtk, setting a ComboBox as can.focus means
1530  // the focus gets stuck in it, so try here to behave like gtk does
1531  // with the settings that work, i.e. can.focus of false doesn't
1532  // set the hard WB_NOTABSTOP
1533  WinBits nBits = GetStyle();
1534  nBits &= ~(WB_TABSTOP|WB_NOTABSTOP);
1535  if (toBool(rValue))
1536  nBits |= WB_TABSTOP;
1537  SetStyle(nBits);
1538  }
1539  else
1540  return Control::set_property(rKey, rValue);
1541  return true;
1542 }
1543 
1545 {
1546  return ComboBoxUIObject::create;
1547 }
1548 
1549 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 GetEntryPos(const OUString &rStr) const
Definition: combobox.cxx:941
OString stripEnd(const OString &rIn, char c)
Point TopLeft() const
long Width() const
void DrawEntry(const UserDrawEvent &rEvt, bool bDrawImage, bool bDrawText, bool bDrawTextAtImagePos=false)
Definition: combobox.cxx:1275
const Color & GetTextColor() const
Definition: outdev.hxx:1110
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, MetricVector *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
Definition: text.cxx:781
virtual FactoryFunction GetUITestFactory() const override
Definition: combobox.cxx:1544
OutDevType GetOutDevType() const
Definition: outdev.hxx:522
bool IsControlBackground() const
Definition: window2.cxx:1082
virtual const Wallpaper & GetDisplayBackground() const
Definition: window.cxx:3068
SAL_DLLPRIVATE float approximate_char_width() const
Definition: text.cxx:903
bool ImplCallEventListenersAndHandler(VclEventId nEvent, std::function< void()> const &callHandler)
this calls both our event listeners, and a specified handler
Definition: ctrl.cxx:305
Size CalcBlockSize(sal_uInt16 nColumns, sal_uInt16 nLines) const
Definition: combobox.cxx:1095
sal_Int32 nIndex
long GetHeight() const
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
SAL_DLLPRIVATE void ImplCalcEditHeight()
Definition: combobox.cxx:151
long ToRelativeLineIndex(long nIndex) const
ToRelativeLineIndex changes a layout data index to a count relative to its line.
Definition: ctrl.cxx:211
static void lcl_GetSelectedEntries(::std::set< sal_Int32 > &rSelectedPos, const OUString &rText, sal_Unicode cTokenSep, const ImplEntryList *pEntryList)
Definition: combobox.cxx:95
Link< ComboBox &, void > m_SelectHdl
Definition: combobox.cxx:63
tools::Rectangle GetBoundingRectangle(sal_Int32 nItem) const
Definition: combobox.cxx:1397
long AdjustWidth(long n)
bool GetNativeControlRegion(ControlType nType, ControlPart nPart, const tools::Rectangle &rControlRegion, ControlState nState, const ImplControlValue &aValue, tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion) const
Query the native control's actual drawing region (including adornment)
bool IsAutoSizeEnabled() const
Definition: combobox.cxx:500
#define KEY_PAGEDOWN
Definition: keycodes.hxx:117
const CommandEvent * GetCommandEvent() const
Definition: event.hxx:318
virtual void StateChanged(StateChangedType nType) override
Definition: combobox.cxx:620
bool m_isSyntheticModify
Definition: combobox.cxx:59
sal_uInt16 m_nDDHeight
Definition: combobox.cxx:56
long Height() const
SAL_DLLPRIVATE void ImplDrawFrame(OutputDevice *pDev, tools::Rectangle &rRect)
draws a frame around the give rectangle, onto the given device
Definition: ctrl.cxx:336
#define KEY_PAGEUP
Definition: keycodes.hxx:116
virtual void Draw(OutputDevice *pDev, const Point &rPos, const Size &rSize, DrawFlags nFlags) override
Definition: combobox.cxx:1152
void ImplUpdateFloatSelection()
Definition: combobox.cxx:819
WinBits const WB_NOGROUP
long getWidth() const
virtual Size CalcMinimumSizeForText(const OUString &rString) const
Definition: edit.cxx:2614
long AdjustLeft(long nHorzMoveDelta)
Point AbsoluteScreenToOutputPixel(const Point &rPos) const
Definition: window.cxx:2874
sal_Int32 m_nWidthInChars
Definition: combobox.cxx:62
OUString GetMRUEntries() const
Definition: combobox.cxx:1296
void disposeAndClear()
Definition: vclptr.hxx:200
SAL_DLLPRIVATE void ImplInit(vcl::Window *pParent, WinBits nStyle)
Definition: combobox.cxx:175
const StyleSettings & GetStyleSettings() const
sal_Int64 n
void ToggleDropDown()
Definition: combobox.cxx:468
std::function< std::unique_ptr< UIObject >vcl::Window *)> FactoryFunction
WinBits const WB_RIGHT
sal_Int32 GetEntryPosForPoint(const Point &rPoint) const
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: edit.cxx:214
void SetMaxMRUCount(sal_Int32 n)
Definition: combobox.cxx:1301
void SetTextFillColor()
Definition: text.cxx:699
sal_uInt16 GetCode() const
Definition: keycod.hxx:53
PosSizeFlags
Definition: window.hxx:141
DataChangedEventType GetType() const
Definition: event.hxx:348
const KeyEvent * GetKeyEvent() const
Definition: event.hxx:302
void IntersectClipRegion(const tools::Rectangle &rRect)
struct SAL_DLLPRIVATE Impl
Definition: combobox.hxx:37
void AppendLayoutData(const Control &rSubControl) const
Definition: ctrl.cxx:273
bool IsTravelSelect() const
Definition: combobox.cxx:965
const Color & GetControlBackground() const
Definition: window2.cxx:1077
virtual void Select()
Definition: combobox.cxx:490
Impl(ComboBox &rThis)
Definition: combobox.cxx:66
SAL_DLLPRIVATE long getMaxWidthScrollBarAndDownButton() const
Definition: combobox.cxx:1007
long AdjustHeight(long n)
sal_Int32 FindEntry(const OUString &rStr, bool bSearchMRUArea=false) const
bool HasChildPathFocus(bool bSystemWindow=false) const
Definition: window.cxx:3005
VclPtr< ImplListBoxFloatingWindow > m_pFloatWin
Definition: combobox.cxx:55
sal_Int32 GetMaxMRUCount() const
Definition: combobox.cxx:1306
bool IsNativeControlSupported(ControlType nType, ControlPart nPart) const
Query the platform layer for control support.
void SetMapMode()
Definition: map.cxx:655
const Link< ComboBox &, void > & GetDoubleClickHdl() const
Definition: combobox.cxx:988
void SetBorderStyle(WindowBorderStyle nBorderStyle)
Definition: combobox.cxx:1405
#define LISTBOX_ENTRY_NOTFOUND
Definition: lstbox.hxx:33
long AdjustBottom(long nVertMoveDelta)
VclPtr< ImplListBox > m_pImplLB
Definition: combobox.cxx:53
void Move(long nHorzMoveDelta, long nVertMoveDelta)
DECL_LINK(ImplSelectHdl, LinkParamNone *, void)
void SetEntryData(sal_Int32 nPos, void *pNewData)
Definition: combobox.cxx:1316
VclPtr< ImplBtn > m_pBtn
Definition: combobox.cxx:54
const Fraction & GetZoom() const
Definition: window2.cxx:1205
StateChangedType
Definition: window.hxx:311
OUString GetEntry(sal_Int32 nPos) const
Definition: combobox.cxx:949
virtual void setPosSizePixel(long nX, long nY, long nWidth, long nHeight, PosSizeFlags nFlags=PosSizeFlags::All)
Definition: window.cxx:2682
sal_uInt16 GetDisplayLineCount() const
Definition: combobox.cxx:1311
sal_Int64 WinBits
sal_uInt16 sal_Unicode
constexpr::Color COL_TRANSPARENT(0xFF, 0xFF, 0xFF, 0xFF)
vcl::Window * GetWindow() const
Definition: event.hxx:295
void SetBackground()
bool IsEntryPosSelected(sal_Int32 nPos) const
Definition: combobox.cxx:1378
ESelection aNewSelection(GetSelection())
bool IsMultiSelectionEnabled() const
Definition: combobox.cxx:977
void EnableUserDraw(bool bUserDraw)
Definition: combobox.cxx:1270
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: combobox.cxx:122
Image GetEntryImage(sal_Int32 nPos) const
Definition: combobox.cxx:934
void Clear()
Definition: combobox.cxx:926
void SetSelectHdl(const Link< ComboBox &, void > &rLink)
Definition: combobox.cxx:982
static std::unique_ptr< UIObject > create(vcl::Window *pWindow)
sal_Unicode m_cMultiSep
Definition: combobox.cxx:57
sal_uInt16 GetDropDownLineCount() const
Definition: combobox.cxx:539
std::unique_ptr< Impl > m_pImpl
Definition: combobox.hxx:38
AllSettingsFlags GetFlags() const
Definition: event.hxx:349
bool IsInDropDown() const
Definition: combobox.cxx:970
virtual void queue_resize(StateChangedType eReason=StateChangedType::Layout)
Definition: window2.cxx:1309
void SetCompoundControl(bool bCompound)
Definition: window2.cxx:942
long Top() const
Definition: edit.hxx:55
ComboBox(vcl::Window *pParent, WinBits nStyle=0)
Definition: combobox.cxx:108
void AdaptDropDownLineCountToMaximum()
Definition: combobox.cxx:529
virtual void SetSelection(const Selection &rSelection)
Definition: edit.cxx:2389
void SetProminentEntryType(ProminentEntry eType)
Definition: combobox.cxx:1335
void DrawRect(const tools::Rectangle &rRect)
Definition: rect.cxx:32
void SetWidthInChars(sal_Int32 nWidthInChars)
Definition: combobox.cxx:1503
const Color & GetControlForeground() const
Definition: window2.cxx:1067
long GetDrawPixel(::OutputDevice const *pDev, long nPixels) const
Definition: window2.cxx:563
static SAL_DLLPRIVATE WinBits ImplInitStyle(WinBits nStyle)
Definition: combobox.cxx:252
long GetIndexForPoint(const Point &rPoint, sal_Int32 &rPos) const
Definition: combobox.cxx:1415
void SetUserItemSize(const Size &rSz)
Definition: combobox.cxx:1265
void RemoveEntry(const OUString &rStr)
Definition: combobox.cxx:913
virtual Size GetOptimalSize() const override
Definition: combobox.cxx:1002
WinBits const WB_NOLIGHTBORDER
Size CalcWindowSize(const Size &rOutSz) const
Definition: window2.cxx:537
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: combobox.cxx:684
void SetLineColor()
virtual void setPosSizePixel(long nX, long nY, long nWidth, long nHeight, PosSizeFlags nFlags=PosSizeFlags::All) override
Definition: combobox.cxx:547
bool IsDropDownBox() const
Definition: combobox.cxx:596
const Color & GetDisableColor() const
bool IsRTLEnabled() const
Definition: outdev.hxx:1354
vcl::RenderContext * GetRenderContext() const
Definition: event.hxx:223
void SetEntryActivateHdl(const Link< Edit &, bool > &rLink)
Definition: combobox.cxx:990
DrawFlags
Definition: window.hxx:354
void setMaxWidthChars(sal_Int32 nWidth)
Definition: combobox.cxx:1512
OutDevType
Definition: outdev.hxx:278
The edit field part of a control, e.g.
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: combobox.cxx:706
virtual void StateChanged(StateChangedType nType) override
Definition: edit.cxx:2140
float approximate_digit_width() const
Definition: text.cxx:911
WinBits const WB_SIMPLEMODE
virtual void UserDraw(const UserDrawEvent &rUDEvt)
Definition: combobox.cxx:1261
SAL_DLLPRIVATE long ImplGetExtraXOffset() const
Definition: edit.cxx:395
void SetNoSelection()
Definition: combobox.cxx:1391
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
Definition: paint.cxx:1160
virtual OUString GetText() const override
Definition: edit.cxx:2559
void CallEventListeners(VclEventId nEvent, void *pData=nullptr)
Definition: ctrl.cxx:297
bool IsUpdateMode() const
Definition: window2.cxx:1168
void SetFillColor()
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:304
CommandEventId GetCommand() const
virtual void Modify()
Definition: edit.cxx:2300
sal_Int32 GetSelectedEntryPos(sal_Int32 nSelIndex=0) const
Definition: combobox.cxx:1366
float u
void SetTextColor(const Color &rColor)
Definition: text.cxx:664
WinBits const WB_RECTSTYLE
void RemoveEntryAt(sal_Int32 nPos)
Definition: combobox.cxx:918
bool bPopup
MouseNotifyEvent GetType() const
Definition: event.hxx:294
IMPL_LINK_NOARG(ComboBox::Impl, ImplClickBtnHdl, void *, void)
Definition: combobox.cxx:276
void SetSubEdit(Edit *pEdit)
Definition: edit.cxx:2599
WinBits const WB_DROPDOWN
virtual ~ComboBox() override
Definition: combobox.cxx:117
static bool toBool(const OString &rValue)
Definition: builder.cxx:72
const AllSettings & GetSettings() const
Definition: outdev.hxx:420
Size GetOutputSizePixel() const
Definition: outdev.hxx:441
DrawTextFlags
Definition: outdev.hxx:144
virtual bool set_property(const OString &rKey, const OUString &rValue)
Definition: window2.cxx:1427
WinBits const WB_SORT
Point ScreenToOutputPixel(const Point &rPos) const
Definition: window.cxx:2821
long GetTextHeight() const
Height where any character of the current font fits; in logic coordinates.
Definition: text.cxx:890
WinBits const WB_LEFT
IMPL_LINK(ComboBox::Impl, ImplAutocompleteHdl, Edit &, rEdit, void)
Definition: combobox.cxx:317
long X() const
void SetStyle(WinBits nStyle)
Definition: window.cxx:1926
Point OutputToAbsoluteScreenPixel(const Point &rPos) const
Definition: window.cxx:2864
Size GetSize() const
WinBits const WB_NOBORDER
sal_uInt16 GetItemId() const
Definition: event.hxx:225
ComboBox & m_rThis
Definition: combobox.cxx:51
void EnableAutocomplete(bool bEnable, bool bMatchCase=false)
Definition: combobox.cxx:261
vcl::Window * GetWindow(GetWindowType nType) const
Definition: stacking.cxx:1046
void GetMaxVisColumnsAndLines(sal_uInt16 &rnCols, sal_uInt16 &rnLines) const
Definition: combobox.cxx:1135
ProminentEntry
Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1179
Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:934
void ImplInitComboBoxData()
Definition: combobox.cxx:135
tools::Rectangle GetDropDownPosSizePixel() const
Definition: combobox.cxx:1340
void SetSeparatorPos(sal_Int32 n)
Definition: combobox.cxx:1281
long GetIndexForPoint(const Point &rPoint) const
Definition: ctrl.cxx:134
virtual const Wallpaper & GetDisplayBackground() const override
Definition: combobox.cxx:1347
ControlType
These types are all based on the supported variants vcl/salnativewidgets.hxx and must be kept in-sync...
#define KEY_RETURN
Definition: keycodes.hxx:119
void SetDoubleClickHdl(const Link< ComboBox &, void > &rLink)
Definition: combobox.cxx:986
void GetBorder(sal_Int32 &rLeftBorder, sal_Int32 &rTopBorder, sal_Int32 &rRightBorder, sal_Int32 &rBottomBorder) const
Definition: window.cxx:2387
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:53
bool IsGradient() const
Definition: wall.cxx:283
Link< ComboBox &, void > m_DoubleClickHdl
Definition: combobox.cxx:64
virtual bool set_property(const OString &rKey, const OUString &rValue) override
Definition: combobox.cxx:1521
virtual void Resize() override
Definition: ctrl.cxx:74
#define KEY_DOWN
Definition: keycodes.hxx:110
weld::Entry & rEdit
long AdjustRight(long nHorzMoveDelta)
VclPtr< Edit > m_pSubEdit
Definition: combobox.cxx:52
WindowType
sal_Int32 GetEntryCount() const
Definition: combobox.cxx:958
#define SAL_WARN_IF(condition, area, stream)
WinBits const WB_BORDER
void SetFont(const vcl::Font &rNewFont)
bool m_isMatchCase
Definition: combobox.cxx:60
std::unique_ptr< vcl::ImplControlData > mpControlData
Definition: ctrl.hxx:36
bool IsAutocompleteEnabled() const
Definition: combobox.cxx:271
#define COMBOBOX_MAX_ENTRIES
Definition: combobox.hxx:29
sal_Int32 GetTopEntry() const
Definition: combobox.cxx:1327
OString strip(const OString &rIn, char c)
bool m_isDDAutoSize
Definition: combobox.cxx:58
Definition: image.hxx:40
static VclPtr< reference_type > Create(Arg &&...arg)
A construction helper for VclPtr.
Definition: vclptr.hxx:127
void SetBottom(long v)
Size CalcAdjustedSize(const Size &rPrefSize) const
Definition: combobox.cxx:1070
long AdjustTop(long nVertMoveDelta)
const Link< ComboBox &, void > & GetSelectHdl() const
Definition: combobox.cxx:984
void EnableSelectAll()
Definition: combobox.cxx:518
WinBits const WB_AUTOHSCROLL
long Left() const
sal_Int32 GetSelectedEntryCount() const
Definition: combobox.cxx:1361
long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
Width of the text.
Definition: text.cxx:879
WinBits const WB_TABSTOP
void * GetEntryData(sal_Int32 nPos) const
Definition: combobox.cxx:1321
virtual void FillLayoutData() const override
Definition: combobox.cxx:598
void DoubleClick()
Definition: combobox.cxx:495
bool IsBitmap() const
Definition: wall.cxx:255
A widget used to choose from a list of items and which has an entry.
Definition: combobox.hxx:34
sal_Int32 m_nMaxWidthChars
Definition: combobox.cxx:61
Event to pass information for UserDraw() handling eg. in comboboxes.
Definition: event.hxx:205
WinBits const WB_CENTER
#define SELECTION_MAX
bool IsEnabled() const
Definition: window2.cxx:1117
void SetDropDownLineCount(sal_uInt16 nLines)
Definition: combobox.cxx:523
sal_Int32 InsertEntryWithImage(const OUString &rStr, const Image &rImage, sal_Int32 nPos=COMBOBOX_APPEND)
Definition: combobox.cxx:892
MouseWheelBehaviour
Definition: settings.hxx:80
WinBits GetStyle() const
Definition: window2.cxx:948
long Max() const
WindowBorderStyle
Definition: vclenum.hxx:108
WinBits const WB_GROUP
void SelectEntryPos(sal_Int32 nPos, bool bSelect=true)
Definition: combobox.cxx:1384
sal_Int32 InsertEntry(const OUString &rStr, sal_Int32 nPos=COMBOBOX_APPEND)
Definition: combobox.cxx:872
virtual bool IsReadOnly() const
Definition: edit.hxx:180
void ImplInitDropDownButton(PushButton *pButton)
Definition: imp_listbox.cxx:50
virtual void SetText(const OUString &rStr) override
Definition: edit.cxx:2540
void SetMRUEntries(const OUString &rEntries)
Definition: combobox.cxx:1291
long GetScrollBarSize() const
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
bool IsReallyVisible() const
Definition: window2.cxx:1102
vcl::Font GetControlFont() const
Definition: window2.cxx:438
void Push(PushFlags nFlags=PushFlags::ALL)
Definition: outdevstate.cxx:60
virtual void SetText(const OUString &rStr) override
Definition: combobox.cxx:795
void setWidth(long nWidth)
void AddSeparator(sal_Int32 n)
Adds a new separator at the given position n.
Definition: combobox.cxx:1286
vcl::Window * GetWindow() const
Definition: event.hxx:222
WinBits const WB_NOTABSTOP
Size CalcMinimumSize() const override
Definition: combobox.cxx:1029
void EnableAutoSize(bool bAuto)
Definition: combobox.cxx:502
SAL_DLLPRIVATE void ImplInit(vcl::Window *pParent, WinBits nStyle)
Definition: edit.cxx:298
bool HasLayoutData() const
determines whether we currently have layout data
Definition: ctrl.cxx:90
virtual void Resize() override
Definition: combobox.cxx:566
long Y() const
sal_uInt16 nPos
ComboBoxBounds calcComboBoxDropDownComponentBounds(const Size &rOutSize, const Size &rBorderOutSize) const
Definition: combobox.cxx:1449
virtual void DataChanged(const DataChangedEvent &rDCEvt)
Definition: event.cxx:35
#define COMBOBOX_APPEND
Definition: combobox.hxx:27
long CalcWindowSizePixel(sal_uInt16 nLines) const
Definition: combobox.cxx:997
virtual void Modify() override
Definition: combobox.cxx:811
void SetLayoutDataParent(const Control *pParent) const
Definition: ctrl.cxx:324
#define KEY_UP
Definition: keycodes.hxx:111
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: ctrl.cxx:225
bool IsMod2() const
Definition: keycod.hxx:62
void setHeight(long nHeight)