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