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