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