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