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