LibreOffice Module vcl (master)  1
imp_listbox.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 <memory>
21 
22 #include <vcl/svapp.hxx>
23 #include <vcl/settings.hxx>
24 #include <vcl/event.hxx>
25 #include <vcl/scrbar.hxx>
26 #include <vcl/toolkit/lstbox.hxx>
27 #include <vcl/i18nhelp.hxx>
28 #include <vcl/naturalsort.hxx>
29 
30 #include <listbox.hxx>
31 #include <controldata.hxx>
32 #include <svdata.hxx>
33 #include <window.h>
34 
35 #include <com/sun/star/accessibility/AccessibleRole.hpp>
36 
37 #include <rtl/instance.hxx>
38 #include <sal/log.hxx>
39 #include <o3tl/safeint.hxx>
40 #include <osl/diagnose.h>
41 #include <comphelper/string.hxx>
43 
44 #include <limits>
45 
46 #define MULTILINE_ENTRY_DRAW_FLAGS ( DrawTextFlags::WordBreak | DrawTextFlags::MultiLine | DrawTextFlags::VCenter )
47 
48 using namespace ::com::sun::star;
49 
50 constexpr tools::Long gnBorder = 1;
51 
53 {
54  pButton->SetSymbol( SymbolType::SPIN_DOWN );
55 
58  pButton->SetBackground();
59 }
60 
62 {
63  mpWindow = pWindow;
66  mnImages = 0;
68 
69  mnMRUCount = 0;
70  mnMaxMRUCount = 0;
71 }
72 
74 {
75  Clear();
76 }
77 
79 {
80  mnImages = 0;
81  maEntries.clear();
82 }
83 
84 void ImplEntryList::SelectEntry( sal_Int32 nPos, bool bSelect )
85 {
86  if (0 <= nPos && o3tl::make_unsigned(nPos) < maEntries.size())
87  {
88  std::vector<std::unique_ptr<ImplEntryType> >::iterator iter = maEntries.begin()+nPos;
89 
90  if ( ( (*iter)->mbIsSelected != bSelect ) &&
92  {
93  (*iter)->mbIsSelected = bSelect;
95  maSelectionChangedHdl.Call( nPos );
96  }
97  }
98 }
99 
100 namespace
101 {
102  struct theSorter
103  : public rtl::StaticWithInit< comphelper::string::NaturalStringSorter, theSorter >
104  {
106  {
109  Application::GetSettings().GetLanguageTag().getLocale());
110  }
111  };
112 }
113 
114 namespace vcl
115 {
116  sal_Int32 NaturalSortCompare(const OUString &rA, const OUString &rB)
117  {
118  const comphelper::string::NaturalStringSorter &rSorter = theSorter::get();
119  return rSorter.compare(rA, rB);
120  }
121 }
122 
123 sal_Int32 ImplEntryList::InsertEntry( sal_Int32 nPos, ImplEntryType* pNewEntry, bool bSort )
124 {
125  assert(nPos >= 0);
127 
128  if ( !!pNewEntry->maImage )
129  mnImages++;
130 
131  sal_Int32 insPos = 0;
132  const sal_Int32 nEntriesSize = static_cast<sal_Int32>(maEntries.size());
133 
134  if ( !bSort || maEntries.empty())
135  {
136  if (0 <= nPos && nPos < nEntriesSize)
137  {
138  insPos = nPos;
139  maEntries.insert( maEntries.begin() + nPos, std::unique_ptr<ImplEntryType>(pNewEntry) );
140  }
141  else
142  {
143  insPos = nEntriesSize;
144  maEntries.push_back(std::unique_ptr<ImplEntryType>(pNewEntry));
145  }
146  }
147  else
148  {
149  const comphelper::string::NaturalStringSorter &rSorter = theSorter::get();
150 
151  const OUString& rStr = pNewEntry->maStr;
152 
153  ImplEntryType* pTemp = GetEntry( nEntriesSize-1 );
154 
155  try
156  {
157  sal_Int32 nComp = rSorter.compare(rStr, pTemp->maStr);
158 
159  // fast insert for sorted data
160  if ( nComp >= 0 )
161  {
162  insPos = nEntriesSize;
163  maEntries.push_back(std::unique_ptr<ImplEntryType>(pNewEntry));
164  }
165  else
166  {
167  pTemp = GetEntry( mnMRUCount );
168 
169  nComp = rSorter.compare(rStr, pTemp->maStr);
170  if ( nComp <= 0 )
171  {
172  insPos = 0;
173  maEntries.insert(maEntries.begin(), std::unique_ptr<ImplEntryType>(pNewEntry));
174  }
175  else
176  {
177  sal_uLong nLow = mnMRUCount;
178  sal_uLong nHigh = maEntries.size()-1;
179  sal_Int32 nMid;
180 
181  // binary search
182  do
183  {
184  nMid = static_cast<sal_Int32>((nLow + nHigh) / 2);
185  pTemp = GetEntry( nMid );
186 
187  nComp = rSorter.compare(rStr, pTemp->maStr);
188 
189  if ( nComp < 0 )
190  nHigh = nMid-1;
191  else
192  {
193  if ( nComp > 0 )
194  nLow = nMid + 1;
195  else
196  break;
197  }
198  }
199  while ( nLow <= nHigh );
200 
201  if ( nComp >= 0 )
202  nMid++;
203 
204  insPos = nMid;
205  maEntries.insert(maEntries.begin()+nMid, std::unique_ptr<ImplEntryType>(pNewEntry));
206  }
207  }
208  }
209  catch (uno::RuntimeException& )
210  {
211  // XXX this is arguable, if the exception occurred because pNewEntry is
212  // garbage you wouldn't insert it. If the exception occurred because the
213  // Collator implementation is garbage then give the user a chance to see
214  // his stuff
215  insPos = 0;
216  maEntries.insert(maEntries.begin(), std::unique_ptr<ImplEntryType>(pNewEntry));
217  }
218 
219  }
220 
221  return insPos;
222 }
223 
224 void ImplEntryList::RemoveEntry( sal_Int32 nPos )
225 {
226  if (0 <= nPos && o3tl::make_unsigned(nPos) < maEntries.size())
227  {
228  std::vector<std::unique_ptr<ImplEntryType> >::iterator iter = maEntries.begin()+ nPos;
229 
230  if ( !!(*iter)->maImage )
231  mnImages--;
232 
233  maEntries.erase(iter);
234  }
235 }
236 
237 sal_Int32 ImplEntryList::FindEntry( std::u16string_view rString, bool bSearchMRUArea ) const
238 {
239  const sal_Int32 nEntries = static_cast<sal_Int32>(maEntries.size());
240  for ( sal_Int32 n = bSearchMRUArea ? 0 : GetMRUCount(); n < nEntries; n++ )
241  {
242  OUString aComp( vcl::I18nHelper::filterFormattingChars( maEntries[n]->maStr ) );
243  if ( aComp == rString )
244  return n;
245  }
246  return LISTBOX_ENTRY_NOTFOUND;
247 }
248 
249 sal_Int32 ImplEntryList::FindMatchingEntry( const OUString& rStr, sal_Int32 nStart, bool bLazy ) const
250 {
251  sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND;
252  sal_Int32 nEntryCount = GetEntryCount();
253 
254  const vcl::I18nHelper& rI18nHelper = mpWindow->GetSettings().GetLocaleI18nHelper();
255  for ( sal_Int32 n = nStart; n < nEntryCount; )
256  {
257  ImplEntryType* pImplEntry = GetEntry( n );
258  bool bMatch;
259  if ( bLazy )
260  {
261  bMatch = rI18nHelper.MatchString( rStr, pImplEntry->maStr );
262  }
263  else
264  {
265  bMatch = pImplEntry->maStr.startsWith(rStr);
266  }
267  if ( bMatch )
268  {
269  nPos = n;
270  break;
271  }
272 
273  n++;
274  }
275 
276  return nPos;
277 }
278 
279 tools::Long ImplEntryList::GetAddedHeight( sal_Int32 i_nEndIndex, sal_Int32 i_nBeginIndex ) const
280 {
281  tools::Long nHeight = 0;
282  sal_Int32 nStart = std::min(i_nEndIndex, i_nBeginIndex);
283  sal_Int32 nStop = std::max(i_nEndIndex, i_nBeginIndex);
284  sal_Int32 nEntryCount = GetEntryCount();
285  if( 0 <= nStop && nStop != LISTBOX_ENTRY_NOTFOUND && nEntryCount != 0 )
286  {
287  // sanity check
288  if( nStop > nEntryCount-1 )
289  nStop = nEntryCount-1;
290  if (nStart < 0)
291  nStart = 0;
292  else if( nStart > nEntryCount-1 )
293  nStart = nEntryCount-1;
294 
295  sal_Int32 nIndex = nStart;
296  while( nIndex != LISTBOX_ENTRY_NOTFOUND && nIndex < nStop )
297  {
298  tools::Long nPosHeight = GetEntryPtr( nIndex )->getHeightWithMargin();
299  if (nHeight > ::std::numeric_limits<tools::Long>::max() - nPosHeight)
300  {
301  SAL_WARN( "vcl", "ImplEntryList::GetAddedHeight: truncated");
302  break;
303  }
304  nHeight += nPosHeight;
305  nIndex++;
306  }
307  }
308  else
309  nHeight = 0;
310  return i_nEndIndex > i_nBeginIndex ? nHeight : -nHeight;
311 }
312 
314 {
315  ImplEntryType* pImplEntry = GetEntry( nPos );
316  return pImplEntry ? pImplEntry->getHeightWithMargin() : 0;
317 }
318 
319 OUString ImplEntryList::GetEntryText( sal_Int32 nPos ) const
320 {
321  OUString aEntryText;
322  ImplEntryType* pImplEntry = GetEntry( nPos );
323  if ( pImplEntry )
324  aEntryText = pImplEntry->maStr;
325  return aEntryText;
326 }
327 
328 bool ImplEntryList::HasEntryImage( sal_Int32 nPos ) const
329 {
330  bool bImage = false;
331  ImplEntryType* pImplEntry = GetEntry( nPos );
332  if ( pImplEntry )
333  bImage = !!pImplEntry->maImage;
334  return bImage;
335 }
336 
337 Image ImplEntryList::GetEntryImage( sal_Int32 nPos ) const
338 {
339  Image aImage;
340  ImplEntryType* pImplEntry = GetEntry( nPos );
341  if ( pImplEntry )
342  aImage = pImplEntry->maImage;
343  return aImage;
344 }
345 
346 void ImplEntryList::SetEntryData( sal_Int32 nPos, void* pNewData )
347 {
348  ImplEntryType* pImplEntry = GetEntry( nPos );
349  if ( pImplEntry )
350  pImplEntry->mpUserData = pNewData;
351 }
352 
353 void* ImplEntryList::GetEntryData( sal_Int32 nPos ) const
354 {
355  ImplEntryType* pImplEntry = GetEntry( nPos );
356  return pImplEntry ? pImplEntry->mpUserData : nullptr;
357 }
358 
359 void ImplEntryList::SetEntryFlags( sal_Int32 nPos, ListBoxEntryFlags nFlags )
360 {
361  ImplEntryType* pImplEntry = GetEntry( nPos );
362  if ( pImplEntry )
363  pImplEntry->mnFlags = nFlags;
364 }
365 
367 {
368  sal_Int32 nSelCount = 0;
369  for ( sal_Int32 n = GetEntryCount(); n; )
370  {
371  ImplEntryType* pImplEntry = GetEntry( --n );
372  if ( pImplEntry->mbIsSelected )
373  nSelCount++;
374  }
375  return nSelCount;
376 }
377 
378 OUString ImplEntryList::GetSelectedEntry( sal_Int32 nIndex ) const
379 {
380  return GetEntryText( GetSelectedEntryPos( nIndex ) );
381 }
382 
383 sal_Int32 ImplEntryList::GetSelectedEntryPos( sal_Int32 nIndex ) const
384 {
385  sal_Int32 nSelEntryPos = LISTBOX_ENTRY_NOTFOUND;
386  sal_Int32 nSel = 0;
387  sal_Int32 nEntryCount = GetEntryCount();
388 
389  for ( sal_Int32 n = 0; n < nEntryCount; n++ )
390  {
391  ImplEntryType* pImplEntry = GetEntry( n );
392  if ( pImplEntry->mbIsSelected )
393  {
394  if ( nSel == nIndex )
395  {
396  nSelEntryPos = n;
397  break;
398  }
399  nSel++;
400  }
401  }
402 
403  return nSelEntryPos;
404 }
405 
406 bool ImplEntryList::IsEntryPosSelected( sal_Int32 nIndex ) const
407 {
408  ImplEntryType* pImplEntry = GetEntry( nIndex );
409  return pImplEntry && pImplEntry->mbIsSelected;
410 }
411 
412 bool ImplEntryList::IsEntrySelectable( sal_Int32 nPos ) const
413 {
414  ImplEntryType* pImplEntry = GetEntry( nPos );
415  return pImplEntry == nullptr || ((pImplEntry->mnFlags & ListBoxEntryFlags::DisableSelection) == ListBoxEntryFlags::NONE);
416 }
417 
418 sal_Int32 ImplEntryList::FindFirstSelectable( sal_Int32 nPos, bool bForward /* = true */ )
419 {
420  if( IsEntrySelectable( nPos ) )
421  return nPos;
422 
423  if( bForward )
424  {
425  for( nPos = nPos + 1; nPos < GetEntryCount(); nPos++ )
426  {
427  if( IsEntrySelectable( nPos ) )
428  return nPos;
429  }
430  }
431  else
432  {
433  while( nPos )
434  {
435  nPos--;
436  if( IsEntrySelectable( nPos ) )
437  return nPos;
438  }
439  }
440 
441  return LISTBOX_ENTRY_NOTFOUND;
442 }
443 
445  Control( pParent, 0 ),
446  maQuickSelectionEngine( *this )
447 {
448  mpEntryList.reset(new ImplEntryList( this ));
449 
450  mnTop = 0;
451  mnLeft = 0;
452  mnSelectModifier = 0;
454  mbTrack = false;
455  mbTravelSelect = false;
456  mbTrackingSelect = false;
457  mbSelectionChanged = false;
458  mbMouseMoveSelect = false;
459  mbMulti = false;
460  mbGrabFocus = false;
461  mbUserDrawEnabled = false;
462  mbInUserDraw = false;
463  mbReadOnly = false;
464  mbHasFocusRect = false;
465  mbRight = ( nWinStyle & WB_RIGHT );
466  mbCenter = ( nWinStyle & WB_CENTER );
467  mbSimpleMode = ( nWinStyle & WB_SIMPLEMODE );
468  mbSort = ( nWinStyle & WB_SORT );
469  mbIsDropdown = ( nWinStyle & WB_DROPDOWN );
470  mbEdgeBlending = false;
471 
474 
475  SetLineColor();
477  SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
478 
479  ApplySettings(*this);
480  ImplCalcMetrics();
481 }
482 
484 {
485  disposeOnce();
486 }
487 
489 {
490  mpEntryList.reset();
492 }
493 
495 {
496  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
497 
498  ApplyControlFont(rRenderContext, rStyleSettings.GetFieldFont());
499  ApplyControlForeground(rRenderContext, rStyleSettings.GetFieldTextColor());
500 
501  if (IsControlBackground())
502  rRenderContext.SetBackground(GetControlBackground());
503  else
504  rRenderContext.SetBackground(rStyleSettings.GetFieldColor());
505 }
506 
508 {
509  mnMaxWidth = 0;
510  mnMaxTxtWidth = 0;
511  mnMaxImgWidth = 0;
512  mnMaxImgTxtWidth= 0;
513  mnMaxImgHeight = 0;
514 
515  mnTextHeight = static_cast<sal_uInt16>(GetTextHeight());
518 
520  mnMaxHeight = static_cast<sal_uInt16>(maUserItemSize.Height());
521  if ( maUserItemSize.Width() > mnMaxWidth )
522  mnMaxWidth= static_cast<sal_uInt16>(maUserItemSize.Width());
523 
524  for ( sal_Int32 n = mpEntryList->GetEntryCount(); n; )
525  {
526  ImplEntryType* pEntry = mpEntryList->GetMutableEntryPtr( --n );
527  ImplUpdateEntryMetrics( *pEntry );
528  }
529 
531  {
532  Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryPtr( mnCurrentPos )->getHeightWithMargin() );
533  maFocusRect.SetSize( aSz );
534  }
535 }
536 
538 {
539  mpEntryList->Clear();
540 
542  mnMaxWidth = 0;
543  mnMaxTxtWidth = 0;
544  mnMaxImgTxtWidth= 0;
545  mnMaxImgWidth = 0;
546  mnMaxImgHeight = 0;
547  mnTop = 0;
548  mnLeft = 0;
550 
553 
554  Invalidate();
555 }
556 
558 {
560  maUserItemSize = rSz;
561  ImplCalcMetrics();
562 }
563 
564 namespace {
565 
566 struct ImplEntryMetrics
567 {
568  bool bText;
569  bool bImage;
570  tools::Long nEntryWidth;
571  tools::Long nEntryHeight;
572  tools::Long nTextWidth;
573  tools::Long nImgWidth;
574  tools::Long nImgHeight;
575 };
576 
577 }
578 
580 {
582 }
583 
585 {
586  if (maStrGlyphs.IsValid())
587  // Use pre-calculated result.
588  return &maStrGlyphs;
589 
590  std::unique_ptr<SalLayout> pLayout = pOutputDevice->ImplLayout(
591  maStr, 0, maStr.getLength(), Point(0, 0), 0, nullptr, SalLayoutFlags::GlyphItemsOnly);
592  if (!pLayout)
593  return nullptr;
594 
595  // Remember the calculation result.
596  maStrGlyphs = pLayout->GetGlyphs();
597 
598  return &maStrGlyphs;
599 }
600 
602 {
603  ImplEntryMetrics aMetrics;
604  aMetrics.bText = !rEntry.maStr.isEmpty();
605  aMetrics.bImage = !!rEntry.maImage;
606  aMetrics.nEntryWidth = 0;
607  aMetrics.nEntryHeight = 0;
608  aMetrics.nTextWidth = 0;
609  aMetrics.nImgWidth = 0;
610  aMetrics.nImgHeight = 0;
611 
612  if ( aMetrics.bText )
613  {
615  {
616  // multiline case
617  Size aCurSize( PixelToLogic( GetSizePixel() ) );
618  // set the current size to a large number
619  // GetTextRect should shrink it to the actual size
620  aCurSize.setHeight( 0x7fffff );
621  tools::Rectangle aTextRect( Point( 0, 0 ), aCurSize );
622  aTextRect = GetTextRect( aTextRect, rEntry.maStr, DrawTextFlags::WordBreak | DrawTextFlags::MultiLine );
623  aMetrics.nTextWidth = aTextRect.GetWidth();
624  if( aMetrics.nTextWidth > mnMaxTxtWidth )
625  mnMaxTxtWidth = aMetrics.nTextWidth;
626  aMetrics.nEntryWidth = mnMaxTxtWidth;
627  aMetrics.nEntryHeight = aTextRect.GetHeight() + gnBorder;
628  }
629  else
630  {
631  // normal single line case
632  const SalLayoutGlyphs* pGlyphs = rEntry.GetTextGlyphs(this);
633  aMetrics.nTextWidth
634  = static_cast<sal_uInt16>(GetTextWidth(rEntry.maStr, 0, -1, nullptr, pGlyphs));
635  if( aMetrics.nTextWidth > mnMaxTxtWidth )
636  mnMaxTxtWidth = aMetrics.nTextWidth;
637  aMetrics.nEntryWidth = mnMaxTxtWidth;
638  aMetrics.nEntryHeight = mnTextHeight + gnBorder;
639  }
640  }
641  if ( aMetrics.bImage )
642  {
643  Size aImgSz = rEntry.maImage.GetSizePixel();
644  aMetrics.nImgWidth = static_cast<sal_uInt16>(CalcZoom( aImgSz.Width() ));
645  aMetrics.nImgHeight = static_cast<sal_uInt16>(CalcZoom( aImgSz.Height() ));
646 
647  if( aMetrics.nImgWidth > mnMaxImgWidth )
648  mnMaxImgWidth = aMetrics.nImgWidth;
649  if( aMetrics.nImgHeight > mnMaxImgHeight )
650  mnMaxImgHeight = aMetrics.nImgHeight;
651 
652  mnMaxImgTxtWidth = std::max( mnMaxImgTxtWidth, aMetrics.nTextWidth );
653  aMetrics.nEntryHeight = std::max( aMetrics.nImgHeight, aMetrics.nEntryHeight );
654 
655  }
656 
657  bool bIsUserDrawEnabled = IsUserDrawEnabled();
658  if (bIsUserDrawEnabled || aMetrics.bImage)
659  {
660  aMetrics.nEntryWidth = std::max( aMetrics.nImgWidth, maUserItemSize.Width() );
661  if (!bIsUserDrawEnabled && aMetrics.bText)
662  aMetrics.nEntryWidth += aMetrics.nTextWidth + IMG_TXT_DISTANCE;
663  aMetrics.nEntryHeight = std::max( std::max( mnMaxImgHeight, maUserItemSize.Height() ) + 2,
664  aMetrics.nEntryHeight );
665  }
666 
667  if (!aMetrics.bText && !aMetrics.bImage && !bIsUserDrawEnabled)
668  {
669  // entries which have no (aka an empty) text, and no image,
670  // and are not user-drawn, should be shown nonetheless
671  aMetrics.nEntryHeight = mnTextHeight + gnBorder;
672  }
673 
674  if ( aMetrics.nEntryWidth > mnMaxWidth )
675  mnMaxWidth = aMetrics.nEntryWidth;
676  if ( aMetrics.nEntryHeight > mnMaxHeight )
677  mnMaxHeight = aMetrics.nEntryHeight;
678 
679  rEntry.mnHeight = aMetrics.nEntryHeight;
680 }
681 
683 {
684  if ( !IsTravelSelect() && GetEntryList()->GetMaxMRUCount() )
685  {
686  // Insert the selected entry as MRU, if not already first MRU
687  sal_Int32 nSelected = GetEntryList()->GetSelectedEntryPos( 0 );
688  sal_Int32 nMRUCount = GetEntryList()->GetMRUCount();
689  OUString aSelected = GetEntryList()->GetEntryText( nSelected );
690  sal_Int32 nFirstMatchingEntryPos = GetEntryList()->FindEntry( aSelected, true );
691  if ( nFirstMatchingEntryPos || !nMRUCount )
692  {
693  bool bSelectNewEntry = false;
694  if ( nFirstMatchingEntryPos < nMRUCount )
695  {
696  RemoveEntry( nFirstMatchingEntryPos );
697  nMRUCount--;
698  if ( nFirstMatchingEntryPos == nSelected )
699  bSelectNewEntry = true;
700  }
701  else if ( nMRUCount == GetEntryList()->GetMaxMRUCount() )
702  {
703  RemoveEntry( nMRUCount - 1 );
704  nMRUCount--;
705  }
706 
708 
709  ImplEntryType* pNewEntry = new ImplEntryType( aSelected );
710  pNewEntry->mbIsSelected = bSelectNewEntry;
711  GetEntryList()->InsertEntry( 0, pNewEntry, false );
712  ImplUpdateEntryMetrics( *pNewEntry );
713  GetEntryList()->SetMRUCount( ++nMRUCount );
714  SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 );
715  maMRUChangedHdl.Call( nullptr );
716  }
717  }
718 
719  maSelectHdl.Call( nullptr );
720  mbSelectionChanged = false;
721 }
722 
723 sal_Int32 ImplListBoxWindow::InsertEntry(sal_Int32 nPos, ImplEntryType* pNewEntry, bool bSort)
724 {
725  assert(nPos >= 0);
726  assert(mpEntryList->GetEntryCount() < LISTBOX_MAX_ENTRIES);
727 
729  sal_Int32 nNewPos = mpEntryList->InsertEntry( nPos, pNewEntry, bSort );
730 
731  if( GetStyle() & WB_WORDBREAK )
733 
734  ImplUpdateEntryMetrics( *pNewEntry );
735  return nNewPos;
736 }
737 
738 sal_Int32 ImplListBoxWindow::InsertEntry( sal_Int32 nPos, ImplEntryType* pNewEntry )
739 {
740  return InsertEntry(nPos, pNewEntry, mbSort);
741 }
742 
743 void ImplListBoxWindow::RemoveEntry( sal_Int32 nPos )
744 {
746  mpEntryList->RemoveEntry( nPos );
747  if( mnCurrentPos >= mpEntryList->GetEntryCount() )
749  ImplCalcMetrics();
750 }
751 
753 {
754  mpEntryList->SetEntryFlags( nPos, nFlags );
755  ImplEntryType* pEntry = mpEntryList->GetMutableEntryPtr( nPos );
756  if( pEntry )
757  ImplUpdateEntryMetrics( *pEntry );
758 }
759 
761 {
762  if ( mbHasFocusRect )
763  HideFocus();
765  mbHasFocusRect = true;
766 }
767 
769 {
770  if ( mbHasFocusRect )
771  {
772  HideFocus();
773  mbHasFocusRect = false;
774  }
775 }
776 
777 sal_Int32 ImplListBoxWindow::GetEntryPosForPoint( const Point& rPoint ) const
778 {
779  tools::Long nY = gnBorder;
780 
781  sal_Int32 nSelect = mnTop;
782  const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nSelect );
783  while (pEntry)
784  {
785  tools::Long nEntryHeight = pEntry->getHeightWithMargin();
786  if (rPoint.Y() <= nEntryHeight + nY)
787  break;
788  nY += nEntryHeight;
789  pEntry = mpEntryList->GetEntryPtr( ++nSelect );
790  }
791  if( pEntry == nullptr )
792  nSelect = LISTBOX_ENTRY_NOTFOUND;
793 
794  return nSelect;
795 }
796 
797 bool ImplListBoxWindow::IsVisible( sal_Int32 i_nEntry ) const
798 {
799  bool bRet = false;
800 
801  if( i_nEntry >= mnTop )
802  {
803  if( mpEntryList->GetAddedHeight( i_nEntry, mnTop ) <
804  PixelToLogic( GetSizePixel() ).Height() )
805  {
806  bRet = true;
807  }
808  }
809 
810  return bRet;
811 }
812 
814 {
816  return mnMaxHeight + nMargin;
817 }
818 
820 {
821  sal_Int32 nPos = mnTop;
822  tools::Long nWindowHeight = GetSizePixel().Height();
823  sal_Int32 nCount = mpEntryList->GetEntryCount();
824  tools::Long nDiff;
825  for( nDiff = 0; nDiff < nWindowHeight && nPos < nCount; nDiff = mpEntryList->GetAddedHeight( nPos, mnTop ) )
826  nPos++;
827 
828  if( nDiff > nWindowHeight && nPos > mnTop )
829  nPos--;
830 
831  if( nPos >= nCount )
832  nPos = nCount-1;
833 
834  return nPos;
835 }
836 
838 {
839  mbMouseMoveSelect = false; // only till the first MouseButtonDown
841 
842  if ( !IsReadOnly() )
843  {
844  if( rMEvt.GetClicks() == 1 )
845  {
846  sal_Int32 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() );
847  if( nSelect != LISTBOX_ENTRY_NOTFOUND )
848  {
851  else
853 
854  mnCurrentPos = nSelect;
855  mbTrackingSelect = true;
856  bool bCurPosChange = (mnCurrentPos != nSelect);
857  (void)SelectEntries( nSelect, LET_MBDOWN, rMEvt.IsShift(), rMEvt.IsMod1() ,bCurPosChange);
858  mbTrackingSelect = false;
859  if ( mbGrabFocus )
860  GrabFocus();
861 
863  }
864  }
865  if( rMEvt.GetClicks() == 2 )
866  {
867  maDoubleClickHdl.Call( this );
868  }
869  }
870  else // if ( mbGrabFocus )
871  {
872  GrabFocus();
873  }
874 }
875 
877 {
878  if (rMEvt.IsLeaveWindow() || mbMulti || !IsMouseMoveSelect() || !mpEntryList->GetEntryCount())
879  return;
880 
882  if( !aRect.IsInside( rMEvt.GetPosPixel() ) )
883  return;
884 
885  if ( IsMouseMoveSelect() )
886  {
887  sal_Int32 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() );
888  if( nSelect == LISTBOX_ENTRY_NOTFOUND )
889  nSelect = mpEntryList->GetEntryCount() - 1;
890  nSelect = std::min( nSelect, GetLastVisibleEntry() );
891  nSelect = std::min( nSelect, static_cast<sal_Int32>( mpEntryList->GetEntryCount() - 1 ) );
892  // Select only visible Entries with MouseMove, otherwise Tracking...
893  if ( IsVisible( nSelect ) &&
894  mpEntryList->IsEntrySelectable( nSelect ) &&
895  ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectedEntryCount() || ( nSelect != GetEntryList()->GetSelectedEntryPos( 0 ) ) ) )
896  {
897  mbTrackingSelect = true;
898  if ( SelectEntries( nSelect, LET_TRACKING ) )
899  {
900  // When list box selection change by mouse move, notify
901  // VclEventId::ListboxSelect vcl event.
902  maListItemSelectHdl.Call(nullptr);
903  }
904  mbTrackingSelect = false;
905  }
906  }
907 
908  // if the DD button was pressed and someone moved into the ListBox
909  // with the mouse button pressed...
910  if ( rMEvt.IsLeft() && !rMEvt.IsSynthetic() )
911  {
914  else
916 
918  }
919 }
920 
922 {
923  while ( GetEntryList()->GetSelectedEntryCount() )
924  {
925  sal_Int32 nS = GetEntryList()->GetSelectedEntryPos( 0 );
926  SelectEntry( nS, false );
927  }
928 }
929 
930 void ImplListBoxWindow::SelectEntry( sal_Int32 nPos, bool bSelect )
931 {
932  if( (mpEntryList->IsEntryPosSelected( nPos ) == bSelect) || !mpEntryList->IsEntrySelectable( nPos ) )
933  return;
934 
936  if( bSelect )
937  {
938  if( !mbMulti )
939  {
940  // deselect the selected entry
941  sal_Int32 nDeselect = GetEntryList()->GetSelectedEntryPos( 0 );
942  if( nDeselect != LISTBOX_ENTRY_NOTFOUND )
943  {
944  //SelectEntryPos( nDeselect, false );
945  GetEntryList()->SelectEntry( nDeselect, false );
946  if (IsUpdateMode() && IsReallyVisible())
947  Invalidate();
948  }
949  }
950  mpEntryList->SelectEntry( nPos, true );
951  mnCurrentPos = nPos;
952  if ( ( nPos != LISTBOX_ENTRY_NOTFOUND ) && IsUpdateMode() )
953  {
954  Invalidate();
955  if ( !IsVisible( nPos ) )
956  {
958  sal_Int32 nVisibleEntries = GetLastVisibleEntry()-mnTop;
959  if ( !nVisibleEntries || !IsReallyVisible() || ( nPos < GetTopEntry() ) )
960  {
961  Resize();
962  ShowProminentEntry( nPos );
963  }
964  else
965  {
966  ShowProminentEntry( nPos );
967  }
968  }
969  }
970  }
971  else
972  {
973  mpEntryList->SelectEntry( nPos, false );
974  Invalidate();
975  }
976  mbSelectionChanged = true;
977 }
978 
979 bool ImplListBoxWindow::SelectEntries( sal_Int32 nSelect, LB_EVENT_TYPE eLET, bool bShift, bool bCtrl, bool bSelectPosChange /*=FALSE*/ )
980 {
981  bool bSelectionChanged = false;
982 
983  if( IsEnabled() && mpEntryList->IsEntrySelectable( nSelect ) )
984  {
985  bool bFocusChanged = false;
986 
987  // here (Single-ListBox) only one entry can be deselected
988  if( !mbMulti )
989  {
990  sal_Int32 nDeselect = mpEntryList->GetSelectedEntryPos( 0 );
991  if( nSelect != nDeselect )
992  {
993  SelectEntry( nSelect, true );
994  mpEntryList->SetLastSelected( nSelect );
995  bFocusChanged = true;
996  bSelectionChanged = true;
997  }
998  }
999  // MultiListBox without Modifier
1000  else if( mbSimpleMode && !bCtrl && !bShift )
1001  {
1002  sal_Int32 nEntryCount = mpEntryList->GetEntryCount();
1003  for ( sal_Int32 nPos = 0; nPos < nEntryCount; nPos++ )
1004  {
1005  bool bSelect = nPos == nSelect;
1006  if ( mpEntryList->IsEntryPosSelected( nPos ) != bSelect )
1007  {
1008  SelectEntry( nPos, bSelect );
1009  bFocusChanged = true;
1010  bSelectionChanged = true;
1011  }
1012  }
1013  mpEntryList->SetLastSelected( nSelect );
1014  mpEntryList->SetSelectionAnchor( nSelect );
1015  }
1016  // MultiListBox only with CTRL/SHIFT or not in SimpleMode
1017  else if( ( !mbSimpleMode /* && !bShift */ ) || ( mbSimpleMode && ( bCtrl || bShift ) ) )
1018  {
1019  // Space for selection change
1020  if( !bShift && ( ( eLET == LET_KEYSPACE ) || ( eLET == LET_MBDOWN ) ) )
1021  {
1022  bool bSelect = !mpEntryList->IsEntryPosSelected( nSelect );
1023  SelectEntry( nSelect, bSelect );
1024  mpEntryList->SetLastSelected( nSelect );
1025  mpEntryList->SetSelectionAnchor( nSelect );
1026  if ( !mpEntryList->IsEntryPosSelected( nSelect ) )
1027  mpEntryList->SetSelectionAnchor( LISTBOX_ENTRY_NOTFOUND );
1028  bFocusChanged = true;
1029  bSelectionChanged = true;
1030  }
1031  else if( ( ( eLET == LET_TRACKING ) && ( nSelect != mnCurrentPos ) ) ||
1032  ( bShift && ( ( eLET == LET_KEYMOVE ) || ( eLET == LET_MBDOWN ) ) ) )
1033  {
1034  mnCurrentPos = nSelect;
1035  bFocusChanged = true;
1036 
1037  sal_Int32 nAnchor = mpEntryList->GetSelectionAnchor();
1038  if( ( nAnchor == LISTBOX_ENTRY_NOTFOUND ) && mpEntryList->GetSelectedEntryCount() )
1039  {
1040  nAnchor = mpEntryList->GetSelectedEntryPos( mpEntryList->GetSelectedEntryCount() - 1 );
1041  }
1042  if( nAnchor != LISTBOX_ENTRY_NOTFOUND )
1043  {
1044  // All entries from Anchor to nSelect have to be selected
1045  sal_Int32 nStart = std::min( nSelect, nAnchor );
1046  sal_Int32 nEnd = std::max( nSelect, nAnchor );
1047  for ( sal_Int32 n = nStart; n <= nEnd; n++ )
1048  {
1049  if ( !mpEntryList->IsEntryPosSelected( n ) )
1050  {
1051  SelectEntry( n, true );
1052  bSelectionChanged = true;
1053  }
1054  }
1055 
1056  // if appropriate some more has to be deselected...
1057  sal_Int32 nLast = mpEntryList->GetLastSelected();
1058  if ( nLast != LISTBOX_ENTRY_NOTFOUND )
1059  {
1060  if ( ( nLast > nSelect ) && ( nLast > nAnchor ) )
1061  {
1062  for ( sal_Int32 n = nSelect+1; n <= nLast; n++ )
1063  {
1064  if ( mpEntryList->IsEntryPosSelected( n ) )
1065  {
1066  SelectEntry( n, false );
1067  bSelectionChanged = true;
1068  }
1069  }
1070  }
1071  else if ( ( nLast < nSelect ) && ( nLast < nAnchor ) )
1072  {
1073  for ( sal_Int32 n = nLast; n < nSelect; n++ )
1074  {
1075  if ( mpEntryList->IsEntryPosSelected( n ) )
1076  {
1077  SelectEntry( n, false );
1078  bSelectionChanged = true;
1079  }
1080  }
1081  }
1082  }
1083  mpEntryList->SetLastSelected( nSelect );
1084  }
1085  }
1086  else if( eLET != LET_TRACKING )
1087  {
1089  Invalidate();
1090  bFocusChanged = true;
1091  }
1092  }
1093  else if( bShift )
1094  {
1095  bFocusChanged = true;
1096  }
1097 
1098  if( bSelectionChanged )
1099  mbSelectionChanged = true;
1100 
1101  if( bFocusChanged )
1102  {
1103  tools::Long nHeightDiff = mpEntryList->GetAddedHeight( nSelect, mnTop );
1104  maFocusRect.SetPos( Point( 0, nHeightDiff ) );
1105  Size aSz( maFocusRect.GetWidth(),
1106  mpEntryList->GetEntryHeight( nSelect ) );
1107  maFocusRect.SetSize( aSz );
1108  if( HasFocus() )
1110  if (bSelectPosChange)
1111  {
1112  maFocusHdl.Call(nSelect);
1113  }
1114  }
1116  }
1117  return bSelectionChanged;
1118 }
1119 
1121 {
1123  bool bInside = aRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() );
1124 
1125  if( rTEvt.IsTrackingCanceled() || rTEvt.IsTrackingEnded() ) // MouseButtonUp
1126  {
1127  if ( bInside && !rTEvt.IsTrackingCanceled() )
1128  {
1130  ImplCallSelect();
1131  }
1132  else
1133  {
1134  maCancelHdl.Call( nullptr );
1135  if ( !mbMulti )
1136  {
1137  mbTrackingSelect = true;
1139  mbTrackingSelect = false;
1141  {
1142  tools::Long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop );
1143  maFocusRect.SetPos( Point( 0, nHeightDiff ) );
1144  Size aSz( maFocusRect.GetWidth(),
1145  mpEntryList->GetEntryHeight( mnCurrentPos ) );
1146  maFocusRect.SetSize( aSz );
1148  }
1149  }
1150  }
1151 
1152  mbTrack = false;
1153  }
1154  else
1155  {
1156  bool bTrackOrQuickClick = mbTrack;
1157  if( !mbTrack )
1158  {
1159  if ( bInside )
1160  {
1161  mbTrack = true;
1162  }
1163 
1164  // this case only happens, if the mouse button is pressed very briefly
1165  if( rTEvt.IsTrackingEnded() && mbTrack )
1166  {
1167  bTrackOrQuickClick = true;
1168  mbTrack = false;
1169  }
1170  }
1171 
1172  if( bTrackOrQuickClick )
1173  {
1174  MouseEvent aMEvt = rTEvt.GetMouseEvent();
1175  Point aPt( aMEvt.GetPosPixel() );
1176  bool bShift = aMEvt.IsShift();
1177  bool bCtrl = aMEvt.IsMod1();
1178 
1179  sal_Int32 nSelect = LISTBOX_ENTRY_NOTFOUND;
1180  if( aPt.Y() < 0 )
1181  {
1183  {
1184  nSelect = mnCurrentPos ? ( mnCurrentPos - 1 ) : 0;
1185  if( nSelect < mnTop )
1186  SetTopEntry( mnTop-1 );
1187  }
1188  }
1189  else if( aPt.Y() > GetOutputSizePixel().Height() )
1190  {
1192  {
1193  nSelect = std::min( static_cast<sal_Int32>(mnCurrentPos+1), static_cast<sal_Int32>(mpEntryList->GetEntryCount()-1) );
1194  if( nSelect >= GetLastVisibleEntry() )
1195  SetTopEntry( mnTop+1 );
1196  }
1197  }
1198  else
1199  {
1200  nSelect = static_cast<sal_Int32>( ( aPt.Y() + gnBorder ) / mnMaxHeight ) + mnTop;
1201  nSelect = std::min( nSelect, GetLastVisibleEntry() );
1202  nSelect = std::min( nSelect, static_cast<sal_Int32>( mpEntryList->GetEntryCount() - 1 ) );
1203  }
1204 
1205  if ( bInside )
1206  {
1207  if ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectedEntryCount() )
1208  {
1209  mbTrackingSelect = true;
1210  SelectEntries(nSelect, LET_TRACKING, bShift, bCtrl);
1211  mbTrackingSelect = false;
1212  }
1213  }
1214  else
1215  {
1216  if ( !mbMulti && GetEntryList()->GetSelectedEntryCount() )
1217  {
1218  mbTrackingSelect = true;
1219  SelectEntry( GetEntryList()->GetSelectedEntryPos( 0 ), false );
1220  mbTrackingSelect = false;
1221  }
1222  }
1223  mnCurrentPos = nSelect;
1225  {
1227  }
1228  else
1229  {
1230  tools::Long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop );
1231  maFocusRect.SetPos( Point( 0, nHeightDiff ) );
1232  Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( mnCurrentPos ) );
1233  maFocusRect.SetSize( aSz );
1235  }
1236  }
1237  }
1238 }
1239 
1241 {
1242  if( !ProcessKeyInput( rKEvt ) )
1243  Control::KeyInput( rKEvt );
1244 }
1245 
1247 {
1248  // entry to be selected
1249  sal_Int32 nSelect = LISTBOX_ENTRY_NOTFOUND;
1250  LB_EVENT_TYPE eLET = LET_KEYMOVE;
1251 
1252  vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
1253 
1254  bool bShift = aKeyCode.IsShift();
1255  bool bCtrl = aKeyCode.IsMod1() || aKeyCode.IsMod3();
1256  bool bMod2 = aKeyCode.IsMod2();
1257  bool bDone = false;
1258  bool bHandleKey = false;
1259 
1260  switch( aKeyCode.GetCode() )
1261  {
1262  case KEY_UP:
1263  {
1264  if ( IsReadOnly() )
1265  {
1266  if ( GetTopEntry() )
1267  SetTopEntry( GetTopEntry()-1 );
1268  }
1269  else if ( !bMod2 )
1270  {
1272  {
1273  nSelect = mpEntryList->FindFirstSelectable( 0 );
1274  }
1275  else if ( mnCurrentPos )
1276  {
1277  // search first selectable above the current position
1278  nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos - 1, false );
1279  }
1280 
1281  if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect < mnTop ) )
1282  SetTopEntry( mnTop-1 );
1283 
1284  bDone = true;
1285  }
1287  }
1288  break;
1289 
1290  case KEY_DOWN:
1291  {
1292  if ( IsReadOnly() )
1293  {
1294  SetTopEntry( GetTopEntry()+1 );
1295  }
1296  else if ( !bMod2 )
1297  {
1299  {
1300  nSelect = mpEntryList->FindFirstSelectable( 0 );
1301  }
1302  else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() )
1303  {
1304  // search first selectable below the current position
1305  nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos + 1 );
1306  }
1307 
1308  if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect >= GetLastVisibleEntry() ) )
1309  SetTopEntry( mnTop+1 );
1310 
1311  bDone = true;
1312  }
1314  }
1315  break;
1316 
1317  case KEY_PAGEUP:
1318  {
1319  if ( IsReadOnly() )
1320  {
1321  sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop +1;
1322  SetTopEntry( ( mnTop > nCurVis ) ?
1323  (mnTop-nCurVis) : 0 );
1324  }
1325  else if ( !bCtrl && !bMod2 )
1326  {
1328  {
1329  nSelect = mpEntryList->FindFirstSelectable( 0 );
1330  }
1331  else if ( mnCurrentPos )
1332  {
1333  if( mnCurrentPos == mnTop )
1334  {
1335  sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop +1;
1336  SetTopEntry( ( mnTop > nCurVis ) ? ( mnTop-nCurVis+1 ) : 0 );
1337  }
1338 
1339  // find first selectable starting from mnTop looking forward
1340  nSelect = mpEntryList->FindFirstSelectable( mnTop );
1341  }
1342  bDone = true;
1343  }
1345  }
1346  break;
1347 
1348  case KEY_PAGEDOWN:
1349  {
1350  if ( IsReadOnly() )
1351  {
1353  }
1354  else if ( !bCtrl && !bMod2 )
1355  {
1357  {
1358  nSelect = mpEntryList->FindFirstSelectable( 0 );
1359  }
1360  else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() )
1361  {
1362  sal_Int32 nCount = mpEntryList->GetEntryCount();
1363  sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop;
1364  sal_Int32 nTmp = std::min( nCurVis, nCount );
1365  nTmp += mnTop - 1;
1366  if( mnCurrentPos == nTmp && mnCurrentPos != nCount - 1 )
1367  {
1368  tools::Long nTmp2 = std::min( static_cast<tools::Long>(nCount-nCurVis), static_cast<tools::Long>(static_cast<tools::Long>(mnTop)+static_cast<tools::Long>(nCurVis)-1) );
1369  nTmp2 = std::max( tools::Long(0) , nTmp2 );
1370  nTmp = static_cast<sal_Int32>(nTmp2+(nCurVis-1) );
1371  SetTopEntry( static_cast<sal_Int32>(nTmp2) );
1372  }
1373  // find first selectable starting from nTmp looking backwards
1374  nSelect = mpEntryList->FindFirstSelectable( nTmp, false );
1375  }
1376  bDone = true;
1377  }
1379  }
1380  break;
1381 
1382  case KEY_HOME:
1383  {
1384  if ( IsReadOnly() )
1385  {
1386  SetTopEntry( 0 );
1387  }
1388  else if ( !bCtrl && !bMod2 && mnCurrentPos )
1389  {
1390  nSelect = mpEntryList->FindFirstSelectable( mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND );
1391  if( mnTop != 0 )
1392  SetTopEntry( 0 );
1393 
1394  bDone = true;
1395  }
1397  }
1398  break;
1399 
1400  case KEY_END:
1401  {
1402  if ( IsReadOnly() )
1403  {
1404  SetTopEntry( 0xFFFF );
1405  }
1406  else if ( !bCtrl && !bMod2 )
1407  {
1409  {
1410  nSelect = mpEntryList->FindFirstSelectable( 0 );
1411  }
1412  else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() )
1413  {
1414  sal_Int32 nCount = mpEntryList->GetEntryCount();
1415  nSelect = mpEntryList->FindFirstSelectable( nCount - 1, false );
1416  sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop + 1;
1417  if( nCount > nCurVis )
1418  SetTopEntry( nCount - nCurVis );
1419  }
1420  bDone = true;
1421  }
1423  }
1424  break;
1425 
1426  case KEY_LEFT:
1427  {
1428  if ( !bCtrl && !bMod2 )
1429  {
1430  ScrollHorz( -HORZ_SCROLL );
1431  bDone = true;
1432  }
1434  }
1435  break;
1436 
1437  case KEY_RIGHT:
1438  {
1439  if ( !bCtrl && !bMod2 )
1440  {
1442  bDone = true;
1443  }
1445  }
1446  break;
1447 
1448  case KEY_RETURN:
1449  {
1450  if ( !bMod2 && !IsReadOnly() )
1451  {
1453  ImplCallSelect();
1454  bDone = false; // do not catch RETURN
1455  }
1457  }
1458  break;
1459 
1460  case KEY_SPACE:
1461  {
1462  if ( !bMod2 && !IsReadOnly() )
1463  {
1464  if( mbMulti && ( !mbSimpleMode || ( mbSimpleMode && bCtrl && !bShift ) ) )
1465  {
1466  nSelect = mnCurrentPos;
1467  eLET = LET_KEYSPACE;
1468  }
1469  bDone = true;
1470  }
1471  bHandleKey = true;
1472  }
1473  break;
1474 
1475  case KEY_A:
1476  {
1477  if( bCtrl && mbMulti )
1478  {
1479  // paint only once
1480  bool bUpdates = IsUpdateMode();
1481  SetUpdateMode( false );
1482 
1483  sal_Int32 nEntryCount = mpEntryList->GetEntryCount();
1484  for( sal_Int32 i = 0; i < nEntryCount; i++ )
1485  SelectEntry( i, true );
1486 
1487  // restore update mode
1488  SetUpdateMode( bUpdates );
1489  Invalidate();
1490 
1492 
1493  bDone = true;
1494  }
1495  else
1496  {
1497  bHandleKey = true;
1498  }
1499  }
1500  break;
1501 
1502  default:
1503  bHandleKey = true;
1504  break;
1505  }
1506  if (bHandleKey && !IsReadOnly())
1507  {
1508  bDone = maQuickSelectionEngine.HandleKeyEvent( rKEvt );
1509  }
1510 
1511  if ( ( nSelect != LISTBOX_ENTRY_NOTFOUND )
1512  && ( ( !mpEntryList->IsEntryPosSelected( nSelect ) )
1513  || ( eLET == LET_KEYSPACE )
1514  )
1515  )
1516  {
1517  SAL_WARN_IF( mpEntryList->IsEntryPosSelected( nSelect ) && !mbMulti, "vcl", "ImplListBox: Selecting same Entry" );
1518  sal_Int32 nCount = mpEntryList->GetEntryCount();
1519  if (nSelect >= nCount)
1520  nSelect = nCount ? nCount-1 : LISTBOX_ENTRY_NOTFOUND;
1521  bool bCurPosChange = (mnCurrentPos != nSelect);
1522  mnCurrentPos = nSelect;
1523  if(SelectEntries( nSelect, eLET, bShift, bCtrl, bCurPosChange))
1524  {
1525  // tdf#129043 Correctly deliver events when changing values with arrow keys in combobox
1526  if (mbIsDropdown && IsReallyVisible())
1527  mbTravelSelect = true;
1529  ImplCallSelect();
1530  mbTravelSelect = false;
1531  }
1532  }
1533 
1534  return bDone;
1535 }
1536 
1537 namespace
1538 {
1539  vcl::StringEntryIdentifier lcl_getEntry( const ImplEntryList& _rList, sal_Int32 _nPos, OUString& _out_entryText )
1540  {
1541  OSL_PRECOND( ( _nPos != LISTBOX_ENTRY_NOTFOUND ), "lcl_getEntry: invalid position!" );
1542  sal_Int32 nEntryCount( _rList.GetEntryCount() );
1543  if ( _nPos >= nEntryCount )
1544  _nPos = 0;
1545  _out_entryText = _rList.GetEntryText( _nPos );
1546 
1547  // vcl::StringEntryIdentifier does not allow for 0 values, but our position is 0-based
1548  // => normalize
1549  return reinterpret_cast< vcl::StringEntryIdentifier >( _nPos + 1 );
1550  }
1551 
1552  sal_Int32 lcl_getEntryPos( vcl::StringEntryIdentifier _entry )
1553  {
1554  // our pos is 0-based, but StringEntryIdentifier does not allow for a NULL
1555  return static_cast< sal_Int32 >( reinterpret_cast< sal_Int64 >( _entry ) ) - 1;
1556  }
1557 }
1558 
1560 {
1561  return lcl_getEntry( *GetEntryList(), ( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) ? 0 : mnCurrentPos, _out_entryText );
1562 }
1563 
1565 {
1566  sal_Int32 nNextPos = lcl_getEntryPos( _currentEntry ) + 1;
1567  return lcl_getEntry( *GetEntryList(), nNextPos, _out_entryText );
1568 }
1569 
1571 {
1572  sal_Int32 nSelect = lcl_getEntryPos( _entry );
1573  if ( mpEntryList->IsEntryPosSelected( nSelect ) )
1574  {
1575  // ignore that. This method is a callback from the QuickSelectionEngine, which means the user attempted
1576  // to select the given entry by typing its starting letters. No need to act.
1577  return;
1578  }
1579 
1580  // normalize
1581  OSL_ENSURE( nSelect < mpEntryList->GetEntryCount(), "ImplListBoxWindow::SelectEntry: how that?" );
1582  sal_Int32 nCount = mpEntryList->GetEntryCount();
1583  if (nSelect >= nCount)
1584  nSelect = nCount ? nCount-1 : LISTBOX_ENTRY_NOTFOUND;
1585 
1586  // make visible
1587  ShowProminentEntry( nSelect );
1588 
1589  // actually select
1590  mnCurrentPos = nSelect;
1591  if ( SelectEntries( nSelect, LET_KEYMOVE ) )
1592  {
1593  mbTravelSelect = true;
1594  mnSelectModifier = 0;
1595  ImplCallSelect();
1596  mbTravelSelect = false;
1597  }
1598 }
1599 
1600 void ImplListBoxWindow::ImplPaint(vcl::RenderContext& rRenderContext, sal_Int32 nPos)
1601 {
1602  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1603 
1604  const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nPos );
1605  if (!pEntry)
1606  return;
1607 
1608  tools::Long nWidth = GetOutputSizePixel().Width();
1609  tools::Long nY = mpEntryList->GetAddedHeight(nPos, mnTop);
1610  tools::Rectangle aRect(Point(0, nY), Size(nWidth, pEntry->getHeightWithMargin()));
1611 
1612  bool bSelected = mpEntryList->IsEntryPosSelected(nPos);
1613  if (bSelected)
1614  {
1615  rRenderContext.SetTextColor(!IsEnabled() ? rStyleSettings.GetDisableColor() : rStyleSettings.GetHighlightTextColor());
1616  rRenderContext.SetFillColor(rStyleSettings.GetHighlightColor());
1617  rRenderContext.SetLineColor();
1618  rRenderContext.DrawRect(aRect);
1619  }
1620  else
1621  {
1622  ApplySettings(rRenderContext);
1623  if (!IsEnabled())
1624  rRenderContext.SetTextColor(rStyleSettings.GetDisableColor());
1625  }
1626  rRenderContext.SetTextFillColor();
1627 
1628  if (IsUserDrawEnabled())
1629  {
1630  mbInUserDraw = true;
1631  mnUserDrawEntry = nPos;
1632  aRect.AdjustLeft( -mnLeft );
1633  if (nPos < GetEntryList()->GetMRUCount())
1634  nPos = GetEntryList()->FindEntry(GetEntryList()->GetEntryText(nPos));
1635  nPos = nPos - GetEntryList()->GetMRUCount();
1636 
1637  UserDrawEvent aUDEvt(&rRenderContext, aRect, nPos, bSelected);
1638  maUserDrawHdl.Call( &aUDEvt );
1639  mbInUserDraw = false;
1640  }
1641  else
1642  {
1643  DrawEntry(rRenderContext, nPos, true, true);
1644  }
1645 }
1646 
1647 void ImplListBoxWindow::DrawEntry(vcl::RenderContext& rRenderContext, sal_Int32 nPos, bool bDrawImage, bool bDrawText)
1648 {
1649  const ImplEntryType* pEntry = mpEntryList->GetEntryPtr(nPos);
1650  if (!pEntry)
1651  return;
1652 
1653  tools::Long nEntryHeight = pEntry->getHeightWithMargin();
1654 
1655  // when changing this function don't forget to adjust ImplWin::DrawEntry()
1656 
1657  if (mbInUserDraw)
1658  nPos = mnUserDrawEntry; // real entry, not the matching entry from MRU
1659 
1660  tools::Long nY = mpEntryList->GetAddedHeight(nPos, mnTop);
1661 
1662  if (bDrawImage && mpEntryList->HasImages())
1663  {
1664  Image aImage = mpEntryList->GetEntryImage(nPos);
1665  if (!!aImage)
1666  {
1667  Size aImgSz = aImage.GetSizePixel();
1668  Point aPtImg(gnBorder - mnLeft, nY + ((nEntryHeight - aImgSz.Height()) / 2));
1669 
1670  if (!IsZoom())
1671  {
1672  rRenderContext.DrawImage(aPtImg, aImage);
1673  }
1674  else
1675  {
1676  aImgSz.setWidth( CalcZoom(aImgSz.Width()) );
1677  aImgSz.setHeight( CalcZoom(aImgSz.Height()) );
1678  rRenderContext.DrawImage(aPtImg, aImgSz, aImage);
1679  }
1680 
1681  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1682  const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
1683 
1684  if (nEdgeBlendingPercent && aImgSz.Width() && aImgSz.Height())
1685  {
1686  const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
1687  const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
1688  const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
1689  const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight));
1690 
1691  if (!aBlendFrame.IsEmpty())
1692  {
1693  rRenderContext.DrawBitmapEx(aPtImg, aBlendFrame);
1694  }
1695  }
1696  }
1697  }
1698 
1699  if (bDrawText)
1700  {
1701  OUString aStr(mpEntryList->GetEntryText(nPos));
1702  if (!aStr.isEmpty())
1703  {
1704  tools::Long nMaxWidth = std::max(mnMaxWidth, GetOutputSizePixel().Width() - 2 * gnBorder);
1705  // a multiline entry should only be as wide as the window
1706  if (pEntry->mnFlags & ListBoxEntryFlags::MultiLine)
1707  nMaxWidth = GetOutputSizePixel().Width() - 2 * gnBorder;
1708 
1709  tools::Rectangle aTextRect(Point(gnBorder - mnLeft, nY),
1710  Size(nMaxWidth, nEntryHeight));
1711 
1712  if (mpEntryList->HasEntryImage(nPos) || IsUserDrawEnabled())
1713  {
1714  tools::Long nImageWidth = std::max(mnMaxImgWidth, maUserItemSize.Width());
1715  aTextRect.AdjustLeft(nImageWidth + IMG_TXT_DISTANCE );
1716  }
1717 
1718  DrawTextFlags nDrawStyle = ImplGetTextStyle();
1719  if (pEntry->mnFlags & ListBoxEntryFlags::MultiLine)
1720  nDrawStyle |= MULTILINE_ENTRY_DRAW_FLAGS;
1722  nDrawStyle |= DrawTextFlags::Disable;
1723 
1724  rRenderContext.DrawText(aTextRect, aStr, nDrawStyle);
1725  }
1726  }
1727 
1728  if ( !maSeparators.empty() && ( isSeparator(nPos) || isSeparator(nPos-1) ) )
1729  {
1730  Color aOldLineColor(rRenderContext.GetLineColor());
1731  rRenderContext.SetLineColor((GetBackground() != COL_LIGHTGRAY) ? COL_LIGHTGRAY : COL_GRAY);
1732  Point aStartPos(0, nY);
1733  if (isSeparator(nPos))
1734  aStartPos.AdjustY(pEntry->getHeightWithMargin() - 1 );
1735  Point aEndPos(aStartPos);
1736  aEndPos.setX( GetOutputSizePixel().Width() );
1737  rRenderContext.DrawLine(aStartPos, aEndPos);
1738  rRenderContext.SetLineColor(aOldLineColor);
1739  }
1740 }
1741 
1743 {
1744  mpControlData->mpLayoutData.reset( new vcl::ControlLayoutData );
1745  const_cast<ImplListBoxWindow*>(this)->Invalidate(tools::Rectangle(Point(0, 0), GetOutputSize()));
1746 }
1747 
1749 {
1750  sal_Int32 nCount = mpEntryList->GetEntryCount();
1751 
1752  bool bShowFocusRect = mbHasFocusRect;
1753  if (mbHasFocusRect)
1755 
1756  tools::Long nY = 0; // + gnBorder;
1757  tools::Long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + gnBorder;
1758 
1759  for (sal_Int32 i = mnTop; i < nCount && nY < nHeight + mnMaxHeight; i++)
1760  {
1761  const ImplEntryType* pEntry = mpEntryList->GetEntryPtr(i);
1762  tools::Long nEntryHeight = pEntry->getHeightWithMargin();
1763  if (nY + nEntryHeight >= rRect.Top() &&
1764  nY <= rRect.Bottom() + mnMaxHeight)
1765  {
1766  ImplPaint(rRenderContext, i);
1767  }
1768  nY += nEntryHeight;
1769  }
1770 
1771  tools::Long nHeightDiff = mpEntryList->GetAddedHeight(mnCurrentPos, mnTop);
1772  maFocusRect.SetPos(Point(0, nHeightDiff));
1773  Size aSz(maFocusRect.GetWidth(), mpEntryList->GetEntryHeight(mnCurrentPos));
1774  maFocusRect.SetSize(aSz);
1775  if (HasFocus() && bShowFocusRect)
1777 }
1778 
1780 {
1782  {
1783  // This widget is explicitly double-buffered, so avoid partial paints.
1784  tools::Rectangle aRect(Point(0, 0), GetOutputSizePixel());
1785  ImplDoPaint(rRenderContext, aRect);
1786  }
1787  else
1788  ImplDoPaint(rRenderContext, rRect);
1789 }
1790 
1792 {
1793  // FIXME: ListBoxEntryFlags::MultiLine
1794 
1795  const sal_Int32 nCount = mpEntryList->GetEntryCount()-mnTop;
1796  tools::Long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + gnBorder;
1797  sal_uInt16 nEntries = static_cast< sal_uInt16 >( ( nHeight + mnMaxHeight - 1 ) / mnMaxHeight );
1798  if( nEntries > nCount )
1799  nEntries = static_cast<sal_uInt16>(nCount);
1800 
1801  return nEntries;
1802 }
1803 
1805 {
1806  Control::Resize();
1807 
1808  bool bShowFocusRect = mbHasFocusRect;
1809  if ( bShowFocusRect )
1811 
1813  {
1814  Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryHeight( mnCurrentPos ) );
1815  maFocusRect.SetSize( aSz );
1816  }
1817 
1818  if ( bShowFocusRect )
1820 
1822 }
1823 
1825 {
1826  sal_Int32 nPos = mnCurrentPos;
1827  if ( nPos == LISTBOX_ENTRY_NOTFOUND )
1828  nPos = 0;
1829  tools::Long nHeightDiff = mpEntryList->GetAddedHeight( nPos, mnTop );
1830  maFocusRect.SetPos( Point( 0, nHeightDiff ) );
1831  Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( nPos ) );
1832  maFocusRect.SetSize( aSz );
1835 }
1836 
1838 {
1841 }
1842 
1843 void ImplListBoxWindow::SetTopEntry( sal_Int32 nTop )
1844 {
1845  if( mpEntryList->GetEntryCount() == 0 )
1846  return;
1847 
1848  tools::Long nWHeight = PixelToLogic( GetSizePixel() ).Height();
1849 
1850  sal_Int32 nLastEntry = mpEntryList->GetEntryCount()-1;
1851  if( nTop > nLastEntry )
1852  nTop = nLastEntry;
1853  const ImplEntryType* pLast = mpEntryList->GetEntryPtr( nLastEntry );
1854  while( nTop > 0 && mpEntryList->GetAddedHeight( nLastEntry, nTop-1 ) + pLast->getHeightWithMargin() <= nWHeight )
1855  nTop--;
1856 
1857  if ( nTop == mnTop )
1858  return;
1859 
1861  tools::Long nDiff = mpEntryList->GetAddedHeight( mnTop, nTop );
1862  PaintImmediately();
1864  mnTop = nTop;
1865  Scroll( 0, nDiff );
1866  PaintImmediately();
1867  if( HasFocus() )
1869  maScrollHdl.Call( this );
1870 }
1871 
1872 void ImplListBoxWindow::ShowProminentEntry( sal_Int32 nEntryPos )
1873 {
1874  SetTopEntry( nEntryPos );
1875 }
1876 
1878 {
1879  ScrollHorz( n - mnLeft );
1880 }
1881 
1883 {
1884  tools::Long nDiff = 0;
1885  if ( n > 0 )
1886  {
1887  tools::Long nWidth = GetOutputSizePixel().Width();
1888  if( ( mnMaxWidth - mnLeft + n ) > nWidth )
1889  nDiff = n;
1890  }
1891  else if ( n < 0 )
1892  {
1893  if( mnLeft )
1894  {
1895  tools::Long nAbs = -n;
1896  nDiff = - std::min( mnLeft, nAbs );
1897  }
1898  }
1899 
1900  if ( nDiff )
1901  {
1903  mnLeft = sal::static_int_cast<sal_uInt16>(mnLeft + nDiff);
1904  PaintImmediately();
1906  Scroll( -nDiff, 0 );
1907  PaintImmediately();
1908  if( HasFocus() )
1910  maScrollHdl.Call( this );
1911  }
1912 }
1913 
1915 {
1916  maSeparators.clear();
1917 
1918  if ( n != LISTBOX_ENTRY_NOTFOUND )
1919  {
1920  maSeparators.insert( n );
1921  }
1922 }
1923 
1925 {
1926  if (!maSeparators.empty())
1927  return *(maSeparators.begin());
1928  else
1929  return LISTBOX_ENTRY_NOTFOUND;
1930 }
1931 
1932 bool ImplListBoxWindow::isSeparator( const sal_Int32 &n) const
1933 {
1934  return maSeparators.find(n) != maSeparators.end();
1935 }
1936 
1937 Size ImplListBoxWindow::CalcSize(sal_Int32 nMaxLines) const
1938 {
1939  // FIXME: ListBoxEntryFlags::MultiLine
1940 
1941  Size aSz;
1942  aSz.setHeight(nMaxLines * GetEntryHeightWithMargin());
1943  aSz.setWidth( mnMaxWidth + 2*gnBorder );
1944  return aSz;
1945 }
1946 
1948 {
1949  const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nItem );
1950  Size aSz( GetSizePixel().Width(), pEntry ? pEntry->getHeightWithMargin() : GetEntryHeightWithMargin() );
1951  tools::Long nY = mpEntryList->GetAddedHeight( nItem, GetTopEntry() ) + GetEntryList()->GetMRUCount()*GetEntryHeightWithMargin();
1952  tools::Rectangle aRect( Point( 0, nY ), aSz );
1953  return aRect;
1954 }
1955 
1957 {
1958  Control::StateChanged( nType );
1959 
1960  if ( nType == StateChangedType::Zoom )
1961  {
1962  ApplySettings(*this);
1963  ImplCalcMetrics();
1964  Invalidate();
1965  }
1966  else if ( nType == StateChangedType::UpdateMode )
1967  {
1968  if ( IsUpdateMode() && IsReallyVisible() )
1969  Invalidate();
1970  }
1971  else if ( nType == StateChangedType::ControlFont )
1972  {
1973  ApplySettings(*this);
1974  ImplCalcMetrics();
1975  Invalidate();
1976  }
1977  else if ( nType == StateChangedType::ControlForeground )
1978  {
1979  ApplySettings(*this);
1980  Invalidate();
1981  }
1982  else if ( nType == StateChangedType::ControlBackground )
1983  {
1984  ApplySettings(*this);
1985  Invalidate();
1986  }
1987  else if( nType == StateChangedType::Enable )
1988  {
1989  Invalidate();
1990  }
1991 
1993 }
1994 
1996 {
1997  Control::DataChanged( rDCEvt );
1998 
1999  if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
2001  ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
2002  (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
2003  {
2005  ApplySettings(*this);
2006  ImplCalcMetrics();
2007  Invalidate();
2008  }
2009 }
2010 
2012 {
2014 
2015  if (mpEntryList->HasImages())
2016  nTextStyle |= DrawTextFlags::Left;
2017  else if (mbCenter)
2018  nTextStyle |= DrawTextFlags::Center;
2019  else if (mbRight)
2020  nTextStyle |= DrawTextFlags::Right;
2021  else
2022  nTextStyle |= DrawTextFlags::Left;
2023 
2024  return nTextStyle;
2025 }
2026 
2028  Control( pParent, nWinStyle ),
2029  maLBWindow(VclPtr<ImplListBoxWindow>::Create( this, nWinStyle&(~WB_BORDER) ))
2030 {
2031  // for native widget rendering we must be able to detect this window type
2032  SetType( WindowType::LISTBOXWINDOW );
2033 
2037 
2038  Link<ScrollBar*,void> aLink( LINK( this, ImplListBox, ScrollBarHdl ) );
2039  mpVScrollBar->SetScrollHdl( aLink );
2040  mpHScrollBar->SetScrollHdl( aLink );
2041 
2042  mbVScroll = false;
2043  mbHScroll = false;
2044  mbAutoHScroll = ( nWinStyle & WB_AUTOHSCROLL );
2045  mbEdgeBlending = false;
2046 
2047  maLBWindow->SetScrollHdl( LINK( this, ImplListBox, LBWindowScrolled ) );
2048  maLBWindow->SetMRUChangedHdl( LINK( this, ImplListBox, MRUChanged ) );
2050  maLBWindow->Show();
2051 }
2052 
2054 {
2055  disposeOnce();
2056 }
2057 
2059 {
2064  Control::dispose();
2065 }
2066 
2068 {
2069  maLBWindow->Clear();
2070  if ( GetEntryList()->GetMRUCount() )
2071  {
2074  }
2075  mpVScrollBar->SetThumbPos( 0 );
2076  mpHScrollBar->SetThumbPos( 0 );
2078 }
2079 
2080 sal_Int32 ImplListBox::InsertEntry( sal_Int32 nPos, const OUString& rStr )
2081 {
2082  ImplEntryType* pNewEntry = new ImplEntryType( rStr );
2083  sal_Int32 nNewPos = maLBWindow->InsertEntry( nPos, pNewEntry );
2085  return nNewPos;
2086 }
2087 
2088 sal_Int32 ImplListBox::InsertEntry( sal_Int32 nPos, const OUString& rStr, const Image& rImage )
2089 {
2090  ImplEntryType* pNewEntry = new ImplEntryType( rStr, rImage );
2091  sal_Int32 nNewPos = maLBWindow->InsertEntry( nPos, pNewEntry );
2093  return nNewPos;
2094 }
2095 
2096 void ImplListBox::RemoveEntry( sal_Int32 nPos )
2097 {
2098  maLBWindow->RemoveEntry( nPos );
2100 }
2101 
2102 void ImplListBox::SetEntryFlags( sal_Int32 nPos, ListBoxEntryFlags nFlags )
2103 {
2104  maLBWindow->SetEntryFlags( nPos, nFlags );
2105 }
2106 
2107 void ImplListBox::SelectEntry( sal_Int32 nPos, bool bSelect )
2108 {
2109  maLBWindow->SelectEntry( nPos, bSelect );
2110 }
2111 
2113 {
2115 }
2116 
2118 {
2119  if (maLBWindow)
2120  maLBWindow->GrabFocus();
2121  else
2123 }
2124 
2126 {
2127  Control::Resize();
2130 }
2131 
2133 {
2134  CompatStateChanged( StateChangedType::Data );
2135 }
2136 
2138 {
2139  tools::Long nSet = GetTopEntry();
2140  if( nSet > mpVScrollBar->GetRangeMax() )
2141  mpVScrollBar->SetRangeMax( GetEntryList()->GetEntryCount() );
2142  mpVScrollBar->SetThumbPos( GetTopEntry() );
2143 
2144  mpHScrollBar->SetThumbPos( GetLeftIndent() );
2145 
2146  maScrollHdl.Call( this );
2147 }
2148 
2149 IMPL_LINK( ImplListBox, ScrollBarHdl, ScrollBar*, pSB, void )
2150 {
2151  sal_uInt16 nPos = static_cast<sal_uInt16>(pSB->GetThumbPos());
2152  if( pSB == mpVScrollBar )
2153  SetTopEntry( nPos );
2154  else if( pSB == mpHScrollBar )
2155  SetLeftIndent( nPos );
2156  if( GetParent() )
2157  GetParent()->Invalidate( InvalidateFlags::Update );
2158 }
2159 
2161 {
2162  bool bArrange = false;
2163 
2164  Size aOutSz = GetOutputSizePixel();
2165  sal_Int32 nEntries = GetEntryList()->GetEntryCount();
2166  sal_uInt16 nMaxVisEntries = static_cast<sal_uInt16>(aOutSz.Height() / GetEntryHeightWithMargin());
2167 
2168  // vertical ScrollBar
2169  if( nEntries > nMaxVisEntries )
2170  {
2171  if( !mbVScroll )
2172  bArrange = true;
2173  mbVScroll = true;
2174 
2175  // check of the scrolled-out region
2176  if( GetEntryList()->GetSelectedEntryCount() == 1 &&
2179  else
2180  SetTopEntry( GetTopEntry() ); // MaxTop is being checked...
2181  }
2182  else
2183  {
2184  if( mbVScroll )
2185  bArrange = true;
2186  mbVScroll = false;
2187  SetTopEntry( 0 );
2188  }
2189 
2190  // horizontal ScrollBar
2191  if( mbAutoHScroll )
2192  {
2193  tools::Long nWidth = static_cast<sal_uInt16>(aOutSz.Width());
2194  if ( mbVScroll )
2195  nWidth -= mpVScrollBar->GetSizePixel().Width();
2196 
2197  tools::Long nMaxWidth = GetMaxEntryWidth();
2198  if( nWidth < nMaxWidth )
2199  {
2200  if( !mbHScroll )
2201  bArrange = true;
2202  mbHScroll = true;
2203 
2204  if ( !mbVScroll ) // maybe we do need one now
2205  {
2206  nMaxVisEntries = static_cast<sal_uInt16>( ( aOutSz.Height() - mpHScrollBar->GetSizePixel().Height() ) / GetEntryHeightWithMargin() );
2207  if( nEntries > nMaxVisEntries )
2208  {
2209  bArrange = true;
2210  mbVScroll = true;
2211 
2212  // check of the scrolled-out region
2213  if( GetEntryList()->GetSelectedEntryCount() == 1 &&
2216  else
2217  SetTopEntry( GetTopEntry() ); // MaxTop is being checked...
2218  }
2219  }
2220 
2221  // check of the scrolled-out region
2222  sal_uInt16 nMaxLI = static_cast<sal_uInt16>(nMaxWidth - nWidth);
2223  if ( nMaxLI < GetLeftIndent() )
2224  SetLeftIndent( nMaxLI );
2225  }
2226  else
2227  {
2228  if( mbHScroll )
2229  bArrange = true;
2230  mbHScroll = false;
2231  SetLeftIndent( 0 );
2232  }
2233  }
2234 
2235  if( bArrange )
2237 
2239 }
2240 
2242 {
2243  Size aOutSz = maLBWindow->GetOutputSizePixel();
2244 
2245  if ( mbVScroll )
2246  {
2247  sal_Int32 nEntries = GetEntryList()->GetEntryCount();
2248  sal_uInt16 nVisEntries = static_cast<sal_uInt16>(aOutSz.Height() / GetEntryHeightWithMargin());
2249  mpVScrollBar->SetRangeMax( nEntries );
2250  mpVScrollBar->SetVisibleSize( nVisEntries );
2251  mpVScrollBar->SetPageSize( nVisEntries - 1 );
2252  }
2253 
2254  if ( mbHScroll )
2255  {
2257  mpHScrollBar->SetVisibleSize( static_cast<sal_uInt16>(aOutSz.Width()) );
2259  mpHScrollBar->SetPageSize( aOutSz.Width() - HORZ_SCROLL );
2260  }
2261 }
2262 
2264 {
2265  // Here we only position the Controls; if the Scrollbars are to be
2266  // visible is already determined in ImplCheckScrollBars
2267 
2268  Size aOutSz = GetOutputSizePixel();
2270  nSBWidth = CalcZoom( nSBWidth );
2271 
2272  Size aInnerSz( aOutSz );
2273  if ( mbVScroll )
2274  aInnerSz.AdjustWidth( -nSBWidth );
2275  if ( mbHScroll )
2276  aInnerSz.AdjustHeight( -nSBWidth );
2277 
2278  Point aWinPos( 0, 0 );
2279  maLBWindow->SetPosSizePixel( aWinPos, aInnerSz );
2280 
2281  // ScrollBarBox
2282  if( mbVScroll && mbHScroll )
2283  {
2284  Point aBoxPos( aInnerSz.Width(), aInnerSz.Height() );
2285  mpScrollBarBox->SetPosSizePixel( aBoxPos, Size( nSBWidth, nSBWidth ) );
2286  mpScrollBarBox->Show();
2287  }
2288  else
2289  {
2290  mpScrollBarBox->Hide();
2291  }
2292 
2293  // vertical ScrollBar
2294  if( mbVScroll )
2295  {
2296  // Scrollbar on left or right side?
2297  Point aVPos( aOutSz.Width() - nSBWidth, 0 );
2298  mpVScrollBar->SetPosSizePixel( aVPos, Size( nSBWidth, aInnerSz.Height() ) );
2299  mpVScrollBar->Show();
2300  }
2301  else
2302  {
2303  mpVScrollBar->Hide();
2304  // #107254# Don't reset top entry after resize, but check for max top entry
2305  SetTopEntry( GetTopEntry() );
2306  }
2307 
2308  // horizontal ScrollBar
2309  if( mbHScroll )
2310  {
2311  Point aHPos( 0, aOutSz.Height() - nSBWidth );
2312  mpHScrollBar->SetPosSizePixel( aHPos, Size( aInnerSz.Width(), nSBWidth ) );
2313  mpHScrollBar->Show();
2314  }
2315  else
2316  {
2317  mpHScrollBar->Hide();
2318  SetLeftIndent( 0 );
2319  }
2320 }
2321 
2323 {
2324  if ( nType == StateChangedType::InitShow )
2325  {
2327  }
2328  else if ( ( nType == StateChangedType::UpdateMode ) || ( nType == StateChangedType::Data ) )
2329  {
2330  bool bUpdate = IsUpdateMode();
2331  maLBWindow->SetUpdateMode( bUpdate );
2332  if ( bUpdate && IsReallyVisible() )
2334  }
2335  else if( nType == StateChangedType::Enable )
2336  {
2340  maLBWindow->Enable( IsEnabled() );
2341 
2342  Invalidate();
2343  }
2344  else if ( nType == StateChangedType::Zoom )
2345  {
2346  maLBWindow->SetZoom( GetZoom() );
2347  Resize();
2348  }
2349  else if ( nType == StateChangedType::ControlFont )
2350  {
2352  }
2353  else if ( nType == StateChangedType::ControlForeground )
2354  {
2356  }
2357  else if ( nType == StateChangedType::ControlBackground )
2358  {
2360  }
2361  else if( nType == StateChangedType::Mirroring )
2362  {
2367  }
2368 
2369  Control::StateChanged( nType );
2370 }
2371 
2373 {
2374  bool bDone = false;
2375  if ( rNEvt.GetType() == MouseNotifyEvent::COMMAND )
2376  {
2377  const CommandEvent& rCEvt = *rNEvt.GetCommandEvent();
2378  if ( rCEvt.GetCommand() == CommandEventId::Wheel )
2379  {
2380  const CommandWheelData* pData = rCEvt.GetWheelData();
2381  if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
2382  {
2383  bDone = HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar );
2384  }
2385  }
2386  else if (rCEvt.GetCommand() == CommandEventId::Gesture)
2387  {
2389  }
2390  }
2391 
2392  return bDone || Window::EventNotify( rNEvt );
2393 }
2394 
2396 {
2397  return maLBWindow->GetDisplayBackground();
2398 }
2399 
2401 {
2402  bool bDone = false;
2403  if ( rCEvt.GetCommand() == CommandEventId::Wheel )
2404  {
2405  const CommandWheelData* pData = rCEvt.GetWheelData();
2406  if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
2407  {
2408  if (!rControl.HasChildPathFocus())
2409  rControl.GrabFocus();
2410  sal_uInt16 nKey = ( pData->GetDelta() < 0 ) ? KEY_DOWN : KEY_UP;
2411  KeyEvent aKeyEvent( 0, vcl::KeyCode( nKey ) );
2412  bDone = ProcessKeyInput( aKeyEvent );
2413  }
2414  }
2415  return bDone;
2416 }
2417 
2418 void ImplListBox::SetMRUEntries( const OUString& rEntries, sal_Unicode cSep )
2419 {
2420  bool bChanges = GetEntryList()->GetMRUCount() != 0;
2421 
2422  // Remove old MRU entries
2423  for ( sal_Int32 n = GetEntryList()->GetMRUCount();n; )
2424  maLBWindow->RemoveEntry( --n );
2425 
2426  sal_Int32 nMRUCount = 0;
2427  sal_Int32 nIndex = 0;
2428  do
2429  {
2430  OUString aEntry = rEntries.getToken( 0, cSep, nIndex );
2431  // Accept only existing entries
2432  if ( GetEntryList()->FindEntry( aEntry ) != LISTBOX_ENTRY_NOTFOUND )
2433  {
2434  ImplEntryType* pNewEntry = new ImplEntryType( aEntry );
2435  maLBWindow->InsertEntry(nMRUCount++, pNewEntry, false);
2436  bChanges = true;
2437  }
2438  }
2439  while ( nIndex >= 0 );
2440 
2441  if ( bChanges )
2442  {
2443  maLBWindow->GetEntryList()->SetMRUCount( nMRUCount );
2444  SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 );
2446  }
2447 }
2448 
2450 {
2451  OUStringBuffer aEntries;
2452  for ( sal_Int32 n = 0; n < GetEntryList()->GetMRUCount(); n++ )
2453  {
2454  aEntries.append(GetEntryList()->GetEntryText( n ));
2455  if( n < ( GetEntryList()->GetMRUCount() - 1 ) )
2456  aEntries.append(cSep);
2457  }
2458  return aEntries.makeStringAndClear();
2459 }
2460 
2462 {
2463  if(mbEdgeBlending != bNew)
2464  {
2465  mbEdgeBlending = bNew;
2467  }
2468 }
2469 
2470 ImplWin::ImplWin( vcl::Window* pParent, WinBits nWinStyle ) :
2471  Control ( pParent, nWinStyle )
2472 {
2475  SetBackground();
2476  else
2477  SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
2478 
2480 
2481  mbEdgeBlending = false;
2483 }
2484 
2486 {
2487  if( IsEnabled() )
2488  {
2489  maMBDownHdl.Call(this);
2490  }
2491 }
2492 
2494 {
2495  mpControlData->mpLayoutData.reset( new vcl::ControlLayoutData );
2496  ImplWin* pThis = const_cast<ImplWin*>(this);
2497  pThis->ImplDraw(*pThis, true);
2498 }
2499 
2501 {
2502  if( rNEvt.GetType() == MouseNotifyEvent::MOUSEMOVE )
2503  {
2504  const MouseEvent* pMouseEvt = rNEvt.GetMouseEvent();
2505  if( pMouseEvt && (pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow()) )
2506  {
2507  // trigger redraw as mouse over state has changed
2510  {
2512  }
2513  }
2514  }
2515 
2516  return Control::PreNotify(rNEvt);
2517 }
2518 
2519 void ImplWin::ImplDraw(vcl::RenderContext& rRenderContext, bool bLayout)
2520 {
2521  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
2522 
2523  if (!bLayout)
2524  {
2525  bool bNativeOK = false;
2526  bool bHasFocus = HasFocus();
2527  bool bIsEnabled = IsEnabled();
2528 
2532  {
2533  // Repaint the (focused) area similarly to
2534  // ImplSmallBorderWindowView::DrawWindow() in
2535  // vcl/source/window/brdwin.cxx
2536  vcl::Window *pWin = GetParent();
2537 
2538  ImplControlValue aControlValue;
2539  bIsEnabled &= pWin->IsEnabled();
2540  if ( !bIsEnabled )
2541  nState &= ~ControlState::ENABLED;
2542  bHasFocus |= pWin->HasFocus();
2543  if ( bHasFocus )
2544  nState |= ControlState::FOCUSED;
2545 
2546  // The listbox is painted over the entire control including the
2547  // border, but ImplWin does not contain the border => correction
2548  // needed.
2549  sal_Int32 nLeft, nTop, nRight, nBottom;
2550  pWin->GetBorder( nLeft, nTop, nRight, nBottom );
2551  Point aPoint( -nLeft, -nTop );
2552  tools::Rectangle aCtrlRegion( aPoint - GetPosPixel(), pWin->GetSizePixel() );
2553 
2554  bool bMouseOver = false;
2555  vcl::Window *pChild = pWin->GetWindow( GetWindowType::FirstChild );
2556  while( pChild )
2557  {
2558  bMouseOver = pChild->IsMouseOver();
2559  if (bMouseOver)
2560  break;
2561  pChild = pChild->GetWindow( GetWindowType::Next );
2562  }
2563  if( bMouseOver )
2564  nState |= ControlState::ROLLOVER;
2565 
2566  // if parent has no border, then nobody has drawn the background
2567  // since no border window exists. so draw it here.
2568  WinBits nParentStyle = pWin->GetStyle();
2569  if( ! (nParentStyle & WB_BORDER) || (nParentStyle & WB_NOBORDER) )
2570  {
2571  tools::Rectangle aParentRect( Point( 0, 0 ), pWin->GetSizePixel() );
2573  nState, aControlValue, OUString() );
2574  }
2575 
2576  bNativeOK = rRenderContext.DrawNativeControl(ControlType::Listbox, ControlPart::Entire, aCtrlRegion,
2577  nState, aControlValue, OUString());
2578  }
2579 
2580  if (bIsEnabled)
2581  {
2582  if (bHasFocus && !ImplGetSVData()->maNWFData.mbDDListBoxNoTextArea)
2583  {
2584  if ( !ImplGetSVData()->maNWFData.mbNoFocusRects )
2585  {
2586  rRenderContext.SetFillColor( rStyleSettings.GetHighlightColor() );
2587  rRenderContext.SetTextColor( rStyleSettings.GetHighlightTextColor() );
2588  }
2589  else
2590  {
2591  rRenderContext.SetLineColor();
2592  rRenderContext.SetFillColor();
2593  rRenderContext.SetTextColor( rStyleSettings.GetFieldTextColor() );
2594  }
2595  rRenderContext.DrawRect( maFocusRect );
2596  }
2597  else
2598  {
2599  Color aColor;
2600  if (IsControlForeground())
2601  aColor = GetControlForeground();
2602  else if (ImplGetSVData()->maNWFData.mbDDListBoxNoTextArea)
2603  {
2604  if( bNativeOK && (nState & ControlState::ROLLOVER) )
2605  aColor = rStyleSettings.GetButtonRolloverTextColor();
2606  else
2607  aColor = rStyleSettings.GetButtonTextColor();
2608  }
2609  else
2610  {
2611  if( bNativeOK && (nState & ControlState::ROLLOVER) )
2612  aColor = rStyleSettings.GetFieldRolloverTextColor();
2613  else
2614  aColor = rStyleSettings.GetFieldTextColor();
2615  }
2616  rRenderContext.SetTextColor(aColor);
2617  if (!bNativeOK)
2618  rRenderContext.Erase(maFocusRect);
2619  }
2620  }
2621  else // Disabled
2622  {
2623  rRenderContext.SetTextColor(rStyleSettings.GetDisableColor());
2624  if (!bNativeOK)
2625  rRenderContext.Erase(maFocusRect);
2626  }
2627  }
2628 
2629  DrawEntry(rRenderContext, bLayout);
2630 }
2631 
2633 {
2634  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
2635 
2636  ApplyControlFont(rRenderContext, rStyleSettings.GetFieldFont());
2637  ApplyControlForeground(rRenderContext, rStyleSettings.GetFieldTextColor());
2638 
2639  if (IsControlBackground())
2640  rRenderContext.SetBackground(GetControlBackground());
2641  else
2642  rRenderContext.SetBackground(rStyleSettings.GetFieldColor());
2643 }
2644 
2645 void ImplWin::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& )
2646 {
2647  ImplDraw(rRenderContext);
2648 }
2649 
2650 void ImplWin::DrawEntry(vcl::RenderContext& rRenderContext, bool bLayout)
2651 {
2652  tools::Long nBorder = 1;
2653  Size aOutSz(GetOutputSizePixel());
2654 
2655  bool bImage = !!maImage;
2656  if (bImage && !bLayout)
2657  {
2659  Size aImgSz = maImage.GetSizePixel();
2660  Point aPtImg( nBorder, ( ( aOutSz.Height() - aImgSz.Height() ) / 2 ) );
2661  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2662 
2663  // check for HC mode
2664  Image *pImage = &maImage;
2665 
2666  if ( !IsZoom() )
2667  {
2668  rRenderContext.DrawImage( aPtImg, *pImage, nStyle );
2669  }
2670  else
2671  {
2672  aImgSz.setWidth( CalcZoom( aImgSz.Width() ) );
2673  aImgSz.setHeight( CalcZoom( aImgSz.Height() ) );
2674  rRenderContext.DrawImage( aPtImg, aImgSz, *pImage, nStyle );
2675  }
2676 
2677  const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
2678 
2679  if(nEdgeBlendingPercent)
2680  {
2681  const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
2682  const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
2683  const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
2684  const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight));
2685 
2686  if(!aBlendFrame.IsEmpty())
2687  {
2688  rRenderContext.DrawBitmapEx(aPtImg, aBlendFrame);
2689  }
2690  }
2691  }
2692 
2693  if( !maString.isEmpty() )
2694  {
2696 
2697  if ( bImage && !bLayout )
2698  nTextStyle |= DrawTextFlags::Left;
2699  else if ( GetStyle() & WB_CENTER )
2700  nTextStyle |= DrawTextFlags::Center;
2701  else if ( GetStyle() & WB_RIGHT )
2702  nTextStyle |= DrawTextFlags::Right;
2703  else
2704  nTextStyle |= DrawTextFlags::Left;
2705 
2706  tools::Rectangle aTextRect( Point( nBorder, 0 ), Size( aOutSz.Width()-2*nBorder, aOutSz.Height() ) );
2707 
2708  if ( bImage )
2709  {
2711  }
2712 
2713  MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : nullptr;
2714  OUString* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : nullptr;
2715  rRenderContext.DrawText( aTextRect, maString, nTextStyle, pVector, pDisplayText );
2716  }
2717 
2718  if( HasFocus() && !bLayout )
2720 }
2721 
2723 {
2724  Control::Resize();
2726  Invalidate();
2727 }
2728 
2730 {
2732  if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2735  {
2737  if( ! pWin )
2738  pWin = GetParent();
2739  pWin->Invalidate();
2740  }
2741  else
2742  Invalidate();
2744 }
2745 
2747 {
2748  HideFocus();
2749  if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2752  {
2754  if( ! pWin )
2755  pWin = GetParent();
2756  pWin->Invalidate();
2757  }
2758  else
2759  Invalidate();
2761 }
2762 
2764 {
2766  {
2767  ImplControlValue aControlValue;
2768 
2769  vcl::Window *pWin = GetParent();
2770  tools::Rectangle aParentRect(Point(0, 0), pWin->GetSizePixel());
2772  ControlState::FOCUSED, aControlValue, OUString());
2773  }
2774  Control::ShowFocus(rRect);
2775 }
2776 
2777 ImplBtn::ImplBtn( vcl::Window* pParent, WinBits nWinStyle ) :
2778  PushButton( pParent, nWinStyle )
2779 {
2780 }
2781 
2783 {
2784  if( IsEnabled() )
2785  maMBDownHdl.Call(this);
2786 }
2787 
2789  FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW ) // no drop shadow for list boxes
2790 {
2791  // for native widget rendering we must be able to detect this window type
2792  SetType( WindowType::LISTBOXWINDOW );
2793 
2794  mpImplLB = nullptr;
2795  mnDDLineCount = 0;
2796  mbAutoWidth = false;
2797 
2799 
2800  vcl::Window * pBorderWindow = ImplGetBorderWindow();
2801  if( pBorderWindow )
2802  {
2803  SetAccessibleRole(accessibility::AccessibleRole::PANEL);
2804  pBorderWindow->SetAccessibleRole(accessibility::AccessibleRole::WINDOW);
2805  }
2806  else
2807  {
2808  SetAccessibleRole(accessibility::AccessibleRole::WINDOW);
2809  }
2810 
2811 }
2812 
2814 {
2815  disposeOnce();
2816 }
2817 
2819 {
2820  mpImplLB.clear();
2822 }
2823 
2824 
2826 {
2827  if( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
2828  {
2829  if( !GetParent()->HasChildPathFocus( true ) )
2830  EndPopupMode();
2831  }
2832 
2833  return FloatingWindow::PreNotify( rNEvt );
2834 }
2835 
2837 {
2838  FloatingWindow::setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
2839 
2840  // Fix #60890# ( MBA ): to be able to resize the Listbox even in its open state
2841  // after a call to Resize(), we adjust its position if necessary
2842  if ( IsReallyVisible() && ( nFlags & PosSizeFlags::Height ) )
2843  {
2844  Point aPos = GetParent()->GetPosPixel();
2845  aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
2846 
2847  if ( nFlags & PosSizeFlags::X )
2848  aPos.setX( nX );
2849 
2850  if ( nFlags & PosSizeFlags::Y )
2851  aPos.setY( nY );
2852 
2853  sal_uInt16 nIndex;
2855  }
2856 
2857 // if( !IsReallyVisible() )
2858  {
2859  // The ImplListBox does not get a Resize() as not visible.
2860  // But the windows must get a Resize(), so that the number of
2861  // visible entries is correct for PgUp/PgDown.
2862  // The number also cannot be calculated by List/Combobox, as for
2863  // this the presence of the vertical Scrollbar has to be known.
2865  static_cast<vcl::Window*>(mpImplLB)->Resize();
2866  static_cast<vcl::Window*>(mpImplLB->GetMainWindow())->Resize();
2867  }
2868 }
2869 
2871 {
2874 }
2875 
2877 {
2878  Size aFloatSz( maPrefSz );
2879 
2880  sal_Int32 nLeft, nTop, nRight, nBottom;
2881  GetBorder( nLeft, nTop, nRight, nBottom );
2882 
2883  sal_Int32 nLines = mpImplLB->GetEntryList()->GetEntryCount();
2884  if ( mnDDLineCount && ( nLines > mnDDLineCount ) )
2885  nLines = mnDDLineCount;
2886 
2887  Size aSz = mpImplLB->CalcSize( nLines );
2888  tools::Long nMaxHeight = aSz.Height() + nTop + nBottom;
2889 
2890  if ( mnDDLineCount )
2891  aFloatSz.setHeight( nMaxHeight );
2892 
2893  if( mbAutoWidth )
2894  {
2895  // AutoSize first only for width...
2896 
2897  aFloatSz.setWidth( aSz.Width() + nLeft + nRight );
2898  aFloatSz.AdjustWidth(nRight ); // adding some space looks better...
2899 
2900  if ( ( aFloatSz.Height() < nMaxHeight ) || ( mnDDLineCount && ( mnDDLineCount < mpImplLB->GetEntryList()->GetEntryCount() ) ) )
2901  {
2902  // then we also need the vertical Scrollbar
2904  aFloatSz.AdjustWidth(nSBWidth );
2905  }
2906 
2907  tools::Long nDesktopWidth = GetDesktopRectPixel().getWidth();
2908  if (aFloatSz.Width() > nDesktopWidth)
2909  // Don't exceed the desktop width.
2910  aFloatSz.setWidth( nDesktopWidth );
2911  }
2912 
2913  if ( aFloatSz.Height() > nMaxHeight )
2914  aFloatSz.setHeight( nMaxHeight );
2915 
2916  // Minimal height, in case height is not set to Float height.
2917  // The parent of FloatWin must be DropDown-Combo/Listbox.
2918  Size aParentSz = GetParent()->GetSizePixel();
2919  if( (!mnDDLineCount || !nLines) && ( aFloatSz.Height() < aParentSz.Height() ) )
2920  aFloatSz.setHeight( aParentSz.Height() );
2921 
2922  // do not get narrower than the parent...
2923  if( aFloatSz.Width() < aParentSz.Width() )
2924  aFloatSz.setWidth( aParentSz.Width() );
2925 
2926  // align height to entries...
2927  tools::Long nInnerHeight = aFloatSz.Height() - nTop - nBottom;
2928  tools::Long nEntryHeight = mpImplLB->GetEntryHeightWithMargin();
2929  if ( nInnerHeight % nEntryHeight )
2930  {
2931  nInnerHeight /= nEntryHeight;
2932  nInnerHeight++;
2933  nInnerHeight *= nEntryHeight;
2934  aFloatSz.setHeight( nInnerHeight + nTop + nBottom );
2935  }
2936 
2937  if (aFloatSz.Width() < aSz.Width())
2938  {
2939  // The max width of list box entries exceeds the window width.
2940  // Account for the scroll bar height.
2942  aFloatSz.AdjustHeight(nSBWidth );
2943  }
2944 
2945  return aFloatSz;
2946 }
2947 
2948 void ImplListBoxFloatingWindow::StartFloat( bool bStartTracking )
2949 {
2950  if( IsInPopupMode() )
2951  return;
2952 
2953  Size aFloatSz = CalcFloatSize();
2954 
2955  SetSizePixel( aFloatSz );
2957 
2958  sal_Int32 nPos = mpImplLB->GetEntryList()->GetSelectedEntryPos( 0 );
2960 
2961  Size aSz = GetParent()->GetSizePixel();
2962  Point aPos = GetParent()->GetPosPixel();
2963  aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
2964  // FIXME: this ugly hack is for Mac/Aqua
2965  // should be replaced by a real mechanism to place the float rectangle
2966  if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2968  {
2969  const sal_Int32 nLeft = 4, nTop = 4, nRight = 4, nBottom = 4;
2970  aPos.AdjustX(nLeft );
2971  aPos.AdjustY(nTop );
2972  aSz.AdjustWidth( -(nLeft + nRight) );
2973  aSz.AdjustHeight( -(nTop + nBottom) );
2974  }
2975  tools::Rectangle aRect( aPos, aSz );
2976 
2977  // check if the control's parent is un-mirrored which is the case for form controls in a mirrored UI
2978  // where the document is unmirrored
2979  // because StartPopupMode() expects a rectangle in mirrored coordinates we have to re-mirror
2980  vcl::Window *pGrandparent = GetParent()->GetParent();
2981  const OutputDevice *pGrandparentOutDev = pGrandparent->GetOutDev();
2982 
2983  if( pGrandparent->ImplIsAntiparallel() )
2984  pGrandparentOutDev->ReMirror( aRect );
2985 
2986  // mouse-button right: close the List-Box-Float-win and don't stop the handling fdo#84795
2988 
2989  if( nPos != LISTBOX_ENTRY_NOTFOUND )
2990  mpImplLB->ShowProminentEntry( nPos );
2991 
2992  if( bStartTracking )
2994 
2997 
2999 
3000 }
3001 
3002 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual Point GetPosPixel() const
Definition: window.cxx:2783
tools::Rectangle maFocusRect
Definition: listbox.hxx:542
void SelectEntry(sal_Int32 nPos, bool bSelect)
Size GetSizePixel() const
Definition: Image.cxx:86
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
void SetPos(const Point &rPoint)
bool IsControlBackground() const
Definition: window2.cxx:1086
bool GetEdgeBlending() const
Definition: listbox.hxx:493
virtual void EnableRTL(bool bEnable=true) override
Definition: ctrl.cxx:65
virtual void ShowFocus(const tools::Rectangle &rRect) override
bool IsInPopupMode() const
Definition: floatwin.hxx:130
virtual const Wallpaper & GetDisplayBackground() const
Definition: window.cxx:3059
bool mbAutoHScroll
Definition: listbox.hxx:386
WinBits const WB_NOSHADOW
virtual void LoseFocus() override
Link< sal_Int32, void > maFocusHdl
Definition: listbox.hxx:230
bool mbEdgeBlending
Definition: listbox.hxx:546
void SetMRUEntries(const OUString &rEntries, sal_Unicode cSep)
const Wallpaper & GetBackground() const
Definition: outdev.hxx:647
sal_Int32 NaturalSortCompare(const OUString &rA, const OUString &rB)
void StartPopupMode(const tools::Rectangle &rRect, FloatWinPopupFlags nFlags)
Definition: floatwin.cxx:771
void HideFocus()
Definition: window2.cxx:91
sal_Int32 nIndex
SalLayoutGlyphs maStrGlyphs
Definition: listbox.hxx:53
bool mbTrack
Tracking.
Definition: listbox.hxx:207
virtual void Resize() override
#define HORZ_SCROLL
Definition: listbox.hxx:39
virtual void LoseFocus() override
bool HandleKeyEvent(const KeyEvent &_rKEvt)
WinBits const WB_SYSTEMWINDOW
bool HasEntryImage(sal_Int32 nPos) const
virtual void StateChanged(StateChangedType nType) override
const ImplEntryList * GetEntryList() const
Definition: listbox.hxx:410
void SetNoSelection()
void DrawImage(const Point &rPos, const Image &rImage, DrawImageFlags nStyle=DrawImageFlags::NONE)
This is an overloaded member function, provided for convenience. It differs from the above function o...
std::vector< tools::Rectangle > MetricVector
Definition: outdev.hxx:138
OUString maString
Definition: listbox.hxx:539
static OUString filterFormattingChars(const OUString &)
Definition: i18nhelp.cxx:93
virtual void FillLayoutData() const override
void setWidth(tools::Long nWidth)
virtual void setPosSizePixel(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, PosSizeFlags nFlags=PosSizeFlags::All) override
sal_Int32 GetSelectedEntryPos(sal_Int32 nIndex) const
void SetUserItemSize(const Size &rSz)
const CommandEvent * GetCommandEvent() const
Definition: event.hxx:324
const Color & GetHighlightTextColor() const
BitmapEx createBlendFrame(const Size &rSize, sal_uInt8 nAlpha, Color aColorTopLeft, Color aColorBottomRight)
Create a blend frame as BitmapEx.
Definition: BitmapEx.cxx:1131
std::unique_ptr< ContentProperties > pData
void SetEntryFlags(sal_Int32 nPos, ListBoxEntryFlags nFlags)
virtual ~ImplListBoxWindow() override
tools::Long getWidth() const
A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for refer...
Definition: button.hxx:35
void ScrollHorz(tools::Long nDiff)
Image maImage
Definition: listbox.hxx:54
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool mbVScroll
Definition: listbox.hxx:384
ImplEntryList * GetEntryList() const
Definition: listbox.hxx:265
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
SAL_DLLPRIVATE void ImplClearLayoutData() const
Definition: ctrl.cxx:330
tools::Rectangle maFocusRect
Definition: listbox.hxx:178
sal_uIntPtr sal_uLong
long Long
void disposeAndClear()
Definition: vclptr.hxx:200
tools::Long mnHeight
Definition: listbox.hxx:58
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:733
constexpr sal_uInt16 KEY_A
Definition: keycodes.hxx:56
tools::Long mnMaxImgWidth
Maximum width of an image item.
Definition: listbox.hxx:187
bool mbSelectionChanged
Do not call Select() too often ...
Definition: listbox.hxx:212
void ImplResizeControls()
bool mbEdgeBlending
Definition: listbox.hxx:387
virtual void StateChanged(StateChangedType nStateChange) override
Definition: ctrl.cxx:260
ImplSVNWFData maNWFData
Definition: svdata.hxx:397
sal_Int64 n
SAL_DLLPRIVATE vcl::Window * ImplGetBorderWindow() const
Definition: window2.cxx:874
Link< ImplListBoxWindow *, void > maScrollHdl
Definition: listbox.hxx:224
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
void EnableMouseMoveSelect(bool bMouseMoveSelect)
Definition: listbox.hxx:334
sal_Int32 GetTopEntry() const
Definition: listbox.hxx:449
virtual Size GetSizePixel() const
Definition: window.cxx:2394
virtual void SetSizePixel(const Size &rNewSize)
Definition: window2.cxx:1261
WinBits const WB_RIGHT
constexpr tools::Long gnBorder
Definition: imp_listbox.cxx:50
#define IMG_TXT_DISTANCE
Definition: listbox.hxx:40
SAL_DLLPRIVATE WindowImpl * ImplGetWindowImpl() const
Definition: window.hxx:537
sal_Int32 GetEntryPosForPoint(const Point &rPoint) const
void CompatStateChanged(StateChangedType nStateChange)
Definition: window.cxx:3888
bool IsShift() const
Definition: event.hxx:158
bool MatchString(const OUString &rStr1, const OUString &rStr2) const
Definition: i18nhelp.cxx:124
void SetMRUCount(sal_Int32 n)
Definition: listbox.hxx:156
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
void SetTextFillColor()
Definition: text.cxx:697
const Color & GetFieldRolloverTextColor() const
sal_uInt16 GetCode() const
Definition: keycod.hxx:51
void SelectEntry(sal_Int32 nPos, bool bSelect)
Definition: imp_listbox.cxx:84
tools::Long GetWidth() const
sal_Int32 FindEntry(std::u16string_view rStr, bool bSearchMRUArea=false) const
sal_Int32 GetSelectedEntryCount() const
PosSizeFlags
Definition: window.hxx:125
DataChangedEventType GetType() const
Definition: event.hxx:354
The invalidated area is updated immediately.
tools::Rectangle GetDesktopRectPixel() const
Definition: window.cxx:2788
sal_Int32 mnMRUCount
Definition: listbox.hxx:93
bool mbMouseMoveSelect
Select at MouseMove.
Definition: listbox.hxx:213
WinBits const WB_VSCROLL
sal_Int32 mnTop
output from line on
Definition: listbox.hxx:199
constexpr::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
sal_uInt16 GetDisplayLineCount() const
const Color & GetControlBackground() const
Definition: window2.cxx:1081
const CommandWheelData * GetWheelData() const
constexpr sal_uInt16 KEY_SPACE
Definition: keycodes.hxx:123
void SetRangeMax(tools::Long nNewRange)
Definition: scrbar.cxx:1333
void SetSeparatorPos(sal_Int32 n)
Removes existing separators, and sets the position of the one and only separator. ...
void SetType(WindowType nType)
Definition: window2.cxx:967
bool mbCenter
center Text output
Definition: listbox.hxx:218
void PaintImmediately()
Definition: paint.cxx:1264
bool HandleScrollCommand(const CommandEvent &rCmd, ScrollBar *pHScrl, ScrollBar *pVScrl)
Definition: window2.cxx:608
void SetEntryFlags(sal_Int32 nPos, ListBoxEntryFlags nFlags)
virtual void Tracking(const TrackingEvent &rTEvt) override
static Point ImplCalcPos(vcl::Window *pWindow, const tools::Rectangle &rRect, FloatWinPopupFlags nFlags, sal_uInt16 &rArrangeIndex, Point *pLOKTwipsPos=nullptr)
Definition: floatwin.cxx:231
void StartTracking(StartTrackingFlags nFlags=StartTrackingFlags::NONE)
Definition: window2.cxx:243
bool HasChildPathFocus(bool bSystemWindow=false) const
Definition: window.cxx:2996
bool IsNativeControlSupported(ControlType nType, ControlPart nPart) const
Query the platform layer for control support.
const vcl::Font & GetFieldFont() const
tools::Long GetLeftIndent() const
Definition: listbox.hxx:454
const Color & GetFieldTextColor() const
int mnListBoxEntryMargin
Definition: svdata.hxx:340
void ImplUpdateEntryMetrics(ImplEntryType &rEntry)
constexpr sal_uInt16 KEY_UP
Definition: keycodes.hxx:111
#define LISTBOX_ENTRY_NOTFOUND
Definition: lstbox.hxx:37
const Color & GetHighlightColor() const
VclPtr< ImplListBoxWindow > maLBWindow
Definition: listbox.hxx:379
bool mbReadOnly
ReadOnly.
Definition: listbox.hxx:217
ImplEntryList(vcl::Window *pWindow)
Definition: imp_listbox.cxx:61
The invalidated area is painted with the background color/pattern.
void ImplInitScrollBars()
Link< void *, void > maMBDownHdl
Definition: listbox.hxx:586
sal_Int32 GetTopEntry() const
Definition: listbox.hxx:286
constexpr sal_uInt16 KEY_END
Definition: keycodes.hxx:115
void RemoveEntry(sal_Int32 nPos)
const Fraction & GetZoom() const
Definition: window2.cxx:1209
void * GetEntryData(sal_Int32 nPos) const
StateChangedType
Definition: window.hxx:289
constexpr tools::Long Width() const
tools::Long mnMaxWidth
Maximum width of an entry.
Definition: listbox.hxx:189
tools::Rectangle GetTextRect(const tools::Rectangle &rRect, const OUString &rStr, DrawTextFlags nStyle=DrawTextFlags::WordBreak, TextRectInfo *pInfo=nullptr, const vcl::ITextLayout *_pTextLayout=nullptr) const
Definition: text.cxx:1799
virtual void ApplySettings(vcl::RenderContext &rRenderContext) override
tools::Long mnTextHeight
text height
Definition: listbox.hxx:201
tools::Long GetMaxEntryWidth() const
Definition: listbox.hxx:472
sal_uInt16 GetEdgeBlending() const
sal_uInt16 GetClicks() const
Definition: event.hxx:126
VclPtr< vcl::Window > mpWindow
For getting the current locale when matching strings.
Definition: listbox.hxx:88
sal_Int64 WinBits
IMPL_LINK_NOARG(ImplListBox, MRUChanged, LinkParamNone *, void)
sal_uInt16 sal_Unicode
bool IsTravelSelect() const
Definition: listbox.hxx:321
std::set< sal_Int32 > maSeparators
Separator positions.
Definition: listbox.hxx:195
virtual bool PreNotify(NotifyEvent &rNEvt) override
void RemoveEntry(sal_Int32 nPos)
void SetBackground()
void SetControlFont()
Definition: window2.cxx:408
tools::Long mnMaxImgTxtWidth
Maximum width of a text item.
Definition: listbox.hxx:185
void Enable(bool bEnable=true, bool bChild=true)
Definition: window.cxx:2425
void SetPageSize(tools::Long nNewSize)
Definition: scrbar.hxx:125
SAL_DLLPRIVATE void ReMirror(Point &rPoint) const
Definition: outdev.cxx:607
this flags lets the item be drawn disabled (e.g.
VclPtr< ImplListBox > mpImplLB
Definition: listbox.hxx:500
void SetSymbol(SymbolType eSymbol)
Definition: button.cxx:1525
virtual void StateChanged(StateChangedType nType) override
LB_EVENT_TYPE
Definition: listbox.hxx:42
virtual ~ImplListBoxFloatingWindow() override
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
bool IsControlForeground() const
Definition: window2.cxx:1076
bool IsEnterWindow() const
Definition: event.hxx:138
bool mbHScroll
Definition: listbox.hxx:385
WinBits const WB_HSCROLL
int nCount
void SetMRUChangedHdl(const Link< LinkParamNone *, void > &rLink)
Definition: listbox.hxx:349
void Hide()
Definition: window.hxx:920
AllSettingsFlags GetFlags() const
Definition: event.hxx:355
constexpr sal_uInt16 KEY_PAGEUP
Definition: keycodes.hxx:116
tools::Long Bottom() const
virtual const Wallpaper & GetDisplayBackground() const override
bool mbIsDropdown
Listbox is actually a dropdown (either combobox, or popup window treated as dropdown) ...
Definition: listbox.hxx:222
tools::Long mnMaxTxtWidth
Maximum width of a text item.
Definition: listbox.hxx:183
tools::Long getHeightWithMargin() const
virtual void Resize() override
sal_uInt16 GetModifier() const
Definition: keycod.hxx:54
const void * StringEntryIdentifier
Link< LinkParamNone *, void > maListItemSelectHdl
Definition: listbox.hxx:231
bool IsValid() const
ImplWin(vcl::Window *pParent, WinBits nWinStyle)
sal_Int32 mnMaxMRUCount
Definition: listbox.hxx:94
bool mbSimpleMode
SimpleMode for MultiListBox.
Definition: listbox.hxx:209
void DrawLine(const Point &rStartPt, const Point &rEndPt)
Definition: line.cxx:89
void SetThumbPos(tools::Long nThumbPos)
Definition: scrbar.cxx:1362
const Color & GetEdgeBlendingBottomRightColor() const
Image GetEntryImage(sal_Int32 nPos) const
void SetLineSize(tools::Long nNewSize)
Definition: scrbar.hxx:123
ImplListBoxWindow * GetMainWindow()
Definition: listbox.hxx:411
void DrawRect(const tools::Rectangle &rRect)
Definition: rect.cxx:51
sal_Int32 mnTrackingSaveSelection
Selection before Tracking();.
Definition: listbox.hxx:193
void SetEntryFlags(sal_Int32 nPos, ListBoxEntryFlags nFlags)
const Color & GetControlForeground() const
Definition: window2.cxx:1071
this flag disables a selection of an entry completely.
void SetTopEntry(sal_Int32 nTop)
Definition: listbox.hxx:448
constexpr sal_uInt16 KEY_DOWN
Definition: keycodes.hxx:110
void RemoveEntry(sal_Int32 nPos)
void SetScrollHdl(const Link< ImplListBoxWindow *, void > &rLink)
Definition: listbox.hxx:344
Link< void *, void > maMBDownHdl
Definition: listbox.hxx:544
ImplListBoxFloatingWindow(vcl::Window *pParent)
sal_Int32 GetSeparatorPos() const
Gets the position of the separator which was added first.
sal_Int32 GetMRUCount() const
Definition: listbox.hxx:157
bool IsEmpty() const
Definition: BitmapEx.cxx:196
void ShowProminentEntry(sal_Int32 nPos)
Definition: listbox.hxx:450
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:74
bool ProcessKeyInput(const KeyEvent &rKEvt)
this flag can be used to make an entry multiline capable A normal entry is single line and will there...
void SetLineColor()
virtual void KeyInput(const KeyEvent &rKEvt) override
void clear()
Definition: vclptr.hxx:190
const Color & GetDisableColor() const
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: syswin.cxx:202
std::vector< std::unique_ptr< ImplEntryType > > maEntries
Definition: listbox.hxx:98
sal_Int32 FindFirstSelectable(sal_Int32 nPos, bool bForward=true)
bool IsRTLEnabled() const
Definition: outdev.hxx:1366
virtual bool PreNotify(NotifyEvent &rNEvt)
Definition: event.cxx:52
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
bool IsLeaveWindow() const
Definition: event.hxx:140
int i
virtual void Resize() override
bool IsEntryPosSelected(sal_Int32 nIndex) const
bool IsNativeWidgetEnabled() const
Definition: window.cxx:3681
ImplBtn(vcl::Window *pParent, WinBits nWinStyle)
virtual void Resize() override
constexpr sal_uInt16 KEY_HOME
Definition: keycodes.hxx:114
virtual ~ImplListBox() override
void SetControlBackground()
Definition: window2.cxx:496
virtual bool PreNotify(NotifyEvent &rNEvt) override
WinBits const WB_SIMPLEMODE
IMPL_LINK(ImplListBox, ScrollBarHdl, ScrollBar *, pSB, void)
bool mbMulti
MultiListBox.
Definition: listbox.hxx:208
void SetVisibleSize(tools::Long nNewSize)
Definition: scrbar.cxx:1376
tools::Long mnLeft
output from column on
Definition: listbox.hxx:200
void ImplCheckScrollBars()
Link< ImplListBoxWindow *, void > maDoubleClickHdl
Definition: listbox.hxx:227
void SetSize(const Size &rSize)
void SetControlForeground()
Definition: window2.cxx:456
CommandWheelMode GetMode() const
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
Definition: paint.cxx:1140
SAL_DLLPRIVATE bool ImplIsAntiparallel() const
Definition: outdev.cxx:591
void SetUpdateMode(bool bUpdate)
Definition: window.cxx:2959
Size GetOutputSize() const
Definition: outdev.hxx:454
sal_Int32 mnSelectionAnchor
Definition: listbox.hxx:90
ImplListBox(vcl::Window *pParent, WinBits nWinStyle)
bool IsUpdateMode() const
Definition: window2.cxx:1172
void SetFillColor()
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_GRAY
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:303
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
const Color & GetFieldColor() const
tools::Long GetEntryHeightWithMargin() const
CommandEventId GetCommand() const
const Color & GetLineColor() const
Definition: outdev.hxx:634
VclPtr< ScrollBarBox > mpScrollBarBox
Definition: listbox.hxx:382
void SetZoom(const Fraction &rZoom)
Definition: window2.cxx:364
sal_uInt16 GetModifier() const
Size CalcSize(sal_Int32 nMaxLines) const
void SetTextColor(const Color &rColor)
Definition: text.cxx:662
constexpr sal_uInt16 KEY_PAGEDOWN
Definition: keycodes.hxx:117
DrawTextFlags ImplGetTextStyle() const
bool IsZoom() const
Definition: window2.cxx:1214
void SetEdgeBlending(bool bNew)
Definition: listbox.hxx:364
void ImplDoPaint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect)
MouseNotifyEvent GetType() const
Definition: event.hxx:300
void SetLeftIndent(tools::Long n)
bool IsInside(const Point &rPOINT) const
bool DrawNativeControl(ControlType nType, ControlPart nPart, const tools::Rectangle &rControlRegion, ControlState nState, const ImplControlValue &aValue, const OUString &aCaption, const Color &rBackgroundColor=COL_AUTO)
Request rendering of a particular control and/or part.
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: ctrl.cxx:59
WinBits const WB_DROPDOWN
const AllSettings & GetSettings() const
Definition: outdev.hxx:418
Size GetOutputSizePixel() const
Definition: outdev.hxx:441
vcl::QuickSelectionEngine maQuickSelectionEngine
Definition: listbox.hxx:233
DrawTextFlags
Definition: outdev.hxx:143
bool GetEdgeBlending() const
Definition: listbox.hxx:573
tools::Long GetScrollBarSize() const
VclPtr< ScrollBar > mpHScrollBar
Definition: listbox.hxx:380
bool HandleWheelAsCursorTravel(const CommandEvent &rCEvt, Control &rControl)
void ApplyControlForeground(vcl::RenderContext &rRenderContext, const Color &rDefaultColor)
Definition: window2.cxx:488
Link< LinkParamNone *, void > maCancelHdl
Definition: listbox.hxx:226
std::unique_ptr< ImplEntryList > mpEntryList
EntryList.
Definition: listbox.hxx:177
WinBits const WB_SORT
sal_uInt16 GetModifier() const
Definition: event.hxx:156
bool mbSort
ListBox sorted.
Definition: listbox.hxx:206
tools::Long Top() const
virtual void LoseFocus()
Definition: window.cxx:1848
bool GetEdgeBlending() const
Definition: listbox.hxx:363
void DrawEntry(vcl::RenderContext &rRenderContext, sal_Int32 nPos, bool bDrawImage, bool bDrawText)
OUString maStr
Definition: listbox.hxx:52
void GrabFocus()
Definition: window.cxx:2968
Link< UserDrawEvent *, void > maUserDrawHdl
Definition: listbox.hxx:228
virtual void ShowFocus(const tools::Rectangle &rRect)
Definition: window2.cxx:49
bool mbTravelSelect
TravelSelect.
Definition: listbox.hxx:210
vcl::Window * GetParent() const
Definition: window2.cxx:1096
ListBoxEntryFlags mnFlags
Definition: listbox.hxx:57
sal_Int32 FindMatchingEntry(const OUString &rStr, sal_Int32 nStart, bool bLazy) const
void SetLeftIndent(sal_uInt16 n)
Definition: listbox.hxx:455
void ImplPaint(vcl::RenderContext &rRenderContext, sal_Int32 nPos)
bool IsTrackingEnded() const
Definition: event.hxx:261
std::unique_ptr< SalLayout > ImplLayout(const OUString &, sal_Int32 nIndex, sal_Int32 nLen, const Point &rLogicPos=Point(0, 0), tools::Long nLogicWidth=0, const tools::Long *pLogicDXArray=nullptr, SalLayoutFlags flags=SalLayoutFlags::NONE, vcl::TextLayoutCache const *=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
Definition: text.cxx:1242
Link< LinkParamNone *, void > maMRUChangedHdl
Definition: listbox.hxx:229
virtual void MouseMove(const MouseEvent &rMEvt) override
void DrawEntry(vcl::RenderContext &rRenderContext, bool bLayout)
Size CalcSize(sal_Int32 nMaxLines) const
Definition: listbox.hxx:469
constexpr sal_uInt16 KEY_RETURN
Definition: keycodes.hxx:119
WinBits const WB_NOBORDER
const Color & GetButtonRolloverTextColor() const
virtual void SetPosSizePixel(const Point &rNewPos, const Size &rNewSize)
Definition: window2.cxx:1267
vcl::Window * GetWindow(GetWindowType nType) const
Definition: stacking.cxx:1035
constexpr sal_uInt16 KEY_RIGHT
Definition: keycodes.hxx:113
#define MULTILINE_ENTRY_DRAW_FLAGS
Definition: imp_listbox.cxx:46
bool mbIsSelected
Definition: listbox.hxx:56
sal_Int32 mnCurrentPos
Position (Focus)
Definition: listbox.hxx:192
bool mbUserDrawEnabled
UserDraw possible.
Definition: listbox.hxx:215
Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1021
VclPtr< ScrollBar > mpVScrollBar
Definition: listbox.hxx:381
tools::Long const nBorder
bool IsMouseMoveSelect() const
Definition: listbox.hxx:335
virtual void setPosSizePixel(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, PosSizeFlags nFlags=PosSizeFlags::All)
Definition: window.cxx:2658
virtual void KeyInput(const KeyEvent &rKEvt)
Definition: window.cxx:1798
const LanguageTag & getLocale()
const vcl::I18nHelper & GetLocaleI18nHelper() const
bool mbUseNativeFocus
Definition: window.h:316
tools::Long mnMaxTxtHeight
Maximum height of a text item.
Definition: listbox.hxx:182
void GetBorder(sal_Int32 &rLeftBorder, sal_Int32 &rTopBorder, sal_Int32 &rRightBorder, sal_Int32 &rBottomBorder) const
Definition: window.cxx:2416
void * mpUserData
Definition: listbox.hxx:55
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:57
void Erase()
Definition: wallpaper.cxx:103
bool IsShift() const
Definition: keycod.hxx:56
tools::Long GetAddedHeight(sal_Int32 nEndIndex, sal_Int32 nBeginIndex) const
helper: add up heights up to index nEndIndex.
bool IsUserDrawEnabled() const
Definition: listbox.hxx:327
bool IsMouseOver() const
Definition: mouse.cxx:605
virtual void Resize() override
Definition: ctrl.cxx:74
ImplEntryType * GetEntry(sal_Int32 nPos) const
Definition: listbox.hxx:100
bool ProcessKeyInput(const KeyEvent &rKEvt)
Definition: listbox.hxx:429
virtual void Scroll(tools::Long nHorzScroll, tools::Long nVertScroll, ScrollFlags nFlags=ScrollFlags::NONE)
Definition: window.cxx:2936
const ImplEntryType * GetEntryPtr(sal_Int32 nPos) const
Definition: listbox.hxx:113
Definition: ctrl.hxx:33
bool IsEntrySelectable(sal_Int32 nPos) const
An Entry is selectable if its mnFlags does not have the ListBoxEntryFlags::DisableSelection flag set...
#define LISTBOX_MAX_ENTRIES
Definition: lstbox.hxx:38
ListBoxEntryFlags
Definition: lstbox.hxx:47
bool IsSynthetic() const
Definition: event.hxx:142
virtual void GetFocus()
Definition: window.cxx:1834
const Color & GetButtonTextColor() const
bool mbNoFocusRects
Definition: svdata.hxx:321
sal_Int32 mnItemPos
because of UserDraw I have to know which item I draw
Definition: listbox.hxx:538
#define SAL_WARN_IF(condition, area, stream)
constexpr tools::Long Height() const
WinBits const WB_BORDER
unsigned char sal_uInt8
bool bIsEnabled
const MouseEvent * GetMouseEvent() const
Definition: event.hxx:316
std::unique_ptr< vcl::ImplControlData > mpControlData
Definition: ctrl.hxx:36
virtual void GetFocus() override
sal_Int32 mnLastSelected
Definition: listbox.hxx:89
tools::Long GetEntryHeightWithMargin() const
Definition: listbox.hxx:471
bool IsVisible() const
Definition: window2.cxx:1101
virtual vcl::StringEntryIdentifier CurrentEntry(OUString &_out_entryText) const override
returns the current entry in the list of searchable strings.
tools::Long GetTextHeight() const
Height where any character of the current font fits; in logic coordinates.
Definition: text.cxx:891
sal_Int32 mnPopupModeStartSaveSelection
Definition: listbox.hxx:503
void SetSeparatorPos(sal_Int32 n)
Removes existing separators, and sets the position of the one and only separator. ...
Definition: listbox.hxx:436
bool SelectEntries(sal_Int32 nSelect, LB_EVENT_TYPE eLET, bool bShift=false, bool bCtrl=false, bool bSelectPosChange=false)
sal_uInt16 mnSelectModifier
Modifiers.
Definition: listbox.hxx:203
::OutputDevice const * GetOutDev() const
Definition: window.cxx:578
bool IsLeft() const
Definition: event.hxx:149
tools::Long AdjustWidth(tools::Long n)
void SetScrollHdl(const Link< ScrollBar *, void > &rLink)
Definition: scrbar.hxx:133
Definition: image.hxx:39
bool IsMod1() const
Definition: keycod.hxx:58
static VclPtr< reference_type > Create(Arg &&...arg)
A construction helper for VclPtr.
Definition: vclptr.hxx:127
tools::Long mnMaxImgHeight
Maximum height of an image item.
Definition: listbox.hxx:188
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
Reference< XComponentContext > getProcessComponentContext()
tools::Long CalcZoom(tools::Long n) const
Definition: window2.cxx:396
ImplListBoxWindow(vcl::Window *pParent, WinBits nWinStyle)
bool IsGrabFocusAllowed() const
Definition: listbox.hxx:298
const Point & GetPosPixel() const
Definition: event.hxx:123
sal_Int32 mnImages
Definition: listbox.hxx:91
WinBits const WB_AUTOHSCROLL
tools::Long AdjustHeight(tools::Long n)
virtual void GetFocus() override
tools::Long GetEntryHeight(sal_Int32 nPos) const
sal_Int32 InsertEntry(sal_Int32 nPos, ImplEntryType *pNewEntry)
void setHeight(tools::Long nHeight)
virtual bool EventNotify(NotifyEvent &rNEvt) override
tools::Long GetHeight() const
Event to pass information for UserDraw() handling eg. in comboboxes.
Definition: event.hxx:221
tools::Long GetDelta() const
WinBits const WB_CENTER
sal_Int32 InsertEntry(sal_Int32 nPos, const OUString &rStr)
bool isSeparator(const sal_Int32 &n) const
Checks if the given number n is an element of the separator positions set.
ScXMLEditAttributeMap::Entry const aEntries[]
bool IsEnabled() const
Definition: window2.cxx:1121
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
#define SAL_WARN(area, stream)
Image maImage
Definition: listbox.hxx:540
OUString GetSelectedEntry(sal_Int32 nIndex) const
void SetTopEntry(sal_Int32 nTop)
bool IsTrackingCanceled() const
Definition: event.hxx:263
OUString GetMRUEntries(sal_Unicode cSep) const
WinBits GetStyle() const
Definition: window2.cxx:952
void SelectEntry(sal_Int32 nPos, bool bSelect)
Link< sal_Int32, void > maSelectionChangedHdl
Definition: listbox.hxx:96
sal_Int32 mnUserDrawEntry
Definition: listbox.hxx:197
virtual void FillLayoutData() const override
bool IsReadOnly() const
Definition: listbox.hxx:359
void ApplyControlFont(vcl::RenderContext &rRenderContext, const vcl::Font &rDefaultFont)
Definition: window2.cxx:448
OUString GetEntryText(sal_Int32 nPos) const
constexpr sal_uInt16 KEY_LEFT
Definition: keycodes.hxx:112
Point OutputToScreenPixel(const Point &rPos) const
Definition: window.cxx:2795
void StartFloat(bool bStartTracking)
sal_Int32 GetLastVisibleEntry() const
void SetEntryData(sal_Int32 nPos, void *pNewData)
void ImplInitDropDownButton(PushButton *pButton)
Definition: imp_listbox.cxx:52
sal_Int32 compare(const OUString &rLHS, const OUString &rRHS) const
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
void SetAccessibleRole(sal_uInt16 nRole)
bool mbInUserDraw
In UserDraw.
Definition: listbox.hxx:216
const MouseEvent & GetMouseEvent() const
Definition: event.hxx:257
bool IsReallyVisible() const
Definition: window2.cxx:1106
vcl::Font GetControlFont() const
Definition: window2.cxx:437
bool mbGrabFocus
Grab focus at MBDown.
Definition: listbox.hxx:214
virtual vcl::StringEntryIdentifier NextEntry(vcl::StringEntryIdentifier _currentEntry, OUString &_out_entryText) const override
returns the next entry in the list.
SalLayoutGlyphs * GetTextGlyphs(const OutputDevice *pOutputDevice)
Computes maStr's text layout (glyphs), cached in maStrGlyphs.
bool HasFocus() const
Definition: window.cxx:2973
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: floatwin.cxx:204
const Color & GetEdgeBlendingTopLeftColor() const
void SetEdgeBlending(bool bNew)
WinBits const WB_WORDBREAK
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
bool SupportsDoubleBuffering() const
Can the widget derived from this Window do the double-buffering via RenderContext properly...
Definition: window.cxx:3850
tools::Long mnMaxHeight
Maximum height of an entry.
Definition: listbox.hxx:190
void ShowProminentEntry(sal_Int32 nEntryPos)
ShowProminentEntry will set the entry corresponding to nEntryPos either at top or in the middle depen...
void EndPopupMode(FloatWinPopupEndFlags nFlags=FloatWinPopupEndFlags::NONE)
Definition: floatwin.cxx:944
sal_Int32 InsertEntry(sal_Int32 nPos, ImplEntryType *pNewEntry, bool bSort)
sal_Int32 nState
DrawImageFlags
Definition: outdev.hxx:171
virtual void SetPosPixel(const Point &rNewPos)
Definition: window2.cxx:1256
aStr
virtual void Resize() override
Definition: syswin.cxx:1005
virtual void ApplySettings(vcl::RenderContext &rRenderContext) override
virtual void GetFocus() override
bool mbCallSelectionChangedHdl
Definition: listbox.hxx:97
sal_Int32 GetEntryCount() const
Definition: listbox.hxx:127
bool IsMod3() const
Definition: keycod.hxx:62
sal_uInt16 nPos
tools::Rectangle GetBoundingRectangle(sal_Int32 nItem) const
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
virtual void DataChanged(const DataChangedEvent &rDCEvt)
Definition: event.cxx:36
Link< LinkParamNone *, void > maSelectHdl
Definition: listbox.hxx:225
bool IsMod1() const
Definition: event.hxx:160
void ImplDraw(vcl::RenderContext &rRenderContext, bool bLayout=false)
WinBits const WB_DRAG
bool IsMod2() const
Definition: keycod.hxx:60
bool mbTrackingSelect
Selected at a MouseMove.
Definition: listbox.hxx:211
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
Definition: window.cxx:2180
bool mbRight
right align Text output
Definition: listbox.hxx:219
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo