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 0 : 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 0 : , m_pStringSorter(NULL)
60 : {
61 0 : osl_atomic_increment(&s_nImageRefCount);
62 0 : pView = pLBView;
63 0 : pTree = pLBTree;
64 0 : aSelEng.SetFunctionSet( (FunctionSet*)&aFctSet );
65 0 : aSelEng.ExpandSelectionOnMouseMove( false );
66 0 : SetStyle( nWinStyle );
67 0 : SetSelectionMode( SINGLE_SELECTION );
68 0 : SetDragDropMode( 0 );
69 :
70 0 : aVerSBar.SetScrollHdl( LINK( this, SvImpLBox, ScrollUpDownHdl ) );
71 0 : aHorSBar.SetScrollHdl( LINK( this, SvImpLBox, ScrollLeftRightHdl ) );
72 0 : aHorSBar.SetEndScrollHdl( LINK( this, SvImpLBox, EndScrollHdl ) );
73 0 : aVerSBar.SetEndScrollHdl( LINK( this, SvImpLBox, EndScrollHdl ) );
74 0 : aVerSBar.SetRange( Range(0,0) );
75 0 : aVerSBar.Hide();
76 0 : aHorSBar.SetRange( Range(0,0) );
77 0 : aHorSBar.SetPageSize( 24 ); // pixels
78 0 : aHorSBar.SetLineSize( 8 ); // pixels
79 :
80 0 : nHorSBarHeight = (short)aHorSBar.GetSizePixel().Height();
81 0 : nVerSBarWidth = (short)aVerSBar.GetSizePixel().Width();
82 :
83 0 : pStartEntry = 0;
84 0 : pCursor = 0;
85 0 : pAnchor = 0;
86 0 : nVisibleCount = 0; // number of rows of data in control
87 0 : nNodeBmpTabDistance = NODE_BMP_TABDIST_NOTVALID;
88 0 : nYoffsNodeBmp = 0;
89 0 : nNodeBmpWidth = 0;
90 :
91 0 : bAsyncBeginDrag = false;
92 0 : aAsyncBeginDragTimer.SetTimeout( 0 );
93 0 : aAsyncBeginDragTimer.SetTimeoutHdl( LINK(this,SvImpLBox,BeginDragHdl));
94 : // button animation in listbox
95 0 : pActiveButton = 0;
96 0 : pActiveEntry = 0;
97 0 : pActiveTab = 0;
98 :
99 0 : nFlags = 0;
100 0 : nCurTabPos = FIRST_ENTRY_TAB;
101 :
102 0 : aEditTimer.SetTimeout( 800 );
103 0 : aEditTimer.SetTimeoutHdl( LINK(this,SvImpLBox,EditTimerCall) );
104 :
105 0 : nMostRight = -1;
106 0 : pMostRightEntry = 0;
107 0 : nCurUserEvent = 0xffffffff;
108 :
109 0 : bUpdateMode = true;
110 0 : bInVScrollHdl = false;
111 0 : nFlags |= F_FILLING;
112 :
113 0 : bSubLstOpRet = bSubLstOpLR = bContextMenuHandling = bIsCellFocusEnabled = false;
114 0 : }
115 :
116 0 : SvImpLBox::~SvImpLBox()
117 : {
118 0 : aEditTimer.Stop();
119 0 : StopUserEvent();
120 :
121 0 : delete m_pStringSorter;
122 0 : if ( osl_atomic_decrement(&s_nImageRefCount) == 0 )
123 : {
124 0 : DELETEZ(s_pDefCollapsed);
125 0 : DELETEZ(s_pDefExpanded);
126 : }
127 0 : }
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 0 : short SvImpLBox::UpdateContextBmpWidthVector( SvTreeListEntry* pEntry, short nWidth )
156 : {
157 : DBG_ASSERT( pView->pModel, "View and Model aren't valid!" );
158 :
159 0 : sal_uInt16 nDepth = pView->pModel->GetDepth( pEntry );
160 : // initialize vector if necessary
161 0 : std::vector< short >::size_type nSize = aContextBmpWidthVector.size();
162 0 : while ( nDepth > nSize )
163 : {
164 0 : aContextBmpWidthVector.resize( nSize + 1 );
165 0 : aContextBmpWidthVector.at( nSize ) = nWidth;
166 0 : ++nSize;
167 : }
168 0 : if( aContextBmpWidthVector.size() == nDepth )
169 : {
170 0 : aContextBmpWidthVector.resize( nDepth + 1 );
171 0 : aContextBmpWidthVector.at( nDepth ) = 0;
172 : }
173 0 : short nContextBmpWidth = aContextBmpWidthVector[ nDepth ];
174 0 : if( nContextBmpWidth < nWidth )
175 : {
176 0 : aContextBmpWidthVector.at( nDepth ) = nWidth;
177 0 : return nWidth;
178 : }
179 : else
180 0 : 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 0 : void SvImpLBox::UpdateContextBmpWidthMax( SvTreeListEntry* pEntry )
206 : {
207 0 : sal_uInt16 nDepth = pView->pModel->GetDepth( pEntry );
208 0 : if( aContextBmpWidthVector.size() < 1 )
209 0 : return;
210 0 : short nWidth = aContextBmpWidthVector[ nDepth ];
211 0 : 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 0 : void SvImpLBox::CalcCellFocusRect( SvTreeListEntry* pEntry, Rectangle& rRect )
220 : {
221 0 : 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 0 : }
237 :
238 0 : void SvImpLBox::SetStyle( WinBits i_nWinStyle )
239 : {
240 0 : m_nStyle = i_nWinStyle;
241 0 : if ( ( m_nStyle & WB_SIMPLEMODE) && ( aSelEng.GetSelectionMode() == MULTIPLE_SELECTION ) )
242 0 : aSelEng.AddAlways( true );
243 0 : }
244 :
245 0 : void SvImpLBox::SetExtendedWindowBits( ExtendedWinBits _nBits )
246 : {
247 0 : nExtendedWinBits = _nBits;
248 0 : }
249 :
250 : // don't touch the model any more
251 0 : void SvImpLBox::Clear()
252 : {
253 0 : StopUserEvent();
254 0 : pStartEntry = 0;
255 0 : pAnchor = 0;
256 :
257 0 : pActiveButton = 0;
258 0 : pActiveEntry = 0;
259 0 : pActiveTab = 0;
260 :
261 0 : nMostRight = -1;
262 0 : pMostRightEntry = 0;
263 :
264 : // don't touch the cursor any more
265 0 : if( pCursor )
266 : {
267 0 : if( pView->HasFocus() )
268 0 : pView->HideFocus();
269 0 : pCursor = 0;
270 : }
271 0 : aVerSBar.Hide();
272 0 : aVerSBar.SetThumbPos( 0 );
273 0 : Range aRange( 0, 0 );
274 0 : aVerSBar.SetRange( aRange );
275 0 : aOutputSize = pView->Control::GetOutputSizePixel();
276 0 : nFlags &= ~(F_VER_SBARSIZE_WITH_HBAR | F_HOR_SBARSIZE_WITH_VBAR );
277 0 : aHorSBar.Hide();
278 0 : aHorSBar.SetThumbPos( 0 );
279 0 : MapMode aMapMode( pView->GetMapMode());
280 0 : aMapMode.SetOrigin( Point(0,0) );
281 0 : pView->Control::SetMapMode( aMapMode );
282 0 : aHorSBar.SetRange( aRange );
283 0 : aHorSBar.SetSizePixel(Size(aOutputSize.Width(),nHorSBarHeight));
284 0 : pView->SetClipRegion();
285 0 : if( GetUpdateMode() )
286 0 : pView->Invalidate( GetVisibleArea() );
287 0 : nFlags |= F_FILLING;
288 0 : if( !aHorSBar.IsVisible() && !aVerSBar.IsVisible() )
289 0 : aScrBarBox.Hide();
290 :
291 0 : aContextBmpWidthVector.clear();
292 :
293 0 : CallEventListeners( VCLEVENT_LISTBOX_ITEMREMOVED, NULL );
294 0 : }
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( (sal_uLong)pNext == (sal_uLong)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()*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( (sal_uLong)pPrev == (sal_uLong)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 0 : void SvImpLBox::InvalidateEntriesFrom( long nY ) const
548 : {
549 0 : if( !(nFlags & F_IN_PAINT ))
550 : {
551 0 : Rectangle aRect( GetVisibleArea() );
552 0 : aRect.Top() = nY;
553 0 : pView->Invalidate( aRect );
554 : }
555 0 : }
556 :
557 0 : void SvImpLBox::InvalidateEntry( long nY ) const
558 : {
559 0 : if( !(nFlags & F_IN_PAINT ))
560 : {
561 0 : Rectangle aRect( GetVisibleArea() );
562 0 : long nMaxBottom = aRect.Bottom();
563 0 : aRect.Top() = nY;
564 0 : aRect.Bottom() = nY; aRect.Bottom() += pView->GetEntryHeight();
565 0 : if( aRect.Top() > nMaxBottom )
566 0 : return;
567 0 : if( aRect.Bottom() > nMaxBottom )
568 0 : aRect.Bottom() = nMaxBottom;
569 0 : pView->Invalidate( aRect );
570 : }
571 : }
572 :
573 0 : void SvImpLBox::InvalidateEntry( SvTreeListEntry* pEntry )
574 : {
575 0 : if( GetUpdateMode() )
576 : {
577 0 : long nPrev = nMostRight;
578 0 : SetMostRight( pEntry );
579 0 : if( nPrev < nMostRight )
580 0 : ShowVerSBar();
581 : }
582 0 : if( !(nFlags & F_IN_PAINT ))
583 : {
584 0 : bool bHasFocusRect = false;
585 0 : if( pEntry==pCursor && pView->HasFocus() )
586 : {
587 0 : bHasFocusRect = true;
588 0 : ShowCursor( false );
589 : }
590 0 : InvalidateEntry( GetEntryLine( pEntry ) );
591 0 : if( bHasFocusRect )
592 0 : ShowCursor( true );
593 : }
594 0 : }
595 :
596 :
597 0 : void SvImpLBox::RecalcFocusRect()
598 : {
599 0 : if( pView->HasFocus() && pCursor )
600 : {
601 0 : pView->HideFocus();
602 0 : long nY = GetEntryLine( pCursor );
603 0 : Rectangle aRect = pView->GetFocusRect( pCursor, nY );
604 0 : CalcCellFocusRect( pCursor, aRect );
605 0 : Region aOldClip( pView->GetClipRegion());
606 0 : Region aClipRegion( GetClipRegionRect() );
607 0 : pView->SetClipRegion( aClipRegion );
608 0 : pView->ShowFocus( aRect );
609 0 : pView->SetClipRegion( aOldClip );
610 : }
611 0 : }
612 :
613 :
614 : // Sets cursor. When using SingleSelection, the selection is adjusted.
615 :
616 :
617 0 : void SvImpLBox::SetCursor( SvTreeListEntry* pEntry, bool bForceNoSelect )
618 : {
619 0 : SvViewDataEntry* pViewDataNewCur = 0;
620 0 : if( pEntry )
621 0 : pViewDataNewCur= pView->GetViewDataEntry(pEntry);
622 0 : if( pEntry &&
623 0 : pEntry == pCursor &&
624 0 : pViewDataNewCur &&
625 0 : pViewDataNewCur->HasFocus() &&
626 0 : pViewDataNewCur->IsSelected())
627 : {
628 0 : return;
629 : }
630 :
631 : // if this cursor is not selectable, find first visible that is and use it
632 0 : while( pEntry && pViewDataNewCur && !pViewDataNewCur->IsSelectable() )
633 : {
634 0 : pEntry = pView->NextVisible(pEntry);
635 0 : pViewDataNewCur = pEntry ? pView->GetViewDataEntry(pEntry) : 0;
636 : }
637 :
638 0 : SvTreeListEntry* pOldCursor = pCursor;
639 0 : if( pCursor && pEntry != pCursor )
640 : {
641 0 : pView->SetEntryFocus( pCursor, false );
642 0 : if( bSimpleTravel )
643 0 : pView->Select( pCursor, false );
644 0 : pView->HideFocus();
645 : }
646 0 : pCursor = pEntry;
647 0 : if( pCursor )
648 : {
649 0 : if (pViewDataNewCur)
650 0 : pViewDataNewCur->SetFocus( true );
651 0 : if(!bForceNoSelect && bSimpleTravel && !(nFlags & F_DESEL_ALL) && GetUpdateMode())
652 : {
653 0 : pView->Select( pCursor, true );
654 0 : 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 0 : if( pAnchor )
676 : {
677 : DBG_ASSERT(aSelEng.GetSelectionMode() != SINGLE_SELECTION,"Mode?");
678 0 : SetAnchorSelection( pOldCursor, pCursor );
679 : }
680 : }
681 0 : nFlags &= (~F_DESEL_ALL);
682 :
683 0 : pView->OnCurrentEntryChanged();
684 : }
685 :
686 0 : void SvImpLBox::ShowCursor( bool bShow )
687 : {
688 0 : if( !bShow || !pCursor || !pView->HasFocus() )
689 : {
690 0 : Region aOldClip( pView->GetClipRegion());
691 0 : Region aClipRegion( GetClipRegionRect() );
692 0 : pView->SetClipRegion( aClipRegion );
693 0 : pView->HideFocus();
694 0 : pView->SetClipRegion( aOldClip );
695 : }
696 : else
697 : {
698 0 : long nY = GetEntryLine( pCursor );
699 0 : Rectangle aRect = pView->GetFocusRect( pCursor, nY );
700 0 : CalcCellFocusRect( pCursor, aRect );
701 0 : Region aOldClip( pView->GetClipRegion());
702 0 : Region aClipRegion( GetClipRegionRect() );
703 0 : pView->SetClipRegion( aClipRegion );
704 0 : pView->ShowFocus( aRect );
705 0 : pView->SetClipRegion( aOldClip );
706 : }
707 0 : }
708 :
709 :
710 :
711 0 : void SvImpLBox::UpdateAll(
712 : bool bInvalidateCompleteView, bool bUpdateVerScrollBar )
713 : {
714 0 : if( bUpdateVerScrollBar )
715 0 : FindMostRight(0);
716 0 : aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
717 0 : SyncVerThumb();
718 0 : FillView();
719 0 : ShowVerSBar();
720 0 : if( bSimpleTravel && pCursor && pView->HasFocus() )
721 0 : pView->Select( pCursor, true );
722 0 : ShowCursor( true );
723 0 : if( bInvalidateCompleteView )
724 0 : pView->Invalidate();
725 : else
726 0 : pView->Invalidate( GetVisibleArea() );
727 0 : }
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 = (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 0 : Rectangle SvImpLBox::GetClipRegionRect() const
884 : {
885 0 : Point aOrigin( pView->GetMapMode().GetOrigin() );
886 0 : aOrigin.X() *= -1; // conversion document coordinates
887 0 : Rectangle aClipRect( aOrigin, aOutputSize );
888 0 : aClipRect.Bottom()++;
889 0 : return aClipRect;
890 : }
891 :
892 :
893 0 : void SvImpLBox::Paint( const Rectangle& rRect )
894 : {
895 0 : if( !pView->GetVisibleCount() )
896 0 : return;
897 :
898 0 : nFlags |= F_IN_PAINT;
899 :
900 0 : if( nFlags & F_FILLING )
901 : {
902 0 : SvTreeListEntry* pFirst = pView->First();
903 0 : 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),(void*)1);
911 0 : return;
912 : }
913 : }
914 :
915 0 : if( !pStartEntry )
916 : {
917 0 : pStartEntry = pView->First();
918 : }
919 :
920 0 : if( nNodeBmpTabDistance == NODE_BMP_TABDIST_NOTVALID )
921 0 : SetNodeBmpTabDistance();
922 :
923 0 : long nRectHeight = rRect.GetHeight();
924 0 : long nEntryHeight = pView->GetEntryHeight();
925 :
926 : // calculate area for the entries we want to draw
927 0 : sal_uInt16 nStartLine = (sal_uInt16)( rRect.Top() / nEntryHeight );
928 0 : sal_uInt16 nCount = (sal_uInt16)( nRectHeight / nEntryHeight );
929 0 : nCount += 2; // don't miss a row
930 :
931 0 : long nY = nStartLine * nEntryHeight;
932 0 : SvTreeListEntry* pEntry = pStartEntry;
933 0 : while( nStartLine && pEntry )
934 : {
935 0 : pEntry = pView->NextVisible(pEntry);
936 0 : nStartLine--;
937 : }
938 :
939 0 : Region aClipRegion( GetClipRegionRect() );
940 :
941 : // first draw the lines, then clip them!
942 0 : pView->SetClipRegion();
943 0 : if( m_nStyle & ( WB_HASLINES | WB_HASLINESATROOT ) )
944 0 : DrawNet();
945 :
946 0 : pView->SetClipRegion( aClipRegion );
947 :
948 0 : for( sal_uInt16 n=0; n< nCount && pEntry; n++ )
949 : {
950 : /*long nMaxRight=*/
951 0 : pView->PaintEntry1( pEntry, nY, 0xffff, true );
952 0 : nY += nEntryHeight;
953 0 : pEntry = pView->NextVisible(pEntry);
954 : }
955 :
956 0 : if ( !pCursor && ( ( nExtendedWinBits & EWB_NO_AUTO_CURENTRY ) == 0 ) )
957 : {
958 : // do not select if multiselection or explicit set
959 0 : bool bNotSelect = ( aSelEng.GetSelectionMode() == MULTIPLE_SELECTION )
960 0 : || ( ( m_nStyle & WB_NOINITIALSELECTION ) == WB_NOINITIALSELECTION );
961 0 : SetCursor( pStartEntry, bNotSelect );
962 : }
963 :
964 0 : nFlags &= (~F_DESEL_ALL);
965 0 : pView->SetClipRegion();
966 0 : if( !(nFlags & F_PAINTED) )
967 : {
968 0 : nFlags |= F_PAINTED;
969 0 : RepaintScrollBars();
970 : }
971 0 : nFlags &= (~F_IN_PAINT);
972 : }
973 :
974 0 : void SvImpLBox::MakeVisible( SvTreeListEntry* pEntry, bool bMoveToTop )
975 : {
976 0 : if( !pEntry )
977 0 : return;
978 :
979 0 : bool bInView = IsEntryInView( pEntry );
980 :
981 0 : if( bInView && (!bMoveToTop || pStartEntry == pEntry) )
982 0 : 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 0 : void SvImpLBox::DrawNet()
1047 : {
1048 0 : if( pView->GetVisibleCount() < 2 && !pStartEntry->HasChildrenOnDemand() &&
1049 0 : !pStartEntry->HasChildren() )
1050 0 : 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 0 : 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 0 : long nEntryHeight = pView->GetEntryHeight();
1068 0 : long nEntryHeightDIV2 = nEntryHeight / 2;
1069 0 : if( nEntryHeightDIV2 && !(nEntryHeight & 0x0001))
1070 0 : nEntryHeightDIV2--;
1071 :
1072 : SvTreeListEntry* pChild;
1073 0 : SvTreeListEntry* pEntry = pStartEntry;
1074 :
1075 0 : SvLBoxTab* pFirstDynamicTab = pView->GetFirstDynamicTab();
1076 0 : while( pTree->GetDepth( pEntry ) > 0 )
1077 0 : pEntry = pView->GetParent( pEntry );
1078 0 : sal_uInt16 nOffs = (sal_uInt16)(pView->GetVisiblePos( pStartEntry ) -
1079 0 : pView->GetVisiblePos( pEntry ));
1080 0 : long nY = 0;
1081 0 : nY -= ( nOffs * nEntryHeight );
1082 :
1083 : DBG_ASSERT(pFirstDynamicTab,"No Tree!");
1084 :
1085 0 : Color aOldLineColor = pView->GetLineColor();
1086 0 : const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
1087 0 : Color aCol= rStyleSettings.GetFaceColor();
1088 :
1089 0 : if( aCol.IsRGBEqual( pView->GetBackground().GetColor()) )
1090 0 : aCol = rStyleSettings.GetShadowColor();
1091 0 : pView->SetLineColor( aCol );
1092 0 : Point aPos1, aPos2;
1093 : sal_uInt16 nDistance;
1094 0 : sal_uLong nMax = nVisibleCount + nOffs + 1;
1095 :
1096 0 : const Image& rExpandedNodeBitmap = GetExpandedNodeBmp();
1097 :
1098 0 : for( sal_uLong n=0; n< nMax && pEntry; n++ )
1099 : {
1100 0 : if( pView->IsExpanded(pEntry) )
1101 : {
1102 0 : 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 0 : if( !pView->nContextBmpWidthMax )
1106 0 : aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1107 :
1108 0 : aPos1.Y() = nY;
1109 0 : aPos1.Y() += nEntryHeightDIV2;
1110 :
1111 0 : pChild = pView->FirstChild( pEntry );
1112 : DBG_ASSERT(pChild,"Child?");
1113 0 : pChild = pTree->LastSibling( pChild );
1114 0 : nDistance = (sal_uInt16)(pView->GetVisiblePos(pChild) -
1115 0 : pView->GetVisiblePos(pEntry));
1116 0 : aPos2 = aPos1;
1117 0 : aPos2.Y() += nDistance * nEntryHeight;
1118 0 : pView->DrawLine( aPos1, aPos2 );
1119 : }
1120 : // visible in control?
1121 0 : if( n>= nOffs && ((m_nStyle & WB_HASLINESATROOT) || !pTree->IsAtRootDepth(pEntry)))
1122 : {
1123 : // can we recycle aPos1?
1124 0 : if( !pView->IsExpanded(pEntry) )
1125 : {
1126 : // nope
1127 0 : 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 0 : if( !pView->nContextBmpWidthMax )
1131 0 : aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1132 0 : aPos1.Y() = nY;
1133 0 : aPos1.Y() += nEntryHeightDIV2;
1134 0 : aPos2.X() = aPos1.X();
1135 : }
1136 0 : aPos2.Y() = aPos1.Y();
1137 0 : aPos2.X() -= pView->GetIndent();
1138 0 : pView->DrawLine( aPos1, aPos2 );
1139 : }
1140 0 : nY += nEntryHeight;
1141 0 : pEntry = pView->NextVisible(pEntry);
1142 : }
1143 0 : if( m_nStyle & WB_HASLINESATROOT )
1144 : {
1145 0 : pEntry = pView->First();
1146 0 : 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 0 : if( !pView->nContextBmpWidthMax )
1150 0 : aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1151 0 : aPos1.X() -= pView->GetIndent();
1152 0 : aPos1.Y() = GetEntryLine( pEntry );
1153 0 : aPos1.Y() += nEntryHeightDIV2;
1154 0 : pChild = pTree->LastSibling( pEntry );
1155 0 : aPos2.X() = aPos1.X();
1156 0 : aPos2.Y() = GetEntryLine( pChild );
1157 0 : aPos2.Y() += nEntryHeightDIV2;
1158 0 : pView->DrawLine( aPos1, aPos2 );
1159 : }
1160 0 : pView->SetLineColor( aOldLineColor );
1161 : }
1162 :
1163 0 : void SvImpLBox::PositionScrollBars( Size& rSize, sal_uInt16 nMask )
1164 : {
1165 0 : long nOverlap = 0;
1166 :
1167 0 : Size aVerSize( nVerSBarWidth, rSize.Height() );
1168 0 : Size aHorSize( rSize.Width(), nHorSBarHeight );
1169 :
1170 0 : if( nMask & 0x0001 )
1171 0 : aHorSize.Width() -= nVerSBarWidth;
1172 0 : if( nMask & 0x0002 )
1173 0 : aVerSize.Height() -= nHorSBarHeight;
1174 :
1175 0 : aVerSize.Height() += 2 * nOverlap;
1176 0 : Point aVerPos( rSize.Width() - aVerSize.Width() + nOverlap, -nOverlap );
1177 0 : aVerSBar.SetPosSizePixel( aVerPos, aVerSize );
1178 :
1179 0 : aHorSize.Width() += 2 * nOverlap;
1180 0 : Point aHorPos( -nOverlap, rSize.Height() - aHorSize.Height() + nOverlap );
1181 :
1182 0 : aHorSBar.SetPosSizePixel( aHorPos, aHorSize );
1183 :
1184 0 : if( nMask & 0x0001 )
1185 0 : rSize.Width() = aVerPos.X();
1186 0 : if( nMask & 0x0002 )
1187 0 : rSize.Height() = aHorPos.Y();
1188 :
1189 0 : if( (nMask & (0x0001|0x0002)) == (0x0001|0x0002) )
1190 0 : aScrBarBox.Show();
1191 : else
1192 0 : aScrBarBox.Hide();
1193 0 : }
1194 :
1195 : // nResult: Bit0 == VerSBar Bit1 == HorSBar
1196 0 : sal_uInt16 SvImpLBox::AdjustScrollBars( Size& rSize )
1197 : {
1198 0 : long nEntryHeight = pView->GetEntryHeight();
1199 0 : if( !nEntryHeight )
1200 0 : return 0;
1201 :
1202 0 : sal_uInt16 nResult = 0;
1203 :
1204 0 : Size aOSize( pView->Control::GetOutputSizePixel() );
1205 :
1206 0 : const WinBits nWindowStyle = pView->GetStyle();
1207 0 : bool bVerSBar = ( nWindowStyle & WB_VSCROLL ) != 0;
1208 0 : bool bHorBar = false;
1209 0 : long nMaxRight = aOSize.Width(); //GetOutputSize().Width();
1210 0 : Point aOrigin( pView->GetMapMode().GetOrigin() );
1211 0 : aOrigin.X() *= -1;
1212 0 : nMaxRight += aOrigin.X() - 1;
1213 0 : long nVis = nMostRight - aOrigin.X();
1214 0 : if( (nWindowStyle & WB_HSCROLL) &&
1215 0 : (nVis < nMostRight || nMaxRight < nMostRight) )
1216 : {
1217 0 : bHorBar = true;
1218 : }
1219 :
1220 : // number of entries that are not collapsed
1221 0 : sal_uLong nTotalCount = pView->GetVisibleCount();
1222 :
1223 : // number of entries visible within the view
1224 0 : nVisibleCount = aOSize.Height() / nEntryHeight;
1225 :
1226 : // do we need a vertical scrollbar?
1227 0 : if( bVerSBar || nTotalCount > nVisibleCount )
1228 : {
1229 0 : nResult = 1;
1230 0 : nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1231 0 : nMaxRight -= nVerSBarWidth;
1232 0 : if( !bHorBar )
1233 : {
1234 0 : if( (nWindowStyle & WB_HSCROLL) &&
1235 0 : (nVis < nMostRight || nMaxRight < nMostRight) )
1236 0 : bHorBar = true;
1237 : }
1238 : }
1239 :
1240 : // do we need a horizontal scrollbar?
1241 0 : if( bHorBar )
1242 : {
1243 0 : nResult |= 0x0002;
1244 : // the number of entries visible within the view has to be recalculated
1245 : // because the horizontal scrollbar is now visible.
1246 0 : nVisibleCount = (aOSize.Height() - nHorSBarHeight) / nEntryHeight;
1247 : // we might actually need a vertical scrollbar now
1248 0 : if( !(nResult & 0x0001) &&
1249 0 : ((nTotalCount > nVisibleCount) || bVerSBar) )
1250 : {
1251 0 : nResult = 3;
1252 0 : nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1253 : }
1254 : }
1255 :
1256 0 : PositionScrollBars( aOSize, nResult );
1257 :
1258 : // adapt Range, VisibleRange etc.
1259 :
1260 : // refresh output size, in case we have to scroll
1261 0 : Rectangle aRect;
1262 0 : aRect.SetSize( aOSize );
1263 0 : aSelEng.SetVisibleArea( aRect );
1264 :
1265 : // vertical scrollbar
1266 0 : long nTemp = (long)nVisibleCount;
1267 0 : nTemp--;
1268 0 : if( nTemp != aVerSBar.GetVisibleSize() )
1269 : {
1270 0 : if( !bInVScrollHdl )
1271 : {
1272 0 : aVerSBar.SetPageSize( nTemp - 1 );
1273 0 : 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 0 : nTemp = aHorSBar.GetThumbPos();
1284 0 : aHorSBar.SetVisibleSize( aOSize.Width() );
1285 0 : long nNewThumbPos = aHorSBar.GetThumbPos();
1286 0 : Range aRange( aHorSBar.GetRange() );
1287 0 : if( aRange.Max() < nMostRight+25 )
1288 : {
1289 0 : aRange.Max() = nMostRight+25;
1290 0 : aHorSBar.SetRange( aRange );
1291 : }
1292 :
1293 0 : 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 0 : if( nResult & 0x0001 )
1306 0 : aVerSBar.Show();
1307 : else
1308 0 : aVerSBar.Hide();
1309 :
1310 0 : if( nResult & 0x0002 )
1311 0 : aHorSBar.Show();
1312 : else
1313 : {
1314 0 : aHorSBar.Hide();
1315 : }
1316 0 : rSize = aOSize;
1317 0 : return nResult;
1318 : }
1319 :
1320 0 : void SvImpLBox::InitScrollBarBox()
1321 : {
1322 0 : aScrBarBox.SetSizePixel( Size(nVerSBarWidth, nHorSBarHeight) );
1323 0 : Size aSize( pView->Control::GetOutputSizePixel() );
1324 0 : aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth, aSize.Height()-nHorSBarHeight));
1325 0 : }
1326 :
1327 0 : void SvImpLBox::Resize()
1328 : {
1329 0 : aOutputSize = pView->Control::GetOutputSizePixel();
1330 0 : if( aOutputSize.Width() <= 0 || aOutputSize.Height() <= 0 )
1331 0 : return;
1332 0 : nFlags |= F_IN_RESIZE;
1333 0 : InitScrollBarBox();
1334 :
1335 0 : if( pView->GetEntryHeight())
1336 : {
1337 0 : AdjustScrollBars( aOutputSize );
1338 0 : 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 0 : if( aHorSBar.IsVisible())
1343 0 : aHorSBar.Invalidate();
1344 0 : if( aVerSBar.IsVisible())
1345 0 : aVerSBar.Invalidate();
1346 0 : nFlags &= (~(F_IN_RESIZE | F_PAINTED));
1347 : }
1348 :
1349 0 : void SvImpLBox::FillView()
1350 : {
1351 0 : if( !pStartEntry )
1352 : {
1353 0 : sal_uInt16 nVisibleViewCount = (sal_uInt16)(pView->GetVisibleCount());
1354 0 : sal_uInt16 nTempThumb = (sal_uInt16)aVerSBar.GetThumbPos();
1355 0 : if( nTempThumb >= nVisibleViewCount )
1356 0 : nTempThumb = nVisibleViewCount - 1;
1357 0 : pStartEntry = pView->GetEntryAtVisPos(nTempThumb);
1358 : }
1359 0 : if( pStartEntry )
1360 : {
1361 0 : sal_uInt16 nLast = (sal_uInt16)(pView->GetVisiblePos(pView->LastVisible()));
1362 0 : sal_uInt16 nThumb = (sal_uInt16)(pView->GetVisiblePos( pStartEntry ));
1363 0 : sal_uInt16 nCurDispEntries = nLast-nThumb+1;
1364 0 : if( nCurDispEntries < nVisibleCount )
1365 : {
1366 0 : ShowCursor( false );
1367 : // fill window by moving the thumb up incrementally
1368 0 : bool bFound = false;
1369 0 : SvTreeListEntry* pTemp = pStartEntry;
1370 0 : while( nCurDispEntries < nVisibleCount && pTemp )
1371 : {
1372 0 : pTemp = pView->PrevVisible(pStartEntry);
1373 0 : if( pTemp )
1374 : {
1375 0 : nThumb--;
1376 0 : pStartEntry = pTemp;
1377 0 : nCurDispEntries++;
1378 0 : bFound = true;
1379 : }
1380 : }
1381 0 : if( bFound )
1382 : {
1383 0 : aVerSBar.SetThumbPos( nThumb );
1384 0 : ShowCursor( true ); // recalculate focus rectangle
1385 0 : pView->Invalidate();
1386 : }
1387 : }
1388 : }
1389 0 : }
1390 :
1391 :
1392 :
1393 :
1394 0 : void SvImpLBox::ShowVerSBar()
1395 : {
1396 0 : bool bVerBar = ( pView->GetStyle() & WB_VSCROLL ) != 0;
1397 0 : sal_uLong nVis = 0;
1398 0 : if( !bVerBar )
1399 0 : nVis = pView->GetVisibleCount();
1400 0 : if( bVerBar || (nVisibleCount && nVis > (sal_uLong)(nVisibleCount-1)) )
1401 : {
1402 0 : if( !aVerSBar.IsVisible() )
1403 : {
1404 0 : pView->nFocusWidth = -1;
1405 0 : AdjustScrollBars( aOutputSize );
1406 0 : if( GetUpdateMode() )
1407 0 : aVerSBar.Update();
1408 : }
1409 : }
1410 : else
1411 : {
1412 0 : if( aVerSBar.IsVisible() )
1413 : {
1414 0 : pView->nFocusWidth = -1;
1415 0 : AdjustScrollBars( aOutputSize );
1416 : }
1417 : }
1418 :
1419 0 : long nMaxRight = GetOutputSize().Width();
1420 0 : Point aPos( pView->GetMapMode().GetOrigin() );
1421 0 : aPos.X() *= -1; // convert document coordinates
1422 0 : nMaxRight = nMaxRight + aPos.X() - 1;
1423 0 : if( nMaxRight < nMostRight )
1424 : {
1425 0 : if( !aHorSBar.IsVisible() )
1426 : {
1427 0 : pView->nFocusWidth = -1;
1428 0 : AdjustScrollBars( aOutputSize );
1429 0 : if( GetUpdateMode() )
1430 0 : aHorSBar.Update();
1431 : }
1432 : else
1433 : {
1434 0 : Range aRange( aHorSBar.GetRange() );
1435 0 : if( aRange.Max() < nMostRight+25 )
1436 : {
1437 0 : aRange.Max() = nMostRight+25;
1438 0 : aHorSBar.SetRange( aRange );
1439 : }
1440 : else
1441 : {
1442 0 : pView->nFocusWidth = -1;
1443 0 : AdjustScrollBars( aOutputSize );
1444 : }
1445 : }
1446 : }
1447 : else
1448 : {
1449 0 : if( aHorSBar.IsVisible() )
1450 : {
1451 0 : pView->nFocusWidth = -1;
1452 0 : AdjustScrollBars( aOutputSize );
1453 : }
1454 : }
1455 0 : }
1456 :
1457 :
1458 0 : void SvImpLBox::SyncVerThumb()
1459 : {
1460 0 : if( pStartEntry )
1461 : {
1462 0 : long nEntryPos = pView->GetVisiblePos( pStartEntry );
1463 0 : aVerSBar.SetThumbPos( nEntryPos );
1464 : }
1465 : else
1466 0 : aVerSBar.SetThumbPos( 0 );
1467 0 : }
1468 :
1469 0 : bool SvImpLBox::IsEntryInView( SvTreeListEntry* pEntry ) const
1470 : {
1471 : // parent collapsed
1472 0 : if( !pView->IsEntryVisible(pEntry) )
1473 0 : return false;
1474 0 : long nY = GetEntryLine( pEntry );
1475 0 : if( nY < 0 )
1476 0 : return false;
1477 0 : long nMax = nVisibleCount * pView->GetEntryHeight();
1478 0 : if( nY >= nMax )
1479 0 : return false;
1480 0 : return true;
1481 : }
1482 :
1483 :
1484 0 : long SvImpLBox::GetEntryLine( SvTreeListEntry* pEntry ) const
1485 : {
1486 0 : if(!pStartEntry )
1487 0 : return -1; // invisible position
1488 :
1489 0 : long nFirstVisPos = pView->GetVisiblePos( pStartEntry );
1490 0 : long nEntryVisPos = pView->GetVisiblePos( pEntry );
1491 0 : nFirstVisPos = nEntryVisPos - nFirstVisPos;
1492 0 : nFirstVisPos *= pView->GetEntryHeight();
1493 0 : return nFirstVisPos;
1494 : }
1495 :
1496 0 : void SvImpLBox::SetEntryHeight( short /* nHeight */ )
1497 : {
1498 0 : SetNodeBmpYOffset( GetExpandedNodeBmp() );
1499 0 : SetNodeBmpYOffset( GetCollapsedNodeBmp() );
1500 0 : if(!pView->HasViewData()) // are we within the Clear?
1501 : {
1502 0 : Size aSize = pView->Control::GetOutputSizePixel();
1503 0 : AdjustScrollBars( aSize );
1504 : }
1505 : else
1506 : {
1507 0 : Resize();
1508 0 : if( GetUpdateMode() )
1509 0 : pView->Invalidate();
1510 : }
1511 0 : }
1512 :
1513 :
1514 :
1515 : // ***********************************************************************
1516 : // Callback Functions
1517 : // ***********************************************************************
1518 :
1519 0 : void SvImpLBox::EntryExpanded( SvTreeListEntry* pEntry )
1520 : {
1521 : // SelAllDestrAnch( false, true ); //DeselectAll();
1522 0 : if( GetUpdateMode() )
1523 : {
1524 0 : ShowCursor( false );
1525 0 : long nY = GetEntryLine( pEntry );
1526 0 : if( IsLineVisible(nY) )
1527 : {
1528 0 : InvalidateEntriesFrom( nY );
1529 0 : FindMostRight( pEntry, 0 );
1530 : }
1531 0 : aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
1532 : // if we expanded before the thumb, the thumb's position has to be
1533 : // corrected
1534 0 : SyncVerThumb();
1535 0 : ShowVerSBar();
1536 0 : ShowCursor( true );
1537 : }
1538 0 : }
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 0 : void SvImpLBox::SetNodeBmpYOffset( const Image& rBmp )
1608 : {
1609 0 : Size aSize;
1610 0 : nYoffsNodeBmp = pView->GetHeightOffset( rBmp, aSize );
1611 0 : nNodeBmpWidth = aSize.Width();
1612 0 : }
1613 :
1614 0 : void SvImpLBox::SetNodeBmpTabDistance()
1615 : {
1616 0 : nNodeBmpTabDistance = -pView->GetIndent();
1617 0 : if( pView->nContextBmpWidthMax )
1618 : {
1619 : // only if the first dynamic tab is centered (we currently assume that)
1620 0 : Size aSize = GetExpandedNodeBmp().GetSizePixel();
1621 0 : nNodeBmpTabDistance -= aSize.Width() / 2;
1622 : }
1623 0 : }
1624 :
1625 :
1626 : // corrects the cursor when using SingleSelection
1627 :
1628 0 : void SvImpLBox::EntrySelected( SvTreeListEntry* pEntry, bool bSelect )
1629 : {
1630 0 : if( nFlags & F_IGNORE_SELECT )
1631 0 : return;
1632 :
1633 0 : nFlags &= (~F_DESEL_ALL);
1634 0 : if( bSelect &&
1635 0 : aSelEng.GetSelectionMode() == SINGLE_SELECTION &&
1636 0 : pEntry != pCursor )
1637 : {
1638 0 : SetCursor( pEntry );
1639 : DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?");
1640 : }
1641 :
1642 0 : if( GetUpdateMode() && pView->IsEntryVisible(pEntry) )
1643 : {
1644 0 : long nY = GetEntryLine( pEntry );
1645 0 : if( IsLineVisible( nY ) )
1646 : {
1647 0 : ShowCursor( false );
1648 0 : pView->PaintEntry1( pEntry, nY, 0xffff ); // because of ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
1649 0 : 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 0 : void SvImpLBox::EntryInserted( SvTreeListEntry* pEntry )
1841 : {
1842 0 : if( GetUpdateMode() )
1843 : {
1844 0 : SvTreeListEntry* pParent = (SvTreeListEntry*)pTree->GetParent(pEntry);
1845 0 : if (pParent && pTree->GetChildList(pParent).size() == 1)
1846 : // draw plus sign
1847 0 : pTree->InvalidateEntry( pParent );
1848 :
1849 0 : if( !pView->IsEntryVisible( pEntry ) )
1850 0 : return;
1851 0 : int bDeselAll = nFlags & F_DESEL_ALL;
1852 0 : if( bDeselAll )
1853 0 : SelAllDestrAnch( false, true );
1854 : else
1855 0 : DestroyAnchor();
1856 : // nFlags &= (~F_DESEL_ALL);
1857 : // ShowCursor( false ); // if cursor is moved lower
1858 0 : long nY = GetEntryLine( pEntry );
1859 0 : bool bEntryVisible = IsLineVisible( nY );
1860 0 : if( bEntryVisible )
1861 : {
1862 0 : ShowCursor( false ); // if cursor is moved lower
1863 0 : nY -= pView->GetEntryHeight(); // because of lines
1864 0 : InvalidateEntriesFrom( nY );
1865 : }
1866 0 : 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 0 : else if( !pStartEntry )
1882 0 : pView->Invalidate();
1883 :
1884 0 : SetMostRight( pEntry );
1885 0 : aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1));
1886 0 : SyncVerThumb(); // if something was inserted before the thumb
1887 0 : ShowVerSBar();
1888 0 : ShowCursor( true );
1889 0 : if( pStartEntry != pView->First() && (nFlags & F_FILLING) )
1890 0 : 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 = (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 : // the entry can still be invalid!
2053 0 : if( !pEntry || !pView->GetViewData( pEntry ))
2054 0 : return;
2055 :
2056 0 : long nY = GetEntryLine( pEntry );
2057 : // Node-Button?
2058 0 : if( ButtonDownCheckExpand( rMEvt, pEntry, nY ) )
2059 0 : return;
2060 :
2061 0 : if( !EntryReallyHit(pEntry,aPos,nY))
2062 0 : return;
2063 :
2064 0 : SvLBoxItem* pXItem = pView->GetItem( pEntry, aPos.X() );
2065 0 : if( pXItem )
2066 : {
2067 0 : SvLBoxTab* pXTab = pView->GetTab( pEntry, pXItem );
2068 0 : if ( !rMEvt.IsMod1() && !rMEvt.IsMod2() && rMEvt.IsLeft() && pXTab->IsEditable()
2069 0 : && pEntry == pView->FirstSelected() && NULL == pView->NextSelected( pEntry ) )
2070 : // #i8234# FirstSelected() and NextSelected() ensures, that inplace editing is only triggered, when only one entry is selected
2071 0 : nFlags |= F_START_EDITTIMER;
2072 0 : if ( !pView->IsSelected( pEntry ) )
2073 0 : nFlags &= ~F_START_EDITTIMER;
2074 : }
2075 :
2076 :
2077 0 : if( (rMEvt.GetClicks() % 2) == 0 )
2078 : {
2079 0 : nFlags &= (~F_START_EDITTIMER);
2080 0 : pView->pHdlEntry = pEntry;
2081 0 : if( pView->DoubleClickHdl() )
2082 : {
2083 : // if the entry was deleted within the handler
2084 0 : pEntry = GetClickedEntry( aPos );
2085 0 : if( !pEntry )
2086 0 : return;
2087 0 : if( pEntry != pView->pHdlEntry )
2088 : {
2089 : // select anew & bye
2090 0 : if( !bSimpleTravel && !aSelEng.IsAlwaysAdding())
2091 0 : SelAllDestrAnch( false, true ); // DeselectAll();
2092 0 : SetCursor( pEntry );
2093 :
2094 0 : return;
2095 : }
2096 0 : if( pEntry->HasChildren() || pEntry->HasChildrenOnDemand() )
2097 : {
2098 0 : if( pView->IsExpanded(pEntry) )
2099 0 : pView->Collapse( pEntry );
2100 : else
2101 0 : pView->Expand( pEntry );
2102 0 : if( pEntry == pCursor ) // only if Entryitem was clicked
2103 : // (Nodebutton is not an Entryitem!)
2104 0 : pView->Select( pCursor, true );
2105 0 : return;
2106 : }
2107 : }
2108 : }
2109 : else
2110 : {
2111 : // CheckButton? (TreeListBox: Check + Info)
2112 0 : if( ButtonDownCheckCtrl(rMEvt, pEntry, nY) == true)
2113 0 : return;
2114 : // Inplace-Editing?
2115 : }
2116 0 : if ( aSelEng.GetSelectionMode() != NO_SELECTION )
2117 0 : aSelEng.SelMouseButtonDown( rMEvt );
2118 : }
2119 :
2120 0 : void SvImpLBox::MouseButtonUp( const MouseEvent& rMEvt)
2121 : {
2122 0 : if ( !ButtonUpCheckCtrl( rMEvt ) && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
2123 0 : aSelEng.SelMouseButtonUp( rMEvt );
2124 0 : EndScroll();
2125 0 : if( nFlags & F_START_EDITTIMER )
2126 : {
2127 0 : nFlags &= (~F_START_EDITTIMER);
2128 0 : aEditClickPos = rMEvt.GetPosPixel();
2129 0 : aEditTimer.Start();
2130 : }
2131 :
2132 0 : return;
2133 : }
2134 :
2135 0 : void SvImpLBox::MouseMove( const MouseEvent& rMEvt)
2136 : {
2137 0 : SvTreeListEntry* pEntry = GetClickedEntry( rMEvt.GetPosPixel() );
2138 0 : if ( !MouseMoveCheckCtrl( rMEvt, pEntry ) && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
2139 0 : aSelEng.SelMouseMove( rMEvt );
2140 0 : return;
2141 : }
2142 :
2143 0 : bool SvImpLBox::KeyInput( const KeyEvent& rKEvt)
2144 : {
2145 0 : aEditTimer.Stop();
2146 0 : const KeyCode& rKeyCode = rKEvt.GetKeyCode();
2147 :
2148 0 : if( rKeyCode.IsMod2() )
2149 0 : return false; // don't evaluate Alt key
2150 :
2151 0 : nFlags &= (~F_FILLING);
2152 :
2153 0 : if( !pCursor )
2154 0 : pCursor = pStartEntry;
2155 0 : if( !pCursor )
2156 0 : return false;
2157 :
2158 0 : bool bKeyUsed = true;
2159 :
2160 0 : sal_uInt16 nDelta = (sal_uInt16)aVerSBar.GetPageSize();
2161 0 : sal_uInt16 aCode = rKeyCode.GetCode();
2162 :
2163 0 : bool bShift = rKeyCode.IsShift();
2164 0 : bool bMod1 = rKeyCode.IsMod1();
2165 :
2166 : SvTreeListEntry* pNewCursor;
2167 :
2168 0 : const WinBits nWindowStyle = pView->GetStyle();
2169 0 : switch( aCode )
2170 : {
2171 : case KEY_UP:
2172 0 : if( !IsEntryInView( pCursor ) )
2173 0 : MakeVisible( pCursor );
2174 :
2175 0 : pNewCursor = pCursor;
2176 0 : do
2177 : {
2178 0 : pNewCursor = pView->PrevVisible(pNewCursor);
2179 0 : } while( pNewCursor && !IsSelectable(pNewCursor) );
2180 :
2181 0 : if ( pNewCursor )
2182 : // new entry selected -> reset current tab position to first tab
2183 0 : nCurTabPos = FIRST_ENTRY_TAB;
2184 : // if there is no next entry, take the current one
2185 : // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
2186 : // the cursor key
2187 0 : if ( !pNewCursor && pCursor )
2188 0 : pNewCursor = pCursor;
2189 :
2190 0 : if( pNewCursor )
2191 : {
2192 0 : aSelEng.CursorPosChanging( bShift, bMod1 );
2193 0 : SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2194 0 : if( !IsEntryInView( pNewCursor ) )
2195 0 : KeyUp( false );
2196 : }
2197 0 : break;
2198 :
2199 : case KEY_DOWN:
2200 0 : if( !IsEntryInView( pCursor ) )
2201 0 : MakeVisible( pCursor );
2202 :
2203 0 : pNewCursor = pCursor;
2204 0 : do
2205 : {
2206 0 : pNewCursor = pView->NextVisible(pNewCursor);
2207 0 : } while( pNewCursor && !IsSelectable(pNewCursor) );
2208 :
2209 0 : if ( pNewCursor )
2210 : // new entry selected -> reset current tab position to first tab
2211 0 : nCurTabPos = FIRST_ENTRY_TAB;
2212 :
2213 : // if there is no next entry, take the current one
2214 : // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
2215 : // the cursor key
2216 : // 06.09.20001 - 83416 - frank.schoenheit@sun.com
2217 0 : if ( !pNewCursor && pCursor )
2218 0 : pNewCursor = pCursor;
2219 :
2220 0 : if( pNewCursor )
2221 : {
2222 0 : aSelEng.CursorPosChanging( bShift, bMod1 );
2223 0 : if( IsEntryInView( pNewCursor ) )
2224 0 : SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2225 : else
2226 : {
2227 0 : if( pCursor )
2228 0 : pView->Select( pCursor, false );
2229 0 : KeyDown( false );
2230 0 : SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2231 : }
2232 : }
2233 : else
2234 0 : KeyDown( false ); // because scrollbar range might still
2235 : // allow scrolling
2236 0 : break;
2237 :
2238 : case KEY_RIGHT:
2239 : {
2240 0 : if( bSubLstOpLR && IsNowExpandable() )
2241 0 : pView->Expand( pCursor );
2242 0 : else if ( bIsCellFocusEnabled && pCursor )
2243 : {
2244 0 : if ( nCurTabPos < ( pView->TabCount() - 1 /*!2*/ ) )
2245 : {
2246 0 : ++nCurTabPos;
2247 0 : ShowCursor( true );
2248 0 : CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
2249 : }
2250 : }
2251 0 : else if( nWindowStyle & WB_HSCROLL )
2252 : {
2253 0 : long nThumb = aHorSBar.GetThumbPos();
2254 0 : nThumb += aHorSBar.GetLineSize();
2255 0 : long nOldThumb = aHorSBar.GetThumbPos();
2256 0 : aHorSBar.SetThumbPos( nThumb );
2257 0 : nThumb = nOldThumb;
2258 0 : nThumb -= aHorSBar.GetThumbPos();
2259 0 : nThumb *= -1;
2260 0 : if( nThumb )
2261 : {
2262 0 : KeyLeftRight( nThumb );
2263 0 : EndScroll();
2264 : }
2265 : }
2266 : else
2267 0 : bKeyUsed = false;
2268 0 : break;
2269 : }
2270 :
2271 : case KEY_LEFT:
2272 : {
2273 0 : if ( bIsCellFocusEnabled && pCursor )
2274 : {
2275 0 : if ( nCurTabPos > FIRST_ENTRY_TAB )
2276 : {
2277 0 : --nCurTabPos;
2278 0 : ShowCursor( true );
2279 0 : CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
2280 : }
2281 : }
2282 0 : else if ( nWindowStyle & WB_HSCROLL )
2283 : {
2284 0 : long nThumb = aHorSBar.GetThumbPos();
2285 0 : nThumb -= aHorSBar.GetLineSize();
2286 0 : long nOldThumb = aHorSBar.GetThumbPos();
2287 0 : aHorSBar.SetThumbPos( nThumb );
2288 0 : nThumb = nOldThumb;
2289 0 : nThumb -= aHorSBar.GetThumbPos();
2290 0 : if( nThumb )
2291 : {
2292 0 : KeyLeftRight( -nThumb );
2293 0 : EndScroll();
2294 : }
2295 0 : else if( bSubLstOpLR )
2296 : {
2297 0 : if( IsExpandable() && pView->IsExpanded( pCursor ) )
2298 0 : pView->Collapse( pCursor );
2299 : else
2300 : {
2301 0 : pNewCursor = pView->GetParent( pCursor );
2302 0 : if( pNewCursor )
2303 0 : SetCursor( pNewCursor );
2304 : }
2305 : }
2306 : }
2307 0 : else if( bSubLstOpLR && IsExpandable() )
2308 0 : pView->Collapse( pCursor );
2309 : else
2310 0 : bKeyUsed = false;
2311 0 : break;
2312 : }
2313 :
2314 : case KEY_PAGEUP:
2315 0 : if( !bMod1 )
2316 : {
2317 0 : pNewCursor = pView->PrevVisible(pCursor, nDelta);
2318 :
2319 0 : while( nDelta && pNewCursor && !IsSelectable(pNewCursor) )
2320 : {
2321 0 : pNewCursor = pView->NextVisible(pNewCursor);
2322 0 : nDelta--;
2323 : }
2324 :
2325 0 : if( nDelta )
2326 : {
2327 : DBG_ASSERT(pNewCursor&&(sal_uLong)pNewCursor!=(sal_uLong)pCursor,"Cursor?");
2328 0 : aSelEng.CursorPosChanging( bShift, bMod1 );
2329 0 : if( IsEntryInView( pNewCursor ) )
2330 0 : SetCursor( pNewCursor );
2331 : else
2332 : {
2333 0 : SetCursor( pNewCursor );
2334 0 : KeyUp( true );
2335 : }
2336 : }
2337 : }
2338 : else
2339 0 : bKeyUsed = false;
2340 0 : break;
2341 :
2342 : case KEY_PAGEDOWN:
2343 0 : if( !bMod1 )
2344 : {
2345 0 : pNewCursor= pView->NextVisible(pCursor, nDelta);
2346 :
2347 0 : while( nDelta && pNewCursor && !IsSelectable(pNewCursor) )
2348 : {
2349 0 : pNewCursor = pView->PrevVisible(pNewCursor);
2350 0 : nDelta--;
2351 : }
2352 :
2353 0 : if( nDelta && pNewCursor )
2354 : {
2355 : DBG_ASSERT(pNewCursor&&(sal_uLong)pNewCursor!=(sal_uLong)pCursor,"Cursor?");
2356 0 : aSelEng.CursorPosChanging( bShift, bMod1 );
2357 0 : if( IsEntryInView( pNewCursor ) )
2358 0 : SetCursor( pNewCursor );
2359 : else
2360 : {
2361 0 : SetCursor( pNewCursor );
2362 0 : KeyDown( true );
2363 : }
2364 : }
2365 : else
2366 0 : KeyDown( false ); // see also: KEY_DOWN
2367 : }
2368 : else
2369 0 : bKeyUsed = false;
2370 0 : break;
2371 :
2372 : case KEY_SPACE:
2373 0 : if ( pView->GetSelectionMode() != NO_SELECTION )
2374 : {
2375 0 : if ( bMod1 )
2376 : {
2377 0 : if ( pView->GetSelectionMode() == MULTIPLE_SELECTION && !bShift )
2378 : // toggle selection
2379 0 : pView->Select( pCursor, !pView->IsSelected( pCursor ) );
2380 : }
2381 0 : else if ( !bShift /*&& !bMod1*/ )
2382 : {
2383 0 : if ( aSelEng.IsAddMode() )
2384 : {
2385 : // toggle selection
2386 0 : pView->Select( pCursor, !pView->IsSelected( pCursor ) );
2387 : }
2388 0 : else if ( !pView->IsSelected( pCursor ) )
2389 : {
2390 0 : SelAllDestrAnch( false );
2391 0 : pView->Select( pCursor, true );
2392 : }
2393 : else
2394 0 : bKeyUsed = false;
2395 : }
2396 : else
2397 0 : bKeyUsed = false;
2398 : }
2399 : else
2400 0 : bKeyUsed = false;
2401 0 : break;
2402 :
2403 : case KEY_RETURN:
2404 0 : if( bSubLstOpRet && IsExpandable() )
2405 : {
2406 0 : if( pView->IsExpanded( pCursor ) )
2407 0 : pView->Collapse( pCursor );
2408 : else
2409 0 : pView->Expand( pCursor );
2410 : }
2411 : else
2412 0 : bKeyUsed = false;
2413 0 : break;
2414 :
2415 : case KEY_F2:
2416 0 : if( !bShift && !bMod1 )
2417 : {
2418 0 : aEditClickPos = Point( -1, -1 );
2419 0 : EditTimerCall( 0 );
2420 : }
2421 : else
2422 0 : bKeyUsed = false;
2423 0 : break;
2424 :
2425 : case KEY_F8:
2426 0 : if( bShift && pView->GetSelectionMode()==MULTIPLE_SELECTION &&
2427 0 : !(m_nStyle & WB_SIMPLEMODE))
2428 : {
2429 0 : if( aSelEng.IsAlwaysAdding() )
2430 0 : aSelEng.AddAlways( false );
2431 : else
2432 0 : aSelEng.AddAlways( true );
2433 : }
2434 : else
2435 0 : bKeyUsed = false;
2436 0 : break;
2437 :
2438 : case KEY_ADD:
2439 0 : if( pCursor )
2440 : {
2441 0 : if( !pView->IsExpanded(pCursor))
2442 0 : pView->Expand( pCursor );
2443 0 : if( bMod1 )
2444 : {
2445 0 : sal_uInt16 nRefDepth = pTree->GetDepth( pCursor );
2446 0 : SvTreeListEntry* pCur = pTree->Next( pCursor );
2447 0 : while( pCur && pTree->GetDepth(pCur) > nRefDepth )
2448 : {
2449 0 : if( pCur->HasChildren() && !pView->IsExpanded(pCur))
2450 0 : pView->Expand( pCur );
2451 0 : pCur = pTree->Next( pCur );
2452 : }
2453 : }
2454 : }
2455 : else
2456 0 : bKeyUsed = false;
2457 0 : break;
2458 :
2459 : case KEY_A:
2460 0 : if( bMod1 )
2461 0 : SelAllDestrAnch( true );
2462 : else
2463 0 : bKeyUsed = false;
2464 0 : break;
2465 :
2466 : case KEY_SUBTRACT:
2467 0 : if( pCursor )
2468 : {
2469 0 : if( pView->IsExpanded(pCursor))
2470 0 : pView->Collapse( pCursor );
2471 0 : if( bMod1 )
2472 : {
2473 : // collapse all parents until we get to the root
2474 0 : SvTreeListEntry* pParentToCollapse = (SvTreeListEntry*)pTree->GetRootLevelParent(pCursor);
2475 0 : if( pParentToCollapse )
2476 : {
2477 : sal_uInt16 nRefDepth;
2478 : // special case explorer: if the root only has a single
2479 : // entry, don't collapse the root entry
2480 0 : if (pTree->GetChildList(0).size() < 2)
2481 : {
2482 0 : nRefDepth = 1;
2483 0 : pParentToCollapse = pCursor;
2484 0 : while( pTree->GetParent(pParentToCollapse) &&
2485 0 : pTree->GetDepth( pTree->GetParent(pParentToCollapse)) > 0)
2486 : {
2487 0 : pParentToCollapse = pTree->GetParent(pParentToCollapse);
2488 : }
2489 : }
2490 : else
2491 0 : nRefDepth = 0;
2492 :
2493 0 : if( pView->IsExpanded(pParentToCollapse) )
2494 0 : pView->Collapse( pParentToCollapse );
2495 0 : SvTreeListEntry* pCur = pTree->Next( pParentToCollapse );
2496 0 : while( pCur && pTree->GetDepth(pCur) > nRefDepth )
2497 : {
2498 0 : if( pCur->HasChildren() && pView->IsExpanded(pCur) )
2499 0 : pView->Collapse( pCur );
2500 0 : pCur = pTree->Next( pCur );
2501 : }
2502 : }
2503 : }
2504 : }
2505 : else
2506 0 : bKeyUsed = false;
2507 0 : break;
2508 :
2509 : case KEY_DIVIDE :
2510 0 : if( bMod1 )
2511 0 : SelAllDestrAnch( true );
2512 : else
2513 0 : bKeyUsed = false;
2514 0 : break;
2515 :
2516 : case KEY_COMMA :
2517 0 : if( bMod1 )
2518 0 : SelAllDestrAnch( false );
2519 : else
2520 0 : bKeyUsed = false;
2521 0 : break;
2522 :
2523 : case KEY_HOME :
2524 0 : pNewCursor = pView->GetModel()->First();
2525 :
2526 0 : while( pNewCursor && !IsSelectable(pNewCursor) )
2527 : {
2528 0 : pNewCursor = pView->NextVisible(pNewCursor);
2529 : }
2530 :
2531 0 : if( pNewCursor && pNewCursor != pCursor )
2532 : {
2533 : // SelAllDestrAnch( false );
2534 0 : aSelEng.CursorPosChanging( bShift, bMod1 );
2535 0 : SetCursor( pNewCursor );
2536 0 : if( !IsEntryInView( pNewCursor ) )
2537 0 : MakeVisible( pNewCursor );
2538 : }
2539 : else
2540 0 : bKeyUsed = false;
2541 0 : break;
2542 :
2543 : case KEY_END :
2544 0 : pNewCursor = pView->GetModel()->Last();
2545 :
2546 0 : while( pNewCursor && !IsSelectable(pNewCursor) )
2547 : {
2548 0 : pNewCursor = pView->PrevVisible(pNewCursor);
2549 : }
2550 :
2551 0 : if( pNewCursor && pNewCursor != pCursor)
2552 : {
2553 : // SelAllDestrAnch( false );
2554 0 : aSelEng.CursorPosChanging( bShift, bMod1 );
2555 0 : SetCursor( pNewCursor );
2556 0 : if( !IsEntryInView( pNewCursor ) )
2557 0 : MakeVisible( pNewCursor );
2558 : }
2559 : else
2560 0 : bKeyUsed = false;
2561 0 : break;
2562 :
2563 : case KEY_ESCAPE:
2564 : case KEY_TAB:
2565 : case KEY_DELETE:
2566 : case KEY_BACKSPACE:
2567 : // must not be handled because this quits dialogs and does other magic things...
2568 : // if there are other single keys which should not be handled, they can be added here
2569 0 : bKeyUsed = false;
2570 0 : break;
2571 :
2572 : default:
2573 : // is there any reason why we should eat the events here? The only place where this is called
2574 : // is from SvTreeListBox::KeyInput. If we set bKeyUsed to true here, then the key input
2575 : // is just silenced. However, we want SvLBox::KeyInput to get a chance, to do the QuickSelection
2576 : // handling.
2577 : // (The old code here which intentionally set bKeyUsed to sal_True said this was because of "quick search"
2578 : // handling, but actually there was no quick search handling anymore. We just re-implemented it.)
2579 : // #i31275# / 2009-06-16 / frank.schoenheit@sun.com
2580 0 : bKeyUsed = false;
2581 0 : break;
2582 : }
2583 0 : return bKeyUsed;
2584 : }
2585 :
2586 0 : void SvImpLBox::GetFocus()
2587 : {
2588 0 : if( pCursor )
2589 : {
2590 0 : pView->SetEntryFocus( pCursor, true );
2591 0 : ShowCursor( true );
2592 : // auskommentiert wg. deselectall
2593 : // if( bSimpleTravel && !pView->IsSelected(pCursor) )
2594 : // pView->Select( pCursor, true );
2595 : }
2596 0 : if( m_nStyle & WB_HIDESELECTION )
2597 : {
2598 0 : SvTreeListEntry* pEntry = pView->FirstSelected();
2599 0 : while( pEntry )
2600 : {
2601 0 : InvalidateEntry( pEntry );
2602 0 : pEntry = pView->NextSelected( pEntry );
2603 : }
2604 : }
2605 0 : }
2606 :
2607 0 : void SvImpLBox::LoseFocus()
2608 : {
2609 0 : aEditTimer.Stop();
2610 0 : if( pCursor )
2611 0 : pView->SetEntryFocus( pCursor,false );
2612 0 : ShowCursor( false );
2613 :
2614 0 : if( m_nStyle & WB_HIDESELECTION )
2615 : {
2616 0 : SvTreeListEntry* pEntry = pView->FirstSelected();
2617 0 : while( pEntry )
2618 : {
2619 0 : InvalidateEntry( pEntry );
2620 0 : pEntry = pView->NextSelected( pEntry );
2621 : }
2622 : }
2623 0 : }
2624 :
2625 :
2626 : // ********************************************************************
2627 : // SelectionEngine
2628 : // ********************************************************************
2629 :
2630 0 : void SvImpLBox::SelectEntry( SvTreeListEntry* pEntry, bool bSelect )
2631 : {
2632 0 : pView->Select( pEntry, bSelect );
2633 0 : }
2634 :
2635 0 : ImpLBSelEng::ImpLBSelEng( SvImpLBox* pImpl, SelectionEngine* pSEng,
2636 0 : SvTreeListBox* pV )
2637 : {
2638 0 : pImp = pImpl;
2639 0 : pSelEng = pSEng;
2640 0 : pView = pV;
2641 0 : }
2642 :
2643 0 : ImpLBSelEng::~ImpLBSelEng()
2644 : {
2645 0 : }
2646 :
2647 0 : void ImpLBSelEng::BeginDrag()
2648 : {
2649 0 : pImp->BeginDrag();
2650 0 : }
2651 :
2652 0 : void ImpLBSelEng::CreateAnchor()
2653 : {
2654 0 : pImp->pAnchor = pImp->pCursor;
2655 0 : }
2656 :
2657 0 : void ImpLBSelEng::DestroyAnchor()
2658 : {
2659 0 : pImp->pAnchor = 0;
2660 0 : }
2661 :
2662 0 : bool ImpLBSelEng::SetCursorAtPoint(const Point& rPoint, bool bDontSelectAtCursor)
2663 : {
2664 0 : SvTreeListEntry* pNewCursor = pImp->MakePointVisible( rPoint );
2665 0 : if( pNewCursor != pImp->pCursor )
2666 0 : pImp->BeginScroll();
2667 :
2668 0 : if( pNewCursor )
2669 : {
2670 : // at SimpleTravel, the SetCursor is selected and the select handler is
2671 : // called
2672 : //if( !bDontSelectAtCursor && !pImp->bSimpleTravel )
2673 : // pImp->SelectEntry( pNewCursor, true );
2674 0 : pImp->SetCursor( pNewCursor, bDontSelectAtCursor );
2675 0 : return true;
2676 : }
2677 0 : return false;
2678 : }
2679 :
2680 0 : bool ImpLBSelEng::IsSelectionAtPoint( const Point& rPoint )
2681 : {
2682 0 : SvTreeListEntry* pEntry = pImp->MakePointVisible( rPoint );
2683 0 : if( pEntry )
2684 0 : return pView->IsSelected(pEntry);
2685 0 : return false;
2686 : }
2687 :
2688 0 : void ImpLBSelEng::DeselectAtPoint( const Point& rPoint )
2689 : {
2690 0 : SvTreeListEntry* pEntry = pImp->MakePointVisible( rPoint );
2691 0 : if( !pEntry )
2692 0 : return;
2693 0 : pImp->SelectEntry( pEntry, false );
2694 : }
2695 :
2696 0 : void ImpLBSelEng::DeselectAll()
2697 : {
2698 0 : pImp->SelAllDestrAnch( false, false ); // don't reset SelectionEngine!
2699 0 : pImp->nFlags &= (~F_DESEL_ALL);
2700 0 : }
2701 :
2702 : // ***********************************************************************
2703 : // Selection
2704 : // ***********************************************************************
2705 :
2706 0 : void SvImpLBox::SetAnchorSelection(SvTreeListEntry* pOldCursor,SvTreeListEntry* pNewCursor)
2707 : {
2708 : SvTreeListEntry* pEntry;
2709 0 : sal_uLong nAnchorVisPos = pView->GetVisiblePos( pAnchor );
2710 0 : sal_uLong nOldVisPos = pView->GetVisiblePos( pOldCursor );
2711 0 : sal_uLong nNewVisPos = pView->GetVisiblePos( pNewCursor );
2712 :
2713 0 : if( nOldVisPos > nAnchorVisPos ||
2714 0 : ( nAnchorVisPos==nOldVisPos && nNewVisPos > nAnchorVisPos) )
2715 : {
2716 0 : if( nNewVisPos > nOldVisPos )
2717 : {
2718 0 : pEntry = pOldCursor;
2719 0 : while( pEntry && pEntry != pNewCursor )
2720 : {
2721 0 : pView->Select( pEntry, true );
2722 0 : pEntry = pView->NextVisible(pEntry);
2723 : }
2724 0 : if( pEntry )
2725 0 : pView->Select( pEntry, true );
2726 0 : return;
2727 : }
2728 :
2729 0 : if( nNewVisPos < nAnchorVisPos )
2730 : {
2731 0 : pEntry = pAnchor;
2732 0 : while( pEntry && pEntry != pOldCursor )
2733 : {
2734 0 : pView->Select( pEntry, false );
2735 0 : pEntry = pView->NextVisible(pEntry);
2736 : }
2737 0 : if( pEntry )
2738 0 : pView->Select( pEntry, false );
2739 :
2740 0 : pEntry = pNewCursor;
2741 0 : while( pEntry && pEntry != pAnchor )
2742 : {
2743 0 : pView->Select( pEntry, true );
2744 0 : pEntry = pView->NextVisible(pEntry);
2745 : }
2746 0 : if( pEntry )
2747 0 : pView->Select( pEntry, true );
2748 0 : return;
2749 : }
2750 :
2751 0 : if( nNewVisPos < nOldVisPos )
2752 : {
2753 0 : pEntry = pNewCursor;
2754 0 : pEntry = pView->NextVisible(pEntry);
2755 0 : while( pEntry && pEntry != pOldCursor )
2756 : {
2757 0 : pView->Select( pEntry, false );
2758 0 : pEntry = pView->NextVisible(pEntry);
2759 : }
2760 0 : if( pEntry )
2761 0 : pView->Select( pEntry, false );
2762 0 : return;
2763 : }
2764 : }
2765 : else
2766 : {
2767 0 : if( nNewVisPos < nOldVisPos ) // enlarge selection
2768 : {
2769 0 : pEntry = pNewCursor;
2770 0 : while( pEntry && pEntry != pOldCursor )
2771 : {
2772 0 : pView->Select( pEntry, true );
2773 0 : pEntry = pView->NextVisible(pEntry);
2774 : }
2775 0 : if( pEntry )
2776 0 : pView->Select( pEntry, true );
2777 0 : return;
2778 : }
2779 :
2780 0 : if( nNewVisPos > nAnchorVisPos )
2781 : {
2782 0 : pEntry = pOldCursor;
2783 0 : while( pEntry && pEntry != pAnchor )
2784 : {
2785 0 : pView->Select( pEntry, false );
2786 0 : pEntry = pView->NextVisible(pEntry);
2787 : }
2788 0 : if( pEntry )
2789 0 : pView->Select( pEntry, false );
2790 0 : pEntry = pAnchor;
2791 0 : while( pEntry && pEntry != pNewCursor )
2792 : {
2793 0 : pView->Select( pEntry, true );
2794 0 : pEntry = pView->NextVisible(pEntry);
2795 : }
2796 0 : if( pEntry )
2797 0 : pView->Select( pEntry, true );
2798 0 : return;
2799 : }
2800 :
2801 0 : if( nNewVisPos > nOldVisPos )
2802 : {
2803 0 : pEntry = pOldCursor;
2804 0 : while( pEntry && pEntry != pNewCursor )
2805 : {
2806 0 : pView->Select( pEntry, false );
2807 0 : pEntry = pView->NextVisible(pEntry);
2808 : }
2809 0 : return;
2810 : }
2811 : }
2812 : }
2813 :
2814 0 : void SvImpLBox::SelAllDestrAnch(
2815 : bool bSelect, bool bDestroyAnchor, bool bSingleSelToo )
2816 : {
2817 : SvTreeListEntry* pEntry;
2818 0 : nFlags &= (~F_DESEL_ALL);
2819 0 : if( bSelect && bSimpleTravel )
2820 : {
2821 0 : if( pCursor && !pView->IsSelected( pCursor ))
2822 : {
2823 0 : pView->Select( pCursor, true );
2824 : }
2825 0 : return;
2826 : }
2827 0 : if( !bSelect && pView->GetSelectionCount() == 0 )
2828 : {
2829 0 : if( bSimpleTravel && ( !GetUpdateMode() || !pCursor) )
2830 0 : nFlags |= F_DESEL_ALL;
2831 0 : return;
2832 : }
2833 0 : if( bSelect && pView->GetSelectionCount() == pView->GetEntryCount())
2834 0 : return;
2835 0 : if( !bSingleSelToo && bSimpleTravel )
2836 0 : return;
2837 :
2838 0 : if( !bSelect && pView->GetSelectionCount()==1 && pCursor &&
2839 0 : pView->IsSelected( pCursor ))
2840 : {
2841 0 : pView->Select( pCursor, false );
2842 0 : if( bDestroyAnchor )
2843 0 : DestroyAnchor(); // delete anchor & reset SelectionEngine
2844 : else
2845 0 : pAnchor = 0; // always delete internal anchor
2846 0 : return;
2847 : }
2848 :
2849 0 : if( bSimpleTravel && !pCursor && !GetUpdateMode() )
2850 0 : nFlags |= F_DESEL_ALL;
2851 :
2852 0 : ShowCursor( false );
2853 0 : bool bUpdate = GetUpdateMode();
2854 :
2855 0 : nFlags |= F_IGNORE_SELECT; // EntryInserted should not do anything
2856 0 : pEntry = pTree->First();
2857 0 : while( pEntry )
2858 : {
2859 0 : if( pView->Select( pEntry, bSelect ) )
2860 : {
2861 0 : if( bUpdate && pView->IsEntryVisible(pEntry) )
2862 : {
2863 0 : long nY = GetEntryLine( pEntry );
2864 0 : if( IsLineVisible( nY ) )
2865 0 : pView->PaintEntry1( pEntry, nY, 0xffff ); // because of ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
2866 : }
2867 : }
2868 0 : pEntry = pTree->Next( pEntry );
2869 : }
2870 0 : nFlags &= ~F_IGNORE_SELECT;
2871 :
2872 0 : if( bDestroyAnchor )
2873 0 : DestroyAnchor(); // delete anchor & reset SelectionEngine
2874 : else
2875 0 : pAnchor = 0; // always delete internal anchor
2876 0 : ShowCursor( true );
2877 : }
2878 :
2879 0 : void SvImpLBox::SetSelectionMode( SelectionMode eSelMode )
2880 : {
2881 0 : aSelEng.SetSelectionMode( eSelMode);
2882 0 : if( eSelMode == SINGLE_SELECTION )
2883 0 : bSimpleTravel = true;
2884 : else
2885 0 : bSimpleTravel = false;
2886 0 : if( (m_nStyle & WB_SIMPLEMODE) && (eSelMode == MULTIPLE_SELECTION) )
2887 0 : aSelEng.AddAlways( true );
2888 0 : }
2889 :
2890 : // ***********************************************************************
2891 : // Drag & Drop
2892 : // ***********************************************************************
2893 :
2894 0 : void SvImpLBox::SetDragDropMode( DragDropMode eDDMode )
2895 : {
2896 0 : if( eDDMode && eDDMode != SV_DRAGDROP_APP_DROP )
2897 : {
2898 0 : aSelEng.ExpandSelectionOnMouseMove( false );
2899 0 : aSelEng.EnableDrag( true );
2900 : }
2901 : else
2902 : {
2903 0 : aSelEng.ExpandSelectionOnMouseMove( true );
2904 0 : aSelEng.EnableDrag( false );
2905 : }
2906 0 : }
2907 :
2908 0 : void SvImpLBox::BeginDrag()
2909 : {
2910 0 : nFlags &= (~F_FILLING);
2911 0 : if( !bAsyncBeginDrag )
2912 : {
2913 0 : BeginScroll();
2914 0 : pView->StartDrag( 0, aSelEng.GetMousePosPixel() );
2915 0 : EndScroll();
2916 : }
2917 : else
2918 : {
2919 0 : aAsyncBeginDragPos = aSelEng.GetMousePosPixel();
2920 0 : aAsyncBeginDragTimer.Start();
2921 : }
2922 0 : }
2923 :
2924 0 : IMPL_LINK_NOARG(SvImpLBox, BeginDragHdl)
2925 : {
2926 0 : pView->StartDrag( 0, aAsyncBeginDragPos );
2927 0 : return 0;
2928 : }
2929 :
2930 0 : void SvImpLBox::PaintDDCursor( SvTreeListEntry* pInsertionPos )
2931 : {
2932 : long nY;
2933 0 : if( pInsertionPos )
2934 : {
2935 0 : nY = GetEntryLine( pInsertionPos );
2936 0 : nY += pView->GetEntryHeight();
2937 : }
2938 : else
2939 0 : nY = 1;
2940 0 : RasterOp eOldOp = pView->GetRasterOp();
2941 0 : pView->SetRasterOp( ROP_INVERT );
2942 0 : Color aOldLineColor = pView->GetLineColor();
2943 0 : pView->SetLineColor( Color( COL_BLACK ) );
2944 0 : pView->DrawLine( Point( 0, nY ), Point( aOutputSize.Width(), nY ) );
2945 0 : pView->SetLineColor( aOldLineColor );
2946 0 : pView->SetRasterOp( eOldOp );
2947 0 : }
2948 :
2949 : // Delete all submenus of a PopupMenu, recursively
2950 0 : static void lcl_DeleteSubPopups(PopupMenu* pPopup)
2951 : {
2952 0 : for(sal_uInt16 i = 0; i < pPopup->GetItemCount(); i++)
2953 : {
2954 0 : PopupMenu* pSubPopup = pPopup->GetPopupMenu( pPopup->GetItemId( i ));
2955 0 : if(pSubPopup)
2956 : {
2957 0 : lcl_DeleteSubPopups(pSubPopup);
2958 0 : delete pSubPopup;
2959 : }
2960 : }
2961 0 : }
2962 :
2963 0 : void SvImpLBox::Command( const CommandEvent& rCEvt )
2964 : {
2965 0 : sal_uInt16 nCommand = rCEvt.GetCommand();
2966 :
2967 0 : if( nCommand == COMMAND_CONTEXTMENU )
2968 0 : aEditTimer.Stop();
2969 :
2970 : // scroll mouse event?
2971 0 : if( ( ( nCommand == COMMAND_WHEEL ) || ( nCommand == COMMAND_STARTAUTOSCROLL ) || ( nCommand == COMMAND_AUTOSCROLL ) )
2972 0 : && pView->HandleScrollCommand( rCEvt, &aHorSBar, &aVerSBar ) )
2973 0 : return;
2974 :
2975 0 : if( bContextMenuHandling && nCommand == COMMAND_CONTEXTMENU )
2976 : {
2977 0 : Point aPopupPos;
2978 0 : bool bClickedIsFreePlace = false;
2979 0 : std::stack<SvTreeListEntry*> aSelRestore;
2980 :
2981 0 : if( rCEvt.IsMouseEvent() )
2982 : { // change selection, if mouse position doesn't fit to selection
2983 :
2984 0 : aPopupPos = rCEvt.GetMousePosPixel();
2985 :
2986 0 : SvTreeListEntry* pClickedEntry = GetEntry( aPopupPos );
2987 0 : if( pClickedEntry )
2988 : { // mouse in non empty area
2989 0 : bool bClickedIsSelected = false;
2990 :
2991 : // collect the currently selected entries
2992 0 : SvTreeListEntry* pSelected = pView->FirstSelected();
2993 0 : while( pSelected )
2994 : {
2995 0 : bClickedIsSelected |= ( pClickedEntry == pSelected );
2996 0 : pSelected = pView->NextSelected( pSelected );
2997 : }
2998 :
2999 : // if the entry which the user clicked at is not selected
3000 0 : if( !bClickedIsSelected )
3001 : { // deselect all other and select the clicked one
3002 0 : pView->SelectAll( false );
3003 0 : pView->SetCursor( pClickedEntry );
3004 : }
3005 : }
3006 0 : else if( aSelEng.GetSelectionMode() == SINGLE_SELECTION )
3007 : {
3008 0 : bClickedIsFreePlace = true;
3009 0 : sal_Int32 nSelectedEntries = pView->GetSelectionCount();
3010 0 : SvTreeListEntry* pSelected = pView->FirstSelected();
3011 0 : for(sal_uInt16 nSel = 0; nSel < nSelectedEntries; nSel++ )
3012 : {
3013 0 : aSelRestore.push(pSelected);
3014 0 : pSelected = pView->NextSelected( pSelected );
3015 : }
3016 0 : pView->SelectAll( false );
3017 : }
3018 : else
3019 : { // deselect all
3020 0 : pView->SelectAll( false );
3021 : }
3022 :
3023 :
3024 : }
3025 : else
3026 : { // key event (or at least no mouse event)
3027 0 : sal_Int32 nSelectionCount = pView->GetSelectionCount();
3028 :
3029 0 : if( nSelectionCount )
3030 : { // now always take first visible as base for positioning the menu
3031 0 : SvTreeListEntry* pSelected = pView->FirstSelected();
3032 0 : while( pSelected )
3033 : {
3034 0 : if( IsEntryInView( pSelected ) )
3035 0 : break;
3036 :
3037 0 : pSelected = pView->NextSelected( pSelected );
3038 : }
3039 :
3040 0 : if( !pSelected )
3041 : {
3042 : // no one was visible
3043 0 : pSelected = pView->FirstSelected();
3044 0 : pView->MakeVisible( pSelected );
3045 : }
3046 :
3047 0 : aPopupPos = pView->GetFocusRect( pSelected, pView->GetEntryPosition( pSelected ).Y() ).Center();
3048 : }
3049 : else
3050 0 : aPopupPos = Point( 0, 0 );
3051 : }
3052 :
3053 0 : PopupMenu* pPopup = pView->CreateContextMenu();
3054 :
3055 0 : if( pPopup )
3056 : {
3057 : // do action for selected entry in popup menu
3058 0 : sal_uInt16 nMenuAction = pPopup->Execute( pView, aPopupPos );
3059 0 : if ( nMenuAction )
3060 0 : pView->ExcecuteContextMenuAction( nMenuAction );
3061 0 : lcl_DeleteSubPopups(pPopup);
3062 0 : delete pPopup;
3063 : }
3064 :
3065 0 : if( bClickedIsFreePlace )
3066 : {
3067 0 : while(!aSelRestore.empty())
3068 : {
3069 0 : SvTreeListEntry* pEntry = aSelRestore.top();
3070 : //#i19717# the entry is maybe already deleted
3071 0 : bool bFound = false;
3072 0 : for(sal_uLong nEntry = 0; nEntry < pView->GetEntryCount(); nEntry++)
3073 0 : if(pEntry == pView->GetEntry(nEntry))
3074 : {
3075 0 : bFound = true;
3076 0 : break;
3077 : }
3078 0 : if(bFound)
3079 0 : SetCurEntry( pEntry );
3080 0 : aSelRestore.pop();
3081 : }
3082 0 : }
3083 : }
3084 : #ifndef NOCOMMAND
3085 : else
3086 : {
3087 0 : const Point& rPos = rCEvt.GetMousePosPixel();
3088 0 : if( rPos.X() < aOutputSize.Width() && rPos.Y() < aOutputSize.Height() )
3089 0 : aSelEng.Command( rCEvt );
3090 : }
3091 : #endif
3092 : }
3093 :
3094 0 : void SvImpLBox::BeginScroll()
3095 : {
3096 0 : if( !(nFlags & F_IN_SCROLLING))
3097 : {
3098 0 : pView->NotifyBeginScroll();
3099 0 : nFlags |= F_IN_SCROLLING;
3100 : }
3101 0 : }
3102 :
3103 0 : void SvImpLBox::EndScroll()
3104 : {
3105 0 : if( nFlags & F_IN_SCROLLING)
3106 : {
3107 0 : pView->NotifyEndScroll();
3108 0 : nFlags &= (~F_IN_SCROLLING);
3109 : }
3110 0 : }
3111 :
3112 :
3113 0 : Rectangle SvImpLBox::GetVisibleArea() const
3114 : {
3115 0 : Point aPos( pView->GetMapMode().GetOrigin() );
3116 0 : aPos.X() *= -1;
3117 0 : Rectangle aRect( aPos, aOutputSize );
3118 0 : return aRect;
3119 : }
3120 :
3121 0 : void SvImpLBox::Invalidate()
3122 : {
3123 0 : pView->SetClipRegion();
3124 0 : }
3125 :
3126 0 : void SvImpLBox::SetCurEntry( SvTreeListEntry* pEntry )
3127 : {
3128 0 : if ( ( aSelEng.GetSelectionMode() != SINGLE_SELECTION )
3129 0 : && ( aSelEng.GetSelectionMode() != NO_SELECTION )
3130 : )
3131 0 : SelAllDestrAnch( false, true, false );
3132 0 : if ( pEntry )
3133 0 : MakeVisible( pEntry );
3134 0 : SetCursor( pEntry );
3135 0 : if ( pEntry && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
3136 0 : pView->Select( pEntry, true );
3137 0 : }
3138 :
3139 0 : IMPL_LINK_NOARG(SvImpLBox, EditTimerCall)
3140 : {
3141 0 : if( pView->IsInplaceEditingEnabled() )
3142 : {
3143 0 : bool bIsMouseTriggered = aEditClickPos.X() >= 0;
3144 0 : if ( bIsMouseTriggered )
3145 : {
3146 0 : Point aCurrentMousePos = pView->GetPointerPosPixel();
3147 0 : if ( ( std::abs( aCurrentMousePos.X() - aEditClickPos.X() ) > 5 )
3148 0 : || ( std::abs( aCurrentMousePos.Y() - aEditClickPos.Y() ) > 5 )
3149 : )
3150 : {
3151 0 : return 0L;
3152 : }
3153 : }
3154 :
3155 0 : SvTreeListEntry* pEntry = GetCurEntry();
3156 0 : if( pEntry )
3157 : {
3158 0 : ShowCursor( false );
3159 0 : pView->ImplEditEntry( pEntry );
3160 0 : ShowCursor( true );
3161 : }
3162 : }
3163 0 : return 0;
3164 : }
3165 :
3166 0 : bool SvImpLBox::RequestHelp( const HelpEvent& rHEvt )
3167 : {
3168 0 : if( rHEvt.GetMode() & HELPMODE_QUICK )
3169 : {
3170 0 : Point aPos( pView->ScreenToOutputPixel( rHEvt.GetMousePosPixel() ));
3171 0 : if( !GetVisibleArea().IsInside( aPos ))
3172 0 : return false;
3173 :
3174 0 : SvTreeListEntry* pEntry = GetEntry( aPos );
3175 0 : if( pEntry )
3176 : {
3177 : // recalculate text rectangle
3178 : SvLBoxTab* pTab;
3179 0 : SvLBoxString* pItem = (SvLBoxString*)(pView->GetItem( pEntry, aPos.X(), &pTab ));
3180 0 : if (!pItem || pItem->GetType() != SV_ITEM_ID_LBOXSTRING)
3181 0 : return false;
3182 :
3183 0 : aPos = GetEntryPosition( pEntry );
3184 0 : aPos.X() = pView->GetTabPos( pEntry, pTab ); //pTab->GetPos();
3185 0 : Size aSize( pItem->GetSize( pView, pEntry ) );
3186 0 : SvLBoxTab* pNextTab = NextTab( pTab );
3187 0 : bool bItemClipped = false;
3188 : // is the item cut off by its right neighbor?
3189 0 : if( pNextTab && pView->GetTabPos(pEntry,pNextTab) < aPos.X()+aSize.Width() )
3190 : {
3191 0 : aSize.Width() = pNextTab->GetPos() - pTab->GetPos();
3192 0 : bItemClipped = true;
3193 : }
3194 0 : Rectangle aItemRect( aPos, aSize );
3195 :
3196 0 : Rectangle aViewRect( GetVisibleArea() );
3197 :
3198 0 : if( bItemClipped || !aViewRect.IsInside( aItemRect ) )
3199 : {
3200 : // clip the right edge of the item at the edge of the view
3201 : //if( aItemRect.Right() > aViewRect.Right() )
3202 : // aItemRect.Right() = aViewRect.Right();
3203 :
3204 0 : Point aPt = pView->OutputToScreenPixel( aItemRect.TopLeft() );
3205 0 : aItemRect.Left() = aPt.X();
3206 0 : aItemRect.Top() = aPt.Y();
3207 0 : aPt = pView->OutputToScreenPixel( aItemRect.BottomRight() );
3208 0 : aItemRect.Right() = aPt.X();
3209 0 : aItemRect.Bottom() = aPt.Y();
3210 :
3211 : Help::ShowQuickHelp( pView, aItemRect,
3212 0 : pItem->GetText(), QUICKHELP_LEFT | QUICKHELP_VCENTER );
3213 0 : return true;
3214 : }
3215 : }
3216 : }
3217 0 : return false;
3218 : }
3219 :
3220 0 : SvLBoxTab* SvImpLBox::NextTab( SvLBoxTab* pTab )
3221 : {
3222 0 : sal_uInt16 nTabCount = pView->TabCount();
3223 0 : if( nTabCount <= 1 )
3224 0 : return 0;
3225 0 : for( sal_uInt16 nTab=0; nTab < (nTabCount-1); nTab++)
3226 : {
3227 0 : if( pView->aTabs[nTab]==pTab )
3228 0 : return (SvLBoxTab*)(pView->aTabs[nTab+1]);
3229 : }
3230 0 : return 0;
3231 : }
3232 :
3233 0 : void SvImpLBox::EndSelection()
3234 : {
3235 0 : DestroyAnchor();
3236 0 : nFlags &= ~F_START_EDITTIMER;
3237 0 : }
3238 :
3239 0 : void SvImpLBox::RepaintScrollBars()
3240 : {
3241 0 : }
3242 :
3243 0 : void SvImpLBox::SetUpdateMode( bool bMode )
3244 : {
3245 0 : if( bUpdateMode != bMode )
3246 : {
3247 0 : bUpdateMode = bMode;
3248 0 : if( bUpdateMode )
3249 0 : UpdateAll( false );
3250 : }
3251 0 : }
3252 :
3253 0 : bool SvImpLBox::SetMostRight( SvTreeListEntry* pEntry )
3254 : {
3255 0 : if( pView->nTreeFlags & TREEFLAG_RECALCTABS )
3256 : {
3257 0 : nFlags |= F_IGNORE_CHANGED_TABS;
3258 0 : pView->SetTabs();
3259 0 : nFlags &= ~F_IGNORE_CHANGED_TABS;
3260 : }
3261 :
3262 0 : sal_uInt16 nLastTab = pView->aTabs.size() - 1;
3263 0 : sal_uInt16 nLastItem = pEntry->ItemCount() - 1;
3264 0 : if( !pView->aTabs.empty() && nLastItem != USHRT_MAX )
3265 : {
3266 0 : if( nLastItem < nLastTab )
3267 0 : nLastTab = nLastItem;
3268 :
3269 0 : SvLBoxTab* pTab = pView->aTabs[ nLastTab ];
3270 0 : SvLBoxItem* pItem = pEntry->GetItem( nLastTab );
3271 :
3272 0 : long nTabPos = pView->GetTabPos( pEntry, pTab );
3273 :
3274 0 : long nMaxRight = GetOutputSize().Width();
3275 0 : Point aPos( pView->GetMapMode().GetOrigin() );
3276 0 : aPos.X() *= -1; // conversion document coordinates
3277 0 : nMaxRight = nMaxRight + aPos.X() - 1;
3278 :
3279 0 : long nNextTab = nTabPos < nMaxRight ? nMaxRight : nMaxRight + 50;
3280 0 : long nTabWidth = nNextTab - nTabPos + 1;
3281 0 : long nItemSize = pItem->GetSize(pView,pEntry).Width();
3282 0 : long nOffset = pTab->CalcOffset( nItemSize, nTabWidth );
3283 :
3284 0 : long nRight = nTabPos + nOffset + nItemSize;
3285 0 : if( nRight > nMostRight )
3286 : {
3287 0 : nMostRight = nRight;
3288 0 : pMostRightEntry = pEntry;
3289 0 : return true;
3290 : }
3291 : }
3292 0 : return false;
3293 : }
3294 :
3295 0 : void SvImpLBox::FindMostRight( SvTreeListEntry* pEntryToIgnore )
3296 : {
3297 0 : nMostRight = -1;
3298 0 : pMostRightEntry = 0;
3299 0 : if( !pView->GetModel() )
3300 0 : return;
3301 :
3302 0 : SvTreeListEntry* pEntry = (SvTreeListEntry*)pView->FirstVisible();
3303 0 : while( pEntry )
3304 : {
3305 0 : if( pEntry != pEntryToIgnore )
3306 0 : SetMostRight( pEntry );
3307 0 : pEntry = (SvTreeListEntry*)pView->NextVisible( pEntry );
3308 : }
3309 : }
3310 :
3311 0 : void SvImpLBox::FindMostRight( SvTreeListEntry* pParent, SvTreeListEntry* pEntryToIgnore )
3312 : {
3313 0 : if( !pParent )
3314 0 : FindMostRight( pEntryToIgnore );
3315 : else
3316 0 : FindMostRight_Impl( pParent, pEntryToIgnore );
3317 0 : }
3318 :
3319 0 : void SvImpLBox::FindMostRight_Impl( SvTreeListEntry* pParent, SvTreeListEntry* pEntryToIgnore )
3320 : {
3321 0 : SvTreeListEntries& rList = pTree->GetChildList( pParent );
3322 :
3323 0 : size_t nCount = rList.size();
3324 0 : for( size_t nCur = 0; nCur < nCount; nCur++ )
3325 : {
3326 0 : SvTreeListEntry* pChild = &rList[nCur];
3327 0 : if( pChild != pEntryToIgnore )
3328 : {
3329 0 : SetMostRight( pChild );
3330 0 : if( pChild->HasChildren() && pView->IsExpanded( pChild ))
3331 0 : FindMostRight_Impl( pChild, pEntryToIgnore );
3332 : }
3333 : }
3334 0 : }
3335 :
3336 0 : void SvImpLBox::NotifyTabsChanged()
3337 : {
3338 0 : if( GetUpdateMode() && !(nFlags & F_IGNORE_CHANGED_TABS ) &&
3339 0 : nCurUserEvent == 0xffffffff )
3340 : {
3341 0 : nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpLBox,MyUserEvent),(void*)0);
3342 : }
3343 0 : }
3344 :
3345 0 : bool SvImpLBox::IsExpandable() const
3346 : {
3347 0 : return pCursor->HasChildren() || pCursor->HasChildrenOnDemand();
3348 : }
3349 :
3350 0 : bool SvImpLBox::IsNowExpandable() const
3351 : {
3352 0 : return IsExpandable() && !pView->IsExpanded( pCursor );
3353 : }
3354 :
3355 0 : IMPL_LINK(SvImpLBox,MyUserEvent,void*, pArg )
3356 : {
3357 0 : nCurUserEvent = 0xffffffff;
3358 0 : if( !pArg )
3359 : {
3360 0 : pView->Invalidate();
3361 0 : pView->Update();
3362 : }
3363 : else
3364 : {
3365 0 : FindMostRight( 0 );
3366 0 : ShowVerSBar();
3367 0 : pView->Invalidate( GetVisibleArea() );
3368 : }
3369 0 : return 0;
3370 : }
3371 :
3372 :
3373 0 : void SvImpLBox::StopUserEvent()
3374 : {
3375 0 : if( nCurUserEvent != 0xffffffff )
3376 : {
3377 0 : Application::RemoveUserEvent( nCurUserEvent );
3378 0 : nCurUserEvent = 0xffffffff;
3379 : }
3380 0 : }
3381 :
3382 0 : void SvImpLBox::ShowFocusRect( const SvTreeListEntry* pEntry )
3383 : {
3384 0 : if( pEntry )
3385 : {
3386 0 : long nY = GetEntryLine( (SvTreeListEntry*)pEntry );
3387 0 : Rectangle aRect = pView->GetFocusRect( (SvTreeListEntry*)pEntry, nY );
3388 0 : Region aOldClip( pView->GetClipRegion());
3389 0 : Region aClipRegion( GetClipRegionRect() );
3390 0 : pView->SetClipRegion( aClipRegion );
3391 0 : pView->ShowFocus( aRect );
3392 0 : pView->SetClipRegion( aOldClip );
3393 :
3394 : }
3395 : else
3396 : {
3397 0 : pView->HideFocus();
3398 : }
3399 0 : }
3400 :
3401 :
3402 0 : void SvImpLBox::implInitDefaultNodeImages()
3403 : {
3404 0 : if ( s_pDefCollapsed )
3405 : // assume that all or nothing is initialized
3406 0 : return;
3407 :
3408 0 : s_pDefCollapsed = new Image( SvtResId( RID_IMG_TREENODE_COLLAPSED ) );
3409 0 : s_pDefExpanded = new Image( SvtResId( RID_IMG_TREENODE_EXPANDED ) );
3410 : }
3411 :
3412 :
3413 0 : const Image& SvImpLBox::GetDefaultExpandedNodeImage( )
3414 : {
3415 0 : implInitDefaultNodeImages();
3416 0 : return *s_pDefExpanded;
3417 : }
3418 :
3419 :
3420 0 : const Image& SvImpLBox::GetDefaultCollapsedNodeImage( )
3421 : {
3422 0 : implInitDefaultNodeImages();
3423 0 : return *s_pDefCollapsed;
3424 : }
3425 :
3426 :
3427 0 : void SvImpLBox::CallEventListeners( sal_uLong nEvent, void* pData )
3428 : {
3429 0 : if ( pView )
3430 0 : pView->CallImplEventListeners( nEvent, pData);
3431 0 : }
3432 :
3433 :
3434 :
3435 0 : bool SvImpLBox::SetCurrentTabPos( sal_uInt16 _nNewPos )
3436 : {
3437 0 : bool bRet = false;
3438 :
3439 0 : if ( pView && _nNewPos < ( pView->TabCount() - 2 ) )
3440 : {
3441 0 : nCurTabPos = _nNewPos;
3442 0 : ShowCursor( true );
3443 0 : bRet = true;
3444 : }
3445 :
3446 0 : return bRet;
3447 : }
3448 :
3449 :
3450 :
3451 0 : bool SvImpLBox::IsSelectable( const SvTreeListEntry* pEntry )
3452 : {
3453 0 : if( pEntry )
3454 : {
3455 0 : SvViewDataEntry* pViewDataNewCur = pView->GetViewDataEntry(const_cast<SvTreeListEntry*>(pEntry));
3456 0 : return (pViewDataNewCur == 0) || pViewDataNewCur->IsSelectable();
3457 : }
3458 : else
3459 : {
3460 0 : return false;
3461 : }
3462 : }
3463 :
3464 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|