xref: /trunk/main/desktop/source/deployment/gui/dp_gui_extlistbox.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_desktop.hxx"
26 
27 #include "svtools/controldims.hrc"
28 
29 #include "dp_gui.h"
30 #include "dp_gui_extlistbox.hxx"
31 #include "dp_gui_theextmgr.hxx"
32 #include "dp_gui_dialog2.hxx"
33 #include "dp_dependencies.hxx"
34 
35 #include "comphelper/processfactory.hxx"
36 #include "com/sun/star/i18n/CollatorOptions.hpp"
37 #include "com/sun/star/deployment/DependencyException.hpp"
38 #include "com/sun/star/deployment/DeploymentException.hpp"
39 #include "cppuhelper/weakref.hxx"
40 
41 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
42 
43 #define USER_PACKAGE_MANAGER    OUSTR("user")
44 #define SHARED_PACKAGE_MANAGER  OUSTR("shared")
45 #define BUNDLED_PACKAGE_MANAGER OUSTR("bundled")
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 
FindWeakRefdp_gui::__anon3ec87a110111::FindWeakRef57     FindWeakRef( uno::Reference<deployment::XPackage> const & ext): m_extension(ext) {}
58     bool operator () (uno::WeakReference< deployment::XPackage >  const & ref);
59 };
60 
operator ()(uno::WeakReference<deployment::XPackage> const & ref)61 bool FindWeakRef::operator () (uno::WeakReference< deployment::XPackage >  const & ref)
62 {
63     const uno::Reference<deployment::XPackage> ext(ref);
64     if (ext == m_extension)
65         return true;
66     return false;
67 }
68 
69 } // end namespace
70 //------------------------------------------------------------------------------
71 //                          struct Entry_Impl
72 //------------------------------------------------------------------------------
Entry_Impl(const uno::Reference<deployment::XPackage> & xPackage,const PackageState eState,const bool bReadOnly)73 Entry_Impl::Entry_Impl( const uno::Reference< deployment::XPackage > &xPackage,
74                         const PackageState eState, const bool bReadOnly ) :
75     m_bActive( false ),
76     m_bLocked( bReadOnly ),
77     m_bHasOptions( false ),
78     m_bUser( false ),
79     m_bShared( false ),
80     m_bNew( false ),
81     m_bChecked( false ),
82     m_bMissingDeps( false ),
83     m_bHasButtons( false ),
84     m_bMissingLic( false ),
85     m_eState( eState ),
86     m_pPublisher( NULL ),
87     m_xPackage( xPackage )
88 {
89     try
90     {
91         m_sTitle = xPackage->getDisplayName();
92         m_sVersion = xPackage->getVersion();
93         m_sDescription = xPackage->getDescription();
94     m_sLicenseText = xPackage->getLicenseText();
95 
96         beans::StringPair aInfo( m_xPackage->getPublisherInfo() );
97         m_sPublisher = aInfo.First;
98         m_sPublisherURL = aInfo.Second;
99 
100         // get the icons for the package if there are any
101         uno::Reference< graphic::XGraphic > xGraphic = xPackage->getIcon( false );
102         if ( xGraphic.is() )
103             m_aIcon = Image( xGraphic );
104 
105         xGraphic = xPackage->getIcon( true );
106         if ( xGraphic.is() )
107             m_aIconHC = Image( xGraphic );
108         else
109             m_aIconHC = m_aIcon;
110 
111         if ( eState == AMBIGUOUS )
112             m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_UNKNOWN_STATUS );
113         else if ( eState == NOT_REGISTERED )
114             checkDependencies();
115     }
116     catch (deployment::ExtensionRemovedException &) {}
117     catch (uno::RuntimeException &) {}
118 }
119 
120 //------------------------------------------------------------------------------
~Entry_Impl()121 Entry_Impl::~Entry_Impl()
122 {}
123 
124 //------------------------------------------------------------------------------
CompareTo(const CollatorWrapper * pCollator,const TEntry_Impl pEntry) const125 StringCompare Entry_Impl::CompareTo( const CollatorWrapper *pCollator, const TEntry_Impl pEntry ) const
126 {
127     StringCompare eCompare = (StringCompare) pCollator->compareString( m_sTitle, pEntry->m_sTitle );
128     if ( eCompare == COMPARE_EQUAL )
129     {
130         eCompare = m_sVersion.CompareTo( pEntry->m_sVersion );
131         if ( eCompare == COMPARE_EQUAL )
132         {
133             sal_Int32 nCompare = m_xPackage->getRepositoryName().compareTo( pEntry->m_xPackage->getRepositoryName() );
134             if ( nCompare < 0 )
135                 eCompare = COMPARE_LESS;
136             else if ( nCompare > 0 )
137                 eCompare = COMPARE_GREATER;
138         }
139     }
140     return eCompare;
141 }
142 
143 //------------------------------------------------------------------------------
checkDependencies()144 void Entry_Impl::checkDependencies()
145 {
146     try {
147         m_xPackage->checkDependencies( uno::Reference< ucb::XCommandEnvironment >() );
148     }
149     catch ( deployment::DeploymentException &e )
150     {
151         deployment::DependencyException depExc;
152         if ( e.Cause >>= depExc )
153         {
154             rtl::OUString aMissingDep( DialogHelper::getResourceString( RID_STR_ERROR_MISSING_DEPENDENCIES ) );
155             for ( sal_Int32 i = 0; i < depExc.UnsatisfiedDependencies.getLength(); ++i )
156             {
157                 aMissingDep += OUSTR("\n");
158                 aMissingDep += dp_misc::Dependencies::getErrorText( depExc.UnsatisfiedDependencies[i]);
159             }
160             aMissingDep += OUSTR("\n");
161             m_sErrorText = aMissingDep;
162             m_bMissingDeps = true;
163         }
164     }
165 }
166 //------------------------------------------------------------------------------
167 // ExtensionRemovedListener
168 //------------------------------------------------------------------------------
disposing(lang::EventObject const & rEvt)169 void ExtensionRemovedListener::disposing( lang::EventObject const & rEvt )
170 {
171     uno::Reference< deployment::XPackage > xPackage( rEvt.Source, uno::UNO_QUERY );
172 
173     if ( xPackage.is() )
174     {
175         m_pParent->removeEntry( xPackage );
176     }
177 }
178 
179 //------------------------------------------------------------------------------
~ExtensionRemovedListener()180 ExtensionRemovedListener::~ExtensionRemovedListener()
181 {
182 }
183 
184 //------------------------------------------------------------------------------
185 // ExtensionBox_Impl
186 //------------------------------------------------------------------------------
ExtensionBox_Impl(Dialog * pParent,TheExtensionManager * pManager)187 ExtensionBox_Impl::ExtensionBox_Impl( Dialog* pParent, TheExtensionManager *pManager ) :
188     IExtensionListBox( pParent, WB_BORDER | WB_TABSTOP | WB_CHILDDLGCTRL ),
189     m_bHasScrollBar( false ),
190     m_bHasActive( false ),
191     m_bNeedsRecalc( true ),
192     m_bHasNew( false ),
193     m_bInCheckMode( false ),
194     m_bAdjustActive( false ),
195     m_bInDelete( false ),
196     m_nActive( 0 ),
197     m_nTopIndex( 0 ),
198     m_nActiveHeight( 0 ),
199     m_nExtraHeight( 2 ),
200     m_aSharedImage( DialogHelper::getResId( RID_IMG_SHARED ) ),
201     m_aSharedImageHC( DialogHelper::getResId( RID_IMG_SHARED_HC ) ),
202     m_aLockedImage( DialogHelper::getResId( RID_IMG_LOCKED ) ),
203     m_aLockedImageHC( DialogHelper::getResId( RID_IMG_LOCKED_HC ) ),
204     m_aWarningImage( DialogHelper::getResId( RID_IMG_WARNING ) ),
205     m_aWarningImageHC( DialogHelper::getResId( RID_IMG_WARNING_HC ) ),
206     m_aDefaultImage( DialogHelper::getResId( RID_IMG_EXTENSION ) ),
207     m_aDefaultImageHC( DialogHelper::getResId( RID_IMG_EXTENSION_HC ) ),
208     m_pScrollBar( NULL ),
209     m_pManager( pManager )
210 {
211     SetHelpId( HID_EXTENSION_MANAGER_LISTBOX );
212 
213     m_pScrollBar = new ScrollBar( this, WB_VERT );
214     m_pScrollBar->SetScrollHdl( LINK( this, ExtensionBox_Impl, ScrollHdl ) );
215     m_pScrollBar->EnableDrag();
216 
217     SetPaintTransparent( true );
218     SetPosPixel( Point( RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP ) );
219     long nIconHeight = 2*TOP_OFFSET + SMALL_ICON_SIZE;
220     long nTitleHeight = 2*TOP_OFFSET + GetTextHeight();
221     if ( nIconHeight < nTitleHeight )
222         m_nStdHeight = nTitleHeight;
223     else
224         m_nStdHeight = nIconHeight;
225     m_nStdHeight += GetTextHeight() + TOP_OFFSET;
226 
227     nIconHeight = ICON_HEIGHT + 2*TOP_OFFSET + 1;
228     if ( m_nStdHeight < nIconHeight )
229         m_nStdHeight = nIconHeight;
230 
231     m_nActiveHeight = m_nStdHeight;
232 
233     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
234     if( IsControlBackground() )
235         SetBackground( GetControlBackground() );
236     else
237         SetBackground( rStyleSettings.GetFieldColor() );
238 
239     m_xRemoveListener = new ExtensionRemovedListener( this );
240 
241     m_pLocale = new lang::Locale( Application::GetSettings().GetLocale() );
242     m_pCollator = new CollatorWrapper( ::comphelper::getProcessServiceFactory() );
243     m_pCollator->loadDefaultCollator( *m_pLocale, i18n::CollatorOptions::CollatorOptions_IGNORE_CASE );
244 
245     Show();
246 }
247 
248 //------------------------------------------------------------------------------
~ExtensionBox_Impl()249 ExtensionBox_Impl::~ExtensionBox_Impl()
250 {
251     if ( ! m_bInDelete )
252         DeleteRemoved();
253 
254     m_bInDelete = true;
255 
256     typedef std::vector< TEntry_Impl >::iterator ITER;
257 
258     for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex )
259     {
260         if ( (*iIndex)->m_pPublisher )
261         {
262             delete (*iIndex)->m_pPublisher;
263             (*iIndex)->m_pPublisher = NULL;
264         }
265         (*iIndex)->m_xPackage->removeEventListener( uno::Reference< lang::XEventListener > ( m_xRemoveListener, uno::UNO_QUERY ) );
266     }
267 
268     m_vEntries.clear();
269 
270     delete m_pScrollBar;
271 
272     m_xRemoveListener.clear();
273 
274     delete m_pLocale;
275     delete m_pCollator;
276 }
277 
278 //------------------------------------------------------------------------------
getItemCount() const279 sal_Int32 ExtensionBox_Impl::getItemCount() const
280 {
281     return static_cast< sal_Int32 >( m_vEntries.size() );
282 }
283 
284 //------------------------------------------------------------------------------
getSelIndex() const285 sal_Int32 ExtensionBox_Impl::getSelIndex() const
286 {
287     if ( m_bHasActive )
288     {
289         OSL_ASSERT( m_nActive >= -1);
290         return static_cast< sal_Int32 >( m_nActive );
291     }
292     else
293         return static_cast< sal_Int32 >( EXTENSION_LISTBOX_ENTRY_NOTFOUND );
294 }
295 
296 //------------------------------------------------------------------------------
checkIndex(sal_Int32 nIndex) const297 void ExtensionBox_Impl::checkIndex( sal_Int32 nIndex ) const
298 {
299     if ( nIndex < 0 )
300         throw lang::IllegalArgumentException( OUSTR("The list index starts with 0"),0, 0 );
301     if ( static_cast< sal_uInt32 >( nIndex ) >= m_vEntries.size())
302         throw lang::IllegalArgumentException( OUSTR("There is no element at the provided position."
303         "The position exceeds the number of available list entries"),0, 0 );
304 }
305 
306 //------------------------------------------------------------------------------
getItemName(sal_Int32 nIndex) const307 rtl::OUString ExtensionBox_Impl::getItemName( sal_Int32 nIndex ) const
308 {
309     const ::osl::MutexGuard aGuard( m_entriesMutex );
310     checkIndex( nIndex );
311     return m_vEntries[ nIndex ]->m_sTitle;
312 }
313 
314 //------------------------------------------------------------------------------
getItemVersion(sal_Int32 nIndex) const315 rtl::OUString ExtensionBox_Impl::getItemVersion( sal_Int32 nIndex ) const
316 {
317     const ::osl::MutexGuard aGuard( m_entriesMutex );
318     checkIndex( nIndex );
319     return m_vEntries[ nIndex ]->m_sVersion;
320 }
321 
322 //------------------------------------------------------------------------------
getItemDescription(sal_Int32 nIndex) const323 rtl::OUString ExtensionBox_Impl::getItemDescription( sal_Int32 nIndex ) const
324 {
325     const ::osl::MutexGuard aGuard( m_entriesMutex );
326     checkIndex( nIndex );
327     return m_vEntries[ nIndex ]->m_sDescription;
328 }
329 
330 //------------------------------------------------------------------------------
getItemPublisher(sal_Int32 nIndex) const331 rtl::OUString ExtensionBox_Impl::getItemPublisher( sal_Int32 nIndex ) const
332 {
333     const ::osl::MutexGuard aGuard( m_entriesMutex );
334     checkIndex( nIndex );
335     return m_vEntries[ nIndex ]->m_sPublisher;
336 }
337 
338 //------------------------------------------------------------------------------
getItemPublisherLink(sal_Int32 nIndex) const339 rtl::OUString ExtensionBox_Impl::getItemPublisherLink( sal_Int32 nIndex ) const
340 {
341     const ::osl::MutexGuard aGuard( m_entriesMutex );
342     checkIndex( nIndex );
343     return m_vEntries[ nIndex ]->m_sPublisherURL;
344 }
345 
346 //------------------------------------------------------------------------------
select(sal_Int32 nIndex)347 void ExtensionBox_Impl::select( sal_Int32 nIndex )
348 {
349     const ::osl::MutexGuard aGuard( m_entriesMutex );
350     checkIndex( nIndex );
351     selectEntry( nIndex );
352 }
353 
354 //------------------------------------------------------------------------------
select(const rtl::OUString & sName)355 void ExtensionBox_Impl::select( const rtl::OUString & sName )
356 {
357     const ::osl::MutexGuard aGuard( m_entriesMutex );
358     typedef ::std::vector< TEntry_Impl >::const_iterator It;
359 
360     for ( It iIter = m_vEntries.begin(); iIter < m_vEntries.end(); iIter++ )
361     {
362         if ( sName.equals( (*iIter)->m_sTitle ) )
363         {
364             long nPos = iIter - m_vEntries.begin();
365             selectEntry( nPos );
366             break;
367         }
368     }
369 }
370 
371 //------------------------------------------------------------------------------
372 //------------------------------------------------------------------------------
373 // Title + description
CalcActiveHeight(const long nPos)374 void ExtensionBox_Impl::CalcActiveHeight( const long nPos )
375 {
376     const ::osl::MutexGuard aGuard( m_entriesMutex );
377 
378     // get title height
379     long aTextHeight;
380     long nIconHeight = 2*TOP_OFFSET + SMALL_ICON_SIZE;
381     long nTitleHeight = 2*TOP_OFFSET + GetTextHeight();
382     if ( nIconHeight < nTitleHeight )
383         aTextHeight = nTitleHeight;
384     else
385         aTextHeight = nIconHeight;
386 
387     // calc description height
388     Size aSize = GetOutputSizePixel();
389     if ( m_bHasScrollBar )
390         aSize.Width() -= m_pScrollBar->GetSizePixel().Width();
391 
392     aSize.Width() -= ICON_OFFSET;
393     aSize.Height() = 10000;
394 
395     rtl::OUString aText( m_vEntries[ nPos ]->m_sErrorText );
396     if ( aText.getLength() )
397         aText += OUSTR("\n");
398     aText += m_vEntries[ nPos ]->m_sDescription;
399 
400     Rectangle aRect = GetTextRect( Rectangle( Point(), aSize ), aText,
401                                    TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
402     aTextHeight += aRect.GetHeight();
403 
404     if ( aTextHeight < m_nStdHeight )
405         aTextHeight = m_nStdHeight;
406 
407     if ( m_vEntries[ nPos ]->m_bHasButtons )
408         m_nActiveHeight = aTextHeight + m_nExtraHeight;
409     else
410         m_nActiveHeight = aTextHeight + 2;
411 }
412 
413 //------------------------------------------------------------------------------
GetMinOutputSizePixel() const414 const Size ExtensionBox_Impl::GetMinOutputSizePixel() const
415 {
416     return Size( 200, 80 );
417 }
418 
419 //------------------------------------------------------------------------------
GetEntryRect(const long nPos) const420 Rectangle ExtensionBox_Impl::GetEntryRect( const long nPos ) const
421 {
422     const ::osl::MutexGuard aGuard( m_entriesMutex );
423 
424     Size aSize( GetOutputSizePixel() );
425 
426     if ( m_bHasScrollBar )
427         aSize.Width() -= m_pScrollBar->GetSizePixel().Width();
428 
429     if ( m_vEntries[ nPos ]->m_bActive )
430         aSize.Height() = m_nActiveHeight;
431     else
432         aSize.Height() = m_nStdHeight;
433 
434     Point aPos( 0, -m_nTopIndex + nPos * m_nStdHeight );
435     if ( m_bHasActive && ( nPos < m_nActive ) )
436         aPos.Y() += m_nActiveHeight - m_nStdHeight;
437 
438     return Rectangle( aPos, aSize );
439 }
440 
441 //------------------------------------------------------------------------------
DeleteRemoved()442 void ExtensionBox_Impl::DeleteRemoved()
443 {
444     const ::osl::MutexGuard aGuard( m_entriesMutex );
445 
446     m_bInDelete = true;
447 
448     if ( ! m_vRemovedEntries.empty() )
449     {
450         typedef std::vector< TEntry_Impl >::iterator ITER;
451 
452         for ( ITER iIndex = m_vRemovedEntries.begin(); iIndex < m_vRemovedEntries.end(); ++iIndex )
453         {
454             if ( (*iIndex)->m_pPublisher )
455             {
456                 delete (*iIndex)->m_pPublisher;
457                 (*iIndex)->m_pPublisher = NULL;
458             }
459         }
460 
461         m_vRemovedEntries.clear();
462     }
463 
464     m_bInDelete = false;
465 }
466 
467 //------------------------------------------------------------------------------
468 //This function may be called with nPos < 0
selectEntry(const long nPos)469 void ExtensionBox_Impl::selectEntry( const long nPos )
470 {
471     //ToDo whe should not use the guard at such a big scope here.
472     //Currently it is used to gard m_vEntries and m_nActive. m_nActive will be
473     //modified in this function.
474     //It would be probably best to always use a copy of m_vEntries
475     //and some other state variables from ExtensionBox_Impl for
476     //the whole painting operation. See issue i86993
477     ::osl::ClearableMutexGuard guard(m_entriesMutex);
478 
479     if ( m_bInCheckMode )
480         return;
481 
482     if ( m_bHasActive )
483     {
484         if ( nPos == m_nActive )
485             return;
486 
487         m_bHasActive = false;
488         m_vEntries[ m_nActive ]->m_bActive = false;
489     }
490 
491     if ( ( nPos >= 0 ) && ( nPos < (long) m_vEntries.size() ) )
492     {
493         m_bHasActive = true;
494         m_nActive = nPos;
495         m_vEntries[ nPos ]->m_bActive = true;
496 
497         if ( IsReallyVisible() )
498         {
499             m_bAdjustActive = true;
500         }
501     }
502 
503     if ( IsReallyVisible() )
504     {
505         m_bNeedsRecalc = true;
506         Invalidate();
507     }
508 
509     guard.clear();
510 }
511 
512 // -----------------------------------------------------------------------
DrawRow(const Rectangle & rRect,const TEntry_Impl pEntry)513 void ExtensionBox_Impl::DrawRow( const Rectangle& rRect, const TEntry_Impl pEntry )
514 {
515     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
516 
517     if ( pEntry->m_bActive )
518         SetTextColor( rStyleSettings.GetHighlightTextColor() );
519     else if ( ( pEntry->m_eState != REGISTERED ) && ( pEntry->m_eState != NOT_AVAILABLE ) )
520         SetTextColor( rStyleSettings.GetDisableColor() );
521     else if ( IsControlForeground() )
522         SetTextColor( GetControlForeground() );
523     else
524         SetTextColor( rStyleSettings.GetFieldTextColor() );
525 
526     if ( pEntry->m_bActive )
527     {
528         SetLineColor();
529         SetFillColor( rStyleSettings.GetHighlightColor() );
530         DrawRect( rRect );
531     }
532     else
533     {
534         if( IsControlBackground() )
535             SetBackground( GetControlBackground() );
536         else
537             SetBackground( rStyleSettings.GetFieldColor() );
538 
539         SetTextFillColor();
540         Erase( rRect );
541     }
542 
543     // Draw extension icon
544     Point aPos( rRect.TopLeft() );
545     aPos += Point( TOP_OFFSET, TOP_OFFSET );
546     Image aImage;
547     if ( ! pEntry->m_aIcon )
548         aImage = isHCMode() ? m_aDefaultImageHC : m_aDefaultImage;
549     else
550         aImage = isHCMode() ? pEntry->m_aIconHC : pEntry->m_aIcon;
551     Size aImageSize = aImage.GetSizePixel();
552     if ( ( aImageSize.Width() <= ICON_WIDTH ) && ( aImageSize.Height() <= ICON_HEIGHT ) )
553         DrawImage( Point( aPos.X()+((ICON_WIDTH-aImageSize.Width())/2), aPos.Y()+((ICON_HEIGHT-aImageSize.Height())/2) ), aImage );
554     else
555         DrawImage( aPos, Size( ICON_WIDTH, ICON_HEIGHT ), aImage );
556 
557     // Setup fonts
558     Font aStdFont( GetFont() );
559     Font aBoldFont( aStdFont );
560     aBoldFont.SetWeight( WEIGHT_BOLD );
561     SetFont( aBoldFont );
562     long aTextHeight = GetTextHeight();
563 
564     // Init publisher link here
565     if ( !pEntry->m_pPublisher && pEntry->m_sPublisher.Len() )
566     {
567         pEntry->m_pPublisher = new svt::FixedHyperlink( this );
568         pEntry->m_pPublisher->SetBackground();
569         pEntry->m_pPublisher->SetPaintTransparent( true );
570         pEntry->m_pPublisher->SetURL( pEntry->m_sPublisherURL );
571         pEntry->m_pPublisher->SetDescription( pEntry->m_sPublisher );
572         Size aSize = FixedText::CalcMinimumTextSize( pEntry->m_pPublisher );
573         pEntry->m_pPublisher->SetSizePixel( aSize );
574 
575         if ( m_aClickHdl.IsSet() )
576             pEntry->m_pPublisher->SetClickHdl( m_aClickHdl );
577     }
578 
579     // Get max title width
580     long nMaxTitleWidth = rRect.GetWidth() - ICON_OFFSET;
581     nMaxTitleWidth -= ( 2 * SMALL_ICON_SIZE ) + ( 4 * SPACE_BETWEEN );
582     if ( pEntry->m_pPublisher )
583     {
584         nMaxTitleWidth -= pEntry->m_pPublisher->GetSizePixel().Width() + (2*SPACE_BETWEEN);
585     }
586 
587     long aVersionWidth = GetTextWidth( pEntry->m_sVersion );
588     long aTitleWidth = GetTextWidth( pEntry->m_sTitle ) + (aTextHeight / 3);
589 
590     aPos = rRect.TopLeft() + Point( ICON_OFFSET, TOP_OFFSET );
591 
592     if ( aTitleWidth > nMaxTitleWidth - aVersionWidth )
593     {
594         aTitleWidth = nMaxTitleWidth - aVersionWidth - (aTextHeight / 3);
595         String aShortTitle = GetEllipsisString( pEntry->m_sTitle, aTitleWidth );
596         DrawText( aPos, aShortTitle );
597         aTitleWidth += (aTextHeight / 3);
598     }
599     else
600         DrawText( aPos, pEntry->m_sTitle );
601 
602     SetFont( aStdFont );
603     DrawText( Point( aPos.X() + aTitleWidth, aPos.Y() ), pEntry->m_sVersion );
604 
605     long nIconHeight = TOP_OFFSET + SMALL_ICON_SIZE;
606     long nTitleHeight = TOP_OFFSET + GetTextHeight();
607     if ( nIconHeight < nTitleHeight )
608         aTextHeight = nTitleHeight;
609     else
610         aTextHeight = nIconHeight;
611 
612     // draw description
613     String sDescription;
614     if ( pEntry->m_sErrorText.Len() )
615     {
616         if ( pEntry->m_bActive )
617             sDescription = pEntry->m_sErrorText + OUSTR("\n") + pEntry->m_sDescription;
618         else
619             sDescription = pEntry->m_sErrorText;
620     }
621     else
622         sDescription = pEntry->m_sDescription;
623 
624     aPos.Y() += aTextHeight;
625     if ( pEntry->m_bActive )
626     {
627         long nExtraHeight = 0;
628 
629         if ( pEntry->m_bHasButtons )
630             nExtraHeight = m_nExtraHeight;
631 
632         DrawText( Rectangle( aPos.X(), aPos.Y(), rRect.Right(), rRect.Bottom() - nExtraHeight ),
633                   sDescription, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
634     }
635     else
636     {
637         const long nWidth = GetTextWidth( sDescription );
638         if ( nWidth > rRect.GetWidth() - aPos.X() )
639             sDescription = GetEllipsisString( sDescription, rRect.GetWidth() - aPos.X() );
640         DrawText( aPos, sDescription );
641     }
642 
643     // Draw publisher link
644     if ( pEntry->m_pPublisher )
645     {
646         pEntry->m_pPublisher->Show();
647         aPos = rRect.TopLeft() + Point( ICON_OFFSET + nMaxTitleWidth + (2*SPACE_BETWEEN), TOP_OFFSET );
648         pEntry->m_pPublisher->SetPosPixel( aPos );
649     }
650 
651     // Draw status icons
652     if ( !pEntry->m_bUser )
653     {
654         aPos = rRect.TopRight() + Point( -(RIGHT_ICON_OFFSET + SMALL_ICON_SIZE), TOP_OFFSET );
655         if ( pEntry->m_bLocked )
656             DrawImage( aPos, Size( SMALL_ICON_SIZE, SMALL_ICON_SIZE ), isHCMode() ? m_aLockedImageHC : m_aLockedImage );
657         else
658             DrawImage( aPos, Size( SMALL_ICON_SIZE, SMALL_ICON_SIZE ), isHCMode() ? m_aSharedImageHC : m_aSharedImage );
659     }
660     if ( ( pEntry->m_eState == AMBIGUOUS ) || pEntry->m_bMissingDeps || pEntry->m_bMissingLic )
661     {
662         aPos = rRect.TopRight() + Point( -(RIGHT_ICON_OFFSET + SPACE_BETWEEN + 2*SMALL_ICON_SIZE), TOP_OFFSET );
663         DrawImage( aPos, Size( SMALL_ICON_SIZE, SMALL_ICON_SIZE ), isHCMode() ? m_aWarningImageHC : m_aWarningImage );
664     }
665 
666     SetLineColor( Color( COL_LIGHTGRAY ) );
667     DrawLine( rRect.BottomLeft(), rRect.BottomRight() );
668 }
669 
670 // -----------------------------------------------------------------------
RecalcAll()671 void ExtensionBox_Impl::RecalcAll()
672 {
673     if ( m_bHasActive )
674         CalcActiveHeight( m_nActive );
675 
676     SetupScrollBar();
677 
678     if ( m_bHasActive )
679     {
680         Rectangle aEntryRect = GetEntryRect( m_nActive );
681 
682         if ( m_bAdjustActive )
683         {
684             m_bAdjustActive = false;
685 
686             // If the top of the selected entry isn't visible, make it visible
687             if ( aEntryRect.Top() < 0 )
688             {
689                 m_nTopIndex += aEntryRect.Top();
690                 aEntryRect.Move( 0, -aEntryRect.Top() );
691             }
692 
693             // If the bottom of the selected entry isn't visible, make it visible even if now the top
694             // isn't visible any longer ( the buttons are more important )
695             Size aOutputSize = GetOutputSizePixel();
696             if ( aEntryRect.Bottom() > aOutputSize.Height() )
697             {
698                 m_nTopIndex += ( aEntryRect.Bottom() - aOutputSize.Height() );
699                 aEntryRect.Move( 0, -( aEntryRect.Bottom() - aOutputSize.Height() ) );
700             }
701 
702             // If there is unused space below the last entry but all entries don't fit into the box,
703             // move the content down to use the whole space
704             const long nTotalHeight = GetTotalHeight();
705             if ( m_bHasScrollBar && ( aOutputSize.Height() + m_nTopIndex > nTotalHeight ) )
706             {
707                 long nOffset = m_nTopIndex;
708                 m_nTopIndex = nTotalHeight - aOutputSize.Height();
709                 nOffset -= m_nTopIndex;
710                 aEntryRect.Move( 0, nOffset );
711             }
712 
713             if ( m_bHasScrollBar )
714                 m_pScrollBar->SetThumbPos( m_nTopIndex );
715         }
716     }
717 
718     m_bNeedsRecalc = false;
719 }
720 
721 // -----------------------------------------------------------------------
HandleTabKey(bool)722 bool ExtensionBox_Impl::HandleTabKey( bool )
723 {
724     return false;
725 }
726 
727 // -----------------------------------------------------------------------
HandleCursorKey(sal_uInt16 nKeyCode)728 bool ExtensionBox_Impl::HandleCursorKey( sal_uInt16 nKeyCode )
729 {
730     if ( m_vEntries.empty() )
731         return true;
732 
733     long nSelect = 0;
734 
735     if ( m_bHasActive )
736     {
737         long nPageSize = GetOutputSizePixel().Height() / m_nStdHeight;
738         if ( nPageSize < 2 )
739             nPageSize = 2;
740 
741         if ( ( nKeyCode == KEY_DOWN ) || ( nKeyCode == KEY_RIGHT ) )
742             nSelect = m_nActive + 1;
743         else if ( ( nKeyCode == KEY_UP ) || ( nKeyCode == KEY_LEFT ) )
744             nSelect = m_nActive - 1;
745         else if ( nKeyCode == KEY_HOME )
746             nSelect = 0;
747         else if ( nKeyCode == KEY_END )
748             nSelect = m_vEntries.size() - 1;
749         else if ( nKeyCode == KEY_PAGEUP )
750             nSelect = m_nActive - nPageSize + 1;
751         else if ( nKeyCode == KEY_PAGEDOWN )
752             nSelect = m_nActive + nPageSize - 1;
753     }
754     else // when there is no selected entry, we will select the first or the last.
755     {
756         if ( ( nKeyCode == KEY_DOWN ) || ( nKeyCode == KEY_PAGEDOWN ) || ( nKeyCode == KEY_HOME ) )
757             nSelect = 0;
758         else if ( ( nKeyCode == KEY_UP ) || ( nKeyCode == KEY_PAGEUP ) || ( nKeyCode == KEY_END ) )
759             nSelect = m_vEntries.size() - 1;
760     }
761 
762     if ( nSelect < 0 )
763         nSelect = 0;
764     if ( nSelect >= (long) m_vEntries.size() )
765         nSelect = m_vEntries.size() - 1;
766 
767     selectEntry( nSelect );
768 
769     return true;
770 }
771 
772 // -----------------------------------------------------------------------
Paint(const Rectangle &)773 void ExtensionBox_Impl::Paint( const Rectangle &/*rPaintRect*/ )
774 {
775     if ( !m_bInDelete )
776         DeleteRemoved();
777 
778     if ( m_bNeedsRecalc )
779         RecalcAll();
780 
781     Point aStart( 0, -m_nTopIndex );
782     Size aSize( GetOutputSizePixel() );
783 
784     if ( m_bHasScrollBar )
785         aSize.Width() -= m_pScrollBar->GetSizePixel().Width();
786 
787     const ::osl::MutexGuard aGuard( m_entriesMutex );
788 
789     typedef std::vector< TEntry_Impl >::iterator ITER;
790     for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex )
791     {
792         aSize.Height() = (*iIndex)->m_bActive ? m_nActiveHeight : m_nStdHeight;
793         Rectangle aEntryRect( aStart, aSize );
794         DrawRow( aEntryRect, *iIndex );
795         aStart.Y() += aSize.Height();
796     }
797 }
798 
799 // -----------------------------------------------------------------------
GetTotalHeight() const800 long ExtensionBox_Impl::GetTotalHeight() const
801 {
802     long nHeight = m_vEntries.size() * m_nStdHeight;
803 
804     if ( m_bHasActive )
805     {
806         nHeight += m_nActiveHeight - m_nStdHeight;
807     }
808 
809     return nHeight;
810 }
811 
812 // -----------------------------------------------------------------------
SetupScrollBar()813 void ExtensionBox_Impl::SetupScrollBar()
814 {
815     const Size aSize = GetOutputSizePixel();
816     const long nScrBarSize = GetSettings().GetStyleSettings().GetScrollBarSize();
817     const long nTotalHeight = GetTotalHeight();
818     const bool bNeedsScrollBar = ( nTotalHeight > aSize.Height() );
819 
820     if ( bNeedsScrollBar )
821     {
822         if ( m_nTopIndex + aSize.Height() > nTotalHeight )
823             m_nTopIndex = nTotalHeight - aSize.Height();
824 
825         m_pScrollBar->SetPosSizePixel( Point( aSize.Width() - nScrBarSize, 0 ),
826                                        Size( nScrBarSize, aSize.Height() ) );
827         m_pScrollBar->SetRangeMax( nTotalHeight );
828         m_pScrollBar->SetVisibleSize( aSize.Height() );
829         m_pScrollBar->SetPageSize( ( aSize.Height() * 4 ) / 5 );
830         m_pScrollBar->SetLineSize( m_nStdHeight );
831         m_pScrollBar->SetThumbPos( m_nTopIndex );
832 
833         if ( !m_bHasScrollBar )
834             m_pScrollBar->Show();
835     }
836     else if ( m_bHasScrollBar )
837     {
838         m_pScrollBar->Hide();
839         m_nTopIndex = 0;
840     }
841 
842     m_bHasScrollBar = bNeedsScrollBar;
843 }
844 
845 // -----------------------------------------------------------------------
Resize()846 void ExtensionBox_Impl::Resize()
847 {
848     RecalcAll();
849 }
850 
851 //------------------------------------------------------------------------------
PointToPos(const Point & rPos)852 long ExtensionBox_Impl::PointToPos( const Point& rPos )
853 {
854     long nPos = ( rPos.Y() + m_nTopIndex ) / m_nStdHeight;
855 
856     if ( m_bHasActive && ( nPos > m_nActive ) )
857     {
858         if ( rPos.Y() + m_nTopIndex <= m_nActive*m_nStdHeight + m_nActiveHeight )
859             nPos = m_nActive;
860         else
861             nPos = ( rPos.Y() + m_nTopIndex - (m_nActiveHeight - m_nStdHeight) ) / m_nStdHeight;
862     }
863 
864     return nPos;
865 }
866 
867 //------------------------------------------------------------------------------
MouseButtonDown(const MouseEvent & rMEvt)868 void ExtensionBox_Impl::MouseButtonDown( const MouseEvent& rMEvt )
869 {
870     long nPos = PointToPos( rMEvt.GetPosPixel() );
871 
872     if ( rMEvt.IsLeft() )
873     {
874         if ( rMEvt.IsMod1() && m_bHasActive )
875             selectEntry( m_vEntries.size() );   // Selecting an not existing entry will deselect the current one
876         else
877             selectEntry( nPos );
878     }
879 }
880 
881 //------------------------------------------------------------------------------
Notify(NotifyEvent & rNEvt)882 long ExtensionBox_Impl::Notify( NotifyEvent& rNEvt )
883 {
884     if ( !m_bInDelete )
885         DeleteRemoved();
886 
887     bool bHandled = false;
888 
889     if ( rNEvt.GetType() == EVENT_KEYINPUT )
890     {
891         const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
892         KeyCode         aKeyCode = pKEvt->GetKeyCode();
893         sal_uInt16          nKeyCode = aKeyCode.GetCode();
894 
895         if ( nKeyCode == KEY_TAB )
896             bHandled = HandleTabKey( aKeyCode.IsShift() );
897         else if ( aKeyCode.GetGroup() == KEYGROUP_CURSOR )
898             bHandled = HandleCursorKey( nKeyCode );
899     }
900 
901     if ( rNEvt.GetType() == EVENT_COMMAND )
902     {
903         if ( m_bHasScrollBar &&
904              ( rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL ) )
905         {
906             const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
907             if ( pData->GetMode() == COMMAND_WHEEL_SCROLL )
908             {
909                 long nThumbPos = m_pScrollBar->GetThumbPos();
910                 if ( pData->GetDelta() < 0 )
911                     m_pScrollBar->DoScroll( nThumbPos + m_nStdHeight );
912                 else
913                     m_pScrollBar->DoScroll( nThumbPos - m_nStdHeight );
914                 bHandled = true;
915             }
916         }
917     }
918 
919     if ( !bHandled )
920         return Control::Notify( rNEvt );
921     else
922         return true;
923 }
924 
925 //------------------------------------------------------------------------------
FindEntryPos(const TEntry_Impl pEntry,const long nStart,const long nEnd,long & nPos)926 bool ExtensionBox_Impl::FindEntryPos( const TEntry_Impl pEntry, const long nStart,
927                                       const long nEnd, long &nPos )
928 {
929     nPos = nStart;
930     if ( nStart > nEnd )
931         return false;
932 
933     StringCompare eCompare;
934 
935     if ( nStart == nEnd )
936     {
937         eCompare = pEntry->CompareTo( m_pCollator, m_vEntries[ nStart ] );
938         if ( eCompare == COMPARE_LESS )
939             return false;
940         else if ( eCompare == COMPARE_EQUAL )
941         {
942             //Workaround. See i86963.
943             if (pEntry->m_xPackage != m_vEntries[nStart]->m_xPackage)
944                 return false;
945 
946             if ( m_bInCheckMode )
947                 m_vEntries[ nStart ]->m_bChecked = true;
948             return true;
949         }
950         else
951         {
952             nPos = nStart + 1;
953             return false;
954         }
955     }
956 
957     const long nMid = nStart + ( ( nEnd - nStart ) / 2 );
958     eCompare = pEntry->CompareTo( m_pCollator, m_vEntries[ nMid ] );
959 
960     if ( eCompare == COMPARE_LESS )
961         return FindEntryPos( pEntry, nStart, nMid-1, nPos );
962     else if ( eCompare == COMPARE_GREATER )
963         return FindEntryPos( pEntry, nMid+1, nEnd, nPos );
964     else
965     {
966         //Workaround.See i86963.
967         if (pEntry->m_xPackage != m_vEntries[nMid]->m_xPackage)
968             return false;
969 
970         if ( m_bInCheckMode )
971             m_vEntries[ nMid ]->m_bChecked = true;
972         nPos = nMid;
973         return true;
974     }
975 }
976 
cleanVecListenerAdded()977 void ExtensionBox_Impl::cleanVecListenerAdded()
978 {
979     typedef ::std::vector<uno::WeakReference<deployment::XPackage> >::iterator IT;
980     IT i = m_vListenerAdded.begin();
981     while( i != m_vListenerAdded.end())
982     {
983         const uno::Reference<deployment::XPackage> hardRef(*i);
984         if (!hardRef.is())
985             i = m_vListenerAdded.erase(i);
986         else
987             ++i;
988     }
989 }
990 
addEventListenerOnce(uno::Reference<deployment::XPackage> const & extension)991 void ExtensionBox_Impl::addEventListenerOnce(
992     uno::Reference<deployment::XPackage > const & extension)
993 {
994     //make sure to only add the listener once
995     cleanVecListenerAdded();
996     if ( ::std::find_if(m_vListenerAdded.begin(), m_vListenerAdded.end(),
997                         FindWeakRef(extension))
998          == m_vListenerAdded.end())
999     {
1000         extension->addEventListener( uno::Reference< lang::XEventListener > (
1001                                          m_xRemoveListener, uno::UNO_QUERY ) );
1002         m_vListenerAdded.push_back(extension);
1003     }
1004 }
1005 
1006 //------------------------------------------------------------------------------
addEntry(const uno::Reference<deployment::XPackage> & xPackage,bool bLicenseMissing)1007 long ExtensionBox_Impl::addEntry( const uno::Reference< deployment::XPackage > &xPackage,
1008                                   bool bLicenseMissing )
1009 {
1010     long         nPos = 0;
1011     PackageState eState = m_pManager->getPackageState( xPackage );
1012     bool         bLocked = m_pManager->isReadOnly( xPackage );
1013 
1014     TEntry_Impl pEntry( new Entry_Impl( xPackage, eState, bLocked ) );
1015 
1016     // Don't add empty entries
1017     if ( ! pEntry->m_sTitle.Len() )
1018         return 0;
1019 
1020     ::osl::ClearableMutexGuard guard(m_entriesMutex);
1021     if ( m_vEntries.empty() )
1022     {
1023         addEventListenerOnce(xPackage);
1024         m_vEntries.push_back( pEntry );
1025     }
1026     else
1027     {
1028         if ( !FindEntryPos( pEntry, 0, m_vEntries.size()-1, nPos ) )
1029         {
1030             addEventListenerOnce(xPackage);
1031             m_vEntries.insert( m_vEntries.begin()+nPos, pEntry );
1032         }
1033         else if ( !m_bInCheckMode )
1034         {
1035             OSL_ENSURE( 0, "ExtensionBox_Impl::addEntry(): Will not add duplicate entries"  );
1036         }
1037     }
1038 
1039     pEntry->m_bHasOptions = m_pManager->supportsOptions( xPackage );
1040     pEntry->m_bUser       = xPackage->getRepositoryName().equals( USER_PACKAGE_MANAGER );
1041     pEntry->m_bShared     = xPackage->getRepositoryName().equals( SHARED_PACKAGE_MANAGER );
1042     pEntry->m_bNew        = m_bInCheckMode;
1043     pEntry->m_bMissingLic = bLicenseMissing;
1044 
1045     if ( bLicenseMissing )
1046         pEntry->m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_MISSING_LICENSE );
1047 
1048     //access to m_nActive must be guarded
1049     if ( !m_bInCheckMode && m_bHasActive && ( m_nActive >= nPos ) )
1050         m_nActive += 1;
1051 
1052     guard.clear();
1053 
1054     if ( IsReallyVisible() )
1055         Invalidate();
1056 
1057     m_bNeedsRecalc = true;
1058 
1059     return nPos;
1060 }
1061 
1062 //------------------------------------------------------------------------------
updateEntry(const uno::Reference<deployment::XPackage> & xPackage)1063 void ExtensionBox_Impl::updateEntry( const uno::Reference< deployment::XPackage > &xPackage )
1064 {
1065     typedef std::vector< TEntry_Impl >::iterator ITER;
1066     for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex )
1067     {
1068         if ( (*iIndex)->m_xPackage == xPackage )
1069         {
1070             PackageState eState = m_pManager->getPackageState( xPackage );
1071             (*iIndex)->m_bHasOptions = m_pManager->supportsOptions( xPackage );
1072             (*iIndex)->m_eState = eState;
1073             (*iIndex)->m_sTitle = xPackage->getDisplayName();
1074             (*iIndex)->m_sVersion = xPackage->getVersion();
1075             (*iIndex)->m_sDescription = xPackage->getDescription();
1076 
1077             if ( eState == REGISTERED )
1078                 (*iIndex)->m_bMissingLic = false;
1079 
1080             if ( eState == AMBIGUOUS )
1081                 (*iIndex)->m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_UNKNOWN_STATUS );
1082             else if ( ! (*iIndex)->m_bMissingLic )
1083                 (*iIndex)->m_sErrorText = String();
1084 
1085             if ( IsReallyVisible() )
1086                 Invalidate();
1087             break;
1088         }
1089     }
1090 }
1091 
1092 //------------------------------------------------------------------------------
1093 //This function is also called as a result of removing an extension.
1094 //see PackageManagerImpl::removePackage
1095 //The gui is a registered as listener on the package. Removing it will cause the
1096 //listeners to be notified an then this function is called. At this moment xPackage
1097 //is in the disposing state and all calls on it may result in a DisposedException.
removeEntry(const uno::Reference<deployment::XPackage> & xPackage)1098 void ExtensionBox_Impl::removeEntry( const uno::Reference< deployment::XPackage > &xPackage )
1099 {
1100    if ( ! m_bInDelete )
1101     {
1102         ::osl::ClearableMutexGuard aGuard( m_entriesMutex );
1103 
1104         typedef std::vector< TEntry_Impl >::iterator ITER;
1105 
1106         for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex )
1107         {
1108             if ( (*iIndex)->m_xPackage == xPackage )
1109             {
1110                 long nPos = iIndex - m_vEntries.begin();
1111 
1112                 // Entries mustn't removed here, because they contain a hyperlink control
1113                 // which can only be deleted when the thread has the solar mutex. Therefor
1114                 // the entry will be moved into the m_vRemovedEntries list which will be
1115                 // cleared on the next paint event
1116                 m_vRemovedEntries.push_back( *iIndex );
1117                 (*iIndex)->m_xPackage->removeEventListener(
1118                     uno::Reference<lang::XEventListener>(m_xRemoveListener, uno::UNO_QUERY));
1119                 m_vEntries.erase( iIndex );
1120 
1121                 m_bNeedsRecalc = true;
1122 
1123                 if ( IsReallyVisible() )
1124                     Invalidate();
1125 
1126                 if ( m_bHasActive )
1127                 {
1128                     if ( nPos < m_nActive )
1129                         m_nActive -= 1;
1130                     else if ( ( nPos == m_nActive ) &&
1131                               ( nPos == (long) m_vEntries.size() ) )
1132                         m_nActive -= 1;
1133 
1134                     m_bHasActive = false;
1135                     //clear before calling out of this method
1136                     aGuard.clear();
1137                     selectEntry( m_nActive );
1138                 }
1139                 break;
1140             }
1141         }
1142     }
1143 }
1144 
1145 //------------------------------------------------------------------------------
RemoveUnlocked()1146 void ExtensionBox_Impl::RemoveUnlocked()
1147 {
1148     bool bAllRemoved = false;
1149 
1150     while ( ! bAllRemoved )
1151     {
1152         bAllRemoved = true;
1153 
1154         ::osl::ClearableMutexGuard aGuard( m_entriesMutex );
1155 
1156         typedef std::vector< TEntry_Impl >::iterator ITER;
1157 
1158         for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex )
1159         {
1160             if ( !(*iIndex)->m_bLocked )
1161             {
1162                 bAllRemoved = false;
1163                 uno::Reference< deployment::XPackage> xPackage = (*iIndex)->m_xPackage;
1164                 aGuard.clear();
1165                 removeEntry( xPackage );
1166                 break;
1167             }
1168         }
1169     }
1170 }
1171 
1172 //------------------------------------------------------------------------------
prepareChecking()1173 void ExtensionBox_Impl::prepareChecking()
1174 {
1175     m_bInCheckMode = true;
1176     typedef std::vector< TEntry_Impl >::iterator ITER;
1177     for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex )
1178     {
1179         (*iIndex)->m_bChecked = false;
1180         (*iIndex)->m_bNew = false;
1181     }
1182 }
1183 
1184 //------------------------------------------------------------------------------
checkEntries()1185 void ExtensionBox_Impl::checkEntries()
1186 {
1187     long nNewPos = -1;
1188     long nPos = 0;
1189     bool bNeedsUpdate = false;
1190 
1191     ::osl::ClearableMutexGuard guard(m_entriesMutex);
1192     typedef std::vector< TEntry_Impl >::iterator ITER;
1193     ITER iIndex = m_vEntries.begin();
1194     while ( iIndex < m_vEntries.end() )
1195     {
1196         if ( (*iIndex)->m_bChecked == false )
1197         {
1198             (*iIndex)->m_bChecked = true;
1199             bNeedsUpdate = true;
1200             nPos = iIndex-m_vEntries.begin();
1201             if ( (*iIndex)->m_bNew )
1202             { // add entry to list and correct active pos
1203                 if ( nNewPos == - 1)
1204                     nNewPos = nPos;
1205                 if ( nPos <= m_nActive )
1206                     m_nActive += 1;
1207                 iIndex++;
1208             }
1209             else
1210             {   // remove entry from list
1211                 if ( nPos < m_nActive )
1212                     m_nActive -= 1;
1213                 else if ( ( nPos == m_nActive ) && ( nPos == (long) m_vEntries.size() - 1 ) )
1214                     m_nActive -= 1;
1215                 m_vRemovedEntries.push_back( *iIndex );
1216                 m_vEntries.erase( iIndex );
1217                 iIndex = m_vEntries.begin() + nPos;
1218             }
1219         }
1220         else
1221             iIndex++;
1222     }
1223     guard.clear();
1224 
1225     m_bInCheckMode = false;
1226 
1227     if ( nNewPos != - 1)
1228         selectEntry( nNewPos );
1229 
1230     if ( bNeedsUpdate )
1231     {
1232         m_bNeedsRecalc = true;
1233         if ( IsReallyVisible() )
1234             Invalidate();
1235     }
1236 }
1237 //------------------------------------------------------------------------------
isHCMode()1238 bool ExtensionBox_Impl::isHCMode()
1239 {
1240     return (bool)GetSettings().GetStyleSettings().GetHighContrastMode();
1241 }
1242 
1243 //------------------------------------------------------------------------------
SetScrollHdl(const Link & rLink)1244 void ExtensionBox_Impl::SetScrollHdl( const Link& rLink )
1245 {
1246     if ( m_pScrollBar )
1247         m_pScrollBar->SetScrollHdl( rLink );
1248 }
1249 
1250 // -----------------------------------------------------------------------
DoScroll(long nDelta)1251 void ExtensionBox_Impl::DoScroll( long nDelta )
1252 {
1253     m_nTopIndex += nDelta;
1254     Point aNewSBPt( m_pScrollBar->GetPosPixel() );
1255 
1256     Rectangle aScrRect( Point(), GetOutputSizePixel() );
1257     aScrRect.Right() -= m_pScrollBar->GetSizePixel().Width();
1258     Scroll( 0, -nDelta, aScrRect );
1259 
1260     m_pScrollBar->SetPosPixel( aNewSBPt );
1261 }
1262 
1263 // -----------------------------------------------------------------------
IMPL_LINK(ExtensionBox_Impl,ScrollHdl,ScrollBar *,pScrBar)1264 IMPL_LINK( ExtensionBox_Impl, ScrollHdl, ScrollBar*, pScrBar )
1265 {
1266     DoScroll( pScrBar->GetDelta() );
1267 
1268     return 1;
1269 }
1270 
1271 } //namespace dp_gui
1272