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 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( const OUString& 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 long ImplEntryList::GetAddedHeight( sal_Int32 i_nEndIndex, sal_Int32 i_nBeginIndex ) const
280 {
281  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  long nPosHeight = GetEntryPtr( nIndex )->getHeightWithMargin();
299  if (nHeight > ::std::numeric_limits<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 
313 long ImplEntryList::GetEntryHeight( sal_Int32 nPos ) const
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  long nEntryWidth;
571  long nEntryHeight;
572  long nTextWidth;
573  long nImgWidth;
574  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  const SalLayoutGlyphs* pGlyphs = pLayout->GetGlyphs();
596  if (!pGlyphs)
597  return nullptr;
598 
599  // Remember the calculation result.
600  maStrGlyphs = *pGlyphs;
601 
602  return &maStrGlyphs;
603 }
604 
606 {
607  ImplEntryMetrics aMetrics;
608  aMetrics.bText = !rEntry.maStr.isEmpty();
609  aMetrics.bImage = !!rEntry.maImage;
610  aMetrics.nEntryWidth = 0;
611  aMetrics.nEntryHeight = 0;
612  aMetrics.nTextWidth = 0;
613  aMetrics.nImgWidth = 0;
614  aMetrics.nImgHeight = 0;
615 
616  if ( aMetrics.bText )
617  {
619  {
620  // multiline case
621  Size aCurSize( PixelToLogic( GetSizePixel() ) );
622  // set the current size to a large number
623  // GetTextRect should shrink it to the actual size
624  aCurSize.setHeight( 0x7fffff );
625  tools::Rectangle aTextRect( Point( 0, 0 ), aCurSize );
626  aTextRect = GetTextRect( aTextRect, rEntry.maStr, DrawTextFlags::WordBreak | DrawTextFlags::MultiLine );
627  aMetrics.nTextWidth = aTextRect.GetWidth();
628  if( aMetrics.nTextWidth > mnMaxTxtWidth )
629  mnMaxTxtWidth = aMetrics.nTextWidth;
630  aMetrics.nEntryWidth = mnMaxTxtWidth;
631  aMetrics.nEntryHeight = aTextRect.GetHeight() + gnBorder;
632  }
633  else
634  {
635  // normal single line case
636  const SalLayoutGlyphs* pGlyphs = rEntry.GetTextGlyphs(this);
637  aMetrics.nTextWidth
638  = static_cast<sal_uInt16>(GetTextWidth(rEntry.maStr, 0, -1, nullptr, pGlyphs));
639  if( aMetrics.nTextWidth > mnMaxTxtWidth )
640  mnMaxTxtWidth = aMetrics.nTextWidth;
641  aMetrics.nEntryWidth = mnMaxTxtWidth;
642  aMetrics.nEntryHeight = mnTextHeight + gnBorder;
643  }
644  }
645  if ( aMetrics.bImage )
646  {
647  Size aImgSz = rEntry.maImage.GetSizePixel();
648  aMetrics.nImgWidth = static_cast<sal_uInt16>(CalcZoom( aImgSz.Width() ));
649  aMetrics.nImgHeight = static_cast<sal_uInt16>(CalcZoom( aImgSz.Height() ));
650 
651  if( aMetrics.nImgWidth > mnMaxImgWidth )
652  mnMaxImgWidth = aMetrics.nImgWidth;
653  if( aMetrics.nImgHeight > mnMaxImgHeight )
654  mnMaxImgHeight = aMetrics.nImgHeight;
655 
656  mnMaxImgTxtWidth = std::max( mnMaxImgTxtWidth, aMetrics.nTextWidth );
657  aMetrics.nEntryHeight = std::max( aMetrics.nImgHeight, aMetrics.nEntryHeight );
658 
659  }
660 
661  bool bIsUserDrawEnabled = IsUserDrawEnabled();
662  if (bIsUserDrawEnabled || aMetrics.bImage)
663  {
664  aMetrics.nEntryWidth = std::max( aMetrics.nImgWidth, maUserItemSize.Width() );
665  if (!bIsUserDrawEnabled && aMetrics.bText)
666  aMetrics.nEntryWidth += aMetrics.nTextWidth + IMG_TXT_DISTANCE;
667  aMetrics.nEntryHeight = std::max( std::max( mnMaxImgHeight, maUserItemSize.Height() ) + 2,
668  aMetrics.nEntryHeight );
669  }
670 
671  if (!aMetrics.bText && !aMetrics.bImage && !bIsUserDrawEnabled)
672  {
673  // entries which have no (aka an empty) text, and no image,
674  // and are not user-drawn, should be shown nonetheless
675  aMetrics.nEntryHeight = mnTextHeight + gnBorder;
676  }
677 
678  if ( aMetrics.nEntryWidth > mnMaxWidth )
679  mnMaxWidth = aMetrics.nEntryWidth;
680  if ( aMetrics.nEntryHeight > mnMaxHeight )
681  mnMaxHeight = aMetrics.nEntryHeight;
682 
683  rEntry.mnHeight = aMetrics.nEntryHeight;
684 }
685 
687 {
688  if ( !IsTravelSelect() && GetEntryList()->GetMaxMRUCount() )
689  {
690  // Insert the selected entry as MRU, if not already first MRU
691  sal_Int32 nSelected = GetEntryList()->GetSelectedEntryPos( 0 );
692  sal_Int32 nMRUCount = GetEntryList()->GetMRUCount();
693  OUString aSelected = GetEntryList()->GetEntryText( nSelected );
694  sal_Int32 nFirstMatchingEntryPos = GetEntryList()->FindEntry( aSelected, true );
695  if ( nFirstMatchingEntryPos || !nMRUCount )
696  {
697  bool bSelectNewEntry = false;
698  if ( nFirstMatchingEntryPos < nMRUCount )
699  {
700  RemoveEntry( nFirstMatchingEntryPos );
701  nMRUCount--;
702  if ( nFirstMatchingEntryPos == nSelected )
703  bSelectNewEntry = true;
704  }
705  else if ( nMRUCount == GetEntryList()->GetMaxMRUCount() )
706  {
707  RemoveEntry( nMRUCount - 1 );
708  nMRUCount--;
709  }
710 
712 
713  ImplEntryType* pNewEntry = new ImplEntryType( aSelected );
714  pNewEntry->mbIsSelected = bSelectNewEntry;
715  GetEntryList()->InsertEntry( 0, pNewEntry, false );
716  ImplUpdateEntryMetrics( *pNewEntry );
717  GetEntryList()->SetMRUCount( ++nMRUCount );
718  SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 );
719  maMRUChangedHdl.Call( nullptr );
720  }
721  }
722 
723  maSelectHdl.Call( nullptr );
724  mbSelectionChanged = false;
725 }
726 
727 sal_Int32 ImplListBoxWindow::InsertEntry(sal_Int32 nPos, ImplEntryType* pNewEntry, bool bSort)
728 {
729  assert(nPos >= 0);
730  assert(mpEntryList->GetEntryCount() < LISTBOX_MAX_ENTRIES);
731 
733  sal_Int32 nNewPos = mpEntryList->InsertEntry( nPos, pNewEntry, bSort );
734 
735  if( GetStyle() & WB_WORDBREAK )
737 
738  ImplUpdateEntryMetrics( *pNewEntry );
739  return nNewPos;
740 }
741 
742 sal_Int32 ImplListBoxWindow::InsertEntry( sal_Int32 nPos, ImplEntryType* pNewEntry )
743 {
744  return InsertEntry(nPos, pNewEntry, mbSort);
745 }
746 
747 void ImplListBoxWindow::RemoveEntry( sal_Int32 nPos )
748 {
750  mpEntryList->RemoveEntry( nPos );
751  if( mnCurrentPos >= mpEntryList->GetEntryCount() )
753  ImplCalcMetrics();
754 }
755 
757 {
758  mpEntryList->SetEntryFlags( nPos, nFlags );
759  ImplEntryType* pEntry = mpEntryList->GetMutableEntryPtr( nPos );
760  if( pEntry )
761  ImplUpdateEntryMetrics( *pEntry );
762 }
763 
765 {
766  if ( mbHasFocusRect )
767  HideFocus();
769  mbHasFocusRect = true;
770 }
771 
773 {
774  if ( mbHasFocusRect )
775  {
776  HideFocus();
777  mbHasFocusRect = false;
778  }
779 }
780 
781 sal_Int32 ImplListBoxWindow::GetEntryPosForPoint( const Point& rPoint ) const
782 {
783  long nY = gnBorder;
784 
785  sal_Int32 nSelect = mnTop;
786  const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nSelect );
787  while (pEntry)
788  {
789  long nEntryHeight = pEntry->getHeightWithMargin();
790  if (rPoint.Y() <= nEntryHeight + nY)
791  break;
792  nY += nEntryHeight;
793  pEntry = mpEntryList->GetEntryPtr( ++nSelect );
794  }
795  if( pEntry == nullptr )
796  nSelect = LISTBOX_ENTRY_NOTFOUND;
797 
798  return nSelect;
799 }
800 
801 bool ImplListBoxWindow::IsVisible( sal_Int32 i_nEntry ) const
802 {
803  bool bRet = false;
804 
805  if( i_nEntry >= mnTop )
806  {
807  if( mpEntryList->GetAddedHeight( i_nEntry, mnTop ) <
808  PixelToLogic( GetSizePixel() ).Height() )
809  {
810  bRet = true;
811  }
812  }
813 
814  return bRet;
815 }
816 
818 {
819  long nMargin = ImplGetSVData()->maNWFData.mnListBoxEntryMargin;
820  return mnMaxHeight + nMargin;
821 }
822 
824 {
825  sal_Int32 nPos = mnTop;
826  long nWindowHeight = GetSizePixel().Height();
827  sal_Int32 nCount = mpEntryList->GetEntryCount();
828  long nDiff;
829  for( nDiff = 0; nDiff < nWindowHeight && nPos < nCount; nDiff = mpEntryList->GetAddedHeight( nPos, mnTop ) )
830  nPos++;
831 
832  if( nDiff > nWindowHeight && nPos > mnTop )
833  nPos--;
834 
835  if( nPos >= nCount )
836  nPos = nCount-1;
837 
838  return nPos;
839 }
840 
842 {
843  mbMouseMoveSelect = false; // only till the first MouseButtonDown
845 
846  if ( !IsReadOnly() )
847  {
848  if( rMEvt.GetClicks() == 1 )
849  {
850  sal_Int32 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() );
851  if( nSelect != LISTBOX_ENTRY_NOTFOUND )
852  {
855  else
857 
858  mnCurrentPos = nSelect;
859  mbTrackingSelect = true;
860  bool bCurPosChange = (mnCurrentPos != nSelect);
861  (void)SelectEntries( nSelect, LET_MBDOWN, rMEvt.IsShift(), rMEvt.IsMod1() ,bCurPosChange);
862  mbTrackingSelect = false;
863  if ( mbGrabFocus )
864  GrabFocus();
865 
867  }
868  }
869  if( rMEvt.GetClicks() == 2 )
870  {
871  maDoubleClickHdl.Call( this );
872  }
873  }
874  else // if ( mbGrabFocus )
875  {
876  GrabFocus();
877  }
878 }
879 
881 {
882  if (rMEvt.IsLeaveWindow() || mbMulti || !IsMouseMoveSelect() || !mpEntryList->GetEntryCount())
883  return;
884 
886  if( !aRect.IsInside( rMEvt.GetPosPixel() ) )
887  return;
888 
889  if ( IsMouseMoveSelect() )
890  {
891  sal_Int32 nSelect = GetEntryPosForPoint( rMEvt.GetPosPixel() );
892  if( nSelect == LISTBOX_ENTRY_NOTFOUND )
893  nSelect = mpEntryList->GetEntryCount() - 1;
894  nSelect = std::min( nSelect, GetLastVisibleEntry() );
895  nSelect = std::min( nSelect, static_cast<sal_Int32>( mpEntryList->GetEntryCount() - 1 ) );
896  // Select only visible Entries with MouseMove, otherwise Tracking...
897  if ( IsVisible( nSelect ) &&
898  mpEntryList->IsEntrySelectable( nSelect ) &&
899  ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectedEntryCount() || ( nSelect != GetEntryList()->GetSelectedEntryPos( 0 ) ) ) )
900  {
901  mbTrackingSelect = true;
902  if ( SelectEntries( nSelect, LET_TRACKING ) )
903  {
904  // When list box selection change by mouse move, notify
905  // VclEventId::ListboxSelect vcl event.
906  maListItemSelectHdl.Call(nullptr);
907  }
908  mbTrackingSelect = false;
909  }
910  }
911 
912  // if the DD button was pressed and someone moved into the ListBox
913  // with the mouse button pressed...
914  if ( rMEvt.IsLeft() && !rMEvt.IsSynthetic() )
915  {
918  else
920 
922  }
923 }
924 
926 {
927  while ( GetEntryList()->GetSelectedEntryCount() )
928  {
929  sal_Int32 nS = GetEntryList()->GetSelectedEntryPos( 0 );
930  SelectEntry( nS, false );
931  }
932 }
933 
934 void ImplListBoxWindow::SelectEntry( sal_Int32 nPos, bool bSelect )
935 {
936  if( (mpEntryList->IsEntryPosSelected( nPos ) == bSelect) || !mpEntryList->IsEntrySelectable( nPos ) )
937  return;
938 
940  if( bSelect )
941  {
942  if( !mbMulti )
943  {
944  // deselect the selected entry
945  sal_Int32 nDeselect = GetEntryList()->GetSelectedEntryPos( 0 );
946  if( nDeselect != LISTBOX_ENTRY_NOTFOUND )
947  {
948  //SelectEntryPos( nDeselect, false );
949  GetEntryList()->SelectEntry( nDeselect, false );
950  if (IsUpdateMode() && IsReallyVisible())
951  Invalidate();
952  }
953  }
954  mpEntryList->SelectEntry( nPos, true );
955  mnCurrentPos = nPos;
956  if ( ( nPos != LISTBOX_ENTRY_NOTFOUND ) && IsUpdateMode() )
957  {
958  Invalidate();
959  if ( !IsVisible( nPos ) )
960  {
962  sal_Int32 nVisibleEntries = GetLastVisibleEntry()-mnTop;
963  if ( !nVisibleEntries || !IsReallyVisible() || ( nPos < GetTopEntry() ) )
964  {
965  Resize();
966  ShowProminentEntry( nPos );
967  }
968  else
969  {
970  ShowProminentEntry( nPos );
971  }
972  }
973  }
974  }
975  else
976  {
977  mpEntryList->SelectEntry( nPos, false );
978  Invalidate();
979  }
980  mbSelectionChanged = true;
981 }
982 
983 bool ImplListBoxWindow::SelectEntries( sal_Int32 nSelect, LB_EVENT_TYPE eLET, bool bShift, bool bCtrl, bool bSelectPosChange /*=FALSE*/ )
984 {
985  bool bSelectionChanged = false;
986 
987  if( IsEnabled() && mpEntryList->IsEntrySelectable( nSelect ) )
988  {
989  bool bFocusChanged = false;
990 
991  // here (Single-ListBox) only one entry can be deselected
992  if( !mbMulti )
993  {
994  sal_Int32 nDeselect = mpEntryList->GetSelectedEntryPos( 0 );
995  if( nSelect != nDeselect )
996  {
997  SelectEntry( nSelect, true );
998  mpEntryList->SetLastSelected( nSelect );
999  bFocusChanged = true;
1000  bSelectionChanged = true;
1001  }
1002  }
1003  // MultiListBox without Modifier
1004  else if( mbSimpleMode && !bCtrl && !bShift )
1005  {
1006  sal_Int32 nEntryCount = mpEntryList->GetEntryCount();
1007  for ( sal_Int32 nPos = 0; nPos < nEntryCount; nPos++ )
1008  {
1009  bool bSelect = nPos == nSelect;
1010  if ( mpEntryList->IsEntryPosSelected( nPos ) != bSelect )
1011  {
1012  SelectEntry( nPos, bSelect );
1013  bFocusChanged = true;
1014  bSelectionChanged = true;
1015  }
1016  }
1017  mpEntryList->SetLastSelected( nSelect );
1018  mpEntryList->SetSelectionAnchor( nSelect );
1019  }
1020  // MultiListBox only with CTRL/SHIFT or not in SimpleMode
1021  else if( ( !mbSimpleMode /* && !bShift */ ) || ( mbSimpleMode && ( bCtrl || bShift ) ) )
1022  {
1023  // Space for selection change
1024  if( !bShift && ( ( eLET == LET_KEYSPACE ) || ( eLET == LET_MBDOWN ) ) )
1025  {
1026  bool bSelect = !mpEntryList->IsEntryPosSelected( nSelect );
1027  SelectEntry( nSelect, bSelect );
1028  mpEntryList->SetLastSelected( nSelect );
1029  mpEntryList->SetSelectionAnchor( nSelect );
1030  if ( !mpEntryList->IsEntryPosSelected( nSelect ) )
1031  mpEntryList->SetSelectionAnchor( LISTBOX_ENTRY_NOTFOUND );
1032  bFocusChanged = true;
1033  bSelectionChanged = true;
1034  }
1035  else if( ( ( eLET == LET_TRACKING ) && ( nSelect != mnCurrentPos ) ) ||
1036  ( bShift && ( ( eLET == LET_KEYMOVE ) || ( eLET == LET_MBDOWN ) ) ) )
1037  {
1038  mnCurrentPos = nSelect;
1039  bFocusChanged = true;
1040 
1041  sal_Int32 nAnchor = mpEntryList->GetSelectionAnchor();
1042  if( ( nAnchor == LISTBOX_ENTRY_NOTFOUND ) && mpEntryList->GetSelectedEntryCount() )
1043  {
1044  nAnchor = mpEntryList->GetSelectedEntryPos( mpEntryList->GetSelectedEntryCount() - 1 );
1045  }
1046  if( nAnchor != LISTBOX_ENTRY_NOTFOUND )
1047  {
1048  // All entries from Anchor to nSelect have to be selected
1049  sal_Int32 nStart = std::min( nSelect, nAnchor );
1050  sal_Int32 nEnd = std::max( nSelect, nAnchor );
1051  for ( sal_Int32 n = nStart; n <= nEnd; n++ )
1052  {
1053  if ( !mpEntryList->IsEntryPosSelected( n ) )
1054  {
1055  SelectEntry( n, true );
1056  bSelectionChanged = true;
1057  }
1058  }
1059 
1060  // if appropriate some more has to be deselected...
1061  sal_Int32 nLast = mpEntryList->GetLastSelected();
1062  if ( nLast != LISTBOX_ENTRY_NOTFOUND )
1063  {
1064  if ( ( nLast > nSelect ) && ( nLast > nAnchor ) )
1065  {
1066  for ( sal_Int32 n = nSelect+1; n <= nLast; n++ )
1067  {
1068  if ( mpEntryList->IsEntryPosSelected( n ) )
1069  {
1070  SelectEntry( n, false );
1071  bSelectionChanged = true;
1072  }
1073  }
1074  }
1075  else if ( ( nLast < nSelect ) && ( nLast < nAnchor ) )
1076  {
1077  for ( sal_Int32 n = nLast; n < nSelect; n++ )
1078  {
1079  if ( mpEntryList->IsEntryPosSelected( n ) )
1080  {
1081  SelectEntry( n, false );
1082  bSelectionChanged = true;
1083  }
1084  }
1085  }
1086  }
1087  mpEntryList->SetLastSelected( nSelect );
1088  }
1089  }
1090  else if( eLET != LET_TRACKING )
1091  {
1093  Invalidate();
1094  bFocusChanged = true;
1095  }
1096  }
1097  else if( bShift )
1098  {
1099  bFocusChanged = true;
1100  }
1101 
1102  if( bSelectionChanged )
1103  mbSelectionChanged = true;
1104 
1105  if( bFocusChanged )
1106  {
1107  long nHeightDiff = mpEntryList->GetAddedHeight( nSelect, mnTop );
1108  maFocusRect.SetPos( Point( 0, nHeightDiff ) );
1109  Size aSz( maFocusRect.GetWidth(),
1110  mpEntryList->GetEntryHeight( nSelect ) );
1111  maFocusRect.SetSize( aSz );
1112  if( HasFocus() )
1114  if (bSelectPosChange)
1115  {
1116  maFocusHdl.Call(nSelect);
1117  }
1118  }
1120  }
1121  return bSelectionChanged;
1122 }
1123 
1125 {
1127  bool bInside = aRect.IsInside( rTEvt.GetMouseEvent().GetPosPixel() );
1128 
1129  if( rTEvt.IsTrackingCanceled() || rTEvt.IsTrackingEnded() ) // MouseButtonUp
1130  {
1131  if ( bInside && !rTEvt.IsTrackingCanceled() )
1132  {
1134  ImplCallSelect();
1135  }
1136  else
1137  {
1138  maCancelHdl.Call( nullptr );
1139  if ( !mbMulti )
1140  {
1141  mbTrackingSelect = true;
1143  mbTrackingSelect = false;
1145  {
1146  long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop );
1147  maFocusRect.SetPos( Point( 0, nHeightDiff ) );
1148  Size aSz( maFocusRect.GetWidth(),
1149  mpEntryList->GetEntryHeight( mnCurrentPos ) );
1150  maFocusRect.SetSize( aSz );
1152  }
1153  }
1154  }
1155 
1156  mbTrack = false;
1157  }
1158  else
1159  {
1160  bool bTrackOrQuickClick = mbTrack;
1161  if( !mbTrack )
1162  {
1163  if ( bInside )
1164  {
1165  mbTrack = true;
1166  }
1167 
1168  // this case only happens, if the mouse button is pressed very briefly
1169  if( rTEvt.IsTrackingEnded() && mbTrack )
1170  {
1171  bTrackOrQuickClick = true;
1172  mbTrack = false;
1173  }
1174  }
1175 
1176  if( bTrackOrQuickClick )
1177  {
1178  MouseEvent aMEvt = rTEvt.GetMouseEvent();
1179  Point aPt( aMEvt.GetPosPixel() );
1180  bool bShift = aMEvt.IsShift();
1181  bool bCtrl = aMEvt.IsMod1();
1182 
1183  sal_Int32 nSelect = LISTBOX_ENTRY_NOTFOUND;
1184  if( aPt.Y() < 0 )
1185  {
1187  {
1188  nSelect = mnCurrentPos ? ( mnCurrentPos - 1 ) : 0;
1189  if( nSelect < mnTop )
1190  SetTopEntry( mnTop-1 );
1191  }
1192  }
1193  else if( aPt.Y() > GetOutputSizePixel().Height() )
1194  {
1196  {
1197  nSelect = std::min( static_cast<sal_Int32>(mnCurrentPos+1), static_cast<sal_Int32>(mpEntryList->GetEntryCount()-1) );
1198  if( nSelect >= GetLastVisibleEntry() )
1199  SetTopEntry( mnTop+1 );
1200  }
1201  }
1202  else
1203  {
1204  nSelect = static_cast<sal_Int32>( ( aPt.Y() + gnBorder ) / mnMaxHeight ) + mnTop;
1205  nSelect = std::min( nSelect, GetLastVisibleEntry() );
1206  nSelect = std::min( nSelect, static_cast<sal_Int32>( mpEntryList->GetEntryCount() - 1 ) );
1207  }
1208 
1209  if ( bInside )
1210  {
1211  if ( ( nSelect != mnCurrentPos ) || !GetEntryList()->GetSelectedEntryCount() )
1212  {
1213  mbTrackingSelect = true;
1214  SelectEntries(nSelect, LET_TRACKING, bShift, bCtrl);
1215  mbTrackingSelect = false;
1216  }
1217  }
1218  else
1219  {
1220  if ( !mbMulti && GetEntryList()->GetSelectedEntryCount() )
1221  {
1222  mbTrackingSelect = true;
1223  SelectEntry( GetEntryList()->GetSelectedEntryPos( 0 ), false );
1224  mbTrackingSelect = false;
1225  }
1226  }
1227  mnCurrentPos = nSelect;
1229  {
1231  }
1232  else
1233  {
1234  long nHeightDiff = mpEntryList->GetAddedHeight( mnCurrentPos, mnTop );
1235  maFocusRect.SetPos( Point( 0, nHeightDiff ) );
1236  Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( mnCurrentPos ) );
1237  maFocusRect.SetSize( aSz );
1239  }
1240  }
1241  }
1242 }
1243 
1245 {
1246  if( !ProcessKeyInput( rKEvt ) )
1247  Control::KeyInput( rKEvt );
1248 }
1249 
1251 {
1252  // entry to be selected
1253  sal_Int32 nSelect = LISTBOX_ENTRY_NOTFOUND;
1254  LB_EVENT_TYPE eLET = LET_KEYMOVE;
1255 
1256  vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
1257 
1258  bool bShift = aKeyCode.IsShift();
1259  bool bCtrl = aKeyCode.IsMod1() || aKeyCode.IsMod3();
1260  bool bMod2 = aKeyCode.IsMod2();
1261  bool bDone = false;
1262  bool bHandleKey = false;
1263 
1264  switch( aKeyCode.GetCode() )
1265  {
1266  case KEY_UP:
1267  {
1268  if ( IsReadOnly() )
1269  {
1270  if ( GetTopEntry() )
1271  SetTopEntry( GetTopEntry()-1 );
1272  }
1273  else if ( !bMod2 )
1274  {
1276  {
1277  nSelect = mpEntryList->FindFirstSelectable( 0 );
1278  }
1279  else if ( mnCurrentPos )
1280  {
1281  // search first selectable above the current position
1282  nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos - 1, false );
1283  }
1284 
1285  if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect < mnTop ) )
1286  SetTopEntry( mnTop-1 );
1287 
1288  bDone = true;
1289  }
1291  }
1292  break;
1293 
1294  case KEY_DOWN:
1295  {
1296  if ( IsReadOnly() )
1297  {
1298  SetTopEntry( GetTopEntry()+1 );
1299  }
1300  else if ( !bMod2 )
1301  {
1303  {
1304  nSelect = mpEntryList->FindFirstSelectable( 0 );
1305  }
1306  else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() )
1307  {
1308  // search first selectable below the current position
1309  nSelect = mpEntryList->FindFirstSelectable( mnCurrentPos + 1 );
1310  }
1311 
1312  if( ( nSelect != LISTBOX_ENTRY_NOTFOUND ) && ( nSelect >= GetLastVisibleEntry() ) )
1313  SetTopEntry( mnTop+1 );
1314 
1315  bDone = true;
1316  }
1318  }
1319  break;
1320 
1321  case KEY_PAGEUP:
1322  {
1323  if ( IsReadOnly() )
1324  {
1325  sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop +1;
1326  SetTopEntry( ( mnTop > nCurVis ) ?
1327  (mnTop-nCurVis) : 0 );
1328  }
1329  else if ( !bCtrl && !bMod2 )
1330  {
1332  {
1333  nSelect = mpEntryList->FindFirstSelectable( 0 );
1334  }
1335  else if ( mnCurrentPos )
1336  {
1337  if( mnCurrentPos == mnTop )
1338  {
1339  sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop +1;
1340  SetTopEntry( ( mnTop > nCurVis ) ? ( mnTop-nCurVis+1 ) : 0 );
1341  }
1342 
1343  // find first selectable starting from mnTop looking forward
1344  nSelect = mpEntryList->FindFirstSelectable( mnTop );
1345  }
1346  bDone = true;
1347  }
1349  }
1350  break;
1351 
1352  case KEY_PAGEDOWN:
1353  {
1354  if ( IsReadOnly() )
1355  {
1357  }
1358  else if ( !bCtrl && !bMod2 )
1359  {
1361  {
1362  nSelect = mpEntryList->FindFirstSelectable( 0 );
1363  }
1364  else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() )
1365  {
1366  sal_Int32 nCount = mpEntryList->GetEntryCount();
1367  sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop;
1368  sal_Int32 nTmp = std::min( nCurVis, nCount );
1369  nTmp += mnTop - 1;
1370  if( mnCurrentPos == nTmp && mnCurrentPos != nCount - 1 )
1371  {
1372  long nTmp2 = std::min( static_cast<long>(nCount-nCurVis), static_cast<long>(static_cast<long>(mnTop)+static_cast<long>(nCurVis)-1) );
1373  nTmp2 = std::max( long(0) , nTmp2 );
1374  nTmp = static_cast<sal_Int32>(nTmp2+(nCurVis-1) );
1375  SetTopEntry( static_cast<sal_Int32>(nTmp2) );
1376  }
1377  // find first selectable starting from nTmp looking backwards
1378  nSelect = mpEntryList->FindFirstSelectable( nTmp, false );
1379  }
1380  bDone = true;
1381  }
1383  }
1384  break;
1385 
1386  case KEY_HOME:
1387  {
1388  if ( IsReadOnly() )
1389  {
1390  SetTopEntry( 0 );
1391  }
1392  else if ( !bCtrl && !bMod2 && mnCurrentPos )
1393  {
1394  nSelect = mpEntryList->FindFirstSelectable( mpEntryList->GetEntryCount() ? 0 : LISTBOX_ENTRY_NOTFOUND );
1395  if( mnTop != 0 )
1396  SetTopEntry( 0 );
1397 
1398  bDone = true;
1399  }
1401  }
1402  break;
1403 
1404  case KEY_END:
1405  {
1406  if ( IsReadOnly() )
1407  {
1408  SetTopEntry( 0xFFFF );
1409  }
1410  else if ( !bCtrl && !bMod2 )
1411  {
1413  {
1414  nSelect = mpEntryList->FindFirstSelectable( 0 );
1415  }
1416  else if ( (mnCurrentPos+1) < mpEntryList->GetEntryCount() )
1417  {
1418  sal_Int32 nCount = mpEntryList->GetEntryCount();
1419  nSelect = mpEntryList->FindFirstSelectable( nCount - 1, false );
1420  sal_Int32 nCurVis = GetLastVisibleEntry() - mnTop + 1;
1421  if( nCount > nCurVis )
1422  SetTopEntry( nCount - nCurVis );
1423  }
1424  bDone = true;
1425  }
1427  }
1428  break;
1429 
1430  case KEY_LEFT:
1431  {
1432  if ( !bCtrl && !bMod2 )
1433  {
1434  ScrollHorz( -HORZ_SCROLL );
1435  bDone = true;
1436  }
1438  }
1439  break;
1440 
1441  case KEY_RIGHT:
1442  {
1443  if ( !bCtrl && !bMod2 )
1444  {
1446  bDone = true;
1447  }
1449  }
1450  break;
1451 
1452  case KEY_RETURN:
1453  {
1454  if ( !bMod2 && !IsReadOnly() )
1455  {
1457  ImplCallSelect();
1458  bDone = false; // do not catch RETURN
1459  }
1461  }
1462  break;
1463 
1464  case KEY_SPACE:
1465  {
1466  if ( !bMod2 && !IsReadOnly() )
1467  {
1468  if( mbMulti && ( !mbSimpleMode || ( mbSimpleMode && bCtrl && !bShift ) ) )
1469  {
1470  nSelect = mnCurrentPos;
1471  eLET = LET_KEYSPACE;
1472  }
1473  bDone = true;
1474  }
1475  bHandleKey = true;
1476  }
1477  break;
1478 
1479  case KEY_A:
1480  {
1481  if( bCtrl && mbMulti )
1482  {
1483  // paint only once
1484  bool bUpdates = IsUpdateMode();
1485  SetUpdateMode( false );
1486 
1487  sal_Int32 nEntryCount = mpEntryList->GetEntryCount();
1488  for( sal_Int32 i = 0; i < nEntryCount; i++ )
1489  SelectEntry( i, true );
1490 
1491  // restore update mode
1492  SetUpdateMode( bUpdates );
1493  Invalidate();
1494 
1496 
1497  bDone = true;
1498  }
1499  else
1500  {
1501  bHandleKey = true;
1502  }
1503  }
1504  break;
1505 
1506  default:
1507  bHandleKey = true;
1508  break;
1509  }
1510  if (bHandleKey && !IsReadOnly())
1511  {
1512  bDone = maQuickSelectionEngine.HandleKeyEvent( rKEvt );
1513  }
1514 
1515  if ( ( nSelect != LISTBOX_ENTRY_NOTFOUND )
1516  && ( ( !mpEntryList->IsEntryPosSelected( nSelect ) )
1517  || ( eLET == LET_KEYSPACE )
1518  )
1519  )
1520  {
1521  SAL_WARN_IF( mpEntryList->IsEntryPosSelected( nSelect ) && !mbMulti, "vcl", "ImplListBox: Selecting same Entry" );
1522  sal_Int32 nCount = mpEntryList->GetEntryCount();
1523  if (nSelect >= nCount)
1524  nSelect = nCount ? nCount-1 : LISTBOX_ENTRY_NOTFOUND;
1525  bool bCurPosChange = (mnCurrentPos != nSelect);
1526  mnCurrentPos = nSelect;
1527  if(SelectEntries( nSelect, eLET, bShift, bCtrl, bCurPosChange))
1528  {
1529  // tdf#129043 Correctly deliver events when changing values with arrow keys in combobox
1530  if (mbIsDropdown && IsReallyVisible())
1531  mbTravelSelect = true;
1533  ImplCallSelect();
1534  mbTravelSelect = false;
1535  }
1536  }
1537 
1538  return bDone;
1539 }
1540 
1541 namespace
1542 {
1543  vcl::StringEntryIdentifier lcl_getEntry( const ImplEntryList& _rList, sal_Int32 _nPos, OUString& _out_entryText )
1544  {
1545  OSL_PRECOND( ( _nPos != LISTBOX_ENTRY_NOTFOUND ), "lcl_getEntry: invalid position!" );
1546  sal_Int32 nEntryCount( _rList.GetEntryCount() );
1547  if ( _nPos >= nEntryCount )
1548  _nPos = 0;
1549  _out_entryText = _rList.GetEntryText( _nPos );
1550 
1551  // vcl::StringEntryIdentifier does not allow for 0 values, but our position is 0-based
1552  // => normalize
1553  return reinterpret_cast< vcl::StringEntryIdentifier >( _nPos + 1 );
1554  }
1555 
1556  sal_Int32 lcl_getEntryPos( vcl::StringEntryIdentifier _entry )
1557  {
1558  // our pos is 0-based, but StringEntryIdentifier does not allow for a NULL
1559  return static_cast< sal_Int32 >( reinterpret_cast< sal_Int64 >( _entry ) ) - 1;
1560  }
1561 }
1562 
1564 {
1565  return lcl_getEntry( *GetEntryList(), ( mnCurrentPos == LISTBOX_ENTRY_NOTFOUND ) ? 0 : mnCurrentPos, _out_entryText );
1566 }
1567 
1569 {
1570  sal_Int32 nNextPos = lcl_getEntryPos( _currentEntry ) + 1;
1571  return lcl_getEntry( *GetEntryList(), nNextPos, _out_entryText );
1572 }
1573 
1575 {
1576  sal_Int32 nSelect = lcl_getEntryPos( _entry );
1577  if ( mpEntryList->IsEntryPosSelected( nSelect ) )
1578  {
1579  // ignore that. This method is a callback from the QuickSelectionEngine, which means the user attempted
1580  // to select the given entry by typing its starting letters. No need to act.
1581  return;
1582  }
1583 
1584  // normalize
1585  OSL_ENSURE( nSelect < mpEntryList->GetEntryCount(), "ImplListBoxWindow::SelectEntry: how that?" );
1586  sal_Int32 nCount = mpEntryList->GetEntryCount();
1587  if (nSelect >= nCount)
1588  nSelect = nCount ? nCount-1 : LISTBOX_ENTRY_NOTFOUND;
1589 
1590  // make visible
1591  ShowProminentEntry( nSelect );
1592 
1593  // actually select
1594  mnCurrentPos = nSelect;
1595  if ( SelectEntries( nSelect, LET_KEYMOVE ) )
1596  {
1597  mbTravelSelect = true;
1598  mnSelectModifier = 0;
1599  ImplCallSelect();
1600  mbTravelSelect = false;
1601  }
1602 }
1603 
1604 void ImplListBoxWindow::ImplPaint(vcl::RenderContext& rRenderContext, sal_Int32 nPos)
1605 {
1606  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1607 
1608  const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nPos );
1609  if (!pEntry)
1610  return;
1611 
1612  long nWidth = GetOutputSizePixel().Width();
1613  long nY = mpEntryList->GetAddedHeight(nPos, mnTop);
1614  tools::Rectangle aRect(Point(0, nY), Size(nWidth, pEntry->getHeightWithMargin()));
1615 
1616  bool bSelected = mpEntryList->IsEntryPosSelected(nPos);
1617  if (bSelected)
1618  {
1619  rRenderContext.SetTextColor(!IsEnabled() ? rStyleSettings.GetDisableColor() : rStyleSettings.GetHighlightTextColor());
1620  rRenderContext.SetFillColor(rStyleSettings.GetHighlightColor());
1621  rRenderContext.SetLineColor();
1622  rRenderContext.DrawRect(aRect);
1623  }
1624  else
1625  {
1626  ApplySettings(rRenderContext);
1627  if (!IsEnabled())
1628  rRenderContext.SetTextColor(rStyleSettings.GetDisableColor());
1629  }
1630  rRenderContext.SetTextFillColor();
1631 
1632  if (IsUserDrawEnabled())
1633  {
1634  mbInUserDraw = true;
1635  mnUserDrawEntry = nPos;
1636  aRect.AdjustLeft( -mnLeft );
1637  if (nPos < GetEntryList()->GetMRUCount())
1638  nPos = GetEntryList()->FindEntry(GetEntryList()->GetEntryText(nPos));
1639  nPos = nPos - GetEntryList()->GetMRUCount();
1640 
1641  UserDrawEvent aUDEvt(this, &rRenderContext, aRect, nPos, bSelected);
1642  maUserDrawHdl.Call( &aUDEvt );
1643  mbInUserDraw = false;
1644  }
1645  else
1646  {
1647  DrawEntry(rRenderContext, nPos, true, true);
1648  }
1649 }
1650 
1651 void ImplListBoxWindow::DrawEntry(vcl::RenderContext& rRenderContext, sal_Int32 nPos, bool bDrawImage, bool bDrawText)
1652 {
1653  const ImplEntryType* pEntry = mpEntryList->GetEntryPtr(nPos);
1654  if (!pEntry)
1655  return;
1656 
1657  long nEntryHeight = pEntry->getHeightWithMargin();
1658 
1659  // when changing this function don't forget to adjust ImplWin::DrawEntry()
1660 
1661  if (mbInUserDraw)
1662  nPos = mnUserDrawEntry; // real entry, not the matching entry from MRU
1663 
1664  long nY = mpEntryList->GetAddedHeight(nPos, mnTop);
1665  Size aImgSz;
1666 
1667  if (bDrawImage && mpEntryList->HasImages())
1668  {
1669  Image aImage = mpEntryList->GetEntryImage(nPos);
1670  if (!!aImage)
1671  {
1672  aImgSz = aImage.GetSizePixel();
1673  Point aPtImg(gnBorder - mnLeft, nY + ((nEntryHeight - aImgSz.Height()) / 2));
1674 
1675  if (!IsZoom())
1676  {
1677  rRenderContext.DrawImage(aPtImg, aImage);
1678  }
1679  else
1680  {
1681  aImgSz.setWidth( CalcZoom(aImgSz.Width()) );
1682  aImgSz.setHeight( CalcZoom(aImgSz.Height()) );
1683  rRenderContext.DrawImage(aPtImg, aImgSz, aImage);
1684  }
1685 
1686  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1687  const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
1688 
1689  if (nEdgeBlendingPercent && aImgSz.Width() && aImgSz.Height())
1690  {
1691  const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
1692  const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
1693  const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
1694  const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight));
1695 
1696  if (!aBlendFrame.IsEmpty())
1697  {
1698  rRenderContext.DrawBitmapEx(aPtImg, aBlendFrame);
1699  }
1700  }
1701  }
1702  }
1703 
1704  if (bDrawText)
1705  {
1706  OUString aStr(mpEntryList->GetEntryText(nPos));
1707  if (!aStr.isEmpty())
1708  {
1709  long nMaxWidth = std::max(mnMaxWidth, GetOutputSizePixel().Width() - 2 * gnBorder);
1710  // a multiline entry should only be as wide as the window
1711  if (pEntry->mnFlags & ListBoxEntryFlags::MultiLine)
1712  nMaxWidth = GetOutputSizePixel().Width() - 2 * gnBorder;
1713 
1714  tools::Rectangle aTextRect(Point(gnBorder - mnLeft, nY),
1715  Size(nMaxWidth, nEntryHeight));
1716 
1717  if (mpEntryList->HasEntryImage(nPos) || IsUserDrawEnabled())
1718  {
1719  long nImageWidth = std::max(mnMaxImgWidth, maUserItemSize.Width());
1720  aTextRect.AdjustLeft(nImageWidth + IMG_TXT_DISTANCE );
1721  }
1722 
1723  DrawTextFlags nDrawStyle = ImplGetTextStyle();
1724  if (pEntry->mnFlags & ListBoxEntryFlags::MultiLine)
1725  nDrawStyle |= MULTILINE_ENTRY_DRAW_FLAGS;
1727  nDrawStyle |= DrawTextFlags::Disable;
1728 
1729  rRenderContext.DrawText(aTextRect, aStr, nDrawStyle);
1730  }
1731  }
1732 
1733  if ( !maSeparators.empty() && ( isSeparator(nPos) || isSeparator(nPos-1) ) )
1734  {
1735  Color aOldLineColor(rRenderContext.GetLineColor());
1736  rRenderContext.SetLineColor((GetBackground() != COL_LIGHTGRAY) ? COL_LIGHTGRAY : COL_GRAY);
1737  Point aStartPos(0, nY);
1738  if (isSeparator(nPos))
1739  aStartPos.AdjustY(pEntry->getHeightWithMargin() - 1 );
1740  Point aEndPos(aStartPos);
1741  aEndPos.setX( GetOutputSizePixel().Width() );
1742  rRenderContext.DrawLine(aStartPos, aEndPos);
1743  rRenderContext.SetLineColor(aOldLineColor);
1744  }
1745 }
1746 
1748 {
1749  mpControlData->mpLayoutData.reset( new vcl::ControlLayoutData );
1750  const_cast<ImplListBoxWindow*>(this)->Invalidate(tools::Rectangle(Point(0, 0), GetOutputSize()));
1751 }
1752 
1754 {
1755  sal_Int32 nCount = mpEntryList->GetEntryCount();
1756 
1757  bool bShowFocusRect = mbHasFocusRect;
1758  if (mbHasFocusRect)
1760 
1761  long nY = 0; // + gnBorder;
1762  long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + gnBorder;
1763 
1764  for (sal_Int32 i = mnTop; i < nCount && nY < nHeight + mnMaxHeight; i++)
1765  {
1766  const ImplEntryType* pEntry = mpEntryList->GetEntryPtr(i);
1767  long nEntryHeight = pEntry->getHeightWithMargin();
1768  if (nY + nEntryHeight >= rRect.Top() &&
1769  nY <= rRect.Bottom() + mnMaxHeight)
1770  {
1771  ImplPaint(rRenderContext, i);
1772  }
1773  nY += nEntryHeight;
1774  }
1775 
1776  long nHeightDiff = mpEntryList->GetAddedHeight(mnCurrentPos, mnTop);
1777  maFocusRect.SetPos(Point(0, nHeightDiff));
1778  Size aSz(maFocusRect.GetWidth(), mpEntryList->GetEntryHeight(mnCurrentPos));
1779  maFocusRect.SetSize(aSz);
1780  if (HasFocus() && bShowFocusRect)
1782 }
1783 
1785 {
1787  {
1788  // This widget is explicitly double-buffered, so avoid partial paints.
1789  tools::Rectangle aRect(Point(0, 0), GetOutputSizePixel());
1790  ImplDoPaint(rRenderContext, aRect);
1791  }
1792  else
1793  ImplDoPaint(rRenderContext, rRect);
1794 }
1795 
1797 {
1798  // FIXME: ListBoxEntryFlags::MultiLine
1799 
1800  const sal_Int32 nCount = mpEntryList->GetEntryCount()-mnTop;
1801  long nHeight = GetOutputSizePixel().Height();// - mnMaxHeight + gnBorder;
1802  sal_uInt16 nEntries = static_cast< sal_uInt16 >( ( nHeight + mnMaxHeight - 1 ) / mnMaxHeight );
1803  if( nEntries > nCount )
1804  nEntries = static_cast<sal_uInt16>(nCount);
1805 
1806  return nEntries;
1807 }
1808 
1810 {
1811  Control::Resize();
1812 
1813  bool bShowFocusRect = mbHasFocusRect;
1814  if ( bShowFocusRect )
1816 
1818  {
1819  Size aSz( GetOutputSizePixel().Width(), mpEntryList->GetEntryHeight( mnCurrentPos ) );
1820  maFocusRect.SetSize( aSz );
1821  }
1822 
1823  if ( bShowFocusRect )
1825 
1827 }
1828 
1830 {
1831  sal_Int32 nPos = mnCurrentPos;
1832  if ( nPos == LISTBOX_ENTRY_NOTFOUND )
1833  nPos = 0;
1834  long nHeightDiff = mpEntryList->GetAddedHeight( nPos, mnTop );
1835  maFocusRect.SetPos( Point( 0, nHeightDiff ) );
1836  Size aSz( maFocusRect.GetWidth(), mpEntryList->GetEntryHeight( nPos ) );
1837  maFocusRect.SetSize( aSz );
1840 }
1841 
1843 {
1846 }
1847 
1848 void ImplListBoxWindow::SetTopEntry( sal_Int32 nTop )
1849 {
1850  if( mpEntryList->GetEntryCount() == 0 )
1851  return;
1852 
1853  long nWHeight = PixelToLogic( GetSizePixel() ).Height();
1854 
1855  sal_Int32 nLastEntry = mpEntryList->GetEntryCount()-1;
1856  if( nTop > nLastEntry )
1857  nTop = nLastEntry;
1858  const ImplEntryType* pLast = mpEntryList->GetEntryPtr( nLastEntry );
1859  while( nTop > 0 && mpEntryList->GetAddedHeight( nLastEntry, nTop-1 ) + pLast->getHeightWithMargin() <= nWHeight )
1860  nTop--;
1861 
1862  if ( nTop == mnTop )
1863  return;
1864 
1866  long nDiff = mpEntryList->GetAddedHeight( mnTop, nTop );
1867  PaintImmediately();
1869  mnTop = nTop;
1870  Scroll( 0, nDiff );
1871  PaintImmediately();
1872  if( HasFocus() )
1874  maScrollHdl.Call( this );
1875 }
1876 
1877 void ImplListBoxWindow::ShowProminentEntry( sal_Int32 nEntryPos )
1878 {
1879  SetTopEntry( nEntryPos );
1880 }
1881 
1883 {
1884  ScrollHorz( n - mnLeft );
1885 }
1886 
1888 {
1889  long nDiff = 0;
1890  if ( n > 0 )
1891  {
1892  long nWidth = GetOutputSizePixel().Width();
1893  if( ( mnMaxWidth - mnLeft + n ) > nWidth )
1894  nDiff = n;
1895  }
1896  else if ( n < 0 )
1897  {
1898  if( mnLeft )
1899  {
1900  long nAbs = -n;
1901  nDiff = - std::min( mnLeft, nAbs );
1902  }
1903  }
1904 
1905  if ( nDiff )
1906  {
1908  mnLeft = sal::static_int_cast<sal_uInt16>(mnLeft + nDiff);
1909  PaintImmediately();
1911  Scroll( -nDiff, 0 );
1912  PaintImmediately();
1913  if( HasFocus() )
1915  maScrollHdl.Call( this );
1916  }
1917 }
1918 
1920 {
1921  maSeparators.clear();
1922 
1923  if ( n != LISTBOX_ENTRY_NOTFOUND )
1924  {
1925  maSeparators.insert( n );
1926  }
1927 }
1928 
1930 {
1931  if (!maSeparators.empty())
1932  return *(maSeparators.begin());
1933  else
1934  return LISTBOX_ENTRY_NOTFOUND;
1935 }
1936 
1937 bool ImplListBoxWindow::isSeparator( const sal_Int32 &n) const
1938 {
1939  return maSeparators.find(n) != maSeparators.end();
1940 }
1941 
1942 Size ImplListBoxWindow::CalcSize(sal_Int32 nMaxLines) const
1943 {
1944  // FIXME: ListBoxEntryFlags::MultiLine
1945 
1946  Size aSz;
1947  aSz.setHeight(nMaxLines * GetEntryHeightWithMargin());
1948  aSz.setWidth( mnMaxWidth + 2*gnBorder );
1949  return aSz;
1950 }
1951 
1953 {
1954  const ImplEntryType* pEntry = mpEntryList->GetEntryPtr( nItem );
1955  Size aSz( GetSizePixel().Width(), pEntry ? pEntry->getHeightWithMargin() : GetEntryHeightWithMargin() );
1956  long nY = mpEntryList->GetAddedHeight( nItem, GetTopEntry() ) + GetEntryList()->GetMRUCount()*GetEntryHeightWithMargin();
1957  tools::Rectangle aRect( Point( 0, nY ), aSz );
1958  return aRect;
1959 }
1960 
1962 {
1963  Control::StateChanged( nType );
1964 
1965  if ( nType == StateChangedType::Zoom )
1966  {
1967  ApplySettings(*this);
1968  ImplCalcMetrics();
1969  Invalidate();
1970  }
1971  else if ( nType == StateChangedType::UpdateMode )
1972  {
1973  if ( IsUpdateMode() && IsReallyVisible() )
1974  Invalidate();
1975  }
1976  else if ( nType == StateChangedType::ControlFont )
1977  {
1978  ApplySettings(*this);
1979  ImplCalcMetrics();
1980  Invalidate();
1981  }
1982  else if ( nType == StateChangedType::ControlForeground )
1983  {
1984  ApplySettings(*this);
1985  Invalidate();
1986  }
1987  else if ( nType == StateChangedType::ControlBackground )
1988  {
1989  ApplySettings(*this);
1990  Invalidate();
1991  }
1992  else if( nType == StateChangedType::Enable )
1993  {
1994  Invalidate();
1995  }
1996 
1998 }
1999 
2001 {
2002  Control::DataChanged( rDCEvt );
2003 
2004  if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
2006  ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
2007  (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
2008  {
2010  ApplySettings(*this);
2011  ImplCalcMetrics();
2012  Invalidate();
2013  }
2014 }
2015 
2017 {
2019 
2020  if (mpEntryList->HasImages())
2021  nTextStyle |= DrawTextFlags::Left;
2022  else if (mbCenter)
2023  nTextStyle |= DrawTextFlags::Center;
2024  else if (mbRight)
2025  nTextStyle |= DrawTextFlags::Right;
2026  else
2027  nTextStyle |= DrawTextFlags::Left;
2028 
2029  return nTextStyle;
2030 }
2031 
2033  Control( pParent, nWinStyle ),
2034  maLBWindow(VclPtr<ImplListBoxWindow>::Create( this, nWinStyle&(~WB_BORDER) ))
2035 {
2036  // for native widget rendering we must be able to detect this window type
2037  SetType( WindowType::LISTBOXWINDOW );
2038 
2042 
2043  Link<ScrollBar*,void> aLink( LINK( this, ImplListBox, ScrollBarHdl ) );
2044  mpVScrollBar->SetScrollHdl( aLink );
2045  mpHScrollBar->SetScrollHdl( aLink );
2046 
2047  mbVScroll = false;
2048  mbHScroll = false;
2049  mbAutoHScroll = ( nWinStyle & WB_AUTOHSCROLL );
2050  mbEdgeBlending = false;
2051 
2052  maLBWindow->SetScrollHdl( LINK( this, ImplListBox, LBWindowScrolled ) );
2053  maLBWindow->SetMRUChangedHdl( LINK( this, ImplListBox, MRUChanged ) );
2055  maLBWindow->Show();
2056 }
2057 
2059 {
2060  disposeOnce();
2061 }
2062 
2064 {
2069  Control::dispose();
2070 }
2071 
2073 {
2074  maLBWindow->Clear();
2075  if ( GetEntryList()->GetMRUCount() )
2076  {
2079  }
2080  mpVScrollBar->SetThumbPos( 0 );
2081  mpHScrollBar->SetThumbPos( 0 );
2083 }
2084 
2085 sal_Int32 ImplListBox::InsertEntry( sal_Int32 nPos, const OUString& rStr )
2086 {
2087  ImplEntryType* pNewEntry = new ImplEntryType( rStr );
2088  sal_Int32 nNewPos = maLBWindow->InsertEntry( nPos, pNewEntry );
2090  return nNewPos;
2091 }
2092 
2093 sal_Int32 ImplListBox::InsertEntry( sal_Int32 nPos, const OUString& rStr, const Image& rImage )
2094 {
2095  ImplEntryType* pNewEntry = new ImplEntryType( rStr, rImage );
2096  sal_Int32 nNewPos = maLBWindow->InsertEntry( nPos, pNewEntry );
2098  return nNewPos;
2099 }
2100 
2101 void ImplListBox::RemoveEntry( sal_Int32 nPos )
2102 {
2103  maLBWindow->RemoveEntry( nPos );
2105 }
2106 
2107 void ImplListBox::SetEntryFlags( sal_Int32 nPos, ListBoxEntryFlags nFlags )
2108 {
2109  maLBWindow->SetEntryFlags( nPos, nFlags );
2110 }
2111 
2112 void ImplListBox::SelectEntry( sal_Int32 nPos, bool bSelect )
2113 {
2114  maLBWindow->SelectEntry( nPos, bSelect );
2115 }
2116 
2118 {
2120 }
2121 
2123 {
2124  if (maLBWindow)
2125  maLBWindow->GrabFocus();
2126  else
2128 }
2129 
2131 {
2132  Control::Resize();
2135 }
2136 
2138 {
2139  CompatStateChanged( StateChangedType::Data );
2140 }
2141 
2143 {
2144  long nSet = GetTopEntry();
2145  if( nSet > mpVScrollBar->GetRangeMax() )
2146  mpVScrollBar->SetRangeMax( GetEntryList()->GetEntryCount() );
2147  mpVScrollBar->SetThumbPos( GetTopEntry() );
2148 
2149  mpHScrollBar->SetThumbPos( GetLeftIndent() );
2150 
2151  maScrollHdl.Call( this );
2152 }
2153 
2154 IMPL_LINK( ImplListBox, ScrollBarHdl, ScrollBar*, pSB, void )
2155 {
2156  sal_uInt16 nPos = static_cast<sal_uInt16>(pSB->GetThumbPos());
2157  if( pSB == mpVScrollBar )
2158  SetTopEntry( nPos );
2159  else if( pSB == mpHScrollBar )
2160  SetLeftIndent( nPos );
2161  if( GetParent() )
2162  GetParent()->Invalidate( InvalidateFlags::Update );
2163 }
2164 
2166 {
2167  bool bArrange = false;
2168 
2169  Size aOutSz = GetOutputSizePixel();
2170  sal_Int32 nEntries = GetEntryList()->GetEntryCount();
2171  sal_uInt16 nMaxVisEntries = static_cast<sal_uInt16>(aOutSz.Height() / GetEntryHeightWithMargin());
2172 
2173  // vertical ScrollBar
2174  if( nEntries > nMaxVisEntries )
2175  {
2176  if( !mbVScroll )
2177  bArrange = true;
2178  mbVScroll = true;
2179 
2180  // check of the scrolled-out region
2181  if( GetEntryList()->GetSelectedEntryCount() == 1 &&
2184  else
2185  SetTopEntry( GetTopEntry() ); // MaxTop is being checked...
2186  }
2187  else
2188  {
2189  if( mbVScroll )
2190  bArrange = true;
2191  mbVScroll = false;
2192  SetTopEntry( 0 );
2193  }
2194 
2195  // horizontal ScrollBar
2196  if( mbAutoHScroll )
2197  {
2198  long nWidth = static_cast<sal_uInt16>(aOutSz.Width());
2199  if ( mbVScroll )
2200  nWidth -= mpVScrollBar->GetSizePixel().Width();
2201 
2202  long nMaxWidth = GetMaxEntryWidth();
2203  if( nWidth < nMaxWidth )
2204  {
2205  if( !mbHScroll )
2206  bArrange = true;
2207  mbHScroll = true;
2208 
2209  if ( !mbVScroll ) // maybe we do need one now
2210  {
2211  nMaxVisEntries = static_cast<sal_uInt16>( ( aOutSz.Height() - mpHScrollBar->GetSizePixel().Height() ) / GetEntryHeightWithMargin() );
2212  if( nEntries > nMaxVisEntries )
2213  {
2214  bArrange = true;
2215  mbVScroll = true;
2216 
2217  // check of the scrolled-out region
2218  if( GetEntryList()->GetSelectedEntryCount() == 1 &&
2221  else
2222  SetTopEntry( GetTopEntry() ); // MaxTop is being checked...
2223  }
2224  }
2225 
2226  // check of the scrolled-out region
2227  sal_uInt16 nMaxLI = static_cast<sal_uInt16>(nMaxWidth - nWidth);
2228  if ( nMaxLI < GetLeftIndent() )
2229  SetLeftIndent( nMaxLI );
2230  }
2231  else
2232  {
2233  if( mbHScroll )
2234  bArrange = true;
2235  mbHScroll = false;
2236  SetLeftIndent( 0 );
2237  }
2238  }
2239 
2240  if( bArrange )
2242 
2244 }
2245 
2247 {
2248  Size aOutSz = maLBWindow->GetOutputSizePixel();
2249 
2250  if ( mbVScroll )
2251  {
2252  sal_Int32 nEntries = GetEntryList()->GetEntryCount();
2253  sal_uInt16 nVisEntries = static_cast<sal_uInt16>(aOutSz.Height() / GetEntryHeightWithMargin());
2254  mpVScrollBar->SetRangeMax( nEntries );
2255  mpVScrollBar->SetVisibleSize( nVisEntries );
2256  mpVScrollBar->SetPageSize( nVisEntries - 1 );
2257  }
2258 
2259  if ( mbHScroll )
2260  {
2262  mpHScrollBar->SetVisibleSize( static_cast<sal_uInt16>(aOutSz.Width()) );
2264  mpHScrollBar->SetPageSize( aOutSz.Width() - HORZ_SCROLL );
2265  }
2266 }
2267 
2269 {
2270  // Here we only position the Controls; if the Scrollbars are to be
2271  // visible is already determined in ImplCheckScrollBars
2272 
2273  Size aOutSz = GetOutputSizePixel();
2274  long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
2275  nSBWidth = CalcZoom( nSBWidth );
2276 
2277  Size aInnerSz( aOutSz );
2278  if ( mbVScroll )
2279  aInnerSz.AdjustWidth( -nSBWidth );
2280  if ( mbHScroll )
2281  aInnerSz.AdjustHeight( -nSBWidth );
2282 
2283  Point aWinPos( 0, 0 );
2284  maLBWindow->SetPosSizePixel( aWinPos, aInnerSz );
2285 
2286  // ScrollBarBox
2287  if( mbVScroll && mbHScroll )
2288  {
2289  Point aBoxPos( aInnerSz.Width(), aInnerSz.Height() );
2290  mpScrollBarBox->SetPosSizePixel( aBoxPos, Size( nSBWidth, nSBWidth ) );
2291  mpScrollBarBox->Show();
2292  }
2293  else
2294  {
2295  mpScrollBarBox->Hide();
2296  }
2297 
2298  // vertical ScrollBar
2299  if( mbVScroll )
2300  {
2301  // Scrollbar on left or right side?
2302  Point aVPos( aOutSz.Width() - nSBWidth, 0 );
2303  mpVScrollBar->SetPosSizePixel( aVPos, Size( nSBWidth, aInnerSz.Height() ) );
2304  mpVScrollBar->Show();
2305  }
2306  else
2307  {
2308  mpVScrollBar->Hide();
2309  // #107254# Don't reset top entry after resize, but check for max top entry
2310  SetTopEntry( GetTopEntry() );
2311  }
2312 
2313  // horizontal ScrollBar
2314  if( mbHScroll )
2315  {
2316  Point aHPos( 0, aOutSz.Height() - nSBWidth );
2317  mpHScrollBar->SetPosSizePixel( aHPos, Size( aInnerSz.Width(), nSBWidth ) );
2318  mpHScrollBar->Show();
2319  }
2320  else
2321  {
2322  mpHScrollBar->Hide();
2323  SetLeftIndent( 0 );
2324  }
2325 }
2326 
2328 {
2329  if ( nType == StateChangedType::InitShow )
2330  {
2332  }
2333  else if ( ( nType == StateChangedType::UpdateMode ) || ( nType == StateChangedType::Data ) )
2334  {
2335  bool bUpdate = IsUpdateMode();
2336  maLBWindow->SetUpdateMode( bUpdate );
2337  if ( bUpdate && IsReallyVisible() )
2339  }
2340  else if( nType == StateChangedType::Enable )
2341  {
2345  maLBWindow->Enable( IsEnabled() );
2346 
2347  Invalidate();
2348  }
2349  else if ( nType == StateChangedType::Zoom )
2350  {
2351  maLBWindow->SetZoom( GetZoom() );
2352  Resize();
2353  }
2354  else if ( nType == StateChangedType::ControlFont )
2355  {
2357  }
2358  else if ( nType == StateChangedType::ControlForeground )
2359  {
2361  }
2362  else if ( nType == StateChangedType::ControlBackground )
2363  {
2365  }
2366  else if( nType == StateChangedType::Mirroring )
2367  {
2372  }
2373 
2374  Control::StateChanged( nType );
2375 }
2376 
2378 {
2379  bool bDone = false;
2380  if ( rNEvt.GetType() == MouseNotifyEvent::COMMAND )
2381  {
2382  const CommandEvent& rCEvt = *rNEvt.GetCommandEvent();
2383  if ( rCEvt.GetCommand() == CommandEventId::Wheel )
2384  {
2385  const CommandWheelData* pData = rCEvt.GetWheelData();
2386  if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
2387  {
2388  bDone = HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar );
2389  }
2390  }
2391  else if (rCEvt.GetCommand() == CommandEventId::Gesture)
2392  {
2394  }
2395  }
2396 
2397  return bDone || Window::EventNotify( rNEvt );
2398 }
2399 
2401 {
2402  return maLBWindow->GetDisplayBackground();
2403 }
2404 
2406 {
2407  bool bDone = false;
2408  if ( rCEvt.GetCommand() == CommandEventId::Wheel )
2409  {
2410  const CommandWheelData* pData = rCEvt.GetWheelData();
2411  if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
2412  {
2413  if (!rControl.HasChildPathFocus())
2414  rControl.GrabFocus();
2415  sal_uInt16 nKey = ( pData->GetDelta() < 0 ) ? KEY_DOWN : KEY_UP;
2416  KeyEvent aKeyEvent( 0, vcl::KeyCode( nKey ) );
2417  bDone = ProcessKeyInput( aKeyEvent );
2418  }
2419  }
2420  return bDone;
2421 }
2422 
2423 void ImplListBox::SetMRUEntries( const OUString& rEntries, sal_Unicode cSep )
2424 {
2425  bool bChanges = GetEntryList()->GetMRUCount() != 0;
2426 
2427  // Remove old MRU entries
2428  for ( sal_Int32 n = GetEntryList()->GetMRUCount();n; )
2429  maLBWindow->RemoveEntry( --n );
2430 
2431  sal_Int32 nMRUCount = 0;
2432  sal_Int32 nIndex = 0;
2433  do
2434  {
2435  OUString aEntry = rEntries.getToken( 0, cSep, nIndex );
2436  // Accept only existing entries
2437  if ( GetEntryList()->FindEntry( aEntry ) != LISTBOX_ENTRY_NOTFOUND )
2438  {
2439  ImplEntryType* pNewEntry = new ImplEntryType( aEntry );
2440  maLBWindow->InsertEntry(nMRUCount++, pNewEntry, false);
2441  bChanges = true;
2442  }
2443  }
2444  while ( nIndex >= 0 );
2445 
2446  if ( bChanges )
2447  {
2448  maLBWindow->GetEntryList()->SetMRUCount( nMRUCount );
2449  SetSeparatorPos( nMRUCount ? nMRUCount-1 : 0 );
2451  }
2452 }
2453 
2455 {
2456  OUStringBuffer aEntries;
2457  for ( sal_Int32 n = 0; n < GetEntryList()->GetMRUCount(); n++ )
2458  {
2459  aEntries.append(GetEntryList()->GetEntryText( n ));
2460  if( n < ( GetEntryList()->GetMRUCount() - 1 ) )
2461  aEntries.append(cSep);
2462  }
2463  return aEntries.makeStringAndClear();
2464 }
2465 
2467 {
2468  if(mbEdgeBlending != bNew)
2469  {
2470  mbEdgeBlending = bNew;
2472  }
2473 }
2474 
2475 ImplWin::ImplWin( vcl::Window* pParent, WinBits nWinStyle ) :
2476  Control ( pParent, nWinStyle )
2477 {
2480  SetBackground();
2481  else
2482  SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
2483 
2485 
2486  mbEdgeBlending = false;
2488 }
2489 
2491 {
2492  if( IsEnabled() )
2493  {
2494  maMBDownHdl.Call(this);
2495  }
2496 }
2497 
2499 {
2500  mpControlData->mpLayoutData.reset( new vcl::ControlLayoutData );
2501  ImplWin* pThis = const_cast<ImplWin*>(this);
2502  pThis->ImplDraw(*pThis, true);
2503 }
2504 
2506 {
2507  if( rNEvt.GetType() == MouseNotifyEvent::MOUSEMOVE )
2508  {
2509  const MouseEvent* pMouseEvt = rNEvt.GetMouseEvent();
2510  if( pMouseEvt && (pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow()) )
2511  {
2512  // trigger redraw as mouse over state has changed
2515  {
2517  }
2518  }
2519  }
2520 
2521  return Control::PreNotify(rNEvt);
2522 }
2523 
2524 void ImplWin::ImplDraw(vcl::RenderContext& rRenderContext, bool bLayout)
2525 {
2526  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
2527 
2528  if (!bLayout)
2529  {
2530  bool bNativeOK = false;
2531  bool bHasFocus = HasFocus();
2532  bool bIsEnabled = IsEnabled();
2533 
2537  {
2538  // Repaint the (focused) area similarly to
2539  // ImplSmallBorderWindowView::DrawWindow() in
2540  // vcl/source/window/brdwin.cxx
2541  vcl::Window *pWin = GetParent();
2542 
2543  ImplControlValue aControlValue;
2544  bIsEnabled &= pWin->IsEnabled();
2545  if ( !bIsEnabled )
2546  nState &= ~ControlState::ENABLED;
2547  bHasFocus |= pWin->HasFocus();
2548  if ( bHasFocus )
2549  nState |= ControlState::FOCUSED;
2550 
2551  // The listbox is painted over the entire control including the
2552  // border, but ImplWin does not contain the border => correction
2553  // needed.
2554  sal_Int32 nLeft, nTop, nRight, nBottom;
2555  pWin->GetBorder( nLeft, nTop, nRight, nBottom );
2556  Point aPoint( -nLeft, -nTop );
2557  tools::Rectangle aCtrlRegion( aPoint - GetPosPixel(), pWin->GetSizePixel() );
2558 
2559  bool bMouseOver = false;
2560  vcl::Window *pChild = pWin->GetWindow( GetWindowType::FirstChild );
2561  while( pChild )
2562  {
2563  bMouseOver = pChild->IsMouseOver();
2564  if (bMouseOver)
2565  break;
2566  pChild = pChild->GetWindow( GetWindowType::Next );
2567  }
2568  if( bMouseOver )
2569  nState |= ControlState::ROLLOVER;
2570 
2571  // if parent has no border, then nobody has drawn the background
2572  // since no border window exists. so draw it here.
2573  WinBits nParentStyle = pWin->GetStyle();
2574  if( ! (nParentStyle & WB_BORDER) || (nParentStyle & WB_NOBORDER) )
2575  {
2576  tools::Rectangle aParentRect( Point( 0, 0 ), pWin->GetSizePixel() );
2578  nState, aControlValue, OUString() );
2579  }
2580 
2581  bNativeOK = rRenderContext.DrawNativeControl(ControlType::Listbox, ControlPart::Entire, aCtrlRegion,
2582  nState, aControlValue, OUString());
2583  }
2584 
2585  if (bIsEnabled)
2586  {
2587  if (bHasFocus && !ImplGetSVData()->maNWFData.mbDDListBoxNoTextArea)
2588  {
2589  if ( !ImplGetSVData()->maNWFData.mbNoFocusRects )
2590  {
2591  rRenderContext.SetFillColor( rStyleSettings.GetHighlightColor() );
2592  rRenderContext.SetTextColor( rStyleSettings.GetHighlightTextColor() );
2593  }
2594  else
2595  {
2596  rRenderContext.SetLineColor();
2597  rRenderContext.SetFillColor();
2598  rRenderContext.SetTextColor( rStyleSettings.GetFieldTextColor() );
2599  }
2600  rRenderContext.DrawRect( maFocusRect );
2601  }
2602  else
2603  {
2604  Color aColor;
2605  if (IsControlForeground())
2606  aColor = GetControlForeground();
2607  else if (ImplGetSVData()->maNWFData.mbDDListBoxNoTextArea)
2608  {
2609  if( bNativeOK && (nState & ControlState::ROLLOVER) )
2610  aColor = rStyleSettings.GetButtonRolloverTextColor();
2611  else
2612  aColor = rStyleSettings.GetButtonTextColor();
2613  }
2614  else
2615  {
2616  if( bNativeOK && (nState & ControlState::ROLLOVER) )
2617  aColor = rStyleSettings.GetFieldRolloverTextColor();
2618  else
2619  aColor = rStyleSettings.GetFieldTextColor();
2620  }
2621  rRenderContext.SetTextColor(aColor);
2622  if (!bNativeOK)
2623  rRenderContext.Erase(maFocusRect);
2624  }
2625  }
2626  else // Disabled
2627  {
2628  rRenderContext.SetTextColor(rStyleSettings.GetDisableColor());
2629  if (!bNativeOK)
2630  rRenderContext.Erase(maFocusRect);
2631  }
2632  }
2633 
2634  DrawEntry(rRenderContext, bLayout);
2635 }
2636 
2638 {
2639  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
2640 
2641  ApplyControlFont(rRenderContext, rStyleSettings.GetFieldFont());
2642  ApplyControlForeground(rRenderContext, rStyleSettings.GetFieldTextColor());
2643 
2644  if (IsControlBackground())
2645  rRenderContext.SetBackground(GetControlBackground());
2646  else
2647  rRenderContext.SetBackground(rStyleSettings.GetFieldColor());
2648 }
2649 
2650 void ImplWin::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& )
2651 {
2652  ImplDraw(rRenderContext);
2653 }
2654 
2655 void ImplWin::DrawEntry(vcl::RenderContext& rRenderContext, bool bLayout)
2656 {
2657  long nBorder = 1;
2658  Size aOutSz(GetOutputSizePixel());
2659 
2660  bool bImage = !!maImage;
2661  if (bImage && !bLayout)
2662  {
2664  Size aImgSz = maImage.GetSizePixel();
2665  Point aPtImg( nBorder, ( ( aOutSz.Height() - aImgSz.Height() ) / 2 ) );
2666  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2667 
2668  // check for HC mode
2669  Image *pImage = &maImage;
2670 
2671  if ( !IsZoom() )
2672  {
2673  rRenderContext.DrawImage( aPtImg, *pImage, nStyle );
2674  }
2675  else
2676  {
2677  aImgSz.setWidth( CalcZoom( aImgSz.Width() ) );
2678  aImgSz.setHeight( CalcZoom( aImgSz.Height() ) );
2679  rRenderContext.DrawImage( aPtImg, aImgSz, *pImage, nStyle );
2680  }
2681 
2682  const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
2683 
2684  if(nEdgeBlendingPercent)
2685  {
2686  const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
2687  const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
2688  const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
2689  const BitmapEx aBlendFrame(createBlendFrame(aImgSz, nAlpha, rTopLeft, rBottomRight));
2690 
2691  if(!aBlendFrame.IsEmpty())
2692  {
2693  rRenderContext.DrawBitmapEx(aPtImg, aBlendFrame);
2694  }
2695  }
2696  }
2697 
2698  if( !maString.isEmpty() )
2699  {
2701 
2702  if ( bImage && !bLayout )
2703  nTextStyle |= DrawTextFlags::Left;
2704  else if ( GetStyle() & WB_CENTER )
2705  nTextStyle |= DrawTextFlags::Center;
2706  else if ( GetStyle() & WB_RIGHT )
2707  nTextStyle |= DrawTextFlags::Right;
2708  else
2709  nTextStyle |= DrawTextFlags::Left;
2710 
2711  tools::Rectangle aTextRect( Point( nBorder, 0 ), Size( aOutSz.Width()-2*nBorder, aOutSz.Height() ) );
2712 
2713  if ( bImage )
2714  {
2716  }
2717 
2718  MetricVector* pVector = bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : nullptr;
2719  OUString* pDisplayText = bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : nullptr;
2720  rRenderContext.DrawText( aTextRect, maString, nTextStyle, pVector, pDisplayText );
2721  }
2722 
2723  if( HasFocus() && !bLayout )
2725 }
2726 
2728 {
2729  Control::Resize();
2731  Invalidate();
2732 }
2733 
2735 {
2737  if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2740  {
2742  if( ! pWin )
2743  pWin = GetParent();
2744  pWin->Invalidate();
2745  }
2746  else
2747  Invalidate();
2749 }
2750 
2752 {
2753  HideFocus();
2754  if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2757  {
2759  if( ! pWin )
2760  pWin = GetParent();
2761  pWin->Invalidate();
2762  }
2763  else
2764  Invalidate();
2766 }
2767 
2769 {
2771  {
2772  ImplControlValue aControlValue;
2773 
2774  vcl::Window *pWin = GetParent();
2775  tools::Rectangle aParentRect(Point(0, 0), pWin->GetSizePixel());
2777  ControlState::FOCUSED, aControlValue, OUString());
2778  }
2779  Control::ShowFocus(rRect);
2780 }
2781 
2782 ImplBtn::ImplBtn( vcl::Window* pParent, WinBits nWinStyle ) :
2783  PushButton( pParent, nWinStyle )
2784 {
2785 }
2786 
2788 {
2789  if( IsEnabled() )
2790  maMBDownHdl.Call(this);
2791 }
2792 
2794  FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW ) // no drop shadow for list boxes
2795 {
2796  mpImplLB = nullptr;
2797  mnDDLineCount = 0;
2798  mbAutoWidth = false;
2799 
2801 
2802  vcl::Window * pBorderWindow = ImplGetBorderWindow();
2803  if( pBorderWindow )
2804  {
2805  SetAccessibleRole(accessibility::AccessibleRole::PANEL);
2806  pBorderWindow->SetAccessibleRole(accessibility::AccessibleRole::WINDOW);
2807  }
2808  else
2809  {
2810  SetAccessibleRole(accessibility::AccessibleRole::WINDOW);
2811  }
2812 
2813 }
2814 
2816 {
2817  disposeOnce();
2818 }
2819 
2821 {
2822  mpImplLB.clear();
2824 }
2825 
2826 
2828 {
2829  if( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
2830  {
2831  if( !GetParent()->HasChildPathFocus( true ) )
2832  EndPopupMode();
2833  }
2834 
2835  return FloatingWindow::PreNotify( rNEvt );
2836 }
2837 
2838 void ImplListBoxFloatingWindow::setPosSizePixel( long nX, long nY, long nWidth, long nHeight, PosSizeFlags nFlags )
2839 {
2840  FloatingWindow::setPosSizePixel( nX, nY, nWidth, nHeight, nFlags );
2841 
2842  // Fix #60890# ( MBA ): to be able to resize the Listbox even in its open state
2843  // after a call to Resize(), we adjust its position if necessary
2844  if ( IsReallyVisible() && ( nFlags & PosSizeFlags::Height ) )
2845  {
2846  Point aPos = GetParent()->GetPosPixel();
2847  aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
2848 
2849  if ( nFlags & PosSizeFlags::X )
2850  aPos.setX( nX );
2851 
2852  if ( nFlags & PosSizeFlags::Y )
2853  aPos.setY( nY );
2854 
2855  sal_uInt16 nIndex;
2857  }
2858 
2859 // if( !IsReallyVisible() )
2860  {
2861  // The ImplListBox does not get a Resize() as not visible.
2862  // But the windows must get a Resize(), so that the number of
2863  // visible entries is correct for PgUp/PgDown.
2864  // The number also cannot be calculated by List/Combobox, as for
2865  // this the presence of the vertical Scrollbar has to be known.
2867  static_cast<vcl::Window*>(mpImplLB)->Resize();
2868  static_cast<vcl::Window*>(mpImplLB->GetMainWindow())->Resize();
2869  }
2870 }
2871 
2873 {
2876 }
2877 
2879 {
2880  Size aFloatSz( maPrefSz );
2881 
2882  sal_Int32 nLeft, nTop, nRight, nBottom;
2883  GetBorder( nLeft, nTop, nRight, nBottom );
2884 
2885  sal_Int32 nLines = mpImplLB->GetEntryList()->GetEntryCount();
2886  if ( mnDDLineCount && ( nLines > mnDDLineCount ) )
2887  nLines = mnDDLineCount;
2888 
2889  Size aSz = mpImplLB->CalcSize( nLines );
2890  long nMaxHeight = aSz.Height() + nTop + nBottom;
2891 
2892  if ( mnDDLineCount )
2893  aFloatSz.setHeight( nMaxHeight );
2894 
2895  if( mbAutoWidth )
2896  {
2897  // AutoSize first only for width...
2898 
2899  aFloatSz.setWidth( aSz.Width() + nLeft + nRight );
2900  aFloatSz.AdjustWidth(nRight ); // adding some space looks better...
2901 
2902  if ( ( aFloatSz.Height() < nMaxHeight ) || ( mnDDLineCount && ( mnDDLineCount < mpImplLB->GetEntryList()->GetEntryCount() ) ) )
2903  {
2904  // then we also need the vertical Scrollbar
2905  long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
2906  aFloatSz.AdjustWidth(nSBWidth );
2907  }
2908 
2909  long nDesktopWidth = GetDesktopRectPixel().getWidth();
2910  if (aFloatSz.Width() > nDesktopWidth)
2911  // Don't exceed the desktop width.
2912  aFloatSz.setWidth( nDesktopWidth );
2913  }
2914 
2915  if ( aFloatSz.Height() > nMaxHeight )
2916  aFloatSz.setHeight( nMaxHeight );
2917 
2918  // Minimal height, in case height is not set to Float height.
2919  // The parent of FloatWin must be DropDown-Combo/Listbox.
2920  Size aParentSz = GetParent()->GetSizePixel();
2921  if( (!mnDDLineCount || !nLines) && ( aFloatSz.Height() < aParentSz.Height() ) )
2922  aFloatSz.setHeight( aParentSz.Height() );
2923 
2924  // do not get narrower than the parent...
2925  if( aFloatSz.Width() < aParentSz.Width() )
2926  aFloatSz.setWidth( aParentSz.Width() );
2927 
2928  // align height to entries...
2929  long nInnerHeight = aFloatSz.Height() - nTop - nBottom;
2930  long nEntryHeight = mpImplLB->GetEntryHeightWithMargin();
2931  if ( nInnerHeight % nEntryHeight )
2932  {
2933  nInnerHeight /= nEntryHeight;
2934  nInnerHeight++;
2935  nInnerHeight *= nEntryHeight;
2936  aFloatSz.setHeight( nInnerHeight + nTop + nBottom );
2937  }
2938 
2939  if (aFloatSz.Width() < aSz.Width())
2940  {
2941  // The max width of list box entries exceeds the window width.
2942  // Account for the scroll bar height.
2943  long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
2944  aFloatSz.AdjustHeight(nSBWidth );
2945  }
2946 
2947  return aFloatSz;
2948 }
2949 
2950 void ImplListBoxFloatingWindow::StartFloat( bool bStartTracking )
2951 {
2952  if( IsInPopupMode() )
2953  return;
2954 
2955  Size aFloatSz = CalcFloatSize();
2956 
2957  SetSizePixel( aFloatSz );
2959 
2960  sal_Int32 nPos = mpImplLB->GetEntryList()->GetSelectedEntryPos( 0 );
2962 
2963  Size aSz = GetParent()->GetSizePixel();
2964  Point aPos = GetParent()->GetPosPixel();
2965  aPos = GetParent()->GetParent()->OutputToScreenPixel( aPos );
2966  // FIXME: this ugly hack is for Mac/Aqua
2967  // should be replaced by a real mechanism to place the float rectangle
2968  if( ImplGetSVData()->maNWFData.mbNoFocusRects &&
2970  {
2971  const sal_Int32 nLeft = 4, nTop = 4, nRight = 4, nBottom = 4;
2972  aPos.AdjustX(nLeft );
2973  aPos.AdjustY(nTop );
2974  aSz.AdjustWidth( -(nLeft + nRight) );
2975  aSz.AdjustHeight( -(nTop + nBottom) );
2976  }
2977  tools::Rectangle aRect( aPos, aSz );
2978 
2979  // check if the control's parent is un-mirrored which is the case for form controls in a mirrored UI
2980  // where the document is unmirrored
2981  // because StartPopupMode() expects a rectangle in mirrored coordinates we have to re-mirror
2982  vcl::Window *pGrandparent = GetParent()->GetParent();
2983  const OutputDevice *pGrandparentOutDev = pGrandparent->GetOutDev();
2984 
2985  if( pGrandparent->ImplIsAntiparallel() )
2986  pGrandparentOutDev->ReMirror( aRect );
2987 
2988  // mouse-button right: close the List-Box-Float-win and don't stop the handling fdo#84795
2990 
2991  if( nPos != LISTBOX_ENTRY_NOTFOUND )
2992  mpImplLB->ShowProminentEntry( nPos );
2993 
2994  if( bStartTracking )
2996 
2999 
3001 
3002 }
3003 
3004 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual Point GetPosPixel() const
Definition: window.cxx:2792
tools::Rectangle maFocusRect
Definition: listbox.hxx:542
long Width() const
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:795
void SetPos(const Point &rPoint)
bool IsControlBackground() const
Definition: window2.cxx:1087
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:148
virtual const Wallpaper & GetDisplayBackground() const
Definition: window.cxx:3051
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
long GetWidth() const
void SetMRUEntries(const OUString &rEntries, sal_Unicode cSep)
const Wallpaper & GetBackground() const
Definition: outdev.hxx:643
sal_Int32 NaturalSortCompare(const OUString &rA, const OUString &rB)
void StartPopupMode(const tools::Rectangle &rRect, FloatWinPopupFlags nFlags)
Definition: floatwin.cxx:753
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
long GetHeight() 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:137
OUString maString
Definition: listbox.hxx:539
static OUString filterFormattingChars(const OUString &)
Definition: i18nhelp.cxx:93
virtual void FillLayoutData() const override
long AdjustWidth(long n)
sal_Int32 GetSelectedEntryPos(sal_Int32 nIndex) const
constexpr long gnBorder
Definition: imp_listbox.cxx:50
void SetUserItemSize(const Size &rSz)
const CommandEvent * GetCommandEvent() const
Definition: event.hxx:327
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:1166
std::unique_ptr< ContentProperties > pData
void SetEntryFlags(sal_Int32 nPos, ListBoxEntryFlags nFlags)
virtual ~ImplListBoxWindow() override
A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for refer...
Definition: button.hxx:32
long Height() const
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
long getWidth() const
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
SAL_DLLPRIVATE void ImplClearLayoutData() const
Definition: ctrl.cxx:330
long AdjustLeft(long nHorzMoveDelta)
tools::Rectangle maFocusRect
Definition: listbox.hxx:178
sal_uIntPtr sal_uLong
long mnLeft
output from column on
Definition: listbox.hxx:200
void disposeAndClear()
Definition: vclptr.hxx:200
long mnMaxTxtWidth
Maximum width of a text item Entry without Image.
Definition: listbox.hxx:183
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:706
constexpr sal_uInt16 KEY_A
Definition: keycodes.hxx:56
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:398
sal_Int64 n
SAL_DLLPRIVATE vcl::Window * ImplGetBorderWindow() const
Definition: window2.cxx:875
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:2395
virtual void SetSizePixel(const Size &rNewSize)
Definition: window2.cxx:1262
WinBits const WB_RIGHT
#define IMG_TXT_DISTANCE
Definition: listbox.hxx:40
SAL_DLLPRIVATE WindowImpl * ImplGetWindowImpl() const
Definition: window.hxx:563
sal_Int32 GetEntryPosForPoint(const Point &rPoint) const
void CompatStateChanged(StateChangedType nStateChange)
Definition: window.cxx:3828
bool IsShift() const
Definition: event.hxx:155
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:701
const Color & GetFieldRolloverTextColor() const
sal_uInt16 GetCode() const
Definition: keycod.hxx:51
void SelectEntry(sal_Int32 nPos, bool bSelect)
Definition: imp_listbox.cxx:84
sal_Int32 GetSelectedEntryCount() const
PosSizeFlags
Definition: window.hxx:140
DataChangedEventType GetType() const
Definition: event.hxx:357
long GetMaxEntryWidth() const
Definition: listbox.hxx:472
The invalidated area is updated immediately.
tools::Rectangle GetDesktopRectPixel() const
Definition: window.cxx:2797
sal_Int32 mnMRUCount
Definition: listbox.hxx:93
long CalcZoom(long n) const
Definition: window2.cxx:397
bool mbMouseMoveSelect
Select at MouseMove.
Definition: listbox.hxx:213
long GetLeftIndent() const
Definition: listbox.hxx:454
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:1082
const CommandWheelData * GetWheelData() const
constexpr sal_uInt16 KEY_SPACE
Definition: keycodes.hxx:123
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:968
bool mbCenter
center Text output
Definition: listbox.hxx:218
void PaintImmediately()
Definition: paint.cxx:1286
bool HandleScrollCommand(const CommandEvent &rCmd, ScrollBar *pHScrl, ScrollBar *pVScrl)
Definition: window2.cxx:609
void SetEntryFlags(sal_Int32 nPos, ListBoxEntryFlags nFlags)
long AdjustHeight(long n)
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:236
sal_Int32 FindEntry(const OUString &rStr, bool bSearchMRUArea=false) const
void StartTracking(StartTrackingFlags nFlags=StartTrackingFlags::NONE)
Definition: window2.cxx:244
bool HasChildPathFocus(bool bSystemWindow=false) const
Definition: window.cxx:2988
bool IsNativeControlSupported(ControlType nType, ControlPart nPart) const
Query the platform layer for control support.
const vcl::Font & GetFieldFont() const
const Color & GetFieldTextColor() const
int mnListBoxEntryMargin
Definition: svdata.hxx:339
void ImplUpdateEntryMetrics(ImplEntryType &rEntry)
constexpr sal_uInt16 KEY_UP
Definition: keycodes.hxx:111
#define LISTBOX_ENTRY_NOTFOUND
Definition: lstbox.hxx:38
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
long GetEntryHeightWithMargin() const
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
virtual void setPosSizePixel(long nX, long nY, long nWidth, long nHeight, PosSizeFlags nFlags=PosSizeFlags::All) override
void RemoveEntry(sal_Int32 nPos)
const Fraction & GetZoom() const
Definition: window2.cxx:1210
void * GetEntryData(sal_Int32 nPos) const
StateChangedType
Definition: window.hxx:317
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:1809
virtual void ApplySettings(vcl::RenderContext &rRenderContext) override
sal_uInt16 GetEdgeBlending() const
virtual void setPosSizePixel(long nX, long nY, long nWidth, long nHeight, PosSizeFlags nFlags=PosSizeFlags::All)
Definition: window.cxx:2667
sal_uInt16 GetClicks() const
Definition: event.hxx:123
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:409
void Enable(bool bEnable=true, bool bChild=true)
Definition: window.cxx:2426
SAL_DLLPRIVATE void ReMirror(Point &rPoint) const
Definition: outdev.cxx:604
this flags lets the item be drawn disabled (e.g.
VclPtr< ImplListBox > mpImplLB
Definition: listbox.hxx:500
void SetSymbol(SymbolType eSymbol)
Definition: button.cxx:1487
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
long mnTextHeight
text height
Definition: listbox.hxx:201
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
bool IsControlForeground() const
Definition: window2.cxx:1077
bool IsEnterWindow() const
Definition: event.hxx:135
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:945
AllSettingsFlags GetFlags() const
Definition: event.hxx:358
constexpr sal_uInt16 KEY_PAGEUP
Definition: keycodes.hxx:116
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
virtual void Resize() override
sal_uInt16 GetModifier() const
Definition: keycod.hxx:54
long mnHeight
Definition: listbox.hxx:58
const void * StringEntryIdentifier
Link< LinkParamNone *, void > maListItemSelectHdl
Definition: listbox.hxx:231
long Top() const
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:88
const Color & GetEdgeBlendingBottomRightColor() const
Image GetEntryImage(sal_Int32 nPos) const
long mnMaxTxtHeight
Maximum height of a text item.
Definition: listbox.hxx:182
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:1072
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:199
void ShowProminentEntry(sal_Int32 nPos)
Definition: listbox.hxx:450
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:76
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:51
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
void ScrollHorz(long nDiff)
bool IsLeaveWindow() const
Definition: event.hxx:137
int i
virtual void Resize() override
bool IsEntryPosSelected(sal_Int32 nIndex) const
bool IsNativeWidgetEnabled() const
Definition: window.cxx:3679
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:497
virtual bool PreNotify(NotifyEvent &rNEvt) override
WinBits const WB_SIMPLEMODE
void SetRangeMax(long nNewRange)
Definition: scrbar.cxx:1333
long mnMaxWidth
Maximum width of an entry.
Definition: listbox.hxx:189
IMPL_LINK(ImplListBox, ScrollBarHdl, ScrollBar *, pSB, void)
void SetVisibleSize(long nNewSize)
Definition: scrbar.cxx:1376
bool mbMulti
MultiListBox.
Definition: listbox.hxx:208
void ImplCheckScrollBars()
Link< ImplListBoxWindow *, void > maDoubleClickHdl
Definition: listbox.hxx:227
void SetSize(const Size &rSize)
void SetControlForeground()
Definition: window2.cxx:457
CommandWheelMode GetMode() const
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
Definition: paint.cxx:1162
SAL_DLLPRIVATE bool ImplIsAntiparallel() const
Definition: outdev.cxx:588
void SetUpdateMode(bool bUpdate)
Definition: window.cxx:2951
Size GetOutputSize() const
Definition: outdev.hxx:450
sal_Int32 mnSelectionAnchor
Definition: listbox.hxx:90
long mnMaxHeight
Maximum height of an entry.
Definition: listbox.hxx:190
ImplListBox(vcl::Window *pParent, WinBits nWinStyle)
bool IsUpdateMode() const
Definition: window2.cxx:1173
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:302
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
const Color & GetFieldColor() const
CommandEventId GetCommand() const
const Color & GetLineColor() const
Definition: outdev.hxx:630
VclPtr< ScrollBarBox > mpScrollBarBox
Definition: listbox.hxx:382
void SetZoom(const Fraction &rZoom)
Definition: window2.cxx:365
sal_uInt16 GetModifier() const
Size CalcSize(sal_Int32 nMaxLines) const
void SetTextColor(const Color &rColor)
Definition: text.cxx:666
long Bottom() const
long GetEntryHeight(sal_Int32 nPos) const
constexpr sal_uInt16 KEY_PAGEDOWN
Definition: keycodes.hxx:117
long const nBorder
DrawTextFlags ImplGetTextStyle() const
bool IsZoom() const
Definition: window2.cxx:1215
void SetEdgeBlending(bool bNew)
Definition: listbox.hxx:364
void ImplDoPaint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect)
MouseNotifyEvent GetType() const
Definition: event.hxx:303
void SetPageSize(long nNewSize)
Definition: scrbar.hxx:125
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:142
bool GetEdgeBlending() const
Definition: listbox.hxx:573
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:489
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:153
bool mbSort
ListBox sorted.
Definition: listbox.hxx:206
virtual void LoseFocus()
Definition: window.cxx:1849
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
std::unique_ptr< SalLayout > ImplLayout(const OUString &, sal_Int32 nIndex, sal_Int32 nLen, const Point &rLogicPos=Point(0, 0), long nLogicWidth=0, const long *pLogicDXArray=nullptr, SalLayoutFlags flags=SalLayoutFlags::NONE, vcl::TextLayoutCache const *=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
Definition: text.cxx:1253
void GrabFocus()
Definition: window.cxx:2960
Link< UserDrawEvent *, void > maUserDrawHdl
Definition: listbox.hxx:228
long GetTextHeight() const
Height where any character of the current font fits; in logic coordinates.
Definition: text.cxx:903
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:1097
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:263
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:1268
vcl::Window * GetWindow(GetWindowType nType) const
Definition: stacking.cxx:1039
constexpr sal_uInt16 KEY_RIGHT
Definition: keycodes.hxx:113
#define MULTILINE_ENTRY_DRAW_FLAGS
Definition: imp_listbox.cxx:46
void SetLineSize(long nNewSize)
Definition: scrbar.hxx:123
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:1186
VclPtr< ScrollBar > mpVScrollBar
Definition: listbox.hxx:381
bool IsMouseMoveSelect() const
Definition: listbox.hxx:335
long mnMaxImgWidth
Maximum width of an image item.
Definition: listbox.hxx:187
virtual void KeyInput(const KeyEvent &rKEvt)
Definition: window.cxx:1799
const LanguageTag & getLocale()
const vcl::I18nHelper & GetLocaleI18nHelper() const
bool mbUseNativeFocus
Definition: window.h:317
void GetBorder(sal_Int32 &rLeftBorder, sal_Int32 &rTopBorder, sal_Int32 &rRightBorder, sal_Int32 &rBottomBorder) const
Definition: window.cxx:2417
void * mpUserData
Definition: listbox.hxx:55
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:54
virtual void Scroll(long nHorzScroll, long nVertScroll, ScrollFlags nFlags=ScrollFlags::NONE)
Definition: window.cxx:2924
void Erase()
Definition: wallpaper.cxx:103
bool IsShift() const
Definition: keycod.hxx:56
bool IsUserDrawEnabled() const
Definition: listbox.hxx:327
bool IsMouseOver() const
Definition: mouse.cxx:606
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
const ImplEntryType * GetEntryPtr(sal_Int32 nPos) const
Definition: listbox.hxx:113
Definition: ctrl.hxx:33
long GetDelta() const
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:39
ListBoxEntryFlags
Definition: lstbox.hxx:48
bool IsSynthetic() const
Definition: event.hxx:139
virtual void GetFocus()
Definition: window.cxx:1835
const Color & GetButtonTextColor() const
bool mbNoFocusRects
Definition: svdata.hxx:320
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)
WinBits const WB_BORDER
unsigned char sal_uInt8
bool bIsEnabled
const MouseEvent * GetMouseEvent() const
Definition: event.hxx:319
std::unique_ptr< vcl::ImplControlData > mpControlData
Definition: ctrl.hxx:36
virtual void GetFocus() override
sal_Int32 mnLastSelected
Definition: listbox.hxx:89
bool IsVisible() const
Definition: window2.cxx:1102
virtual vcl::StringEntryIdentifier CurrentEntry(OUString &_out_entryText) const override
returns the current entry in the list of searchable strings.
sal_Int32 mnPopupModeStartSaveSelection
Definition: listbox.hxx:503
long mnMaxImgHeight
Maximum height of an image item.
Definition: listbox.hxx:188
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:576
bool IsLeft() const
Definition: event.hxx:146
void SetScrollHdl(const Link< ScrollBar *, void > &rLink)
Definition: scrbar.hxx:133
Definition: image.hxx:39
bool IsMod1() const
Definition: keycod.hxx:58
long GetAddedHeight(sal_Int32 nEndIndex, sal_Int32 nBeginIndex) const
helper: add up heights up to index nEndIndex.
static VclPtr< reference_type > Create(Arg &&...arg)
A construction helper for VclPtr.
Definition: vclptr.hxx:127
long GetEntryHeightWithMargin() const
Definition: listbox.hxx:471
long mnMaxImgTxtWidth
Maximum width of a text item Entry AND Image.
Definition: listbox.hxx:185
Reference< XComponentContext > getProcessComponentContext()
ImplListBoxWindow(vcl::Window *pParent, WinBits nWinStyle)
bool IsGrabFocusAllowed() const
Definition: listbox.hxx:298
const Point & GetPosPixel() const
Definition: event.hxx:120
sal_Int32 mnImages
Definition: listbox.hxx:91
WinBits const WB_AUTOHSCROLL
long getHeightWithMargin() const
virtual void GetFocus() override
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:892
sal_Int32 InsertEntry(sal_Int32 nPos, ImplEntryType *pNewEntry)
virtual bool EventNotify(NotifyEvent &rNEvt) override
Event to pass information for UserDraw() handling eg. in comboboxes.
Definition: event.hxx:218
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:1122
#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:265
OUString GetMRUEntries(sal_Unicode cSep) const
WinBits GetStyle() const
Definition: window2.cxx:953
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:449
OUString GetEntryText(sal_Int32 nPos) const
constexpr sal_uInt16 KEY_LEFT
Definition: keycodes.hxx:112
Point OutputToScreenPixel(const Point &rPos) const
Definition: window.cxx:2804
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 SetLeftIndent(long n)
void SetAccessibleRole(sal_uInt16 nRole)
long GetScrollBarSize() const
bool mbInUserDraw
In UserDraw.
Definition: listbox.hxx:216
const MouseEvent & GetMouseEvent() const
Definition: event.hxx:259
bool IsReallyVisible() const
Definition: window2.cxx:1107
vcl::Font GetControlFont() const
Definition: window2.cxx:438
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:2965
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:3790
void setWidth(long nWidth)
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:927
sal_Int32 InsertEntry(sal_Int32 nPos, ImplEntryType *pNewEntry, bool bSort)
sal_Int32 nState
DrawImageFlags
Definition: outdev.hxx:170
virtual void SetPosPixel(const Point &rNewPos)
Definition: window2.cxx:1257
aStr
virtual void Resize() override
Definition: syswin.cxx:1053
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
void SetThumbPos(long nThumbPos)
Definition: scrbar.cxx:1362
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:35
Link< LinkParamNone *, void > maSelectHdl
Definition: listbox.hxx:225
bool IsMod1() const
Definition: event.hxx:157
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:2181
void setHeight(long nHeight)
bool mbRight
right align Text output
Definition: listbox.hxx:219
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo