1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2009 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_desktop.hxx"
31 #include "svtools/controldims.hrc"
34 #include "dp_gui_extlistbox.hxx"
35 #include "dp_gui_theextmgr.hxx"
36 #include "dp_gui_dialog2.hxx"
37 #include "dp_dependencies.hxx"
39 #include "comphelper/processfactory.hxx"
40 #include "com/sun/star/i18n/CollatorOptions.hpp"
41 #include "com/sun/star/deployment/DependencyException.hpp"
42 #include "com/sun/star/deployment/DeploymentException.hpp"
45 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
47 using namespace ::com::sun::star
;
51 //------------------------------------------------------------------------------
53 //------------------------------------------------------------------------------
54 Entry_Impl::Entry_Impl( const uno::Reference
< deployment::XPackage
> &xPackage
,
55 const uno::Reference
< deployment::XPackageManager
> &xPackageManager
,
56 PackageState eState
) :
59 m_bHasOptions( false ),
63 m_bMissingDeps( false ),
66 m_xPackage( xPackage
),
67 m_xPackageManager( xPackageManager
)
69 m_sTitle
= xPackage
->getDisplayName();
70 m_sVersion
= xPackage
->getVersion();
71 m_sDescription
= xPackage
->getDescription();
73 beans::StringPair
aInfo( m_xPackage
->getPublisherInfo() );
74 m_sPublisher
= aInfo
.First
;
75 m_sPublisherURL
= aInfo
.Second
;
77 // get the icons for the package if there are any
78 uno::Reference
< graphic::XGraphic
> xGraphic
= xPackage
->getIcon( false );
80 m_aIcon
= Image( xGraphic
);
82 xGraphic
= xPackage
->getIcon( true );
84 m_aIconHC
= Image( xGraphic
);
88 m_bLocked
= m_xPackageManager
->isReadOnly();
90 if ( eState
== AMBIGUOUS
)
91 m_sErrorText
= DialogHelper::getResourceString( RID_STR_ERROR_UNKNOWN_STATUS
);
92 else if ( eState
== NOT_REGISTERED
)
96 //------------------------------------------------------------------------------
97 Entry_Impl::~Entry_Impl()
100 //------------------------------------------------------------------------------
101 StringCompare
Entry_Impl::CompareTo( const CollatorWrapper
*pCollator
, const TEntry_Impl pEntry
) const
103 StringCompare eCompare
= (StringCompare
) pCollator
->compareString( m_sTitle
, pEntry
->m_sTitle
);
104 if ( eCompare
== COMPARE_EQUAL
)
106 eCompare
= m_sVersion
.CompareTo( pEntry
->m_sVersion
);
107 if ( eCompare
== COMPARE_EQUAL
)
109 if ( m_xPackageManager
!= pEntry
->m_xPackageManager
)
111 sal_Int32 nCompare
= m_xPackageManager
->getContext().compareTo( pEntry
->m_xPackageManager
->getContext() );
113 eCompare
= COMPARE_LESS
;
114 else if ( nCompare
> 0 )
115 eCompare
= COMPARE_GREATER
;
122 //------------------------------------------------------------------------------
123 void Entry_Impl::checkDependencies()
126 m_xPackage
->checkDependencies( uno::Reference
< ucb::XCommandEnvironment
>() );
128 catch ( deployment::DeploymentException
&e
)
130 deployment::DependencyException depExc
;
131 if ( e
.Cause
>>= depExc
)
133 rtl::OUString
aMissingDep( DialogHelper::getResourceString( RID_STR_ERROR_MISSING_DEPENDENCIES
) );
134 for ( sal_Int32 i
= 0; i
< depExc
.UnsatisfiedDependencies
.getLength(); ++i
)
136 aMissingDep
+= OUSTR("\n");
137 aMissingDep
+= dp_misc::Dependencies::getErrorText( depExc
.UnsatisfiedDependencies
[i
]);
139 aMissingDep
+= OUSTR("\n");
140 m_sErrorText
= aMissingDep
;
141 m_bMissingDeps
= true;
145 //------------------------------------------------------------------------------
146 // ExtensionRemovedListener
147 //------------------------------------------------------------------------------
148 void ExtensionRemovedListener::disposing( lang::EventObject
const & rEvt
)
149 throw ( uno::RuntimeException
)
151 uno::Reference
< deployment::XPackage
> xPackage( rEvt
.Source
, uno::UNO_QUERY
);
155 m_pParent
->removeEntry( xPackage
);
159 //------------------------------------------------------------------------------
160 ExtensionRemovedListener::~ExtensionRemovedListener()
164 //------------------------------------------------------------------------------
166 //------------------------------------------------------------------------------
167 ExtensionBox_Impl::ExtensionBox_Impl( Dialog
* pParent
, TheExtensionManager
*pManager
) :
168 IExtensionListBox( pParent
, WB_BORDER
| WB_TABSTOP
| WB_CHILDDLGCTRL
),
169 m_bHasScrollBar( false ),
170 m_bHasActive( false ),
171 m_bNeedsRecalc( true ),
173 m_bInCheckMode( false ),
174 m_bAdjustActive( false ),
175 m_bInDelete( false ),
178 m_nActiveHeight( 0 ),
180 m_aLockedImage( DialogHelper::getResId( RID_IMG_LOCKED
) ),
181 m_aLockedImageHC( DialogHelper::getResId( RID_IMG_LOCKED_HC
) ),
182 m_aWarningImage( DialogHelper::getResId( RID_IMG_WARNING
) ),
183 m_aWarningImageHC( DialogHelper::getResId( RID_IMG_WARNING_HC
) ),
184 m_aDefaultImage( DialogHelper::getResId( RID_IMG_EXTENSION
) ),
185 m_aDefaultImageHC( DialogHelper::getResId( RID_IMG_EXTENSION_HC
) ),
186 m_pScrollBar( NULL
),
187 m_pManager( pManager
)
189 SetHelpId( HID_EXTENSION_MANAGER_LISTBOX
);
191 m_pScrollBar
= new ScrollBar( this, WB_VERT
);
192 m_pScrollBar
->SetScrollHdl( LINK( this, ExtensionBox_Impl
, ScrollHdl
) );
193 m_pScrollBar
->EnableDrag();
195 SetPaintTransparent( true );
196 SetPosPixel( Point( RSC_SP_DLG_INNERBORDER_LEFT
, RSC_SP_DLG_INNERBORDER_TOP
) );
197 long nIconHeight
= 2*TOP_OFFSET
+ SMALL_ICON_SIZE
;
198 long nTitleHeight
= 2*TOP_OFFSET
+ GetTextHeight();
199 if ( nIconHeight
< nTitleHeight
)
200 m_nStdHeight
= nTitleHeight
;
202 m_nStdHeight
= nIconHeight
;
203 m_nStdHeight
+= GetTextHeight() + TOP_OFFSET
;
205 nIconHeight
= ICON_HEIGHT
+ 2*TOP_OFFSET
+ 1;
206 if ( m_nStdHeight
< nIconHeight
)
207 m_nStdHeight
= nIconHeight
;
209 m_nActiveHeight
= m_nStdHeight
;
211 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
212 if( IsControlBackground() )
213 SetBackground( GetControlBackground() );
215 SetBackground( rStyleSettings
.GetFieldColor() );
217 m_xRemoveListener
= new ExtensionRemovedListener( this );
219 m_pLocale
= new lang::Locale( Application::GetSettings().GetLocale() );
220 m_pCollator
= new CollatorWrapper( ::comphelper::getProcessServiceFactory() );
221 m_pCollator
->loadDefaultCollator( *m_pLocale
, i18n::CollatorOptions::CollatorOptions_IGNORE_CASE
);
226 //------------------------------------------------------------------------------
227 ExtensionBox_Impl::~ExtensionBox_Impl()
234 typedef std::vector
< TEntry_Impl
>::iterator ITER
;
236 for ( ITER iIndex
= m_vEntries
.begin(); iIndex
< m_vEntries
.end(); ++iIndex
)
238 if ( (*iIndex
)->m_pPublisher
)
240 delete (*iIndex
)->m_pPublisher
;
241 (*iIndex
)->m_pPublisher
= NULL
;
243 (*iIndex
)->m_xPackage
->removeEventListener( uno::Reference
< lang::XEventListener
> ( m_xRemoveListener
, uno::UNO_QUERY
) );
250 m_xRemoveListener
.clear();
256 //------------------------------------------------------------------------------
257 sal_Int32
ExtensionBox_Impl::getItemCount() const
259 return static_cast< sal_Int32
>( m_vEntries
.size() );
262 //------------------------------------------------------------------------------
263 sal_Int32
ExtensionBox_Impl::getSelIndex() const
267 OSL_ASSERT( m_nActive
>= -1);
268 return static_cast< sal_Int32
>( m_nActive
);
271 return static_cast< sal_Int32
>( EXTENSION_LISTBOX_ENTRY_NOTFOUND
);
274 //------------------------------------------------------------------------------
275 void ExtensionBox_Impl::checkIndex( sal_Int32 nIndex
) const
278 throw lang::IllegalArgumentException( OUSTR("The list index starts with 0"),0, 0 );
279 if ( static_cast< sal_uInt32
>( nIndex
) >= m_vEntries
.size())
280 throw lang::IllegalArgumentException( OUSTR("There is no element at the provided position."
281 "The position exceeds the number of available list entries"),0, 0 );
284 //------------------------------------------------------------------------------
285 rtl::OUString
ExtensionBox_Impl::getItemName( sal_Int32 nIndex
) const
287 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
288 checkIndex( nIndex
);
289 return m_vEntries
[ nIndex
]->m_sTitle
;
292 //------------------------------------------------------------------------------
293 rtl::OUString
ExtensionBox_Impl::getItemVersion( sal_Int32 nIndex
) const
295 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
296 checkIndex( nIndex
);
297 return m_vEntries
[ nIndex
]->m_sVersion
;
300 //------------------------------------------------------------------------------
301 rtl::OUString
ExtensionBox_Impl::getItemDescription( sal_Int32 nIndex
) const
303 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
304 checkIndex( nIndex
);
305 return m_vEntries
[ nIndex
]->m_sDescription
;
308 //------------------------------------------------------------------------------
309 rtl::OUString
ExtensionBox_Impl::getItemPublisher( sal_Int32 nIndex
) const
311 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
312 checkIndex( nIndex
);
313 return m_vEntries
[ nIndex
]->m_sPublisher
;
316 //------------------------------------------------------------------------------
317 rtl::OUString
ExtensionBox_Impl::getItemPublisherLink( sal_Int32 nIndex
) const
319 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
320 checkIndex( nIndex
);
321 return m_vEntries
[ nIndex
]->m_sPublisherURL
;
324 //------------------------------------------------------------------------------
325 void ExtensionBox_Impl::select( sal_Int32 nIndex
)
327 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
328 checkIndex( nIndex
);
329 selectEntry( nIndex
);
332 //------------------------------------------------------------------------------
333 void ExtensionBox_Impl::select( const rtl::OUString
& sName
)
335 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
336 typedef ::std::vector
< TEntry_Impl
>::const_iterator It
;
338 for ( It iIter
= m_vEntries
.begin(); iIter
< m_vEntries
.end(); iIter
++ )
340 if ( sName
.equals( (*iIter
)->m_sTitle
) )
342 long nPos
= iIter
- m_vEntries
.begin();
349 //------------------------------------------------------------------------------
350 //------------------------------------------------------------------------------
351 // Title + description
352 void ExtensionBox_Impl::CalcActiveHeight( const long nPos
)
354 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
358 long nIconHeight
= 2*TOP_OFFSET
+ SMALL_ICON_SIZE
;
359 long nTitleHeight
= 2*TOP_OFFSET
+ GetTextHeight();
360 if ( nIconHeight
< nTitleHeight
)
361 aTextHeight
= nTitleHeight
;
363 aTextHeight
= nIconHeight
;
365 // calc description height
366 Size aSize
= GetOutputSizePixel();
367 if ( m_bHasScrollBar
)
368 aSize
.Width() -= m_pScrollBar
->GetSizePixel().Width();
370 aSize
.Width() -= ICON_OFFSET
;
371 aSize
.Height() = 10000;
373 rtl::OUString
aText( m_vEntries
[ nPos
]->m_sErrorText
);
374 aText
+= m_vEntries
[ nPos
]->m_sDescription
;
376 Rectangle aRect
= GetTextRect( Rectangle( Point(), aSize
), aText
,
377 TEXT_DRAW_MULTILINE
| TEXT_DRAW_WORDBREAK
);
378 aTextHeight
+= aRect
.GetHeight();
380 if ( aTextHeight
< m_nStdHeight
)
381 aTextHeight
= m_nStdHeight
;
383 m_nActiveHeight
= aTextHeight
+ m_nExtraHeight
;
386 //------------------------------------------------------------------------------
387 const Size
ExtensionBox_Impl::GetMinOutputSizePixel() const
389 return Size( 200, 80 );
392 //------------------------------------------------------------------------------
393 Rectangle
ExtensionBox_Impl::GetEntryRect( const long nPos
) const
395 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
397 Size
aSize( GetOutputSizePixel() );
399 if ( m_bHasScrollBar
)
400 aSize
.Width() -= m_pScrollBar
->GetSizePixel().Width();
402 if ( m_vEntries
[ nPos
]->m_bActive
)
403 aSize
.Height() = m_nActiveHeight
;
405 aSize
.Height() = m_nStdHeight
;
407 Point
aPos( 0, -m_nTopIndex
+ nPos
* m_nStdHeight
);
408 if ( m_bHasActive
&& ( nPos
< m_nActive
) )
409 aPos
.Y() += m_nActiveHeight
- m_nStdHeight
;
411 return Rectangle( aPos
, aSize
);
414 //------------------------------------------------------------------------------
415 void ExtensionBox_Impl::DeleteRemoved()
417 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
421 if ( ! m_vRemovedEntries
.empty() )
423 typedef std::vector
< TEntry_Impl
>::iterator ITER
;
425 for ( ITER iIndex
= m_vRemovedEntries
.begin(); iIndex
< m_vRemovedEntries
.end(); ++iIndex
)
427 if ( (*iIndex
)->m_pPublisher
)
429 delete (*iIndex
)->m_pPublisher
;
430 (*iIndex
)->m_pPublisher
= NULL
;
434 m_vRemovedEntries
.clear();
440 //------------------------------------------------------------------------------
441 //This function may be called with nPos < 0
442 void ExtensionBox_Impl::selectEntry( const long nPos
)
444 //ToDo whe should not use the guard at such a big scope here.
445 //Currently it is used to gard m_vEntries and m_nActive. m_nActive will be
446 //modified in this function.
447 //It would be probably best to always use a copy of m_vEntries
448 //and some other state variables from ExtensionBox_Impl for
449 //the whole painting operation. See issue i86993
450 ::osl::ClearableMutexGuard
guard(m_entriesMutex
);
452 if ( m_bInCheckMode
)
457 if ( nPos
== m_nActive
)
460 m_bHasActive
= false;
461 m_vEntries
[ m_nActive
]->m_bActive
= false;
464 if ( ( nPos
>= 0 ) && ( nPos
< (long) m_vEntries
.size() ) )
468 m_vEntries
[ nPos
]->m_bActive
= true;
470 if ( IsReallyVisible() )
472 m_bNeedsRecalc
= true;
473 m_bAdjustActive
= true;
477 if ( IsReallyVisible() )
483 // -----------------------------------------------------------------------
484 void ExtensionBox_Impl::DrawRow( const Rectangle
& rRect
, const TEntry_Impl pEntry
)
486 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
488 if ( pEntry
->m_bActive
)
489 SetTextColor( rStyleSettings
.GetHighlightTextColor() );
490 else if ( ( pEntry
->m_eState
!= REGISTERED
) && ( pEntry
->m_eState
!= NOT_AVAILABLE
) )
491 SetTextColor( rStyleSettings
.GetDisableColor() );
492 else if ( IsControlForeground() )
493 SetTextColor( GetControlForeground() );
495 SetTextColor( rStyleSettings
.GetFieldTextColor() );
497 if ( pEntry
->m_bActive
)
500 SetFillColor( rStyleSettings
.GetHighlightColor() );
505 if( IsControlBackground() )
506 SetBackground( GetControlBackground() );
508 SetBackground( rStyleSettings
.GetFieldColor() );
514 // Draw extension icon
515 Point
aPos( rRect
.TopLeft() );
516 aPos
+= Point( TOP_OFFSET
, TOP_OFFSET
);
518 if ( ! pEntry
->m_aIcon
)
519 aImage
= isHCMode() ? m_aDefaultImageHC
: m_aDefaultImage
;
521 aImage
= isHCMode() ? pEntry
->m_aIconHC
: pEntry
->m_aIcon
;
522 Size aImageSize
= aImage
.GetSizePixel();
523 if ( ( aImageSize
.Width() <= ICON_HEIGHT
) && ( aImageSize
.Height() <= ICON_HEIGHT
) )
524 DrawImage( Point( aPos
.X()+((ICON_HEIGHT
-aImageSize
.Width())/2), aPos
.Y()+((ICON_HEIGHT
-aImageSize
.Height())/2) ), aImage
);
526 DrawImage( aPos
, Size( ICON_HEIGHT
, ICON_HEIGHT
), aImage
);
529 Font
aStdFont( GetFont() );
530 Font
aBoldFont( aStdFont
);
531 aBoldFont
.SetWeight( WEIGHT_BOLD
);
532 SetFont( aBoldFont
);
533 long aTextHeight
= GetTextHeight();
535 // Init publisher link here
536 if ( !pEntry
->m_pPublisher
&& pEntry
->m_sPublisher
.Len() )
538 pEntry
->m_pPublisher
= new svt::FixedHyperlink( this );
539 pEntry
->m_pPublisher
->SetBackground();
540 pEntry
->m_pPublisher
->SetPaintTransparent( true );
541 pEntry
->m_pPublisher
->SetURL( pEntry
->m_sPublisherURL
);
542 pEntry
->m_pPublisher
->SetDescription( pEntry
->m_sPublisher
);
543 Size aSize
= FixedText::CalcMinimumTextSize( pEntry
->m_pPublisher
);
544 pEntry
->m_pPublisher
->SetSizePixel( aSize
);
546 if ( m_aClickHdl
.IsSet() )
547 pEntry
->m_pPublisher
->SetClickHdl( m_aClickHdl
);
550 // Get max title width
551 long nMaxTitleWidth
= rRect
.GetWidth() - ICON_OFFSET
;
552 nMaxTitleWidth
-= ( 2 * SMALL_ICON_SIZE
) + ( 4 * SPACE_BETWEEN
);
553 if ( pEntry
->m_pPublisher
)
555 nMaxTitleWidth
-= pEntry
->m_pPublisher
->GetSizePixel().Width() + (2*SPACE_BETWEEN
);
558 long aVersionWidth
= GetTextWidth( pEntry
->m_sVersion
);
559 long aTitleWidth
= GetTextWidth( pEntry
->m_sTitle
) + (aTextHeight
/ 3);
561 aPos
= rRect
.TopLeft() + Point( ICON_OFFSET
, TOP_OFFSET
);
563 if ( aTitleWidth
> nMaxTitleWidth
- aVersionWidth
)
565 aTitleWidth
= nMaxTitleWidth
- aVersionWidth
- (aTextHeight
/ 3);
566 String aShortTitle
= GetEllipsisString( pEntry
->m_sTitle
, aTitleWidth
);
567 DrawText( aPos
, aShortTitle
);
568 aTitleWidth
+= (aTextHeight
/ 3);
571 DrawText( aPos
, pEntry
->m_sTitle
);
574 DrawText( Point( aPos
.X() + aTitleWidth
, aPos
.Y() ), pEntry
->m_sVersion
);
576 long nIconHeight
= TOP_OFFSET
+ SMALL_ICON_SIZE
;
577 long nTitleHeight
= TOP_OFFSET
+ GetTextHeight();
578 if ( nIconHeight
< nTitleHeight
)
579 aTextHeight
= nTitleHeight
;
581 aTextHeight
= nIconHeight
;
585 if ( pEntry
->m_sErrorText
.Len() )
587 if ( pEntry
->m_bActive
)
588 sDescription
= pEntry
->m_sErrorText
+ OUSTR("\n") + pEntry
->m_sDescription
;
590 sDescription
= pEntry
->m_sErrorText
;
593 sDescription
= pEntry
->m_sDescription
;
595 aPos
.Y() += aTextHeight
;
596 if ( pEntry
->m_bActive
)
598 DrawText( Rectangle( aPos
.X(), aPos
.Y(), rRect
.Right(), rRect
.Bottom() - m_nExtraHeight
),
599 sDescription
, TEXT_DRAW_MULTILINE
| TEXT_DRAW_WORDBREAK
);
603 const long nWidth
= GetTextWidth( sDescription
);
604 if ( nWidth
> rRect
.GetWidth() - aPos
.X() )
605 sDescription
= GetEllipsisString( sDescription
, rRect
.GetWidth() - aPos
.X() );
606 DrawText( aPos
, sDescription
);
609 // Draw publisher link
610 if ( pEntry
->m_pPublisher
)
612 pEntry
->m_pPublisher
->Show();
613 aPos
= rRect
.TopLeft() + Point( ICON_OFFSET
+ nMaxTitleWidth
+ (2*SPACE_BETWEEN
), TOP_OFFSET
);
614 pEntry
->m_pPublisher
->SetPosPixel( aPos
);
618 if ( pEntry
->m_bShared
)
620 aPos
= rRect
.TopRight() + Point( -(RIGHT_ICON_OFFSET
+ SMALL_ICON_SIZE
), TOP_OFFSET
);
621 DrawImage( aPos
, Size( SMALL_ICON_SIZE
, SMALL_ICON_SIZE
), isHCMode() ? m_aLockedImageHC
: m_aLockedImage
);
623 if ( ( pEntry
->m_eState
== AMBIGUOUS
) || pEntry
->m_bMissingDeps
)
625 aPos
= rRect
.TopRight() + Point( -(RIGHT_ICON_OFFSET
+ SPACE_BETWEEN
+ 2*SMALL_ICON_SIZE
), TOP_OFFSET
);
626 DrawImage( aPos
, Size( SMALL_ICON_SIZE
, SMALL_ICON_SIZE
), isHCMode() ? m_aWarningImageHC
: m_aWarningImage
);
629 SetLineColor( Color( COL_LIGHTGRAY
) );
630 DrawLine( rRect
.BottomLeft(), rRect
.BottomRight() );
633 // -----------------------------------------------------------------------
634 void ExtensionBox_Impl::RecalcAll()
637 CalcActiveHeight( m_nActive
);
643 Rectangle aEntryRect
= GetEntryRect( m_nActive
);
645 if ( m_bAdjustActive
)
647 m_bAdjustActive
= false;
649 // If the top of the selected entry isn't visible, make it visible
650 if ( aEntryRect
.Top() < 0 )
652 m_nTopIndex
+= aEntryRect
.Top();
653 aEntryRect
.Move( 0, -aEntryRect
.Top() );
656 // If the bottom of the selected entry isn't visible, make it visible even if now the top
657 // isn't visible any longer ( the buttons are more important )
658 Size aOutputSize
= GetOutputSizePixel();
659 if ( aEntryRect
.Bottom() > aOutputSize
.Height() )
661 m_nTopIndex
+= ( aEntryRect
.Bottom() - aOutputSize
.Height() );
662 aEntryRect
.Move( 0, -( aEntryRect
.Bottom() - aOutputSize
.Height() ) );
665 // If there is unused space below the last entry but all entries don't fit into the box,
666 // move the content down to use the whole space
667 const long nTotalHeight
= GetTotalHeight();
668 if ( m_bHasScrollBar
&& ( aOutputSize
.Height() + m_nTopIndex
> nTotalHeight
) )
670 long nOffset
= m_nTopIndex
;
671 m_nTopIndex
= nTotalHeight
- aOutputSize
.Height();
672 nOffset
-= m_nTopIndex
;
673 aEntryRect
.Move( 0, nOffset
);
676 if ( m_bHasScrollBar
)
677 m_pScrollBar
->SetThumbPos( m_nTopIndex
);
681 m_bNeedsRecalc
= false;
684 // -----------------------------------------------------------------------
685 bool ExtensionBox_Impl::HandleTabKey( bool )
690 // -----------------------------------------------------------------------
691 bool ExtensionBox_Impl::HandleCursorKey( USHORT nKeyCode
)
693 if ( m_vEntries
.empty() )
700 long nPageSize
= GetOutputSizePixel().Height() / m_nStdHeight
;
704 if ( ( nKeyCode
== KEY_DOWN
) || ( nKeyCode
== KEY_RIGHT
) )
705 nSelect
= m_nActive
+ 1;
706 else if ( ( nKeyCode
== KEY_UP
) || ( nKeyCode
== KEY_LEFT
) )
707 nSelect
= m_nActive
- 1;
708 else if ( nKeyCode
== KEY_HOME
)
710 else if ( nKeyCode
== KEY_END
)
711 nSelect
= m_vEntries
.size() - 1;
712 else if ( nKeyCode
== KEY_PAGEUP
)
713 nSelect
= m_nActive
- nPageSize
+ 1;
714 else if ( nKeyCode
== KEY_PAGEDOWN
)
715 nSelect
= m_nActive
+ nPageSize
- 1;
717 else // when there is no selected entry, we will select the first or the last.
719 if ( ( nKeyCode
== KEY_DOWN
) || ( nKeyCode
== KEY_PAGEDOWN
) || ( nKeyCode
== KEY_HOME
) )
721 else if ( ( nKeyCode
== KEY_UP
) || ( nKeyCode
== KEY_PAGEUP
) || ( nKeyCode
== KEY_END
) )
722 nSelect
= m_vEntries
.size() - 1;
727 if ( nSelect
>= (long) m_vEntries
.size() )
728 nSelect
= m_vEntries
.size() - 1;
730 selectEntry( nSelect
);
735 // -----------------------------------------------------------------------
736 void ExtensionBox_Impl::Paint( const Rectangle
&/*rPaintRect*/ )
741 if ( m_bNeedsRecalc
)
744 Point
aStart( 0, -m_nTopIndex
);
745 Size
aSize( GetOutputSizePixel() );
747 if ( m_bHasScrollBar
)
748 aSize
.Width() -= m_pScrollBar
->GetSizePixel().Width();
750 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
752 typedef std::vector
< TEntry_Impl
>::iterator ITER
;
753 for ( ITER iIndex
= m_vEntries
.begin(); iIndex
< m_vEntries
.end(); ++iIndex
)
755 aSize
.Height() = (*iIndex
)->m_bActive
? m_nActiveHeight
: m_nStdHeight
;
756 Rectangle
aEntryRect( aStart
, aSize
);
757 DrawRow( aEntryRect
, *iIndex
);
758 aStart
.Y() += aSize
.Height();
762 // -----------------------------------------------------------------------
763 long ExtensionBox_Impl::GetTotalHeight() const
765 long nHeight
= m_vEntries
.size() * m_nStdHeight
;
769 nHeight
+= m_nActiveHeight
- m_nStdHeight
;
775 // -----------------------------------------------------------------------
776 void ExtensionBox_Impl::SetupScrollBar()
778 const Size aSize
= GetOutputSizePixel();
779 const long nScrBarSize
= GetSettings().GetStyleSettings().GetScrollBarSize();
780 const long nTotalHeight
= GetTotalHeight();
781 const bool bNeedsScrollBar
= ( nTotalHeight
> aSize
.Height() );
783 if ( bNeedsScrollBar
)
785 if ( m_nTopIndex
+ aSize
.Height() > nTotalHeight
)
786 m_nTopIndex
= nTotalHeight
- aSize
.Height();
788 m_pScrollBar
->SetPosSizePixel( Point( aSize
.Width() - nScrBarSize
, 0 ),
789 Size( nScrBarSize
, aSize
.Height() ) );
790 m_pScrollBar
->SetRangeMax( nTotalHeight
);
791 m_pScrollBar
->SetVisibleSize( aSize
.Height() );
792 m_pScrollBar
->SetPageSize( ( aSize
.Height() * 4 ) / 5 );
793 m_pScrollBar
->SetLineSize( m_nStdHeight
);
794 m_pScrollBar
->SetThumbPos( m_nTopIndex
);
796 if ( !m_bHasScrollBar
)
797 m_pScrollBar
->Show();
799 else if ( m_bHasScrollBar
)
801 m_pScrollBar
->Hide();
805 m_bHasScrollBar
= bNeedsScrollBar
;
808 // -----------------------------------------------------------------------
809 void ExtensionBox_Impl::Resize()
814 //------------------------------------------------------------------------------
815 long ExtensionBox_Impl::PointToPos( const Point
& rPos
)
817 long nPos
= ( rPos
.Y() + m_nTopIndex
) / m_nStdHeight
;
819 if ( m_bHasActive
&& ( nPos
> m_nActive
) )
821 if ( rPos
.Y() + m_nTopIndex
<= m_nActive
*m_nStdHeight
+ m_nActiveHeight
)
824 nPos
= ( rPos
.Y() + m_nTopIndex
- (m_nActiveHeight
- m_nStdHeight
) ) / m_nStdHeight
;
830 //------------------------------------------------------------------------------
831 void ExtensionBox_Impl::MouseButtonDown( const MouseEvent
& rMEvt
)
833 long nPos
= PointToPos( rMEvt
.GetPosPixel() );
835 if ( rMEvt
.IsLeft() )
837 if ( rMEvt
.IsMod1() && m_bHasActive
)
838 selectEntry( m_vEntries
.size() ); // Selecting an not existing entry will deselect the current one
844 //------------------------------------------------------------------------------
845 long ExtensionBox_Impl::Notify( NotifyEvent
& rNEvt
)
850 bool bHandled
= false;
852 if ( rNEvt
.GetType() == EVENT_KEYINPUT
)
854 const KeyEvent
* pKEvt
= rNEvt
.GetKeyEvent();
855 KeyCode aKeyCode
= pKEvt
->GetKeyCode();
856 USHORT nKeyCode
= aKeyCode
.GetCode();
858 if ( nKeyCode
== KEY_TAB
)
859 bHandled
= HandleTabKey( aKeyCode
.IsShift() );
860 else if ( aKeyCode
.GetGroup() == KEYGROUP_CURSOR
)
861 bHandled
= HandleCursorKey( nKeyCode
);
864 if ( rNEvt
.GetType() == EVENT_COMMAND
)
866 if ( m_bHasScrollBar
&&
867 ( rNEvt
.GetCommandEvent()->GetCommand() == COMMAND_WHEEL
) )
869 const CommandWheelData
* pData
= rNEvt
.GetCommandEvent()->GetWheelData();
870 if ( pData
->GetMode() == COMMAND_WHEEL_SCROLL
)
872 long nThumbPos
= m_pScrollBar
->GetThumbPos();
873 if ( pData
->GetDelta() < 0 )
874 m_pScrollBar
->DoScroll( nThumbPos
+ m_nStdHeight
);
876 m_pScrollBar
->DoScroll( nThumbPos
- m_nStdHeight
);
883 return Control::Notify( rNEvt
);
888 //------------------------------------------------------------------------------
889 bool ExtensionBox_Impl::FindEntryPos( const TEntry_Impl pEntry
, const long nStart
,
890 const long nEnd
, long &nPos
)
896 StringCompare eCompare
;
898 if ( nStart
== nEnd
)
900 eCompare
= pEntry
->CompareTo( m_pCollator
, m_vEntries
[ nStart
] );
901 if ( eCompare
== COMPARE_LESS
)
903 else if ( eCompare
== COMPARE_EQUAL
)
905 //Workaround. See i86963.
906 if (pEntry
->m_xPackage
!= m_vEntries
[nStart
]->m_xPackage
)
909 if ( m_bInCheckMode
)
910 m_vEntries
[ nStart
]->m_bChecked
= true;
920 const long nMid
= nStart
+ ( ( nEnd
- nStart
) / 2 );
921 eCompare
= pEntry
->CompareTo( m_pCollator
, m_vEntries
[ nMid
] );
923 if ( eCompare
== COMPARE_LESS
)
924 return FindEntryPos( pEntry
, nStart
, nMid
-1, nPos
);
925 else if ( eCompare
== COMPARE_GREATER
)
926 return FindEntryPos( pEntry
, nMid
+1, nEnd
, nPos
);
929 //Workaround.See i86963.
930 if (pEntry
->m_xPackage
!= m_vEntries
[nMid
]->m_xPackage
)
933 if ( m_bInCheckMode
)
934 m_vEntries
[ nMid
]->m_bChecked
= true;
940 //------------------------------------------------------------------------------
941 long ExtensionBox_Impl::addEntry( const uno::Reference
< deployment::XPackage
> &xPackage
,
942 const uno::Reference
< deployment::XPackageManager
> &xPackageManager
)
945 PackageState eState
= m_pManager
->getPackageState( xPackage
);
947 TEntry_Impl
pEntry( new Entry_Impl( xPackage
, xPackageManager
, eState
) );
948 xPackage
->addEventListener( uno::Reference
< lang::XEventListener
> ( m_xRemoveListener
, uno::UNO_QUERY
) );
950 ::osl::ClearableMutexGuard
guard(m_entriesMutex
);
951 if ( m_vEntries
.empty() )
953 pEntry
->m_bHasOptions
= m_pManager
->supportsOptions( xPackage
);
954 pEntry
->m_bShared
= ( m_pManager
->getSharedPkgMgr() == xPackageManager
);
955 pEntry
->m_bNew
= m_bInCheckMode
;
956 m_vEntries
.push_back( pEntry
);
960 if ( !FindEntryPos( pEntry
, 0, m_vEntries
.size()-1, nPos
) )
962 pEntry
->m_bHasOptions
= m_pManager
->supportsOptions( xPackage
);
963 pEntry
->m_bShared
= ( m_pManager
->getSharedPkgMgr() == xPackageManager
);
964 pEntry
->m_bNew
= m_bInCheckMode
;
965 m_vEntries
.insert( m_vEntries
.begin()+nPos
, pEntry
);
967 else if ( !m_bInCheckMode
)
969 OSL_ENSURE( 0, "ExtensionBox_Impl::addEntry(): Will not add duplicate entries" );
972 //access to m_nActive must be guarded
973 if ( !m_bInCheckMode
&& m_bHasActive
&& ( m_nActive
>= nPos
) )
978 if ( IsReallyVisible() )
981 m_bNeedsRecalc
= true;
986 //------------------------------------------------------------------------------
987 void ExtensionBox_Impl::updateEntry( const uno::Reference
< deployment::XPackage
> &xPackage
)
989 typedef std::vector
< TEntry_Impl
>::iterator ITER
;
990 for ( ITER iIndex
= m_vEntries
.begin(); iIndex
< m_vEntries
.end(); ++iIndex
)
992 if ( (*iIndex
)->m_xPackage
== xPackage
)
994 PackageState eState
= m_pManager
->getPackageState( xPackage
);
995 (*iIndex
)->m_bHasOptions
= m_pManager
->supportsOptions( xPackage
);
996 (*iIndex
)->m_eState
= eState
;
997 (*iIndex
)->m_sTitle
= xPackage
->getDisplayName();
998 (*iIndex
)->m_sVersion
= xPackage
->getVersion();
999 (*iIndex
)->m_sDescription
= xPackage
->getDescription();
1001 if ( eState
== AMBIGUOUS
)
1002 (*iIndex
)->m_sErrorText
= DialogHelper::getResourceString( RID_STR_ERROR_UNKNOWN_STATUS
);
1004 (*iIndex
)->m_sErrorText
= String();
1006 if ( IsReallyVisible() )
1013 //------------------------------------------------------------------------------
1014 void ExtensionBox_Impl::removeEntry( const uno::Reference
< deployment::XPackage
> &xPackage
)
1016 if ( ! m_bInDelete
)
1018 ::osl::ClearableMutexGuard
aGuard( m_entriesMutex
);
1020 typedef std::vector
< TEntry_Impl
>::iterator ITER
;
1022 for ( ITER iIndex
= m_vEntries
.begin(); iIndex
< m_vEntries
.end(); ++iIndex
)
1024 if ( (*iIndex
)->m_xPackage
== xPackage
)
1026 long nPos
= iIndex
- m_vEntries
.begin();
1028 // Entries mustn't removed here, because they contain a hyperlink control
1029 // which can only be deleted when the thread has the solar mutex. Therefor
1030 // the entry will be moved into the m_vRemovedEntries list which will be
1031 // cleared on the next paint event
1032 m_vRemovedEntries
.push_back( *iIndex
);
1033 m_vEntries
.erase( iIndex
);
1035 m_bNeedsRecalc
= true;
1037 if ( IsReallyVisible() )
1042 if ( nPos
< m_nActive
)
1044 else if ( ( nPos
== m_nActive
) &&
1045 ( nPos
== (long) m_vEntries
.size() ) )
1048 m_bHasActive
= false;
1049 //clear before calling out of this method
1051 selectEntry( m_nActive
);
1059 //------------------------------------------------------------------------------
1060 void ExtensionBox_Impl::RemoveUnlocked()
1062 bool bAllRemoved
= false;
1064 while ( ! bAllRemoved
)
1068 ::osl::ClearableMutexGuard
aGuard( m_entriesMutex
);
1070 typedef std::vector
< TEntry_Impl
>::iterator ITER
;
1072 for ( ITER iIndex
= m_vEntries
.begin(); iIndex
< m_vEntries
.end(); ++iIndex
)
1074 if ( !(*iIndex
)->m_bLocked
)
1076 bAllRemoved
= false;
1077 uno::Reference
< deployment::XPackage
> xPackage
= (*iIndex
)->m_xPackage
;
1079 removeEntry( xPackage
);
1086 //------------------------------------------------------------------------------
1087 void ExtensionBox_Impl::prepareChecking( const uno::Reference
< deployment::XPackageManager
> &xPackageMgr
)
1089 m_bInCheckMode
= true;
1090 typedef std::vector
< TEntry_Impl
>::iterator ITER
;
1091 for ( ITER iIndex
= m_vEntries
.begin(); iIndex
< m_vEntries
.end(); ++iIndex
)
1093 if ( (*iIndex
)->m_xPackageManager
== xPackageMgr
)
1094 (*iIndex
)->m_bChecked
= false;
1096 (*iIndex
)->m_bChecked
= true;
1097 (*iIndex
)->m_bNew
= false;
1101 //------------------------------------------------------------------------------
1102 void ExtensionBox_Impl::checkEntries()
1106 bool bNeedsUpdate
= false;
1108 ::osl::ClearableMutexGuard
guard(m_entriesMutex
);
1109 typedef std::vector
< TEntry_Impl
>::iterator ITER
;
1110 ITER iIndex
= m_vEntries
.begin();
1111 while ( iIndex
< m_vEntries
.end() )
1113 if ( (*iIndex
)->m_bChecked
== false )
1115 bNeedsUpdate
= true;
1116 nPos
= iIndex
-m_vEntries
.begin();
1117 if ( (*iIndex
)->m_bNew
)
1119 if ( nNewPos
== - 1)
1121 if ( nPos
<= m_nActive
)
1129 m_bInCheckMode
= false;
1131 if ( nNewPos
!= - 1)
1132 selectEntry( nNewPos
);
1136 m_bNeedsRecalc
= true;
1137 if ( IsReallyVisible() )
1141 //------------------------------------------------------------------------------
1142 bool ExtensionBox_Impl::isHCMode()
1144 return (bool)GetDisplayBackground().GetColor().IsDark();
1147 //------------------------------------------------------------------------------
1148 void ExtensionBox_Impl::SetScrollHdl( const Link
& rLink
)
1151 m_pScrollBar
->SetScrollHdl( rLink
);
1154 // -----------------------------------------------------------------------
1155 void ExtensionBox_Impl::DoScroll( long nDelta
)
1157 m_nTopIndex
+= nDelta
;
1158 Point
aNewSBPt( m_pScrollBar
->GetPosPixel() );
1160 Rectangle
aScrRect( Point(), GetOutputSizePixel() );
1161 aScrRect
.Right() -= m_pScrollBar
->GetSizePixel().Width();
1162 Scroll( 0, -nDelta
, aScrRect
);
1164 m_pScrollBar
->SetPosPixel( aNewSBPt
);
1167 // -----------------------------------------------------------------------
1168 IMPL_LINK( ExtensionBox_Impl
, ScrollHdl
, ScrollBar
*, pScrBar
)
1170 DoScroll( pScrBar
->GetDelta() );
1175 } //namespace dp_gui