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 <vector>
21 :
22 : #include "svtools/controldims.hrc"
23 :
24 : #include "RemoteDialogClientBox.hxx"
25 : #include "RemoteServer.hxx"
26 :
27 : #include "comphelper/processfactory.hxx"
28 : #include "com/sun/star/i18n/CollatorOptions.hpp"
29 : #include "com/sun/star/deployment/DependencyException.hpp"
30 : #include "com/sun/star/deployment/DeploymentException.hpp"
31 : #include <vcl/settings.hxx>
32 :
33 : #include "glob.hrc"
34 :
35 : using namespace std;
36 :
37 : using namespace ::com::sun::star;
38 :
39 : namespace sd {
40 :
41 : // struct ClientBoxEntry
42 :
43 0 : ClientBoxEntry::ClientBoxEntry( ::boost::shared_ptr<ClientInfo> pClientInfo ) :
44 : m_bActive( false ),
45 0 : m_pClientInfo( pClientInfo )
46 : {
47 0 : }
48 :
49 0 : ClientBoxEntry::~ClientBoxEntry()
50 0 : {}
51 :
52 0 : void ClientRemovedListener::disposing( lang::EventObject const & rEvt )
53 : throw ( uno::RuntimeException, std::exception )
54 : {
55 : (void) rEvt;
56 0 : }
57 :
58 0 : ClientRemovedListener::~ClientRemovedListener()
59 : {
60 0 : }
61 :
62 : // ClientBox
63 :
64 0 : ClientBox::ClientBox( vcl::Window* pParent, WinBits nStyle ) :
65 : Control( pParent, nStyle ),
66 : m_bHasScrollBar( false ),
67 : m_bHasActive( false ),
68 : m_bNeedsRecalc( true ),
69 : m_bInCheckMode( false ),
70 : m_bAdjustActive( false ),
71 : m_bInDelete( false ),
72 : m_nActive( 0 ),
73 : m_nTopIndex( 0 ),
74 : m_nActiveHeight( 0 ),
75 : m_nExtraHeight( 2 ),
76 : m_aPinBox( this, 0 ),
77 : m_aDeauthoriseButton( this ),
78 0 : m_aScrollBar( this, WB_VERT )
79 : {
80 0 : m_aScrollBar.SetScrollHdl( LINK( this, ClientBox, ScrollHdl ) );
81 0 : m_aScrollBar.EnableDrag();
82 :
83 0 : m_aPinBox.SetUseThousandSep(false);
84 0 : m_aDeauthoriseButton.SetText( SD_RESSTR(STR_DEAUTHORISE_CLIENT) );
85 0 : m_aDeauthoriseButton.SetClickHdl( LINK( this, ClientBox, DeauthoriseHdl ) );
86 :
87 0 : SetPosPixel( Point( RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP ) );
88 0 : long nIconHeight = 2*TOP_OFFSET + SMALL_ICON_SIZE;
89 0 : long nTitleHeight = 2*TOP_OFFSET + GetTextHeight();
90 0 : if ( nIconHeight < nTitleHeight )
91 0 : m_nStdHeight = nTitleHeight;
92 : else
93 0 : m_nStdHeight = nIconHeight;
94 0 : m_nStdHeight += GetTextHeight() + TOP_OFFSET;
95 :
96 0 : m_nActiveHeight = m_nStdHeight;
97 :
98 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
99 0 : if( IsControlBackground() )
100 0 : SetBackground( GetControlBackground() );
101 : else
102 0 : SetBackground( rStyleSettings.GetFieldColor() );
103 :
104 0 : m_xRemoveListener = new ClientRemovedListener( this );
105 :
106 0 : populateEntries();
107 :
108 0 : Show();
109 0 : }
110 :
111 0 : extern "C" SAL_DLLPUBLIC_EXPORT vcl::Window* SAL_CALL makeClientBox(vcl::Window *pParent, VclBuilder::stringmap &rMap)
112 : {
113 0 : WinBits nWinStyle = WB_TABSTOP;
114 0 : OString sBorder = VclBuilder::extractCustomProperty(rMap);
115 0 : if (!sBorder.isEmpty())
116 0 : nWinStyle |= WB_BORDER;
117 0 : return new ClientBox(pParent, nWinStyle);
118 : }
119 :
120 0 : Size ClientBox::GetOptimalSize() const
121 : {
122 0 : return LogicToPixel(Size(200, 140), MAP_APPFONT);
123 : }
124 :
125 0 : ClientBox::~ClientBox()
126 : {
127 0 : if ( ! m_bInDelete )
128 0 : DeleteRemoved();
129 :
130 0 : m_bInDelete = true;
131 :
132 0 : m_vEntries.clear();
133 :
134 0 : m_xRemoveListener.clear();
135 0 : }
136 :
137 : // Title + description
138 0 : void ClientBox::CalcActiveHeight( const long nPos )
139 : {
140 : (void) nPos;
141 0 : const ::osl::MutexGuard aGuard( m_entriesMutex );
142 :
143 : // get title height
144 : long aTextHeight;
145 0 : long nIconHeight = 2*TOP_OFFSET + SMALL_ICON_SIZE;
146 0 : long nTitleHeight = 2*TOP_OFFSET + GetTextHeight();
147 0 : if ( nIconHeight < nTitleHeight )
148 0 : aTextHeight = nTitleHeight;
149 : else
150 0 : aTextHeight = nIconHeight;
151 :
152 : // Text entry height
153 0 : Size aSize = GetOutputSizePixel();
154 0 : if ( m_bHasScrollBar )
155 0 : aSize.Width() -= m_aScrollBar.GetSizePixel().Width();
156 :
157 0 : aSize.Width() -= ICON_OFFSET;
158 :
159 : aSize = LogicToPixel( Size( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ),
160 0 : MapMode( MAP_APPFONT ) );
161 0 : aTextHeight += aSize.Height();
162 :
163 0 : if ( aTextHeight < m_nStdHeight )
164 0 : aTextHeight = m_nStdHeight;
165 :
166 0 : m_nActiveHeight = aTextHeight + 2;
167 0 : }
168 :
169 0 : Rectangle ClientBox::GetEntryRect( const long nPos ) const
170 : {
171 0 : const ::osl::MutexGuard aGuard( m_entriesMutex );
172 :
173 0 : Size aSize( GetOutputSizePixel() );
174 :
175 0 : if ( m_bHasScrollBar )
176 0 : aSize.Width() -= m_aScrollBar.GetSizePixel().Width();
177 :
178 0 : if ( m_vEntries[ nPos ]->m_bActive )
179 0 : aSize.Height() = m_nActiveHeight;
180 : else
181 0 : aSize.Height() = m_nStdHeight;
182 :
183 0 : Point aPos( 0, -m_nTopIndex + nPos * m_nStdHeight );
184 0 : if ( m_bHasActive && ( nPos < m_nActive ) )
185 0 : aPos.Y() += m_nActiveHeight - m_nStdHeight;
186 :
187 0 : return Rectangle( aPos, aSize );
188 : }
189 :
190 0 : void ClientBox::DeleteRemoved()
191 : {
192 0 : const ::osl::MutexGuard aGuard( m_entriesMutex );
193 :
194 0 : m_bInDelete = true;
195 :
196 0 : if ( ! m_vRemovedEntries.empty() )
197 : {
198 0 : m_vRemovedEntries.clear();
199 : }
200 :
201 0 : m_bInDelete = false;
202 0 : }
203 :
204 0 : long ClientBox::GetActiveEntryIndex()
205 : {
206 0 : if ( m_bHasActive )
207 0 : return m_nActive;
208 : else
209 0 : return -1;
210 : }
211 :
212 : //This function may be called with nPos < 0
213 0 : void ClientBox::selectEntry( const long nPos )
214 : {
215 : //ToDo whe should not use the guard at such a big scope here.
216 : //Currently it is used to guard m_vEntries and m_nActive. m_nActive will be
217 : //modified in this function.
218 : //It would be probably best to always use a copy of m_vEntries
219 : //and some other state variables from ClientBox for
220 : //the whole painting operation. See issue i86993
221 0 : ::osl::ClearableMutexGuard guard(m_entriesMutex);
222 :
223 0 : if ( m_bInCheckMode )
224 0 : return;
225 :
226 0 : if ( m_bHasActive )
227 : {
228 0 : if ( nPos == m_nActive )
229 0 : return;
230 :
231 0 : m_bHasActive = false;
232 0 : m_vEntries[ m_nActive ]->m_bActive = false;
233 : }
234 :
235 0 : if ( ( nPos >= 0 ) && ( nPos < (long) m_vEntries.size() ) )
236 : {
237 0 : m_bHasActive = true;
238 0 : m_nActive = nPos;
239 0 : m_vEntries[ nPos ]->m_bActive = true;
240 :
241 0 : if ( IsReallyVisible() )
242 : {
243 0 : m_bAdjustActive = true;
244 : }
245 : }
246 :
247 : // We empty the pin box now too, just in case the user previously
248 : // entered a pin, but then changed their selected device.
249 0 : m_aPinBox.SetText( "" );
250 0 : if ( m_bHasActive )
251 : {
252 : bool bAlreadyAuthorised =
253 0 : m_vEntries[ m_nActive ]->m_pClientInfo->mbIsAlreadyAuthorised;
254 :
255 0 : if ( bAlreadyAuthorised )
256 : {
257 0 : m_aDeauthoriseButton.GetFocus();
258 : }
259 : else
260 : {
261 0 : m_aPinBox.GetFocus();
262 : }
263 : }
264 :
265 0 : if ( IsReallyVisible() )
266 : {
267 0 : m_bNeedsRecalc = true;
268 0 : Invalidate();
269 : }
270 :
271 0 : guard.clear();
272 : }
273 :
274 0 : void ClientBox::DrawRow( const Rectangle& rRect, const TClientBoxEntry pEntry )
275 : {
276 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
277 :
278 0 : if ( pEntry->m_bActive )
279 0 : SetTextColor( rStyleSettings.GetHighlightTextColor() );
280 : else
281 0 : SetTextColor( rStyleSettings.GetFieldTextColor() );
282 :
283 0 : if ( pEntry->m_bActive )
284 : {
285 0 : SetLineColor();
286 0 : SetFillColor( rStyleSettings.GetHighlightColor() );
287 0 : DrawRect( rRect );
288 : }
289 : else
290 : {
291 0 : if( IsControlBackground() )
292 0 : SetBackground( GetControlBackground() );
293 : else
294 0 : SetBackground( rStyleSettings.GetFieldColor() );
295 :
296 0 : SetTextFillColor();
297 0 : Erase( rRect );
298 : }
299 :
300 : // FIXME: draw bluetooth or wifi icon
301 0 : Point aPos( rRect.TopLeft() );
302 :
303 : // Setup fonts
304 0 : vcl::Font aStdFont( GetFont() );
305 0 : vcl::Font aBoldFont( aStdFont );
306 0 : aBoldFont.SetWeight( WEIGHT_BOLD );
307 0 : SetFont( aBoldFont );
308 0 : long aTextHeight = GetTextHeight();
309 :
310 : // Get max title width
311 0 : long nMaxTitleWidth = rRect.GetWidth() - ICON_OFFSET;
312 0 : nMaxTitleWidth -= ( 2 * SMALL_ICON_SIZE ) + ( 4 * SPACE_BETWEEN );
313 :
314 0 : long aTitleWidth = GetTextWidth( pEntry->m_pClientInfo->mName ) + (aTextHeight / 3);
315 :
316 0 : aPos = rRect.TopLeft() + Point( ICON_OFFSET, TOP_OFFSET );
317 :
318 0 : if ( aTitleWidth > nMaxTitleWidth )
319 : {
320 0 : aTitleWidth = nMaxTitleWidth - (aTextHeight / 3);
321 0 : OUString aShortTitle = GetEllipsisString( pEntry->m_pClientInfo->mName,
322 0 : aTitleWidth );
323 0 : DrawText( aPos, aShortTitle );
324 0 : aTitleWidth += (aTextHeight / 3);
325 : }
326 : else
327 0 : DrawText( aPos, pEntry->m_pClientInfo->mName );
328 :
329 0 : SetFont( aStdFont );
330 :
331 0 : aPos.Y() += aTextHeight;
332 0 : if ( pEntry->m_bActive )
333 : {
334 0 : OUString sPinText(SD_RESSTR(STR_ENTER_PIN));
335 : DrawText( m_sPinTextRect,
336 0 : sPinText, 0 );
337 : }
338 :
339 0 : SetLineColor( Color( COL_LIGHTGRAY ) );
340 0 : DrawLine( rRect.BottomLeft(), rRect.BottomRight() );
341 0 : }
342 :
343 0 : void ClientBox::RecalcAll()
344 : {
345 0 : if ( m_bHasActive )
346 0 : CalcActiveHeight( m_nActive );
347 :
348 0 : SetupScrollBar();
349 :
350 : Size aPBSize = LogicToPixel(
351 : Size( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ),
352 0 : MapMode( MAP_APPFONT ) );
353 0 : m_aPinBox.SetSizePixel( aPBSize );
354 0 : m_aDeauthoriseButton.SetSizePixel( m_aDeauthoriseButton.GetOptimalSize() );
355 :
356 0 : if ( !m_bHasActive )
357 : {
358 0 : m_aPinBox.Show( false );
359 0 : m_aDeauthoriseButton.Show( false );
360 : }
361 : else
362 : {
363 0 : Rectangle aEntryRect = GetEntryRect( m_nActive );
364 :
365 0 : Size aPinBoxSize( m_aPinBox.GetSizePixel() );
366 0 : Point aPos( aEntryRect.Left(),
367 0 : aEntryRect.Bottom() - TOP_OFFSET - aPinBoxSize.Height() );
368 :
369 0 : bool bAlreadyAuthorised = m_vEntries[ m_nActive ]->m_pClientInfo->mbIsAlreadyAuthorised;
370 :
371 0 : if ( !bAlreadyAuthorised )
372 : {
373 0 : m_sPinTextRect = Rectangle( aPos.X(), aPos.Y(),
374 0 : aEntryRect.Right(),
375 0 : aEntryRect.Bottom() - TOP_OFFSET);
376 :
377 0 : OUString sPinText(SD_RESSTR(STR_ENTER_PIN));
378 :
379 0 : aPos = Point( aEntryRect.Left() + GetTextWidth( sPinText ),
380 0 : aEntryRect.Bottom() - TOP_OFFSET - aPinBoxSize.Height() );
381 0 : m_aPinBox.SetPosPixel( aPos );
382 : // The text would have it's TOP aligned with the top of
383 : // the pin box -- hence we push it down to align baselines.
384 0 : m_sPinTextRect += Point( 0, 4 );
385 : }
386 : else
387 : {
388 0 : aPos += Point( 20, 0 );
389 0 : m_aDeauthoriseButton.SetPosPixel( aPos );
390 : }
391 :
392 0 : m_aPinBox.Show( !bAlreadyAuthorised );
393 0 : m_aDeauthoriseButton.Show( bAlreadyAuthorised );
394 :
395 0 : if ( m_bAdjustActive )
396 : {
397 0 : m_bAdjustActive = false;
398 :
399 : // If the top of the selected entry isn't visible, make it visible
400 0 : if ( aEntryRect.Top() < 0 )
401 : {
402 0 : m_nTopIndex += aEntryRect.Top();
403 0 : aEntryRect.Move( 0, -aEntryRect.Top() );
404 : }
405 :
406 : // If the bottom of the selected entry isn't visible, make it visible even if now the top
407 : // isn't visible any longer ( the buttons are more important )
408 0 : Size aOutputSize = GetOutputSizePixel();
409 0 : if ( aEntryRect.Bottom() > aOutputSize.Height() )
410 : {
411 0 : m_nTopIndex += ( aEntryRect.Bottom() - aOutputSize.Height() );
412 0 : aEntryRect.Move( 0, -( aEntryRect.Bottom() - aOutputSize.Height() ) );
413 : }
414 :
415 : // If there is unused space below the last entry but all entries don't fit into the box,
416 : // move the content down to use the whole space
417 0 : const long nTotalHeight = GetTotalHeight();
418 0 : if ( m_bHasScrollBar && ( aOutputSize.Height() + m_nTopIndex > nTotalHeight ) )
419 : {
420 0 : long nOffset = m_nTopIndex;
421 0 : m_nTopIndex = nTotalHeight - aOutputSize.Height();
422 0 : nOffset -= m_nTopIndex;
423 0 : aEntryRect.Move( 0, nOffset );
424 : }
425 :
426 0 : if ( m_bHasScrollBar )
427 0 : m_aScrollBar.SetThumbPos( m_nTopIndex );
428 : }
429 : }
430 :
431 0 : m_bNeedsRecalc = false;
432 0 : }
433 :
434 0 : bool ClientBox::HandleTabKey( bool )
435 : {
436 0 : return false;
437 : }
438 :
439 0 : bool ClientBox::HandleCursorKey( sal_uInt16 nKeyCode )
440 : {
441 0 : if ( m_vEntries.empty() )
442 0 : return true;
443 :
444 0 : long nSelect = 0;
445 :
446 0 : if ( m_bHasActive )
447 : {
448 0 : long nPageSize = GetOutputSizePixel().Height() / m_nStdHeight;
449 0 : if ( nPageSize < 2 )
450 0 : nPageSize = 2;
451 :
452 0 : if ( ( nKeyCode == KEY_DOWN ) || ( nKeyCode == KEY_RIGHT ) )
453 0 : nSelect = m_nActive + 1;
454 0 : else if ( ( nKeyCode == KEY_UP ) || ( nKeyCode == KEY_LEFT ) )
455 0 : nSelect = m_nActive - 1;
456 0 : else if ( nKeyCode == KEY_HOME )
457 0 : nSelect = 0;
458 0 : else if ( nKeyCode == KEY_END )
459 0 : nSelect = m_vEntries.size() - 1;
460 0 : else if ( nKeyCode == KEY_PAGEUP )
461 0 : nSelect = m_nActive - nPageSize + 1;
462 0 : else if ( nKeyCode == KEY_PAGEDOWN )
463 0 : nSelect = m_nActive + nPageSize - 1;
464 : }
465 : else // when there is no selected entry, we will select the first or the last.
466 : {
467 0 : if ( ( nKeyCode == KEY_DOWN ) || ( nKeyCode == KEY_PAGEDOWN ) || ( nKeyCode == KEY_HOME ) )
468 0 : nSelect = 0;
469 0 : else if ( ( nKeyCode == KEY_UP ) || ( nKeyCode == KEY_PAGEUP ) || ( nKeyCode == KEY_END ) )
470 0 : nSelect = m_vEntries.size() - 1;
471 : }
472 :
473 0 : if ( nSelect < 0 )
474 0 : nSelect = 0;
475 0 : if ( nSelect >= (long) m_vEntries.size() )
476 0 : nSelect = m_vEntries.size() - 1;
477 :
478 0 : selectEntry( nSelect );
479 :
480 0 : return true;
481 : }
482 :
483 0 : void ClientBox::Paint( const Rectangle &/*rPaintRect*/ )
484 : {
485 0 : if ( !m_bInDelete )
486 0 : DeleteRemoved();
487 :
488 0 : if ( m_bNeedsRecalc )
489 0 : RecalcAll();
490 :
491 0 : Point aStart( 0, -m_nTopIndex );
492 0 : Size aSize( GetOutputSizePixel() );
493 :
494 0 : if ( m_bHasScrollBar )
495 0 : aSize.Width() -= m_aScrollBar.GetSizePixel().Width();
496 :
497 0 : const ::osl::MutexGuard aGuard( m_entriesMutex );
498 :
499 : typedef std::vector< TClientBoxEntry >::iterator ITER;
500 0 : for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex )
501 : {
502 0 : aSize.Height() = (*iIndex)->m_bActive ? m_nActiveHeight : m_nStdHeight;
503 0 : Rectangle aEntryRect( aStart, aSize );
504 0 : DrawRow( aEntryRect, *iIndex );
505 0 : aStart.Y() += aSize.Height();
506 0 : }
507 0 : }
508 :
509 0 : long ClientBox::GetTotalHeight() const
510 : {
511 0 : long nHeight = m_vEntries.size() * m_nStdHeight;
512 :
513 0 : if ( m_bHasActive )
514 : {
515 0 : nHeight += m_nActiveHeight - m_nStdHeight;
516 : }
517 :
518 0 : return nHeight;
519 : }
520 :
521 0 : void ClientBox::SetupScrollBar()
522 : {
523 0 : const Size aSize = GetOutputSizePixel();
524 0 : const long nScrBarSize = GetSettings().GetStyleSettings().GetScrollBarSize();
525 0 : const long nTotalHeight = GetTotalHeight();
526 0 : const bool bNeedsScrollBar = ( nTotalHeight > aSize.Height() );
527 :
528 0 : if ( bNeedsScrollBar )
529 : {
530 0 : if ( m_nTopIndex + aSize.Height() > nTotalHeight )
531 0 : m_nTopIndex = nTotalHeight - aSize.Height();
532 :
533 0 : m_aScrollBar.SetPosSizePixel( Point( aSize.Width() - nScrBarSize, 0 ),
534 0 : Size( nScrBarSize, aSize.Height() ) );
535 0 : m_aScrollBar.SetRangeMax( nTotalHeight );
536 0 : m_aScrollBar.SetVisibleSize( aSize.Height() );
537 0 : m_aScrollBar.SetPageSize( ( aSize.Height() * 4 ) / 5 );
538 0 : m_aScrollBar.SetLineSize( m_nStdHeight );
539 0 : m_aScrollBar.SetThumbPos( m_nTopIndex );
540 :
541 0 : if ( !m_bHasScrollBar )
542 0 : m_aScrollBar.Show();
543 : }
544 0 : else if ( m_bHasScrollBar )
545 : {
546 0 : m_aScrollBar.Hide();
547 0 : m_nTopIndex = 0;
548 : }
549 :
550 0 : m_bHasScrollBar = bNeedsScrollBar;
551 0 : }
552 :
553 0 : void ClientBox::Resize()
554 : {
555 0 : RecalcAll();
556 0 : }
557 :
558 0 : long ClientBox::PointToPos( const Point& rPos )
559 : {
560 0 : long nPos = ( rPos.Y() + m_nTopIndex ) / m_nStdHeight;
561 :
562 0 : if ( m_bHasActive && ( nPos > m_nActive ) )
563 : {
564 0 : if ( rPos.Y() + m_nTopIndex <= m_nActive*m_nStdHeight + m_nActiveHeight )
565 0 : nPos = m_nActive;
566 : else
567 0 : nPos = ( rPos.Y() + m_nTopIndex - (m_nActiveHeight - m_nStdHeight) ) / m_nStdHeight;
568 : }
569 :
570 0 : return nPos;
571 : }
572 :
573 0 : OUString ClientBox::getPin()
574 : {
575 0 : return OUString::number( m_aPinBox.GetValue() );
576 : }
577 :
578 0 : void ClientBox::MouseButtonDown( const MouseEvent& rMEvt )
579 : {
580 0 : long nPos = PointToPos( rMEvt.GetPosPixel() );
581 :
582 0 : if ( rMEvt.IsLeft() )
583 : {
584 0 : if ( rMEvt.IsMod1() && m_bHasActive )
585 0 : selectEntry( m_vEntries.size() ); // Selecting an not existing entry will deselect the current one
586 : else
587 0 : selectEntry( nPos );
588 : }
589 0 : }
590 :
591 0 : bool ClientBox::Notify( NotifyEvent& rNEvt )
592 : {
593 0 : if ( !m_bInDelete )
594 0 : DeleteRemoved();
595 :
596 0 : bool bHandled = false;
597 :
598 0 : if ( rNEvt.GetType() == EVENT_KEYINPUT )
599 : {
600 0 : const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
601 0 : vcl::KeyCode aKeyCode = pKEvt->GetKeyCode();
602 0 : sal_uInt16 nKeyCode = aKeyCode.GetCode();
603 :
604 0 : if ( nKeyCode == KEY_TAB )
605 0 : bHandled = HandleTabKey( aKeyCode.IsShift() );
606 0 : else if ( aKeyCode.GetGroup() == KEYGROUP_CURSOR )
607 0 : bHandled = HandleCursorKey( nKeyCode );
608 : }
609 :
610 0 : if ( rNEvt.GetType() == EVENT_COMMAND )
611 : {
612 0 : if ( m_bHasScrollBar &&
613 0 : ( rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL ) )
614 : {
615 0 : const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
616 0 : if ( pData->GetMode() == CommandWheelMode::SCROLL )
617 : {
618 0 : long nThumbPos = m_aScrollBar.GetThumbPos();
619 0 : if ( pData->GetDelta() < 0 )
620 0 : m_aScrollBar.DoScroll( nThumbPos + m_nStdHeight );
621 : else
622 0 : m_aScrollBar.DoScroll( nThumbPos - m_nStdHeight );
623 0 : bHandled = true;
624 : }
625 : }
626 : }
627 :
628 0 : if ( !bHandled )
629 0 : return Control::Notify( rNEvt );
630 : else
631 0 : return true;
632 : }
633 :
634 0 : long ClientBox::addEntry( ::boost::shared_ptr<ClientInfo> pClientInfo )
635 : {
636 0 : long nPos = 0;
637 :
638 0 : TClientBoxEntry pEntry( new ClientBoxEntry( pClientInfo ) );
639 :
640 0 : ::osl::ClearableMutexGuard guard(m_entriesMutex);
641 0 : if ( m_vEntries.empty() )
642 : {
643 0 : m_vEntries.push_back( pEntry );
644 : }
645 : else
646 : {
647 : // if ( !FindEntryPos( pEntry, 0, m_vEntries.size()-1, nPos ) )
648 : // {
649 0 : m_vEntries.insert( m_vEntries.begin()+nPos, pEntry );
650 : // }
651 : // else if ( !m_bInCheckMode )
652 : // {
653 : // OSL_FAIL( "ClientBox::addEntry(): Will not add duplicate entries" );
654 : // }
655 : }
656 :
657 : //access to m_nActive must be guarded
658 0 : if ( !m_bInCheckMode && m_bHasActive && ( m_nActive >= nPos ) )
659 0 : m_nActive += 1;
660 :
661 0 : guard.clear();
662 :
663 0 : if ( IsReallyVisible() )
664 0 : Invalidate();
665 :
666 0 : m_bNeedsRecalc = true;
667 :
668 0 : return nPos;
669 : }
670 :
671 0 : void ClientBox::clearEntries()
672 : {
673 0 : selectEntry( -1 );
674 0 : m_bHasActive = false;
675 :
676 0 : const ::osl::MutexGuard aGuard( m_entriesMutex );
677 :
678 0 : m_vEntries.clear();
679 0 : if ( IsReallyVisible() )
680 0 : Invalidate();
681 0 : m_bNeedsRecalc = true;
682 0 : }
683 :
684 0 : void ClientBox::populateEntries()
685 : {
686 0 : const ::osl::MutexGuard aGuard( m_entriesMutex );
687 :
688 0 : clearEntries();
689 :
690 : #ifdef ENABLE_SDREMOTE
691 0 : RemoteServer::ensureDiscoverable();
692 :
693 0 : vector< ::boost::shared_ptr< ClientInfo > > aClients( RemoteServer::getClients() );
694 :
695 0 : const vector< ::boost::shared_ptr<ClientInfo > >::const_iterator aEnd( aClients.end() );
696 :
697 0 : for ( vector< ::boost::shared_ptr< ClientInfo > >::const_iterator aIt( aClients.begin() );
698 : aIt != aEnd; ++aIt )
699 : {
700 0 : addEntry( *aIt );
701 : }
702 : #endif
703 :
704 0 : if ( IsReallyVisible() )
705 0 : Invalidate();
706 0 : m_bNeedsRecalc = true;
707 0 : }
708 :
709 0 : void ClientBox::DoScroll( long nDelta )
710 : {
711 0 : m_nTopIndex += nDelta;
712 0 : Point aNewSBPt( m_aScrollBar.GetPosPixel() );
713 :
714 0 : Rectangle aScrRect( Point(), GetOutputSizePixel() );
715 0 : aScrRect.Right() -= m_aScrollBar.GetSizePixel().Width();
716 0 : Scroll( 0, -nDelta, aScrRect );
717 :
718 0 : m_aScrollBar.SetPosPixel( aNewSBPt );
719 0 : }
720 :
721 0 : IMPL_LINK( ClientBox, ScrollHdl, ScrollBar*, pScrBar )
722 : {
723 0 : DoScroll( pScrBar->GetDelta() );
724 :
725 0 : return 1;
726 : }
727 :
728 0 : IMPL_LINK_NOARG( ClientBox, DeauthoriseHdl )
729 : {
730 0 : long aSelected = GetActiveEntryIndex();
731 0 : if ( aSelected < 0 )
732 0 : return 1;
733 0 : TClientBoxEntry aEntry = GetEntryData(aSelected);
734 :
735 : #ifdef ENABLE_SDREMOTE
736 0 : RemoteServer::deauthoriseClient( aEntry->m_pClientInfo );
737 : #endif
738 0 : populateEntries();
739 0 : return 1;
740 : }
741 :
742 0 : } //namespace dp_gui
743 :
744 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|