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 <vcl/svapp.hxx>
21 : #include <vcl/salnativewidgets.hxx>
22 : #include <vcl/help.hxx>
23 :
24 : #include <stack>
25 :
26 : #include <svtools/treelistbox.hxx>
27 : #include <svtools/svlbitm.hxx>
28 : #include <svimpbox.hxx>
29 : #include <rtl/instance.hxx>
30 : #include <svtools/svtresid.hxx>
31 : #include <tools/wintypes.hxx>
32 : #include <svtools/svtools.hrc>
33 : #include <comphelper/processfactory.hxx>
34 : #include <comphelper/string.hxx>
35 :
36 : #include "svtools/treelistentry.hxx"
37 : #include "svtools/viewdataentry.hxx"
38 :
39 : #define NODE_BMP_TABDIST_NOTVALID -2000000
40 : #define FIRST_ENTRY_TAB 1
41 :
42 : // #i27063# (pl), #i32300# (pb) never access VCL after DeInitVCL - also no destructors
43 : Image* SvImpLBox::s_pDefCollapsed = NULL;
44 : Image* SvImpLBox::s_pDefExpanded = NULL;
45 : sal_Int32 SvImpLBox::s_nImageRefCount = 0;
46 :
47 0 : SvImpLBox::SvImpLBox( SvTreeListBox* pLBView, SvTreeList* pLBTree, WinBits nWinStyle) :
48 :
49 : aVerSBar( pLBView, WB_DRAG | WB_VSCROLL ),
50 : aHorSBar( pLBView, WB_DRAG | WB_HSCROLL ),
51 : aScrBarBox( pLBView ),
52 : aOutputSize( 0, 0 ),
53 : aSelEng( pLBView, (FunctionSet*)0 ),
54 : aFctSet( this, &aSelEng, pLBView ),
55 : nExtendedWinBits( 0 ),
56 : bAreChildrenTransient( true ),
57 0 : m_pStringSorter(NULL)
58 : {
59 0 : osl_atomic_increment(&s_nImageRefCount);
60 0 : pView = pLBView;
61 0 : pTree = pLBTree;
62 0 : aSelEng.SetFunctionSet( (FunctionSet*)&aFctSet );
63 0 : aSelEng.ExpandSelectionOnMouseMove( false );
64 0 : SetStyle( nWinStyle );
65 0 : SetSelectionMode( SINGLE_SELECTION );
66 0 : SetDragDropMode( 0 );
67 :
68 0 : aVerSBar.SetScrollHdl( LINK( this, SvImpLBox, ScrollUpDownHdl ) );
69 0 : aHorSBar.SetScrollHdl( LINK( this, SvImpLBox, ScrollLeftRightHdl ) );
70 0 : aHorSBar.SetEndScrollHdl( LINK( this, SvImpLBox, EndScrollHdl ) );
71 0 : aVerSBar.SetEndScrollHdl( LINK( this, SvImpLBox, EndScrollHdl ) );
72 0 : aVerSBar.SetRange( Range(0,0) );
73 0 : aVerSBar.Hide();
74 0 : aHorSBar.SetRange( Range(0,0) );
75 0 : aHorSBar.SetPageSize( 24 ); // pixels
76 0 : aHorSBar.SetLineSize( 8 ); // pixels
77 :
78 0 : nHorSBarHeight = (short)aHorSBar.GetSizePixel().Height();
79 0 : nVerSBarWidth = (short)aVerSBar.GetSizePixel().Width();
80 :
81 0 : pStartEntry = 0;
82 0 : pCursor = 0;
83 0 : pAnchor = 0;
84 0 : nVisibleCount = 0; // number of rows of data in control
85 0 : nNodeBmpTabDistance = NODE_BMP_TABDIST_NOTVALID;
86 0 : nYoffsNodeBmp = 0;
87 0 : nNodeBmpWidth = 0;
88 :
89 0 : bAsyncBeginDrag = false;
90 0 : aAsyncBeginDragTimer.SetTimeout( 0 );
91 0 : aAsyncBeginDragTimer.SetTimeoutHdl( LINK(this,SvImpLBox,BeginDragHdl));
92 : // button animation in listbox
93 0 : pActiveButton = 0;
94 0 : pActiveEntry = 0;
95 0 : pActiveTab = 0;
96 :
97 0 : nFlags = 0;
98 0 : nCurTabPos = FIRST_ENTRY_TAB;
99 :
100 0 : aEditTimer.SetTimeout( 800 );
101 0 : aEditTimer.SetTimeoutHdl( LINK(this,SvImpLBox,EditTimerCall) );
102 :
103 0 : nMostRight = -1;
104 0 : pMostRightEntry = 0;
105 0 : nCurUserEvent = 0xffffffff;
106 :
107 0 : bUpdateMode = true;
108 0 : bInVScrollHdl = false;
109 0 : nFlags |= F_FILLING;
110 :
111 0 : bSubLstOpRet = bSubLstOpLR = bContextMenuHandling = bIsCellFocusEnabled = false;
112 0 : }
113 :
114 0 : SvImpLBox::~SvImpLBox()
115 : {
116 0 : aEditTimer.Stop();
117 0 : StopUserEvent();
118 :
119 0 : delete m_pStringSorter;
120 0 : if ( osl_atomic_decrement(&s_nImageRefCount) == 0 )
121 : {
122 0 : DELETEZ(s_pDefCollapsed);
123 0 : DELETEZ(s_pDefExpanded);
124 : }
125 0 : }
126 :
127 0 : void SvImpLBox::UpdateStringSorter()
128 : {
129 0 : const ::com::sun::star::lang::Locale& rNewLocale = Application::GetSettings().GetLanguageTag().getLocale();
130 :
131 0 : if( m_pStringSorter )
132 : {
133 : // different Locale from the older one, drop it and force recreate
134 0 : const ::com::sun::star::lang::Locale &aLocale = m_pStringSorter->getLocale();
135 0 : if( aLocale.Language != rNewLocale.Language ||
136 0 : aLocale.Country != rNewLocale.Country ||
137 0 : aLocale.Variant != rNewLocale.Variant )
138 : {
139 0 : delete m_pStringSorter;
140 0 : m_pStringSorter = NULL;
141 : }
142 : }
143 :
144 0 : if( !m_pStringSorter )
145 : {
146 : m_pStringSorter = new comphelper::string::NaturalStringSorter(
147 : ::comphelper::getProcessComponentContext(),
148 0 : rNewLocale);
149 : }
150 0 : }
151 :
152 : // #97680# ----------------------
153 0 : short SvImpLBox::UpdateContextBmpWidthVector( SvTreeListEntry* pEntry, short nWidth )
154 : {
155 : DBG_ASSERT( pView->pModel, "View and Model aren't valid!" );
156 :
157 0 : sal_uInt16 nDepth = pView->pModel->GetDepth( pEntry );
158 : // initialize vector if necessary
159 0 : std::vector< short >::size_type nSize = aContextBmpWidthVector.size();
160 0 : while ( nDepth > nSize )
161 : {
162 0 : aContextBmpWidthVector.resize( nSize + 1 );
163 0 : aContextBmpWidthVector.at( nSize ) = nWidth;
164 0 : ++nSize;
165 : }
166 0 : if( aContextBmpWidthVector.size() == nDepth )
167 : {
168 0 : aContextBmpWidthVector.resize( nDepth + 1 );
169 0 : aContextBmpWidthVector.at( nDepth ) = 0;
170 : }
171 0 : short nContextBmpWidth = aContextBmpWidthVector[ nDepth ];
172 0 : if( nContextBmpWidth < nWidth )
173 : {
174 0 : aContextBmpWidthVector.at( nDepth ) = nWidth;
175 0 : return nWidth;
176 : }
177 : else
178 0 : return nContextBmpWidth;
179 : }
180 :
181 0 : void SvImpLBox::UpdateContextBmpWidthVectorFromMovedEntry( SvTreeListEntry* pEntry )
182 : {
183 : DBG_ASSERT( pEntry, "Moved Entry is invalid!" );
184 :
185 0 : SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
186 0 : short nExpWidth = (short)pBmpItem->GetBitmap1().GetSizePixel().Width();
187 0 : short nColWidth = (short)pBmpItem->GetBitmap2().GetSizePixel().Width();
188 0 : short nMax = Max(nExpWidth, nColWidth);
189 0 : UpdateContextBmpWidthVector( pEntry, nMax );
190 :
191 0 : if( pEntry->HasChildren() ) // recursive call, whether expanded or not
192 : {
193 0 : SvTreeListEntry* pChild = pView->FirstChild( pEntry );
194 : DBG_ASSERT( pChild, "The first child is invalid!" );
195 0 : do
196 : {
197 0 : UpdateContextBmpWidthVectorFromMovedEntry( pChild );
198 0 : pChild = pView->Next( pChild );
199 : } while ( pChild );
200 : }
201 0 : }
202 :
203 0 : void SvImpLBox::UpdateContextBmpWidthMax( SvTreeListEntry* pEntry )
204 : {
205 0 : sal_uInt16 nDepth = pView->pModel->GetDepth( pEntry );
206 0 : if( aContextBmpWidthVector.size() < 1 )
207 0 : return;
208 0 : short nWidth = aContextBmpWidthVector[ nDepth ];
209 0 : if( nWidth != pView->nContextBmpWidthMax ) {
210 0 : pView->nContextBmpWidthMax = nWidth;
211 0 : nFlags |= F_IGNORE_CHANGED_TABS;
212 0 : pView->SetTabs();
213 0 : nFlags &= ~F_IGNORE_CHANGED_TABS;
214 : }
215 : }
216 :
217 0 : void SvImpLBox::CalcCellFocusRect( SvTreeListEntry* pEntry, Rectangle& rRect )
218 : {
219 0 : if ( pEntry && bIsCellFocusEnabled )
220 : {
221 0 : if ( nCurTabPos > FIRST_ENTRY_TAB )
222 : {
223 0 : SvLBoxItem* pItem = pCursor->GetItem( nCurTabPos );
224 0 : rRect.Left() = pView->GetTab( pCursor, pItem )->GetPos();
225 : }
226 0 : if (pCursor->ItemCount() > static_cast<size_t>(nCurTabPos+1))
227 : {
228 0 : SvLBoxItem* pNextItem = pCursor->GetItem( nCurTabPos + 1 );
229 0 : long nRight = pView->GetTab( pCursor, pNextItem )->GetPos() - 1;
230 0 : if ( nRight < rRect.Right() )
231 0 : rRect.Right() = nRight;
232 : }
233 : }
234 0 : }
235 :
236 0 : void SvImpLBox::SetStyle( WinBits i_nWinStyle )
237 : {
238 0 : m_nStyle = i_nWinStyle;
239 0 : if ( ( m_nStyle & WB_SIMPLEMODE) && ( aSelEng.GetSelectionMode() == MULTIPLE_SELECTION ) )
240 0 : aSelEng.AddAlways( true );
241 0 : }
242 :
243 0 : void SvImpLBox::SetExtendedWindowBits( ExtendedWinBits _nBits )
244 : {
245 0 : nExtendedWinBits = _nBits;
246 0 : }
247 :
248 : // don't touch the model any more
249 0 : void SvImpLBox::Clear()
250 : {
251 0 : StopUserEvent();
252 0 : pStartEntry = 0;
253 0 : pAnchor = 0;
254 :
255 0 : pActiveButton = 0;
256 0 : pActiveEntry = 0;
257 0 : pActiveTab = 0;
258 :
259 0 : nMostRight = -1;
260 0 : pMostRightEntry = 0;
261 :
262 : // don't touch the cursor any more
263 0 : if( pCursor )
264 : {
265 0 : if( pView->HasFocus() )
266 0 : pView->HideFocus();
267 0 : pCursor = 0;
268 : }
269 0 : aVerSBar.Hide();
270 0 : aVerSBar.SetThumbPos( 0 );
271 0 : Range aRange( 0, 0 );
272 0 : aVerSBar.SetRange( aRange );
273 0 : aOutputSize = pView->Control::GetOutputSizePixel();
274 0 : nFlags &= ~(F_VER_SBARSIZE_WITH_HBAR | F_HOR_SBARSIZE_WITH_VBAR );
275 0 : aHorSBar.Hide();
276 0 : aHorSBar.SetThumbPos( 0 );
277 0 : MapMode aMapMode( pView->GetMapMode());
278 0 : aMapMode.SetOrigin( Point(0,0) );
279 0 : pView->Control::SetMapMode( aMapMode );
280 0 : aHorSBar.SetRange( aRange );
281 0 : aHorSBar.SetSizePixel(Size(aOutputSize.Width(),nHorSBarHeight));
282 0 : pView->SetClipRegion();
283 0 : if( GetUpdateMode() )
284 0 : pView->Invalidate( GetVisibleArea() );
285 0 : nFlags |= F_FILLING;
286 0 : if( !aHorSBar.IsVisible() && !aVerSBar.IsVisible() )
287 0 : aScrBarBox.Hide();
288 :
289 0 : aContextBmpWidthVector.clear();
290 0 : }
291 :
292 : // *********************************************************************
293 : // Paint, navigate, scroll
294 : // *********************************************************************
295 :
296 0 : IMPL_LINK_NOARG_INLINE_START(SvImpLBox, EndScrollHdl)
297 : {
298 0 : if( nFlags & F_ENDSCROLL_SET_VIS_SIZE )
299 : {
300 0 : aVerSBar.SetVisibleSize( nNextVerVisSize );
301 0 : nFlags &= ~F_ENDSCROLL_SET_VIS_SIZE;
302 : }
303 0 : EndScroll();
304 0 : return 0;
305 : }
306 0 : IMPL_LINK_NOARG_INLINE_END(SvImpLBox, EndScrollHdl)
307 :
308 :
309 : // handler for vertical scrollbar
310 :
311 0 : IMPL_LINK( SvImpLBox, ScrollUpDownHdl, ScrollBar *, pScrollBar )
312 : {
313 : DBG_ASSERT(!bInVScrollHdl,"Scroll handler out-paces itself!");
314 0 : long nDelta = pScrollBar->GetDelta();
315 0 : if( !nDelta )
316 0 : return 0;
317 :
318 0 : nFlags &= (~F_FILLING);
319 :
320 0 : bInVScrollHdl = true;
321 :
322 0 : if( pView->IsEditingActive() )
323 : {
324 0 : pView->EndEditing( true ); // Cancel
325 0 : pView->Update();
326 : }
327 0 : BeginScroll();
328 :
329 0 : if( nDelta > 0 )
330 : {
331 0 : if( nDelta == 1 )
332 0 : CursorDown();
333 : else
334 0 : PageDown( (sal_uInt16) nDelta );
335 : }
336 : else
337 : {
338 0 : nDelta *= (-1);
339 0 : if( nDelta == 1 )
340 0 : CursorUp();
341 : else
342 0 : PageUp( (sal_uInt16) nDelta );
343 : }
344 0 : bInVScrollHdl = false;
345 0 : return 0;
346 : }
347 :
348 :
349 0 : void SvImpLBox::CursorDown()
350 : {
351 0 : SvTreeListEntry* pNextFirstToDraw = pView->NextVisible(pStartEntry);
352 0 : if( pNextFirstToDraw )
353 : {
354 0 : nFlags &= (~F_FILLING);
355 0 : pView->NotifyScrolling( -1 );
356 0 : ShowCursor( false );
357 0 : pView->Update();
358 0 : pStartEntry = pNextFirstToDraw;
359 0 : Rectangle aArea( GetVisibleArea() );
360 0 : pView->Scroll( 0, -(pView->GetEntryHeight()), aArea, SCROLL_NOCHILDREN );
361 0 : pView->Update();
362 0 : ShowCursor( true );
363 0 : pView->NotifyScrolled();
364 : }
365 0 : }
366 :
367 0 : void SvImpLBox::CursorUp()
368 : {
369 0 : SvTreeListEntry* pPrevFirstToDraw = pView->PrevVisible(pStartEntry);
370 0 : if( pPrevFirstToDraw )
371 : {
372 0 : nFlags &= (~F_FILLING);
373 0 : long nEntryHeight = pView->GetEntryHeight();
374 0 : pView->NotifyScrolling( 1 );
375 0 : ShowCursor( false );
376 0 : pView->Update();
377 0 : pStartEntry = pPrevFirstToDraw;
378 0 : Rectangle aArea( GetVisibleArea() );
379 0 : aArea.Bottom() -= nEntryHeight;
380 0 : pView->Scroll( 0, nEntryHeight, aArea, SCROLL_NOCHILDREN );
381 0 : pView->Update();
382 0 : ShowCursor( true );
383 0 : pView->NotifyScrolled();
384 : }
385 0 : }
386 :
387 0 : void SvImpLBox::PageDown( sal_uInt16 nDelta )
388 : {
389 0 : sal_uInt16 nRealDelta = nDelta;
390 :
391 0 : if( !nDelta )
392 : return;
393 :
394 0 : SvTreeListEntry* pNext = pView->NextVisible(pStartEntry, nRealDelta);
395 0 : if( (sal_uLong)pNext == (sal_uLong)pStartEntry )
396 : return;
397 :
398 0 : ShowCursor( false );
399 :
400 0 : nFlags &= (~F_FILLING);
401 0 : pView->Update();
402 0 : pStartEntry = pNext;
403 :
404 0 : if( nRealDelta >= nVisibleCount )
405 : {
406 0 : pView->Invalidate( GetVisibleArea() );
407 0 : pView->Update();
408 : }
409 : else
410 : {
411 0 : long nScroll = nRealDelta * (-1);
412 0 : pView->NotifyScrolling( nScroll );
413 0 : Rectangle aArea( GetVisibleArea() );
414 0 : nScroll = pView->GetEntryHeight()*nRealDelta;
415 0 : nScroll = -nScroll;
416 0 : pView->Update();
417 0 : pView->Scroll( 0, nScroll, aArea, SCROLL_NOCHILDREN );
418 0 : pView->Update();
419 0 : pView->NotifyScrolled();
420 : }
421 :
422 0 : ShowCursor( true );
423 : }
424 :
425 0 : void SvImpLBox::PageUp( sal_uInt16 nDelta )
426 : {
427 0 : sal_uInt16 nRealDelta = nDelta;
428 0 : if( !nDelta )
429 : return;
430 :
431 0 : SvTreeListEntry* pPrev = pView->PrevVisible(pStartEntry, nRealDelta);
432 0 : if( (sal_uLong)pPrev == (sal_uLong)pStartEntry )
433 : return;
434 :
435 0 : nFlags &= (~F_FILLING);
436 0 : ShowCursor( false );
437 :
438 0 : pView->Update();
439 0 : pStartEntry = pPrev;
440 0 : if( nRealDelta >= nVisibleCount )
441 : {
442 0 : pView->Invalidate( GetVisibleArea() );
443 0 : pView->Update();
444 : }
445 : else
446 : {
447 0 : long nEntryHeight = pView->GetEntryHeight();
448 0 : pView->NotifyScrolling( (long)nRealDelta );
449 0 : Rectangle aArea( GetVisibleArea() );
450 0 : pView->Update();
451 0 : pView->Scroll( 0, nEntryHeight*nRealDelta, aArea, SCROLL_NOCHILDREN );
452 0 : pView->Update();
453 0 : pView->NotifyScrolled();
454 : }
455 :
456 0 : ShowCursor( true );
457 : }
458 :
459 0 : void SvImpLBox::KeyUp( bool bPageUp, bool bNotifyScroll )
460 : {
461 0 : if( !aVerSBar.IsVisible() )
462 0 : return;
463 :
464 : long nDelta;
465 0 : if( bPageUp )
466 0 : nDelta = aVerSBar.GetPageSize();
467 : else
468 0 : nDelta = 1;
469 :
470 0 : long nThumbPos = aVerSBar.GetThumbPos();
471 :
472 0 : if( nThumbPos < nDelta )
473 0 : nDelta = nThumbPos;
474 :
475 0 : if( nDelta <= 0 )
476 0 : return;
477 :
478 0 : nFlags &= (~F_FILLING);
479 0 : if( bNotifyScroll )
480 0 : BeginScroll();
481 :
482 0 : aVerSBar.SetThumbPos( nThumbPos - nDelta );
483 0 : if( bPageUp )
484 0 : PageUp( (short)nDelta );
485 : else
486 0 : CursorUp();
487 :
488 0 : if( bNotifyScroll )
489 0 : EndScroll();
490 : }
491 :
492 :
493 0 : void SvImpLBox::KeyDown( bool bPageDown, bool bNotifyScroll )
494 : {
495 0 : if( !aVerSBar.IsVisible() )
496 0 : return;
497 :
498 : long nDelta;
499 0 : if( bPageDown )
500 0 : nDelta = aVerSBar.GetPageSize();
501 : else
502 0 : nDelta = 1;
503 :
504 0 : long nThumbPos = aVerSBar.GetThumbPos();
505 0 : long nVisibleSize = aVerSBar.GetVisibleSize();
506 0 : long nRange = aVerSBar.GetRange().Len();
507 :
508 0 : long nTmp = nThumbPos+nVisibleSize;
509 0 : while( (nDelta > 0) && (nTmp+nDelta) >= nRange )
510 0 : nDelta--;
511 :
512 0 : if( nDelta <= 0 )
513 0 : return;
514 :
515 0 : nFlags &= (~F_FILLING);
516 0 : if( bNotifyScroll )
517 0 : BeginScroll();
518 :
519 0 : aVerSBar.SetThumbPos( nThumbPos+nDelta );
520 0 : if( bPageDown )
521 0 : PageDown( (short)nDelta );
522 : else
523 0 : CursorDown();
524 :
525 0 : if( bNotifyScroll )
526 0 : EndScroll();
527 : }
528 :
529 :
530 :
531 0 : void SvImpLBox::InvalidateEntriesFrom( long nY ) const
532 : {
533 0 : if( !(nFlags & F_IN_PAINT ))
534 : {
535 0 : Rectangle aRect( GetVisibleArea() );
536 0 : aRect.Top() = nY;
537 0 : pView->Invalidate( aRect );
538 : }
539 0 : }
540 :
541 0 : void SvImpLBox::InvalidateEntry( long nY ) const
542 : {
543 0 : if( !(nFlags & F_IN_PAINT ))
544 : {
545 0 : Rectangle aRect( GetVisibleArea() );
546 0 : long nMaxBottom = aRect.Bottom();
547 0 : aRect.Top() = nY;
548 0 : aRect.Bottom() = nY; aRect.Bottom() += pView->GetEntryHeight();
549 0 : if( aRect.Top() > nMaxBottom )
550 0 : return;
551 0 : if( aRect.Bottom() > nMaxBottom )
552 0 : aRect.Bottom() = nMaxBottom;
553 0 : pView->Invalidate( aRect );
554 : }
555 : }
556 :
557 0 : void SvImpLBox::InvalidateEntry( SvTreeListEntry* pEntry )
558 : {
559 0 : if( GetUpdateMode() )
560 : {
561 0 : long nPrev = nMostRight;
562 0 : SetMostRight( pEntry );
563 0 : if( nPrev < nMostRight )
564 0 : ShowVerSBar();
565 : }
566 0 : if( !(nFlags & F_IN_PAINT ))
567 : {
568 0 : bool bHasFocusRect = false;
569 0 : if( pEntry==pCursor && pView->HasFocus() )
570 : {
571 0 : bHasFocusRect = true;
572 0 : ShowCursor( false );
573 : }
574 0 : InvalidateEntry( GetEntryLine( pEntry ) );
575 0 : if( bHasFocusRect )
576 0 : ShowCursor( true );
577 : }
578 0 : }
579 :
580 :
581 0 : void SvImpLBox::RecalcFocusRect()
582 : {
583 0 : if( pView->HasFocus() && pCursor )
584 : {
585 0 : pView->HideFocus();
586 0 : long nY = GetEntryLine( pCursor );
587 0 : Rectangle aRect = pView->GetFocusRect( pCursor, nY );
588 0 : CalcCellFocusRect( pCursor, aRect );
589 0 : Region aOldClip( pView->GetClipRegion());
590 0 : Region aClipRegion( GetClipRegionRect() );
591 0 : pView->SetClipRegion( aClipRegion );
592 0 : pView->ShowFocus( aRect );
593 0 : pView->SetClipRegion( aOldClip );
594 : }
595 0 : }
596 :
597 : //
598 : // Sets cursor. When using SingleSelection, the selection is adjusted.
599 : //
600 :
601 0 : void SvImpLBox::SetCursor( SvTreeListEntry* pEntry, bool bForceNoSelect )
602 : {
603 0 : SvViewDataEntry* pViewDataNewCur = 0;
604 0 : if( pEntry )
605 0 : pViewDataNewCur= pView->GetViewDataEntry(pEntry);
606 0 : if( pEntry &&
607 : pEntry == pCursor &&
608 0 : pViewDataNewCur->HasFocus() &&
609 0 : pViewDataNewCur->IsSelected())
610 : {
611 0 : return;
612 : }
613 :
614 : // if this cursor is not selectable, find first visible that is and use it
615 0 : while( pEntry && pViewDataNewCur && !pViewDataNewCur->IsSelectable() )
616 : {
617 0 : pEntry = pView->NextVisible(pEntry);
618 0 : pViewDataNewCur = pEntry ? pView->GetViewDataEntry(pEntry) : 0;
619 : }
620 :
621 0 : SvTreeListEntry* pOldCursor = pCursor;
622 0 : if( pCursor && pEntry != pCursor )
623 : {
624 0 : pView->SetEntryFocus( pCursor, false );
625 0 : if( bSimpleTravel )
626 0 : pView->Select( pCursor, false );
627 0 : pView->HideFocus();
628 : }
629 0 : pCursor = pEntry;
630 0 : if( pCursor )
631 : {
632 0 : pViewDataNewCur->SetFocus( true );
633 0 : if(!bForceNoSelect && bSimpleTravel && !(nFlags & F_DESEL_ALL) && GetUpdateMode())
634 : {
635 0 : pView->Select( pCursor, true );
636 : }
637 : // multiple selection: select in cursor move if we're not in
638 : // Add mode (Ctrl-F8)
639 0 : else if( GetUpdateMode() &&
640 0 : pView->GetSelectionMode() == MULTIPLE_SELECTION &&
641 0 : !(nFlags & F_DESEL_ALL) && !aSelEng.IsAddMode() &&
642 0 : !bForceNoSelect )
643 : {
644 0 : pView->Select( pCursor, true );
645 : }
646 : else
647 : {
648 0 : ShowCursor( true );
649 : }
650 :
651 0 : if( pAnchor )
652 : {
653 : DBG_ASSERT(aSelEng.GetSelectionMode() != SINGLE_SELECTION,"Mode?");
654 0 : SetAnchorSelection( pOldCursor, pCursor );
655 : }
656 : }
657 0 : nFlags &= (~F_DESEL_ALL);
658 :
659 0 : pView->OnCurrentEntryChanged();
660 : }
661 :
662 0 : void SvImpLBox::ShowCursor( bool bShow )
663 : {
664 0 : if( !bShow || !pCursor || !pView->HasFocus() )
665 : {
666 0 : Region aOldClip( pView->GetClipRegion());
667 0 : Region aClipRegion( GetClipRegionRect() );
668 0 : pView->SetClipRegion( aClipRegion );
669 0 : pView->HideFocus();
670 0 : pView->SetClipRegion( aOldClip );
671 : }
672 : else
673 : {
674 0 : long nY = GetEntryLine( pCursor );
675 0 : Rectangle aRect = pView->GetFocusRect( pCursor, nY );
676 0 : CalcCellFocusRect( pCursor, aRect );
677 0 : Region aOldClip( pView->GetClipRegion());
678 0 : Region aClipRegion( GetClipRegionRect() );
679 0 : pView->SetClipRegion( aClipRegion );
680 0 : pView->ShowFocus( aRect );
681 0 : pView->SetClipRegion( aOldClip );
682 : }
683 0 : }
684 :
685 :
686 :
687 0 : void SvImpLBox::UpdateAll(
688 : bool bInvalidateCompleteView, bool bUpdateVerScrollBar )
689 : {
690 0 : if( bUpdateVerScrollBar )
691 0 : FindMostRight(0);
692 0 : aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
693 0 : SyncVerThumb();
694 0 : FillView();
695 0 : ShowVerSBar();
696 0 : if( bSimpleTravel && pCursor && pView->HasFocus() )
697 0 : pView->Select( pCursor, true );
698 0 : ShowCursor( true );
699 0 : if( bInvalidateCompleteView )
700 0 : pView->Invalidate();
701 : else
702 0 : pView->Invalidate( GetVisibleArea() );
703 0 : }
704 :
705 0 : IMPL_LINK_INLINE_START( SvImpLBox, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
706 : {
707 0 : long nDelta = pScrollBar->GetDelta();
708 0 : if( nDelta )
709 : {
710 0 : if( pView->IsEditingActive() )
711 : {
712 0 : pView->EndEditing( true ); // Cancel
713 0 : pView->Update();
714 : }
715 0 : pView->nFocusWidth = -1;
716 0 : KeyLeftRight( nDelta );
717 : }
718 0 : return 0;
719 : }
720 0 : IMPL_LINK_INLINE_END( SvImpLBox, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
721 :
722 0 : void SvImpLBox::KeyLeftRight( long nDelta )
723 : {
724 0 : if( !(nFlags & F_IN_RESIZE) )
725 0 : pView->Update();
726 0 : BeginScroll();
727 0 : nFlags &= (~F_FILLING);
728 0 : pView->NotifyScrolling( 0 ); // 0 == horizontal scrolling
729 0 : ShowCursor( false );
730 :
731 : // neuen Origin berechnen
732 0 : long nPos = aHorSBar.GetThumbPos();
733 0 : Point aOrigin( -nPos, 0 );
734 :
735 0 : MapMode aMapMode( pView->GetMapMode() );
736 0 : aMapMode.SetOrigin( aOrigin );
737 0 : pView->SetMapMode( aMapMode );
738 :
739 0 : if( !(nFlags & F_IN_RESIZE) )
740 : {
741 0 : Rectangle aRect( GetVisibleArea() );
742 0 : pView->Scroll( -nDelta, 0, aRect, SCROLL_NOCHILDREN );
743 : }
744 : else
745 0 : pView->Invalidate();
746 0 : RecalcFocusRect();
747 0 : ShowCursor( true );
748 0 : pView->NotifyScrolled();
749 0 : }
750 :
751 :
752 : // returns the last entry if position is just past the last entry
753 0 : SvTreeListEntry* SvImpLBox::GetClickedEntry( const Point& rPoint ) const
754 : {
755 : DBG_ASSERT( pView->GetModel(), "SvImpLBox::GetClickedEntry: how can this ever happen? Please tell me (frank.schoenheit@sun.com) how to reproduce!" );
756 0 : if ( !pView->GetModel() )
757 : // this is quite impossible. Nevertheless, stack traces from the crash reporter
758 : // suggest it isn't. Okay, make it safe, and wait for somebody to reproduce it
759 : // reliably :-\ ....
760 : // #122359# / 2005-05-23 / frank.schoenheit@sun.com
761 0 : return NULL;
762 0 : if( pView->GetEntryCount() == 0 || !pStartEntry || !pView->GetEntryHeight())
763 0 : return 0;
764 :
765 0 : sal_uInt16 nClickedEntry = (sal_uInt16)(rPoint.Y() / pView->GetEntryHeight() );
766 0 : sal_uInt16 nTemp = nClickedEntry;
767 0 : SvTreeListEntry* pEntry = pView->NextVisible(pStartEntry, nTemp);
768 0 : return pEntry;
769 : }
770 :
771 : //
772 : // checks if the entry was hit "the right way"
773 : // (Focusrect+ ContextBitmap bei TreeListBox)
774 : //
775 0 : bool SvImpLBox::EntryReallyHit(SvTreeListEntry* pEntry, const Point& rPosPixel, long nLine)
776 : {
777 : bool bRet;
778 : // we are not too exact when it comes to "special" entries
779 : // (with CheckButtons etc.)
780 0 : if( pEntry->ItemCount() >= 3 )
781 0 : return true;
782 :
783 0 : Rectangle aRect( pView->GetFocusRect( pEntry, nLine ));
784 0 : aRect.Right() = GetOutputSize().Width() - pView->GetMapMode().GetOrigin().X();
785 :
786 0 : SvLBoxContextBmp* pBmp = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
787 0 : aRect.Left() -= pBmp->GetSize(pView,pEntry).Width();
788 0 : aRect.Left() -= 4; // a little tolerance
789 :
790 0 : Point aPos( rPosPixel );
791 0 : aPos -= pView->GetMapMode().GetOrigin();
792 0 : if( aRect.IsInside( aPos ) )
793 0 : bRet = true;
794 : else
795 0 : bRet = false;
796 0 : return bRet;
797 : }
798 :
799 :
800 : // returns 0 if position is just past the last entry
801 0 : SvTreeListEntry* SvImpLBox::GetEntry( const Point& rPoint ) const
802 : {
803 0 : if( (pView->GetEntryCount() == 0) || !pStartEntry ||
804 0 : (rPoint.Y() > aOutputSize.Height())
805 0 : || !pView->GetEntryHeight())
806 0 : return 0;
807 :
808 0 : sal_uInt16 nClickedEntry = (sal_uInt16)(rPoint.Y() / pView->GetEntryHeight() );
809 0 : sal_uInt16 nTemp = nClickedEntry;
810 0 : SvTreeListEntry* pEntry = pView->NextVisible(pStartEntry, nTemp);
811 0 : if( nTemp != nClickedEntry )
812 0 : pEntry = 0;
813 0 : return pEntry;
814 : }
815 :
816 :
817 0 : SvTreeListEntry* SvImpLBox::MakePointVisible(const Point& rPoint, bool bNotifyScroll)
818 : {
819 0 : if( !pCursor )
820 0 : return 0;
821 0 : long nY = rPoint.Y();
822 0 : SvTreeListEntry* pEntry = 0;
823 0 : long nMax = aOutputSize.Height();
824 0 : if( nY < 0 || nY >= nMax ) // aOutputSize.Height() )
825 : {
826 0 : if( nY < 0 )
827 0 : pEntry = pView->PrevVisible(pCursor);
828 : else
829 0 : pEntry = pView->NextVisible(pCursor);
830 :
831 0 : if( pEntry && pEntry != pCursor )
832 0 : pView->SetEntryFocus( pCursor, false );
833 :
834 0 : if( nY < 0 )
835 0 : KeyUp( false, bNotifyScroll );
836 : else
837 0 : KeyDown( false, bNotifyScroll );
838 : }
839 : else
840 : {
841 0 : pEntry = GetClickedEntry( rPoint );
842 0 : if( !pEntry )
843 : {
844 0 : sal_uInt16 nSteps = 0xFFFF;
845 : // TODO: LastVisible is not yet implemented!
846 0 : pEntry = pView->NextVisible(pStartEntry, nSteps);
847 : }
848 0 : if( pEntry )
849 : {
850 0 : if( pEntry != pCursor &&
851 0 : aSelEng.GetSelectionMode() == SINGLE_SELECTION
852 : )
853 0 : pView->Select( pCursor, false );
854 : }
855 : }
856 0 : return pEntry;
857 : }
858 :
859 0 : Rectangle SvImpLBox::GetClipRegionRect() const
860 : {
861 0 : Point aOrigin( pView->GetMapMode().GetOrigin() );
862 0 : aOrigin.X() *= -1; // conversion document coordinates
863 0 : Rectangle aClipRect( aOrigin, aOutputSize );
864 0 : aClipRect.Bottom()++;
865 0 : return aClipRect;
866 : }
867 :
868 :
869 0 : void SvImpLBox::Paint( const Rectangle& rRect )
870 : {
871 0 : if( !pView->GetVisibleCount() )
872 : return;
873 :
874 0 : nFlags |= F_IN_PAINT;
875 :
876 0 : if( nFlags & F_FILLING )
877 : {
878 0 : SvTreeListEntry* pFirst = pView->First();
879 0 : if( pFirst != pStartEntry )
880 : {
881 0 : ShowCursor( false );
882 0 : pStartEntry = pView->First();
883 0 : aVerSBar.SetThumbPos( 0 );
884 0 : StopUserEvent();
885 0 : ShowCursor( true );
886 0 : nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpLBox,MyUserEvent),(void*)1);
887 : return;
888 : }
889 : }
890 :
891 0 : if( !pStartEntry )
892 : {
893 0 : pStartEntry = pView->First();
894 : }
895 :
896 0 : if( nNodeBmpTabDistance == NODE_BMP_TABDIST_NOTVALID )
897 0 : SetNodeBmpTabDistance();
898 :
899 0 : long nRectHeight = rRect.GetHeight();
900 0 : long nEntryHeight = pView->GetEntryHeight();
901 :
902 : // calculate area for the entries we want to draw
903 0 : sal_uInt16 nStartLine = (sal_uInt16)( rRect.Top() / nEntryHeight );
904 0 : sal_uInt16 nCount = (sal_uInt16)( nRectHeight / nEntryHeight );
905 0 : nCount += 2; // don't miss a row
906 :
907 0 : long nY = nStartLine * nEntryHeight;
908 0 : SvTreeListEntry* pEntry = pStartEntry;
909 0 : while( nStartLine && pEntry )
910 : {
911 0 : pEntry = pView->NextVisible(pEntry);
912 0 : nStartLine--;
913 : }
914 :
915 0 : Region aClipRegion( GetClipRegionRect() );
916 :
917 : // first draw the lines, then clip them!
918 0 : pView->SetClipRegion();
919 0 : if( m_nStyle & ( WB_HASLINES | WB_HASLINESATROOT ) )
920 0 : DrawNet();
921 :
922 0 : pView->SetClipRegion( aClipRegion );
923 :
924 0 : for( sal_uInt16 n=0; n< nCount && pEntry; n++ )
925 : {
926 : /*long nMaxRight=*/
927 0 : pView->PaintEntry1( pEntry, nY, 0xffff, true );
928 0 : nY += nEntryHeight;
929 0 : pEntry = pView->NextVisible(pEntry);
930 : }
931 :
932 0 : if ( !pCursor && ( ( nExtendedWinBits & EWB_NO_AUTO_CURENTRY ) == 0 ) )
933 : {
934 : // do not select if multiselection or explicit set
935 0 : bool bNotSelect = ( aSelEng.GetSelectionMode() == MULTIPLE_SELECTION )
936 0 : || ( ( m_nStyle & WB_NOINITIALSELECTION ) == WB_NOINITIALSELECTION );
937 0 : SetCursor( pStartEntry, bNotSelect );
938 : }
939 :
940 0 : nFlags &= (~F_DESEL_ALL);
941 0 : pView->SetClipRegion();
942 0 : Rectangle aRect;
943 0 : if( !(nFlags & F_PAINTED) )
944 : {
945 0 : nFlags |= F_PAINTED;
946 0 : RepaintScrollBars();
947 : }
948 0 : nFlags &= (~F_IN_PAINT);
949 : }
950 :
951 0 : void SvImpLBox::MakeVisible( SvTreeListEntry* pEntry, bool bMoveToTop )
952 : {
953 0 : if( !pEntry )
954 0 : return;
955 :
956 0 : bool bInView = IsEntryInView( pEntry );
957 :
958 0 : if( bInView && (!bMoveToTop || pStartEntry == pEntry) )
959 0 : return; // is already visible
960 :
961 0 : if( pStartEntry || (m_nStyle & WB_FORCE_MAKEVISIBLE) )
962 0 : nFlags &= (~F_FILLING);
963 0 : if( !bInView )
964 : {
965 0 : if( !pView->IsEntryVisible(pEntry) ) // Parent(s) collapsed?
966 : {
967 0 : SvTreeListEntry* pParent = pView->GetParent( pEntry );
968 0 : while( pParent )
969 : {
970 0 : if( !pView->IsExpanded( pParent ) )
971 : {
972 : #ifdef DBG_UTIL
973 : bool bRet =
974 : #endif
975 0 : pView->Expand( pParent );
976 : DBG_ASSERT(bRet,"Not expanded!");
977 : }
978 0 : pParent = pView->GetParent( pParent );
979 : }
980 : // do the parent's children fit into the view or do we have to scroll?
981 0 : if( IsEntryInView( pEntry ) && !bMoveToTop )
982 0 : return; // no need to scroll
983 : }
984 : }
985 :
986 0 : pStartEntry = pEntry;
987 0 : ShowCursor( false );
988 0 : FillView();
989 0 : aVerSBar.SetThumbPos( (long)(pView->GetVisiblePos( pStartEntry )) );
990 0 : ShowCursor( true );
991 0 : pView->Invalidate();
992 : }
993 :
994 0 : void SvImpLBox::ScrollToAbsPos( long nPos )
995 : {
996 0 : if( pView->GetVisibleCount() == 0 )
997 0 : return;
998 0 : long nLastEntryPos = pView->GetAbsPos( pView->Last() );
999 :
1000 0 : if( nPos < 0 )
1001 0 : nPos = 0;
1002 0 : else if( nPos > nLastEntryPos )
1003 0 : nPos = nLastEntryPos;
1004 :
1005 0 : SvTreeListEntry* pEntry = (SvTreeListEntry*)pView->GetEntryAtAbsPos( nPos );
1006 0 : if( !pEntry || pEntry == pStartEntry )
1007 0 : return;
1008 :
1009 0 : if( pStartEntry || (m_nStyle & WB_FORCE_MAKEVISIBLE) )
1010 0 : nFlags &= (~F_FILLING);
1011 :
1012 0 : if( pView->IsEntryVisible(pEntry) )
1013 : {
1014 0 : pStartEntry = pEntry;
1015 0 : ShowCursor( false );
1016 0 : aVerSBar.SetThumbPos( nPos );
1017 0 : ShowCursor( true );
1018 0 : if (GetUpdateMode())
1019 0 : pView->Invalidate();
1020 : }
1021 : }
1022 :
1023 0 : void SvImpLBox::DrawNet()
1024 : {
1025 0 : if( pView->GetVisibleCount() < 2 && !pStartEntry->HasChildrenOnDemand() &&
1026 0 : !pStartEntry->HasChildren() )
1027 : return;
1028 :
1029 : // for platforms that don't have nets, DrawNativeControl does nothing and returns true
1030 : // so that SvImpLBox::DrawNet() doesn't draw anything either
1031 0 : if(pView->IsNativeControlSupported( CTRL_LISTNET, PART_ENTIRE_CONTROL)) {
1032 0 : ImplControlValue aControlValue;
1033 0 : Point aTemp(0,0); // temporary needed for g++ 3.3.5
1034 0 : Rectangle aCtrlRegion( aTemp, Size( 0, 0 ) );
1035 0 : ControlState nState = CTRL_STATE_ENABLED;
1036 0 : if( pView->DrawNativeControl( CTRL_LISTNET, PART_ENTIRE_CONTROL,
1037 0 : aCtrlRegion, nState, aControlValue, rtl::OUString() ) )
1038 : {
1039 : return;
1040 0 : }
1041 :
1042 : }
1043 :
1044 0 : long nEntryHeight = pView->GetEntryHeight();
1045 0 : long nEntryHeightDIV2 = nEntryHeight / 2;
1046 0 : if( nEntryHeightDIV2 && !(nEntryHeight & 0x0001))
1047 0 : nEntryHeightDIV2--;
1048 :
1049 : SvTreeListEntry* pChild;
1050 0 : SvTreeListEntry* pEntry = pStartEntry;
1051 :
1052 0 : SvLBoxTab* pFirstDynamicTab = pView->GetFirstDynamicTab();
1053 0 : while( pTree->GetDepth( pEntry ) > 0 )
1054 0 : pEntry = pView->GetParent( pEntry );
1055 0 : sal_uInt16 nOffs = (sal_uInt16)(pView->GetVisiblePos( pStartEntry ) -
1056 0 : pView->GetVisiblePos( pEntry ));
1057 0 : long nY = 0;
1058 0 : nY -= ( nOffs * nEntryHeight );
1059 :
1060 : DBG_ASSERT(pFirstDynamicTab,"No Tree!");
1061 :
1062 0 : Color aOldLineColor = pView->GetLineColor();
1063 0 : const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
1064 0 : Color aCol= rStyleSettings.GetFaceColor();
1065 :
1066 0 : if( aCol.IsRGBEqual( pView->GetBackground().GetColor()) )
1067 0 : aCol = rStyleSettings.GetShadowColor();
1068 0 : pView->SetLineColor( aCol );
1069 0 : Point aPos1, aPos2;
1070 : sal_uInt16 nDistance;
1071 0 : sal_uLong nMax = nVisibleCount + nOffs + 1;
1072 :
1073 0 : const Image& rExpandedNodeBitmap = GetExpandedNodeBmp();
1074 :
1075 0 : for( sal_uLong n=0; n< nMax && pEntry; n++ )
1076 : {
1077 0 : if( pView->IsExpanded(pEntry) )
1078 : {
1079 0 : aPos1.X() = pView->GetTabPos(pEntry, pFirstDynamicTab);
1080 : // if it is not a context bitmap, go a little to the right below the
1081 : // first text (node bitmap, too)
1082 0 : if( !pView->nContextBmpWidthMax )
1083 0 : aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1084 :
1085 0 : aPos1.Y() = nY;
1086 0 : aPos1.Y() += nEntryHeightDIV2;
1087 :
1088 0 : pChild = pView->FirstChild( pEntry );
1089 : DBG_ASSERT(pChild,"Child?");
1090 0 : pChild = pTree->LastSibling( pChild );
1091 0 : nDistance = (sal_uInt16)(pView->GetVisiblePos(pChild) -
1092 0 : pView->GetVisiblePos(pEntry));
1093 0 : aPos2 = aPos1;
1094 0 : aPos2.Y() += nDistance * nEntryHeight;
1095 0 : pView->DrawLine( aPos1, aPos2 );
1096 : }
1097 : // visible in control?
1098 0 : if( n>= nOffs && ((m_nStyle & WB_HASLINESATROOT) || !pTree->IsAtRootDepth(pEntry)))
1099 : {
1100 : // can we recycle aPos1?
1101 0 : if( !pView->IsExpanded(pEntry) )
1102 : {
1103 : // nope
1104 0 : aPos1.X() = pView->GetTabPos(pEntry, pFirstDynamicTab);
1105 : // if it is not a context bitmap, go a little to the right below
1106 : // the first text (node bitmap, too)
1107 0 : if( !pView->nContextBmpWidthMax )
1108 0 : aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1109 0 : aPos1.Y() = nY;
1110 0 : aPos1.Y() += nEntryHeightDIV2;
1111 0 : aPos2.X() = aPos1.X();
1112 : }
1113 0 : aPos2.Y() = aPos1.Y();
1114 0 : aPos2.X() -= pView->GetIndent();
1115 0 : pView->DrawLine( aPos1, aPos2 );
1116 : }
1117 0 : nY += nEntryHeight;
1118 0 : pEntry = pView->NextVisible(pEntry);
1119 : }
1120 0 : if( m_nStyle & WB_HASLINESATROOT )
1121 : {
1122 0 : pEntry = pView->First();
1123 0 : aPos1.X() = pView->GetTabPos( pEntry, pFirstDynamicTab);
1124 : // if it is not a context bitmap, go a little to the right below the
1125 : // first text (node bitmap, too)
1126 0 : if( !pView->nContextBmpWidthMax )
1127 0 : aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1128 0 : aPos1.X() -= pView->GetIndent();
1129 0 : aPos1.Y() = GetEntryLine( pEntry );
1130 0 : aPos1.Y() += nEntryHeightDIV2;
1131 0 : pChild = pTree->LastSibling( pEntry );
1132 0 : aPos2.X() = aPos1.X();
1133 0 : aPos2.Y() = GetEntryLine( pChild );
1134 0 : aPos2.Y() += nEntryHeightDIV2;
1135 0 : pView->DrawLine( aPos1, aPos2 );
1136 : }
1137 0 : pView->SetLineColor( aOldLineColor );
1138 : }
1139 :
1140 0 : void SvImpLBox::PositionScrollBars( Size& rSize, sal_uInt16 nMask )
1141 : {
1142 0 : long nOverlap = 0;
1143 :
1144 0 : Size aVerSize( nVerSBarWidth, rSize.Height() );
1145 0 : Size aHorSize( rSize.Width(), nHorSBarHeight );
1146 :
1147 0 : if( nMask & 0x0001 )
1148 0 : aHorSize.Width() -= nVerSBarWidth;
1149 0 : if( nMask & 0x0002 )
1150 0 : aVerSize.Height() -= nHorSBarHeight;
1151 :
1152 0 : aVerSize.Height() += 2 * nOverlap;
1153 0 : Point aVerPos( rSize.Width() - aVerSize.Width() + nOverlap, -nOverlap );
1154 0 : aVerSBar.SetPosSizePixel( aVerPos, aVerSize );
1155 :
1156 0 : aHorSize.Width() += 2 * nOverlap;
1157 0 : Point aHorPos( -nOverlap, rSize.Height() - aHorSize.Height() + nOverlap );
1158 :
1159 0 : aHorSBar.SetPosSizePixel( aHorPos, aHorSize );
1160 :
1161 0 : if( nMask & 0x0001 )
1162 0 : rSize.Width() = aVerPos.X();
1163 0 : if( nMask & 0x0002 )
1164 0 : rSize.Height() = aHorPos.Y();
1165 :
1166 0 : if( (nMask & (0x0001|0x0002)) == (0x0001|0x0002) )
1167 0 : aScrBarBox.Show();
1168 : else
1169 0 : aScrBarBox.Hide();
1170 0 : }
1171 :
1172 : // nResult: Bit0 == VerSBar Bit1 == HorSBar
1173 0 : sal_uInt16 SvImpLBox::AdjustScrollBars( Size& rSize )
1174 : {
1175 0 : long nEntryHeight = pView->GetEntryHeight();
1176 0 : if( !nEntryHeight )
1177 0 : return 0;
1178 :
1179 0 : sal_uInt16 nResult = 0;
1180 :
1181 0 : Size aOSize( pView->Control::GetOutputSizePixel() );
1182 :
1183 0 : const WinBits nWindowStyle = pView->GetStyle();
1184 0 : bool bVerSBar = ( nWindowStyle & WB_VSCROLL ) != 0;
1185 0 : bool bHorBar = false;
1186 0 : long nMaxRight = aOSize.Width(); //GetOutputSize().Width();
1187 0 : Point aOrigin( pView->GetMapMode().GetOrigin() );
1188 0 : aOrigin.X() *= -1;
1189 0 : nMaxRight += aOrigin.X() - 1;
1190 0 : long nVis = nMostRight - aOrigin.X();
1191 0 : if( (nWindowStyle & WB_HSCROLL) &&
1192 : (nVis < nMostRight || nMaxRight < nMostRight) )
1193 : {
1194 0 : bHorBar = true;
1195 : }
1196 :
1197 : // number of entries that are not collapsed
1198 0 : sal_uLong nTotalCount = pView->GetVisibleCount();
1199 :
1200 : // number of entries visible within the view
1201 0 : nVisibleCount = aOSize.Height() / nEntryHeight;
1202 :
1203 : // do we need a vertical scrollbar?
1204 0 : if( bVerSBar || nTotalCount > nVisibleCount )
1205 : {
1206 0 : nResult = 1;
1207 0 : nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1208 0 : nMaxRight -= nVerSBarWidth;
1209 0 : if( !bHorBar )
1210 : {
1211 0 : if( (nWindowStyle & WB_HSCROLL) &&
1212 : (nVis < nMostRight || nMaxRight < nMostRight) )
1213 0 : bHorBar = true;
1214 : }
1215 : }
1216 :
1217 : // do we need a horizontal scrollbar?
1218 0 : if( bHorBar )
1219 : {
1220 0 : nResult |= 0x0002;
1221 : // the number of entries visible within the view has to be recalculated
1222 : // because the horizontal scrollbar is now visible.
1223 0 : nVisibleCount = (aOSize.Height() - nHorSBarHeight) / nEntryHeight;
1224 : // we might actually need a vertical scrollbar now
1225 0 : if( !(nResult & 0x0001) &&
1226 : ((nTotalCount > nVisibleCount) || bVerSBar) )
1227 : {
1228 0 : nResult = 3;
1229 0 : nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1230 : }
1231 : }
1232 :
1233 0 : PositionScrollBars( aOSize, nResult );
1234 :
1235 : // adapt Range, VisibleRange etc.
1236 :
1237 : // refresh output size, in case we have to scroll
1238 0 : Rectangle aRect;
1239 0 : aRect.SetSize( aOSize );
1240 0 : aSelEng.SetVisibleArea( aRect );
1241 :
1242 : // vertical scrollbar
1243 0 : long nTemp = (long)nVisibleCount;
1244 0 : nTemp--;
1245 0 : if( nTemp != aVerSBar.GetVisibleSize() )
1246 : {
1247 0 : if( !bInVScrollHdl )
1248 : {
1249 0 : aVerSBar.SetPageSize( nTemp - 1 );
1250 0 : aVerSBar.SetVisibleSize( nTemp );
1251 : }
1252 : else
1253 : {
1254 0 : nFlags |= F_ENDSCROLL_SET_VIS_SIZE;
1255 0 : nNextVerVisSize = nTemp;
1256 : }
1257 : }
1258 :
1259 : // horizontal scrollbar
1260 0 : nTemp = aHorSBar.GetThumbPos();
1261 0 : aHorSBar.SetVisibleSize( aOSize.Width() );
1262 0 : long nNewThumbPos = aHorSBar.GetThumbPos();
1263 0 : Range aRange( aHorSBar.GetRange() );
1264 0 : if( aRange.Max() < nMostRight+25 )
1265 : {
1266 0 : aRange.Max() = nMostRight+25;
1267 0 : aHorSBar.SetRange( aRange );
1268 : }
1269 :
1270 0 : if( nTemp != nNewThumbPos )
1271 : {
1272 0 : nTemp = nNewThumbPos - nTemp;
1273 0 : if( pView->IsEditingActive() )
1274 : {
1275 0 : pView->EndEditing( true ); // Cancel
1276 0 : pView->Update();
1277 : }
1278 0 : pView->nFocusWidth = -1;
1279 0 : KeyLeftRight( nTemp );
1280 : }
1281 :
1282 0 : if( nResult & 0x0001 )
1283 0 : aVerSBar.Show();
1284 : else
1285 0 : aVerSBar.Hide();
1286 :
1287 0 : if( nResult & 0x0002 )
1288 0 : aHorSBar.Show();
1289 : else
1290 : {
1291 0 : aHorSBar.Hide();
1292 : }
1293 0 : rSize = aOSize;
1294 0 : return nResult;
1295 : }
1296 :
1297 0 : void SvImpLBox::InitScrollBarBox()
1298 : {
1299 0 : aScrBarBox.SetSizePixel( Size(nVerSBarWidth, nHorSBarHeight) );
1300 0 : Size aSize( pView->Control::GetOutputSizePixel() );
1301 0 : aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth, aSize.Height()-nHorSBarHeight));
1302 0 : }
1303 :
1304 0 : void SvImpLBox::Resize()
1305 : {
1306 0 : Size aSize( pView->Control::GetOutputSizePixel());
1307 0 : if( aSize.Width() <= 0 || aSize.Height() <= 0 )
1308 0 : return;
1309 0 : nFlags |= F_IN_RESIZE;
1310 0 : InitScrollBarBox();
1311 :
1312 0 : if( pView->GetEntryHeight())
1313 : {
1314 0 : AdjustScrollBars( aOutputSize );
1315 0 : FillView();
1316 : }
1317 : // HACK, as in floating and docked windows the scrollbars might not be drawn
1318 : // correctly/not be drawn at all after resizing!
1319 0 : if( aHorSBar.IsVisible())
1320 0 : aHorSBar.Invalidate();
1321 0 : if( aVerSBar.IsVisible())
1322 0 : aVerSBar.Invalidate();
1323 0 : nFlags &= (~(F_IN_RESIZE | F_PAINTED));
1324 : }
1325 :
1326 0 : void SvImpLBox::FillView()
1327 : {
1328 0 : if( !pStartEntry )
1329 : {
1330 0 : sal_uInt16 nVisibleViewCount = (sal_uInt16)(pView->GetVisibleCount());
1331 0 : sal_uInt16 nTempThumb = (sal_uInt16)aVerSBar.GetThumbPos();
1332 0 : if( nTempThumb >= nVisibleViewCount )
1333 0 : nTempThumb = nVisibleViewCount - 1;
1334 0 : pStartEntry = pView->GetEntryAtVisPos(nTempThumb);
1335 : }
1336 0 : if( pStartEntry )
1337 : {
1338 0 : sal_uInt16 nLast = (sal_uInt16)(pView->GetVisiblePos(pView->LastVisible()));
1339 0 : sal_uInt16 nThumb = (sal_uInt16)(pView->GetVisiblePos( pStartEntry ));
1340 0 : sal_uInt16 nCurDispEntries = nLast-nThumb+1;
1341 0 : if( nCurDispEntries < nVisibleCount )
1342 : {
1343 0 : ShowCursor( false );
1344 : // fill window by moving the thumb up incrementally
1345 0 : bool bFound = false;
1346 0 : SvTreeListEntry* pTemp = pStartEntry;
1347 0 : while( nCurDispEntries < nVisibleCount && pTemp )
1348 : {
1349 0 : pTemp = pView->PrevVisible(pStartEntry);
1350 0 : if( pTemp )
1351 : {
1352 0 : nThumb--;
1353 0 : pStartEntry = pTemp;
1354 0 : nCurDispEntries++;
1355 0 : bFound = true;
1356 : }
1357 : }
1358 0 : if( bFound )
1359 : {
1360 0 : aVerSBar.SetThumbPos( nThumb );
1361 0 : ShowCursor( true ); // recalculate focus rectangle
1362 0 : pView->Invalidate();
1363 : }
1364 : }
1365 : }
1366 0 : }
1367 :
1368 :
1369 :
1370 :
1371 0 : void SvImpLBox::ShowVerSBar()
1372 : {
1373 0 : bool bVerBar = ( pView->GetStyle() & WB_VSCROLL ) != 0;
1374 0 : sal_uLong nVis = 0;
1375 0 : if( !bVerBar )
1376 0 : nVis = pView->GetVisibleCount();
1377 0 : if( bVerBar || (nVisibleCount && nVis > (sal_uLong)(nVisibleCount-1)) )
1378 : {
1379 0 : if( !aVerSBar.IsVisible() )
1380 : {
1381 0 : pView->nFocusWidth = -1;
1382 0 : AdjustScrollBars( aOutputSize );
1383 0 : if( GetUpdateMode() )
1384 0 : aVerSBar.Update();
1385 : }
1386 : }
1387 : else
1388 : {
1389 0 : if( aVerSBar.IsVisible() )
1390 : {
1391 0 : pView->nFocusWidth = -1;
1392 0 : AdjustScrollBars( aOutputSize );
1393 : }
1394 : }
1395 :
1396 0 : long nMaxRight = GetOutputSize().Width();
1397 0 : Point aPos( pView->GetMapMode().GetOrigin() );
1398 0 : aPos.X() *= -1; // convert document coordinates
1399 0 : nMaxRight = nMaxRight + aPos.X() - 1;
1400 0 : if( nMaxRight < nMostRight )
1401 : {
1402 0 : if( !aHorSBar.IsVisible() )
1403 : {
1404 0 : pView->nFocusWidth = -1;
1405 0 : AdjustScrollBars( aOutputSize );
1406 0 : if( GetUpdateMode() )
1407 0 : aHorSBar.Update();
1408 : }
1409 : else
1410 : {
1411 0 : Range aRange( aHorSBar.GetRange() );
1412 0 : if( aRange.Max() < nMostRight+25 )
1413 : {
1414 0 : aRange.Max() = nMostRight+25;
1415 0 : aHorSBar.SetRange( aRange );
1416 : }
1417 : else
1418 : {
1419 0 : pView->nFocusWidth = -1;
1420 0 : AdjustScrollBars( aOutputSize );
1421 : }
1422 : }
1423 : }
1424 : else
1425 : {
1426 0 : if( aHorSBar.IsVisible() )
1427 : {
1428 0 : pView->nFocusWidth = -1;
1429 0 : AdjustScrollBars( aOutputSize );
1430 : }
1431 : }
1432 0 : }
1433 :
1434 :
1435 0 : void SvImpLBox::SyncVerThumb()
1436 : {
1437 0 : if( pStartEntry )
1438 : {
1439 0 : long nEntryPos = pView->GetVisiblePos( pStartEntry );
1440 0 : aVerSBar.SetThumbPos( nEntryPos );
1441 : }
1442 : else
1443 0 : aVerSBar.SetThumbPos( 0 );
1444 0 : }
1445 :
1446 0 : bool SvImpLBox::IsEntryInView( SvTreeListEntry* pEntry ) const
1447 : {
1448 : // parent collapsed
1449 0 : if( !pView->IsEntryVisible(pEntry) )
1450 0 : return false;
1451 0 : long nY = GetEntryLine( pEntry );
1452 0 : if( nY < 0 )
1453 0 : return false;
1454 0 : long nMax = nVisibleCount * pView->GetEntryHeight();
1455 0 : if( nY >= nMax )
1456 0 : return false;
1457 0 : return true;
1458 : }
1459 :
1460 :
1461 0 : long SvImpLBox::GetEntryLine( SvTreeListEntry* pEntry ) const
1462 : {
1463 0 : if(!pStartEntry )
1464 0 : return -1; // invisible position
1465 :
1466 0 : long nFirstVisPos = pView->GetVisiblePos( pStartEntry );
1467 0 : long nEntryVisPos = pView->GetVisiblePos( pEntry );
1468 0 : nFirstVisPos = nEntryVisPos - nFirstVisPos;
1469 0 : nFirstVisPos *= pView->GetEntryHeight();
1470 0 : return nFirstVisPos;
1471 : }
1472 :
1473 0 : void SvImpLBox::SetEntryHeight( short /* nHeight */ )
1474 : {
1475 0 : SetNodeBmpYOffset( GetExpandedNodeBmp() );
1476 0 : SetNodeBmpYOffset( GetCollapsedNodeBmp() );
1477 0 : if(!pView->HasViewData()) // are we within the Clear?
1478 : {
1479 0 : Size aSize = pView->Control::GetOutputSizePixel();
1480 0 : AdjustScrollBars( aSize );
1481 : }
1482 : else
1483 : {
1484 0 : Resize();
1485 0 : if( GetUpdateMode() )
1486 0 : pView->Invalidate();
1487 : }
1488 0 : }
1489 :
1490 :
1491 :
1492 : // ***********************************************************************
1493 : // Callback Functions
1494 : // ***********************************************************************
1495 :
1496 0 : void SvImpLBox::EntryExpanded( SvTreeListEntry* pEntry )
1497 : {
1498 : // SelAllDestrAnch( false, true ); //DeselectAll();
1499 0 : if( GetUpdateMode() )
1500 : {
1501 0 : ShowCursor( false );
1502 0 : long nY = GetEntryLine( pEntry );
1503 0 : if( IsLineVisible(nY) )
1504 : {
1505 0 : InvalidateEntriesFrom( nY );
1506 0 : FindMostRight( pEntry, 0 );
1507 : }
1508 0 : aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
1509 : // if we expanded before the thumb, the thumb's position has to be
1510 : // corrected
1511 0 : SyncVerThumb();
1512 0 : ShowVerSBar();
1513 0 : ShowCursor( true );
1514 : }
1515 0 : }
1516 :
1517 0 : void SvImpLBox::EntryCollapsed( SvTreeListEntry* pEntry )
1518 : {
1519 0 : if( !pView->IsEntryVisible( pEntry ) )
1520 0 : return;
1521 :
1522 0 : ShowCursor( false );
1523 :
1524 0 : if( !pMostRightEntry || pTree->IsChild( pEntry,pMostRightEntry ) )
1525 : {
1526 0 : FindMostRight(0);
1527 : }
1528 :
1529 0 : if( pStartEntry )
1530 : {
1531 0 : long nOldThumbPos = aVerSBar.GetThumbPos();
1532 0 : sal_uLong nVisList = pView->GetVisibleCount();
1533 0 : aVerSBar.SetRange( Range(0, nVisList-1) );
1534 0 : long nNewThumbPos = aVerSBar.GetThumbPos();
1535 0 : if( nNewThumbPos != nOldThumbPos )
1536 : {
1537 0 : pStartEntry = pView->First();
1538 0 : sal_uInt16 nDistance = (sal_uInt16)nNewThumbPos;
1539 0 : if( nDistance )
1540 0 : pStartEntry = pView->NextVisible(pStartEntry, nDistance);
1541 0 : if( GetUpdateMode() )
1542 0 : pView->Invalidate();
1543 : }
1544 : else
1545 0 : SyncVerThumb();
1546 0 : ShowVerSBar();
1547 : }
1548 : // has the cursor been collapsed?
1549 0 : if( pTree->IsChild( pEntry, pCursor ) )
1550 0 : SetCursor( pEntry );
1551 0 : if( GetUpdateMode() )
1552 0 : ShowVerSBar();
1553 0 : ShowCursor( true );
1554 0 : if( GetUpdateMode() && pCursor )
1555 0 : pView->Select( pCursor, true );
1556 : }
1557 :
1558 0 : void SvImpLBox::CollapsingEntry( SvTreeListEntry* pEntry )
1559 : {
1560 0 : if( !pView->IsEntryVisible( pEntry ) || !pStartEntry )
1561 0 : return;
1562 :
1563 0 : SelAllDestrAnch( false, true ); // deselect all
1564 :
1565 : // is the collapsed cursor visible?
1566 0 : long nY = GetEntryLine( pEntry );
1567 0 : if( IsLineVisible(nY) )
1568 : {
1569 0 : if( GetUpdateMode() )
1570 0 : InvalidateEntriesFrom( nY );
1571 : }
1572 : else
1573 : {
1574 0 : if( pTree->IsChild(pEntry, pStartEntry) )
1575 : {
1576 0 : pStartEntry = pEntry;
1577 0 : if( GetUpdateMode() )
1578 0 : pView->Invalidate();
1579 : }
1580 : }
1581 : }
1582 :
1583 :
1584 0 : void SvImpLBox::SetNodeBmpYOffset( const Image& rBmp )
1585 : {
1586 0 : Size aSize;
1587 0 : nYoffsNodeBmp = pView->GetHeightOffset( rBmp, aSize );
1588 0 : nNodeBmpWidth = aSize.Width();
1589 0 : }
1590 :
1591 0 : void SvImpLBox::SetNodeBmpTabDistance()
1592 : {
1593 0 : nNodeBmpTabDistance = -pView->GetIndent();
1594 0 : if( pView->nContextBmpWidthMax )
1595 : {
1596 : // only if the first dynamic tab is centered (we currently assume that)
1597 0 : Size aSize = GetExpandedNodeBmp().GetSizePixel();
1598 0 : nNodeBmpTabDistance -= aSize.Width() / 2;
1599 : }
1600 0 : }
1601 :
1602 : //
1603 : // corrects the cursor when using SingleSelection
1604 : //
1605 0 : void SvImpLBox::EntrySelected( SvTreeListEntry* pEntry, bool bSelect )
1606 : {
1607 0 : if( nFlags & F_IGNORE_SELECT )
1608 0 : return;
1609 :
1610 0 : nFlags &= (~F_DESEL_ALL);
1611 0 : if( bSelect &&
1612 0 : aSelEng.GetSelectionMode() == SINGLE_SELECTION &&
1613 : pEntry != pCursor )
1614 : {
1615 0 : SetCursor( pEntry );
1616 : DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?");
1617 : }
1618 :
1619 0 : if( GetUpdateMode() && pView->IsEntryVisible(pEntry) )
1620 : {
1621 0 : long nY = GetEntryLine( pEntry );
1622 0 : if( IsLineVisible( nY ) )
1623 : {
1624 0 : ShowCursor( false );
1625 0 : pView->PaintEntry1( pEntry, nY, 0xffff ); // because of ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
1626 0 : ShowCursor( true );
1627 : }
1628 : }
1629 : }
1630 :
1631 :
1632 0 : void SvImpLBox::RemovingEntry( SvTreeListEntry* pEntry )
1633 : {
1634 0 : DestroyAnchor();
1635 :
1636 0 : if( !pView->IsEntryVisible( pEntry ) )
1637 : {
1638 : // if parent is collapsed => bye!
1639 0 : nFlags |= F_REMOVED_ENTRY_INVISIBLE;
1640 0 : return;
1641 : }
1642 :
1643 0 : if( pEntry == pMostRightEntry || (
1644 0 : pEntry->HasChildren() && pView->IsExpanded(pEntry) &&
1645 0 : pTree->IsChild(pEntry, pMostRightEntry)))
1646 : {
1647 0 : nFlags |= F_REMOVED_RECALC_MOST_RIGHT;
1648 : }
1649 :
1650 0 : SvTreeListEntry* pOldStartEntry = pStartEntry;
1651 :
1652 0 : SvTreeListEntry* pParent = pView->GetModel()->GetParent(pEntry);
1653 :
1654 0 : if (pParent && pView->GetModel()->GetChildList(pParent).size() == 1)
1655 : {
1656 : DBG_ASSERT( pView->IsExpanded( pParent ), "Parent not expanded");
1657 0 : pParent->SetFlags( pParent->GetFlags() | SV_ENTRYFLAG_NO_NODEBMP);
1658 0 : InvalidateEntry( pParent );
1659 : }
1660 :
1661 0 : if( pCursor && pTree->IsChild( pEntry, pCursor) )
1662 0 : pCursor = pEntry;
1663 0 : if( pStartEntry && pTree->IsChild(pEntry,pStartEntry) )
1664 0 : pStartEntry = pEntry;
1665 :
1666 : SvTreeListEntry* pTemp;
1667 0 : if( pCursor && pCursor == pEntry )
1668 : {
1669 0 : if( bSimpleTravel )
1670 0 : pView->Select( pCursor, false );
1671 0 : ShowCursor( false ); // focus rectangle gone
1672 : // NextSibling, because we also delete the children of the cursor
1673 0 : pTemp = pView->NextSibling( pCursor );
1674 0 : if( !pTemp )
1675 0 : pTemp = pView->PrevVisible(pCursor);
1676 :
1677 0 : SetCursor( pTemp, true );
1678 : }
1679 0 : if( pStartEntry && pStartEntry == pEntry )
1680 : {
1681 0 : pTemp = pView->NextSibling( pStartEntry );
1682 0 : if( !pTemp )
1683 0 : pTemp = pView->PrevVisible(pStartEntry);
1684 0 : pStartEntry = pTemp;
1685 : }
1686 0 : if( GetUpdateMode())
1687 : {
1688 : // if it is the last one, we have to invalidate it, so the lines are
1689 : // drawn correctly (in this case they're deleted)
1690 0 : if( pStartEntry && (pStartEntry != pOldStartEntry || pEntry == (SvTreeListEntry*)pView->GetModel()->Last()) )
1691 : {
1692 0 : aVerSBar.SetThumbPos( pView->GetVisiblePos( pStartEntry ));
1693 0 : pView->Invalidate( GetVisibleArea() );
1694 : }
1695 : else
1696 0 : InvalidateEntriesFrom( GetEntryLine( pEntry ) );
1697 : }
1698 : }
1699 :
1700 0 : void SvImpLBox::EntryRemoved()
1701 : {
1702 0 : if( nFlags & F_REMOVED_ENTRY_INVISIBLE )
1703 : {
1704 0 : nFlags &= (~F_REMOVED_ENTRY_INVISIBLE);
1705 0 : return;
1706 : }
1707 0 : if( !pStartEntry )
1708 0 : pStartEntry = pTree->First();
1709 0 : if( !pCursor )
1710 0 : SetCursor( pStartEntry, true );
1711 :
1712 0 : if( pCursor && (bSimpleTravel || !pView->GetSelectionCount() ))
1713 0 : pView->Select( pCursor, true );
1714 :
1715 0 : if( GetUpdateMode())
1716 : {
1717 0 : if( nFlags & F_REMOVED_RECALC_MOST_RIGHT )
1718 0 : FindMostRight(0);
1719 0 : aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
1720 0 : FillView();
1721 0 : if( pStartEntry )
1722 : // if something above the thumb was deleted
1723 0 : aVerSBar.SetThumbPos( pView->GetVisiblePos( pStartEntry) );
1724 :
1725 0 : ShowVerSBar();
1726 0 : if( pCursor && pView->HasFocus() && !pView->IsSelected(pCursor) )
1727 : {
1728 0 : if( pView->GetSelectionCount() )
1729 : {
1730 : // is a neighboring entry selected?
1731 0 : SvTreeListEntry* pNextCursor = (SvTreeListEntry*)pView->PrevVisible( pCursor );
1732 0 : if( !pNextCursor || !pView->IsSelected( pNextCursor ))
1733 0 : pNextCursor = (SvTreeListEntry*)pView->NextVisible( pCursor );
1734 0 : if( !pNextCursor || !pView->IsSelected( pNextCursor ))
1735 : // no neighbor selected: use first selected
1736 0 : pNextCursor = pView->FirstSelected();
1737 0 : SetCursor( pNextCursor );
1738 0 : MakeVisible( pCursor );
1739 : }
1740 : else
1741 0 : pView->Select( pCursor, true );
1742 : }
1743 0 : ShowCursor( true );
1744 : }
1745 0 : nFlags &= (~F_REMOVED_RECALC_MOST_RIGHT);
1746 : }
1747 :
1748 :
1749 0 : void SvImpLBox::MovingEntry( SvTreeListEntry* pEntry )
1750 : {
1751 0 : int bDeselAll = nFlags & F_DESEL_ALL;
1752 0 : SelAllDestrAnch( false, true ); // DeselectAll();
1753 0 : if( !bDeselAll )
1754 0 : nFlags &= (~F_DESEL_ALL);
1755 :
1756 0 : if( pEntry == pCursor )
1757 0 : ShowCursor( false );
1758 0 : if( IsEntryInView( pEntry ) )
1759 0 : pView->Invalidate();
1760 0 : if( pEntry == pStartEntry )
1761 : {
1762 0 : SvTreeListEntry* pNew = 0;
1763 0 : if( !pEntry->HasChildren() )
1764 : {
1765 0 : pNew = pView->NextVisible(pStartEntry);
1766 0 : if( !pNew )
1767 0 : pNew = pView->PrevVisible(pStartEntry);
1768 : }
1769 : else
1770 : {
1771 0 : pNew = pTree->NextSibling( pEntry );
1772 0 : if( !pNew )
1773 0 : pNew = pTree->PrevSibling( pEntry );
1774 : }
1775 0 : pStartEntry = pNew;
1776 : }
1777 0 : }
1778 :
1779 0 : void SvImpLBox::EntryMoved( SvTreeListEntry* pEntry )
1780 : {
1781 0 : UpdateContextBmpWidthVectorFromMovedEntry( pEntry );
1782 :
1783 0 : if ( !pStartEntry )
1784 : // this might happen if the only entry in the view is moved to its very same position
1785 : // #i97346#
1786 0 : pStartEntry = pView->First();
1787 :
1788 0 : aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1));
1789 0 : sal_uInt16 nFirstPos = (sal_uInt16)pTree->GetAbsPos( pStartEntry );
1790 0 : sal_uInt16 nNewPos = (sal_uInt16)pTree->GetAbsPos( pEntry );
1791 0 : FindMostRight(0);
1792 0 : if( nNewPos < nFirstPos ) // HACK!
1793 0 : pStartEntry = pEntry;
1794 0 : SyncVerThumb();
1795 0 : if( pEntry == pCursor )
1796 : {
1797 0 : if( pView->IsEntryVisible( pCursor ) )
1798 0 : ShowCursor( true );
1799 : else
1800 : {
1801 0 : SvTreeListEntry* pParent = pEntry;
1802 0 : do {
1803 0 : pParent = pTree->GetParent( pParent );
1804 : }
1805 0 : while( !pView->IsEntryVisible( pParent ) );
1806 0 : SetCursor( pParent );
1807 : }
1808 : }
1809 0 : if( IsEntryInView( pEntry ) )
1810 0 : pView->Invalidate();
1811 0 : }
1812 :
1813 :
1814 :
1815 0 : void SvImpLBox::EntryInserted( SvTreeListEntry* pEntry )
1816 : {
1817 0 : if( GetUpdateMode() )
1818 : {
1819 0 : SvTreeListEntry* pParent = (SvTreeListEntry*)pTree->GetParent(pEntry);
1820 0 : if (pParent && pTree->GetChildList(pParent).size() == 1)
1821 : // draw plus sign
1822 0 : pTree->InvalidateEntry( pParent );
1823 :
1824 0 : if( !pView->IsEntryVisible( pEntry ) )
1825 0 : return;
1826 0 : int bDeselAll = nFlags & F_DESEL_ALL;
1827 0 : if( bDeselAll )
1828 0 : SelAllDestrAnch( false, true );
1829 : else
1830 0 : DestroyAnchor();
1831 : // nFlags &= (~F_DESEL_ALL);
1832 : // ShowCursor( false ); // if cursor is moved lower
1833 0 : long nY = GetEntryLine( pEntry );
1834 0 : bool bEntryVisible = IsLineVisible( nY );
1835 0 : if( bEntryVisible )
1836 : {
1837 0 : ShowCursor( false ); // if cursor is moved lower
1838 0 : nY -= pView->GetEntryHeight(); // because of lines
1839 0 : InvalidateEntriesFrom( nY );
1840 : }
1841 0 : else if( pStartEntry && nY < GetEntryLine(pStartEntry) )
1842 : {
1843 : // Check if the view is filled completely. If not, then adjust
1844 : // pStartEntry and the Cursor (automatic scrolling).
1845 0 : sal_uInt16 nLast = (sal_uInt16)(pView->GetVisiblePos(pView->LastVisible()));
1846 0 : sal_uInt16 nThumb = (sal_uInt16)(pView->GetVisiblePos( pStartEntry ));
1847 0 : sal_uInt16 nCurDispEntries = nLast-nThumb+1;
1848 0 : if( nCurDispEntries < nVisibleCount )
1849 : {
1850 : // set at the next paint event
1851 0 : pStartEntry = 0;
1852 0 : SetCursor( 0 );
1853 0 : pView->Invalidate();
1854 : }
1855 : }
1856 0 : else if( !pStartEntry )
1857 0 : pView->Invalidate();
1858 :
1859 0 : SetMostRight( pEntry );
1860 0 : aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1));
1861 0 : SyncVerThumb(); // if something was inserted before the thumb
1862 0 : ShowVerSBar();
1863 0 : ShowCursor( true );
1864 0 : if( pStartEntry != pView->First() && (nFlags & F_FILLING) )
1865 0 : pView->Update();
1866 : }
1867 : }
1868 :
1869 :
1870 :
1871 : // ********************************************************************
1872 : // Event handler
1873 : // ********************************************************************
1874 :
1875 :
1876 : // ****** Control the control animation
1877 :
1878 0 : bool SvImpLBox::ButtonDownCheckCtrl(
1879 : const MouseEvent& rMEvt, SvTreeListEntry* pEntry, long nY)
1880 : {
1881 0 : SvLBoxItem* pItem = pView->GetItem(pEntry,rMEvt.GetPosPixel().X(),&pActiveTab);
1882 0 : if (pItem && pItem->GetType() == SV_ITEM_ID_LBOXBUTTON)
1883 : {
1884 0 : pActiveButton = (SvLBoxButton*)pItem;
1885 0 : pActiveEntry = pEntry;
1886 0 : if( pCursor == pActiveEntry )
1887 0 : pView->HideFocus();
1888 0 : pView->CaptureMouse();
1889 0 : pActiveButton->SetStateHilighted( true );
1890 : pView->PaintEntry1( pActiveEntry, nY,
1891 : SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
1892 0 : SV_LBOXTAB_ADJUST_RIGHT );
1893 0 : return true;
1894 : }
1895 : else
1896 0 : pActiveButton = 0;
1897 0 : return false;
1898 : }
1899 :
1900 0 : bool SvImpLBox::MouseMoveCheckCtrl(const MouseEvent& rMEvt, SvTreeListEntry* pEntry)
1901 : {
1902 0 : if( pActiveButton )
1903 : {
1904 : long nY;
1905 0 : long nMouseX = rMEvt.GetPosPixel().X();
1906 0 : if( pEntry == pActiveEntry &&
1907 0 : pView->GetItem(pActiveEntry, nMouseX) == pActiveButton )
1908 : {
1909 0 : if( !pActiveButton->IsStateHilighted() )
1910 : {
1911 0 : pActiveButton->SetStateHilighted(true );
1912 0 : nY = GetEntryLine( pActiveEntry );
1913 : pView->PaintEntry1( pActiveEntry, nY,
1914 : SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
1915 0 : SV_LBOXTAB_ADJUST_RIGHT );
1916 : }
1917 : }
1918 : else
1919 : {
1920 0 : if( pActiveButton->IsStateHilighted() )
1921 : {
1922 0 : pActiveButton->SetStateHilighted(false );
1923 0 : nY = GetEntryLine( pActiveEntry );
1924 0 : pView->PaintEntry1( pActiveEntry, nY, SV_LBOXTAB_PUSHABLE );
1925 : }
1926 : }
1927 0 : return true;
1928 : }
1929 0 : return false;
1930 : }
1931 :
1932 0 : bool SvImpLBox::ButtonUpCheckCtrl( const MouseEvent& rMEvt )
1933 : {
1934 0 : if( pActiveButton )
1935 : {
1936 0 : pView->ReleaseMouse();
1937 0 : SvTreeListEntry* pEntry = GetClickedEntry( rMEvt.GetPosPixel() );
1938 0 : long nY = GetEntryLine( pActiveEntry );
1939 0 : pActiveButton->SetStateHilighted( false );
1940 0 : long nMouseX = rMEvt.GetPosPixel().X();
1941 0 : if( pEntry == pActiveEntry &&
1942 0 : pView->GetItem( pActiveEntry, nMouseX ) == pActiveButton )
1943 0 : pActiveButton->ClickHdl( pView, pActiveEntry );
1944 : pView->PaintEntry1( pActiveEntry, nY,
1945 : SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
1946 0 : SV_LBOXTAB_ADJUST_RIGHT );
1947 0 : if( pCursor == pActiveEntry )
1948 0 : ShowCursor( true );
1949 0 : pActiveButton = 0;
1950 0 : pActiveEntry = 0;
1951 0 : pActiveTab = 0;
1952 0 : return true;
1953 : }
1954 0 : return false;
1955 : }
1956 :
1957 : // ******* Control plus/minus button for expanding/collapsing
1958 :
1959 : // false == no expand/collapse button hit
1960 0 : bool SvImpLBox::IsNodeButton( const Point& rPosPixel, SvTreeListEntry* pEntry ) const
1961 : {
1962 0 : if( !pEntry->HasChildren() && !pEntry->HasChildrenOnDemand() )
1963 0 : return false;
1964 :
1965 0 : SvLBoxTab* pFirstDynamicTab = pView->GetFirstDynamicTab();
1966 0 : if( !pFirstDynamicTab )
1967 0 : return false;
1968 :
1969 0 : long nMouseX = rPosPixel.X();
1970 : // convert to document coordinates
1971 0 : Point aOrigin( pView->GetMapMode().GetOrigin() );
1972 0 : nMouseX -= aOrigin.X();
1973 :
1974 0 : long nX = pView->GetTabPos( pEntry, pFirstDynamicTab);
1975 0 : nX += nNodeBmpTabDistance;
1976 0 : if( nMouseX < nX )
1977 0 : return false;
1978 0 : nX += nNodeBmpWidth;
1979 0 : if( nMouseX > nX )
1980 0 : return false;
1981 0 : return true;
1982 : }
1983 :
1984 : // false == hit no node button
1985 0 : bool SvImpLBox::ButtonDownCheckExpand( const MouseEvent& rMEvt, SvTreeListEntry* pEntry, long /* nY */ )
1986 : {
1987 0 : bool bRet = false;
1988 :
1989 0 : if ( pView->IsEditingActive() && pEntry == pView->pEdEntry )
1990 : // inplace editing -> nothing to do
1991 0 : bRet = true;
1992 0 : else if ( IsNodeButton( rMEvt.GetPosPixel(), pEntry ) )
1993 : {
1994 0 : if ( pView->IsExpanded( pEntry ) )
1995 : {
1996 0 : pView->EndEditing( true );
1997 0 : pView->Collapse( pEntry );
1998 : }
1999 : else
2000 : {
2001 : // you can expand an entry, which is in editing
2002 0 : pView->Expand( pEntry );
2003 : }
2004 0 : bRet = true;
2005 : }
2006 :
2007 0 : return bRet;
2008 : }
2009 :
2010 0 : void SvImpLBox::MouseButtonDown( const MouseEvent& rMEvt )
2011 : {
2012 0 : if ( !rMEvt.IsLeft() && !rMEvt.IsRight())
2013 : return;
2014 :
2015 0 : aEditTimer.Stop();
2016 0 : Point aPos( rMEvt.GetPosPixel());
2017 :
2018 0 : if( aPos.X() > aOutputSize.Width() || aPos.Y() > aOutputSize.Height() )
2019 : return;
2020 :
2021 0 : SvTreeListEntry* pEntry = GetEntry( aPos );
2022 0 : if ( pEntry != pCursor )
2023 : // new entry selected -> reset current tab position to first tab
2024 0 : nCurTabPos = FIRST_ENTRY_TAB;
2025 0 : nFlags &= (~F_FILLING);
2026 0 : pView->GrabFocus();
2027 : // the entry can still be invalid!
2028 0 : if( !pEntry || !pView->GetViewData( pEntry ))
2029 : return;
2030 :
2031 0 : long nY = GetEntryLine( pEntry );
2032 : // Node-Button?
2033 0 : if( ButtonDownCheckExpand( rMEvt, pEntry, nY ) )
2034 : return;
2035 :
2036 0 : if( !EntryReallyHit(pEntry,aPos,nY))
2037 : return;
2038 :
2039 0 : SvLBoxItem* pXItem = pView->GetItem( pEntry, aPos.X() );
2040 0 : if( pXItem )
2041 : {
2042 0 : SvLBoxTab* pXTab = pView->GetTab( pEntry, pXItem );
2043 0 : if ( !rMEvt.IsMod1() && !rMEvt.IsMod2() && rMEvt.IsLeft() && pXTab->IsEditable()
2044 0 : && pEntry == pView->FirstSelected() && NULL == pView->NextSelected( pEntry ) )
2045 : // #i8234# FirstSelected() and NextSelected() ensures, that inplace editing is only triggered, when only one entry is selected
2046 0 : nFlags |= F_START_EDITTIMER;
2047 0 : if ( !pView->IsSelected( pEntry ) )
2048 0 : nFlags &= ~F_START_EDITTIMER;
2049 : }
2050 :
2051 :
2052 0 : if( (rMEvt.GetClicks() % 2) == 0 )
2053 : {
2054 0 : nFlags &= (~F_START_EDITTIMER);
2055 0 : pView->pHdlEntry = pEntry;
2056 0 : if( pView->DoubleClickHdl() )
2057 : {
2058 : // if the entry was deleted within the handler
2059 0 : pEntry = GetClickedEntry( aPos );
2060 0 : if( !pEntry )
2061 : return;
2062 0 : if( pEntry != pView->pHdlEntry )
2063 : {
2064 : // select anew & bye
2065 0 : if( !bSimpleTravel && !aSelEng.IsAlwaysAdding())
2066 0 : SelAllDestrAnch( false, true ); // DeselectAll();
2067 0 : SetCursor( pEntry );
2068 :
2069 : return;
2070 : }
2071 0 : if( pEntry->HasChildren() || pEntry->HasChildrenOnDemand() )
2072 : {
2073 0 : if( pView->IsExpanded(pEntry) )
2074 0 : pView->Collapse( pEntry );
2075 : else
2076 0 : pView->Expand( pEntry );
2077 0 : if( pEntry == pCursor ) // only if Entryitem was clicked
2078 : // (Nodebutton is not an Entryitem!)
2079 0 : pView->Select( pCursor, true );
2080 : return;
2081 : }
2082 : }
2083 : }
2084 : else
2085 : {
2086 : // CheckButton? (TreeListBox: Check + Info)
2087 0 : if( ButtonDownCheckCtrl(rMEvt, pEntry, nY) == true)
2088 : return;
2089 : // Inplace-Editing?
2090 : }
2091 0 : if ( aSelEng.GetSelectionMode() != NO_SELECTION )
2092 0 : aSelEng.SelMouseButtonDown( rMEvt );
2093 : }
2094 :
2095 0 : void SvImpLBox::MouseButtonUp( const MouseEvent& rMEvt)
2096 : {
2097 0 : if ( !ButtonUpCheckCtrl( rMEvt ) && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
2098 0 : aSelEng.SelMouseButtonUp( rMEvt );
2099 0 : EndScroll();
2100 0 : if( nFlags & F_START_EDITTIMER )
2101 : {
2102 0 : nFlags &= (~F_START_EDITTIMER);
2103 0 : aEditClickPos = rMEvt.GetPosPixel();
2104 0 : aEditTimer.Start();
2105 : }
2106 :
2107 0 : return;
2108 : }
2109 :
2110 0 : void SvImpLBox::MouseMove( const MouseEvent& rMEvt)
2111 : {
2112 0 : SvTreeListEntry* pEntry = GetClickedEntry( rMEvt.GetPosPixel() );
2113 0 : if ( !MouseMoveCheckCtrl( rMEvt, pEntry ) && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
2114 0 : aSelEng.SelMouseMove( rMEvt );
2115 0 : return;
2116 : }
2117 :
2118 0 : bool SvImpLBox::KeyInput( const KeyEvent& rKEvt)
2119 : {
2120 0 : aEditTimer.Stop();
2121 0 : const KeyCode& rKeyCode = rKEvt.GetKeyCode();
2122 :
2123 0 : if( rKeyCode.IsMod2() )
2124 0 : return false; // don't evaluate Alt key
2125 :
2126 0 : nFlags &= (~F_FILLING);
2127 :
2128 0 : if( !pCursor )
2129 0 : pCursor = pStartEntry;
2130 0 : if( !pCursor )
2131 0 : return false;
2132 :
2133 0 : bool bKeyUsed = true;
2134 :
2135 0 : sal_uInt16 nDelta = (sal_uInt16)aVerSBar.GetPageSize();
2136 0 : sal_uInt16 aCode = rKeyCode.GetCode();
2137 :
2138 0 : bool bShift = rKeyCode.IsShift();
2139 0 : bool bMod1 = rKeyCode.IsMod1();
2140 :
2141 : SvTreeListEntry* pNewCursor;
2142 :
2143 0 : const WinBits nWindowStyle = pView->GetStyle();
2144 0 : switch( aCode )
2145 : {
2146 : case KEY_UP:
2147 0 : if( !IsEntryInView( pCursor ) )
2148 0 : MakeVisible( pCursor );
2149 :
2150 0 : pNewCursor = pCursor;
2151 0 : do
2152 : {
2153 0 : pNewCursor = pView->PrevVisible(pNewCursor);
2154 0 : } while( pNewCursor && !IsSelectable(pNewCursor) );
2155 :
2156 0 : if ( pNewCursor )
2157 : // new entry selected -> reset current tab position to first tab
2158 0 : nCurTabPos = FIRST_ENTRY_TAB;
2159 : // if there is no next entry, take the current one
2160 : // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
2161 : // the cursor key
2162 0 : if ( !pNewCursor && pCursor )
2163 0 : pNewCursor = pCursor;
2164 :
2165 0 : if( pNewCursor )
2166 : {
2167 0 : aSelEng.CursorPosChanging( bShift, bMod1 );
2168 0 : SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2169 0 : if( !IsEntryInView( pNewCursor ) )
2170 0 : KeyUp( false );
2171 : }
2172 0 : break;
2173 :
2174 : case KEY_DOWN:
2175 0 : if( !IsEntryInView( pCursor ) )
2176 0 : MakeVisible( pCursor );
2177 :
2178 0 : pNewCursor = pCursor;
2179 0 : do
2180 : {
2181 0 : pNewCursor = pView->NextVisible(pNewCursor);
2182 0 : } while( pNewCursor && !IsSelectable(pNewCursor) );
2183 :
2184 0 : if ( pNewCursor )
2185 : // new entry selected -> reset current tab position to first tab
2186 0 : nCurTabPos = FIRST_ENTRY_TAB;
2187 :
2188 : // if there is no next entry, take the current one
2189 : // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
2190 : // the cursor key
2191 : // 06.09.20001 - 83416 - frank.schoenheit@sun.com
2192 0 : if ( !pNewCursor && pCursor )
2193 0 : pNewCursor = pCursor;
2194 :
2195 0 : if( pNewCursor )
2196 : {
2197 0 : aSelEng.CursorPosChanging( bShift, bMod1 );
2198 0 : if( IsEntryInView( pNewCursor ) )
2199 0 : SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2200 : else
2201 : {
2202 0 : if( pCursor )
2203 0 : pView->Select( pCursor, false );
2204 0 : KeyDown( false );
2205 0 : SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2206 : }
2207 : }
2208 : else
2209 0 : KeyDown( false ); // because scrollbar range might still
2210 : // allow scrolling
2211 0 : break;
2212 :
2213 : case KEY_RIGHT:
2214 : {
2215 0 : if( bSubLstOpLR && IsNowExpandable() )
2216 0 : pView->Expand( pCursor );
2217 0 : else if ( bIsCellFocusEnabled && pCursor )
2218 : {
2219 0 : if ( nCurTabPos < ( pView->TabCount() - 1 /*!2*/ ) )
2220 : {
2221 0 : ++nCurTabPos;
2222 0 : ShowCursor( true );
2223 0 : CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
2224 : }
2225 : }
2226 0 : else if( nWindowStyle & WB_HSCROLL )
2227 : {
2228 0 : long nThumb = aHorSBar.GetThumbPos();
2229 0 : nThumb += aHorSBar.GetLineSize();
2230 0 : long nOldThumb = aHorSBar.GetThumbPos();
2231 0 : aHorSBar.SetThumbPos( nThumb );
2232 0 : nThumb = nOldThumb;
2233 0 : nThumb -= aHorSBar.GetThumbPos();
2234 0 : nThumb *= -1;
2235 0 : if( nThumb )
2236 : {
2237 0 : KeyLeftRight( nThumb );
2238 0 : EndScroll();
2239 : }
2240 : }
2241 : else
2242 0 : bKeyUsed = false;
2243 0 : break;
2244 : }
2245 :
2246 : case KEY_LEFT:
2247 : {
2248 0 : if ( bIsCellFocusEnabled )
2249 : {
2250 0 : if ( nCurTabPos > FIRST_ENTRY_TAB )
2251 : {
2252 0 : --nCurTabPos;
2253 0 : ShowCursor( true );
2254 0 : CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
2255 : }
2256 : }
2257 0 : else if ( nWindowStyle & WB_HSCROLL )
2258 : {
2259 0 : long nThumb = aHorSBar.GetThumbPos();
2260 0 : nThumb -= aHorSBar.GetLineSize();
2261 0 : long nOldThumb = aHorSBar.GetThumbPos();
2262 0 : aHorSBar.SetThumbPos( nThumb );
2263 0 : nThumb = nOldThumb;
2264 0 : nThumb -= aHorSBar.GetThumbPos();
2265 0 : if( nThumb )
2266 : {
2267 0 : KeyLeftRight( -nThumb );
2268 0 : EndScroll();
2269 : }
2270 0 : else if( bSubLstOpLR )
2271 : {
2272 0 : if( IsExpandable() && pView->IsExpanded( pCursor ) )
2273 0 : pView->Collapse( pCursor );
2274 : else
2275 : {
2276 0 : pNewCursor = pView->GetParent( pCursor );
2277 0 : if( pNewCursor )
2278 0 : SetCursor( pNewCursor );
2279 : }
2280 : }
2281 : }
2282 0 : else if( bSubLstOpLR && IsExpandable() )
2283 0 : pView->Collapse( pCursor );
2284 : else
2285 0 : bKeyUsed = false;
2286 0 : break;
2287 : }
2288 :
2289 : case KEY_PAGEUP:
2290 0 : if( !bMod1 )
2291 : {
2292 0 : pNewCursor = pView->PrevVisible(pCursor, nDelta);
2293 :
2294 0 : while( nDelta && pNewCursor && !IsSelectable(pNewCursor) )
2295 : {
2296 0 : pNewCursor = pView->NextVisible(pNewCursor);
2297 0 : nDelta--;
2298 : }
2299 :
2300 0 : if( nDelta )
2301 : {
2302 : DBG_ASSERT(pNewCursor&&(sal_uLong)pNewCursor!=(sal_uLong)pCursor,"Cursor?");
2303 0 : aSelEng.CursorPosChanging( bShift, bMod1 );
2304 0 : if( IsEntryInView( pNewCursor ) )
2305 0 : SetCursor( pNewCursor );
2306 : else
2307 : {
2308 0 : SetCursor( pNewCursor );
2309 0 : KeyUp( true );
2310 : }
2311 : }
2312 : }
2313 : else
2314 0 : bKeyUsed = false;
2315 0 : break;
2316 :
2317 : case KEY_PAGEDOWN:
2318 0 : if( !bMod1 )
2319 : {
2320 0 : pNewCursor= pView->NextVisible(pCursor, nDelta);
2321 :
2322 0 : while( nDelta && pNewCursor && !IsSelectable(pNewCursor) )
2323 : {
2324 0 : pNewCursor = pView->PrevVisible(pNewCursor);
2325 0 : nDelta--;
2326 : }
2327 :
2328 0 : if( nDelta )
2329 : {
2330 : DBG_ASSERT(pNewCursor&&(sal_uLong)pNewCursor!=(sal_uLong)pCursor,"Cursor?");
2331 0 : aSelEng.CursorPosChanging( bShift, bMod1 );
2332 0 : if( IsEntryInView( pNewCursor ) )
2333 0 : SetCursor( pNewCursor );
2334 : else
2335 : {
2336 0 : SetCursor( pNewCursor );
2337 0 : KeyDown( true );
2338 : }
2339 : }
2340 : else
2341 0 : KeyDown( false ); // see also: KEY_DOWN
2342 : }
2343 : else
2344 0 : bKeyUsed = false;
2345 0 : break;
2346 :
2347 : case KEY_SPACE:
2348 0 : if ( pView->GetSelectionMode() != NO_SELECTION )
2349 : {
2350 0 : if ( bMod1 )
2351 : {
2352 0 : if ( pView->GetSelectionMode() == MULTIPLE_SELECTION && !bShift )
2353 : // toggle selection
2354 0 : pView->Select( pCursor, !pView->IsSelected( pCursor ) );
2355 : }
2356 0 : else if ( !bShift /*&& !bMod1*/ )
2357 : {
2358 0 : if ( aSelEng.IsAddMode() )
2359 : {
2360 : // toggle selection
2361 0 : pView->Select( pCursor, !pView->IsSelected( pCursor ) );
2362 : }
2363 0 : else if ( !pView->IsSelected( pCursor ) )
2364 : {
2365 0 : SelAllDestrAnch( false );
2366 0 : pView->Select( pCursor, true );
2367 : }
2368 : else
2369 0 : bKeyUsed = false;
2370 : }
2371 : else
2372 0 : bKeyUsed = false;
2373 : }
2374 : else
2375 0 : bKeyUsed = false;
2376 0 : break;
2377 :
2378 : case KEY_RETURN:
2379 0 : if( bSubLstOpRet && IsExpandable() )
2380 : {
2381 0 : if( pView->IsExpanded( pCursor ) )
2382 0 : pView->Collapse( pCursor );
2383 : else
2384 0 : pView->Expand( pCursor );
2385 : }
2386 : else
2387 0 : bKeyUsed = false;
2388 0 : break;
2389 :
2390 : case KEY_F2:
2391 0 : if( !bShift && !bMod1 )
2392 : {
2393 0 : aEditClickPos = Point( -1, -1 );
2394 0 : EditTimerCall( 0 );
2395 : }
2396 : else
2397 0 : bKeyUsed = false;
2398 0 : break;
2399 :
2400 : case KEY_F8:
2401 0 : if( bShift && pView->GetSelectionMode()==MULTIPLE_SELECTION &&
2402 0 : !(m_nStyle & WB_SIMPLEMODE))
2403 : {
2404 0 : if( aSelEng.IsAlwaysAdding() )
2405 0 : aSelEng.AddAlways( false );
2406 : else
2407 0 : aSelEng.AddAlways( true );
2408 : }
2409 : else
2410 0 : bKeyUsed = false;
2411 0 : break;
2412 :
2413 : case KEY_ADD:
2414 0 : if( pCursor )
2415 : {
2416 0 : if( !pView->IsExpanded(pCursor))
2417 0 : pView->Expand( pCursor );
2418 0 : if( bMod1 )
2419 : {
2420 0 : sal_uInt16 nRefDepth = pTree->GetDepth( pCursor );
2421 0 : SvTreeListEntry* pCur = pTree->Next( pCursor );
2422 0 : while( pCur && pTree->GetDepth(pCur) > nRefDepth )
2423 : {
2424 0 : if( pCur->HasChildren() && !pView->IsExpanded(pCur))
2425 0 : pView->Expand( pCur );
2426 0 : pCur = pTree->Next( pCur );
2427 : }
2428 : }
2429 : }
2430 : else
2431 0 : bKeyUsed = false;
2432 0 : break;
2433 :
2434 : case KEY_A:
2435 0 : if( bMod1 )
2436 0 : SelAllDestrAnch( true );
2437 : else
2438 0 : bKeyUsed = false;
2439 0 : break;
2440 :
2441 : case KEY_SUBTRACT:
2442 0 : if( pCursor )
2443 : {
2444 0 : if( pView->IsExpanded(pCursor))
2445 0 : pView->Collapse( pCursor );
2446 0 : if( bMod1 )
2447 : {
2448 : // collapse all parents until we get to the root
2449 0 : SvTreeListEntry* pParentToCollapse = (SvTreeListEntry*)pTree->GetRootLevelParent(pCursor);
2450 0 : if( pParentToCollapse )
2451 : {
2452 : sal_uInt16 nRefDepth;
2453 : // special case explorer: if the root only has a single
2454 : // entry, don't collapse the root entry
2455 0 : if (pTree->GetChildList(0).size() < 2)
2456 : {
2457 0 : nRefDepth = 1;
2458 0 : pParentToCollapse = pCursor;
2459 0 : while( pTree->GetParent(pParentToCollapse) &&
2460 0 : pTree->GetDepth( pTree->GetParent(pParentToCollapse)) > 0)
2461 : {
2462 0 : pParentToCollapse = pTree->GetParent(pParentToCollapse);
2463 : }
2464 : }
2465 : else
2466 0 : nRefDepth = 0;
2467 :
2468 0 : if( pView->IsExpanded(pParentToCollapse) )
2469 0 : pView->Collapse( pParentToCollapse );
2470 0 : SvTreeListEntry* pCur = pTree->Next( pParentToCollapse );
2471 0 : while( pCur && pTree->GetDepth(pCur) > nRefDepth )
2472 : {
2473 0 : if( pCur->HasChildren() && pView->IsExpanded(pCur) )
2474 0 : pView->Collapse( pCur );
2475 0 : pCur = pTree->Next( pCur );
2476 : }
2477 : }
2478 : }
2479 : }
2480 : else
2481 0 : bKeyUsed = false;
2482 0 : break;
2483 :
2484 : case KEY_DIVIDE :
2485 0 : if( bMod1 )
2486 0 : SelAllDestrAnch( true );
2487 : else
2488 0 : bKeyUsed = false;
2489 0 : break;
2490 :
2491 : case KEY_COMMA :
2492 0 : if( bMod1 )
2493 0 : SelAllDestrAnch( false );
2494 : else
2495 0 : bKeyUsed = false;
2496 0 : break;
2497 :
2498 : case KEY_HOME :
2499 0 : pNewCursor = pView->GetModel()->First();
2500 :
2501 0 : while( pNewCursor && !IsSelectable(pNewCursor) )
2502 : {
2503 0 : pNewCursor = pView->NextVisible(pNewCursor);
2504 : }
2505 :
2506 0 : if( pNewCursor && pNewCursor != pCursor )
2507 : {
2508 : // SelAllDestrAnch( false );
2509 0 : aSelEng.CursorPosChanging( bShift, bMod1 );
2510 0 : SetCursor( pNewCursor );
2511 0 : if( !IsEntryInView( pNewCursor ) )
2512 0 : MakeVisible( pNewCursor );
2513 : }
2514 : else
2515 0 : bKeyUsed = false;
2516 0 : break;
2517 :
2518 : case KEY_END :
2519 0 : pNewCursor = pView->GetModel()->Last();
2520 :
2521 0 : while( pNewCursor && !IsSelectable(pNewCursor) )
2522 : {
2523 0 : pNewCursor = pView->PrevVisible(pNewCursor);
2524 : }
2525 :
2526 0 : if( pNewCursor && pNewCursor != pCursor)
2527 : {
2528 : // SelAllDestrAnch( false );
2529 0 : aSelEng.CursorPosChanging( bShift, bMod1 );
2530 0 : SetCursor( pNewCursor );
2531 0 : if( !IsEntryInView( pNewCursor ) )
2532 0 : MakeVisible( pNewCursor );
2533 : }
2534 : else
2535 0 : bKeyUsed = false;
2536 0 : break;
2537 :
2538 : case KEY_ESCAPE:
2539 : case KEY_TAB:
2540 : case KEY_DELETE:
2541 : case KEY_BACKSPACE:
2542 : // must not be handled because this quits dialogs and does other magic things...
2543 : // if there are other single keys which should not be handled, they can be added here
2544 0 : bKeyUsed = false;
2545 0 : break;
2546 :
2547 : default:
2548 : // is there any reason why we should eat the events here? The only place where this is called
2549 : // is from SvTreeListBox::KeyInput. If we set bKeyUsed to true here, then the key input
2550 : // is just silenced. However, we want SvLBox::KeyInput to get a chance, to do the QuickSelection
2551 : // handling.
2552 : // (The old code here which intentionally set bKeyUsed to TRUE said this was because of "quick search"
2553 : // handling, but actually there was no quick search handling anymore. We just re-implemented it.)
2554 : // #i31275# / 2009-06-16 / frank.schoenheit@sun.com
2555 0 : bKeyUsed = false;
2556 0 : break;
2557 : }
2558 0 : return bKeyUsed;
2559 : }
2560 :
2561 0 : void SvImpLBox::GetFocus()
2562 : {
2563 0 : if( pCursor )
2564 : {
2565 0 : pView->SetEntryFocus( pCursor, true );
2566 0 : ShowCursor( true );
2567 : // auskommentiert wg. deselectall
2568 : // if( bSimpleTravel && !pView->IsSelected(pCursor) )
2569 : // pView->Select( pCursor, true );
2570 : }
2571 0 : if( m_nStyle & WB_HIDESELECTION )
2572 : {
2573 0 : SvTreeListEntry* pEntry = pView->FirstSelected();
2574 0 : while( pEntry )
2575 : {
2576 0 : InvalidateEntry( pEntry );
2577 0 : pEntry = pView->NextSelected( pEntry );
2578 : }
2579 : }
2580 0 : }
2581 :
2582 0 : void SvImpLBox::LoseFocus()
2583 : {
2584 0 : aEditTimer.Stop();
2585 0 : if( pCursor )
2586 0 : pView->SetEntryFocus( pCursor,false );
2587 0 : ShowCursor( false );
2588 :
2589 0 : if( m_nStyle & WB_HIDESELECTION )
2590 : {
2591 0 : SvTreeListEntry* pEntry = pView->FirstSelected();
2592 0 : while( pEntry )
2593 : {
2594 0 : InvalidateEntry( pEntry );
2595 0 : pEntry = pView->NextSelected( pEntry );
2596 : }
2597 : }
2598 0 : }
2599 :
2600 :
2601 : // ********************************************************************
2602 : // SelectionEngine
2603 : // ********************************************************************
2604 :
2605 0 : void SvImpLBox::SelectEntry( SvTreeListEntry* pEntry, bool bSelect )
2606 : {
2607 0 : pView->Select( pEntry, bSelect );
2608 0 : }
2609 :
2610 0 : ImpLBSelEng::ImpLBSelEng( SvImpLBox* pImpl, SelectionEngine* pSEng,
2611 0 : SvTreeListBox* pV )
2612 : {
2613 0 : pImp = pImpl;
2614 0 : pSelEng = pSEng;
2615 0 : pView = pV;
2616 0 : }
2617 :
2618 0 : ImpLBSelEng::~ImpLBSelEng()
2619 : {
2620 0 : }
2621 :
2622 0 : void ImpLBSelEng::BeginDrag()
2623 : {
2624 0 : pImp->BeginDrag();
2625 0 : }
2626 :
2627 0 : void ImpLBSelEng::CreateAnchor()
2628 : {
2629 0 : pImp->pAnchor = pImp->pCursor;
2630 0 : }
2631 :
2632 0 : void ImpLBSelEng::DestroyAnchor()
2633 : {
2634 0 : pImp->pAnchor = 0;
2635 0 : }
2636 :
2637 0 : sal_Bool ImpLBSelEng::SetCursorAtPoint(const Point& rPoint, sal_Bool bDontSelectAtCursor)
2638 : {
2639 0 : SvTreeListEntry* pNewCursor = pImp->MakePointVisible( rPoint );
2640 0 : if( pNewCursor != pImp->pCursor )
2641 0 : pImp->BeginScroll();
2642 :
2643 0 : if( pNewCursor )
2644 : {
2645 : // at SimpleTravel, the SetCursor is selected and the select handler is
2646 : // called
2647 : //if( !bDontSelectAtCursor && !pImp->bSimpleTravel )
2648 : // pImp->SelectEntry( pNewCursor, true );
2649 0 : pImp->SetCursor( pNewCursor, bDontSelectAtCursor );
2650 0 : return true;
2651 : }
2652 0 : return false;
2653 : }
2654 :
2655 0 : sal_Bool ImpLBSelEng::IsSelectionAtPoint( const Point& rPoint )
2656 : {
2657 0 : SvTreeListEntry* pEntry = pImp->MakePointVisible( rPoint );
2658 0 : if( pEntry )
2659 0 : return pView->IsSelected(pEntry);
2660 0 : return false;
2661 : }
2662 :
2663 0 : void ImpLBSelEng::DeselectAtPoint( const Point& rPoint )
2664 : {
2665 0 : SvTreeListEntry* pEntry = pImp->MakePointVisible( rPoint );
2666 0 : if( !pEntry )
2667 0 : return;
2668 0 : pImp->SelectEntry( pEntry, false );
2669 : }
2670 :
2671 0 : void ImpLBSelEng::DeselectAll()
2672 : {
2673 0 : pImp->SelAllDestrAnch( false, false ); // don't reset SelectionEngine!
2674 0 : pImp->nFlags &= (~F_DESEL_ALL);
2675 0 : }
2676 :
2677 : // ***********************************************************************
2678 : // Selection
2679 : // ***********************************************************************
2680 :
2681 0 : void SvImpLBox::SetAnchorSelection(SvTreeListEntry* pOldCursor,SvTreeListEntry* pNewCursor)
2682 : {
2683 : SvTreeListEntry* pEntry;
2684 0 : sal_uLong nAnchorVisPos = pView->GetVisiblePos( pAnchor );
2685 0 : sal_uLong nOldVisPos = pView->GetVisiblePos( pOldCursor );
2686 0 : sal_uLong nNewVisPos = pView->GetVisiblePos( pNewCursor );
2687 :
2688 0 : if( nOldVisPos > nAnchorVisPos ||
2689 : ( nAnchorVisPos==nOldVisPos && nNewVisPos > nAnchorVisPos) )
2690 : {
2691 0 : if( nNewVisPos > nOldVisPos )
2692 : {
2693 0 : pEntry = pOldCursor;
2694 0 : while( pEntry && pEntry != pNewCursor )
2695 : {
2696 0 : pView->Select( pEntry, true );
2697 0 : pEntry = pView->NextVisible(pEntry);
2698 : }
2699 0 : if( pEntry )
2700 0 : pView->Select( pEntry, true );
2701 0 : return;
2702 : }
2703 :
2704 0 : if( nNewVisPos < nAnchorVisPos )
2705 : {
2706 0 : pEntry = pAnchor;
2707 0 : while( pEntry && pEntry != pOldCursor )
2708 : {
2709 0 : pView->Select( pEntry, false );
2710 0 : pEntry = pView->NextVisible(pEntry);
2711 : }
2712 0 : if( pEntry )
2713 0 : pView->Select( pEntry, false );
2714 :
2715 0 : pEntry = pNewCursor;
2716 0 : while( pEntry && pEntry != pAnchor )
2717 : {
2718 0 : pView->Select( pEntry, true );
2719 0 : pEntry = pView->NextVisible(pEntry);
2720 : }
2721 0 : if( pEntry )
2722 0 : pView->Select( pEntry, true );
2723 0 : return;
2724 : }
2725 :
2726 0 : if( nNewVisPos < nOldVisPos )
2727 : {
2728 0 : pEntry = pNewCursor;
2729 0 : pEntry = pView->NextVisible(pEntry);
2730 0 : while( pEntry && pEntry != pOldCursor )
2731 : {
2732 0 : pView->Select( pEntry, false );
2733 0 : pEntry = pView->NextVisible(pEntry);
2734 : }
2735 0 : if( pEntry )
2736 0 : pView->Select( pEntry, false );
2737 0 : return;
2738 : }
2739 : }
2740 : else
2741 : {
2742 0 : if( nNewVisPos < nOldVisPos ) // enlarge selection
2743 : {
2744 0 : pEntry = pNewCursor;
2745 0 : while( pEntry && pEntry != pOldCursor )
2746 : {
2747 0 : pView->Select( pEntry, true );
2748 0 : pEntry = pView->NextVisible(pEntry);
2749 : }
2750 0 : if( pEntry )
2751 0 : pView->Select( pEntry, true );
2752 0 : return;
2753 : }
2754 :
2755 0 : if( nNewVisPos > nAnchorVisPos )
2756 : {
2757 0 : pEntry = pOldCursor;
2758 0 : while( pEntry && pEntry != pAnchor )
2759 : {
2760 0 : pView->Select( pEntry, false );
2761 0 : pEntry = pView->NextVisible(pEntry);
2762 : }
2763 0 : if( pEntry )
2764 0 : pView->Select( pEntry, false );
2765 0 : pEntry = pAnchor;
2766 0 : while( pEntry && pEntry != pNewCursor )
2767 : {
2768 0 : pView->Select( pEntry, true );
2769 0 : pEntry = pView->NextVisible(pEntry);
2770 : }
2771 0 : if( pEntry )
2772 0 : pView->Select( pEntry, true );
2773 0 : return;
2774 : }
2775 :
2776 0 : if( nNewVisPos > nOldVisPos )
2777 : {
2778 0 : pEntry = pOldCursor;
2779 0 : while( pEntry && pEntry != pNewCursor )
2780 : {
2781 0 : pView->Select( pEntry, false );
2782 0 : pEntry = pView->NextVisible(pEntry);
2783 : }
2784 0 : return;
2785 : }
2786 : }
2787 : }
2788 :
2789 0 : void SvImpLBox::SelAllDestrAnch(
2790 : bool bSelect, bool bDestroyAnchor, bool bSingleSelToo )
2791 : {
2792 : SvTreeListEntry* pEntry;
2793 0 : nFlags &= (~F_DESEL_ALL);
2794 0 : if( bSelect && bSimpleTravel )
2795 : {
2796 0 : if( pCursor && !pView->IsSelected( pCursor ))
2797 : {
2798 0 : pView->Select( pCursor, true );
2799 : }
2800 0 : return;
2801 : }
2802 0 : if( !bSelect && pView->GetSelectionCount() == 0 )
2803 : {
2804 0 : if( bSimpleTravel && ( !GetUpdateMode() || !pCursor) )
2805 0 : nFlags |= F_DESEL_ALL;
2806 0 : return;
2807 : }
2808 0 : if( bSelect && pView->GetSelectionCount() == pView->GetEntryCount())
2809 0 : return;
2810 0 : if( !bSingleSelToo && bSimpleTravel )
2811 0 : return;
2812 :
2813 0 : if( !bSelect && pView->GetSelectionCount()==1 && pCursor &&
2814 0 : pView->IsSelected( pCursor ))
2815 : {
2816 0 : pView->Select( pCursor, false );
2817 0 : if( bDestroyAnchor )
2818 0 : DestroyAnchor(); // delete anchor & reset SelectionEngine
2819 : else
2820 0 : pAnchor = 0; // always delete internal anchor
2821 0 : return;
2822 : }
2823 :
2824 0 : if( bSimpleTravel && !pCursor && !GetUpdateMode() )
2825 0 : nFlags |= F_DESEL_ALL;
2826 :
2827 0 : ShowCursor( false );
2828 0 : bool bUpdate = GetUpdateMode();
2829 :
2830 0 : nFlags |= F_IGNORE_SELECT; // EntryInserted should not do anything
2831 0 : pEntry = pTree->First();
2832 0 : while( pEntry )
2833 : {
2834 0 : if( pView->Select( pEntry, bSelect ) )
2835 : {
2836 0 : if( bUpdate && pView->IsEntryVisible(pEntry) )
2837 : {
2838 0 : long nY = GetEntryLine( pEntry );
2839 0 : if( IsLineVisible( nY ) )
2840 0 : pView->PaintEntry1( pEntry, nY, 0xffff ); // because of ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
2841 : }
2842 : }
2843 0 : pEntry = pTree->Next( pEntry );
2844 : }
2845 0 : nFlags &= ~F_IGNORE_SELECT;
2846 :
2847 0 : if( bDestroyAnchor )
2848 0 : DestroyAnchor(); // delete anchor & reset SelectionEngine
2849 : else
2850 0 : pAnchor = 0; // always delete internal anchor
2851 0 : ShowCursor( true );
2852 : }
2853 :
2854 0 : void SvImpLBox::SetSelectionMode( SelectionMode eSelMode )
2855 : {
2856 0 : aSelEng.SetSelectionMode( eSelMode);
2857 0 : if( eSelMode == SINGLE_SELECTION )
2858 0 : bSimpleTravel = true;
2859 : else
2860 0 : bSimpleTravel = false;
2861 0 : if( (m_nStyle & WB_SIMPLEMODE) && (eSelMode == MULTIPLE_SELECTION) )
2862 0 : aSelEng.AddAlways( true );
2863 0 : }
2864 :
2865 : // ***********************************************************************
2866 : // Drag & Drop
2867 : // ***********************************************************************
2868 :
2869 0 : void SvImpLBox::SetDragDropMode( DragDropMode eDDMode )
2870 : {
2871 0 : if( eDDMode && eDDMode != SV_DRAGDROP_APP_DROP )
2872 : {
2873 0 : aSelEng.ExpandSelectionOnMouseMove( false );
2874 0 : aSelEng.EnableDrag( true );
2875 : }
2876 : else
2877 : {
2878 0 : aSelEng.ExpandSelectionOnMouseMove( true );
2879 0 : aSelEng.EnableDrag( false );
2880 : }
2881 0 : }
2882 :
2883 0 : void SvImpLBox::BeginDrag()
2884 : {
2885 0 : nFlags &= (~F_FILLING);
2886 0 : if( !bAsyncBeginDrag )
2887 : {
2888 0 : BeginScroll();
2889 0 : pView->StartDrag( 0, aSelEng.GetMousePosPixel() );
2890 0 : EndScroll();
2891 : }
2892 : else
2893 : {
2894 0 : aAsyncBeginDragPos = aSelEng.GetMousePosPixel();
2895 0 : aAsyncBeginDragTimer.Start();
2896 : }
2897 0 : }
2898 :
2899 0 : IMPL_LINK_NOARG(SvImpLBox, BeginDragHdl)
2900 : {
2901 0 : pView->StartDrag( 0, aAsyncBeginDragPos );
2902 0 : return 0;
2903 : }
2904 :
2905 0 : void SvImpLBox::PaintDDCursor( SvTreeListEntry* pInsertionPos )
2906 : {
2907 : long nY;
2908 0 : if( pInsertionPos )
2909 : {
2910 0 : nY = GetEntryLine( pInsertionPos );
2911 0 : nY += pView->GetEntryHeight();
2912 : }
2913 : else
2914 0 : nY = 1;
2915 0 : RasterOp eOldOp = pView->GetRasterOp();
2916 0 : pView->SetRasterOp( ROP_INVERT );
2917 0 : Color aOldLineColor = pView->GetLineColor();
2918 0 : pView->SetLineColor( Color( COL_BLACK ) );
2919 0 : pView->DrawLine( Point( 0, nY ), Point( aOutputSize.Width(), nY ) );
2920 0 : pView->SetLineColor( aOldLineColor );
2921 0 : pView->SetRasterOp( eOldOp );
2922 0 : }
2923 :
2924 : // Delete all submenus of a PopupMenu, recursively
2925 0 : static void lcl_DeleteSubPopups(PopupMenu* pPopup)
2926 : {
2927 0 : for(sal_uInt16 i = 0; i < pPopup->GetItemCount(); i++)
2928 : {
2929 0 : PopupMenu* pSubPopup = pPopup->GetPopupMenu( pPopup->GetItemId( i ));
2930 0 : if(pSubPopup)
2931 : {
2932 0 : lcl_DeleteSubPopups(pSubPopup);
2933 0 : delete pSubPopup;
2934 : }
2935 : }
2936 0 : }
2937 :
2938 0 : void SvImpLBox::Command( const CommandEvent& rCEvt )
2939 : {
2940 0 : sal_uInt16 nCommand = rCEvt.GetCommand();
2941 :
2942 0 : if( nCommand == COMMAND_CONTEXTMENU )
2943 0 : aEditTimer.Stop();
2944 :
2945 : // scroll mouse event?
2946 0 : if( ( ( nCommand == COMMAND_WHEEL ) || ( nCommand == COMMAND_STARTAUTOSCROLL ) || ( nCommand == COMMAND_AUTOSCROLL ) )
2947 0 : && pView->HandleScrollCommand( rCEvt, &aHorSBar, &aVerSBar ) )
2948 0 : return;
2949 :
2950 0 : if( bContextMenuHandling && nCommand == COMMAND_CONTEXTMENU )
2951 : {
2952 0 : Point aPopupPos;
2953 0 : bool bClickedIsFreePlace = false;
2954 0 : std::stack<SvTreeListEntry*> aSelRestore;
2955 :
2956 0 : if( rCEvt.IsMouseEvent() )
2957 : { // change selection, if mouse position doesn't fit to selection
2958 :
2959 0 : aPopupPos = rCEvt.GetMousePosPixel();
2960 :
2961 0 : SvTreeListEntry* pClickedEntry = GetEntry( aPopupPos );
2962 0 : if( pClickedEntry )
2963 : { // mouse in non empty area
2964 0 : bool bClickedIsSelected = false;
2965 :
2966 : // collect the currently selected entries
2967 0 : SvTreeListEntry* pSelected = pView->FirstSelected();
2968 0 : while( pSelected )
2969 : {
2970 0 : bClickedIsSelected |= ( pClickedEntry == pSelected );
2971 0 : pSelected = pView->NextSelected( pSelected );
2972 : }
2973 :
2974 : // if the entry which the user clicked at is not selected
2975 0 : if( !bClickedIsSelected )
2976 : { // deselect all other and select the clicked one
2977 0 : pView->SelectAll( false );
2978 0 : pView->SetCursor( pClickedEntry );
2979 : }
2980 : }
2981 0 : else if( aSelEng.GetSelectionMode() == SINGLE_SELECTION )
2982 : {
2983 0 : bClickedIsFreePlace = true;
2984 0 : sal_Int32 nSelectedEntries = pView->GetSelectionCount();
2985 0 : SvTreeListEntry* pSelected = pView->FirstSelected();
2986 0 : for(sal_uInt16 nSel = 0; nSel < nSelectedEntries; nSel++ )
2987 : {
2988 0 : aSelRestore.push(pSelected);
2989 0 : pSelected = pView->NextSelected( pSelected );
2990 : }
2991 0 : pView->SelectAll( false );
2992 : }
2993 : else
2994 : { // deselect all
2995 0 : pView->SelectAll( false );
2996 : }
2997 :
2998 :
2999 : }
3000 : else
3001 : { // key event (or at least no mouse event)
3002 0 : sal_Int32 nSelectionCount = pView->GetSelectionCount();
3003 :
3004 0 : if( nSelectionCount )
3005 : { // now always take first visible as base for positioning the menu
3006 0 : SvTreeListEntry* pSelected = pView->FirstSelected();
3007 0 : while( pSelected )
3008 : {
3009 0 : if( IsEntryInView( pSelected ) )
3010 0 : break;
3011 :
3012 0 : pSelected = pView->NextSelected( pSelected );
3013 : }
3014 :
3015 0 : if( !pSelected )
3016 : {
3017 : // no one was visible
3018 0 : pSelected = pView->FirstSelected();
3019 0 : pView->MakeVisible( pSelected );
3020 : }
3021 :
3022 0 : aPopupPos = pView->GetFocusRect( pSelected, pView->GetEntryPosition( pSelected ).Y() ).Center();
3023 : }
3024 : else
3025 0 : aPopupPos = Point( 0, 0 );
3026 : }
3027 :
3028 0 : PopupMenu* pPopup = pView->CreateContextMenu();
3029 :
3030 0 : if( pPopup )
3031 : {
3032 : // do action for selected entry in popup menu
3033 0 : sal_uInt16 nMenuAction = pPopup->Execute( pView, aPopupPos );
3034 0 : if ( nMenuAction )
3035 0 : pView->ExcecuteContextMenuAction( nMenuAction );
3036 0 : lcl_DeleteSubPopups(pPopup);
3037 0 : delete pPopup;
3038 : }
3039 :
3040 0 : if( bClickedIsFreePlace )
3041 : {
3042 0 : while(!aSelRestore.empty())
3043 : {
3044 0 : SvTreeListEntry* pEntry = aSelRestore.top();
3045 : //#i19717# the entry is maybe already deleted
3046 0 : bool bFound = false;
3047 0 : for(sal_uLong nEntry = 0; nEntry < pView->GetEntryCount(); nEntry++)
3048 0 : if(pEntry == pView->GetEntry(nEntry))
3049 : {
3050 0 : bFound = true;
3051 0 : break;
3052 : }
3053 0 : if(bFound)
3054 0 : SetCurEntry( pEntry );
3055 0 : aSelRestore.pop();
3056 : }
3057 0 : }
3058 : }
3059 : #ifndef NOCOMMAND
3060 : else
3061 : {
3062 0 : const Point& rPos = rCEvt.GetMousePosPixel();
3063 0 : if( rPos.X() < aOutputSize.Width() && rPos.Y() < aOutputSize.Height() )
3064 0 : aSelEng.Command( rCEvt );
3065 : }
3066 : #endif
3067 : }
3068 :
3069 0 : void SvImpLBox::BeginScroll()
3070 : {
3071 0 : if( !(nFlags & F_IN_SCROLLING))
3072 : {
3073 0 : pView->NotifyBeginScroll();
3074 0 : nFlags |= F_IN_SCROLLING;
3075 : }
3076 0 : }
3077 :
3078 0 : void SvImpLBox::EndScroll()
3079 : {
3080 0 : if( nFlags & F_IN_SCROLLING)
3081 : {
3082 0 : pView->NotifyEndScroll();
3083 0 : nFlags &= (~F_IN_SCROLLING);
3084 : }
3085 0 : }
3086 :
3087 :
3088 0 : Rectangle SvImpLBox::GetVisibleArea() const
3089 : {
3090 0 : Point aPos( pView->GetMapMode().GetOrigin() );
3091 0 : aPos.X() *= -1;
3092 0 : Rectangle aRect( aPos, aOutputSize );
3093 0 : return aRect;
3094 : }
3095 :
3096 0 : void SvImpLBox::Invalidate()
3097 : {
3098 0 : pView->SetClipRegion();
3099 0 : }
3100 :
3101 0 : void SvImpLBox::SetCurEntry( SvTreeListEntry* pEntry )
3102 : {
3103 0 : if ( ( aSelEng.GetSelectionMode() != SINGLE_SELECTION )
3104 0 : && ( aSelEng.GetSelectionMode() != NO_SELECTION )
3105 : )
3106 0 : SelAllDestrAnch( false, true, false );
3107 0 : if ( pEntry )
3108 0 : MakeVisible( pEntry );
3109 0 : SetCursor( pEntry );
3110 0 : if ( pEntry && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
3111 0 : pView->Select( pEntry, true );
3112 0 : }
3113 :
3114 0 : IMPL_LINK_NOARG(SvImpLBox, EditTimerCall)
3115 : {
3116 0 : if( pView->IsInplaceEditingEnabled() )
3117 : {
3118 0 : bool bIsMouseTriggered = aEditClickPos.X() >= 0;
3119 0 : if ( bIsMouseTriggered )
3120 : {
3121 0 : Point aCurrentMousePos = pView->GetPointerPosPixel();
3122 0 : if ( ( abs( aCurrentMousePos.X() - aEditClickPos.X() ) > 5 )
3123 0 : || ( abs( aCurrentMousePos.Y() - aEditClickPos.Y() ) > 5 )
3124 : )
3125 : {
3126 0 : return 0L;
3127 : }
3128 : }
3129 :
3130 0 : SvTreeListEntry* pEntry = GetCurEntry();
3131 0 : if( pEntry )
3132 : {
3133 0 : ShowCursor( false );
3134 0 : pView->ImplEditEntry( pEntry );
3135 0 : ShowCursor( true );
3136 : }
3137 : }
3138 0 : return 0;
3139 : }
3140 :
3141 0 : bool SvImpLBox::RequestHelp( const HelpEvent& rHEvt )
3142 : {
3143 0 : if( rHEvt.GetMode() & HELPMODE_QUICK )
3144 : {
3145 0 : Point aPos( pView->ScreenToOutputPixel( rHEvt.GetMousePosPixel() ));
3146 0 : if( !GetVisibleArea().IsInside( aPos ))
3147 0 : return false;
3148 :
3149 0 : SvTreeListEntry* pEntry = GetEntry( aPos );
3150 0 : if( pEntry )
3151 : {
3152 : // recalculate text rectangle
3153 : SvLBoxTab* pTab;
3154 0 : SvLBoxString* pItem = (SvLBoxString*)(pView->GetItem( pEntry, aPos.X(), &pTab ));
3155 0 : if (!pItem || pItem->GetType() != SV_ITEM_ID_LBOXSTRING)
3156 0 : return false;
3157 :
3158 0 : aPos = GetEntryPosition( pEntry );
3159 0 : aPos.X() = pView->GetTabPos( pEntry, pTab ); //pTab->GetPos();
3160 0 : Size aSize( pItem->GetSize( pView, pEntry ) );
3161 0 : SvLBoxTab* pNextTab = NextTab( pTab );
3162 0 : bool bItemClipped = false;
3163 : // is the item cut off by its right neighbor?
3164 0 : if( pNextTab && pView->GetTabPos(pEntry,pNextTab) < aPos.X()+aSize.Width() )
3165 : {
3166 0 : aSize.Width() = pNextTab->GetPos() - pTab->GetPos();
3167 0 : bItemClipped = true;
3168 : }
3169 0 : Rectangle aItemRect( aPos, aSize );
3170 :
3171 0 : Rectangle aViewRect( GetVisibleArea() );
3172 :
3173 0 : if( bItemClipped || !aViewRect.IsInside( aItemRect ) )
3174 : {
3175 : // clip the right edge of the item at the edge of the view
3176 : //if( aItemRect.Right() > aViewRect.Right() )
3177 : // aItemRect.Right() = aViewRect.Right();
3178 :
3179 0 : Point aPt = pView->OutputToScreenPixel( aItemRect.TopLeft() );
3180 0 : aItemRect.Left() = aPt.X();
3181 0 : aItemRect.Top() = aPt.Y();
3182 0 : aPt = pView->OutputToScreenPixel( aItemRect.BottomRight() );
3183 0 : aItemRect.Right() = aPt.X();
3184 0 : aItemRect.Bottom() = aPt.Y();
3185 :
3186 : Help::ShowQuickHelp( pView, aItemRect,
3187 0 : pItem->GetText(), QUICKHELP_LEFT | QUICKHELP_VCENTER );
3188 0 : return true;
3189 : }
3190 : }
3191 : }
3192 0 : return false;
3193 : }
3194 :
3195 0 : SvLBoxTab* SvImpLBox::NextTab( SvLBoxTab* pTab )
3196 : {
3197 0 : sal_uInt16 nTabCount = pView->TabCount();
3198 0 : if( nTabCount <= 1 )
3199 0 : return 0;
3200 0 : for( sal_uInt16 nTab=0; nTab < (nTabCount-1); nTab++)
3201 : {
3202 0 : if( pView->aTabs[nTab]==pTab )
3203 0 : return (SvLBoxTab*)(pView->aTabs[nTab+1]);
3204 : }
3205 0 : return 0;
3206 : }
3207 :
3208 0 : void SvImpLBox::EndSelection()
3209 : {
3210 0 : DestroyAnchor();
3211 0 : nFlags &= ~F_START_EDITTIMER;
3212 0 : }
3213 :
3214 0 : void SvImpLBox::RepaintScrollBars()
3215 : {
3216 0 : }
3217 :
3218 0 : void SvImpLBox::SetUpdateMode( bool bMode )
3219 : {
3220 0 : if( bUpdateMode != bMode )
3221 : {
3222 0 : bUpdateMode = bMode;
3223 0 : if( bUpdateMode )
3224 0 : UpdateAll( false );
3225 : }
3226 0 : }
3227 :
3228 0 : bool SvImpLBox::SetMostRight( SvTreeListEntry* pEntry )
3229 : {
3230 0 : if( pView->nTreeFlags & TREEFLAG_RECALCTABS )
3231 : {
3232 0 : nFlags |= F_IGNORE_CHANGED_TABS;
3233 0 : pView->SetTabs();
3234 0 : nFlags &= ~F_IGNORE_CHANGED_TABS;
3235 : }
3236 :
3237 0 : sal_uInt16 nLastTab = pView->aTabs.size() - 1;
3238 0 : sal_uInt16 nLastItem = pEntry->ItemCount() - 1;
3239 0 : if( !pView->aTabs.empty() && nLastItem != USHRT_MAX )
3240 : {
3241 0 : if( nLastItem < nLastTab )
3242 0 : nLastTab = nLastItem;
3243 :
3244 0 : SvLBoxTab* pTab = pView->aTabs[ nLastTab ];
3245 0 : SvLBoxItem* pItem = pEntry->GetItem( nLastTab );
3246 :
3247 0 : long nTabPos = pView->GetTabPos( pEntry, pTab );
3248 :
3249 0 : long nMaxRight = GetOutputSize().Width();
3250 0 : Point aPos( pView->GetMapMode().GetOrigin() );
3251 0 : aPos.X() *= -1; // conversion document coordinates
3252 0 : nMaxRight = nMaxRight + aPos.X() - 1;
3253 :
3254 0 : long nNextTab = nTabPos < nMaxRight ? nMaxRight : nMaxRight + 50;
3255 0 : long nTabWidth = nNextTab - nTabPos + 1;
3256 0 : long nItemSize = pItem->GetSize(pView,pEntry).Width();
3257 0 : long nOffset = pTab->CalcOffset( nItemSize, nTabWidth );
3258 :
3259 0 : long nRight = nTabPos + nOffset + nItemSize;
3260 0 : if( nRight > nMostRight )
3261 : {
3262 0 : nMostRight = nRight;
3263 0 : pMostRightEntry = pEntry;
3264 0 : return true;
3265 : }
3266 : }
3267 0 : return false;
3268 : }
3269 :
3270 0 : void SvImpLBox::FindMostRight( SvTreeListEntry* pEntryToIgnore )
3271 : {
3272 0 : nMostRight = -1;
3273 0 : pMostRightEntry = 0;
3274 0 : if( !pView->GetModel() )
3275 0 : return;
3276 :
3277 0 : SvTreeListEntry* pEntry = (SvTreeListEntry*)pView->FirstVisible();
3278 0 : while( pEntry )
3279 : {
3280 0 : if( pEntry != pEntryToIgnore )
3281 0 : SetMostRight( pEntry );
3282 0 : pEntry = (SvTreeListEntry*)pView->NextVisible( pEntry );
3283 : }
3284 : }
3285 :
3286 0 : void SvImpLBox::FindMostRight( SvTreeListEntry* pParent, SvTreeListEntry* pEntryToIgnore )
3287 : {
3288 0 : if( !pParent )
3289 0 : FindMostRight( pEntryToIgnore );
3290 : else
3291 0 : FindMostRight_Impl( pParent, pEntryToIgnore );
3292 0 : }
3293 :
3294 0 : void SvImpLBox::FindMostRight_Impl( SvTreeListEntry* pParent, SvTreeListEntry* pEntryToIgnore )
3295 : {
3296 0 : SvTreeListEntries& rList = pTree->GetChildList( pParent );
3297 :
3298 0 : size_t nCount = rList.size();
3299 0 : for( size_t nCur = 0; nCur < nCount; nCur++ )
3300 : {
3301 0 : SvTreeListEntry* pChild = &rList[nCur];
3302 0 : if( pChild != pEntryToIgnore )
3303 : {
3304 0 : SetMostRight( pChild );
3305 0 : if( pChild->HasChildren() && pView->IsExpanded( pChild ))
3306 0 : FindMostRight_Impl( pChild, pEntryToIgnore );
3307 : }
3308 : }
3309 0 : }
3310 :
3311 0 : void SvImpLBox::NotifyTabsChanged()
3312 : {
3313 0 : if( GetUpdateMode() && !(nFlags & F_IGNORE_CHANGED_TABS ) &&
3314 : nCurUserEvent == 0xffffffff )
3315 : {
3316 0 : nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpLBox,MyUserEvent),(void*)0);
3317 : }
3318 0 : }
3319 :
3320 0 : bool SvImpLBox::IsExpandable() const
3321 : {
3322 0 : return pCursor->HasChildren() || pCursor->HasChildrenOnDemand();
3323 : }
3324 :
3325 0 : bool SvImpLBox::IsNowExpandable() const
3326 : {
3327 0 : return IsExpandable() && !pView->IsExpanded( pCursor );
3328 : }
3329 :
3330 0 : IMPL_LINK(SvImpLBox,MyUserEvent,void*, pArg )
3331 : {
3332 0 : nCurUserEvent = 0xffffffff;
3333 0 : if( !pArg )
3334 : {
3335 0 : pView->Invalidate();
3336 0 : pView->Update();
3337 : }
3338 : else
3339 : {
3340 0 : FindMostRight( 0 );
3341 0 : ShowVerSBar();
3342 0 : pView->Invalidate( GetVisibleArea() );
3343 : }
3344 0 : return 0;
3345 : }
3346 :
3347 :
3348 0 : void SvImpLBox::StopUserEvent()
3349 : {
3350 0 : if( nCurUserEvent != 0xffffffff )
3351 : {
3352 0 : Application::RemoveUserEvent( nCurUserEvent );
3353 0 : nCurUserEvent = 0xffffffff;
3354 : }
3355 0 : }
3356 :
3357 0 : void SvImpLBox::ShowFocusRect( const SvTreeListEntry* pEntry )
3358 : {
3359 0 : if( pEntry )
3360 : {
3361 0 : long nY = GetEntryLine( (SvTreeListEntry*)pEntry );
3362 0 : Rectangle aRect = pView->GetFocusRect( (SvTreeListEntry*)pEntry, nY );
3363 0 : Region aOldClip( pView->GetClipRegion());
3364 0 : Region aClipRegion( GetClipRegionRect() );
3365 0 : pView->SetClipRegion( aClipRegion );
3366 0 : pView->ShowFocus( aRect );
3367 0 : pView->SetClipRegion( aOldClip );
3368 :
3369 : }
3370 : else
3371 : {
3372 0 : pView->HideFocus();
3373 : }
3374 0 : }
3375 :
3376 : // -----------------------------------------------------------------------
3377 0 : void SvImpLBox::implInitDefaultNodeImages()
3378 : {
3379 0 : if ( s_pDefCollapsed )
3380 : // assume that all or nothing is initialized
3381 0 : return;
3382 :
3383 0 : s_pDefCollapsed = new Image( SvtResId( RID_IMG_TREENODE_COLLAPSED ) );
3384 0 : s_pDefExpanded = new Image( SvtResId( RID_IMG_TREENODE_EXPANDED ) );
3385 : }
3386 :
3387 : // -----------------------------------------------------------------------
3388 0 : const Image& SvImpLBox::GetDefaultExpandedNodeImage( )
3389 : {
3390 0 : implInitDefaultNodeImages();
3391 0 : return *s_pDefExpanded;
3392 : }
3393 :
3394 : // -----------------------------------------------------------------------
3395 0 : const Image& SvImpLBox::GetDefaultCollapsedNodeImage( )
3396 : {
3397 0 : implInitDefaultNodeImages();
3398 0 : return *s_pDefCollapsed;
3399 : }
3400 :
3401 : // -----------------------------------------------------------------------
3402 0 : void SvImpLBox::CallEventListeners( sal_uLong nEvent, void* pData )
3403 : {
3404 0 : if ( pView )
3405 0 : pView->CallImplEventListeners( nEvent, pData);
3406 0 : }
3407 :
3408 : // -----------------------------------------------------------------------
3409 :
3410 0 : bool SvImpLBox::SetCurrentTabPos( sal_uInt16 _nNewPos )
3411 : {
3412 0 : bool bRet = false;
3413 :
3414 0 : if ( pView && _nNewPos < ( pView->TabCount() - 2 ) )
3415 : {
3416 0 : nCurTabPos = _nNewPos;
3417 0 : ShowCursor( true );
3418 0 : bRet = true;
3419 : }
3420 :
3421 0 : return bRet;
3422 : }
3423 :
3424 : // -----------------------------------------------------------------------
3425 :
3426 0 : bool SvImpLBox::IsSelectable( const SvTreeListEntry* pEntry )
3427 : {
3428 0 : if( pEntry )
3429 : {
3430 0 : SvViewDataEntry* pViewDataNewCur = pView->GetViewDataEntry(const_cast<SvTreeListEntry*>(pEntry));
3431 0 : return (pViewDataNewCur == 0) || pViewDataNewCur->IsSelectable();
3432 : }
3433 : else
3434 : {
3435 0 : return false;
3436 : }
3437 : }
3438 :
3439 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|