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