1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "svtools/controldims.hrc"
22 #include "RemoteDialogClientBox.hxx"
23 #include "RemoteDialog.hrc"
25 #include "comphelper/processfactory.hxx"
26 #include "com/sun/star/i18n/CollatorOptions.hpp"
27 #include "com/sun/star/deployment/DependencyException.hpp"
28 #include "com/sun/star/deployment/DeploymentException.hpp"
30 using namespace ::com::sun::star
;
34 //------------------------------------------------------------------------------
35 // struct ClientBoxEntry
36 //------------------------------------------------------------------------------
37 ClientBoxEntry::ClientBoxEntry( ClientInfo
* pClientInfo
) :
39 m_pClientInfo( pClientInfo
)
43 //------------------------------------------------------------------------------
44 ClientBoxEntry::~ClientBoxEntry()
48 //------------------------------------------------------------------------------
49 // ClientRemovedListener
50 //------------------------------------------------------------------------------
51 void ClientRemovedListener::disposing( lang::EventObject
const & rEvt
)
52 throw ( uno::RuntimeException
)
57 //------------------------------------------------------------------------------
58 ClientRemovedListener::~ClientRemovedListener()
62 //------------------------------------------------------------------------------
64 //------------------------------------------------------------------------------
65 ClientBox::ClientBox( Dialog
* pParent
, RemoteServer
*pServer
,
66 const SdResId
& aId
) :
67 Control( pParent
, aId
),
68 m_bHasScrollBar( false ),
69 m_bHasActive( false ),
70 m_bNeedsRecalc( true ),
71 m_bInCheckMode( false ),
72 m_bAdjustActive( false ),
78 m_aPinBox( this, SdResId( INPUT_PIN
) ),
79 m_aPinDescription( this, SdResId( TEXT_PIN
) ),
80 m_pScrollBar( new ScrollBar( this, WB_VERT
) ),
83 m_pScrollBar
->SetScrollHdl( LINK( this, ClientBox
, ScrollHdl
) );
84 m_pScrollBar
->EnableDrag();
86 m_aPinBox
.SetUseThousandSep(false);
87 // m_aPinDescription.SetText( String( SdResId( STR_ENTER_PIN ) ) );
89 SetPaintTransparent( true );
90 SetPosPixel( Point( RSC_SP_DLG_INNERBORDER_LEFT
, RSC_SP_DLG_INNERBORDER_TOP
) );
91 long nIconHeight
= 2*TOP_OFFSET
+ SMALL_ICON_SIZE
;
92 long nTitleHeight
= 2*TOP_OFFSET
+ GetTextHeight();
93 if ( nIconHeight
< nTitleHeight
)
94 m_nStdHeight
= nTitleHeight
;
96 m_nStdHeight
= nIconHeight
;
97 m_nStdHeight
+= GetTextHeight() + TOP_OFFSET
;
99 // nIconHeight = ICON_HEIGHT + 2*TOP_OFFSET + 1;
100 // if ( m_nStdHeight < nIconHeight )
101 // m_nStdHeight = nIconHeight;
103 m_nActiveHeight
= m_nStdHeight
;
105 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
106 if( IsControlBackground() )
107 SetBackground( GetControlBackground() );
109 SetBackground( rStyleSettings
.GetFieldColor() );
111 m_xRemoveListener
= new ClientRemovedListener( this );
116 //------------------------------------------------------------------------------
117 ClientBox::~ClientBox()
124 typedef std::vector
< TClientBoxEntry
>::iterator ITER
;
126 for ( ITER iIndex
= m_vEntries
.begin(); iIndex
< m_vEntries
.end(); ++iIndex
)
128 // (*iIndex)->m_xPackage->removeEventListener( uno::Reference< lang::XEventListener > ( m_xRemoveListener, uno::UNO_QUERY ) );
133 m_xRemoveListener
.clear();
136 //------------------------------------------------------------------------------
137 // Title + description
138 void ClientBox::CalcActiveHeight( const long nPos
)
141 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
145 long nIconHeight
= 2*TOP_OFFSET
+ SMALL_ICON_SIZE
;
146 long nTitleHeight
= 2*TOP_OFFSET
+ GetTextHeight();
147 if ( nIconHeight
< nTitleHeight
)
148 aTextHeight
= nTitleHeight
;
150 aTextHeight
= nIconHeight
;
153 Size aSize
= GetOutputSizePixel();
154 if ( m_bHasScrollBar
)
155 aSize
.Width() -= m_pScrollBar
->GetSizePixel().Width();
157 aSize
.Width() -= ICON_OFFSET
;
159 aSize
= LogicToPixel( Size( RSC_CD_PUSHBUTTON_WIDTH
, RSC_CD_PUSHBUTTON_HEIGHT
),
160 MapMode( MAP_APPFONT
) );
161 aTextHeight
+= aSize
.Height();
163 if ( aTextHeight
< m_nStdHeight
)
164 aTextHeight
= m_nStdHeight
;
166 m_nActiveHeight
= aTextHeight
+ 2;
169 //------------------------------------------------------------------------------
170 Rectangle
ClientBox::GetEntryRect( const long nPos
) const
172 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
174 Size
aSize( GetOutputSizePixel() );
176 if ( m_bHasScrollBar
)
177 aSize
.Width() -= m_pScrollBar
->GetSizePixel().Width();
179 if ( m_vEntries
[ nPos
]->m_bActive
)
180 aSize
.Height() = m_nActiveHeight
;
182 aSize
.Height() = m_nStdHeight
;
184 Point
aPos( 0, -m_nTopIndex
+ nPos
* m_nStdHeight
);
185 if ( m_bHasActive
&& ( nPos
< m_nActive
) )
186 aPos
.Y() += m_nActiveHeight
- m_nStdHeight
;
188 return Rectangle( aPos
, aSize
);
191 //------------------------------------------------------------------------------
192 void ClientBox::DeleteRemoved()
194 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
198 if ( ! m_vRemovedEntries
.empty() )
200 m_vRemovedEntries
.clear();
206 long ClientBox::GetActiveEntryIndex()
214 //------------------------------------------------------------------------------
215 //This function may be called with nPos < 0
216 void ClientBox::selectEntry( const long nPos
)
218 //ToDo whe should not use the guard at such a big scope here.
219 //Currently it is used to gard m_vEntries and m_nActive. m_nActive will be
220 //modified in this function.
221 //It would be probably best to always use a copy of m_vEntries
222 //and some other state variables from ClientBox for
223 //the whole painting operation. See issue i86993
224 ::osl::ClearableMutexGuard
guard(m_entriesMutex
);
226 if ( m_bInCheckMode
)
231 if ( nPos
== m_nActive
)
234 m_bHasActive
= false;
235 m_vEntries
[ m_nActive
]->m_bActive
= false;
238 if ( ( nPos
>= 0 ) && ( nPos
< (long) m_vEntries
.size() ) )
242 m_vEntries
[ nPos
]->m_bActive
= true;
244 if ( IsReallyVisible() )
246 m_bAdjustActive
= true;
250 if ( IsReallyVisible() )
252 m_bNeedsRecalc
= true;
259 // -----------------------------------------------------------------------
260 void ClientBox::DrawRow( const Rectangle
& rRect
, const TClientBoxEntry pEntry
)
262 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
264 if ( pEntry
->m_bActive
)
265 SetTextColor( rStyleSettings
.GetHighlightTextColor() );
267 SetTextColor( rStyleSettings
.GetFieldTextColor() );
269 if ( pEntry
->m_bActive
)
272 SetFillColor( rStyleSettings
.GetHighlightColor() );
277 if( IsControlBackground() )
278 SetBackground( GetControlBackground() );
280 SetBackground( rStyleSettings
.GetFieldColor() );
286 // FIXME: draw bluetooth or wifi icon
287 Point
aPos( rRect
.TopLeft() );
288 // aPos += Point( TOP_OFFSET, TOP_OFFSET );
290 // if ( ! pEntry->m_aIcon )
291 // aImage = m_aDefaultImage;
293 // aImage = pEntry->m_aIcon;
294 // Size aImageSize = aImage.GetSizePixel();
295 // if ( ( aImageSize.Width() <= ICON_WIDTH ) && ( aImageSize.Height() <= ICON_HEIGHT ) )
296 // DrawImage( Point( aPos.X()+((ICON_WIDTH-aImageSize.Width())/2), aPos.Y()+((ICON_HEIGHT-aImageSize.Height())/2) ), aImage );
298 // DrawImage( aPos, Size( ICON_WIDTH, ICON_HEIGHT ), aImage );
301 Font
aStdFont( GetFont() );
302 Font
aBoldFont( aStdFont
);
303 aBoldFont
.SetWeight( WEIGHT_BOLD
);
304 SetFont( aBoldFont
);
305 long aTextHeight
= GetTextHeight();
307 // Get max title width
308 long nMaxTitleWidth
= rRect
.GetWidth() - ICON_OFFSET
;
309 nMaxTitleWidth
-= ( 2 * SMALL_ICON_SIZE
) + ( 4 * SPACE_BETWEEN
);
311 long aTitleWidth
= GetTextWidth( String( pEntry
->m_pClientInfo
->mName
) ) + (aTextHeight
/ 3);
313 aPos
= rRect
.TopLeft() + Point( ICON_OFFSET
, TOP_OFFSET
);
315 if ( aTitleWidth
> nMaxTitleWidth
)
317 aTitleWidth
= nMaxTitleWidth
- (aTextHeight
/ 3);
318 String aShortTitle
= GetEllipsisString( pEntry
->m_pClientInfo
->mName
,
320 DrawText( aPos
, aShortTitle
);
321 aTitleWidth
+= (aTextHeight
/ 3);
324 DrawText( aPos
, pEntry
->m_pClientInfo
->mName
);
328 aPos
.Y() += aTextHeight
;
329 if ( pEntry
->m_bActive
)
331 Size aSize
= LogicToPixel( Size( RSC_CD_PUSHBUTTON_WIDTH
, RSC_CD_PUSHBUTTON_HEIGHT
),
332 MapMode( MAP_APPFONT
) );
333 m_aPinBox
.SetSizePixel( aSize
);
334 const Rectangle
aRect( GetEntryRect( m_nActive
) );
335 Size
aBtnSize( m_aPinBox
.GetSizePixel() );
336 Point
aBtnPos( aRect
.Left(),
337 aRect
.Bottom() - TOP_OFFSET
- aBtnSize
.Height() );
338 // m_aPinDescription.SetPosPixel( aBtnPos );
339 DrawText( Rectangle( aBtnPos
.X(), aBtnPos
.Y(), rRect
.Right(), rRect
.Bottom() - TOP_OFFSET
),
340 String( SdResId( STR_ENTER_PIN
) ), 0 );
342 aBtnPos
= Point( aRect
.Left() + GetTextWidth( String( SdResId( STR_ENTER_PIN
) ) ),
343 aRect
.Bottom() - TOP_OFFSET
- aBtnSize
.Height() );
345 m_aPinBox
.SetPosPixel( aBtnPos
);
351 // long nExtraHeight = 0;
353 // if ( pEntry->m_bHasButtons )
354 // nExtraHeight = m_nExtraHeight;
356 // DrawText( Rectangle( aPos.X(), aPos.Y(), rRect.Right(), rRect.Bottom() - nExtraHeight ),
357 // sDescription, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
363 SetLineColor( Color( COL_LIGHTGRAY
) );
364 DrawLine( rRect
.BottomLeft(), rRect
.BottomRight() );
367 // -----------------------------------------------------------------------
368 void ClientBox::RecalcAll()
371 CalcActiveHeight( m_nActive
);
377 Rectangle aEntryRect
= GetEntryRect( m_nActive
);
379 if ( m_bAdjustActive
)
381 m_bAdjustActive
= false;
383 // If the top of the selected entry isn't visible, make it visible
384 if ( aEntryRect
.Top() < 0 )
386 m_nTopIndex
+= aEntryRect
.Top();
387 aEntryRect
.Move( 0, -aEntryRect
.Top() );
390 // If the bottom of the selected entry isn't visible, make it visible even if now the top
391 // isn't visible any longer ( the buttons are more important )
392 Size aOutputSize
= GetOutputSizePixel();
393 if ( aEntryRect
.Bottom() > aOutputSize
.Height() )
395 m_nTopIndex
+= ( aEntryRect
.Bottom() - aOutputSize
.Height() );
396 aEntryRect
.Move( 0, -( aEntryRect
.Bottom() - aOutputSize
.Height() ) );
399 // If there is unused space below the last entry but all entries don't fit into the box,
400 // move the content down to use the whole space
401 const long nTotalHeight
= GetTotalHeight();
402 if ( m_bHasScrollBar
&& ( aOutputSize
.Height() + m_nTopIndex
> nTotalHeight
) )
404 long nOffset
= m_nTopIndex
;
405 m_nTopIndex
= nTotalHeight
- aOutputSize
.Height();
406 nOffset
-= m_nTopIndex
;
407 aEntryRect
.Move( 0, nOffset
);
410 if ( m_bHasScrollBar
)
411 m_pScrollBar
->SetThumbPos( m_nTopIndex
);
415 m_bNeedsRecalc
= false;
418 // -----------------------------------------------------------------------
419 bool ClientBox::HandleTabKey( bool )
424 // -----------------------------------------------------------------------
425 bool ClientBox::HandleCursorKey( sal_uInt16 nKeyCode
)
427 if ( m_vEntries
.empty() )
434 long nPageSize
= GetOutputSizePixel().Height() / m_nStdHeight
;
438 if ( ( nKeyCode
== KEY_DOWN
) || ( nKeyCode
== KEY_RIGHT
) )
439 nSelect
= m_nActive
+ 1;
440 else if ( ( nKeyCode
== KEY_UP
) || ( nKeyCode
== KEY_LEFT
) )
441 nSelect
= m_nActive
- 1;
442 else if ( nKeyCode
== KEY_HOME
)
444 else if ( nKeyCode
== KEY_END
)
445 nSelect
= m_vEntries
.size() - 1;
446 else if ( nKeyCode
== KEY_PAGEUP
)
447 nSelect
= m_nActive
- nPageSize
+ 1;
448 else if ( nKeyCode
== KEY_PAGEDOWN
)
449 nSelect
= m_nActive
+ nPageSize
- 1;
451 else // when there is no selected entry, we will select the first or the last.
453 if ( ( nKeyCode
== KEY_DOWN
) || ( nKeyCode
== KEY_PAGEDOWN
) || ( nKeyCode
== KEY_HOME
) )
455 else if ( ( nKeyCode
== KEY_UP
) || ( nKeyCode
== KEY_PAGEUP
) || ( nKeyCode
== KEY_END
) )
456 nSelect
= m_vEntries
.size() - 1;
461 if ( nSelect
>= (long) m_vEntries
.size() )
462 nSelect
= m_vEntries
.size() - 1;
464 selectEntry( nSelect
);
469 // -----------------------------------------------------------------------
470 void ClientBox::Paint( const Rectangle
&/*rPaintRect*/ )
475 if ( m_bNeedsRecalc
)
478 Point
aStart( 0, -m_nTopIndex
);
479 Size
aSize( GetOutputSizePixel() );
481 if ( m_bHasScrollBar
)
482 aSize
.Width() -= m_pScrollBar
->GetSizePixel().Width();
484 const ::osl::MutexGuard
aGuard( m_entriesMutex
);
486 typedef std::vector
< TClientBoxEntry
>::iterator ITER
;
487 for ( ITER iIndex
= m_vEntries
.begin(); iIndex
< m_vEntries
.end(); ++iIndex
)
489 aSize
.Height() = (*iIndex
)->m_bActive
? m_nActiveHeight
: m_nStdHeight
;
490 Rectangle
aEntryRect( aStart
, aSize
);
491 DrawRow( aEntryRect
, *iIndex
);
492 aStart
.Y() += aSize
.Height();
496 // -----------------------------------------------------------------------
497 long ClientBox::GetTotalHeight() const
499 long nHeight
= m_vEntries
.size() * m_nStdHeight
;
503 nHeight
+= m_nActiveHeight
- m_nStdHeight
;
509 // -----------------------------------------------------------------------
510 void ClientBox::SetupScrollBar()
512 const Size aSize
= GetOutputSizePixel();
513 const long nScrBarSize
= GetSettings().GetStyleSettings().GetScrollBarSize();
514 const long nTotalHeight
= GetTotalHeight();
515 const bool bNeedsScrollBar
= ( nTotalHeight
> aSize
.Height() );
517 if ( bNeedsScrollBar
)
519 if ( m_nTopIndex
+ aSize
.Height() > nTotalHeight
)
520 m_nTopIndex
= nTotalHeight
- aSize
.Height();
522 m_pScrollBar
->SetPosSizePixel( Point( aSize
.Width() - nScrBarSize
, 0 ),
523 Size( nScrBarSize
, aSize
.Height() ) );
524 m_pScrollBar
->SetRangeMax( nTotalHeight
);
525 m_pScrollBar
->SetVisibleSize( aSize
.Height() );
526 m_pScrollBar
->SetPageSize( ( aSize
.Height() * 4 ) / 5 );
527 m_pScrollBar
->SetLineSize( m_nStdHeight
);
528 m_pScrollBar
->SetThumbPos( m_nTopIndex
);
530 if ( !m_bHasScrollBar
)
531 m_pScrollBar
->Show();
533 else if ( m_bHasScrollBar
)
535 m_pScrollBar
->Hide();
539 m_bHasScrollBar
= bNeedsScrollBar
;
542 // -----------------------------------------------------------------------
543 void ClientBox::Resize()
548 //------------------------------------------------------------------------------
549 long ClientBox::PointToPos( const Point
& rPos
)
551 long nPos
= ( rPos
.Y() + m_nTopIndex
) / m_nStdHeight
;
553 if ( m_bHasActive
&& ( nPos
> m_nActive
) )
555 if ( rPos
.Y() + m_nTopIndex
<= m_nActive
*m_nStdHeight
+ m_nActiveHeight
)
558 nPos
= ( rPos
.Y() + m_nTopIndex
- (m_nActiveHeight
- m_nStdHeight
) ) / m_nStdHeight
;
564 OUString
ClientBox::getPin()
566 return OUString::valueOf( m_aPinBox
.GetValue() );
569 //------------------------------------------------------------------------------
570 void ClientBox::MouseButtonDown( const MouseEvent
& rMEvt
)
572 long nPos
= PointToPos( rMEvt
.GetPosPixel() );
574 if ( rMEvt
.IsLeft() )
576 if ( rMEvt
.IsMod1() && m_bHasActive
)
577 selectEntry( m_vEntries
.size() ); // Selecting an not existing entry will deselect the current one
583 //------------------------------------------------------------------------------
584 long ClientBox::Notify( NotifyEvent
& rNEvt
)
589 bool bHandled
= false;
591 if ( rNEvt
.GetType() == EVENT_KEYINPUT
)
593 const KeyEvent
* pKEvt
= rNEvt
.GetKeyEvent();
594 KeyCode aKeyCode
= pKEvt
->GetKeyCode();
595 sal_uInt16 nKeyCode
= aKeyCode
.GetCode();
597 if ( nKeyCode
== KEY_TAB
)
598 bHandled
= HandleTabKey( aKeyCode
.IsShift() );
599 else if ( aKeyCode
.GetGroup() == KEYGROUP_CURSOR
)
600 bHandled
= HandleCursorKey( nKeyCode
);
603 if ( rNEvt
.GetType() == EVENT_COMMAND
)
605 if ( m_bHasScrollBar
&&
606 ( rNEvt
.GetCommandEvent()->GetCommand() == COMMAND_WHEEL
) )
608 const CommandWheelData
* pData
= rNEvt
.GetCommandEvent()->GetWheelData();
609 if ( pData
->GetMode() == COMMAND_WHEEL_SCROLL
)
611 long nThumbPos
= m_pScrollBar
->GetThumbPos();
612 if ( pData
->GetDelta() < 0 )
613 m_pScrollBar
->DoScroll( nThumbPos
+ m_nStdHeight
);
615 m_pScrollBar
->DoScroll( nThumbPos
- m_nStdHeight
);
622 return Control::Notify( rNEvt
);
628 //------------------------------------------------------------------------------
629 long ClientBox::addEntry( ClientInfo
* pClientInfo
)
632 // PackageState eState = m_pManager->getPackageState( xPackage );
633 // bool bLocked = m_pManager->isReadOnly( xPackage );
635 TClientBoxEntry
pEntry( new ClientBoxEntry( pClientInfo
) );
637 bool bNewEntryInserted
= false;
639 ::osl::ClearableMutexGuard
guard(m_entriesMutex
);
640 if ( m_vEntries
.empty() )
642 m_vEntries
.push_back( pEntry
);
643 bNewEntryInserted
= true;
647 // if ( !FindEntryPos( pEntry, 0, m_vEntries.size()-1, nPos ) )
649 m_vEntries
.insert( m_vEntries
.begin()+nPos
, pEntry
);
650 bNewEntryInserted
= true;
652 // else if ( !m_bInCheckMode )
654 // OSL_FAIL( "ClientBox::addEntry(): Will not add duplicate entries" );
658 //Related: rhbz#702833 Only add a Listener if we're adding a new entry, to
659 //keep in sync with removeEventListener logic
660 if (bNewEntryInserted
)
663 // pEntry->m_xPackage->addEventListener(uno::Reference< lang::XEventListener > ( m_xRemoveListener, uno::UNO_QUERY ) );
667 // pEntry->m_bHasOptions = m_pManager->supportsOptions( xPackage );
668 // pEntry->m_bUser = xPackage->getRepositoryName().equals( USER_PACKAGE_MANAGER );
669 // pEntry->m_bShared = xPackage->getRepositoryName().equals( SHARED_PACKAGE_MANAGER );
670 // pEntry->m_bNew = m_bInCheckMode;
671 // pEntry->m_bMissingLic = bLicenseMissing;
673 // if ( bLicenseMissing )
674 // pEntry->m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_MISSING_LICENSE );
676 //access to m_nActive must be guarded
677 if ( !m_bInCheckMode
&& m_bHasActive
&& ( m_nActive
>= nPos
) )
682 if ( IsReallyVisible() )
685 m_bNeedsRecalc
= true;
690 // -----------------------------------------------------------------------
691 void ClientBox::DoScroll( long nDelta
)
693 m_nTopIndex
+= nDelta
;
694 Point
aNewSBPt( m_pScrollBar
->GetPosPixel() );
696 Rectangle
aScrRect( Point(), GetOutputSizePixel() );
697 aScrRect
.Right() -= m_pScrollBar
->GetSizePixel().Width();
698 Scroll( 0, -nDelta
, aScrRect
);
700 m_pScrollBar
->SetPosPixel( aNewSBPt
);
703 // -----------------------------------------------------------------------
704 IMPL_LINK( ClientBox
, ScrollHdl
, ScrollBar
*, pScrBar
)
706 DoScroll( pScrBar
->GetDelta() );
713 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */