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