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