merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / contnr / svimpbox.cxx
blob0ca5e45fcee84a2bb236e84db1532ee81ad09cc7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svimpbox.cxx,v $
10 * $Revision: 1.57 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
33 #include <vcl/svapp.hxx>
34 #include <vcl/salnativewidgets.hxx>
36 #ifndef _HELP_HXX
37 #include <vcl/help.hxx>
38 #endif
39 #include <tabbar.hxx>
41 #ifndef _STACK_
42 #include <stack>
43 #endif
45 #define _SVTREEBX_CXX
46 #include <svtools/svtreebx.hxx>
47 #include <svtools/svlbox.hxx>
48 #include <svimpbox.hxx>
49 #include <rtl/instance.hxx>
50 #include <svtools/svtdata.hxx>
52 #ifndef _SVTOOLS_HRC
53 #include <svtools/svtools.hrc>
54 #endif
56 // #102891# --------------------
57 #ifndef _UNOTOOLS_PROCESSFACTORY_HXX
58 #include <comphelper/processfactory.hxx>
59 #endif
61 #define NODE_BMP_TABDIST_NOTVALID -2000000
62 #define FIRST_ENTRY_TAB 1
64 // #i27063# (pl), #i32300# (pb) never access VCL after DeInitVCL - also no destructors
65 Image* SvImpLBox::s_pDefCollapsed = NULL;
66 Image* SvImpLBox::s_pDefExpanded = NULL;
67 Image* SvImpLBox::s_pDefCollapsedHC = NULL;
68 Image* SvImpLBox::s_pDefExpandedHC = NULL;
69 sal_Int32 SvImpLBox::s_nImageRefCount = 0;
71 SvImpLBox::SvImpLBox( SvTreeListBox* pLBView, SvLBoxTreeList* pLBTree, WinBits nWinStyle) :
73 pTabBar( NULL ),
74 aVerSBar( pLBView, WB_DRAG | WB_VSCROLL ),
75 aHorSBar( pLBView, WB_DRAG | WB_HSCROLL ),
76 aScrBarBox( pLBView ),
77 aOutputSize( 0, 0 ),
78 aSelEng( pLBView, (FunctionSet*)0 ),
79 aFctSet( this, &aSelEng, pLBView ),
80 nExtendedWinBits( 0 ),
81 bAreChildrenTransient( sal_True ),
82 pIntlWrapper( NULL ) // #102891# -----------------------
84 osl_incrementInterlockedCount(&s_nImageRefCount);
85 pView = pLBView;
86 pTree = pLBTree;
87 aSelEng.SetFunctionSet( (FunctionSet*)&aFctSet );
88 aSelEng.ExpandSelectionOnMouseMove( FALSE );
89 SetWindowBits( nWinStyle );
90 SetSelectionMode( SINGLE_SELECTION );
91 SetDragDropMode( 0 );
93 aVerSBar.SetScrollHdl( LINK( this, SvImpLBox, ScrollUpDownHdl ) );
94 aHorSBar.SetScrollHdl( LINK( this, SvImpLBox, ScrollLeftRightHdl ) );
95 aHorSBar.SetEndScrollHdl( LINK( this, SvImpLBox, EndScrollHdl ) );
96 aVerSBar.SetEndScrollHdl( LINK( this, SvImpLBox, EndScrollHdl ) );
97 aVerSBar.SetRange( Range(0,0) );
98 aVerSBar.Hide();
99 aHorSBar.SetRange( Range(0,0) );
100 aHorSBar.SetPageSize( 24 ); // Pixel
101 aHorSBar.SetLineSize( 8 ); // Pixel
103 nHorSBarHeight = (short)aHorSBar.GetSizePixel().Height();
104 nVerSBarWidth = (short)aVerSBar.GetSizePixel().Width();
106 pStartEntry = 0;
107 pCursor = 0;
108 pAnchor = 0;
109 nVisibleCount = 0; // Anzahl Daten-Zeilen im Control
110 nNodeBmpTabDistance = NODE_BMP_TABDIST_NOTVALID;
111 nYoffsNodeBmp = 0;
112 nNodeBmpWidth = 0;
114 bAsyncBeginDrag = FALSE;
115 aAsyncBeginDragTimer.SetTimeout( 0 );
116 aAsyncBeginDragTimer.SetTimeoutHdl( LINK(this,SvImpLBox,BeginDragHdl));
117 // Button-Animation in Listbox
118 pActiveButton = 0;
119 pActiveEntry = 0;
120 pActiveTab = 0;
122 nFlags = 0;
123 nCurTabPos = FIRST_ENTRY_TAB;
125 aEditTimer.SetTimeout( 800 );
126 aEditTimer.SetTimeoutHdl( LINK(this,SvImpLBox,EditTimerCall) );
128 nMostRight = -1;
129 pMostRightEntry = 0;
130 nCurUserEvent = 0xffffffff;
132 bUpdateMode = TRUE;
133 bInVScrollHdl = FALSE;
134 nFlags |= F_FILLING;
136 bSubLstOpRet = bSubLstOpLR = bContextMenuHandling = bIsCellFocusEnabled = FALSE;
139 SvImpLBox::~SvImpLBox()
141 aEditTimer.Stop();
142 StopUserEvent();
144 // #102891# ---------------------
145 if( pIntlWrapper )
146 delete pIntlWrapper;
147 if ( osl_decrementInterlockedCount(&s_nImageRefCount) == 0 )
149 DELETEZ(s_pDefCollapsed);
150 DELETEZ(s_pDefExpanded);
151 DELETEZ(s_pDefCollapsedHC);
152 DELETEZ(s_pDefExpandedHC);
156 // #102891# --------------------
157 void SvImpLBox::UpdateIntlWrapper()
159 const ::com::sun::star::lang::Locale & aNewLocale = Application::GetSettings().GetLocale();
160 if( !pIntlWrapper )
161 pIntlWrapper = new IntlWrapper( ::comphelper::getProcessServiceFactory(), aNewLocale );
162 else
164 const ::com::sun::star::lang::Locale &aLocale = pIntlWrapper->getLocale();
165 if( aLocale.Language != aNewLocale.Language || // different Locale from the older one
166 aLocale.Country != aNewLocale.Country ||
167 aLocale.Variant != aNewLocale.Variant )
169 delete pIntlWrapper;
170 pIntlWrapper = new IntlWrapper( ::comphelper::getProcessServiceFactory(), aNewLocale );
175 // #97680# ----------------------
176 short SvImpLBox::UpdateContextBmpWidthVector( SvLBoxEntry* pEntry, short nWidth )
178 DBG_ASSERT( pView->pModel, "View and Model aren't valid!" );
180 USHORT nDepth = pView->pModel->GetDepth( pEntry );
181 // initialize vector if necessary
182 std::vector< short >::size_type nSize = aContextBmpWidthVector.size();
183 while ( nDepth > nSize )
185 aContextBmpWidthVector.resize( nSize + 1 );
186 aContextBmpWidthVector.at( nSize ) = nWidth;
187 ++nSize;
189 if( aContextBmpWidthVector.size() == nDepth )
191 aContextBmpWidthVector.resize( nDepth + 1 );
192 aContextBmpWidthVector.at( nDepth ) = 0;
194 short nContextBmpWidth = aContextBmpWidthVector[ nDepth ];
195 if( nContextBmpWidth < nWidth )
197 aContextBmpWidthVector.at( nDepth ) = nWidth;
198 return nWidth;
200 else
201 return nContextBmpWidth;
204 void SvImpLBox::UpdateContextBmpWidthVectorFromMovedEntry( SvLBoxEntry* pEntry )
206 DBG_ASSERT( pEntry, "Moved Entry is invalid!" );
208 SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) );
209 short nExpWidth = (short)pBmpItem->GetBitmap1().GetSizePixel().Width();
210 short nColWidth = (short)pBmpItem->GetBitmap2().GetSizePixel().Width();
211 short nMax = Max(nExpWidth, nColWidth);
212 UpdateContextBmpWidthVector( pEntry, nMax );
214 if( pEntry->HasChilds() ) // recursive call, whether expanded or not
216 SvLBoxEntry* pChild = pView->FirstChild( pEntry );
217 DBG_ASSERT( pChild, "The first child is invalid!" );
220 UpdateContextBmpWidthVectorFromMovedEntry( pChild );
221 pChild = pView->Next( pChild );
222 } while ( pChild );
226 void SvImpLBox::UpdateContextBmpWidthMax( SvLBoxEntry* pEntry )
228 USHORT nDepth = pView->pModel->GetDepth( pEntry );
229 if( aContextBmpWidthVector.size() < 1 )
230 return;
231 short nWidth = aContextBmpWidthVector[ nDepth ];
232 if( nWidth != pView->nContextBmpWidthMax ) {
233 pView->nContextBmpWidthMax = nWidth;
234 nFlags |= F_IGNORE_CHANGED_TABS;
235 pView->SetTabs();
236 nFlags &= ~F_IGNORE_CHANGED_TABS;
240 void SvImpLBox::CalcCellFocusRect( SvLBoxEntry* pEntry, Rectangle& rRect )
242 if ( pEntry && bIsCellFocusEnabled )
244 if ( nCurTabPos > FIRST_ENTRY_TAB )
246 SvLBoxItem* pItem = pCursor->GetItem( nCurTabPos );
247 rRect.Left() = pView->GetTab( pCursor, pItem )->GetPos();
249 if ( pCursor->ItemCount() > ( nCurTabPos + 1 ) )
251 SvLBoxItem* pNextItem = pCursor->GetItem( nCurTabPos + 1 );
252 long nRight = pView->GetTab( pCursor, pNextItem )->GetPos() - 1;
253 if ( nRight < rRect.Right() )
254 rRect.Right() = nRight;
259 void SvImpLBox::SetWindowBits( WinBits nWinStyle )
261 nWinBits = nWinStyle;
262 if((nWinStyle & WB_SIMPLEMODE) && aSelEng.GetSelectionMode()==MULTIPLE_SELECTION)
263 aSelEng.AddAlways( TRUE );
266 void SvImpLBox::SetExtendedWindowBits( ExtendedWinBits _nBits )
268 nExtendedWinBits = _nBits;
271 // Das Model darf hier nicht mehr angefasst werden
272 void SvImpLBox::Clear()
274 StopUserEvent();
275 pStartEntry = 0;
276 pAnchor = 0;
278 pActiveButton = 0;
279 pActiveEntry = 0;
280 pActiveTab = 0;
282 nMostRight = -1;
283 pMostRightEntry = 0;
285 // Der Cursor darf hier nicht mehr angefasst werden!
286 if( pCursor )
288 if( pView->HasFocus() )
289 pView->HideFocus();
290 pCursor = 0;
292 aVerSBar.Hide();
293 aVerSBar.SetThumbPos( 0 );
294 Range aRange( 0, 0 );
295 aVerSBar.SetRange( aRange );
296 aOutputSize = pView->Control::GetOutputSizePixel();
297 nFlags &= ~(F_VER_SBARSIZE_WITH_HBAR | F_HOR_SBARSIZE_WITH_VBAR );
298 if( pTabBar )
300 aOutputSize.Height() -= nHorSBarHeight;
301 nFlags |= F_VER_SBARSIZE_WITH_HBAR;
303 if( !pTabBar )
304 aHorSBar.Hide();
305 aHorSBar.SetThumbPos( 0 );
306 MapMode aMapMode( pView->GetMapMode());
307 aMapMode.SetOrigin( Point(0,0) );
308 pView->Control::SetMapMode( aMapMode );
309 aHorSBar.SetRange( aRange );
310 aHorSBar.SetSizePixel(Size(aOutputSize.Width(),nHorSBarHeight));
311 pView->SetClipRegion();
312 if( GetUpdateMode() )
313 pView->Invalidate( GetVisibleArea() );
314 nFlags |= F_FILLING;
315 if( !aHorSBar.IsVisible() && !aVerSBar.IsVisible() )
316 aScrBarBox.Hide();
318 // #97680# ---------
319 aContextBmpWidthVector.clear();
322 // *********************************************************************
323 // Painten, Navigieren, Scrollen
324 // *********************************************************************
326 IMPL_LINK_INLINE_START( SvImpLBox, EndScrollHdl, ScrollBar *, EMPTYARG )
328 if( nFlags & F_ENDSCROLL_SET_VIS_SIZE )
330 aVerSBar.SetVisibleSize( nNextVerVisSize );
331 nFlags &= ~F_ENDSCROLL_SET_VIS_SIZE;
333 EndScroll();
334 return 0;
336 IMPL_LINK_INLINE_END( SvImpLBox, EndScrollHdl, ScrollBar *, pScrollBar )
339 // Handler vertikale ScrollBar
341 IMPL_LINK( SvImpLBox, ScrollUpDownHdl, ScrollBar *, pScrollBar )
343 DBG_ASSERT(!bInVScrollHdl,"Scroll-Handler ueberholt sich!");
344 long nDelta = pScrollBar->GetDelta();
345 if( !nDelta )
346 return 0;
348 nFlags &= (~F_FILLING);
350 bInVScrollHdl = TRUE;
352 if( pView->IsEditingActive() )
354 pView->EndEditing( TRUE ); // Cancel
355 pView->Update();
357 BeginScroll();
359 if( nDelta > 0 )
361 if( nDelta == 1 )
362 CursorDown();
363 else
364 PageDown( (USHORT) nDelta );
366 else
368 nDelta *= (-1);
369 if( nDelta == 1 )
370 CursorUp();
371 else
372 PageUp( (USHORT) nDelta );
374 bInVScrollHdl = FALSE;
375 return 0;
379 void SvImpLBox::CursorDown()
381 SvLBoxEntry* pNextFirstToDraw = (SvLBoxEntry*)(pView->NextVisible( pStartEntry));
382 if( pNextFirstToDraw )
384 nFlags &= (~F_FILLING);
385 pView->NotifyScrolling( -1 );
386 ShowCursor( FALSE );
387 pView->Update();
388 pStartEntry = pNextFirstToDraw;
389 Rectangle aArea( GetVisibleArea() );
390 pView->Scroll( 0, -(pView->GetEntryHeight()), aArea, SCROLL_NOCHILDREN );
391 pView->Update();
392 ShowCursor( TRUE );
393 pView->NotifyScrolled();
397 void SvImpLBox::CursorUp()
399 SvLBoxEntry* pPrevFirstToDraw = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry));
400 if( pPrevFirstToDraw )
402 nFlags &= (~F_FILLING);
403 long nEntryHeight = pView->GetEntryHeight();
404 pView->NotifyScrolling( 1 );
405 ShowCursor( FALSE );
406 pView->Update();
407 pStartEntry = pPrevFirstToDraw;
408 Rectangle aArea( GetVisibleArea() );
409 aArea.Bottom() -= nEntryHeight;
410 pView->Scroll( 0, nEntryHeight, aArea, SCROLL_NOCHILDREN );
411 pView->Update();
412 ShowCursor( TRUE );
413 pView->NotifyScrolled();
417 void SvImpLBox::PageDown( USHORT nDelta )
419 USHORT nRealDelta = nDelta;
421 if( !nDelta )
422 return;
424 SvLBoxEntry* pNext;
425 pNext = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nRealDelta ));
426 if( (ULONG)pNext == (ULONG)pStartEntry )
427 return;
429 ShowCursor( FALSE );
431 nFlags &= (~F_FILLING);
432 pView->Update();
433 pStartEntry = pNext;
435 if( nRealDelta >= nVisibleCount )
437 pView->Invalidate( GetVisibleArea() );
438 pView->Update();
440 else
442 long nScroll = nRealDelta * (-1);
443 pView->NotifyScrolling( nScroll );
444 Rectangle aArea( GetVisibleArea() );
445 nScroll = pView->GetEntryHeight()*nRealDelta;
446 nScroll = -nScroll;
447 pView->Update();
448 pView->Scroll( 0, nScroll, aArea, SCROLL_NOCHILDREN );
449 pView->Update();
450 pView->NotifyScrolled();
453 ShowCursor( TRUE );
456 void SvImpLBox::PageUp( USHORT nDelta )
458 USHORT nRealDelta = nDelta;
459 if( !nDelta )
460 return;
462 SvLBoxEntry* pPrev = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry, nRealDelta ));
463 if( (ULONG)pPrev == (ULONG)pStartEntry )
464 return;
466 nFlags &= (~F_FILLING);
467 ShowCursor( FALSE );
469 pView->Update();
470 pStartEntry = pPrev;
471 if( nRealDelta >= nVisibleCount )
473 pView->Invalidate( GetVisibleArea() );
474 pView->Update();
476 else
478 long nEntryHeight = pView->GetEntryHeight();
479 pView->NotifyScrolling( (long)nRealDelta );
480 Rectangle aArea( GetVisibleArea() );
481 pView->Update();
482 pView->Scroll( 0, nEntryHeight*nRealDelta, aArea, SCROLL_NOCHILDREN );
483 pView->Update();
484 pView->NotifyScrolled();
487 ShowCursor( TRUE );
490 void SvImpLBox::KeyUp( BOOL bPageUp, BOOL bNotifyScroll )
492 if( !aVerSBar.IsVisible() )
493 return;
495 long nDelta;
496 if( bPageUp )
497 nDelta = aVerSBar.GetPageSize();
498 else
499 nDelta = 1;
501 long nThumbPos = aVerSBar.GetThumbPos();
503 if( nThumbPos < nDelta )
504 nDelta = nThumbPos;
506 if( nDelta <= 0 )
507 return;
509 nFlags &= (~F_FILLING);
510 if( bNotifyScroll )
511 BeginScroll();
513 aVerSBar.SetThumbPos( nThumbPos - nDelta );
514 if( bPageUp )
515 PageUp( (short)nDelta );
516 else
517 CursorUp();
519 if( bNotifyScroll )
520 EndScroll();
524 void SvImpLBox::KeyDown( BOOL bPageDown, BOOL bNotifyScroll )
526 if( !aVerSBar.IsVisible() )
527 return;
529 long nDelta;
530 if( bPageDown )
531 nDelta = aVerSBar.GetPageSize();
532 else
533 nDelta = 1;
535 long nThumbPos = aVerSBar.GetThumbPos();
536 long nVisibleSize = aVerSBar.GetVisibleSize();
537 long nRange = aVerSBar.GetRange().Len();
539 long nTmp = nThumbPos+nVisibleSize;
540 while( (nDelta > 0) && (nTmp+nDelta) >= nRange )
541 nDelta--;
543 if( nDelta <= 0 )
544 return;
546 nFlags &= (~F_FILLING);
547 if( bNotifyScroll )
548 BeginScroll();
550 aVerSBar.SetThumbPos( nThumbPos+nDelta );
551 if( bPageDown )
552 PageDown( (short)nDelta );
553 else
554 CursorDown();
556 if( bNotifyScroll )
557 EndScroll();
562 void SvImpLBox::InvalidateEntriesFrom( long nY ) const
564 if( !(nFlags & F_IN_PAINT ))
566 Rectangle aRect( GetVisibleArea() );
567 aRect.Top() = nY;
568 pView->Invalidate( aRect );
572 void SvImpLBox::InvalidateEntry( long nY ) const
574 if( !(nFlags & F_IN_PAINT ))
576 Rectangle aRect( GetVisibleArea() );
577 long nMaxBottom = aRect.Bottom();
578 aRect.Top() = nY;
579 aRect.Bottom() = nY; aRect.Bottom() += pView->GetEntryHeight();
580 if( aRect.Top() > nMaxBottom )
581 return;
582 if( aRect.Bottom() > nMaxBottom )
583 aRect.Bottom() = nMaxBottom;
584 pView->Invalidate( aRect );
588 void SvImpLBox::InvalidateEntry( SvLBoxEntry* pEntry )
590 if( GetUpdateMode() )
592 long nPrev = nMostRight;
593 SetMostRight( pEntry );
594 if( nPrev < nMostRight )
595 ShowVerSBar();
597 if( !(nFlags & F_IN_PAINT ))
599 BOOL bHasFocusRect = FALSE;
600 if( pEntry==pCursor && pView->HasFocus() )
602 bHasFocusRect = TRUE;
603 ShowCursor( FALSE );
605 InvalidateEntry( GetEntryLine( pEntry ) );
606 if( bHasFocusRect )
607 ShowCursor( TRUE );
612 void SvImpLBox::RecalcFocusRect()
614 if( pView->HasFocus() && pCursor )
616 pView->HideFocus();
617 long nY = GetEntryLine( pCursor );
618 Rectangle aRect = pView->GetFocusRect( pCursor, nY );
619 CalcCellFocusRect( pCursor, aRect );
620 Region aOldClip( pView->GetClipRegion());
621 Region aClipRegion( GetClipRegionRect() );
622 pView->SetClipRegion( aClipRegion );
623 pView->ShowFocus( aRect );
624 pView->SetClipRegion( aOldClip );
629 // Setzt Cursor. Passt bei SingleSelection die Selektion an
632 void SvImpLBox::SetCursor( SvLBoxEntry* pEntry, BOOL bForceNoSelect )
634 SvViewDataEntry* pViewDataNewCur = 0;
635 if( pEntry )
636 pViewDataNewCur= pView->GetViewDataEntry(pEntry);
637 if( pEntry &&
638 pEntry == pCursor &&
639 pViewDataNewCur->HasFocus() &&
640 pViewDataNewCur->IsSelected())
642 return;
645 // if this cursor is not selectable, find first visible that is and use it
646 while( pEntry && pViewDataNewCur && !pViewDataNewCur->IsSelectable() )
648 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
649 pViewDataNewCur = pEntry ? pView->GetViewDataEntry(pEntry) : 0;
652 SvLBoxEntry* pOldCursor = pCursor;
653 if( pCursor && pEntry != pCursor )
655 pView->SetEntryFocus( pCursor, FALSE );
656 if( bSimpleTravel )
657 pView->Select( pCursor, FALSE );
658 pView->HideFocus();
660 pCursor = pEntry;
661 if( pCursor )
663 pViewDataNewCur->SetFocus( TRUE );
664 if(!bForceNoSelect && bSimpleTravel && !(nFlags & F_DESEL_ALL) && GetUpdateMode())
666 pView->Select( pCursor, TRUE );
668 // Mehrfachselektion: Im Cursor-Move selektieren, wenn
669 // nicht im Add-Mode (Ctrl-F8)
670 else if( GetUpdateMode() &&
671 pView->GetSelectionMode() == MULTIPLE_SELECTION &&
672 !(nFlags & F_DESEL_ALL) && !aSelEng.IsAddMode() &&
673 !bForceNoSelect )
675 pView->Select( pCursor, TRUE );
677 else
679 ShowCursor( TRUE );
682 if( pAnchor )
684 DBG_ASSERT(aSelEng.GetSelectionMode() != SINGLE_SELECTION,"Mode?");
685 SetAnchorSelection( pOldCursor, pCursor );
688 nFlags &= (~F_DESEL_ALL);
691 void SvImpLBox::ShowCursor( BOOL bShow )
693 if( !bShow || !pCursor || !pView->HasFocus() )
695 Region aOldClip( pView->GetClipRegion());
696 Region aClipRegion( GetClipRegionRect() );
697 pView->SetClipRegion( aClipRegion );
698 pView->HideFocus();
699 pView->SetClipRegion( aOldClip );
701 else
703 long nY = GetEntryLine( pCursor );
704 Rectangle aRect = pView->GetFocusRect( pCursor, nY );
705 CalcCellFocusRect( pCursor, aRect );
706 Region aOldClip( pView->GetClipRegion());
707 Region aClipRegion( GetClipRegionRect() );
708 pView->SetClipRegion( aClipRegion );
709 pView->ShowFocus( aRect );
710 pView->SetClipRegion( aOldClip );
716 void SvImpLBox::UpdateAll( BOOL bInvalidateCompleteView,
717 BOOL bUpdateVerScrollBar )
719 if( bUpdateVerScrollBar )
720 FindMostRight(0);
721 aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
722 SyncVerThumb();
723 FillView();
724 ShowVerSBar();
725 if( bSimpleTravel && pCursor && pView->HasFocus() )
726 pView->Select( pCursor, TRUE );
727 ShowCursor( TRUE );
728 if( bInvalidateCompleteView )
729 pView->Invalidate();
730 else
731 pView->Invalidate( GetVisibleArea() );
734 IMPL_LINK_INLINE_START( SvImpLBox, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
736 long nDelta = pScrollBar->GetDelta();
737 if( nDelta )
739 if( pView->IsEditingActive() )
741 pView->EndEditing( TRUE ); // Cancel
742 pView->Update();
744 pView->nFocusWidth = -1;
745 KeyLeftRight( nDelta );
747 return 0;
749 IMPL_LINK_INLINE_END( SvImpLBox, ScrollLeftRightHdl, ScrollBar *, pScrollBar )
751 void SvImpLBox::KeyLeftRight( long nDelta )
753 if( !(nFlags & F_IN_RESIZE) )
754 pView->Update();
755 BeginScroll();
756 nFlags &= (~F_FILLING);
757 pView->NotifyScrolling( 0 ); // 0 == horizontales Scrolling
758 ShowCursor( FALSE );
760 // neuen Origin berechnen
761 long nPos = aHorSBar.GetThumbPos();
762 Point aOrigin( -nPos, 0 );
764 MapMode aMapMode( pView->GetMapMode() );
765 aMapMode.SetOrigin( aOrigin );
766 pView->SetMapMode( aMapMode );
768 if( !(nFlags & F_IN_RESIZE) )
770 Rectangle aRect( GetVisibleArea() );
771 pView->Scroll( -nDelta, 0, aRect, SCROLL_NOCHILDREN );
773 else
774 pView->Invalidate();
775 RecalcFocusRect();
776 ShowCursor( TRUE );
777 pView->NotifyScrolled();
781 // gibt letzten Eintrag zurueck, wenn Position unter
782 // dem letzten Eintrag ist
783 SvLBoxEntry* SvImpLBox::GetClickedEntry( const Point& rPoint ) const
785 DBG_ASSERT( pView->GetModel(), "SvImpLBox::GetClickedEntry: how can this ever happen? Please tell me (frank.schoenheit@sun.com) how to reproduce!" );
786 if ( !pView->GetModel() )
787 // this is quite impossible. Nevertheless, stack traces from the crash reporter
788 // suggest it isn't. Okay, make it safe, and wait for somebody to reproduce it
789 // reliably :-\ ....
790 // #122359# / 2005-05-23 / frank.schoenheit@sun.com
791 return NULL;
792 if( pView->GetEntryCount() == 0 || !pStartEntry || !pView->GetEntryHeight())
793 return 0;
795 USHORT nClickedEntry = (USHORT)(rPoint.Y() / pView->GetEntryHeight() );
796 USHORT nTemp = nClickedEntry;
797 SvLBoxEntry* pEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nTemp ));
798 return pEntry;
802 // prueft, ob der Eintrag "richtig" getroffen wurde
803 // (Focusrect+ ContextBitmap bei TreeListBox)
805 BOOL SvImpLBox::EntryReallyHit(SvLBoxEntry* pEntry,const Point& rPosPixel,long nLine)
807 BOOL bRet;
808 // bei "besonderen" Entries (mit CheckButtons usw.) sind wir
809 // nicht so pingelig
810 if( pEntry->ItemCount() >= 3 )
811 return TRUE;
813 Rectangle aRect( pView->GetFocusRect( pEntry, nLine ));
814 aRect.Right() = GetOutputSize().Width() - pView->GetMapMode().GetOrigin().X();
815 if( pView->IsA() == SV_LISTBOX_ID_TREEBOX )
817 SvLBoxContextBmp* pBmp = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
818 aRect.Left() -= pBmp->GetSize(pView,pEntry).Width();
819 aRect.Left() -= 4; // etwas Speilraum lassen
821 Point aPos( rPosPixel );
822 aPos -= pView->GetMapMode().GetOrigin();
823 if( aRect.IsInside( aPos ) )
824 bRet = TRUE;
825 else
826 bRet = FALSE;
827 return bRet;
831 // gibt 0 zurueck, wenn Position unter dem letzten Eintrag ist
832 SvLBoxEntry* SvImpLBox::GetEntry( const Point& rPoint ) const
834 if( (pView->GetEntryCount() == 0) || !pStartEntry ||
835 (rPoint.Y() > aOutputSize.Height())
836 || !pView->GetEntryHeight())
837 return 0;
839 USHORT nClickedEntry = (USHORT)(rPoint.Y() / pView->GetEntryHeight() );
840 USHORT nTemp = nClickedEntry;
841 SvLBoxEntry* pEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nTemp ));
842 if( nTemp != nClickedEntry )
843 pEntry = 0;
844 return pEntry;
848 SvLBoxEntry* SvImpLBox::MakePointVisible(const Point& rPoint,BOOL bNotifyScroll)
850 if( !pCursor )
851 return 0;
852 long nY = rPoint.Y();
853 SvLBoxEntry* pEntry = 0;
854 long nMax = aOutputSize.Height();
855 if( nY < 0 || nY >= nMax ) // aOutputSize.Height() )
857 if( nY < 0 )
858 pEntry = (SvLBoxEntry*)(pView->PrevVisible( pCursor ));
859 else
860 pEntry = (SvLBoxEntry*)(pView->NextVisible( pCursor ));
862 if( pEntry && pEntry != pCursor )
863 pView->SetEntryFocus( pCursor, FALSE );
865 if( nY < 0 )
866 KeyUp( FALSE, bNotifyScroll );
867 else
868 KeyDown( FALSE, bNotifyScroll );
870 else
872 pEntry = GetClickedEntry( rPoint );
873 if( !pEntry )
875 USHORT nSteps = 0xFFFF;
876 // LastVisible ist noch nicht implementiert!
877 pEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry, nSteps ));
879 if( pEntry )
881 if( pEntry != pCursor &&
882 aSelEng.GetSelectionMode() == SINGLE_SELECTION
884 pView->Select( pCursor, FALSE );
887 return pEntry;
890 Rectangle SvImpLBox::GetClipRegionRect() const
892 Point aOrigin( pView->GetMapMode().GetOrigin() );
893 aOrigin.X() *= -1; // Umrechnung Dokumentkoord.
894 Rectangle aClipRect( aOrigin, aOutputSize );
895 aClipRect.Bottom()++;
896 return aClipRect;
900 void SvImpLBox::Paint( const Rectangle& rRect )
902 if( !pView->GetVisibleCount() )
903 return;
905 nFlags |= F_IN_PAINT;
907 if( nFlags & F_FILLING )
909 SvLBoxEntry* pFirst = pView->First();
910 if( pFirst != pStartEntry )
912 ShowCursor( FALSE );
913 pStartEntry = pView->First();
914 aVerSBar.SetThumbPos( 0 );
915 StopUserEvent();
916 ShowCursor( TRUE );
917 nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpLBox,MyUserEvent),(void*)1);
918 return;
922 if( !pStartEntry )
924 pStartEntry = pView->First();
927 #ifdef XX_OV
928 ULONG nXAbsPos = (USHORT)pTree->GetAbsPos( pStartEntry );
929 ULONG nXVisPos = pView->GetVisiblePos( pStartEntry );
930 SvLBoxString* pXStr = (SvLBoxString*)pStartEntry->GetFirstItem( SV_ITEM_ID_LBOXSTRING);
931 #endif
935 if( nNodeBmpTabDistance == NODE_BMP_TABDIST_NOTVALID )
936 SetNodeBmpTabDistance();
938 long nRectHeight = rRect.GetHeight();
939 long nEntryHeight = pView->GetEntryHeight();
941 // Bereich der zu zeichnenden Entries berechnen
942 USHORT nStartLine = (USHORT)( rRect.Top() / nEntryHeight );
943 USHORT nCount = (USHORT)( nRectHeight / nEntryHeight );
944 nCount += 2; // keine Zeile vergessen
946 long nY = nStartLine * nEntryHeight;
947 SvLBoxEntry* pEntry = pStartEntry;
948 while( nStartLine && pEntry )
950 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
951 nStartLine--;
954 Region aClipRegion( GetClipRegionRect() );
956 // erst die Linien Zeichnen, dann clippen!
957 pView->SetClipRegion();
958 if( nWinBits & ( WB_HASLINES | WB_HASLINESATROOT ) )
959 DrawNet();
961 pView->SetClipRegion( aClipRegion );
963 for( USHORT n=0; n< nCount && pEntry; n++ )
965 /*long nMaxRight=*/
966 pView->PaintEntry1( pEntry, nY, 0xffff, TRUE );
967 nY += nEntryHeight;
968 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
971 if ( !pCursor && ( ( nExtendedWinBits & EWB_NO_AUTO_CURENTRY ) == 0 ) )
973 // do not select if multiselection or explicit set
974 BOOL bNotSelect = ( aSelEng.GetSelectionMode() == MULTIPLE_SELECTION )
975 || ( ( nWinBits & WB_NOINITIALSELECTION ) == WB_NOINITIALSELECTION );
976 SetCursor( pStartEntry, bNotSelect );
979 nFlags &= (~F_DESEL_ALL);
980 pView->SetClipRegion();
981 Rectangle aRect;
982 if( !(nFlags & F_PAINTED) )
984 nFlags |= F_PAINTED;
985 RepaintScrollBars();
987 nFlags &= (~F_IN_PAINT);
990 void SvImpLBox::MakeVisible( SvLBoxEntry* pEntry, BOOL bMoveToTop )
992 if( !pEntry )
993 return;
995 BOOL bInView = IsEntryInView( pEntry );
997 if( bInView && (!bMoveToTop || pStartEntry == pEntry) )
998 return; // ist schon sichtbar
1000 if( pStartEntry || (nWinBits & WB_FORCE_MAKEVISIBLE) )
1001 nFlags &= (~F_FILLING);
1002 if( !bInView )
1004 if( !pView->IsEntryVisible(pEntry) ) // Parent(s) zugeklappt ?
1006 SvLBoxEntry* pParent = pView->GetParent( pEntry );
1007 while( pParent )
1009 if( !pView->IsExpanded( pParent ) )
1011 #ifdef DBG_UTIL
1012 BOOL bRet =
1013 #endif
1014 pView->Expand( pParent );
1015 DBG_ASSERT(bRet,"Not expanded!");
1017 pParent = pView->GetParent( pParent );
1019 // Passen Childs der Parents in View oder muessen wir scrollen ?
1020 if( IsEntryInView( pEntry ) && !bMoveToTop )
1021 return; // Scrollen nicht noetig -> tschuess
1025 pStartEntry = pEntry;
1026 ShowCursor( FALSE );
1027 FillView();
1028 aVerSBar.SetThumbPos( (long)(pView->GetVisiblePos( pStartEntry )) );
1029 ShowCursor( TRUE );
1030 pView->Invalidate();
1034 void SvImpLBox::RepaintSelectionItems()
1036 if( !pView->GetVisibleCount() )
1037 return;
1039 if( !pStartEntry )
1040 pStartEntry = pView->First();
1042 if( nNodeBmpTabDistance == NODE_BMP_TABDIST_NOTVALID )
1043 SetNodeBmpTabDistance();
1045 ShowCursor( FALSE );
1047 long nEntryHeight = pView->GetEntryHeight();
1049 ULONG nCount = nVisibleCount;
1050 long nY = 0;
1051 SvLBoxEntry* pEntry = pStartEntry;
1052 for( ULONG n=0; n< nCount && pEntry; n++ )
1054 pView->PaintEntry1( pEntry, nY, 0xffff ); //wg. ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
1055 nY += nEntryHeight;
1056 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
1059 ShowCursor( TRUE );
1063 void SvImpLBox::DrawNet()
1065 if( pView->GetVisibleCount() < 2 && !pStartEntry->HasChildsOnDemand() &&
1066 !pStartEntry->HasChilds() )
1067 return;
1069 //for platforms who don't have nets, DrawNativeControl does nothing and return true
1070 //so that SvImpLBox::DrawNet() doesn't draw anything too
1071 if(pView->IsNativeControlSupported( CTRL_LISTNET, PART_ENTIRE_CONTROL)) {
1072 ImplControlValue aControlValue;
1073 Point aTemp(0,0); // temporary needed for g++ 3.3.5
1074 Region aCtrlRegion( Rectangle(aTemp, Size( 0, 0 )) );
1075 ControlState nState = CTRL_STATE_ENABLED;
1076 if( pView->DrawNativeControl( CTRL_LISTNET, PART_ENTIRE_CONTROL,
1077 aCtrlRegion, nState, aControlValue, rtl::OUString() ) )
1079 return;
1084 long nEntryHeight = pView->GetEntryHeight();
1085 long nEntryHeightDIV2 = nEntryHeight / 2;
1086 if( nEntryHeightDIV2 && !(nEntryHeight & 0x0001))
1087 nEntryHeightDIV2--;
1089 SvLBoxEntry* pChild;
1090 SvLBoxEntry* pEntry = pStartEntry;
1092 SvLBoxTab* pFirstDynamicTab = pView->GetFirstDynamicTab();
1093 while( pTree->GetDepth( pEntry ) > 0 )
1094 pEntry = pView->GetParent( pEntry );
1095 USHORT nOffs = (USHORT)(pView->GetVisiblePos( pStartEntry ) -
1096 pView->GetVisiblePos( pEntry ));
1097 long nY = 0;
1098 nY -= ( nOffs * nEntryHeight );
1100 DBG_ASSERT(pFirstDynamicTab,"No Tree!");
1102 Color aOldLineColor = pView->GetLineColor();
1103 const StyleSettings& rStyleSettings = pView->GetSettings().GetStyleSettings();
1104 Color aCol= rStyleSettings.GetFaceColor();
1106 if( aCol.IsRGBEqual( pView->GetBackground().GetColor()) )
1107 aCol = rStyleSettings.GetShadowColor();
1108 pView->SetLineColor( aCol );
1109 Point aPos1, aPos2;
1110 USHORT nDistance;
1111 ULONG nMax = nVisibleCount + nOffs + 1;
1113 const Image& rExpandedNodeBitmap = GetExpandedNodeBmp();
1115 for( ULONG n=0; n< nMax && pEntry; n++ )
1117 if( pView->IsExpanded(pEntry) )
1119 aPos1.X() = pView->GetTabPos(pEntry, pFirstDynamicTab);
1120 // wenn keine ContextBitmap, dann etwas nach rechts
1121 // unter den ersten Text (Node.Bmp ebenfalls
1122 if( !pView->nContextBmpWidthMax )
1123 aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1125 aPos1.Y() = nY;
1126 aPos1.Y() += nEntryHeightDIV2;
1128 pChild = pView->FirstChild( pEntry );
1129 DBG_ASSERT(pChild,"Child?");
1130 pChild = pTree->LastSibling( pChild );
1131 nDistance = (USHORT)(pView->GetVisiblePos(pChild) -
1132 pView->GetVisiblePos(pEntry));
1133 aPos2 = aPos1;
1134 aPos2.Y() += nDistance * nEntryHeight;
1135 pView->DrawLine( aPos1, aPos2 );
1137 // Sichtbar im Control ?
1138 if( n>= nOffs && ((nWinBits & WB_HASLINESATROOT) || !pTree->IsAtRootDepth(pEntry)))
1140 // kann aPos1 recyclet werden ?
1141 if( !pView->IsExpanded(pEntry) )
1143 // njet
1144 aPos1.X() = pView->GetTabPos(pEntry, pFirstDynamicTab);
1145 // wenn keine ContextBitmap, dann etwas nach rechts
1146 // unter den ersten Text (Node.Bmp ebenfalls
1147 if( !pView->nContextBmpWidthMax )
1148 aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1149 aPos1.Y() = nY;
1150 aPos1.Y() += nEntryHeightDIV2;
1151 aPos2.X() = aPos1.X();
1153 aPos2.Y() = aPos1.Y();
1154 aPos2.X() -= pView->GetIndent();
1155 pView->DrawLine( aPos1, aPos2 );
1157 nY += nEntryHeight;
1158 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
1160 if( nWinBits & WB_HASLINESATROOT )
1162 pEntry = pView->First();
1163 aPos1.X() = pView->GetTabPos( pEntry, pFirstDynamicTab);
1164 // wenn keine ContextBitmap, dann etwas nach rechts
1165 // unter den ersten Text (Node.Bmp ebenfalls
1166 if( !pView->nContextBmpWidthMax )
1167 aPos1.X() += rExpandedNodeBitmap.GetSizePixel().Width() / 2;
1168 aPos1.X() -= pView->GetIndent();
1169 aPos1.Y() = GetEntryLine( pEntry );
1170 aPos1.Y() += nEntryHeightDIV2;
1171 pChild = pTree->LastSibling( pEntry );
1172 aPos2.X() = aPos1.X();
1173 aPos2.Y() = GetEntryLine( pChild );
1174 aPos2.Y() += nEntryHeightDIV2;
1175 pView->DrawLine( aPos1, aPos2 );
1177 pView->SetLineColor( aOldLineColor );
1181 static long GetOptSize( TabBar* pTabBar )
1183 return pTabBar->CalcWindowSizePixel().Width();
1186 void SvImpLBox::PositionScrollBars( Size& rSize, USHORT nMask )
1188 long nOverlap = 0;
1190 Size aVerSize( nVerSBarWidth, rSize.Height() );
1191 Size aHorSize( rSize.Width(), nHorSBarHeight );
1192 long nTabBarWidth = 0;
1193 if( pTabBar )
1195 nTabBarWidth = GetOptSize( pTabBar );
1196 long nMaxWidth = (rSize.Width() * 700) / 1000;
1197 if( nTabBarWidth > nMaxWidth )
1199 nTabBarWidth = nMaxWidth;
1200 pTabBar->SetStyle( pTabBar->GetStyle() | WB_MINSCROLL );
1202 else
1204 WinBits nStyle = pTabBar->GetStyle();
1205 nStyle &= ~(WB_MINSCROLL);
1206 pTabBar->SetStyle( nStyle );
1208 aHorSize.Width() -= nTabBarWidth;
1209 Size aTabSize( pTabBar->GetSizePixel() );
1210 aTabSize.Width() = nTabBarWidth;
1211 pTabBar->SetSizePixel( aTabSize );
1213 if( nMask & 0x0001 )
1214 aHorSize.Width() -= nVerSBarWidth;
1215 if( nMask & 0x0002 )
1216 aVerSize.Height() -= nHorSBarHeight;
1218 aVerSize.Height() += 2 * nOverlap;
1219 Point aVerPos( rSize.Width() - aVerSize.Width() + nOverlap, -nOverlap );
1220 aVerSBar.SetPosSizePixel( aVerPos, aVerSize );
1222 aHorSize.Width() += 2 * nOverlap;
1223 Point aHorPos( -nOverlap, rSize.Height() - aHorSize.Height() + nOverlap );
1224 if( pTabBar )
1225 pTabBar->SetPosPixel( aHorPos );
1226 aHorPos.X() += nTabBarWidth;
1227 aHorSBar.SetPosSizePixel( aHorPos, aHorSize );
1229 if( nMask & 0x0001 )
1230 rSize.Width() = aVerPos.X();
1231 if( nMask & 0x0002 )
1232 rSize.Height() = aHorPos.Y();
1233 if( pTabBar )
1234 pTabBar->Show();
1236 if( (nMask & (0x0001|0x0002)) == (0x0001|0x0002) )
1237 aScrBarBox.Show();
1238 else
1239 aScrBarBox.Hide();
1243 // nResult: Bit0 == VerSBar Bit1 == HorSBar
1244 USHORT SvImpLBox::AdjustScrollBars( Size& rSize )
1246 long nEntryHeight = pView->GetEntryHeight();
1247 if( !nEntryHeight )
1248 return 0;
1250 USHORT nResult = 0;
1252 Size aOSize( pView->Control::GetOutputSizePixel() );
1254 BOOL bVerSBar = ( pView->nWindowStyle & WB_VSCROLL ) != 0;
1255 BOOL bHorBar = FALSE;
1256 long nMaxRight = aOSize.Width(); //GetOutputSize().Width();
1257 Point aOrigin( pView->GetMapMode().GetOrigin() );
1258 aOrigin.X() *= -1;
1259 nMaxRight += aOrigin.X() - 1;
1260 long nVis = nMostRight - aOrigin.X();
1261 if( pTabBar || (
1262 (pView->nWindowStyle & WB_HSCROLL) &&
1263 (nVis < nMostRight || nMaxRight < nMostRight) ))
1264 bHorBar = TRUE;
1266 // Anzahl aller nicht eingeklappten Eintraege
1267 ULONG nTotalCount = pView->GetVisibleCount();
1269 // Anzahl in der View sichtbarer Eintraege
1270 nVisibleCount = aOSize.Height() / nEntryHeight;
1272 // muessen wir eine vertikale Scrollbar einblenden?
1273 if( bVerSBar || nTotalCount > nVisibleCount )
1275 nResult = 1;
1276 nFlags |= F_HOR_SBARSIZE_WITH_VBAR;
1277 nMaxRight -= nVerSBarWidth;
1278 if( !bHorBar )
1280 if( (pView->nWindowStyle & WB_HSCROLL) &&
1281 (nVis < nMostRight || nMaxRight < nMostRight) )
1282 bHorBar = TRUE;
1286 // muessen wir eine horizontale Scrollbar einblenden?
1287 if( bHorBar )
1289 nResult |= 0x0002;
1290 // die Anzahl der in der View sichtbaren Eintraege
1291 // muss neu berechnet werden, da die horizontale
1292 // ScrollBar eingeblendet wird
1293 nVisibleCount = (aOSize.Height() - nHorSBarHeight) / nEntryHeight;
1294 // eventuell brauchen wir jetzt doch eine vertikale ScrollBar
1295 if( !(nResult & 0x0001) &&
1296 ((nTotalCount > nVisibleCount) || bVerSBar) )
1298 nResult = 3;
1299 nFlags |= F_VER_SBARSIZE_WITH_HBAR;
1303 PositionScrollBars( aOSize, nResult );
1305 // Range, VisibleRange usw. anpassen
1307 // Output-Size aktualisieren, falls wir scrollen muessen
1308 Rectangle aRect;
1309 aRect.SetSize( aOSize );
1310 aSelEng.SetVisibleArea( aRect );
1312 // Vertikale ScrollBar
1313 long nTemp = (long)nVisibleCount;
1314 nTemp--;
1315 if( nTemp != aVerSBar.GetVisibleSize() )
1317 if( !bInVScrollHdl )
1319 aVerSBar.SetPageSize( nTemp - 1 );
1320 aVerSBar.SetVisibleSize( nTemp );
1322 else
1324 nFlags |= F_ENDSCROLL_SET_VIS_SIZE;
1325 nNextVerVisSize = nTemp;
1329 // Horizontale ScrollBar
1330 nTemp = aHorSBar.GetThumbPos();
1331 aHorSBar.SetVisibleSize( aOSize.Width() );
1332 long nNewThumbPos = aHorSBar.GetThumbPos();
1333 Range aRange( aHorSBar.GetRange() );
1334 if( aRange.Max() < nMostRight+25 )
1336 aRange.Max() = nMostRight+25;
1337 aHorSBar.SetRange( aRange );
1340 if( nTemp != nNewThumbPos )
1342 nTemp = nNewThumbPos - nTemp;
1343 if( pView->IsEditingActive() )
1345 pView->EndEditing( TRUE ); // Cancel
1346 pView->Update();
1348 pView->nFocusWidth = -1;
1349 KeyLeftRight( nTemp );
1352 if( nResult & 0x0001 )
1353 aVerSBar.Show();
1354 else
1355 aVerSBar.Hide();
1357 if( nResult & 0x0002 )
1358 aHorSBar.Show();
1359 else
1361 if( !pTabBar )
1362 aHorSBar.Hide();
1364 rSize = aOSize;
1365 return nResult;
1368 void SvImpLBox::InitScrollBarBox()
1370 aScrBarBox.SetSizePixel( Size(nVerSBarWidth, nHorSBarHeight) );
1371 Size aSize( pView->Control::GetOutputSizePixel() );
1372 aScrBarBox.SetPosPixel( Point(aSize.Width()-nVerSBarWidth, aSize.Height()-nHorSBarHeight));
1375 void SvImpLBox::Resize()
1377 Size aSize( pView->Control::GetOutputSizePixel());
1378 if( aSize.Width() <= 0 || aSize.Height() <= 0 )
1379 return;
1380 nFlags |= F_IN_RESIZE;
1381 InitScrollBarBox();
1383 if( pView->GetEntryHeight())
1385 AdjustScrollBars( aOutputSize );
1386 FillView();
1388 // !!!HACK, da in Floating- & Docking-Windows nach Resizes
1389 // die Scrollbars nicht richtig, bzw. ueberhaupt nicht gezeichnet werden
1390 if( aHorSBar.IsVisible())
1391 aHorSBar.Invalidate();
1392 if( aVerSBar.IsVisible())
1393 aVerSBar.Invalidate();
1394 nFlags &= (~(F_IN_RESIZE | F_PAINTED));
1397 void SvImpLBox::FillView()
1399 if( !pStartEntry )
1401 USHORT nVisibleViewCount = (USHORT)(pView->GetVisibleCount());
1402 USHORT nTempThumb = (USHORT)aVerSBar.GetThumbPos();
1403 if( nTempThumb >= nVisibleViewCount )
1404 nTempThumb = nVisibleViewCount - 1;
1405 pStartEntry = (SvLBoxEntry*)(pView->GetEntryAtVisPos(nTempThumb));
1407 if( pStartEntry )
1409 USHORT nLast = (USHORT)(pView->GetVisiblePos( (SvLBoxEntry*)(pView->LastVisible())));
1410 USHORT nThumb = (USHORT)(pView->GetVisiblePos( pStartEntry ));
1411 USHORT nCurDispEntries = nLast-nThumb+1;
1412 if( nCurDispEntries < nVisibleCount )
1414 ShowCursor( FALSE );
1415 // Fenster fuellen, indem der Thumb schrittweise
1416 // nach oben bewegt wird
1417 BOOL bFound = FALSE;
1418 SvLBoxEntry* pTemp = pStartEntry;
1419 while( nCurDispEntries < nVisibleCount && pTemp )
1421 pTemp = (SvLBoxEntry*)(pView->PrevVisible(pStartEntry));
1422 if( pTemp )
1424 nThumb--;
1425 pStartEntry = pTemp;
1426 nCurDispEntries++;
1427 bFound = TRUE;
1430 if( bFound )
1432 aVerSBar.SetThumbPos( nThumb );
1433 ShowCursor( TRUE ); // Focusrect neu berechnen
1434 pView->Invalidate();
1443 void SvImpLBox::ShowVerSBar()
1445 BOOL bVerBar = ( pView->nWindowStyle & WB_VSCROLL ) != 0;
1446 ULONG nVis = 0;
1447 if( !bVerBar )
1448 nVis = pView->GetVisibleCount();
1449 if( bVerBar || (nVisibleCount && nVis > (ULONG)(nVisibleCount-1)) )
1451 if( !aVerSBar.IsVisible() )
1453 pView->nFocusWidth = -1;
1454 AdjustScrollBars( aOutputSize );
1455 if( GetUpdateMode() )
1456 aVerSBar.Update();
1459 else
1461 if( aVerSBar.IsVisible() )
1463 pView->nFocusWidth = -1;
1464 AdjustScrollBars( aOutputSize );
1468 long nMaxRight = GetOutputSize().Width();
1469 Point aPos( pView->GetMapMode().GetOrigin() );
1470 aPos.X() *= -1; // Umrechnung Dokumentkoord.
1471 nMaxRight = nMaxRight + aPos.X() - 1;
1472 if( nMaxRight < nMostRight )
1474 if( !aHorSBar.IsVisible() )
1476 pView->nFocusWidth = -1;
1477 AdjustScrollBars( aOutputSize );
1478 if( GetUpdateMode() )
1479 aHorSBar.Update();
1481 else
1483 Range aRange( aHorSBar.GetRange() );
1484 if( aRange.Max() < nMostRight+25 )
1486 aRange.Max() = nMostRight+25;
1487 aHorSBar.SetRange( aRange );
1489 else
1491 pView->nFocusWidth = -1;
1492 AdjustScrollBars( aOutputSize );
1496 else
1498 if( aHorSBar.IsVisible() )
1500 pView->nFocusWidth = -1;
1501 AdjustScrollBars( aOutputSize );
1507 void SvImpLBox::SyncVerThumb()
1509 if( pStartEntry )
1511 long nEntryPos = pView->GetVisiblePos( pStartEntry );
1512 aVerSBar.SetThumbPos( nEntryPos );
1514 else
1515 aVerSBar.SetThumbPos( 0 );
1518 BOOL SvImpLBox::IsEntryInView( SvLBoxEntry* pEntry ) const
1520 // Parent eingeklappt
1521 if( !pView->IsEntryVisible(pEntry) )
1522 return FALSE;
1523 long nY = GetEntryLine( pEntry );
1524 if( nY < 0 )
1525 return FALSE;
1526 long nMax = nVisibleCount * pView->GetEntryHeight();
1527 if( nY >= nMax )
1528 return FALSE;
1529 return TRUE;
1533 long SvImpLBox::GetEntryLine( SvLBoxEntry* pEntry ) const
1535 if(!pStartEntry )
1536 return -1; // unsichtbare Position
1538 long nFirstVisPos = pView->GetVisiblePos( pStartEntry );
1539 long nEntryVisPos = pView->GetVisiblePos( pEntry );
1540 nFirstVisPos = nEntryVisPos - nFirstVisPos;
1541 nFirstVisPos *= pView->GetEntryHeight();
1542 return nFirstVisPos;
1545 void SvImpLBox::SetEntryHeight( short /* nHeight */ )
1547 SetNodeBmpYOffset( GetExpandedNodeBmp() );
1548 SetNodeBmpYOffset( GetCollapsedNodeBmp() );
1549 if(!pView->HasViewData()) // stehen wir im Clear?
1551 Size aSize = pView->Control::GetOutputSizePixel();
1552 AdjustScrollBars( aSize );
1554 else
1556 Resize();
1557 if( GetUpdateMode() )
1558 pView->Invalidate();
1564 // ***********************************************************************
1565 // Callback-Functions
1566 // ***********************************************************************
1568 void SvImpLBox::IndentChanged( short /* nIndentPixel */ ) {}
1570 void SvImpLBox::EntryExpanded( SvLBoxEntry* pEntry )
1572 // SelAllDestrAnch( FALSE, TRUE ); //DeselectAll();
1573 if( GetUpdateMode() )
1575 ShowCursor( FALSE );
1576 long nY = GetEntryLine( pEntry );
1577 if( IsLineVisible(nY) )
1579 InvalidateEntriesFrom( nY );
1580 FindMostRight( pEntry, 0 );
1582 aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
1583 // falls vor dem Thumb expandiert wurde, muss
1584 // die Thumb-Position korrigiert werden.
1585 SyncVerThumb();
1586 ShowVerSBar();
1587 ShowCursor( TRUE );
1591 void SvImpLBox::EntryCollapsed( SvLBoxEntry* pEntry )
1593 if( !pView->IsEntryVisible( pEntry ) )
1594 return;
1596 ShowCursor( FALSE );
1598 if( !pMostRightEntry || pTree->IsChild( pEntry,pMostRightEntry ) )
1600 FindMostRight(0);
1603 if( pStartEntry )
1605 long nOldThumbPos = aVerSBar.GetThumbPos();
1606 ULONG nVisList = pView->GetVisibleCount();
1607 aVerSBar.SetRange( Range(0, nVisList-1) );
1608 long nNewThumbPos = aVerSBar.GetThumbPos();
1609 if( nNewThumbPos != nOldThumbPos )
1611 pStartEntry = pView->First();
1612 USHORT nDistance = (USHORT)nNewThumbPos;
1613 if( nDistance )
1614 pStartEntry = (SvLBoxEntry*)(pView->NextVisible( pStartEntry,
1615 nDistance));
1616 if( GetUpdateMode() )
1617 pView->Invalidate();
1619 else
1620 SyncVerThumb();
1621 ShowVerSBar();
1623 // wurde Cursor eingeklappt ?
1624 if( pTree->IsChild( pEntry, pCursor ) )
1625 SetCursor( pEntry );
1626 if( GetUpdateMode() )
1627 ShowVerSBar();
1628 ShowCursor( TRUE );
1629 if( GetUpdateMode() && pCursor )
1630 pView->Select( pCursor, TRUE );
1633 void SvImpLBox::CollapsingEntry( SvLBoxEntry* pEntry )
1635 if( !pView->IsEntryVisible( pEntry ) || !pStartEntry )
1636 return;
1638 SelAllDestrAnch( FALSE, TRUE ); // deselectall
1640 // ist der eingeklappte Parent sichtbar ?
1641 long nY = GetEntryLine( pEntry );
1642 if( IsLineVisible(nY) )
1644 if( GetUpdateMode() )
1645 InvalidateEntriesFrom( nY );
1647 else
1649 if( pTree->IsChild(pEntry, pStartEntry) )
1651 pStartEntry = pEntry;
1652 if( GetUpdateMode() )
1653 pView->Invalidate();
1659 void SvImpLBox::SetNodeBmpYOffset( const Image& rBmp )
1661 Size aSize;
1662 nYoffsNodeBmp = pView->GetHeightOffset( rBmp, aSize );
1663 nNodeBmpWidth = aSize.Width();
1666 void SvImpLBox::SetNodeBmpTabDistance()
1668 nNodeBmpTabDistance = -pView->GetIndent();
1669 if( pView->nContextBmpWidthMax )
1671 // nur, wenn der erste dynamische Tab zentriert ist
1672 // (setze ich momentan voraus)
1673 Size aSize = GetExpandedNodeBmp().GetSizePixel();
1674 nNodeBmpTabDistance -= aSize.Width() / 2;
1679 // korrigiert bei SingleSelection den Cursor
1681 void SvImpLBox::EntrySelected( SvLBoxEntry* pEntry, BOOL bSelect )
1683 if( nFlags & F_IGNORE_SELECT )
1684 return;
1687 if( (nWinBits & WB_HIDESELECTION) && pEntry && !pView->HasFocus() )
1689 SvViewData* pViewData = pView->GetViewData( pEntry );
1690 pViewData->SetCursored( bSelect );
1694 nFlags &= (~F_DESEL_ALL);
1695 if( bSelect &&
1696 aSelEng.GetSelectionMode() == SINGLE_SELECTION &&
1697 pEntry != pCursor )
1699 SetCursor( pEntry );
1700 DBG_ASSERT(pView->GetSelectionCount()==1,"selection count?");
1703 if( GetUpdateMode() && pView->IsEntryVisible(pEntry) )
1705 long nY = GetEntryLine( pEntry );
1706 if( IsLineVisible( nY ) )
1708 ShowCursor( FALSE );
1709 pView->PaintEntry1( pEntry, nY, 0xffff ); // wg. ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
1710 ShowCursor( TRUE );
1716 void SvImpLBox::RemovingEntry( SvLBoxEntry* pEntry )
1718 DestroyAnchor();
1720 if( !pView->IsEntryVisible( pEntry ) )
1722 // wenn Parent eingeklappt, dann tschuess
1723 nFlags |= F_REMOVED_ENTRY_INVISIBLE;
1724 return;
1727 if( pEntry == pMostRightEntry || (
1728 pEntry->HasChilds() && pView->IsExpanded(pEntry) &&
1729 pTree->IsChild(pEntry, pMostRightEntry)))
1731 nFlags |= F_REMOVED_RECALC_MOST_RIGHT;
1734 SvLBoxEntry* pOldStartEntry = pStartEntry;
1736 SvLBoxEntry* pParent = (SvLBoxEntry*)(pView->GetModel()->GetParent(pEntry));
1738 if( pParent && pView->GetModel()->GetChildList(pParent)->Count() == 1 )
1740 DBG_ASSERT( pView->IsExpanded( pParent ), "Parent not expanded");
1741 pParent->SetFlags( pParent->GetFlags() | SV_ENTRYFLAG_NO_NODEBMP);
1742 InvalidateEntry( pParent );
1745 if( pCursor && pTree->IsChild( pEntry, pCursor) )
1746 pCursor = pEntry;
1747 if( pStartEntry && pTree->IsChild(pEntry,pStartEntry) )
1748 pStartEntry = pEntry;
1750 SvLBoxEntry* pTemp;
1751 if( pCursor && pCursor == pEntry )
1753 if( bSimpleTravel )
1754 pView->Select( pCursor, FALSE );
1755 ShowCursor( FALSE ); // Focus-Rect weg
1756 // NextSibling, weil auch Childs des Cursors geloescht werden
1757 pTemp = pView->NextSibling( pCursor );
1758 if( !pTemp )
1759 pTemp = (SvLBoxEntry*)(pView->PrevVisible( pCursor ));
1761 SetCursor( pTemp, TRUE );
1763 if( pStartEntry && pStartEntry == pEntry )
1765 pTemp = pView->NextSibling( pStartEntry );
1766 if( !pTemp )
1767 pTemp = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry ));
1768 pStartEntry = pTemp;
1770 if( GetUpdateMode())
1772 // wenns der letzte ist, muss invalidiert werden, damit die Linien
1773 // richtig gezeichnet (in diesem Fall geloescht) werden.
1774 if( pStartEntry && (pStartEntry != pOldStartEntry || pEntry == (SvLBoxEntry*)pView->GetModel()->Last()) )
1776 aVerSBar.SetThumbPos( pView->GetVisiblePos( pStartEntry ));
1777 pView->Invalidate( GetVisibleArea() );
1779 else
1780 InvalidateEntriesFrom( GetEntryLine( pEntry ) );
1784 void SvImpLBox::EntryRemoved()
1786 if( nFlags & F_REMOVED_ENTRY_INVISIBLE )
1788 nFlags &= (~F_REMOVED_ENTRY_INVISIBLE);
1789 return;
1791 if( !pStartEntry )
1792 pStartEntry = pTree->First();
1793 if( !pCursor )
1794 SetCursor( pStartEntry, TRUE );
1796 if( pCursor && (bSimpleTravel || !pView->GetSelectionCount() ))
1797 pView->Select( pCursor, TRUE );
1799 if( GetUpdateMode())
1801 if( nFlags & F_REMOVED_RECALC_MOST_RIGHT )
1802 FindMostRight(0);
1803 aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1 ) );
1804 FillView();
1805 if( pStartEntry )
1806 // falls ueber dem Thumb geloescht wurde
1807 aVerSBar.SetThumbPos( pView->GetVisiblePos( pStartEntry) );
1809 ShowVerSBar();
1810 if( pCursor && pView->HasFocus() && !pView->IsSelected(pCursor) )
1812 if( pView->GetSelectionCount() )
1814 // ist ein benachbarter Eintrag selektiert?
1815 SvLBoxEntry* pNextCursor = (SvLBoxEntry*)pView->PrevVisible( pCursor );
1816 if( !pNextCursor || !pView->IsSelected( pNextCursor ))
1817 pNextCursor = (SvLBoxEntry*)pView->NextVisible( pCursor );
1818 if( !pNextCursor || !pView->IsSelected( pNextCursor ))
1819 // kein Nachbar selektiert: Ersten selektierten nehmen
1820 pNextCursor = pView->FirstSelected();
1821 SetCursor( pNextCursor );
1822 MakeVisible( pCursor );
1824 else
1825 pView->Select( pCursor, TRUE );
1827 ShowCursor( TRUE );
1829 nFlags &= (~F_REMOVED_RECALC_MOST_RIGHT);
1833 void SvImpLBox::MovingEntry( SvLBoxEntry* pEntry )
1835 int bDeselAll = nFlags & F_DESEL_ALL;
1836 SelAllDestrAnch( FALSE, TRUE ); // DeselectAll();
1837 if( !bDeselAll )
1838 nFlags &= (~F_DESEL_ALL);
1840 if( pEntry == pCursor )
1841 ShowCursor( FALSE );
1842 if( IsEntryInView( pEntry ) )
1843 pView->Invalidate();
1844 if( pEntry == pStartEntry )
1846 SvLBoxEntry* pNew = 0;
1847 if( !pEntry->HasChilds() )
1849 pNew = (SvLBoxEntry*)(pView->NextVisible( pStartEntry ));
1850 if( !pNew )
1851 pNew = (SvLBoxEntry*)(pView->PrevVisible( pStartEntry ));
1853 else
1855 pNew = pTree->NextSibling( pEntry );
1856 if( !pNew )
1857 pNew = pTree->PrevSibling( pEntry );
1859 pStartEntry = pNew;
1863 void SvImpLBox::EntryMoved( SvLBoxEntry* pEntry )
1865 // #97680# --------------
1866 UpdateContextBmpWidthVectorFromMovedEntry( pEntry );
1868 if ( !pStartEntry )
1869 // this might happen if the only entry in the view is moved to its very same position
1870 // #i97346#
1871 pStartEntry = pView->First();
1873 aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1));
1874 USHORT nFirstPos = (USHORT)pTree->GetAbsPos( pStartEntry );
1875 USHORT nNewPos = (USHORT)pTree->GetAbsPos( pEntry );
1876 FindMostRight(0);
1877 if( nNewPos < nFirstPos ) //!!!Notloesung
1878 pStartEntry = pEntry;
1879 // #97702# ---------------
1880 SyncVerThumb();
1881 if( pEntry == pCursor )
1883 if( pView->IsEntryVisible( pCursor ) )
1884 ShowCursor( TRUE );
1885 else
1887 SvLBoxEntry* pParent = pEntry;
1888 do {
1889 pParent = pTree->GetParent( pParent );
1891 while( !pView->IsEntryVisible( pParent ) );
1892 SetCursor( pParent );
1895 if( IsEntryInView( pEntry ) )
1896 pView->Invalidate();
1901 void SvImpLBox::EntryInserted( SvLBoxEntry* pEntry )
1903 if( GetUpdateMode() )
1905 SvLBoxEntry* pParent = (SvLBoxEntry*)pTree->GetParent(pEntry);
1906 if( pParent && pTree->GetChildList(pParent)->Count() == 1 )
1907 // Pluszeichen zeichnen
1908 pTree->InvalidateEntry( pParent );
1910 if( !pView->IsEntryVisible( pEntry ) )
1911 return;
1912 int bDeselAll = nFlags & F_DESEL_ALL;
1913 if( bDeselAll )
1914 SelAllDestrAnch( FALSE, TRUE );
1915 else
1916 DestroyAnchor();
1917 // nFlags &= (~F_DESEL_ALL);
1918 // ShowCursor( FALSE ); // falls sich Cursor nach unten verschiebt
1919 long nY = GetEntryLine( pEntry );
1920 BOOL bEntryVisible = IsLineVisible( nY );
1921 if( bEntryVisible )
1923 ShowCursor( FALSE ); // falls sich Cursor nach unten verschiebt
1924 nY -= pView->GetEntryHeight(); // wg. Linien
1925 InvalidateEntriesFrom( nY );
1927 else if( pStartEntry && nY < GetEntryLine(pStartEntry) )
1929 // pruefen, ob die View komplett gefuellt ist. Wenn
1930 // nicht, dann pStartEntry und den Cursor anpassen
1931 // (automatisches scrollen)
1932 USHORT nLast = (USHORT)(pView->GetVisiblePos( (SvLBoxEntry*)(pView->LastVisible())));
1933 USHORT nThumb = (USHORT)(pView->GetVisiblePos( pStartEntry ));
1934 USHORT nCurDispEntries = nLast-nThumb+1;
1935 if( nCurDispEntries < nVisibleCount )
1937 // beim naechsten Paint-Event setzen
1938 pStartEntry = 0;
1939 SetCursor( 0 );
1940 pView->Invalidate();
1943 else if( !pStartEntry )
1944 pView->Invalidate();
1946 // die Linien invalidieren
1948 if( (bEntryVisible || bPrevEntryVisible) &&
1949 (nWinBits & ( WB_HASLINES | WB_HASLINESATROOT )) )
1951 SvLBoxTab* pTab = pView->GetFirstDynamicTab();
1952 if( pTab )
1954 long nDX = pView->GetTabPos( pEntry, pTab );
1955 Point aTmpPoint;
1956 Size aSize( nDX, nY );
1957 Rectangle aRect( aTmpPoint, aSize );
1958 pView->Invalidate( aRect );
1963 SetMostRight( pEntry );
1964 aVerSBar.SetRange( Range(0, pView->GetVisibleCount()-1));
1965 SyncVerThumb(); // falls vor Thumb eingefuegt wurde
1966 ShowVerSBar();
1967 ShowCursor( TRUE );
1968 if( pStartEntry != pView->First() && (nFlags & F_FILLING) )
1969 pView->Update();
1975 // ********************************************************************
1976 // Eventhandler
1977 // ********************************************************************
1980 // ****** Steuerung der Controlanimation
1982 BOOL SvImpLBox::ButtonDownCheckCtrl(const MouseEvent& rMEvt, SvLBoxEntry* pEntry,
1983 long nY )
1985 SvLBoxItem* pItem = pView->GetItem(pEntry,rMEvt.GetPosPixel().X(),&pActiveTab);
1986 if( pItem && (pItem->IsA()==SV_ITEM_ID_LBOXBUTTON))
1988 pActiveButton = (SvLBoxButton*)pItem;
1989 pActiveEntry = pEntry;
1990 if( pCursor == pActiveEntry )
1991 pView->HideFocus();
1992 pView->CaptureMouse();
1993 pActiveButton->SetStateHilighted( TRUE );
1994 pView->PaintEntry1( pActiveEntry, nY,
1995 SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
1996 SV_LBOXTAB_ADJUST_RIGHT );
1997 return TRUE;
1999 else
2000 pActiveButton = 0;
2001 return FALSE;
2004 BOOL SvImpLBox::MouseMoveCheckCtrl( const MouseEvent& rMEvt, SvLBoxEntry* pEntry)
2006 if( pActiveButton )
2008 long nY;
2009 long nMouseX = rMEvt.GetPosPixel().X();
2010 if( pEntry == pActiveEntry &&
2011 pView->GetItem(pActiveEntry, nMouseX) == pActiveButton )
2013 if( !pActiveButton->IsStateHilighted() )
2015 pActiveButton->SetStateHilighted(TRUE );
2016 nY = GetEntryLine( pActiveEntry );
2017 pView->PaintEntry1( pActiveEntry, nY,
2018 SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
2019 SV_LBOXTAB_ADJUST_RIGHT );
2022 else
2024 if( pActiveButton->IsStateHilighted() )
2026 pActiveButton->SetStateHilighted(FALSE );
2027 nY = GetEntryLine( pActiveEntry );
2028 pView->PaintEntry1( pActiveEntry, nY, SV_LBOXTAB_PUSHABLE );
2031 return TRUE;
2033 return FALSE;
2036 BOOL SvImpLBox::ButtonUpCheckCtrl( const MouseEvent& rMEvt )
2038 if( pActiveButton )
2040 pView->ReleaseMouse();
2041 SvLBoxEntry* pEntry = GetClickedEntry( rMEvt.GetPosPixel() );
2042 long nY = GetEntryLine( pActiveEntry );
2043 pActiveButton->SetStateHilighted( FALSE );
2044 long nMouseX = rMEvt.GetPosPixel().X();
2045 if( pEntry == pActiveEntry &&
2046 pView->GetItem( pActiveEntry, nMouseX ) == pActiveButton )
2047 pActiveButton->ClickHdl( pView, pActiveEntry );
2048 pView->PaintEntry1( pActiveEntry, nY,
2049 SV_LBOXTAB_PUSHABLE | SV_LBOXTAB_ADJUST_CENTER |
2050 SV_LBOXTAB_ADJUST_RIGHT );
2051 if( pCursor == pActiveEntry )
2052 ShowCursor( TRUE );
2053 pActiveButton = 0;
2054 pActiveEntry = 0;
2055 pActiveTab = 0;
2056 return TRUE;
2058 return FALSE;
2061 // ******* Steuerung Plus/Minus-Button zum Expandieren/Kollabieren
2063 // FALSE == kein Expand/Collapse-Button getroffen
2064 BOOL SvImpLBox::IsNodeButton( const Point& rPosPixel, SvLBoxEntry* pEntry ) const
2066 if( !pEntry->HasChilds() && !pEntry->HasChildsOnDemand() )
2067 return FALSE;
2069 SvLBoxTab* pFirstDynamicTab = pView->GetFirstDynamicTab();
2070 if( !pFirstDynamicTab )
2071 return FALSE;
2073 long nMouseX = rPosPixel.X();
2074 // in Doc-Koords umrechnen
2075 Point aOrigin( pView->GetMapMode().GetOrigin() );
2076 nMouseX -= aOrigin.X();
2078 long nX = pView->GetTabPos( pEntry, pFirstDynamicTab);
2079 nX += nNodeBmpTabDistance;
2080 if( nMouseX < nX )
2081 return FALSE;
2082 nX += nNodeBmpWidth;
2083 if( nMouseX > nX )
2084 return FALSE;
2085 return TRUE;
2088 // FALSE == hit no node button
2089 BOOL SvImpLBox::ButtonDownCheckExpand( const MouseEvent& rMEvt, SvLBoxEntry* pEntry, long /* nY */ )
2091 BOOL bRet = FALSE;
2093 if ( pView->IsEditingActive() && pEntry == pView->pEdEntry )
2094 // inplace editing -> nothing to do
2095 bRet = TRUE;
2096 else if ( IsNodeButton( rMEvt.GetPosPixel(), pEntry ) )
2098 if ( pView->IsExpanded( pEntry ) )
2100 pView->EndEditing( TRUE );
2101 pView->Collapse( pEntry );
2103 else
2105 // you can expand an entry, which is in editing
2106 pView->Expand( pEntry );
2108 bRet = TRUE;
2111 return bRet;
2114 void SvImpLBox::MouseButtonDown( const MouseEvent& rMEvt )
2116 if ( !rMEvt.IsLeft() && !rMEvt.IsRight())
2117 return;
2119 #ifdef OS2
2120 // unter OS/2 kommt zwischen MouseButtonDown und
2121 // MouseButtonUp ein MouseMove
2122 nFlags |= F_IGNORE_NEXT_MOUSEMOVE;
2123 #endif
2124 aEditTimer.Stop();
2125 Point aPos( rMEvt.GetPosPixel());
2127 if( aPos.X() > aOutputSize.Width() || aPos.Y() > aOutputSize.Height() )
2128 return;
2130 SvLBoxEntry* pEntry = GetEntry( aPos );
2131 if ( pEntry != pCursor )
2132 // new entry selected -> reset current tab position to first tab
2133 nCurTabPos = FIRST_ENTRY_TAB;
2134 nFlags &= (~F_FILLING);
2135 pView->GrabFocus();
2136 // #120417# the entry can still be invalid!
2137 if( !pEntry || !pView->GetViewData( pEntry ))
2138 return;
2140 long nY = GetEntryLine( pEntry );
2141 // Node-Button?
2142 if( ButtonDownCheckExpand( rMEvt, pEntry, nY ) )
2143 return;
2145 if( !EntryReallyHit(pEntry,aPos,nY))
2146 return;
2148 SvLBoxItem* pXItem = pView->GetItem( pEntry, aPos.X() );
2149 if( pXItem )
2151 SvLBoxTab* pXTab = pView->GetTab( pEntry, pXItem );
2152 if ( !rMEvt.IsMod1() && !rMEvt.IsMod2() && rMEvt.IsLeft() && pXTab->IsEditable()
2153 && pEntry == pView->FirstSelected() && NULL == pView->NextSelected( pEntry ) )
2154 // #i8234# FirstSelected() and NextSelected() ensures, that inplace editing is only triggered, when only one entry is selected
2155 nFlags |= F_START_EDITTIMER;
2156 if ( !pView->IsSelected( pEntry ) )
2157 nFlags &= ~F_START_EDITTIMER;
2161 if( (rMEvt.GetClicks() % 2) == 0 )
2163 nFlags &= (~F_START_EDITTIMER);
2164 pView->pHdlEntry = pEntry;
2165 if( pView->DoubleClickHdl() )
2167 // falls im Handler der Eintrag geloescht wurde
2168 pEntry = GetClickedEntry( aPos );
2169 if( !pEntry )
2170 return;
2171 if( pEntry != pView->pHdlEntry )
2173 // neu selektieren & tschuess
2174 if( !bSimpleTravel && !aSelEng.IsAlwaysAdding())
2175 SelAllDestrAnch( FALSE, TRUE ); // DeselectAll();
2176 SetCursor( pEntry );
2178 DBG_ERROR( "Please report what you did to get this assertion to FS!" );
2179 // The entry which has been double-clicked changed - and we select it, again.
2180 // I have situations where this behaviour does not make any sense at all - even more, it
2181 // leads to hacks to revert it's results.
2182 // So I'm not sure if this behaviour here is nonsense (which I believe at the moment),
2183 // or if there are really scenarious where it dones make sense ....
2184 // 07.12.2001 - 95727 - fs@openoffice.org
2186 return;
2188 if( pEntry->HasChilds() || pEntry->HasChildsOnDemand() )
2190 if( pView->IsExpanded(pEntry) )
2191 pView->Collapse( pEntry );
2192 else
2193 pView->Expand( pEntry );
2194 if( pEntry == pCursor ) // nur wenn Entryitem angeklickt wurde
2195 // (Nodebutton ist kein Entryitem!)
2196 pView->Select( pCursor, TRUE );
2197 return;
2201 else
2203 // CheckButton? (TreeListBox: Check + Info)
2204 if( ButtonDownCheckCtrl(rMEvt, pEntry, nY) == TRUE)
2205 return;
2206 // Inplace-Editing?
2207 #if 0
2208 if( rMEvt.IsMod2() && pView->IsInplaceEditingEnabled() )
2210 SvLBoxItem* pItem = pView->GetItem( pEntry, aPos.X() );
2211 if( pItem )
2212 pView->EditingRequest( pEntry, pItem, aPos );
2213 return;
2215 #endif
2217 if ( aSelEng.GetSelectionMode() != NO_SELECTION )
2218 aSelEng.SelMouseButtonDown( rMEvt );
2221 void SvImpLBox::MouseButtonUp( const MouseEvent& rMEvt)
2223 #ifdef OS2
2224 nFlags &= (~F_IGNORE_NEXT_MOUSEMOVE);
2225 #endif
2226 if ( !ButtonUpCheckCtrl( rMEvt ) && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
2227 aSelEng.SelMouseButtonUp( rMEvt );
2228 EndScroll();
2229 if( nFlags & F_START_EDITTIMER )
2231 nFlags &= (~F_START_EDITTIMER);
2232 aEditClickPos = rMEvt.GetPosPixel();
2233 aEditTimer.Start();
2236 return;
2239 void SvImpLBox::MouseMove( const MouseEvent& rMEvt)
2241 #ifdef OS2
2242 if( nFlags & F_IGNORE_NEXT_MOUSEMOVE )
2244 nFlags &= (~F_IGNORE_NEXT_MOUSEMOVE);
2245 return;
2247 #endif
2248 SvLBoxEntry* pEntry = GetClickedEntry( rMEvt.GetPosPixel() );
2249 if ( !MouseMoveCheckCtrl( rMEvt, pEntry ) && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
2250 aSelEng.SelMouseMove( rMEvt );
2251 return;
2254 BOOL SvImpLBox::KeyInput( const KeyEvent& rKEvt)
2256 aEditTimer.Stop();
2257 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
2259 if( rKeyCode.IsMod2() )
2260 return FALSE; // Alt-Taste nicht auswerten
2262 nFlags &= (~F_FILLING);
2264 if( !pCursor )
2265 pCursor = pStartEntry;
2266 if( !pCursor )
2267 return FALSE;
2269 BOOL bKeyUsed = TRUE;
2271 USHORT nDelta = (USHORT)aVerSBar.GetPageSize();
2272 USHORT aCode = rKeyCode.GetCode();
2274 BOOL bShift = rKeyCode.IsShift();
2275 BOOL bMod1 = rKeyCode.IsMod1();
2277 SvLBoxEntry* pNewCursor;
2279 switch( aCode )
2281 case KEY_UP:
2282 if( !IsEntryInView( pCursor ) )
2283 MakeVisible( pCursor );
2285 pNewCursor = pCursor;
2288 pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pNewCursor ));
2289 } while( pNewCursor && !IsSelectable(pNewCursor) );
2291 if ( pNewCursor )
2292 // new entry selected -> reset current tab position to first tab
2293 nCurTabPos = FIRST_ENTRY_TAB;
2294 // if there is no next entry, take the current one
2295 // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
2296 // the cursor key
2297 // 06.09.20001 - 83416 - fs@openoffice.org
2298 if ( !pNewCursor && pCursor )
2299 pNewCursor = pCursor;
2301 if( pNewCursor )
2303 aSelEng.CursorPosChanging( bShift, bMod1 );
2304 SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2305 if( !IsEntryInView( pNewCursor ) )
2306 KeyUp( FALSE );
2308 break;
2310 case KEY_DOWN:
2311 if( !IsEntryInView( pCursor ) )
2312 MakeVisible( pCursor );
2314 pNewCursor = pCursor;
2317 pNewCursor = (SvLBoxEntry*)(pView->NextVisible( pNewCursor ));
2318 } while( pNewCursor && !IsSelectable(pNewCursor) );
2320 if ( pNewCursor )
2321 // new entry selected -> reset current tab position to first tab
2322 nCurTabPos = FIRST_ENTRY_TAB;
2324 // if there is no next entry, take the current one
2325 // this ensures that in case of _one_ entry in the list, this entry is selected when pressing
2326 // the cursor key
2327 // 06.09.20001 - 83416 - frank.schoenheit@sun.com
2328 if ( !pNewCursor && pCursor )
2329 pNewCursor = pCursor;
2331 if( pNewCursor )
2333 aSelEng.CursorPosChanging( bShift, bMod1 );
2334 if( IsEntryInView( pNewCursor ) )
2335 SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2336 else
2338 if( pCursor )
2339 pView->Select( pCursor, FALSE );
2340 KeyDown( FALSE );
2341 SetCursor( pNewCursor, bMod1 ); // no selection, when Ctrl is on
2344 else
2345 KeyDown( FALSE ); // weil ScrollBar-Range evtl. noch
2346 // scrollen erlaubt
2347 break;
2349 case KEY_RIGHT:
2351 if( bSubLstOpLR && IsNowExpandable() )
2352 pView->Expand( pCursor );
2353 else if ( bIsCellFocusEnabled && pCursor )
2355 if ( nCurTabPos < ( pView->TabCount() - 1 /*!2*/ ) )
2357 ++nCurTabPos;
2358 ShowCursor( TRUE );
2359 CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
2362 else if( pView->nWindowStyle & WB_HSCROLL )
2364 long nThumb = aHorSBar.GetThumbPos();
2365 nThumb += aHorSBar.GetLineSize();
2366 long nOldThumb = aHorSBar.GetThumbPos();
2367 aHorSBar.SetThumbPos( nThumb );
2368 nThumb = nOldThumb;
2369 nThumb -= aHorSBar.GetThumbPos();
2370 nThumb *= -1;
2371 if( nThumb )
2373 KeyLeftRight( nThumb );
2374 EndScroll();
2377 else
2378 bKeyUsed = FALSE;
2379 break;
2382 case KEY_LEFT:
2384 if ( bIsCellFocusEnabled )
2386 if ( nCurTabPos > FIRST_ENTRY_TAB )
2388 --nCurTabPos;
2389 ShowCursor( TRUE );
2390 CallEventListeners( VCLEVENT_LISTBOX_SELECT, pCursor );
2393 else if ( pView->nWindowStyle & WB_HSCROLL )
2395 long nThumb = aHorSBar.GetThumbPos();
2396 nThumb -= aHorSBar.GetLineSize();
2397 long nOldThumb = aHorSBar.GetThumbPos();
2398 aHorSBar.SetThumbPos( nThumb );
2399 nThumb = nOldThumb;
2400 nThumb -= aHorSBar.GetThumbPos();
2401 if( nThumb )
2403 KeyLeftRight( -nThumb );
2404 EndScroll();
2406 else if( bSubLstOpLR )
2408 if( IsExpandable() && pView->IsExpanded( pCursor ) )
2409 pView->Collapse( pCursor );
2410 else
2412 pNewCursor = pView->GetParent( pCursor );
2413 if( pNewCursor )
2414 SetCursor( pNewCursor );
2418 else if( bSubLstOpLR && IsExpandable() )
2419 pView->Collapse( pCursor );
2420 else
2421 bKeyUsed = FALSE;
2422 break;
2425 case KEY_PAGEUP:
2426 if( !bMod1 )
2428 pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pCursor, nDelta ));
2430 while( nDelta && pNewCursor && !IsSelectable(pNewCursor) )
2432 pNewCursor = (SvLBoxEntry*)(pView->NextVisible( pNewCursor ));
2433 nDelta--;
2436 if( nDelta )
2438 DBG_ASSERT(pNewCursor&&(ULONG)pNewCursor!=(ULONG)pCursor,"Cursor?");
2439 aSelEng.CursorPosChanging( bShift, bMod1 );
2440 if( IsEntryInView( pNewCursor ) )
2441 SetCursor( pNewCursor );
2442 else
2444 SetCursor( pNewCursor );
2445 KeyUp( TRUE );
2449 else
2450 bKeyUsed = FALSE;
2451 break;
2453 case KEY_PAGEDOWN:
2454 if( !bMod1 )
2456 pNewCursor= (SvLBoxEntry*)(pView->NextVisible( pCursor, nDelta ));
2458 while( nDelta && pNewCursor && !IsSelectable(pNewCursor) )
2460 pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pNewCursor ));
2461 nDelta--;
2464 if( nDelta )
2466 DBG_ASSERT(pNewCursor&&(ULONG)pNewCursor!=(ULONG)pCursor,"Cursor?");
2467 aSelEng.CursorPosChanging( bShift, bMod1 );
2468 if( IsEntryInView( pNewCursor ) )
2469 SetCursor( pNewCursor );
2470 else
2472 SetCursor( pNewCursor );
2473 KeyDown( TRUE );
2476 else
2477 KeyDown( FALSE ); // siehe KEY_DOWN
2479 else
2480 bKeyUsed = FALSE;
2481 break;
2483 case KEY_SPACE:
2484 if ( pView->GetSelectionMode() != NO_SELECTION )
2486 if ( bMod1 )
2488 if ( pView->GetSelectionMode() == MULTIPLE_SELECTION && !bShift )
2489 // toggle selection
2490 pView->Select( pCursor, !pView->IsSelected( pCursor ) );
2492 else if ( !bShift /*&& !bMod1*/ )
2494 if ( aSelEng.IsAddMode() )
2495 // toggle selection
2496 pView->Select( pCursor, !pView->IsSelected( pCursor ) );
2497 else
2499 SelAllDestrAnch( FALSE );
2500 pView->Select( pCursor, TRUE );
2503 else
2504 bKeyUsed = FALSE;
2506 else
2507 bKeyUsed = FALSE;
2508 break;
2510 case KEY_RETURN:
2511 if( bSubLstOpRet && IsExpandable() )
2513 if( pView->IsExpanded( pCursor ) )
2514 pView->Collapse( pCursor );
2515 else
2516 pView->Expand( pCursor );
2518 else
2519 bKeyUsed = FALSE;
2520 break;
2522 case KEY_F2:
2523 if( !bShift && !bMod1 )
2525 aEditClickPos = Point( -1, -1 );
2526 EditTimerCall( 0 );
2528 else
2529 bKeyUsed = FALSE;
2530 break;
2532 case KEY_F8:
2533 if( bShift && pView->GetSelectionMode()==MULTIPLE_SELECTION &&
2534 !(nWinBits & WB_SIMPLEMODE))
2536 if( aSelEng.IsAlwaysAdding() )
2537 aSelEng.AddAlways( FALSE );
2538 else
2539 aSelEng.AddAlways( TRUE );
2541 else
2542 bKeyUsed = FALSE;
2543 break;
2546 #ifdef OV_DEBUG
2547 case KEY_F9:
2548 MakeVisible( pCursor );
2549 break;
2550 case KEY_F10:
2551 pView->RemoveSelection();
2552 break;
2553 case KEY_DELETE:
2554 pView->RemoveEntry( pCursor );
2555 break;
2556 #endif
2558 case KEY_ADD:
2559 if( pCursor )
2561 if( !pView->IsExpanded(pCursor))
2562 pView->Expand( pCursor );
2563 if( bMod1 )
2565 USHORT nRefDepth = pTree->GetDepth( pCursor );
2566 SvLBoxEntry* pCur = pTree->Next( pCursor );
2567 while( pCur && pTree->GetDepth(pCur) > nRefDepth )
2569 if( pCur->HasChilds() && !pView->IsExpanded(pCur))
2570 pView->Expand( pCur );
2571 pCur = pTree->Next( pCur );
2575 else
2576 bKeyUsed = FALSE;
2577 break;
2579 case KEY_A:
2580 if( bMod1 )
2581 SelAllDestrAnch( TRUE );
2582 // else
2583 // bKeyUsed = FALSE; #105907# assume user wants to use quicksearch with key "a", so key is handled!
2584 break;
2586 case KEY_SUBTRACT:
2587 if( pCursor )
2589 if( pView->IsExpanded(pCursor))
2590 pView->Collapse( pCursor );
2591 if( bMod1 )
2593 // bis zur Root alle Parents einklappen
2594 SvLBoxEntry* pParentToCollapse = (SvLBoxEntry*)pTree->GetRootLevelParent(pCursor);
2595 if( pParentToCollapse )
2597 USHORT nRefDepth;
2598 // Sonderbehandlung Explorer: Befindet sich auf der
2599 // Root nur ein Eintrag,dann den Root-Entry nicht
2600 // einklappen
2601 if( pTree->GetChildList(0)->Count() < 2 )
2603 nRefDepth = 1;
2604 pParentToCollapse = pCursor;
2605 while( pTree->GetParent(pParentToCollapse) &&
2606 pTree->GetDepth( pTree->GetParent(pParentToCollapse)) > 0)
2608 pParentToCollapse = pTree->GetParent(pParentToCollapse);
2611 else
2612 nRefDepth = 0;
2614 if( pView->IsExpanded(pParentToCollapse) )
2615 pView->Collapse( pParentToCollapse );
2616 SvLBoxEntry* pCur = pTree->Next( pParentToCollapse );
2617 while( pCur && pTree->GetDepth(pCur) > nRefDepth )
2619 if( pCur->HasChilds() && pView->IsExpanded(pCur) )
2620 pView->Collapse( pCur );
2621 pCur = pTree->Next( pCur );
2626 else
2627 bKeyUsed = FALSE;
2628 break;
2630 case KEY_DIVIDE :
2631 if( bMod1 )
2632 SelAllDestrAnch( TRUE );
2633 else
2634 bKeyUsed = FALSE;
2635 break;
2637 case KEY_COMMA :
2638 if( bMod1 )
2639 SelAllDestrAnch( FALSE );
2640 else
2641 bKeyUsed = FALSE;
2642 break;
2644 case KEY_HOME :
2645 pNewCursor = pView->GetModel()->First();
2647 while( pNewCursor && !IsSelectable(pNewCursor) )
2649 pNewCursor = (SvLBoxEntry*)(pView->NextVisible( pNewCursor ));
2652 if( pNewCursor && pNewCursor != pCursor )
2654 // SelAllDestrAnch( FALSE );
2655 aSelEng.CursorPosChanging( bShift, bMod1 );
2656 SetCursor( pNewCursor );
2657 if( !IsEntryInView( pNewCursor ) )
2658 MakeVisible( pNewCursor );
2660 else
2661 bKeyUsed = FALSE;
2662 break;
2664 case KEY_END :
2665 pNewCursor = pView->GetModel()->Last();
2667 while( pNewCursor && !IsSelectable(pNewCursor) )
2669 pNewCursor = (SvLBoxEntry*)(pView->PrevVisible( pNewCursor ));
2672 if( pNewCursor && pNewCursor != pCursor)
2674 // SelAllDestrAnch( FALSE );
2675 aSelEng.CursorPosChanging( bShift, bMod1 );
2676 SetCursor( pNewCursor );
2677 if( !IsEntryInView( pNewCursor ) )
2678 MakeVisible( pNewCursor );
2680 else
2681 bKeyUsed = FALSE;
2682 break;
2684 case KEY_ESCAPE:
2685 case KEY_TAB:
2686 case KEY_DELETE:
2687 case KEY_BACKSPACE:
2688 // #105907# must not be handled because this quits dialogs and does other magic things...
2689 // if there are other single keys which should not be handled, they can be added here
2690 bKeyUsed = FALSE;
2691 break;
2693 default:
2694 if( bMod1 || rKeyCode.GetGroup() == KEYGROUP_FKEYS )
2695 // #105907# CTRL or Function key is pressed, assume user don't want to use quicksearch...
2696 // if there are groups of keys which should not be handled, they can be added here
2697 bKeyUsed = FALSE;
2699 return bKeyUsed;
2702 void __EXPORT SvImpLBox::GetFocus()
2704 if( pCursor )
2706 pView->SetEntryFocus( pCursor, TRUE );
2707 ShowCursor( TRUE );
2708 // auskommentiert wg. deselectall
2709 // if( bSimpleTravel && !pView->IsSelected(pCursor) )
2710 // pView->Select( pCursor, TRUE );
2712 if( nWinBits & WB_HIDESELECTION )
2714 SvLBoxEntry* pEntry = pView->FirstSelected();
2715 while( pEntry )
2717 InvalidateEntry( pEntry );
2718 pEntry = pView->NextSelected( pEntry );
2721 SvLBoxEntry* pEntry = pView->GetModel()->First();
2722 while( pEntry )
2724 SvViewData* pViewData = pView->GetViewData( pEntry );
2725 if( pViewData->IsCursored() )
2727 pViewData->SetCursored( FALSE );
2728 InvalidateEntry( pEntry );
2730 pEntry = pView->GetModel()->Next( pEntry );
2738 void __EXPORT SvImpLBox::LoseFocus()
2740 aEditTimer.Stop();
2741 if( pCursor )
2742 pView->SetEntryFocus( pCursor,FALSE );
2743 ShowCursor( FALSE );
2745 if( nWinBits & WB_HIDESELECTION )
2747 SvLBoxEntry* pEntry = pView->FirstSelected();
2748 while( pEntry )
2750 //SvViewData* pViewData = pView->GetViewData( pEntry );
2751 //pViewData->SetCursored( TRUE );
2752 InvalidateEntry( pEntry );
2753 pEntry = pView->NextSelected( pEntry );
2759 // ********************************************************************
2760 // SelectionEngine
2761 // ********************************************************************
2763 inline void SvImpLBox::SelectEntry( SvLBoxEntry* pEntry, BOOL bSelect )
2765 pView->Select( pEntry, bSelect );
2768 __EXPORT ImpLBSelEng::ImpLBSelEng( SvImpLBox* pImpl, SelectionEngine* pSEng,
2769 SvTreeListBox* pV )
2771 pImp = pImpl;
2772 pSelEng = pSEng;
2773 pView = pV;
2776 __EXPORT ImpLBSelEng::~ImpLBSelEng()
2780 void __EXPORT ImpLBSelEng::BeginDrag()
2782 pImp->BeginDrag();
2786 void __EXPORT ImpLBSelEng::EndDrag( const Point& )
2791 void __EXPORT ImpLBSelEng::CreateAnchor()
2793 pImp->pAnchor = pImp->pCursor;
2796 void __EXPORT ImpLBSelEng::DestroyAnchor()
2798 pImp->pAnchor = 0;
2802 void __EXPORT ImpLBSelEng::CreateCursor()
2804 pImp->pAnchor = 0;
2809 BOOL __EXPORT ImpLBSelEng::SetCursorAtPoint(const Point& rPoint, BOOL bDontSelectAtCursor)
2811 SvLBoxEntry* pNewCursor = pImp->MakePointVisible( rPoint );
2812 if( pNewCursor != pImp->pCursor )
2813 pImp->BeginScroll();
2815 if( pNewCursor )
2817 // bei SimpleTravel wird in SetCursor selektiert und
2818 // der Select-Handler gerufen
2819 //if( !bDontSelectAtCursor && !pImp->bSimpleTravel )
2820 // pImp->SelectEntry( pNewCursor, TRUE );
2821 pImp->SetCursor( pNewCursor, bDontSelectAtCursor );
2822 return TRUE;
2824 return FALSE;
2827 BOOL __EXPORT ImpLBSelEng::IsSelectionAtPoint( const Point& rPoint )
2829 SvLBoxEntry* pEntry = pImp->MakePointVisible( rPoint );
2830 if( pEntry )
2831 return pView->IsSelected(pEntry);
2832 return FALSE;
2835 void __EXPORT ImpLBSelEng::DeselectAtPoint( const Point& rPoint )
2837 SvLBoxEntry* pEntry = pImp->MakePointVisible( rPoint );
2838 if( !pEntry )
2839 return;
2840 pImp->SelectEntry( pEntry, FALSE );
2844 void __EXPORT ImpLBSelEng::SelectAtPoint( const Point& rPoint )
2846 SvLBoxEntry* pEntry = pImp->MakePointVisible( rPoint );
2847 if( !pEntry )
2848 return;
2849 pImp->SelectEntry( pEntry, TRUE );
2853 void __EXPORT ImpLBSelEng::DeselectAll()
2855 pImp->SelAllDestrAnch( FALSE, FALSE ); // SelectionEngine nicht resetten!
2856 pImp->nFlags &= (~F_DESEL_ALL);
2859 // ***********************************************************************
2860 // Selektion
2861 // ***********************************************************************
2863 void SvImpLBox::SetAnchorSelection(SvLBoxEntry* pOldCursor,SvLBoxEntry* pNewCursor)
2865 SvLBoxEntry* pEntry;
2866 ULONG nAnchorVisPos = pView->GetVisiblePos( pAnchor );
2867 ULONG nOldVisPos = pView->GetVisiblePos( pOldCursor );
2868 ULONG nNewVisPos = pView->GetVisiblePos( pNewCursor );
2870 if( nOldVisPos > nAnchorVisPos ||
2871 ( nAnchorVisPos==nOldVisPos && nNewVisPos > nAnchorVisPos) )
2873 if( nNewVisPos > nOldVisPos )
2875 pEntry = pOldCursor;
2876 while( pEntry && pEntry != pNewCursor )
2878 pView->Select( pEntry, TRUE );
2879 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2881 if( pEntry )
2882 pView->Select( pEntry, TRUE );
2883 return;
2886 if( nNewVisPos < nAnchorVisPos )
2888 pEntry = pAnchor;
2889 while( pEntry && pEntry != pOldCursor )
2891 pView->Select( pEntry, FALSE );
2892 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2894 if( pEntry )
2895 pView->Select( pEntry, FALSE );
2897 pEntry = pNewCursor;
2898 while( pEntry && pEntry != pAnchor )
2900 pView->Select( pEntry, TRUE );
2901 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2903 if( pEntry )
2904 pView->Select( pEntry, TRUE );
2905 return;
2908 if( nNewVisPos < nOldVisPos )
2910 pEntry = pNewCursor;
2911 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2912 while( pEntry && pEntry != pOldCursor )
2914 pView->Select( pEntry, FALSE );
2915 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2917 if( pEntry )
2918 pView->Select( pEntry, FALSE );
2919 return;
2922 else
2924 if( nNewVisPos < nOldVisPos ) // Vergroessern der Selektion
2926 pEntry = pNewCursor;
2927 while( pEntry && pEntry != pOldCursor )
2929 pView->Select( pEntry, TRUE );
2930 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2932 if( pEntry )
2933 pView->Select( pEntry, TRUE );
2934 return;
2937 if( nNewVisPos > nAnchorVisPos )
2939 pEntry = pOldCursor;
2940 while( pEntry && pEntry != pAnchor )
2942 pView->Select( pEntry, FALSE );
2943 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2945 if( pEntry )
2946 pView->Select( pEntry, FALSE );
2947 pEntry = pAnchor;
2948 while( pEntry && pEntry != pNewCursor )
2950 pView->Select( pEntry, TRUE );
2951 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2953 if( pEntry )
2954 pView->Select( pEntry, TRUE );
2955 return;
2958 if( nNewVisPos > nOldVisPos )
2960 pEntry = pOldCursor;
2961 while( pEntry && pEntry != pNewCursor )
2963 pView->Select( pEntry, FALSE );
2964 pEntry = (SvLBoxEntry*)(pView->NextVisible( pEntry ));
2966 return;
2971 void SvImpLBox::SelAllDestrAnch( BOOL bSelect, BOOL bDestroyAnchor,
2972 BOOL bSingleSelToo )
2974 SvLBoxEntry* pEntry;
2975 nFlags &= (~F_DESEL_ALL);
2976 if( bSelect && bSimpleTravel )
2978 if( pCursor && !pView->IsSelected( pCursor ))
2980 pView->Select( pCursor, TRUE );
2982 return;
2984 if( !bSelect && pView->GetSelectionCount() == 0 )
2986 if( bSimpleTravel && ( !GetUpdateMode() || !pCursor) )
2987 nFlags |= F_DESEL_ALL;
2988 return;
2990 if( bSelect && pView->GetSelectionCount() == pView->GetEntryCount())
2991 return;
2992 if( !bSingleSelToo && bSimpleTravel )
2993 return;
2995 if( !bSelect && pView->GetSelectionCount()==1 && pCursor &&
2996 pView->IsSelected( pCursor ))
2998 pView->Select( pCursor, FALSE );
2999 if( bDestroyAnchor )
3000 DestroyAnchor(); // Anker loeschen & SelectionEngine zuruecksetzen
3001 else
3002 pAnchor = 0; // internen Anker immer loeschen
3003 return;
3006 if( bSimpleTravel && !pCursor && !GetUpdateMode() )
3007 nFlags |= F_DESEL_ALL;
3009 ShowCursor( FALSE );
3010 BOOL bUpdate = GetUpdateMode();
3012 nFlags |= F_IGNORE_SELECT; // EntryInserted soll nix tun
3013 pEntry = pTree->First();
3014 while( pEntry )
3016 if( pView->Select( pEntry, bSelect ) )
3018 if( bUpdate && pView->IsEntryVisible(pEntry) )
3020 long nY = GetEntryLine( pEntry );
3021 if( IsLineVisible( nY ) )
3022 pView->PaintEntry1( pEntry, nY, 0xffff ); // wg. ItemsetBrowser SV_LBOXTAB_SHOW_SELECTION );
3025 pEntry = pTree->Next( pEntry );
3027 nFlags &= ~F_IGNORE_SELECT;
3029 if( bDestroyAnchor )
3030 DestroyAnchor(); // Anker loeschen & SelectionEngine zuruecksetzen
3031 else
3032 pAnchor = 0; // internen Anker immer loeschen
3033 ShowCursor( TRUE );
3036 void SvImpLBox::SetSelectionMode( SelectionMode eSelMode )
3038 aSelEng.SetSelectionMode( eSelMode);
3039 if( eSelMode == SINGLE_SELECTION )
3040 bSimpleTravel = TRUE;
3041 else
3042 bSimpleTravel = FALSE;
3043 if( (nWinBits & WB_SIMPLEMODE) && (eSelMode == MULTIPLE_SELECTION) )
3044 aSelEng.AddAlways( TRUE );
3047 // ***********************************************************************
3048 // Drag & Drop
3049 // ***********************************************************************
3051 void SvImpLBox::SetDragDropMode( DragDropMode eDDMode )
3053 if( eDDMode && eDDMode != SV_DRAGDROP_APP_DROP )
3055 aSelEng.ExpandSelectionOnMouseMove( FALSE );
3056 aSelEng.EnableDrag( TRUE );
3058 else
3060 aSelEng.ExpandSelectionOnMouseMove( TRUE );
3061 aSelEng.EnableDrag( FALSE );
3065 void SvImpLBox::BeginDrag()
3067 nFlags &= (~F_FILLING);
3068 if( !bAsyncBeginDrag )
3070 BeginScroll();
3071 pView->StartDrag( 0, aSelEng.GetMousePosPixel() );
3072 EndScroll();
3074 else
3076 aAsyncBeginDragPos = aSelEng.GetMousePosPixel();
3077 aAsyncBeginDragTimer.Start();
3081 IMPL_LINK( SvImpLBox, BeginDragHdl, void*, EMPTYARG )
3083 pView->StartDrag( 0, aAsyncBeginDragPos );
3084 return 0;
3087 void SvImpLBox::PaintDDCursor( SvLBoxEntry* pInsertionPos )
3089 long nY;
3090 if( pInsertionPos )
3092 nY = GetEntryLine( pInsertionPos );
3093 nY += pView->GetEntryHeight();
3095 else
3096 nY = 1;
3097 RasterOp eOldOp = pView->GetRasterOp();
3098 pView->SetRasterOp( ROP_INVERT );
3099 Color aOldLineColor = pView->GetLineColor();
3100 pView->SetLineColor( Color( COL_BLACK ) );
3101 pView->DrawLine( Point( 0, nY ), Point( aOutputSize.Width(), nY ) );
3102 pView->SetLineColor( aOldLineColor );
3103 pView->SetRasterOp( eOldOp );
3105 /* -----------------26.08.2003 12:52-----------------
3106 Delete all sub menues of a PopupMenu, recursively
3107 --------------------------------------------------*/
3108 void lcl_DeleteSubPopups(PopupMenu* pPopup)
3110 for(USHORT i = 0; i < pPopup->GetItemCount(); i++)
3112 PopupMenu* pSubPopup = pPopup->GetPopupMenu( pPopup->GetItemId( i ));
3113 if(pSubPopup)
3115 lcl_DeleteSubPopups(pSubPopup);
3116 delete pSubPopup;
3121 void SvImpLBox::Command( const CommandEvent& rCEvt )
3123 USHORT nCommand = rCEvt.GetCommand();
3125 if( nCommand == COMMAND_CONTEXTMENU )
3126 aEditTimer.Stop();
3128 // Rollmaus-Event?
3129 if( ( ( nCommand == COMMAND_WHEEL ) || ( nCommand == COMMAND_STARTAUTOSCROLL ) || ( nCommand == COMMAND_AUTOSCROLL ) )
3130 && pView->HandleScrollCommand( rCEvt, &aHorSBar, &aVerSBar ) )
3131 return;
3133 if( bContextMenuHandling && nCommand == COMMAND_CONTEXTMENU )
3135 Point aPopupPos;
3136 BOOL bClickedIsFreePlace = FALSE;
3137 std::stack<SvLBoxEntry*> aSelRestore;
3139 if( rCEvt.IsMouseEvent() )
3140 { // change selection, if mouse pos doesn't fit to selection
3142 aPopupPos = rCEvt.GetMousePosPixel();
3144 SvLBoxEntry* pClickedEntry = GetEntry( aPopupPos );
3145 if( pClickedEntry )
3146 { // mouse in non empty area
3147 BOOL bClickedIsSelected = FALSE;
3149 // collect the currently selected entries
3150 SvLBoxEntry* pSelected = pView->FirstSelected();
3151 while( pSelected )
3153 bClickedIsSelected |= ( pClickedEntry == pSelected );
3154 pSelected = pView->NextSelected( pSelected );
3157 // if the entry which the user clicked at is not selected
3158 if( !bClickedIsSelected )
3159 { // deselect all other and select the clicked one
3160 pView->SelectAll( FALSE );
3161 pView->SetCursor( pClickedEntry );
3164 else if( aSelEng.GetSelectionMode() == SINGLE_SELECTION )
3165 {//modified by BerryJia for fixing Bug102739 2002-9-9 17:00(Beijing Time)
3166 bClickedIsFreePlace = TRUE;
3167 INT32 nSelectedEntries = pView->GetSelectionCount();
3168 SvLBoxEntry* pSelected = pView->FirstSelected();
3169 for(USHORT nSel = 0; nSel < nSelectedEntries; nSel++ )
3171 aSelRestore.push(pSelected);
3172 pSelected = pView->NextSelected( pSelected );
3174 pView->SelectAll( FALSE );
3176 else
3177 { // deselect all
3178 pView->SelectAll( FALSE );
3183 else
3184 { // key event (or at least no mouse event)
3185 INT32 nSelectionCount = pView->GetSelectionCount();
3187 if( nSelectionCount )
3188 { // now allways take first visible as base for positioning the menu
3189 SvLBoxEntry* pSelected = pView->FirstSelected();
3190 while( pSelected )
3192 if( IsEntryInView( pSelected ) )
3193 break;
3195 pSelected = pView->NextSelected( pSelected );
3198 if( !pSelected )
3200 // no one was visible
3201 pSelected = pView->FirstSelected();
3202 pView->MakeVisible( pSelected );
3205 aPopupPos = pView->GetFocusRect( pSelected, pView->GetEntryPosition( pSelected ).Y() ).Center();
3207 else
3208 aPopupPos = Point( 0, 0 );
3211 PopupMenu* pPopup = pView->CreateContextMenu();
3213 if( pPopup )
3215 // do action for selected entry in popup menu
3216 USHORT nMenuAction = pPopup->Execute( pView, aPopupPos );
3217 if ( nMenuAction )
3218 pView->ExcecuteContextMenuAction( nMenuAction );
3219 lcl_DeleteSubPopups(pPopup);
3220 delete pPopup;
3222 //added by BerryJia for fixing Bug102739 2002-9-9 17:00(Beijing Time)
3223 if( bClickedIsFreePlace )
3225 while(!aSelRestore.empty())
3227 SvLBoxEntry* pEntry = aSelRestore.top();
3228 //#i19717# the entry is maybe already deleted
3229 bool bFound = false;
3230 for(ULONG nEntry = 0; nEntry < pView->GetEntryCount(); nEntry++)
3231 if(pEntry == pView->GetEntry(nEntry))
3233 bFound = true;
3234 break;
3236 if(bFound)
3237 SetCurEntry( pEntry );
3238 aSelRestore.pop();
3242 #ifndef NOCOMMAND
3243 else
3245 const Point& rPos = rCEvt.GetMousePosPixel();
3246 if( rPos.X() < aOutputSize.Width() && rPos.Y() < aOutputSize.Height() )
3247 aSelEng.Command( rCEvt );
3249 #endif
3252 void SvImpLBox::BeginScroll()
3254 if( !(nFlags & F_IN_SCROLLING))
3256 pView->NotifyBeginScroll();
3257 nFlags |= F_IN_SCROLLING;
3261 void SvImpLBox::EndScroll()
3263 if( nFlags & F_IN_SCROLLING)
3265 pView->NotifyEndScroll();
3266 nFlags &= (~F_IN_SCROLLING);
3271 Rectangle SvImpLBox::GetVisibleArea() const
3273 Point aPos( pView->GetMapMode().GetOrigin() );
3274 aPos.X() *= -1;
3275 Rectangle aRect( aPos, aOutputSize );
3276 return aRect;
3279 void SvImpLBox::Invalidate()
3281 pView->SetClipRegion();
3284 void SvImpLBox::SetCurEntry( SvLBoxEntry* pEntry )
3286 if ( ( aSelEng.GetSelectionMode() != SINGLE_SELECTION )
3287 && ( aSelEng.GetSelectionMode() != NO_SELECTION )
3289 SelAllDestrAnch( FALSE, TRUE, FALSE );
3290 if ( pEntry )
3291 MakeVisible( pEntry );
3292 SetCursor( pEntry );
3293 if ( pEntry && ( aSelEng.GetSelectionMode() != NO_SELECTION ) )
3294 pView->Select( pEntry, TRUE );
3297 IMPL_LINK( SvImpLBox, EditTimerCall, Timer *, EMPTYARG )
3299 if( pView->IsInplaceEditingEnabled() )
3301 sal_Bool bIsMouseTriggered = aEditClickPos.X() >= 0;
3302 if ( bIsMouseTriggered )
3304 Point aCurrentMousePos = pView->GetPointerPosPixel();
3305 if ( ( abs( aCurrentMousePos.X() - aEditClickPos.X() ) > 5 )
3306 || ( abs( aCurrentMousePos.Y() - aEditClickPos.Y() ) > 5 )
3309 return 0L;
3313 SvLBoxEntry* pEntry = GetCurEntry();
3314 if( pEntry )
3316 ShowCursor( FALSE );
3317 pView->ImplEditEntry( pEntry );
3318 ShowCursor( TRUE );
3321 return 0;
3324 BOOL SvImpLBox::RequestHelp( const HelpEvent& rHEvt )
3326 if( rHEvt.GetMode() & HELPMODE_QUICK )
3328 Point aPos( pView->ScreenToOutputPixel( rHEvt.GetMousePosPixel() ));
3329 if( !GetVisibleArea().IsInside( aPos ))
3330 return FALSE;
3332 SvLBoxEntry* pEntry = GetEntry( aPos );
3333 if( pEntry )
3335 // Rechteck des Textes berechnen
3336 SvLBoxTab* pTab;
3337 SvLBoxString* pItem = (SvLBoxString*)(pView->GetItem( pEntry, aPos.X(), &pTab ));
3338 if( !pItem || pItem->IsA() != SV_ITEM_ID_LBOXSTRING )
3339 return FALSE;
3341 aPos = GetEntryPosition( pEntry );
3342 aPos.X() = pView->GetTabPos( pEntry, pTab ); //pTab->GetPos();
3343 Size aSize( pItem->GetSize( pView, pEntry ) );
3344 SvLBoxTab* pNextTab = NextTab( pTab );
3345 BOOL bItemClipped = FALSE;
3346 // wurde das Item von seinem rechten Nachbarn abgeschnitten?
3347 if( pNextTab && pView->GetTabPos(pEntry,pNextTab) < aPos.X()+aSize.Width() )
3349 aSize.Width() = pNextTab->GetPos() - pTab->GetPos();
3350 bItemClipped = TRUE;
3352 Rectangle aItemRect( aPos, aSize );
3354 Rectangle aViewRect( GetVisibleArea() );
3356 if( bItemClipped || !aViewRect.IsInside( aItemRect ) )
3358 // rechten Item-Rand am View-Rand clippen
3359 //if( aItemRect.Right() > aViewRect.Right() )
3360 // aItemRect.Right() = aViewRect.Right();
3362 Point aPt = pView->OutputToScreenPixel( aItemRect.TopLeft() );
3363 aItemRect.Left() = aPt.X();
3364 aItemRect.Top() = aPt.Y();
3365 aPt = pView->OutputToScreenPixel( aItemRect.BottomRight() );
3366 aItemRect.Right() = aPt.X();
3367 aItemRect.Bottom() = aPt.Y();
3369 Help::ShowQuickHelp( pView, aItemRect,
3370 pItem->GetText(), QUICKHELP_LEFT | QUICKHELP_VCENTER );
3371 return TRUE;
3375 return FALSE;
3378 SvLBoxTab* SvImpLBox::NextTab( SvLBoxTab* pTab )
3380 USHORT nTabCount = pView->TabCount();
3381 if( nTabCount <= 1 )
3382 return 0;
3383 for( USHORT nTab=0; nTab < (nTabCount-1); nTab++)
3385 if( pView->aTabs[nTab]==pTab )
3386 return (SvLBoxTab*)(pView->aTabs[nTab+1]);
3388 return 0;
3391 void SvImpLBox::EndSelection()
3393 DestroyAnchor();
3394 nFlags &= ~F_START_EDITTIMER;
3397 void SvImpLBox::RepaintScrollBars()
3401 void SvImpLBox::SetUpdateMode( BOOL bMode )
3403 if( bUpdateMode != bMode )
3405 bUpdateMode = bMode;
3406 if( bUpdateMode )
3407 UpdateAll( FALSE );
3411 void SvImpLBox::SetUpdateModeFast( BOOL bMode )
3413 if( bUpdateMode != bMode )
3415 bUpdateMode = bMode;
3416 if( bUpdateMode )
3417 UpdateAll( FALSE, FALSE );
3422 BOOL SvImpLBox::SetMostRight( SvLBoxEntry* pEntry )
3424 if( pView->nTreeFlags & TREEFLAG_RECALCTABS )
3426 nFlags |= F_IGNORE_CHANGED_TABS;
3427 pView->SetTabs();
3428 nFlags &= ~F_IGNORE_CHANGED_TABS;
3431 USHORT nLastTab = pView->aTabs.Count() - 1;
3432 USHORT nLastItem = pEntry->ItemCount() - 1;
3433 if( nLastTab != USHRT_MAX && nLastItem != USHRT_MAX )
3435 if( nLastItem < nLastTab )
3436 nLastTab = nLastItem;
3438 SvLBoxTab* pTab = (SvLBoxTab*)pView->aTabs[ nLastTab ];
3439 SvLBoxItem* pItem = pEntry->GetItem( nLastTab );
3441 long nTabPos = pView->GetTabPos( pEntry, pTab );
3443 long nMaxRight = GetOutputSize().Width();
3444 Point aPos( pView->GetMapMode().GetOrigin() );
3445 aPos.X() *= -1; // Umrechnung Dokumentkoord.
3446 nMaxRight = nMaxRight + aPos.X() - 1;
3448 long nNextTab = nTabPos < nMaxRight ? nMaxRight : nMaxRight + 50;
3449 long nTabWidth = nNextTab - nTabPos + 1;
3450 long nItemSize = pItem->GetSize(pView,pEntry).Width();
3451 long nOffset = pTab->CalcOffset( nItemSize, nTabWidth );
3453 long nRight = nTabPos + nOffset + nItemSize;
3454 if( nRight > nMostRight )
3456 nMostRight = nRight;
3457 pMostRightEntry = pEntry;
3458 return TRUE;
3461 return FALSE;
3464 void SvImpLBox::FindMostRight( SvLBoxEntry* pEntryToIgnore )
3466 nMostRight = -1;
3467 pMostRightEntry = 0;
3468 if( !pView->GetModel() )
3469 return;
3471 SvLBoxEntry* pEntry = (SvLBoxEntry*)pView->FirstVisible();
3472 while( pEntry )
3474 if( pEntry != pEntryToIgnore )
3475 SetMostRight( pEntry );
3476 pEntry = (SvLBoxEntry*)pView->NextVisible( pEntry );
3480 void SvImpLBox::FindMostRight( SvLBoxEntry* pParent, SvLBoxEntry* pEntryToIgnore )
3482 if( !pParent )
3483 FindMostRight( pEntryToIgnore );
3484 else
3485 FindMostRight_Impl( pParent, pEntryToIgnore );
3488 void SvImpLBox::FindMostRight_Impl( SvLBoxEntry* pParent, SvLBoxEntry* pEntryToIgnore )
3490 SvTreeEntryList* pList = pTree->GetChildList( pParent );
3492 if( !pList )
3493 return;
3495 ULONG nCount = pList->Count();
3496 for( ULONG nCur = 0; nCur < nCount; nCur++ )
3498 SvLBoxEntry* pChild = (SvLBoxEntry*)pList->GetObject( nCur );
3499 if( pChild != pEntryToIgnore )
3501 SetMostRight( pChild );
3502 if( pChild->HasChilds() && pView->IsExpanded( pChild ))
3503 FindMostRight_Impl( pChild, pEntryToIgnore );
3508 void SvImpLBox::NotifyTabsChanged()
3510 if( GetUpdateMode() && !(nFlags & F_IGNORE_CHANGED_TABS ) &&
3511 nCurUserEvent == 0xffffffff )
3513 nCurUserEvent = Application::PostUserEvent(LINK(this,SvImpLBox,MyUserEvent),(void*)0);
3517 IMPL_LINK(SvImpLBox,MyUserEvent,void*, pArg )
3519 nCurUserEvent = 0xffffffff;
3520 if( !pArg )
3522 pView->Invalidate();
3523 pView->Update();
3525 else
3527 FindMostRight( 0 );
3528 ShowVerSBar();
3529 pView->Invalidate( GetVisibleArea() );
3531 return 0;
3535 void SvImpLBox::StopUserEvent()
3537 if( nCurUserEvent != 0xffffffff )
3539 Application::RemoveUserEvent( nCurUserEvent );
3540 nCurUserEvent = 0xffffffff;
3544 void SvImpLBox::ShowFocusRect( const SvLBoxEntry* pEntry )
3546 if( pEntry )
3548 long nY = GetEntryLine( (SvLBoxEntry*)pEntry );
3549 Rectangle aRect = pView->GetFocusRect( (SvLBoxEntry*)pEntry, nY );
3550 Region aOldClip( pView->GetClipRegion());
3551 Region aClipRegion( GetClipRegionRect() );
3552 pView->SetClipRegion( aClipRegion );
3553 pView->ShowFocus( aRect );
3554 pView->SetClipRegion( aOldClip );
3557 else
3559 pView->HideFocus();
3563 void SvImpLBox::SetTabBar( TabBar* _pTabBar )
3565 pTabBar = _pTabBar;
3568 void SvImpLBox::CancelPendingEdit()
3570 if( aEditTimer.IsActive() )
3571 aEditTimer.Stop();
3572 nFlags &= ~F_START_EDITTIMER;
3575 // -----------------------------------------------------------------------
3576 void SvImpLBox::implInitDefaultNodeImages()
3578 if ( s_pDefCollapsed )
3579 // assume that all or nothing is initialized
3580 return;
3582 s_pDefCollapsed = new Image( SvtResId( RID_IMG_TREENODE_COLLAPSED ) );
3583 s_pDefCollapsedHC = new Image( SvtResId( RID_IMG_TREENODE_COLLAPSED_HC ) );
3584 s_pDefExpanded = new Image( SvtResId( RID_IMG_TREENODE_EXPANDED ) );
3585 s_pDefExpandedHC = new Image( SvtResId( RID_IMG_TREENODE_EXPANDED_HC ) );
3588 // -----------------------------------------------------------------------
3589 const Image& SvImpLBox::GetDefaultExpandedNodeImage( BmpColorMode _eMode )
3591 implInitDefaultNodeImages();
3592 return ( BMP_COLOR_NORMAL == _eMode ) ? *s_pDefExpanded : *s_pDefExpandedHC;
3595 // -----------------------------------------------------------------------
3596 const Image& SvImpLBox::GetDefaultCollapsedNodeImage( BmpColorMode _eMode )
3598 implInitDefaultNodeImages();
3599 return ( BMP_COLOR_NORMAL == _eMode ) ? *s_pDefCollapsed : *s_pDefCollapsedHC;
3602 // -----------------------------------------------------------------------
3603 void SvImpLBox::CallEventListeners( ULONG nEvent, void* pData )
3605 if ( pView )
3606 pView->CallImplEventListeners( nEvent, pData);
3609 // -----------------------------------------------------------------------
3611 bool SvImpLBox::SetCurrentTabPos( USHORT _nNewPos )
3613 bool bRet = false;
3615 if ( pView && _nNewPos < ( pView->TabCount() - 2 ) )
3617 nCurTabPos = _nNewPos;
3618 ShowCursor( TRUE );
3619 bRet = true;
3622 return bRet;
3625 // -----------------------------------------------------------------------
3627 bool SvImpLBox::IsSelectable( const SvLBoxEntry* pEntry )
3629 if( pEntry )
3631 SvViewDataEntry* pViewDataNewCur = pView->GetViewDataEntry(const_cast<SvLBoxEntry*>(pEntry));
3632 return (pViewDataNewCur == 0) || pViewDataNewCur->IsSelectable();
3634 else
3636 return false;