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