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