LibreOffice Module desktop (master)  1
dp_gui_extlistbox.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 <svtools/controldims.hxx>
21 
22 #include <dp_shared.hxx>
23 #include <strings.hrc>
24 #include "dp_gui.h"
25 #include "dp_gui_extlistbox.hxx"
26 #include "dp_gui_theextmgr.hxx"
27 #include "dp_gui_dialog2.hxx"
28 #include <dp_dependencies.hxx>
29 #include <bitmaps.hlst>
30 
32 #include <com/sun/star/i18n/CollatorOptions.hpp>
33 #include <com/sun/star/deployment/DependencyException.hpp>
34 #include <com/sun/star/deployment/DeploymentException.hpp>
35 #include <com/sun/star/deployment/ExtensionRemovedException.hpp>
36 #include <cppuhelper/weakref.hxx>
38 #include <vcl/event.hxx>
39 #include <vcl/settings.hxx>
40 #include <vcl/builderfactory.hxx>
41 #include <vcl/commandevent.hxx>
42 #include <algorithm>
43 
44 #define USER_PACKAGE_MANAGER "user"
45 #define SHARED_PACKAGE_MANAGER "shared"
46 
47 using namespace ::com::sun::star;
48 
49 namespace dp_gui {
50 
51 namespace {
52 
53 struct FindWeakRef
54 {
55  const uno::Reference<deployment::XPackage> m_extension;
56 
57  explicit FindWeakRef( uno::Reference<deployment::XPackage> const & ext): m_extension(ext) {}
58  bool operator () (uno::WeakReference< deployment::XPackage > const & ref);
59 };
60 
61 bool FindWeakRef::operator () (uno::WeakReference< deployment::XPackage > const & ref)
62 {
63  const uno::Reference<deployment::XPackage> ext(ref);
64  return ext == m_extension;
65 }
66 
67 } // end namespace
68 
69 // struct Entry_Impl
70 
71 Entry_Impl::Entry_Impl( const uno::Reference< deployment::XPackage > &xPackage,
72  const PackageState eState, const bool bReadOnly ) :
73  m_bActive( false ),
74  m_bLocked( bReadOnly ),
75  m_bHasOptions( false ),
76  m_bUser( false ),
77  m_bShared( false ),
78  m_bNew( false ),
79  m_bChecked( false ),
80  m_bMissingDeps( false ),
81  m_bHasButtons( false ),
82  m_bMissingLic( false ),
83  m_eState( eState ),
84  m_pPublisher( nullptr ),
85  m_xPackage( xPackage )
86 {
87  try
88  {
89  m_sTitle = xPackage->getDisplayName();
90  m_sVersion = xPackage->getVersion();
91  m_sDescription = xPackage->getDescription();
92  m_sLicenseText = xPackage->getLicenseText();
93 
94  beans::StringPair aInfo( m_xPackage->getPublisherInfo() );
95  m_sPublisher = aInfo.First;
96  m_sPublisherURL = aInfo.Second;
97 
98  // get the icons for the package if there are any
99  uno::Reference< graphic::XGraphic > xGraphic = xPackage->getIcon( false );
100  if ( xGraphic.is() )
101  m_aIcon = Image( xGraphic );
102 
103  if ( eState == AMBIGUOUS )
104  m_sErrorText = DpResId( RID_STR_ERROR_UNKNOWN_STATUS );
105  else if ( eState == NOT_REGISTERED )
107  }
108  catch (const deployment::ExtensionRemovedException &) {}
109  catch (const uno::RuntimeException &) {}
110 }
111 
112 
114 {}
115 
116 
117 sal_Int32 Entry_Impl::CompareTo( const CollatorWrapper *pCollator, const TEntry_Impl& rEntry ) const
118 {
119  sal_Int32 eCompare = pCollator->compareString( m_sTitle, rEntry->m_sTitle );
120  if ( eCompare == 0 )
121  {
122  eCompare = m_sVersion.compareTo( rEntry->m_sVersion );
123  if ( eCompare == 0 )
124  {
125  sal_Int32 nCompare = m_xPackage->getRepositoryName().compareTo( rEntry->m_xPackage->getRepositoryName() );
126  if ( nCompare < 0 )
127  eCompare = -1;
128  else if ( nCompare > 0 )
129  eCompare = 1;
130  }
131  }
132  return eCompare;
133 }
134 
135 
137 {
138  try {
139  m_xPackage->checkDependencies( uno::Reference< ucb::XCommandEnvironment >() );
140  }
141  catch ( const deployment::DeploymentException &e )
142  {
143  deployment::DependencyException depExc;
144  if ( e.Cause >>= depExc )
145  {
146  OUStringBuffer aMissingDep( DpResId( RID_STR_ERROR_MISSING_DEPENDENCIES ) );
147  for ( sal_Int32 i = 0; i < depExc.UnsatisfiedDependencies.getLength(); ++i )
148  {
149  aMissingDep.append("\n");
150  aMissingDep.append(dp_misc::Dependencies::getErrorText( depExc.UnsatisfiedDependencies[i]));
151  }
152  aMissingDep.append("\n");
153  m_sErrorText = aMissingDep.makeStringAndClear();
154  m_bMissingDeps = true;
155  }
156  }
157 }
158 
159 // ExtensionRemovedListener
160 
161 void ExtensionRemovedListener::disposing( lang::EventObject const & rEvt )
162 {
163  uno::Reference< deployment::XPackage > xPackage( rEvt.Source, uno::UNO_QUERY );
164 
165  if ( xPackage.is() )
166  {
167  m_pParent->removeEntry( xPackage );
168  }
169 }
170 
171 
173 {
174 }
175 
176 
177 // ExtensionBox_Impl
179  IExtensionListBox( pParent ),
180  m_bHasScrollBar( false ),
181  m_bHasActive( false ),
182  m_bNeedsRecalc( true ),
183  m_bInCheckMode( false ),
184  m_bAdjustActive( false ),
185  m_bInDelete( false ),
186  m_nActive( 0 ),
187  m_nTopIndex( 0 ),
188  m_nActiveHeight( 0 ),
189  m_aSharedImage(StockImage::Yes, RID_BMP_SHARED),
190  m_aLockedImage(StockImage::Yes, RID_BMP_LOCKED),
191  m_aWarningImage(StockImage::Yes, RID_BMP_WARNING),
192  m_aDefaultImage(StockImage::Yes, RID_BMP_EXTENSION),
193  m_pScrollBar( nullptr ),
194  m_pManager( nullptr )
195 {
196  Init();
197 }
198 
200 {
202  m_pScrollBar->SetScrollHdl( LINK( this, ExtensionBox_Impl, ScrollHdl ) );
204 
205  SetPaintTransparent( true );
207  long nIconHeight = 2*TOP_OFFSET + SMALL_ICON_SIZE;
208  long nTitleHeight = 2*TOP_OFFSET + GetTextHeight();
209  if ( nIconHeight < nTitleHeight )
210  m_nStdHeight = nTitleHeight;
211  else
212  m_nStdHeight = nIconHeight;
213  m_nStdHeight += GetTextHeight() + TOP_OFFSET;
214 
215  nIconHeight = ICON_HEIGHT + 2*TOP_OFFSET + 1;
216  if ( m_nStdHeight < nIconHeight )
217  m_nStdHeight = nIconHeight;
218 
220 
221  const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
222  if( IsControlBackground() )
223  SetBackground( GetControlBackground() );
224  else
225  SetBackground( rStyleSettings.GetFieldColor() );
226 
228 
229  m_pLocale.reset( new lang::Locale( Application::GetSettings().GetLanguageTag().getLocale() ) );
231  m_pCollator->loadDefaultCollator( *m_pLocale, i18n::CollatorOptions::CollatorOptions_IGNORE_CASE );
232 
233  Show();
234 }
235 
236 
238 {
239  disposeOnce();
240 }
241 
243 {
244  if ( ! m_bInDelete )
245  DeleteRemoved();
246 
247  m_bInDelete = true;
248 
249  for (auto const& entry : m_vEntries)
250  {
251  entry->m_pPublisher.disposeAndClear();
252  entry->m_xPackage->removeEventListener( m_xRemoveListener.get() );
253  }
254 
255  m_vEntries.clear();
256 
258 
259  m_xRemoveListener.clear();
260 
261  m_pLocale.reset();
262  m_pCollator.reset();
263  ::svt::IExtensionListBox::dispose();
264 }
265 
266 
268 {
269  return static_cast< sal_Int32 >( m_vEntries.size() );
270 }
271 
272 
274 {
275  if ( m_bHasActive )
276  {
277  OSL_ASSERT( m_nActive >= -1);
278  return static_cast< sal_Int32 >( m_nActive );
279  }
280  else
281  return ENTRY_NOTFOUND;
282 }
283 
284 
285 // Title + description
286 void ExtensionBox_Impl::CalcActiveHeight( const long nPos )
287 {
288  const ::osl::MutexGuard aGuard( m_entriesMutex );
289 
290  // get title height
291  long aTextHeight;
292  long nIconHeight = 2*TOP_OFFSET + SMALL_ICON_SIZE;
293  long nTitleHeight = 2*TOP_OFFSET + GetTextHeight();
294  if ( nIconHeight < nTitleHeight )
295  aTextHeight = nTitleHeight;
296  else
297  aTextHeight = nIconHeight;
298 
299  // calc description height
300  Size aSize = GetOutputSizePixel();
301  if ( m_bHasScrollBar )
302  aSize.AdjustWidth( -(m_pScrollBar->GetSizePixel().Width()) );
303 
304  aSize.AdjustWidth( -(ICON_OFFSET) );
305  aSize.setHeight( 10000 );
306 
307  OUString aText( m_vEntries[ nPos ]->m_sErrorText );
308  if ( !aText.isEmpty() )
309  aText += "\n";
310  aText += m_vEntries[ nPos ]->m_sDescription;
311 
312  tools::Rectangle aRect = GetTextRect( tools::Rectangle( Point(), aSize ), aText,
313  DrawTextFlags::MultiLine | DrawTextFlags::WordBreak );
314  aTextHeight += aRect.GetHeight();
315 
316  if ( aTextHeight < m_nStdHeight )
317  aTextHeight = m_nStdHeight;
318 
319  m_nActiveHeight = aTextHeight;
320 
321  if ( m_vEntries[ nPos ]->m_bHasButtons )
322  m_nActiveHeight += 2;
323 }
324 
326 {
327  const ::osl::MutexGuard aGuard( m_entriesMutex );
328 
329  Size aSize( GetOutputSizePixel() );
330 
331  if ( m_bHasScrollBar )
332  aSize.AdjustWidth( -(m_pScrollBar->GetSizePixel().Width()) );
333 
334  if ( m_vEntries[ nPos ]->m_bActive )
335  aSize.setHeight( m_nActiveHeight );
336  else
337  aSize.setHeight( m_nStdHeight );
338 
339  Point aPos( 0, -m_nTopIndex + nPos * m_nStdHeight );
340  if ( m_bHasActive && ( nPos < m_nActive ) )
341  aPos.AdjustY(m_nActiveHeight - m_nStdHeight );
342 
343  return tools::Rectangle( aPos, aSize );
344 }
345 
346 
348 {
349  const ::osl::MutexGuard aGuard( m_entriesMutex );
350 
351  m_bInDelete = true;
352 
353  if ( ! m_vRemovedEntries.empty() )
354  {
355  for (auto const& removedEntry : m_vRemovedEntries)
356  {
357  removedEntry->m_pPublisher.disposeAndClear();
358  }
359 
360  m_vRemovedEntries.clear();
361  }
362 
363  m_bInDelete = false;
364 }
365 
366 
367 //This function may be called with nPos < 0
368 void ExtensionBox_Impl::selectEntry( const long nPos )
369 {
370  bool invalidate = false;
371  {
372  //ToDo we should not use the guard at such a big scope here.
373  //Currently it is used to guard m_vEntries and m_nActive. m_nActive will be
374  //modified in this function.
375  //It would be probably best to always use a copy of m_vEntries
376  //and some other state variables from ExtensionBox_Impl for
377  //the whole painting operation. See issue i86993
378  ::osl::MutexGuard guard(m_entriesMutex);
379 
380  if ( m_bInCheckMode )
381  return;
382 
383  if ( m_bHasActive )
384  {
385  if ( nPos == m_nActive )
386  return;
387 
388  m_bHasActive = false;
389  m_vEntries[ m_nActive ]->m_bActive = false;
390  }
391 
392  if ( ( nPos >= 0 ) && ( nPos < static_cast<long>(m_vEntries.size()) ) )
393  {
394  m_bHasActive = true;
395  m_nActive = nPos;
396  m_vEntries[ nPos ]->m_bActive = true;
397 
398  if ( IsReallyVisible() )
399  {
400  m_bAdjustActive = true;
401  }
402  }
403 
404  if ( IsReallyVisible() )
405  {
406  m_bNeedsRecalc = true;
407  invalidate = true;
408  }
409  }
410 
411  if (invalidate)
412  {
413  SolarMutexGuard g;
414  Invalidate();
415  }
416 }
417 
418 
419 void ExtensionBox_Impl::DrawRow(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, const TEntry_Impl& rEntry)
420 {
421  const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
422 
423  if (rEntry->m_bActive)
424  rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor());
425  else if ((rEntry->m_eState != REGISTERED) && (rEntry->m_eState != NOT_AVAILABLE))
426  rRenderContext.SetTextColor(rStyleSettings.GetDisableColor());
427  else if (IsControlForeground())
428  rRenderContext.SetTextColor(GetControlForeground());
429  else
430  rRenderContext.SetTextColor(rStyleSettings.GetFieldTextColor());
431 
432  if (rEntry->m_bActive)
433  {
434  rRenderContext.SetLineColor();
435  rRenderContext.SetFillColor(rStyleSettings.GetHighlightColor());
436  rRenderContext.DrawRect(rRect);
437  }
438  else
439  {
440  if (IsControlBackground())
441  rRenderContext.SetBackground(GetControlBackground());
442  else
443  rRenderContext.SetBackground(rStyleSettings.GetFieldColor());
444 
445  rRenderContext.SetTextFillColor();
446  rRenderContext.Erase(rRect);
447  }
448 
449  // Draw extension icon
450  Point aPos( rRect.TopLeft() );
451  aPos += Point(TOP_OFFSET, TOP_OFFSET);
452  Image aImage;
453  if (!rEntry->m_aIcon)
454  aImage = m_aDefaultImage;
455  else
456  aImage = rEntry->m_aIcon;
457  Size aImageSize = aImage.GetSizePixel();
458  if ((aImageSize.Width() <= ICON_WIDTH ) && ( aImageSize.Height() <= ICON_HEIGHT ) )
459  rRenderContext.DrawImage(Point(aPos.X() + ((ICON_WIDTH - aImageSize.Width()) / 2),
460  aPos.Y() + ((ICON_HEIGHT - aImageSize.Height()) / 2)),
461  aImage);
462  else
463  rRenderContext.DrawImage(aPos, Size(ICON_WIDTH, ICON_HEIGHT), aImage);
464 
465  // Setup fonts
466  vcl::Font aStdFont(rRenderContext.GetFont());
467  vcl::Font aBoldFont(aStdFont);
468  aBoldFont.SetWeight(WEIGHT_BOLD);
469  rRenderContext.SetFont(aBoldFont);
470  long aTextHeight = rRenderContext.GetTextHeight();
471 
472  // Init publisher link here
473  if (!rEntry->m_pPublisher && !rEntry->m_sPublisher.isEmpty())
474  {
475  rEntry->m_pPublisher = VclPtr<FixedHyperlink>::Create(this);
476  rEntry->m_pPublisher->SetBackground();
477  rEntry->m_pPublisher->SetPaintTransparent(true);
478  rEntry->m_pPublisher->SetURL(rEntry->m_sPublisherURL);
479  rEntry->m_pPublisher->SetText(rEntry->m_sPublisher);
480  Size aSize = FixedText::CalcMinimumTextSize(rEntry->m_pPublisher);
481  rEntry->m_pPublisher->SetSizePixel(aSize);
482  }
483 
484  // Get max title width
485  long nMaxTitleWidth = rRect.GetWidth() - ICON_OFFSET;
486  nMaxTitleWidth -= (2 * SMALL_ICON_SIZE) + (4 * SPACE_BETWEEN);
487  if (rEntry->m_pPublisher)
488  {
489  nMaxTitleWidth -= rEntry->m_pPublisher->GetSizePixel().Width() + (2 * SPACE_BETWEEN);
490  }
491 
492  long aVersionWidth = rRenderContext.GetTextWidth(rEntry->m_sVersion);
493  long aTitleWidth = rRenderContext.GetTextWidth(rEntry->m_sTitle) + (aTextHeight / 3);
494 
495  aPos = rRect.TopLeft() + Point(ICON_OFFSET, TOP_OFFSET);
496 
497  if (aTitleWidth > nMaxTitleWidth - aVersionWidth)
498  {
499  aTitleWidth = nMaxTitleWidth - aVersionWidth - (aTextHeight / 3);
500  OUString aShortTitle = rRenderContext.GetEllipsisString(rEntry->m_sTitle, aTitleWidth);
501  rRenderContext.DrawText(aPos, aShortTitle);
502  aTitleWidth += (aTextHeight / 3);
503  }
504  else
505  rRenderContext.DrawText(aPos, rEntry->m_sTitle);
506 
507  rRenderContext.SetFont(aStdFont);
508  rRenderContext.DrawText(Point(aPos.X() + aTitleWidth, aPos.Y()), rEntry->m_sVersion);
509 
510  long nIconHeight = TOP_OFFSET + SMALL_ICON_SIZE;
511  long nTitleHeight = TOP_OFFSET + GetTextHeight();
512  if ( nIconHeight < nTitleHeight )
513  aTextHeight = nTitleHeight;
514  else
515  aTextHeight = nIconHeight;
516 
517  // draw description
518  OUString sDescription;
519  if (!rEntry->m_sErrorText.isEmpty())
520  {
521  if (rEntry->m_bActive)
522  sDescription = rEntry->m_sErrorText + "\n" + rEntry->m_sDescription;
523  else
524  sDescription = rEntry->m_sErrorText;
525  }
526  else
527  sDescription = rEntry->m_sDescription;
528 
529  aPos.AdjustY(aTextHeight );
530  if (rEntry->m_bActive)
531  {
532  long nExtraHeight = 0;
533 
534  if (rEntry->m_bHasButtons)
535  nExtraHeight = 2;
536 
537  rRenderContext.DrawText(tools::Rectangle(aPos.X(), aPos.Y(), rRect.Right(), rRect.Bottom() - nExtraHeight),
538  sDescription, DrawTextFlags::MultiLine | DrawTextFlags::WordBreak );
539  }
540  else
541  {
542  //replace LF to space, so words do not stick together in one line view
543  sDescription = sDescription.replace(0x000A, ' ');
544  const long nWidth = GetTextWidth( sDescription );
545  if (nWidth > rRect.GetWidth() - aPos.X())
546  sDescription = rRenderContext.GetEllipsisString(sDescription, rRect.GetWidth() - aPos.X());
547  rRenderContext.DrawText(aPos, sDescription);
548  }
549 
550  // Draw publisher link
551  if (rEntry->m_pPublisher)
552  {
553  rEntry->m_pPublisher->Show();
554  aPos = rRect.TopLeft() + Point( ICON_OFFSET + nMaxTitleWidth + (2*SPACE_BETWEEN), TOP_OFFSET );
555  rEntry->m_pPublisher->SetPosPixel(aPos);
556  }
557 
558  // Draw status icons
559  if (!rEntry->m_bUser)
560  {
561  aPos = rRect.TopRight() + Point( -(RIGHT_ICON_OFFSET + SMALL_ICON_SIZE), TOP_OFFSET );
562  if (rEntry->m_bLocked)
563  rRenderContext.DrawImage(aPos, Size(SMALL_ICON_SIZE, SMALL_ICON_SIZE), m_aLockedImage);
564  else
565  rRenderContext.DrawImage(aPos, Size(SMALL_ICON_SIZE, SMALL_ICON_SIZE), m_aSharedImage);
566  }
567  if ((rEntry->m_eState == AMBIGUOUS ) || rEntry->m_bMissingDeps || rEntry->m_bMissingLic)
568  {
569  aPos = rRect.TopRight() + Point(-(RIGHT_ICON_OFFSET + SPACE_BETWEEN + 2 * SMALL_ICON_SIZE), TOP_OFFSET);
570  rRenderContext.DrawImage(aPos, Size(SMALL_ICON_SIZE, SMALL_ICON_SIZE), m_aWarningImage);
571  }
572 
573  rRenderContext.SetLineColor(COL_LIGHTGRAY);
574  rRenderContext.DrawLine(rRect.BottomLeft(), rRect.BottomRight());
575 }
576 
577 
579 {
580  if ( m_bHasActive )
582 
583  SetupScrollBar();
584 
585  if ( m_bHasActive )
586  {
587  tools::Rectangle aEntryRect = GetEntryRect( m_nActive );
588 
589  if ( m_bAdjustActive )
590  {
591  m_bAdjustActive = false;
592 
593  // If the top of the selected entry isn't visible, make it visible
594  if ( aEntryRect.Top() < 0 )
595  {
596  m_nTopIndex += aEntryRect.Top();
597  aEntryRect.Move( 0, -aEntryRect.Top() );
598  }
599 
600  // If the bottom of the selected entry isn't visible, make it visible even if now the top
601  // isn't visible any longer ( the buttons are more important )
602  Size aOutputSize = GetOutputSizePixel();
603  if ( aEntryRect.Bottom() > aOutputSize.Height() )
604  {
605  m_nTopIndex += ( aEntryRect.Bottom() - aOutputSize.Height() );
606  aEntryRect.Move( 0, -( aEntryRect.Bottom() - aOutputSize.Height() ) );
607  }
608 
609  // If there is unused space below the last entry but all entries don't fit into the box,
610  // move the content down to use the whole space
611  const long nTotalHeight = GetTotalHeight();
612  if ( m_bHasScrollBar && ( aOutputSize.Height() + m_nTopIndex > nTotalHeight ) )
613  {
614  long nOffset = m_nTopIndex;
615  m_nTopIndex = nTotalHeight - aOutputSize.Height();
616  nOffset -= m_nTopIndex;
617  aEntryRect.Move( 0, nOffset );
618  }
619 
620  if ( m_bHasScrollBar )
622  }
623  }
624 
625  m_bNeedsRecalc = false;
626 }
627 
628 
629 bool ExtensionBox_Impl::HandleCursorKey( sal_uInt16 nKeyCode )
630 {
631  if ( m_vEntries.empty() )
632  return true;
633 
634  long nSelect = 0;
635 
636  if ( m_bHasActive )
637  {
638  long nPageSize = GetOutputSizePixel().Height() / m_nStdHeight;
639  if ( nPageSize < 2 )
640  nPageSize = 2;
641 
642  if ( ( nKeyCode == KEY_DOWN ) || ( nKeyCode == KEY_RIGHT ) )
643  nSelect = m_nActive + 1;
644  else if ( ( nKeyCode == KEY_UP ) || ( nKeyCode == KEY_LEFT ) )
645  nSelect = m_nActive - 1;
646  else if ( nKeyCode == KEY_HOME )
647  nSelect = 0;
648  else if ( nKeyCode == KEY_END )
649  nSelect = m_vEntries.size() - 1;
650  else if ( nKeyCode == KEY_PAGEUP )
651  nSelect = m_nActive - nPageSize + 1;
652  else if ( nKeyCode == KEY_PAGEDOWN )
653  nSelect = m_nActive + nPageSize - 1;
654  }
655  else // when there is no selected entry, we will select the first or the last.
656  {
657  if ( ( nKeyCode == KEY_DOWN ) || ( nKeyCode == KEY_PAGEDOWN ) || ( nKeyCode == KEY_HOME ) )
658  nSelect = 0;
659  else if ( ( nKeyCode == KEY_UP ) || ( nKeyCode == KEY_PAGEUP ) || ( nKeyCode == KEY_END ) )
660  nSelect = m_vEntries.size() - 1;
661  }
662 
663  if ( nSelect < 0 )
664  nSelect = 0;
665  if ( nSelect >= static_cast<long>(m_vEntries.size()) )
666  nSelect = m_vEntries.size() - 1;
667 
668  selectEntry( nSelect );
669 
670  return true;
671 }
672 
673 
674 void ExtensionBox_Impl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rPaintRect*/)
675 {
676  if ( !m_bInDelete )
677  DeleteRemoved();
678 
679  if ( m_bNeedsRecalc )
680  RecalcAll();
681 
682  Point aStart( 0, -m_nTopIndex );
683  Size aSize(GetOutputSizePixel());
684 
685  if ( m_bHasScrollBar )
686  aSize.AdjustWidth( -(m_pScrollBar->GetSizePixel().Width()) );
687 
688  const ::osl::MutexGuard aGuard( m_entriesMutex );
689 
690  for (auto const& entry : m_vEntries)
691  {
692  aSize.setHeight( entry->m_bActive ? m_nActiveHeight : m_nStdHeight );
693  tools::Rectangle aEntryRect( aStart, aSize );
694  DrawRow(rRenderContext, aEntryRect, entry);
695  aStart.AdjustY(aSize.Height() );
696  }
697 }
698 
699 
701 {
702  long nHeight = m_vEntries.size() * m_nStdHeight;
703 
704  if ( m_bHasActive )
705  {
706  nHeight += m_nActiveHeight - m_nStdHeight;
707  }
708 
709  return nHeight;
710 }
711 
712 
714 {
715  const Size aSize = GetOutputSizePixel();
716  const long nScrBarSize = GetSettings().GetStyleSettings().GetScrollBarSize();
717  const long nTotalHeight = GetTotalHeight();
718  const bool bNeedsScrollBar = ( nTotalHeight > aSize.Height() );
719 
720  if ( bNeedsScrollBar )
721  {
722  if ( m_nTopIndex + aSize.Height() > nTotalHeight )
723  m_nTopIndex = nTotalHeight - aSize.Height();
724 
725  m_pScrollBar->SetPosSizePixel( Point( aSize.Width() - nScrBarSize, 0 ),
726  Size( nScrBarSize, aSize.Height() ) );
727  m_pScrollBar->SetRangeMax( nTotalHeight );
728  m_pScrollBar->SetVisibleSize( aSize.Height() );
729  m_pScrollBar->SetPageSize( ( aSize.Height() * 4 ) / 5 );
732 
733  if ( !m_bHasScrollBar )
734  m_pScrollBar->Show();
735  }
736  else if ( m_bHasScrollBar )
737  {
738  m_pScrollBar->Hide();
739  m_nTopIndex = 0;
740  }
741 
742  m_bHasScrollBar = bNeedsScrollBar;
743 }
744 
745 
747 {
748  RecalcAll();
749 }
750 
752 {
753  return LogicToPixel(Size(250, 150), MapMode(MapUnit::MapAppFont));
754 }
755 
756 extern "C" SAL_DLLPUBLIC_EXPORT void makeExtensionBox(VclPtr<vcl::Window> & rRet, VclPtr<vcl::Window> & pParent, VclBuilder::stringmap &)
757 {
758  rRet = VclPtr<ExtensionBox_Impl>::Create(pParent);
759 }
760 
762 {
763  long nPos = ( rPos.Y() + m_nTopIndex ) / m_nStdHeight;
764 
765  if ( m_bHasActive && ( nPos > m_nActive ) )
766  {
767  if ( rPos.Y() + m_nTopIndex <= m_nActive*m_nStdHeight + m_nActiveHeight )
768  nPos = m_nActive;
769  else
770  nPos = ( rPos.Y() + m_nTopIndex - (m_nActiveHeight - m_nStdHeight) ) / m_nStdHeight;
771  }
772 
773  return nPos;
774 }
775 
776 
778 {
779  long nPos = PointToPos( rMEvt.GetPosPixel() );
780 
781  if ( rMEvt.IsLeft() )
782  {
783  if ( rMEvt.IsMod1() && m_bHasActive )
784  selectEntry( m_vEntries.size() ); // Selecting an not existing entry will deselect the current one
785  else
786  selectEntry( nPos );
787  }
788 }
789 
790 
792 {
793  if ( !m_bInDelete )
794  DeleteRemoved();
795 
796  bool bHandled = false;
797 
798  if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
799  {
800  const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
801  vcl::KeyCode aKeyCode = pKEvt->GetKeyCode();
802  sal_uInt16 nKeyCode = aKeyCode.GetCode();
803 
804  if ( nKeyCode == KEY_TAB )
805  ;
806  else if ( aKeyCode.GetGroup() == KEYGROUP_CURSOR )
807  bHandled = HandleCursorKey( nKeyCode );
808  }
809 
810  if ( rNEvt.GetType() == MouseNotifyEvent::COMMAND )
811  {
812  if ( m_bHasScrollBar &&
813  ( rNEvt.GetCommandEvent()->GetCommand() == CommandEventId::Wheel ) )
814  {
815  const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
816  if ( pData->GetMode() == CommandWheelMode::SCROLL )
817  {
818  long nThumbPos = m_pScrollBar->GetThumbPos();
819  if ( pData->GetDelta() < 0 )
820  m_pScrollBar->DoScroll( nThumbPos + m_nStdHeight );
821  else
822  m_pScrollBar->DoScroll( nThumbPos - m_nStdHeight );
823  bHandled = true;
824  }
825  }
826  }
827 
828  if ( !bHandled )
829  return Control::EventNotify(rNEvt);
830  else
831  return true;
832 }
833 
834 
835 bool ExtensionBox_Impl::FindEntryPos( const TEntry_Impl& rEntry, const long nStart,
836  const long nEnd, long &nPos )
837 {
838  nPos = nStart;
839  if ( nStart > nEnd )
840  return false;
841 
842  sal_Int32 eCompare;
843 
844  if ( nStart == nEnd )
845  {
846  eCompare = rEntry->CompareTo( m_pCollator.get(), m_vEntries[ nStart ] );
847  if ( eCompare < 0 )
848  return false;
849  else if ( eCompare == 0 )
850  {
851  //Workaround. See i86963.
852  if (rEntry->m_xPackage != m_vEntries[nStart]->m_xPackage)
853  return false;
854 
855  if ( m_bInCheckMode )
856  m_vEntries[ nStart ]->m_bChecked = true;
857  return true;
858  }
859  else
860  {
861  nPos = nStart + 1;
862  return false;
863  }
864  }
865 
866  const long nMid = nStart + ( ( nEnd - nStart ) / 2 );
867  eCompare = rEntry->CompareTo( m_pCollator.get(), m_vEntries[ nMid ] );
868 
869  if ( eCompare < 0 )
870  return FindEntryPos( rEntry, nStart, nMid-1, nPos );
871  else if ( eCompare > 0 )
872  return FindEntryPos( rEntry, nMid+1, nEnd, nPos );
873  else
874  {
875  //Workaround.See i86963.
876  if (rEntry->m_xPackage != m_vEntries[nMid]->m_xPackage)
877  return false;
878 
879  if ( m_bInCheckMode )
880  m_vEntries[ nMid ]->m_bChecked = true;
881  nPos = nMid;
882  return true;
883  }
884 }
885 
887 {
888  m_vListenerAdded.erase(std::remove_if(m_vListenerAdded.begin(), m_vListenerAdded.end(),
889  [](const uno::WeakReference<deployment::XPackage>& rxListener) {
890  const uno::Reference<deployment::XPackage> hardRef(rxListener);
891  return !hardRef.is();
892  }),
893  m_vListenerAdded.end());
894 }
895 
897  uno::Reference<deployment::XPackage > const & extension)
898 {
899  //make sure to only add the listener once
901  if ( std::none_of(m_vListenerAdded.begin(), m_vListenerAdded.end(),
902  FindWeakRef(extension)) )
903  {
904  extension->addEventListener( m_xRemoveListener.get() );
905  m_vListenerAdded.emplace_back(extension);
906  }
907 }
908 
909 
910 void ExtensionBox_Impl::addEntry( const uno::Reference< deployment::XPackage > &xPackage,
911  bool bLicenseMissing )
912 {
913  long nPos = 0;
915  bool bLocked = m_pManager->isReadOnly( xPackage );
916 
917  TEntry_Impl pEntry( new Entry_Impl( xPackage, eState, bLocked ) );
918 
919  // Don't add empty entries
920  if ( pEntry->m_sTitle.isEmpty() )
921  return;
922 
923  ::osl::ClearableMutexGuard guard(m_entriesMutex);
924  if ( m_vEntries.empty() )
925  {
926  addEventListenerOnce(xPackage);
927  m_vEntries.push_back( pEntry );
928  }
929  else
930  {
931  if ( !FindEntryPos( pEntry, 0, m_vEntries.size()-1, nPos ) )
932  {
933  addEventListenerOnce(xPackage);
934  m_vEntries.insert( m_vEntries.begin()+nPos, pEntry );
935  }
936  else if ( !m_bInCheckMode )
937  {
938  OSL_FAIL( "ExtensionBox_Impl::addEntry(): Will not add duplicate entries" );
939  }
940  }
941 
942  pEntry->m_bHasOptions = m_pManager->supportsOptions( xPackage );
943  pEntry->m_bUser = (xPackage->getRepositoryName() == USER_PACKAGE_MANAGER);
944  pEntry->m_bShared = (xPackage->getRepositoryName() == SHARED_PACKAGE_MANAGER);
945  pEntry->m_bNew = m_bInCheckMode;
946  pEntry->m_bMissingLic = bLicenseMissing;
947 
948  if ( bLicenseMissing )
949  pEntry->m_sErrorText = DpResId( RID_STR_ERROR_MISSING_LICENSE );
950 
951  //access to m_nActive must be guarded
952  if ( !m_bInCheckMode && m_bHasActive && ( m_nActive >= nPos ) )
953  m_nActive += 1;
954  guard.clear();
955 
956  if ( IsReallyVisible() )
957  Invalidate();
958 
959  m_bNeedsRecalc = true;
960 }
961 
962 void ExtensionBox_Impl::updateEntry( const uno::Reference< deployment::XPackage > &xPackage )
963 {
964  for (auto const& entry : m_vEntries)
965  {
966  if ( entry->m_xPackage == xPackage )
967  {
969  entry->m_bHasOptions = m_pManager->supportsOptions( xPackage );
970  entry->m_eState = eState;
971  entry->m_sTitle = xPackage->getDisplayName();
972  entry->m_sVersion = xPackage->getVersion();
973  entry->m_sDescription = xPackage->getDescription();
974 
975  if ( eState == REGISTERED )
976  entry->m_bMissingLic = false;
977 
978  if ( eState == AMBIGUOUS )
979  entry->m_sErrorText = DpResId( RID_STR_ERROR_UNKNOWN_STATUS );
980  else if ( ! entry->m_bMissingLic )
981  entry->m_sErrorText.clear();
982 
983  if ( IsReallyVisible() )
984  Invalidate();
985  break;
986  }
987  }
988 }
989 
990 //This function is also called as a result of removing an extension.
991 //see PackageManagerImpl::removePackage
992 //The gui is a registered as listener on the package. Removing it will cause the
993 //listeners to be notified an then this function is called. At this moment xPackage
994 //is in the disposing state and all calls on it may result in a DisposedException.
995 void ExtensionBox_Impl::removeEntry( const uno::Reference< deployment::XPackage > &xPackage )
996 {
997  if ( ! m_bInDelete )
998  {
999  bool invalidate = false;
1000  {
1001  ::osl::ClearableMutexGuard aGuard( m_entriesMutex );
1002 
1003  auto iIndex = std::find_if(m_vEntries.begin(), m_vEntries.end(),
1004  [&xPackage](const TEntry_Impl& rxEntry) { return rxEntry->m_xPackage == xPackage; });
1005  if (iIndex != m_vEntries.end())
1006  {
1007  long nPos = iIndex - m_vEntries.begin();
1008 
1009  // Entries mustn't be removed here, because they contain a hyperlink control
1010  // which can only be deleted when the thread has the solar mutex. Therefore
1011  // the entry will be moved into the m_vRemovedEntries list which will be
1012  // cleared on the next paint event
1013  m_vRemovedEntries.push_back( *iIndex );
1014  (*iIndex)->m_xPackage->removeEventListener(m_xRemoveListener.get());
1015  m_vEntries.erase( iIndex );
1016 
1017  m_bNeedsRecalc = true;
1018 
1019  if ( IsReallyVisible() )
1020  invalidate = true;
1021 
1022  if ( m_bHasActive )
1023  {
1024  if ( nPos < m_nActive )
1025  m_nActive -= 1;
1026  else if ( ( nPos == m_nActive ) &&
1027  ( nPos == static_cast<long>(m_vEntries.size()) ) )
1028  m_nActive -= 1;
1029 
1030  m_bHasActive = false;
1031  //clear before calling out of this method
1032  aGuard.clear();
1034  }
1035  }
1036  }
1037 
1038  if (invalidate)
1039  {
1040  SolarMutexGuard g;
1041  Invalidate();
1042  }
1043  }
1044 }
1045 
1046 
1048 {
1049  bool bAllRemoved = false;
1050 
1051  while ( ! bAllRemoved )
1052  {
1053  bAllRemoved = true;
1054 
1055  ::osl::ClearableMutexGuard aGuard( m_entriesMutex );
1056 
1057  for (auto const& entry : m_vEntries)
1058  {
1059  if ( !entry->m_bLocked )
1060  {
1061  bAllRemoved = false;
1062  uno::Reference< deployment::XPackage> xPackage = entry->m_xPackage;
1063  aGuard.clear();
1064  removeEntry( xPackage );
1065  break;
1066  }
1067  }
1068  }
1069 }
1070 
1071 
1073 {
1074  m_bInCheckMode = true;
1075  for (auto const& entry : m_vEntries)
1076  {
1077  entry->m_bChecked = false;
1078  entry->m_bNew = false;
1079  }
1080 }
1081 
1082 
1084 {
1085  long nNewPos = -1;
1086  long nChangedActivePos = -1;
1087  long nPos = 0;
1088  bool bNeedsUpdate = false;
1089 
1090  ::osl::ClearableMutexGuard guard(m_entriesMutex);
1091  auto iIndex = m_vEntries.begin();
1092  while ( iIndex != m_vEntries.end() )
1093  {
1094  if ( !(*iIndex)->m_bChecked )
1095  {
1096  (*iIndex)->m_bChecked = true;
1097  bNeedsUpdate = true;
1098  nPos = iIndex-m_vEntries.begin();
1099  if ( (*iIndex)->m_bNew )
1100  { // add entry to list and correct active pos
1101  if ( nNewPos == - 1)
1102  nNewPos = nPos;
1103  if ( nPos <= m_nActive )
1104  m_nActive += 1;
1105  ++iIndex;
1106  }
1107  else
1108  { // remove entry from list
1109  if (nPos < nNewPos) {
1110  --nNewPos;
1111  }
1112  if (nPos < nChangedActivePos) {
1113  --nChangedActivePos;
1114  }
1115  if ( nPos < m_nActive )
1116  m_nActive -= 1;
1117  else if ( nPos == m_nActive )
1118  {
1119  nChangedActivePos = nPos;
1120  m_nActive = -1;
1121  m_bHasActive = false;
1122  }
1123  m_vRemovedEntries.push_back( *iIndex );
1124  iIndex = m_vEntries.erase( iIndex );
1125  }
1126  }
1127  else
1128  ++iIndex;
1129  }
1130  guard.clear();
1131 
1132  m_bInCheckMode = false;
1133 
1134  if ( nNewPos != - 1)
1135  selectEntry( nNewPos );
1136  else if (nChangedActivePos != -1) {
1137  selectEntry(nChangedActivePos);
1138  }
1139 
1140  if ( bNeedsUpdate )
1141  {
1142  m_bNeedsRecalc = true;
1143  if ( IsReallyVisible() )
1144  Invalidate();
1145  }
1146 }
1147 
1148 
1149 void ExtensionBox_Impl::DoScroll( long nDelta )
1150 {
1151  m_nTopIndex += nDelta;
1152  Point aNewSBPt( m_pScrollBar->GetPosPixel() );
1153 
1154  tools::Rectangle aScrRect( Point(), GetOutputSizePixel() );
1155  aScrRect.AdjustRight( -(m_pScrollBar->GetSizePixel().Width()) );
1156  Scroll( 0, -nDelta, aScrRect );
1157 
1158  m_pScrollBar->SetPosPixel( aNewSBPt );
1159 }
1160 
1161 
1162 IMPL_LINK( ExtensionBox_Impl, ScrollHdl, ScrollBar*, pScrBar, void )
1163 {
1164  DoScroll( pScrBar->GetDelta() );
1165 }
1166 
1167 } //namespace dp_gui
1168 
1169 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual Point GetPosPixel() const
#define RSC_SP_DLG_INNERBORDER_LEFT
Point TopLeft() const
long Width() const
Size GetSizePixel() const
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)
void addEntry(const css::uno::Reference< css::deployment::XPackage > &xPackage, bool bLicenseMissing=false)
OUString GetEllipsisString(const OUString &rStr, long nMaxWidth, DrawTextFlags nStyle=DrawTextFlags::EndEllipsis) const
long GetWidth() const
void updateEntry(const css::uno::Reference< css::deployment::XPackage > &xPackage)
#define ICON_WIDTH
#define KEYGROUP_CURSOR
long GetHeight() const
SAL_DLLPUBLIC_EXPORT void makeExtensionBox(VclPtr< vcl::Window > &rRet, VclPtr< vcl::Window > &pParent, VclBuilder::stringmap &)
sal_Int32 compareString(const OUString &s1, const OUString &s2) const
void DrawImage(const Point &rPos, const Image &rImage, DrawImageFlags nStyle=DrawImageFlags::NONE)
virtual void Resize() override
bool HandleCursorKey(sal_uInt16 nKeyCode)
long AdjustWidth(long n)
void CalcActiveHeight(const long nPos)
virtual sal_Int32 getSelIndex() const override
#define KEY_TAB
#define KEY_PAGEDOWN
const CommandEvent * GetCommandEvent() const
const Color & GetHighlightTextColor() const
long Height() const
#define KEY_PAGEUP
sal_Int32 CompareTo(const CollatorWrapper *pCollator, const TEntry_Impl &rEntry) const
Point BottomLeft() const
bool FindEntryPos(const TEntry_Impl &rEntry, long nStart, long nEnd, long &nFound)
VclPtr< ExtensionBox_Impl > m_pParent
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
Entry_Impl(const css::uno::Reference< css::deployment::XPackage > &xPackage, const PackageState eState, const bool bReadOnly)
virtual Size GetSizePixel() const
VclPtr< ScrollBar > m_pScrollBar
virtual void dispose() override
static Size CalcMinimumTextSize(Control const *pControl, long nMaxWidth=0x7fffffff)
#define TOP_OFFSET
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rPaintRect) override
long GetThumbPos() const
sal_uInt16 GetGroup() const
void SetTextFillColor()
sal_uInt16 GetCode() const
const KeyEvent * GetKeyEvent() const
virtual sal_Int32 getItemCount() const override
virtual ~ExtensionRemovedListener() override
constexpr::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
const CommandWheelData * GetWheelData() const
#define KEY_LEFT
const Color & GetFieldTextColor() const
#define RIGHT_ICON_OFFSET
const Color & GetHighlightColor() const
void Move(long nHorzMoveDelta, long nVertMoveDelta)
WEIGHT_BOLD
virtual void selectEntry(const long nPos)
void SetBackground()
long Right() const
const vcl::Font & GetFont() const
WinBits const WB_VERT
#define SMALL_ICON_SIZE
void DrawRow(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect, const TEntry_Impl &rEntry)
long PointToPos(const Point &rPos)
virtual bool EventNotify(NotifyEvent &rNEvt) override
virtual ~ExtensionBox_Impl() override
long Top() const
void DrawLine(const Point &rStartPt, const Point &rEndPt)
void DrawRect(const tools::Rectangle &rRect)
std::unique_ptr< css::lang::Locale > m_pLocale
Point BottomRight() const
ExtensionBox_Impl(vcl::Window *pParent)
void SetLineColor()
const Color & GetDisableColor() const
long DoScroll(long nNewPos)
rtl::Reference< ExtensionRemovedListener > m_xRemoveListener
#define RSC_SP_DLG_INNERBORDER_TOP
long AdjustY(long nVertMove)
virtual void SAL_CALL disposing(css::lang::EventObject const &evt) override
TheExtensionManager * m_pManager
void SetRangeMax(long nNewRange)
bool isReadOnly(const css::uno::Reference< css::deployment::XPackage > &xPackage) const
void SetVisibleSize(long nNewSize)
int i
CommandWheelMode GetMode() const
void SetFillColor()
const Color & GetFieldColor() const
CommandEventId GetCommand() const
std::map< OString, OUString > stringmap
void SetTextColor(const Color &rColor)
long Bottom() const
#define SHARED_PACKAGE_MANAGER
#define ICON_OFFSET
MouseNotifyEvent GetType() const
const uno::Reference< deployment::XPackage > m_extension
void SetPageSize(long nNewSize)
css::uno::Reference< css::deployment::XPackage > m_xPackage
const AllSettings & GetSettings() const
bool supportsOptions(const css::uno::Reference< css::deployment::XPackage > &xPackage) const
long GetTextHeight() const
#define SPACE_BETWEEN
std::vector< TEntry_Impl > m_vEntries
#define KEY_END
virtual void SetPosSizePixel(const Point &rNewPos, const Size &rNewSize)
void SetLineSize(long nNewSize)
StockImage
const vcl::KeyCode & GetKeyCode() const
#define USER_PACKAGE_MANAGER
#define KEY_DOWN
tools::Rectangle GetEntryRect(const long nPos) const
long GetDelta() const
std::vector< TEntry_Impl > m_vRemovedEntries
#define ICON_HEIGHT
void SetFont(const vcl::Font &rNewFont)
virtual Size GetOptimalSize() const override
bool IsLeft() const
void SetScrollHdl(const Link< ScrollBar *, void > &rLink)
static VclPtr< reference_type > Create(Arg &&...arg)
PackageState
Definition: dp_gui.h:62
std::unique_ptr< CollatorWrapper > m_pCollator
Reference< XComponentContext > getProcessComponentContext()
static PackageState getPackageState(const css::uno::Reference< css::deployment::XPackage > &xPackage)
const Point & GetPosPixel() const
void EnableDrag()
long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
void addEventListenerOnce(css::uno::Reference< css::deployment::XPackage > const &extension)
mutable::osl::Mutex m_entriesMutex
#define KEY_HOME
OUString DpResId(const char *pId)
Definition: dp_shared.hxx:38
std::vector< css::uno::WeakReference< css::deployment::XPackage > > m_vListenerAdded
Definition: dp_gui.h:60
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getErrorText(css::uno::Reference< css::xml::dom::XElement > const &dependency)
Obtain the (human-readable) error message of a failed dependency.
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
sal_Int32 nPos
virtual void SetPosPixel(const Point &rNewPos)
Point TopRight() const
#define KEY_RIGHT
void removeEntry(const css::uno::Reference< css::deployment::XPackage > &xPackage)
void SetThumbPos(long nThumbPos)
long Y() const
std::shared_ptr< Entry_Impl > TEntry_Impl
bool IsMod1() const
IMPL_LINK(ExtMgrDialog, startProgress, void *, _bLockInterface, void)
#define KEY_UP
virtual bool EventNotify(NotifyEvent &rNEvt) override
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
void setHeight(long nHeight)