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