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