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