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