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