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