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