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 27 #define _SVTREEBX_CXX 28 #include <vcl/svapp.hxx> 29 #ifndef GCC 30 #endif 31 32 class TabBar; 33 34 // #102891# ----------------------- 35 36 #include <svtools/svlbox.hxx> 37 #include <svtools/svlbitm.hxx> 38 #include <svtools/svtreebx.hxx> 39 #include <tools/diagnose_ex.h> 40 #include <svimpbox.hxx> 41 #include <unotools/accessiblestatesethelper.hxx> 42 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 43 #include <com/sun/star/awt/XWindowPeer.hpp> 44 45 46 using namespace ::com::sun::star::accessibility; 47 48 /* 49 Bugs/ToDo 50 51 - Berechnung Rectangle beim Inplace-Editing (Bug bei manchen Fonts) 52 - SetSpaceBetweenEntries: Offset wird in SetEntryHeight nicht 53 beruecksichtigt 54 */ 55 56 #define TREEFLAG_FIXEDHEIGHT 0x0010 57 58 59 DBG_NAME(SvTreeListBox) 60 61 #define SV_LBOX_DEFAULT_INDENT_PIXEL 20 62 63 SvTreeListBox::SvTreeListBox( Window* pParent, WinBits nWinStyle ) 64 : SvLBox( pParent, nWinStyle ) 65 { 66 DBG_CTOR(SvTreeListBox,0); 67 InitTreeView(); 68 69 SetSublistOpenWithLeftRight(); 70 } 71 72 SvTreeListBox::SvTreeListBox( Window* pParent , const ResId& rResId ) 73 : SvLBox( pParent,rResId ) 74 { 75 DBG_CTOR(SvTreeListBox,0); 76 77 InitTreeView(); 78 Resize(); 79 80 SetSublistOpenWithLeftRight(); 81 } 82 83 void SvTreeListBox::InitTreeView() 84 { 85 DBG_CHKTHIS(SvTreeListBox,0); 86 pCheckButtonData = NULL; 87 pEdEntry = NULL; 88 pEdItem = NULL; 89 nEntryHeight = 0; 90 pEdCtrl = NULL; 91 nFirstSelTab = 0; 92 nLastSelTab = 0; 93 nFocusWidth = -1; 94 nAllItemAccRoleType = 0; 95 96 Link* pLink = new Link( LINK(this,SvTreeListBox, DefaultCompare) ); 97 pLBoxImpl->m_pLink = pLink; 98 99 nTreeFlags = TREEFLAG_RECALCTABS; 100 nIndent = SV_LBOX_DEFAULT_INDENT_PIXEL; 101 nEntryHeightOffs = SV_ENTRYHEIGHTOFFS_PIXEL; 102 pImp = new SvImpLBox( this, GetModel(), GetStyle() ); 103 104 aContextBmpMode = SVLISTENTRYFLAG_EXPANDED; 105 nContextBmpWidthMax = 0; 106 SetFont( GetFont() ); 107 SetSpaceBetweenEntries( 0 ); 108 SetLineColor(); 109 InitSettings( sal_True, sal_True, sal_True ); 110 ImplInitStyle(); 111 SetTabs(); 112 } 113 114 115 SvTreeListBox::~SvTreeListBox() 116 { 117 DBG_DTOR(SvTreeListBox,0); 118 pImp->CallEventListeners( VCLEVENT_OBJECT_DYING ); 119 delete pImp; 120 delete pLBoxImpl->m_pLink; 121 ClearTabList(); 122 } 123 124 void SvTreeListBox::SetExtendedWinBits( ExtendedWinBits _nBits ) 125 { 126 pImp->SetExtendedWindowBits( _nBits ); 127 } 128 129 ExtendedWinBits SvTreeListBox::GetExtendedWinBits() const 130 { 131 return pImp->GetExtendedWindowBits(); 132 } 133 134 void SvTreeListBox::SetModel( SvLBoxTreeList* pNewModel ) 135 { 136 DBG_CHKTHIS(SvTreeListBox,0); 137 pImp->SetModel( pNewModel ); 138 SvLBox::SetModel( pNewModel ); 139 } 140 141 void SvTreeListBox::DisconnectFromModel() 142 { 143 DBG_CHKTHIS(SvTreeListBox,0); 144 SvLBox::DisconnectFromModel(); 145 pImp->SetModel( GetModel() ); 146 } 147 148 149 sal_uInt16 SvTreeListBox::IsA() 150 { 151 DBG_CHKTHIS(SvTreeListBox,0); 152 return SV_LISTBOX_ID_TREEBOX; 153 } 154 155 void SvTreeListBox::SetSublistOpenWithReturn( sal_Bool b ) 156 { 157 pImp->bSubLstOpRet = b; 158 } 159 160 sal_Bool SvTreeListBox::IsSublistOpenWithReturn() const 161 { 162 return pImp->bSubLstOpRet; 163 } 164 165 void SvTreeListBox::SetSublistOpenWithLeftRight( sal_Bool b ) 166 { 167 pImp->bSubLstOpLR = b; 168 } 169 170 sal_Bool SvTreeListBox::IsSublistOpenWithLeftRight() const 171 { 172 return pImp->bSubLstOpLR; 173 } 174 175 void SvTreeListBox::Resize() 176 { 177 DBG_CHKTHIS(SvTreeListBox,0); 178 if( IsEditingActive() ) 179 EndEditing( sal_True ); 180 SvLBox::Resize(); 181 pImp->Resize(); 182 nFocusWidth = -1; 183 pImp->ShowCursor( sal_False ); 184 pImp->ShowCursor( sal_True ); 185 } 186 187 /* Faelle: 188 189 A) Entries haben Bitmaps 190 0. Keine Buttons 191 1. Node-Buttons (optional auch an Root-Items) 192 2. Node-Buttons (optional auch an Root-Items) + CheckButton 193 3. CheckButton 194 B) Entries haben keine Bitmaps (->ueber WindowBits wg. D&D !!!!!!) 195 0. Keine Buttons 196 1. Node-Buttons (optional auch an Root-Items) 197 2. Node-Buttons (optional auch an Root-Items) + CheckButton 198 3. CheckButton 199 */ 200 201 #define NO_BUTTONS 0 202 #define NODE_BUTTONS 1 203 #define NODE_AND_CHECK_BUTTONS 2 204 #define CHECK_BUTTONS 3 205 206 #define TABFLAGS_TEXT (SV_LBOXTAB_DYNAMIC | \ 207 SV_LBOXTAB_ADJUST_LEFT | \ 208 SV_LBOXTAB_EDITABLE | \ 209 SV_LBOXTAB_SHOW_SELECTION) 210 211 #define TABFLAGS_CONTEXTBMP (SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER) 212 213 #define TABFLAGS_CHECKBTN (SV_LBOXTAB_DYNAMIC | \ 214 SV_LBOXTAB_ADJUST_CENTER | \ 215 SV_LBOXTAB_PUSHABLE) 216 217 #define TAB_STARTPOS 2 218 219 // bei Aenderungen GetTextOffset beruecksichtigen 220 void SvTreeListBox::SetTabs() 221 { 222 DBG_CHKTHIS(SvTreeListBox,0); 223 if( IsEditingActive() ) 224 EndEditing( sal_True ); 225 nTreeFlags &= (~TREEFLAG_RECALCTABS); 226 nFocusWidth = -1; 227 const WinBits nStyle( GetStyle() ); 228 sal_Bool bHasButtons = (nStyle & WB_HASBUTTONS)!=0; 229 sal_Bool bHasButtonsAtRoot = (nStyle & (WB_HASLINESATROOT | 230 WB_HASBUTTONSATROOT))!=0; 231 long nStartPos = TAB_STARTPOS; 232 long nNodeWidthPixel = GetExpandedNodeBmp().GetSizePixel().Width(); 233 234 long nCheckWidth = 0; 235 if( nTreeFlags & TREEFLAG_CHKBTN ) 236 nCheckWidth = pCheckButtonData->aBmps[0].GetSizePixel().Width(); 237 long nCheckWidthDIV2 = nCheckWidth / 2; 238 239 long nContextWidth = nContextBmpWidthMax; 240 long nContextWidthDIV2 = nContextWidth / 2; 241 242 ClearTabList(); 243 244 int nCase = NO_BUTTONS; 245 if( !(nTreeFlags & TREEFLAG_CHKBTN) ) 246 { 247 if( bHasButtons ) 248 nCase = NODE_BUTTONS; 249 } 250 else 251 { 252 if( bHasButtons ) 253 nCase = NODE_AND_CHECK_BUTTONS; 254 else 255 nCase = CHECK_BUTTONS; 256 } 257 258 switch( nCase ) 259 { 260 case NO_BUTTONS : 261 nStartPos += nContextWidthDIV2; // wg. Zentrierung 262 AddTab( nStartPos, TABFLAGS_CONTEXTBMP ); 263 nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp 264 // Abstand setzen nur wenn Bitmaps da 265 if( nContextBmpWidthMax ) 266 nStartPos += 5; // Abstand Context-Bmp - Text 267 AddTab( nStartPos, TABFLAGS_TEXT ); 268 break; 269 270 case NODE_BUTTONS : 271 if( bHasButtonsAtRoot ) 272 nStartPos += ( nIndent + (nNodeWidthPixel/2) ); 273 else 274 nStartPos += nContextWidthDIV2; 275 AddTab( nStartPos, TABFLAGS_CONTEXTBMP ); 276 nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp 277 // Abstand setzen nur wenn Bitmaps da 278 if( nContextBmpWidthMax ) 279 nStartPos += 5; // Abstand Context-Bmp - Text 280 AddTab( nStartPos, TABFLAGS_TEXT ); 281 break; 282 283 case NODE_AND_CHECK_BUTTONS : 284 if( bHasButtonsAtRoot ) 285 nStartPos += ( nIndent + nNodeWidthPixel ); 286 else 287 nStartPos += nCheckWidthDIV2; 288 AddTab( nStartPos, TABFLAGS_CHECKBTN ); 289 nStartPos += nCheckWidthDIV2; // rechter Rand des CheckButtons 290 nStartPos += 3; // Abstand CheckButton Context-Bmp 291 nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp 292 AddTab( nStartPos, TABFLAGS_CONTEXTBMP ); 293 nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp 294 // Abstand setzen nur wenn Bitmaps da 295 if( nContextBmpWidthMax ) 296 nStartPos += 5; // Abstand Context-Bmp - Text 297 AddTab( nStartPos, TABFLAGS_TEXT ); 298 break; 299 300 case CHECK_BUTTONS : 301 nStartPos += nCheckWidthDIV2; 302 AddTab( nStartPos, TABFLAGS_CHECKBTN ); 303 nStartPos += nCheckWidthDIV2; // rechter Rand CheckButton 304 nStartPos += 3; // Abstand CheckButton Context-Bmp 305 nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp 306 AddTab( nStartPos, TABFLAGS_CONTEXTBMP ); 307 nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp 308 // Abstand setzen nur wenn Bitmaps da 309 if( nContextBmpWidthMax ) 310 nStartPos += 5; // Abstand Context-Bmp - Text 311 AddTab( nStartPos, TABFLAGS_TEXT ); 312 break; 313 } 314 pImp->NotifyTabsChanged(); 315 } 316 317 void SvTreeListBox::InitEntry( SvLBoxEntry* pEntry, 318 const XubString& aStr, const Image& aCollEntryBmp, const Image& aExpEntryBmp, 319 SvLBoxButtonKind eButtonKind) 320 { 321 DBG_CHKTHIS(SvTreeListBox,0); 322 SvLBoxButton* pButton; 323 SvLBoxString* pString; 324 SvLBoxContextBmp* pContextBmp; 325 326 if( nTreeFlags & TREEFLAG_CHKBTN ) 327 { 328 pButton= new SvLBoxButton( pEntry,eButtonKind,0,pCheckButtonData ); 329 pEntry->AddItem( pButton ); 330 } 331 332 pContextBmp= new SvLBoxContextBmp( pEntry,0, aCollEntryBmp,aExpEntryBmp, 333 aContextBmpMode ); 334 pEntry->AddItem( pContextBmp ); 335 336 pString = new SvLBoxString( pEntry, 0, aStr ); 337 pEntry->AddItem( pString ); 338 } 339 340 String SvTreeListBox::GetEntryText(SvLBoxEntry* pEntry) const 341 { 342 DBG_CHKTHIS(SvTreeListBox,0); 343 DBG_ASSERT( pEntry, "SvTreeListBox::GetEntryText(): no entry" ); 344 SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); 345 DBG_ASSERT( pEntry, "SvTreeListBox::GetEntryText(): item not found" ); 346 return pItem->GetText(); 347 } 348 349 String SvTreeListBox::GetEntryAltText( SvLBoxEntry* ) const 350 { 351 String tmp; 352 return tmp; 353 } 354 String SvTreeListBox::GetEntryLongDescription( SvLBoxEntry* ) const 355 { 356 String tmp; 357 return tmp; 358 } 359 360 String SvTreeListBox::SearchEntryTextWithHeadTitle( SvLBoxEntry* pEntry ) 361 { 362 DBG_CHKTHIS(SvTreeListBox,0); 363 DBG_ASSERT( pEntry, "SvTreeListBox::SearchEntryText(): no entry" ); 364 String sRet; 365 366 sal_uInt16 nCount = pEntry->ItemCount(); 367 sal_uInt16 nCur = 0; 368 sal_uInt16 nHeaderCur = 0; 369 SvLBoxItem* pItem; 370 while( nCur < nCount ) 371 { 372 // MT: SV_ITEM_ID_EXTENDRLBOXSTRING / GetExtendText() was in use in IA2 cws, but only used in sc: ScSolverOptionsString. Needed? 373 pItem = pEntry->GetItem( nCur ); 374 if ( (pItem->IsA() == SV_ITEM_ID_LBOXSTRING /* || pItem->IsA() == SV_ITEM_ID_EXTENDRLBOXSTRING */ ) && 375 static_cast<SvLBoxString*>( pItem )->GetText().Len() > 0 ) 376 { 377 378 //want to the column header 379 if( headString.Len() > 0) 380 { 381 xub_StrLen nEnd = headString.Search( sal_Unicode( '\t' ) ); 382 if( nEnd == STRING_NOTFOUND ) 383 { 384 if(sRet.Len()>0) 385 { 386 sRet += ','; 387 } 388 if(headString.Len()>0) 389 { 390 sRet += headString ; 391 sRet += ':' ; 392 } 393 } 394 else 395 { 396 String aString=headString.GetToken(nHeaderCur, sal_Unicode( '\t' ) ); 397 if(sRet.Len()>0) 398 { 399 sRet += ','; 400 } 401 if( aString.Len() > 0) 402 { 403 sRet += aString ; 404 sRet += ':' ; 405 } 406 nHeaderCur++; 407 } 408 // if (pItem->IsA() == SV_ITEM_ID_LBOXSTRING) 409 sRet += static_cast<SvLBoxString*>( pItem )->GetText(); 410 // else 411 // sRet += static_cast<SvLBoxString*>( pItem )->GetExtendText(); 412 } 413 else 414 { 415 // if (pItem->IsA() == SV_ITEM_ID_LBOXSTRING) 416 sRet += static_cast<SvLBoxString*>( pItem )->GetText(); 417 // else 418 // sRet += static_cast<SvLBoxString*>( pItem )->GetExtendText(); 419 sRet += ','; 420 } 421 //end want to the column header 422 } 423 nCur++; 424 } 425 426 if (sRet.Len() > 0) 427 sRet = sRet.Erase(sRet.Len() - 1); 428 return sRet; 429 } 430 String SvTreeListBox::SearchEntryText( SvLBoxEntry* pEntry ) const 431 { 432 DBG_CHKTHIS(SvTreeListBox,0); 433 DBG_ASSERT( pEntry, "SvTreeListBox::SearchEntryText(): no entry" ); 434 String sRet; 435 sal_uInt16 nCount = pEntry->ItemCount(); 436 sal_uInt16 nCur = 0; 437 SvLBoxItem* pItem; 438 while( nCur < nCount ) 439 { 440 pItem = pEntry->GetItem( nCur ); 441 if ( pItem->IsA() == SV_ITEM_ID_LBOXSTRING && 442 static_cast<SvLBoxString*>( pItem )->GetText().Len() > 0 ) 443 { 444 sRet = static_cast<SvLBoxString*>( pItem )->GetText(); 445 break; 446 } 447 nCur++; 448 } 449 return sRet; 450 } 451 452 const Image& SvTreeListBox::GetExpandedEntryBmp(SvLBoxEntry* pEntry, BmpColorMode _eMode) const 453 { 454 DBG_CHKTHIS(SvTreeListBox,0); 455 DBG_ASSERT(pEntry,"Entry?"); 456 SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); 457 DBG_ASSERT(pItem,"GetContextBmp:Item not found"); 458 return pItem->GetBitmap2( _eMode ); 459 } 460 461 const Image& SvTreeListBox::GetCollapsedEntryBmp( SvLBoxEntry* pEntry, BmpColorMode _eMode ) const 462 { 463 DBG_CHKTHIS(SvTreeListBox,0); 464 DBG_ASSERT(pEntry,"Entry?"); 465 SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); 466 DBG_ASSERT(pItem,"GetContextBmp:Item not found"); 467 return pItem->GetBitmap1( _eMode ); 468 } 469 470 IMPL_LINK_INLINE_START( SvTreeListBox, CheckButtonClick, SvLBoxButtonData *, pData ) 471 { 472 DBG_CHKTHIS(SvTreeListBox,0); 473 pHdlEntry = pData->GetActEntry(); 474 CheckButtonHdl(); 475 return 0; 476 } 477 IMPL_LINK_INLINE_END( SvTreeListBox, CheckButtonClick, SvLBoxButtonData *, pData ) 478 479 SvLBoxEntry* SvTreeListBox::InsertEntry( const XubString& aText,SvLBoxEntry* pParent, 480 sal_Bool bChildsOnDemand, sal_uLong nPos, void* pUser, 481 SvLBoxButtonKind eButtonKind ) 482 { 483 DBG_CHKTHIS(SvTreeListBox,0); 484 nTreeFlags |= TREEFLAG_MANINS; 485 486 const Image& rDefExpBmp = pImp->GetDefaultEntryExpBmp( ); 487 const Image& rDefColBmp = pImp->GetDefaultEntryColBmp( ); 488 489 aCurInsertedExpBmp = rDefExpBmp; 490 aCurInsertedColBmp = rDefColBmp; 491 492 SvLBoxEntry* pEntry = CreateEntry(); 493 pEntry->SetUserData( pUser ); 494 InitEntry( pEntry, aText, rDefColBmp, rDefExpBmp, eButtonKind ); 495 pEntry->EnableChildsOnDemand( bChildsOnDemand ); 496 497 // Add the HC versions of the default images 498 SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) ); 499 if( pBmpItem ) 500 { 501 pBmpItem->SetBitmap1( pImp->GetDefaultEntryColBmp( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST ); 502 pBmpItem->SetBitmap2( pImp->GetDefaultEntryExpBmp( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST ); 503 } 504 505 if( !pParent ) 506 SvLBox::Insert( pEntry, nPos ); 507 else 508 SvLBox::Insert( pEntry, pParent, nPos ); 509 510 aPrevInsertedExpBmp = rDefExpBmp; 511 aPrevInsertedColBmp = rDefColBmp; 512 513 nTreeFlags &= (~TREEFLAG_MANINS); 514 515 return pEntry; 516 } 517 518 SvLBoxEntry* SvTreeListBox::InsertEntry( const XubString& aText, 519 const Image& aExpEntryBmp, const Image& aCollEntryBmp, 520 SvLBoxEntry* pParent, sal_Bool bChildsOnDemand, sal_uLong nPos, void* pUser, 521 SvLBoxButtonKind eButtonKind ) 522 { 523 DBG_CHKTHIS(SvTreeListBox,0); 524 nTreeFlags |= TREEFLAG_MANINS; 525 526 aCurInsertedExpBmp = aExpEntryBmp; 527 aCurInsertedColBmp = aCollEntryBmp; 528 529 SvLBoxEntry* pEntry = CreateEntry(); 530 pEntry->SetUserData( pUser ); 531 InitEntry( pEntry, aText, aCollEntryBmp, aExpEntryBmp, eButtonKind ); 532 533 pEntry->EnableChildsOnDemand( bChildsOnDemand ); 534 535 if( !pParent ) 536 SvLBox::Insert( pEntry, nPos ); 537 else 538 SvLBox::Insert( pEntry, pParent, nPos ); 539 540 aPrevInsertedExpBmp = aExpEntryBmp; 541 aPrevInsertedColBmp = aCollEntryBmp; 542 543 nTreeFlags &= (~TREEFLAG_MANINS); 544 545 return pEntry; 546 } 547 548 void SvTreeListBox::SetEntryText( SvLBoxEntry* pEntry, const XubString& aStr) 549 { 550 DBG_CHKTHIS(SvTreeListBox,0); 551 SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); 552 DBG_ASSERT(pItem,"SetText:Item not found"); 553 pItem->SetText( pEntry, aStr ); 554 pItem->InitViewData( this, pEntry, 0 ); 555 GetModel()->InvalidateEntry( pEntry ); 556 } 557 558 void SvTreeListBox::SetExpandedEntryBmp( SvLBoxEntry* pEntry, const Image& aBmp, BmpColorMode _eMode ) 559 { 560 DBG_CHKTHIS(SvTreeListBox,0); 561 SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); 562 563 DBG_ASSERT(pItem,"SetExpBmp:Item not found"); 564 pItem->SetBitmap2( aBmp, _eMode ); 565 566 GetModel()->InvalidateEntry( pEntry ); 567 SetEntryHeight( pEntry ); 568 Size aSize = aBmp.GetSizePixel(); 569 // #97680# --------------- 570 short nWidth = pImp->UpdateContextBmpWidthVector( pEntry, (short)aSize.Width() ); 571 if( nWidth > nContextBmpWidthMax ) 572 { 573 nContextBmpWidthMax = nWidth; 574 SetTabs(); 575 } 576 } 577 578 void SvTreeListBox::SetCollapsedEntryBmp(SvLBoxEntry* pEntry,const Image& aBmp, BmpColorMode _eMode ) 579 { 580 DBG_CHKTHIS(SvTreeListBox,0); 581 SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); 582 583 DBG_ASSERT(pItem,"SetExpBmp:Item not found"); 584 pItem->SetBitmap1( aBmp, _eMode ); 585 586 GetModel()->InvalidateEntry( pEntry ); 587 SetEntryHeight( pEntry ); 588 Size aSize = aBmp.GetSizePixel(); 589 // #97680# ----------- 590 short nWidth = pImp->UpdateContextBmpWidthVector( pEntry, (short)aSize.Width() ); 591 if( nWidth > nContextBmpWidthMax ) 592 { 593 nContextBmpWidthMax = nWidth; 594 SetTabs(); 595 } 596 } 597 598 void SvTreeListBox::ImpEntryInserted( SvLBoxEntry* pEntry ) 599 { 600 DBG_CHKTHIS(SvTreeListBox,0); 601 602 SvLBoxEntry* pParent = (SvLBoxEntry*)pModel->GetParent( pEntry ); 603 if( pParent ) 604 { 605 sal_uInt16 nFlags = pParent->GetFlags(); 606 nFlags &= ~SV_ENTRYFLAG_NO_NODEBMP; 607 pParent->SetFlags( nFlags ); 608 } 609 610 if(!((nTreeFlags & TREEFLAG_MANINS) && 611 (aPrevInsertedExpBmp == aCurInsertedExpBmp) && 612 (aPrevInsertedColBmp == aCurInsertedColBmp) )) 613 { 614 Size aSize = GetCollapsedEntryBmp( pEntry ).GetSizePixel(); 615 if( aSize.Width() > nContextBmpWidthMax ) 616 { 617 nContextBmpWidthMax = (short)aSize.Width(); 618 nTreeFlags |= TREEFLAG_RECALCTABS; 619 } 620 aSize = GetExpandedEntryBmp( pEntry ).GetSizePixel(); 621 if( aSize.Width() > nContextBmpWidthMax ) 622 { 623 nContextBmpWidthMax = (short)aSize.Width(); 624 nTreeFlags |= TREEFLAG_RECALCTABS; 625 } 626 } 627 SetEntryHeight( (SvLBoxEntry*)pEntry ); 628 } 629 630 631 632 void SvTreeListBox::SetCheckButtonState( SvLBoxEntry* pEntry, SvButtonState eState) 633 { 634 DBG_CHKTHIS(SvTreeListBox,0); 635 if( nTreeFlags & TREEFLAG_CHKBTN ) 636 { 637 SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON)); 638 if(!(pItem && pItem->CheckModification())) 639 return ; 640 switch( eState ) 641 { 642 case SV_BUTTON_CHECKED: 643 pItem->SetStateChecked(); 644 break; 645 646 case SV_BUTTON_UNCHECKED: 647 pItem->SetStateUnchecked(); 648 break; 649 650 case SV_BUTTON_TRISTATE: 651 pItem->SetStateTristate(); 652 break; 653 } 654 InvalidateEntry( pEntry ); 655 } 656 } 657 658 SvButtonState SvTreeListBox::GetCheckButtonState( SvLBoxEntry* pEntry ) const 659 { 660 DBG_CHKTHIS(SvTreeListBox,0); 661 SvButtonState eState = SV_BUTTON_UNCHECKED; 662 if( nTreeFlags & TREEFLAG_CHKBTN ) 663 { 664 SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON)); 665 if(!pItem) 666 return SV_BUTTON_TRISTATE; 667 sal_uInt16 nButtonFlags = pItem->GetButtonFlags(); 668 eState = pCheckButtonData->ConvertToButtonState( nButtonFlags ); 669 } 670 return eState; 671 } 672 673 void SvTreeListBox::CheckButtonHdl() 674 { 675 DBG_CHKTHIS(SvTreeListBox,0); 676 aCheckButtonHdl.Call( this ); 677 if ( pCheckButtonData ) 678 pImp->CallEventListeners( VCLEVENT_CHECKBOX_TOGGLE, (void*)pCheckButtonData->GetActEntry() ); 679 } 680 681 // ********************************************************************* 682 // ********************************************************************* 683 684 // 685 // TODO: Momentan werden die Daten so geklont, dass sie dem 686 // Standard-TreeView-Format entsprechen. Hier sollte eigentlich 687 // das Model als Referenz dienen. Dies fuehrt dazu, dass 688 // SvLBoxEntry::Clone _nicht_ gerufen wird, sondern nur dessen 689 // Basisklasse SvListEntry 690 // 691 692 SvLBoxEntry* SvTreeListBox::CloneEntry( SvLBoxEntry* pSource ) 693 { 694 DBG_CHKTHIS(SvTreeListBox,0); 695 XubString aStr; 696 Image aCollEntryBmp; 697 Image aExpEntryBmp; 698 SvLBoxButtonKind eButtonKind = SvLBoxButtonKind_enabledCheckbox; 699 700 SvLBoxString* pStringItem = (SvLBoxString*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); 701 if( pStringItem ) 702 aStr = pStringItem->GetText(); 703 SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); 704 if( pBmpItem ) 705 { 706 aCollEntryBmp = pBmpItem->GetBitmap1( BMP_COLOR_NORMAL ); 707 aExpEntryBmp = pBmpItem->GetBitmap2( BMP_COLOR_NORMAL ); 708 } 709 SvLBoxButton* pButtonItem = (SvLBoxButton*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXBUTTON)); 710 if( pButtonItem ) 711 eButtonKind = pButtonItem->GetKind(); 712 SvLBoxEntry* pClone = CreateEntry(); 713 InitEntry( pClone, aStr, aCollEntryBmp, aExpEntryBmp, eButtonKind ); 714 pClone->SvListEntry::Clone( pSource ); 715 pClone->EnableChildsOnDemand( pSource->HasChildsOnDemand() ); 716 pClone->SetUserData( pSource->GetUserData() ); 717 718 if ( pBmpItem ) 719 { 720 SvLBoxContextBmp* pCloneBitmap = static_cast< SvLBoxContextBmp* >( pClone->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) ); 721 if ( pCloneBitmap ) 722 { 723 pCloneBitmap->SetBitmap1( pBmpItem->GetBitmap1( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST ); 724 pCloneBitmap->SetBitmap2( pBmpItem->GetBitmap2( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST ); 725 } 726 } 727 728 return pClone; 729 } 730 731 // ********************************************************************* 732 // ********************************************************************* 733 734 735 void SvTreeListBox::ShowExpandBitmapOnCursor( sal_Bool bYes ) 736 { 737 DBG_CHKTHIS(SvTreeListBox,0); 738 if( bYes ) 739 aContextBmpMode = SVLISTENTRYFLAG_FOCUSED; 740 else 741 aContextBmpMode = SVLISTENTRYFLAG_EXPANDED; 742 } 743 744 void SvTreeListBox::SetIndent( short nNewIndent ) 745 { 746 DBG_CHKTHIS(SvTreeListBox,0); 747 nIndent = nNewIndent; 748 SetTabs(); 749 if( IsUpdateMode() ) 750 Invalidate(); 751 } 752 753 const Image& SvTreeListBox::GetDefaultExpandedEntryBmp( BmpColorMode _eMode ) const 754 { 755 return pImp->GetDefaultEntryExpBmp( _eMode ); 756 } 757 758 const Image& SvTreeListBox::GetDefaultCollapsedEntryBmp( BmpColorMode _eMode ) const 759 { 760 return pImp->GetDefaultEntryColBmp( _eMode ); 761 } 762 763 void SvTreeListBox::SetDefaultExpandedEntryBmp( const Image& aBmp, BmpColorMode _eMode ) 764 { 765 DBG_CHKTHIS(SvTreeListBox,0); 766 Size aSize = aBmp.GetSizePixel(); 767 if( aSize.Width() > nContextBmpWidthMax ) 768 nContextBmpWidthMax = (short)aSize.Width(); 769 SetTabs(); 770 771 pImp->SetDefaultEntryExpBmp( aBmp, _eMode ); 772 } 773 774 void SvTreeListBox::SetDefaultCollapsedEntryBmp( const Image& aBmp, BmpColorMode _eMode ) 775 { 776 DBG_CHKTHIS(SvTreeListBox,0); 777 Size aSize = aBmp.GetSizePixel(); 778 if( aSize.Width() > nContextBmpWidthMax ) 779 nContextBmpWidthMax = (short)aSize.Width(); 780 SetTabs(); 781 782 pImp->SetDefaultEntryColBmp( aBmp, _eMode ); 783 } 784 785 void SvTreeListBox::EnableCheckButton( SvLBoxButtonData* pData ) 786 { 787 DBG_CHKTHIS(SvTreeListBox,0); 788 DBG_ASSERT(!GetEntryCount(),"EnableCheckButton: Entry count != 0"); 789 if( !pData ) 790 nTreeFlags &= (~TREEFLAG_CHKBTN); 791 else 792 { 793 SetCheckButtonData( pData ); 794 nTreeFlags |= TREEFLAG_CHKBTN; 795 pData->SetLink( LINK(this, SvTreeListBox, CheckButtonClick)); 796 } 797 798 SetTabs(); 799 if( IsUpdateMode() ) 800 Invalidate(); 801 } 802 803 void SvTreeListBox::SetCheckButtonData( SvLBoxButtonData* pData ) 804 { 805 DBG_CHKTHIS(SvTreeListBox,0); 806 if ( pData ) 807 pCheckButtonData = pData; 808 } 809 810 const Image& SvTreeListBox::GetDefaultExpandedNodeImage( BmpColorMode _eMode ) 811 { 812 return SvImpLBox::GetDefaultExpandedNodeImage( _eMode ); 813 } 814 815 const Image& SvTreeListBox::GetDefaultCollapsedNodeImage( BmpColorMode _eMode ) 816 { 817 return SvImpLBox::GetDefaultCollapsedNodeImage( _eMode ); 818 } 819 820 void SvTreeListBox::SetNodeBitmaps( const Image& rCollapsedNodeBmp, const Image& rExpandedNodeBmp, BmpColorMode _eMode ) 821 { 822 DBG_CHKTHIS(SvTreeListBox,0); 823 SetExpandedNodeBmp( rExpandedNodeBmp, _eMode ); 824 SetCollapsedNodeBmp( rCollapsedNodeBmp, _eMode ); 825 SetTabs(); 826 } 827 828 void SvTreeListBox::SetDontKnowNodeBitmap( const Image& rDontKnowBmp, BmpColorMode _eMode ) 829 { 830 pImp->SetDontKnowNodeBmp( rDontKnowBmp, _eMode ); 831 } 832 833 sal_Bool SvTreeListBox::EditingEntry( SvLBoxEntry*, Selection& ) 834 { 835 DBG_CHKTHIS(SvTreeListBox,0); 836 return sal_True; 837 } 838 839 sal_Bool SvTreeListBox::EditedEntry( SvLBoxEntry* /*pEntry*/,const XubString& /*rNewText*/) 840 { 841 DBG_CHKTHIS(SvTreeListBox,0); 842 return sal_True; 843 } 844 845 void SvTreeListBox::EnableInplaceEditing( sal_Bool bOn ) 846 { 847 DBG_CHKTHIS(SvTreeListBox,0); 848 SvLBox::EnableInplaceEditing( bOn ); 849 } 850 851 void SvTreeListBox::KeyInput( const KeyEvent& rKEvt ) 852 { 853 DBG_CHKTHIS(SvTreeListBox,0); 854 // unter OS/2 bekommen wir auch beim Editieren Key-Up/Down 855 if( IsEditingActive() ) 856 return; 857 858 nImpFlags |= SVLBOX_IS_TRAVELSELECT; 859 860 #ifdef OVDEBUG 861 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); 862 switch ( nCode ) 863 { 864 case KEY_F1: 865 { 866 SvLBoxEntry* pEntry = First(); 867 pEntry = NextVisible( pEntry ); 868 SetEntryText( pEntry, "SetEntryText" ); 869 Sound::Beep(); 870 } 871 break; 872 } 873 #endif 874 875 if( !pImp->KeyInput( rKEvt ) ) 876 SvLBox::KeyInput( rKEvt ); 877 878 nImpFlags &= ~SVLBOX_IS_TRAVELSELECT; 879 } 880 881 void SvTreeListBox::RequestingChilds( SvLBoxEntry* pParent ) 882 { 883 DBG_CHKTHIS(SvTreeListBox,0); 884 if( !pParent->HasChilds() ) 885 InsertEntry( String::CreateFromAscii("<dummy>"), pParent, sal_False, LIST_APPEND ); 886 } 887 888 void SvTreeListBox::GetFocus() 889 { 890 DBG_CHKTHIS(SvTreeListBox,0); 891 //Solution:If there is no item in the tree,draw focus. 892 if( !SvLBox::First()) 893 { 894 Invalidate(); 895 } 896 pImp->GetFocus(); 897 SvLBox::GetFocus(); 898 899 SvLBoxEntry* pEntry = FirstSelected(); 900 if ( !pEntry ) 901 { 902 pEntry = pImp->GetCurrentEntry(); 903 } 904 if (pImp->pCursor) 905 { 906 if (pEntry != pImp->pCursor) 907 pEntry = pImp->pCursor; 908 } 909 if ( pEntry ) 910 //pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry ); 911 pImp->CallEventListeners( VCLEVENT_LISTBOX_TREEFOCUS, pEntry ); 912 913 } 914 915 void SvTreeListBox::LoseFocus() 916 { 917 DBG_CHKTHIS(SvTreeListBox,0); 918 //Solution:If there is no item in the tree,delete visual focus. 919 if( !SvLBox::First()) 920 { 921 Invalidate(); 922 } 923 pImp->LoseFocus(); 924 SvLBox::LoseFocus(); 925 } 926 927 void SvTreeListBox::ModelHasCleared() 928 { 929 DBG_CHKTHIS(SvTreeListBox,0); 930 pImp->pCursor = 0; //sonst Absturz beim Inplace-Editieren im GetFocus 931 delete pEdCtrl; 932 pEdCtrl = NULL; 933 pImp->Clear(); 934 nFocusWidth = -1; 935 936 nContextBmpWidthMax = 0; 937 SetDefaultExpandedEntryBmp( GetDefaultExpandedEntryBmp() ); 938 SetDefaultCollapsedEntryBmp( GetDefaultCollapsedEntryBmp() ); 939 940 if( !(nTreeFlags & TREEFLAG_FIXEDHEIGHT )) 941 nEntryHeight = 0; 942 AdjustEntryHeight( GetFont() ); 943 AdjustEntryHeight( GetDefaultExpandedEntryBmp() ); 944 AdjustEntryHeight( GetDefaultCollapsedEntryBmp() ); 945 946 SvLBox::ModelHasCleared(); 947 // if( IsUpdateMode() ) 948 // Invalidate(); 949 } 950 951 void SvTreeListBox::ShowTargetEmphasis( SvLBoxEntry* pEntry, sal_Bool /* bShow */ ) 952 { 953 DBG_CHKTHIS(SvTreeListBox,0); 954 pImp->PaintDDCursor( pEntry ); 955 } 956 957 void SvTreeListBox::ScrollOutputArea( short nDeltaEntries ) 958 { 959 DBG_CHKTHIS(SvTreeListBox,0); 960 if( !nDeltaEntries || !pImp->aVerSBar.IsVisible() ) 961 return; 962 963 long nThumb = pImp->aVerSBar.GetThumbPos(); 964 long nMax = pImp->aVerSBar.GetRange().Max(); 965 966 NotifyBeginScroll(); 967 if( nDeltaEntries < 0 ) 968 { 969 // das Fenster nach oben verschieben 970 nDeltaEntries *= -1; 971 long nVis = pImp->aVerSBar.GetVisibleSize(); 972 long nTemp = nThumb + nVis; 973 if( nDeltaEntries > (nMax - nTemp) ) 974 nDeltaEntries = (short)(nMax - nTemp); 975 pImp->PageDown( (sal_uInt16)nDeltaEntries ); 976 } 977 else 978 { 979 if( nDeltaEntries > nThumb ) 980 nDeltaEntries = (short)nThumb; 981 pImp->PageUp( (sal_uInt16)nDeltaEntries ); 982 } 983 pImp->SyncVerThumb(); 984 NotifyEndScroll(); 985 } 986 987 void SvTreeListBox::SetSelectionMode( SelectionMode eSelectMode ) 988 { 989 DBG_CHKTHIS(SvTreeListBox,0); 990 SvLBox::SetSelectionMode( eSelectMode ); 991 pImp->SetSelectionMode( eSelectMode ); 992 } 993 994 void SvTreeListBox::SetDragDropMode( DragDropMode nDDMode ) 995 { 996 DBG_CHKTHIS(SvTreeListBox,0); 997 SvLBox::SetDragDropMode( nDDMode ); 998 pImp->SetDragDropMode( nDDMode ); 999 } 1000 1001 short SvTreeListBox::GetHeightOffset(const Image& rBmp, Size& aSizeLogic ) 1002 { 1003 DBG_CHKTHIS(SvTreeListBox,0); 1004 short nOffset = 0; 1005 aSizeLogic = rBmp.GetSizePixel(); 1006 if( GetEntryHeight() > aSizeLogic.Height() ) 1007 nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2; 1008 return nOffset; 1009 } 1010 1011 short SvTreeListBox::GetHeightOffset(const Font& /* rFont */, Size& aSizeLogic ) 1012 { 1013 DBG_CHKTHIS(SvTreeListBox,0); 1014 short nOffset = 0; 1015 aSizeLogic = Size(GetTextWidth('X'), GetTextHeight()); 1016 if( GetEntryHeight() > aSizeLogic.Height() ) 1017 nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2; 1018 return nOffset; 1019 } 1020 1021 void SvTreeListBox::SetEntryHeight( SvLBoxEntry* pEntry ) 1022 { 1023 DBG_CHKTHIS(SvTreeListBox,0); 1024 short nHeight, nHeightMax=0; 1025 sal_uInt16 nCount = pEntry->ItemCount(); 1026 sal_uInt16 nCur = 0; 1027 SvViewDataEntry* pViewData = GetViewDataEntry( pEntry ); 1028 while( nCur < nCount ) 1029 { 1030 SvLBoxItem* pItem = pEntry->GetItem( nCur ); 1031 nHeight = (short)(pItem->GetSize( pViewData, nCur ).Height()); 1032 if( nHeight > nHeightMax ) 1033 nHeightMax = nHeight; 1034 nCur++; 1035 } 1036 1037 if( nHeightMax > nEntryHeight ) 1038 { 1039 nEntryHeight = nHeightMax; 1040 SvLBox::SetFont( GetFont() ); 1041 pImp->SetEntryHeight( nHeightMax ); 1042 } 1043 } 1044 1045 void SvTreeListBox::SetEntryHeight( short nHeight, sal_Bool bAlways ) 1046 { 1047 DBG_CHKTHIS(SvTreeListBox,0); 1048 1049 if( bAlways || nHeight > nEntryHeight ) 1050 { 1051 nEntryHeight = nHeight; 1052 if( nEntryHeight ) 1053 nTreeFlags |= TREEFLAG_FIXEDHEIGHT; 1054 else 1055 nTreeFlags &= ~TREEFLAG_FIXEDHEIGHT; 1056 SvLBox::SetFont( GetFont() ); 1057 pImp->SetEntryHeight( nHeight ); 1058 } 1059 } 1060 1061 1062 void SvTreeListBox::AdjustEntryHeight( const Image& rBmp ) 1063 { 1064 DBG_CHKTHIS(SvTreeListBox,0); 1065 Size aSize; 1066 GetHeightOffset( rBmp, aSize ); 1067 if( aSize.Height() > nEntryHeight ) 1068 { 1069 nEntryHeight = (short)aSize.Height() + nEntryHeightOffs; 1070 pImp->SetEntryHeight( nEntryHeight ); 1071 } 1072 } 1073 1074 void SvTreeListBox::AdjustEntryHeight( const Font& rFont ) 1075 { 1076 DBG_CHKTHIS(SvTreeListBox,0); 1077 Size aSize; 1078 GetHeightOffset( rFont, aSize ); 1079 if( aSize.Height() > nEntryHeight ) 1080 { 1081 nEntryHeight = (short)aSize.Height() + nEntryHeightOffs; 1082 pImp->SetEntryHeight( nEntryHeight ); 1083 } 1084 } 1085 1086 sal_Bool SvTreeListBox::Expand( SvLBoxEntry* pParent ) 1087 { 1088 DBG_CHKTHIS(SvTreeListBox,0); 1089 pHdlEntry = pParent; 1090 sal_Bool bExpanded = sal_False; 1091 sal_uInt16 nFlags; 1092 1093 if( pParent->HasChildsOnDemand() ) 1094 RequestingChilds( pParent ); 1095 if( pParent->HasChilds() ) 1096 { 1097 nImpFlags |= SVLBOX_IS_EXPANDING; 1098 if( ExpandingHdl() ) 1099 { 1100 bExpanded = sal_True; 1101 SvListView::Expand( pParent ); 1102 pImp->EntryExpanded( pParent ); 1103 pHdlEntry = pParent; 1104 ExpandedHdl(); 1105 } 1106 nFlags = pParent->GetFlags(); 1107 nFlags &= ~SV_ENTRYFLAG_NO_NODEBMP; 1108 nFlags |= SV_ENTRYFLAG_HAD_CHILDREN; 1109 pParent->SetFlags( nFlags ); 1110 } 1111 else 1112 { 1113 nFlags = pParent->GetFlags(); 1114 nFlags |= SV_ENTRYFLAG_NO_NODEBMP; 1115 pParent->SetFlags( nFlags ); 1116 GetModel()->InvalidateEntry( pParent ); // neu zeichnen 1117 } 1118 1119 // --> OD 2009-04-01 #i92103# 1120 if ( bExpanded ) 1121 { 1122 pImp->CallEventListeners( VCLEVENT_ITEM_EXPANDED, pParent ); 1123 } 1124 // <-- 1125 1126 return bExpanded; 1127 } 1128 1129 sal_Bool SvTreeListBox::Collapse( SvLBoxEntry* pParent ) 1130 { 1131 DBG_CHKTHIS(SvTreeListBox,0); 1132 nImpFlags &= ~SVLBOX_IS_EXPANDING; 1133 pHdlEntry = pParent; 1134 sal_Bool bCollapsed = sal_False; 1135 1136 if( ExpandingHdl() ) 1137 { 1138 bCollapsed = sal_True; 1139 pImp->CollapsingEntry( pParent ); 1140 SvListView::Collapse( pParent ); 1141 pImp->EntryCollapsed( pParent ); 1142 pHdlEntry = pParent; 1143 ExpandedHdl(); 1144 } 1145 1146 // --> OD 2009-04-01 #i92103# 1147 if ( bCollapsed ) 1148 { 1149 pImp->CallEventListeners( VCLEVENT_ITEM_COLLAPSED, pParent ); 1150 } 1151 // <-- 1152 1153 return bCollapsed; 1154 } 1155 1156 sal_Bool SvTreeListBox::Select( SvLBoxEntry* pEntry, sal_Bool bSelect ) 1157 { 1158 DBG_CHKTHIS(SvTreeListBox,0); 1159 DBG_ASSERT(pEntry,"Select: Null-Ptr"); 1160 sal_Bool bRetVal = SvListView::Select( pEntry, bSelect ); 1161 DBG_ASSERT(IsSelected(pEntry)==bSelect,"Select failed"); 1162 if( bRetVal ) 1163 { 1164 pImp->EntrySelected( pEntry, bSelect ); 1165 pHdlEntry = pEntry; 1166 if( bSelect ) 1167 { 1168 SelectHdl(); 1169 // pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry ); 1170 CallEventListeners( VCLEVENT_LISTBOX_TREESELECT, pEntry); 1171 } 1172 else 1173 DeselectHdl(); 1174 } 1175 return bRetVal; 1176 } 1177 1178 sal_uLong SvTreeListBox::SelectChilds( SvLBoxEntry* pParent, sal_Bool bSelect ) 1179 { 1180 DBG_CHKTHIS(SvTreeListBox,0); 1181 pImp->DestroyAnchor(); 1182 sal_uLong nRet = 0; 1183 if( !pParent->HasChilds() ) 1184 return 0; 1185 sal_uInt16 nRefDepth = pModel->GetDepth( pParent ); 1186 SvLBoxEntry* pChild = FirstChild( pParent ); 1187 do { 1188 nRet++; 1189 Select( pChild, bSelect ); 1190 pChild = Next( pChild ); 1191 } while( pChild && pModel->GetDepth( pChild ) > nRefDepth ); 1192 return nRet; 1193 } 1194 1195 void SvTreeListBox::SelectAll( sal_Bool bSelect, sal_Bool ) 1196 { 1197 DBG_CHKTHIS(SvTreeListBox,0); 1198 pImp->SelAllDestrAnch( 1199 bSelect, 1200 sal_True, // Anker loeschen, 1201 sal_True ); // auch bei SINGLE_SELECTION den Cursor deselektieren 1202 } 1203 1204 void SvTreeListBox::ModelHasInsertedTree( SvListEntry* pEntry ) 1205 { 1206 DBG_CHKTHIS(SvTreeListBox,0); 1207 sal_uInt16 nRefDepth = pModel->GetDepth( (SvLBoxEntry*)pEntry ); 1208 SvLBoxEntry* pTmp = (SvLBoxEntry*)pEntry; 1209 do 1210 { 1211 ImpEntryInserted( pTmp ); 1212 pTmp = Next( pTmp ); 1213 } while( pTmp && nRefDepth < pModel->GetDepth( pTmp ) ); 1214 pImp->TreeInserted( (SvLBoxEntry*)pEntry ); 1215 } 1216 1217 void SvTreeListBox::ModelHasInserted( SvListEntry* pEntry ) 1218 { 1219 DBG_CHKTHIS(SvTreeListBox,0); 1220 ImpEntryInserted( (SvLBoxEntry*)pEntry ); 1221 pImp->EntryInserted( (SvLBoxEntry*)pEntry ); 1222 } 1223 1224 void SvTreeListBox::ModelIsMoving(SvListEntry* pSource, 1225 SvListEntry* /* pTargetParent */, 1226 sal_uLong /* nChildPos */ ) 1227 { 1228 DBG_CHKTHIS(SvTreeListBox,0); 1229 pImp->MovingEntry( (SvLBoxEntry*)pSource ); 1230 } 1231 1232 void SvTreeListBox::ModelHasMoved( SvListEntry* pSource ) 1233 { 1234 DBG_CHKTHIS(SvTreeListBox,0); 1235 pImp->EntryMoved( (SvLBoxEntry*)pSource ); 1236 } 1237 1238 void SvTreeListBox::ModelIsRemoving( SvListEntry* pEntry ) 1239 { 1240 DBG_CHKTHIS(SvTreeListBox,0); 1241 if(pEdEntry == pEntry) 1242 pEdEntry = NULL; 1243 1244 pImp->RemovingEntry( (SvLBoxEntry*)pEntry ); 1245 NotifyRemoving( (SvLBoxEntry*)pEntry ); 1246 } 1247 1248 void SvTreeListBox::ModelHasRemoved( SvListEntry* pEntry ) 1249 { 1250 DBG_CHKTHIS(SvTreeListBox,0); 1251 if ( pEntry == pHdlEntry) 1252 pHdlEntry = NULL; 1253 pImp->EntryRemoved(); 1254 } 1255 1256 void SvTreeListBox::SetCollapsedNodeBmp( const Image& rBmp, BmpColorMode _eMode ) 1257 { 1258 DBG_CHKTHIS(SvTreeListBox,0); 1259 AdjustEntryHeight( rBmp ); 1260 pImp->SetCollapsedNodeBmp( rBmp, _eMode ); 1261 } 1262 1263 void SvTreeListBox::SetExpandedNodeBmp( const Image& rBmp, BmpColorMode _eMode ) 1264 { 1265 DBG_CHKTHIS(SvTreeListBox,0); 1266 AdjustEntryHeight( rBmp ); 1267 pImp->SetExpandedNodeBmp( rBmp, _eMode ); 1268 } 1269 1270 1271 void SvTreeListBox::SetFont( const Font& rFont ) 1272 { 1273 DBG_CHKTHIS(SvTreeListBox,0); 1274 Font aTempFont( rFont ); 1275 aTempFont.SetTransparent( sal_True ); 1276 Control::SetFont( aTempFont ); 1277 AdjustEntryHeight( aTempFont ); 1278 // immer Invalidieren, sonst fallen wir 1279 // bei SetEntryHeight auf die Nase 1280 RecalcViewData(); 1281 } 1282 1283 1284 void SvTreeListBox::Paint( const Rectangle& rRect ) 1285 { 1286 DBG_CHKTHIS(SvTreeListBox,0); 1287 SvLBox::Paint( rRect ); 1288 if( nTreeFlags & TREEFLAG_RECALCTABS ) 1289 SetTabs(); 1290 pImp->Paint( rRect ); 1291 //Solution:Add visual focus draw 1292 if( !SvLBox::First() ) 1293 { 1294 if( HasFocus() ) 1295 { 1296 long tempHeight = GetTextHeight(); 1297 Rectangle tempRect( 1298 Point(0,0),Size(GetSizePixel().Width(),tempHeight) 1299 ); 1300 ShowFocus(tempRect); 1301 } 1302 1303 else{ 1304 HideFocus(); 1305 } 1306 } 1307 } 1308 1309 void SvTreeListBox::MouseButtonDown( const MouseEvent& rMEvt ) 1310 { 1311 DBG_CHKTHIS(SvTreeListBox,0); 1312 pImp->MouseButtonDown( rMEvt ); 1313 } 1314 1315 void SvTreeListBox::MouseButtonUp( const MouseEvent& rMEvt ) 1316 { 1317 DBG_CHKTHIS(SvTreeListBox,0); 1318 pImp->MouseButtonUp( rMEvt ); 1319 } 1320 1321 void SvTreeListBox::MouseMove( const MouseEvent& rMEvt ) 1322 { 1323 DBG_CHKTHIS(SvTreeListBox,0); 1324 pImp->MouseMove( rMEvt ); 1325 } 1326 1327 1328 void SvTreeListBox::SetUpdateMode( sal_Bool bUpdate ) 1329 { 1330 DBG_CHKTHIS(SvTreeListBox,0); 1331 pImp->SetUpdateMode( bUpdate ); 1332 } 1333 1334 void SvTreeListBox::SetUpdateModeFast( sal_Bool bUpdate ) 1335 { 1336 DBG_CHKTHIS(SvTreeListBox,0); 1337 pImp->SetUpdateModeFast( bUpdate ); 1338 } 1339 1340 void SvTreeListBox::SetSpaceBetweenEntries( short nOffsLogic ) 1341 { 1342 DBG_CHKTHIS(SvTreeListBox,0); 1343 if( nOffsLogic != nEntryHeightOffs ) 1344 { 1345 nEntryHeight = nEntryHeight - nEntryHeightOffs; 1346 nEntryHeightOffs = (short)nOffsLogic; 1347 nEntryHeight = nEntryHeight + nOffsLogic; 1348 AdjustEntryHeight( GetFont() ); 1349 RecalcViewData(); 1350 pImp->SetEntryHeight( nEntryHeight ); 1351 } 1352 } 1353 1354 void SvTreeListBox::SetCursor( SvLBoxEntry* pEntry, sal_Bool bForceNoSelect ) 1355 { 1356 DBG_CHKTHIS(SvTreeListBox,0); 1357 pImp->SetCursor(pEntry, bForceNoSelect); 1358 } 1359 1360 void SvTreeListBox::SetCurEntry( SvLBoxEntry* pEntry ) 1361 { 1362 DBG_CHKTHIS(SvTreeListBox,0); 1363 pImp->SetCurEntry( pEntry ); 1364 } 1365 1366 Image SvTreeListBox::GetCollapsedNodeBmp( BmpColorMode _eMode ) const 1367 { 1368 return pImp->GetCollapsedNodeBmp( _eMode ); 1369 } 1370 1371 Image SvTreeListBox::GetExpandedNodeBmp( BmpColorMode _eMode ) const 1372 { 1373 return pImp->GetExpandedNodeBmp( _eMode ); 1374 } 1375 1376 Point SvTreeListBox::GetEntryPosition( SvLBoxEntry* pEntry ) const 1377 { 1378 return pImp->GetEntryPosition( pEntry ); 1379 } 1380 1381 void SvTreeListBox::ShowEntry( SvLBoxEntry* pEntry ) 1382 { 1383 MakeVisible( pEntry ); 1384 } 1385 1386 void SvTreeListBox::MakeVisible( SvLBoxEntry* pEntry ) 1387 { 1388 pImp->MakeVisible(pEntry); 1389 } 1390 1391 void SvTreeListBox::MakeVisible( SvLBoxEntry* pEntry, sal_Bool bMoveToTop ) 1392 { 1393 pImp->MakeVisible( pEntry, bMoveToTop ); 1394 } 1395 1396 void SvTreeListBox::ModelHasEntryInvalidated( SvListEntry* pEntry ) 1397 { 1398 DBG_CHKTHIS(SvTreeListBox,0); 1399 // die einzelnen Items des Entries reinitialisieren 1400 SvLBox::ModelHasEntryInvalidated( pEntry ); 1401 // repainten 1402 pImp->InvalidateEntry( (SvLBoxEntry*)pEntry ); 1403 } 1404 1405 void SvTreeListBox::EditItemText( SvLBoxEntry* pEntry, SvLBoxString* pItem, 1406 const Selection& rSelection ) 1407 { 1408 DBG_CHKTHIS(SvTreeListBox,0); 1409 DBG_ASSERT(pEntry&&pItem,"EditItemText: Bad params"); 1410 if( IsSelected( pEntry )) 1411 { 1412 pImp->ShowCursor( sal_False ); 1413 SvListView::Select( pEntry, sal_False ); 1414 PaintEntry( pEntry ); 1415 SvListView::Select( pEntry, sal_True ); 1416 pImp->ShowCursor( sal_True ); 1417 } 1418 pEdEntry = pEntry; 1419 pEdItem = pItem; 1420 SvLBoxTab* pTab = GetTab( pEntry, pItem ); 1421 DBG_ASSERT(pTab,"EditItemText:Tab not found"); 1422 1423 Size aItemSize( pItem->GetSize(this, pEntry) ); 1424 Point aPos = GetEntryPosition( pEntry ); 1425 aPos.Y() += ( nEntryHeight - aItemSize.Height() ) / 2; 1426 aPos.X() = GetTabPos( pEntry, pTab ); 1427 long nOutputWidth = pImp->GetOutputSize().Width(); 1428 Size aSize( nOutputWidth - aPos.X(), aItemSize.Height() ); 1429 sal_uInt16 nPos = aTabs.GetPos( pTab ); 1430 if( nPos+1 < aTabs.Count() ) 1431 { 1432 SvLBoxTab* pRightTab = (SvLBoxTab*)aTabs.GetObject( nPos + 1 ); 1433 long nRight = GetTabPos( pEntry, pRightTab ); 1434 if( nRight <= nOutputWidth ) 1435 aSize.Width() = nRight - aPos.X(); 1436 } 1437 Point aOrigin( GetMapMode().GetOrigin() ); 1438 aPos += aOrigin; // in Win-Koord umrechnen 1439 aSize.Width() -= aOrigin.X(); 1440 Rectangle aRect( aPos, aSize ); 1441 #ifdef OS2 1442 // Platz lassen fuer WB_BORDER 1443 aRect.Left() -= 2; 1444 aRect.Top() -= 3; 1445 aRect.Bottom() += 3; 1446 #endif 1447 EditText( pItem->GetText(), aRect, rSelection ); 1448 } 1449 1450 void SvTreeListBox::CancelEditing() 1451 { 1452 DBG_CHKTHIS(SvTreeListBox,0); 1453 SvLBox::CancelTextEditing(); 1454 } 1455 1456 void SvTreeListBox::EditEntry( SvLBoxEntry* pEntry ) 1457 { 1458 pImp->aEditClickPos = Point( -1, -1 ); 1459 ImplEditEntry( pEntry ); 1460 } 1461 1462 void SvTreeListBox::ImplEditEntry( SvLBoxEntry* pEntry ) 1463 { 1464 DBG_CHKTHIS(SvTreeListBox,0); 1465 if( IsEditingActive() ) 1466 EndEditing(); 1467 if( !pEntry ) 1468 pEntry = GetCurEntry(); 1469 if( pEntry ) 1470 { 1471 long nClickX = pImp->aEditClickPos.X(); 1472 bool bIsMouseTriggered = nClickX >= 0; 1473 1474 SvLBoxString* pItem = NULL; 1475 sal_uInt16 nCount = pEntry->ItemCount(); 1476 for( sal_uInt16 i = 0 ; i < nCount ; i++ ) 1477 { 1478 SvLBoxItem* pTmpItem = pEntry->GetItem( i ); 1479 if( pTmpItem->IsA() != SV_ITEM_ID_LBOXSTRING ) 1480 continue; 1481 1482 SvLBoxTab* pTab = GetTab( pEntry, pTmpItem ); 1483 long nTabPos = pTab->GetPos(); 1484 long nNextTabPos = -1; 1485 if( i < nCount - 1 ) 1486 { 1487 SvLBoxItem* pNextItem = pEntry->GetItem( i + 1 ); 1488 SvLBoxTab* pNextTab = GetTab( pEntry, pNextItem ); 1489 nNextTabPos = pNextTab->GetPos(); 1490 } 1491 1492 if( pTab && pTab->IsEditable() ) 1493 { 1494 if( !bIsMouseTriggered || (nClickX > nTabPos && (nNextTabPos == -1 || nClickX < nNextTabPos ) ) ) 1495 { 1496 pItem = static_cast<SvLBoxString*>( pTmpItem ); 1497 break; 1498 } 1499 } 1500 } 1501 1502 Selection aSel( SELECTION_MIN, SELECTION_MAX ); 1503 if( pItem && EditingEntry( pEntry, aSel ) ) 1504 { 1505 SelectAll( sal_False ); 1506 MakeVisible( pEntry ); 1507 EditItemText( pEntry, pItem, aSel ); 1508 } 1509 } 1510 } 1511 1512 sal_Bool SvTreeListBox::AreChildrenTransient() const 1513 { 1514 return pImp->AreChildrenTransient(); 1515 } 1516 1517 void SvTreeListBox::SetChildrenNotTransient() 1518 { 1519 pImp->SetChildrenNotTransient(); 1520 } 1521 1522 void SvTreeListBox::EditedText( const XubString& rStr ) 1523 1524 { 1525 DBG_CHKTHIS(SvTreeListBox,0); 1526 if(pEdEntry) // we have to check if this entry is null that means that it is removed while editing 1527 { 1528 Point aPos = GetEntryPosition( pEdEntry ); 1529 if( EditedEntry( pEdEntry, rStr ) ) 1530 { 1531 ((SvLBoxString*)pEdItem)->SetText( pEdEntry, rStr ); 1532 pModel->InvalidateEntry( pEdEntry ); 1533 } 1534 //if( GetSelectionMode() == SINGLE_SELECTION ) 1535 //{ 1536 if( GetSelectionCount() == 0 ) 1537 Select( pEdEntry ); 1538 if( GetSelectionMode() == MULTIPLE_SELECTION && !GetCurEntry() ) 1539 SetCurEntry( pEdEntry ); 1540 //} 1541 } 1542 } 1543 1544 void SvTreeListBox::EditingRequest( SvLBoxEntry* pEntry, SvLBoxItem* pItem, 1545 const Point& ) 1546 { 1547 DBG_CHKTHIS(SvTreeListBox,0); 1548 if( IsEditingActive() ) 1549 EndEditing(); 1550 if( pItem->IsA() == SV_ITEM_ID_LBOXSTRING ) 1551 { 1552 Selection aSel( SELECTION_MIN, SELECTION_MAX ); 1553 if( EditingEntry( pEntry, aSel ) ) 1554 { 1555 SelectAll( sal_False ); 1556 EditItemText( pEntry, (SvLBoxString*)pItem, aSel ); 1557 } 1558 } 1559 } 1560 1561 1562 1563 SvLBoxEntry* SvTreeListBox::GetDropTarget( const Point& rPos ) 1564 { 1565 DBG_CHKTHIS(SvTreeListBox,0); 1566 // Scrollen 1567 if( rPos.Y() < 12 ) 1568 { 1569 SvLBox::ImplShowTargetEmphasis( SvLBox::pTargetEntry, sal_False ); 1570 ScrollOutputArea( +1 ); 1571 } 1572 else 1573 { 1574 Size aSize( pImp->GetOutputSize() ); 1575 if( rPos.Y() > aSize.Height() - 12 ) 1576 { 1577 SvLBox::ImplShowTargetEmphasis( SvLBox::pTargetEntry, sal_False ); 1578 ScrollOutputArea( -1 ); 1579 } 1580 } 1581 1582 SvLBoxEntry* pTarget = pImp->GetEntry( rPos ); 1583 // bei Droppen in leere Flaeche -> den letzten Eintrag nehmen 1584 if( !pTarget ) 1585 return (SvLBoxEntry*)LastVisible(); 1586 else if( (GetDragDropMode() & SV_DRAGDROP_ENABLE_TOP) && 1587 pTarget == First() && rPos.Y() < 6 ) 1588 return 0; 1589 1590 return pTarget; 1591 } 1592 1593 1594 SvLBoxEntry* SvTreeListBox::GetEntry( const Point& rPos, sal_Bool bHit ) const 1595 { 1596 DBG_CHKTHIS(SvTreeListBox,0); 1597 SvLBoxEntry* pEntry = pImp->GetEntry( rPos ); 1598 if( pEntry && bHit ) 1599 { 1600 long nLine = pImp->GetEntryLine( pEntry ); 1601 if( !(pImp->EntryReallyHit( pEntry, rPos, nLine)) ) 1602 return 0; 1603 } 1604 return pEntry; 1605 } 1606 1607 SvLBoxEntry* SvTreeListBox::GetCurEntry() const 1608 { 1609 DBG_CHKTHIS(SvTreeListBox,0); 1610 return pImp->GetCurEntry(); 1611 } 1612 1613 void SvTreeListBox::ImplInitStyle() 1614 { 1615 DBG_CHKTHIS(SvTreeListBox,0); 1616 1617 const WinBits nWindowStyle = GetStyle(); 1618 1619 nTreeFlags |= TREEFLAG_RECALCTABS; 1620 if( nWindowStyle & WB_SORT ) 1621 { 1622 GetModel()->SetSortMode( SortAscending ); 1623 GetModel()->SetCompareHdl( LINK(this,SvTreeListBox,DefaultCompare)); 1624 } 1625 else 1626 { 1627 GetModel()->SetSortMode( SortNone ); 1628 GetModel()->SetCompareHdl( Link() ); 1629 } 1630 pImp->SetStyle( nWindowStyle ); 1631 pImp->Resize(); 1632 Invalidate(); 1633 } 1634 1635 void SvTreeListBox::PaintEntry( SvLBoxEntry* pEntry ) 1636 { 1637 DBG_CHKTHIS(SvTreeListBox,0); 1638 DBG_ASSERT(pEntry,"PaintEntry:No Entry"); 1639 if( pEntry ) 1640 pImp->PaintEntry( pEntry ); 1641 } 1642 1643 void SvTreeListBox::InvalidateEntry( SvLBoxEntry* pEntry ) 1644 { 1645 DBG_CHKTHIS(SvTreeListBox,0); 1646 DBG_ASSERT(pEntry,"InvalidateEntry:No Entry"); 1647 if( pEntry ) 1648 { 1649 GetModel()->InvalidateEntry( pEntry ); 1650 // pImp->InvalidateEntry( pEntry ); 1651 } 1652 } 1653 1654 1655 long SvTreeListBox::PaintEntry(SvLBoxEntry* pEntry,long nLine,sal_uInt16 nTabFlags) 1656 { 1657 return PaintEntry1(pEntry,nLine,nTabFlags); 1658 } 1659 1660 #define SV_TAB_BORDER 8 1661 1662 long SvTreeListBox::PaintEntry1(SvLBoxEntry* pEntry,long nLine,sal_uInt16 nTabFlags, 1663 sal_Bool bHasClipRegion ) 1664 { 1665 DBG_CHKTHIS(SvTreeListBox,0); 1666 1667 Rectangle aRect; // multi purpose 1668 1669 sal_Bool bHorSBar = pImp->HasHorScrollBar(); 1670 PreparePaint( pEntry ); 1671 1672 // #97680# ------------------ 1673 pImp->UpdateContextBmpWidthMax( pEntry ); 1674 1675 if( nTreeFlags & TREEFLAG_RECALCTABS ) 1676 SetTabs(); 1677 1678 short nTempEntryHeight = GetEntryHeight(); 1679 long nWidth = pImp->GetOutputSize().Width(); 1680 1681 // wurde innerhalb des PreparePaints die horizontale ScrollBar 1682 // angeschaltet? Wenn ja, muss die ClipRegion neu gesetzt werden 1683 if( !bHorSBar && pImp->HasHorScrollBar() ) 1684 SetClipRegion( Region(pImp->GetClipRegionRect()) ); 1685 1686 Point aEntryPos( GetMapMode().GetOrigin() ); 1687 aEntryPos.X() *= -1; // Umrechnung Dokumentkoord. 1688 long nMaxRight = nWidth + aEntryPos.X() - 1; 1689 1690 Color aBackupTextColor( GetTextColor() ); 1691 Font aBackupFont( GetFont() ); 1692 Color aBackupColor = GetFillColor(); 1693 1694 bool bCurFontIsSel = false; 1695 sal_Bool bInUse = pEntry->HasInUseEmphasis(); 1696 // wenn eine ClipRegion von aussen gesetzt wird, dann 1697 // diese nicht zuruecksetzen 1698 const WinBits nWindowStyle = GetStyle(); 1699 const sal_Bool bResetClipRegion = !bHasClipRegion; 1700 const sal_Bool bHideSelection = ((nWindowStyle & WB_HIDESELECTION) && !HasFocus())!=0; 1701 const StyleSettings& rSettings = GetSettings().GetStyleSettings(); 1702 1703 Font aHighlightFont( GetFont() ); 1704 const Color aHighlightTextColor( rSettings.GetHighlightTextColor() ); 1705 aHighlightFont.SetColor( aHighlightTextColor ); 1706 1707 Size aRectSize( 0, nTempEntryHeight ); 1708 1709 if( !bHasClipRegion && nWindowStyle & WB_HSCROLL ) 1710 { 1711 SetClipRegion( Region(pImp->GetClipRegionRect()) ); 1712 bHasClipRegion = sal_True; 1713 } 1714 1715 SvViewDataEntry* pViewDataEntry = GetViewDataEntry( pEntry ); 1716 1717 sal_uInt16 nTabCount = aTabs.Count(); 1718 sal_uInt16 nItemCount = pEntry->ItemCount(); 1719 sal_uInt16 nCurTab = 0; 1720 sal_uInt16 nCurItem = 0; 1721 1722 while( nCurTab < nTabCount && nCurItem < nItemCount ) 1723 { 1724 SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nCurTab ); 1725 sal_uInt16 nNextTab = nCurTab + 1; 1726 SvLBoxTab* pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0; 1727 SvLBoxItem* pItem = nCurItem < nItemCount ? pEntry->GetItem(nCurItem) : 0; 1728 1729 sal_uInt16 nFlags = pTab->nFlags; 1730 Size aSize( pItem->GetSize( pViewDataEntry, nCurItem )); 1731 long nTabPos = GetTabPos( pEntry, pTab ); 1732 1733 long nNextTabPos; 1734 if( pNextTab ) 1735 nNextTabPos = GetTabPos( pEntry, pNextTab ); 1736 else 1737 { 1738 nNextTabPos = nMaxRight; 1739 if( nTabPos > nMaxRight ) 1740 nNextTabPos += 50; 1741 } 1742 1743 long nX; 1744 if( pTab->nFlags & SV_LBOXTAB_ADJUST_RIGHT ) 1745 //verhindern, das rechter Rand von der Tabtrennung abgeschnitten wird 1746 nX = nTabPos + pTab->CalcOffset(aSize.Width(), (nNextTabPos-SV_TAB_BORDER-1) -nTabPos); 1747 else 1748 nX = nTabPos + pTab->CalcOffset(aSize.Width(), nNextTabPos-nTabPos); 1749 1750 if( nFlags & nTabFlags ) 1751 { 1752 if( !bHasClipRegion && nX + aSize.Width() >= nMaxRight ) 1753 { 1754 SetClipRegion( Region(pImp->GetClipRegionRect()) ); 1755 bHasClipRegion = sal_True; 1756 } 1757 aEntryPos.X() = nX; 1758 aEntryPos.Y() = nLine; 1759 1760 // Hintergrund-Muster & Farbe bestimmen 1761 1762 Wallpaper aWallpaper = GetBackground(); 1763 1764 int bSelTab = nFlags & SV_LBOXTAB_SHOW_SELECTION; 1765 sal_uInt16 nItemType = pItem->IsA(); 1766 1767 if ( pViewDataEntry->IsSelected() && bSelTab && !pViewDataEntry->IsCursored() ) 1768 { 1769 Color aNewWallColor = rSettings.GetHighlightColor(); 1770 if ( !bInUse || nItemType != SV_ITEM_ID_LBOXCONTEXTBMP ) 1771 { 1772 // if the face color is bright then the deactive color is also bright 1773 // -> so you can't see any deactive selection 1774 if ( bHideSelection && !rSettings.GetFaceColor().IsBright() && 1775 aWallpaper.GetColor().IsBright() != rSettings.GetDeactiveColor().IsBright() ) 1776 aNewWallColor = rSettings.GetDeactiveColor(); 1777 // set font color to highlight 1778 if ( !bCurFontIsSel ) 1779 { 1780 SetTextColor( aHighlightTextColor ); 1781 SetFont( aHighlightFont ); 1782 bCurFontIsSel = true; 1783 } 1784 } 1785 aWallpaper.SetColor( aNewWallColor ); 1786 } 1787 else // keine Selektion 1788 { 1789 if( bInUse && nItemType == SV_ITEM_ID_LBOXCONTEXTBMP ) 1790 aWallpaper.SetColor( rSettings.GetFieldColor() ); 1791 else if( bCurFontIsSel ) 1792 { 1793 bCurFontIsSel = false; 1794 SetTextColor( aBackupTextColor ); 1795 SetFont( aBackupFont ); 1796 } 1797 } 1798 1799 // Hintergrund zeichnen 1800 if( !(nTreeFlags & TREEFLAG_USESEL)) 1801 { 1802 // nur den Bereich zeichnen, den das Item einnimmt 1803 aRectSize.Width() = aSize.Width(); 1804 aRect.SetPos( aEntryPos ); 1805 aRect.SetSize( aRectSize ); 1806 } 1807 else 1808 { 1809 // vom aktuellen bis zum naechsten Tab zeichnen 1810 if( nCurTab != 0 ) 1811 aRect.Left() = nTabPos; 1812 else 1813 // beim nullten Tab immer ab Spalte 0 zeichnen 1814 // (sonst Probleme bei Tabs mit Zentrierung) 1815 aRect.Left() = 0; 1816 aRect.Top() = nLine; 1817 aRect.Bottom() = nLine + nTempEntryHeight - 1; 1818 if( pNextTab ) 1819 { 1820 long nRight; 1821 nRight = GetTabPos(pEntry,pNextTab)-1; 1822 if( nRight > nMaxRight ) 1823 nRight = nMaxRight; 1824 aRect.Right() = nRight; 1825 } 1826 else 1827 aRect.Right() = nMaxRight; 1828 } 1829 // bei anwenderdefinierter Selektion, die bei einer Tabposition 1830 // groesser 0 beginnt den Hintergrund des 0.ten Items nicht 1831 // fuellen, da sonst z.B. TablistBoxen mit Linien nicht 1832 // realisiert werden koennen. 1833 if( !(nCurTab==0 && (nTreeFlags & TREEFLAG_USESEL) && nFirstSelTab) ) 1834 { 1835 SetFillColor( aWallpaper.GetColor() ); 1836 // Bei kleinen hor. Resizes tritt dieser Fall auf 1837 if( aRect.Left() < aRect.Right() ) 1838 DrawRect( aRect ); 1839 } 1840 // Item zeichnen 1841 // vertikal zentrieren 1842 aEntryPos.Y() += ( nTempEntryHeight - aSize.Height() ) / 2; 1843 pItem->Paint( aEntryPos, *this, pViewDataEntry->GetFlags(), pEntry ); 1844 1845 // Trennungslinie zwischen Tabs 1846 if( pNextTab && pItem->IsA() == SV_ITEM_ID_LBOXSTRING && 1847 // nicht am rechten Fensterrand! 1848 aRect.Right() < nMaxRight ) 1849 { 1850 aRect.Left() = aRect.Right() - SV_TAB_BORDER; 1851 DrawRect( aRect ); 1852 } 1853 1854 SetFillColor( aBackupColor ); 1855 } 1856 nCurItem++; 1857 nCurTab++; 1858 } 1859 if( pViewDataEntry->IsCursored() && !HasFocus() ) 1860 { 1861 // Cursor-Emphasis 1862 SetFillColor(); 1863 Color aOldLineColor = GetLineColor(); 1864 SetLineColor( Color( COL_BLACK ) ); 1865 aRect = GetFocusRect( pEntry, nLine ); 1866 aRect.Top()++; 1867 aRect.Bottom()--; 1868 DrawRect( aRect ); 1869 SetLineColor( aOldLineColor ); 1870 SetFillColor( aBackupColor ); 1871 } 1872 1873 if( bCurFontIsSel ) 1874 { 1875 SetTextColor( aBackupTextColor ); 1876 SetFont( aBackupFont ); 1877 } 1878 1879 sal_uInt16 nFirstDynTabPos; 1880 SvLBoxTab* pFirstDynamicTab = GetFirstDynamicTab( nFirstDynTabPos ); 1881 long nDynTabPos = GetTabPos( pEntry, pFirstDynamicTab ); 1882 nDynTabPos += pImp->nNodeBmpTabDistance; 1883 nDynTabPos += pImp->nNodeBmpWidth / 2; 1884 nDynTabPos += 4; // 4 Pixel Reserve, damit die Node-Bitmap 1885 // nicht zu nah am naechsten Tab steht 1886 1887 if( (!(pEntry->GetFlags() & SV_ENTRYFLAG_NO_NODEBMP)) && 1888 (nWindowStyle & WB_HASBUTTONS) && pFirstDynamicTab && 1889 ( pEntry->HasChilds() || pEntry->HasChildsOnDemand() ) ) 1890 { 1891 // ersten festen Tab suchen, und pruefen ob die Node-Bitmap 1892 // in ihn hineinragt 1893 sal_uInt16 nNextTab = nFirstDynTabPos; 1894 SvLBoxTab* pNextTab; 1895 do 1896 { 1897 nNextTab++; 1898 pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0; 1899 } while( pNextTab && pNextTab->IsDynamic() ); 1900 1901 if( !pNextTab || (GetTabPos( pEntry, pNextTab ) > nDynTabPos) ) 1902 { 1903 if((nWindowStyle & WB_HASBUTTONSATROOT) || pModel->GetDepth(pEntry) > 0) 1904 { 1905 Point aPos( GetTabPos(pEntry,pFirstDynamicTab), nLine ); 1906 aPos.X() += pImp->nNodeBmpTabDistance; 1907 1908 const Image* pImg = 0; 1909 BmpColorMode eBitmapMode = BMP_COLOR_NORMAL; 1910 if ( GetSettings().GetStyleSettings().GetHighContrastMode() ) 1911 eBitmapMode = BMP_COLOR_HIGHCONTRAST; 1912 1913 if( IsExpanded(pEntry) ) 1914 pImg = &pImp->GetExpandedNodeBmp( eBitmapMode ); 1915 else 1916 { 1917 if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() && 1918 (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) && 1919 pImp->GetDontKnowNodeBmp().GetSizePixel().Width() ) 1920 pImg = &pImp->GetDontKnowNodeBmp( eBitmapMode ); 1921 else 1922 pImg = &pImp->GetCollapsedNodeBmp( eBitmapMode ); 1923 } 1924 aPos.Y() += (nTempEntryHeight - pImg->GetSizePixel().Height()) / 2; 1925 1926 sal_uInt16 nStyle = 0; 1927 if ( !IsEnabled() ) 1928 nStyle |= IMAGE_DRAW_DISABLE; 1929 1930 //native 1931 sal_Bool bNativeOK = sal_False; 1932 if ( IsNativeControlSupported( CTRL_LISTNODE, PART_ENTIRE_CONTROL) ) 1933 { 1934 ImplControlValue aControlValue; 1935 Rectangle aCtrlRegion( aPos, pImg->GetSizePixel() ); 1936 ControlState nState = 0; 1937 1938 if ( IsEnabled() ) nState |= CTRL_STATE_ENABLED; 1939 1940 if ( IsExpanded(pEntry) ) 1941 aControlValue.setTristateVal( BUTTONVALUE_ON );//expanded node 1942 else 1943 { 1944 if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() && 1945 (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) && 1946 pImp->GetDontKnowNodeBmp().GetSizePixel().Width() ) 1947 aControlValue.setTristateVal( BUTTONVALUE_DONTKNOW );//dont know 1948 else 1949 aControlValue.setTristateVal( BUTTONVALUE_OFF );//collapsed node 1950 } 1951 1952 bNativeOK = DrawNativeControl( CTRL_LISTNODE, PART_ENTIRE_CONTROL, 1953 aCtrlRegion, nState, aControlValue, rtl::OUString() ); 1954 } 1955 1956 if( !bNativeOK) { 1957 //non native 1958 DrawImage( aPos, *pImg ,nStyle); 1959 } 1960 } 1961 } 1962 } 1963 1964 1965 if( bHasClipRegion && bResetClipRegion ) 1966 SetClipRegion(); 1967 return 0; // nRowLen; 1968 } 1969 1970 void SvTreeListBox::PreparePaint( SvLBoxEntry* ) 1971 { 1972 } 1973 1974 Rectangle SvTreeListBox::GetFocusRect( SvLBoxEntry* pEntry, long nLine ) 1975 { 1976 DBG_CHKTHIS(SvTreeListBox,0); 1977 Size aSize; 1978 Rectangle aRect; 1979 aRect.Top() = nLine; 1980 aSize.Height() = GetEntryHeight(); 1981 1982 long nRealWidth = pImp->GetOutputSize().Width(); 1983 nRealWidth -= GetMapMode().GetOrigin().X(); 1984 1985 sal_uInt16 nCurTab; 1986 SvLBoxTab* pTab = GetFirstTab( SV_LBOXTAB_SHOW_SELECTION, nCurTab ); 1987 long nTabPos = 0; 1988 if( pTab ) 1989 nTabPos = GetTabPos( pEntry, pTab ); 1990 long nNextTabPos; 1991 if( pTab && nCurTab < aTabs.Count() - 1 ) 1992 { 1993 SvLBoxTab* pNextTab = (SvLBoxTab*)aTabs.GetObject( nCurTab + 1 ); 1994 nNextTabPos = GetTabPos( pEntry, pNextTab ); 1995 } 1996 else 1997 { 1998 nNextTabPos = nRealWidth; 1999 if( nTabPos > nRealWidth ) 2000 nNextTabPos += 50; 2001 } 2002 2003 sal_Bool bUserSelection = (sal_Bool)( nTreeFlags & TREEFLAG_USESEL ) != 0; 2004 if( !bUserSelection ) 2005 { 2006 if( pTab && nCurTab < pEntry->ItemCount() ) 2007 { 2008 SvLBoxItem* pItem = pEntry->GetItem( nCurTab ); 2009 aSize.Width() = pItem->GetSize( this, pEntry ).Width(); 2010 if( !aSize.Width() ) 2011 aSize.Width() = 15; 2012 long nX = nTabPos; //GetTabPos( pEntry, pTab ); 2013 // Ausrichtung 2014 nX += pTab->CalcOffset( aSize.Width(), nNextTabPos - nTabPos ); 2015 aRect.Left() = nX; 2016 // damit erster & letzter Buchstabe nicht angeknabbert werden 2017 aRect.SetSize( aSize ); 2018 if( aRect.Left() > 0 ) 2019 aRect.Left()--; 2020 aRect.Right()++; 2021 } 2022 } 2023 else 2024 { 2025 // wenn erster SelTab != 0, dann muessen wir auch rechnen 2026 if( nFocusWidth == -1 || nFirstSelTab ) 2027 { 2028 sal_uInt16 nLastTab; 2029 SvLBoxTab* pLastTab = GetLastTab(SV_LBOXTAB_SHOW_SELECTION,nLastTab); 2030 nLastTab++; 2031 if( nLastTab < aTabs.Count() ) // gibts noch einen ? 2032 pLastTab = (SvLBoxTab*)aTabs.GetObject( nLastTab ); 2033 else 2034 pLastTab = 0; // ueber gesamte Breite selektieren 2035 aSize.Width() = pLastTab ? pLastTab->GetPos() : 0x0fffffff; 2036 nFocusWidth = (short)aSize.Width(); 2037 if( pTab ) 2038 nFocusWidth = nFocusWidth - (short)nTabPos; //pTab->GetPos(); 2039 } 2040 else 2041 { 2042 aSize.Width() = nFocusWidth; 2043 if( pTab ) 2044 { 2045 if( nCurTab ) 2046 aSize.Width() += nTabPos; 2047 else 2048 aSize.Width() += pTab->GetPos(); // Tab0 immer ab ganz links 2049 } 2050 } 2051 // wenn Sel. beim nullten Tab anfaengt, dann ab Spalte 0 sel. zeichnen 2052 if( nCurTab != 0 ) 2053 { 2054 aRect.Left() = nTabPos; 2055 aSize.Width() -= nTabPos; 2056 } 2057 aRect.SetSize( aSize ); 2058 } 2059 // rechten Rand anpassen wg. Clipping 2060 if( aRect.Right() >= nRealWidth ) 2061 { 2062 aRect.Right() = nRealWidth-1; 2063 nFocusWidth = (short)aRect.GetWidth(); 2064 } 2065 return aRect; 2066 } 2067 2068 2069 long SvTreeListBox::GetTabPos( SvLBoxEntry* pEntry, SvLBoxTab* pTab) 2070 { 2071 DBG_CHKTHIS(SvTreeListBox,0); 2072 DBG_ASSERT(pTab,"No Tab"); 2073 long nPos = pTab->GetPos(); 2074 if( pTab->IsDynamic() ) 2075 { 2076 sal_uInt16 nDepth = pModel->GetDepth( pEntry ); 2077 nDepth = nDepth * (sal_uInt16)nIndent; 2078 nPos += (long)nDepth; 2079 } 2080 return nPos; 2081 } 2082 2083 SvLBoxItem* SvTreeListBox::GetItem_Impl( SvLBoxEntry* pEntry, long nX, 2084 SvLBoxTab** ppTab, sal_uInt16 nEmptyWidth ) 2085 { 2086 DBG_CHKTHIS(SvTreeListBox,0); 2087 SvLBoxItem* pItemClicked = 0; 2088 sal_uInt16 nTabCount = aTabs.Count(); 2089 sal_uInt16 nItemCount = pEntry->ItemCount(); 2090 SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0); 2091 SvLBoxItem* pItem = pEntry->GetItem(0); 2092 sal_uInt16 nNextItem = 1; 2093 nX -= GetMapMode().GetOrigin().X(); 2094 long nRealWidth = pImp->GetOutputSize().Width(); 2095 nRealWidth -= GetMapMode().GetOrigin().X(); 2096 2097 while( 1 ) 2098 { 2099 SvLBoxTab* pNextTab=nNextItem<nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextItem) : 0; 2100 long nStart = GetTabPos( pEntry, pTab ); 2101 2102 long nNextTabPos; 2103 if( pNextTab ) 2104 nNextTabPos = GetTabPos( pEntry, pNextTab ); 2105 else 2106 { 2107 nNextTabPos = nRealWidth; 2108 if( nStart > nRealWidth ) 2109 nNextTabPos += 50; 2110 } 2111 2112 Size aItemSize( pItem->GetSize(this, pEntry)); 2113 nStart += pTab->CalcOffset( aItemSize.Width(), nNextTabPos - nStart ); 2114 long nLen = aItemSize.Width(); 2115 if( pNextTab ) 2116 { 2117 long nTabWidth = GetTabPos( pEntry, pNextTab ) - nStart; 2118 if( nTabWidth < nLen ) 2119 nLen = nTabWidth; 2120 } 2121 2122 if( !nLen ) 2123 nLen = nEmptyWidth; 2124 2125 if( nX >= nStart && nX < (nStart+nLen ) ) 2126 { 2127 pItemClicked = pItem; 2128 if( ppTab ) 2129 { 2130 *ppTab = pTab; 2131 break; 2132 } 2133 } 2134 if( nNextItem >= nItemCount || nNextItem >= nTabCount) 2135 break; 2136 pTab = (SvLBoxTab*)aTabs.GetObject( nNextItem ); 2137 pItem = pEntry->GetItem( nNextItem ); 2138 nNextItem++; 2139 } 2140 return pItemClicked; 2141 } 2142 2143 SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX,SvLBoxTab** ppTab) 2144 { 2145 return GetItem_Impl( pEntry, nX, ppTab, 0 ); 2146 } 2147 2148 SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX ) 2149 { 2150 DBG_CHKTHIS(SvTreeListBox,0); 2151 SvLBoxTab* pDummyTab; 2152 return GetItem_Impl( pEntry, nX, &pDummyTab, 0 ); 2153 } 2154 2155 SvLBoxItem* SvTreeListBox::GetFirstDynamicItem( SvLBoxEntry* pEntry ) 2156 { 2157 DBG_CHKTHIS(SvTreeListBox,0); 2158 2159 SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0); 2160 SvLBoxItem* pItem = pEntry->GetItem(0); 2161 sal_uInt16 nTabCount = aTabs.Count(); 2162 2163 sal_uInt16 nNext = 1; 2164 while ( !pTab->IsDynamic() && nNext < nTabCount ) 2165 { 2166 pItem = pEntry->GetItem( nNext ); 2167 pTab = (SvLBoxTab*)aTabs.GetObject( nNext ); 2168 nNext++; 2169 } 2170 return pItem; 2171 } 2172 2173 void SvTreeListBox::AddTab(long nTabPos,sal_uInt16 nFlags,void* pUserData ) 2174 { 2175 DBG_CHKTHIS(SvTreeListBox,0); 2176 nFocusWidth = -1; 2177 SvLBoxTab* pTab = new SvLBoxTab( nTabPos, nFlags ); 2178 pTab->SetUserData( pUserData ); 2179 aTabs.Insert( pTab, aTabs.Count() ); 2180 if( nTreeFlags & TREEFLAG_USESEL ) 2181 { 2182 sal_uInt16 nPos = aTabs.Count() - 1; 2183 if( nPos >= nFirstSelTab && nPos <= nLastSelTab ) 2184 pTab->nFlags |= SV_LBOXTAB_SHOW_SELECTION; 2185 else 2186 // String-Items werden normalerweise immer selektiert 2187 // deshalb explizit ausschalten 2188 pTab->nFlags &= ~SV_LBOXTAB_SHOW_SELECTION; 2189 } 2190 } 2191 2192 2193 2194 SvLBoxTab* SvTreeListBox::GetFirstDynamicTab( sal_uInt16& rPos ) const 2195 { 2196 DBG_CHKTHIS(SvTreeListBox,0); 2197 sal_uInt16 nCurTab = 0; 2198 sal_uInt16 nTabCount = aTabs.Count(); 2199 while( nCurTab < nTabCount ) 2200 { 2201 SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(nCurTab); 2202 if( pTab->nFlags & SV_LBOXTAB_DYNAMIC ) 2203 { 2204 rPos = nCurTab; 2205 return pTab; 2206 } 2207 nCurTab++; 2208 } 2209 return 0; 2210 } 2211 2212 SvLBoxTab* SvTreeListBox::GetFirstDynamicTab() const 2213 { 2214 sal_uInt16 nDummy; 2215 return GetFirstDynamicTab( nDummy ); 2216 } 2217 2218 SvLBoxTab* SvTreeListBox::GetTab( SvLBoxEntry* pEntry, SvLBoxItem* pItem) const 2219 { 2220 DBG_CHKTHIS(SvTreeListBox,0); 2221 sal_uInt16 nPos = pEntry->GetPos( pItem ); 2222 return (SvLBoxTab*)aTabs.GetObject( nPos ); 2223 } 2224 2225 void SvTreeListBox::ClearTabList() 2226 { 2227 DBG_CHKTHIS(SvTreeListBox,0); 2228 sal_uInt16 nTabCount = aTabs.Count(); 2229 while( nTabCount ) 2230 { 2231 nTabCount--; 2232 SvLBoxTab* pDelTab = (SvLBoxTab*)aTabs.GetObject( nTabCount ); 2233 delete pDelTab; 2234 } 2235 aTabs.Remove(0,aTabs.Count()); 2236 } 2237 2238 2239 Size SvTreeListBox::GetOutputSizePixel() const 2240 { 2241 DBG_CHKTHIS(SvTreeListBox,0); 2242 Size aSize = pImp->GetOutputSize(); 2243 return aSize; 2244 } 2245 2246 void SvTreeListBox::NotifyBeginScroll() 2247 { 2248 DBG_CHKTHIS(SvTreeListBox,0); 2249 } 2250 2251 void SvTreeListBox::NotifyEndScroll() 2252 { 2253 DBG_CHKTHIS(SvTreeListBox,0); 2254 } 2255 2256 void SvTreeListBox::NotifyScrolling( long ) 2257 { 2258 DBG_CHKTHIS(SvTreeListBox,0); 2259 } 2260 2261 void SvTreeListBox::NotifyScrolled() 2262 { 2263 DBG_CHKTHIS(SvTreeListBox,0); 2264 aScrolledHdl.Call( this ); 2265 } 2266 2267 void SvTreeListBox::NotifyInvalidating() 2268 { 2269 DBG_CHKTHIS(SvTreeListBox,0); 2270 } 2271 2272 void SvTreeListBox::Invalidate( sal_uInt16 nInvalidateFlags ) 2273 { 2274 DBG_CHKTHIS(SvTreeListBox,0); 2275 if( nFocusWidth == -1 ) 2276 // damit Control nicht nach dem Paint ein falsches FocusRect anzeigt 2277 pImp->RecalcFocusRect(); 2278 NotifyInvalidating(); 2279 SvLBox::Invalidate( nInvalidateFlags ); 2280 pImp->Invalidate(); 2281 } 2282 2283 void SvTreeListBox::Invalidate( const Rectangle& rRect, sal_uInt16 nInvalidateFlags ) 2284 { 2285 DBG_CHKTHIS(SvTreeListBox,0); 2286 if( nFocusWidth == -1 ) 2287 // damit Control nicht nach dem Paint ein falsches FocusRect anzeigt 2288 pImp->RecalcFocusRect(); 2289 NotifyInvalidating(); 2290 SvLBox::Invalidate( rRect, nInvalidateFlags ); 2291 } 2292 2293 2294 void SvTreeListBox::SetHighlightRange( sal_uInt16 nStart, sal_uInt16 nEnd) 2295 { 2296 DBG_CHKTHIS(SvTreeListBox,0); 2297 2298 sal_uInt16 nTemp; 2299 nTreeFlags |= TREEFLAG_USESEL; 2300 if( nStart > nEnd ) 2301 { 2302 nTemp = nStart; 2303 nStart = nEnd; 2304 nEnd = nTemp; 2305 } 2306 // alle Tabs markieren, die im Bereich liegen 2307 nTreeFlags |= TREEFLAG_RECALCTABS; 2308 nFirstSelTab = nStart; 2309 nLastSelTab = nEnd; 2310 pImp->RecalcFocusRect(); 2311 } 2312 2313 void SvTreeListBox::RemoveHighlightRange() 2314 { 2315 DBG_CHKTHIS(SvTreeListBox,0); 2316 nTreeFlags &= (~TREEFLAG_USESEL); 2317 if( IsUpdateMode() ) 2318 Invalidate(); 2319 } 2320 2321 sal_uLong SvTreeListBox::GetAscInsertionPos(SvLBoxEntry*,SvLBoxEntry*) 2322 { 2323 return LIST_APPEND; 2324 } 2325 2326 sal_uLong SvTreeListBox::GetDescInsertionPos(SvLBoxEntry*,SvLBoxEntry*) 2327 { 2328 DBG_CHKTHIS(SvTreeListBox,0); 2329 return LIST_APPEND; 2330 } 2331 2332 Region SvTreeListBox::GetDragRegion() const 2333 { 2334 DBG_CHKTHIS(SvTreeListBox,0); 2335 Rectangle aRect; 2336 SvLBoxEntry* pEntry = GetCurEntry(); 2337 if( pEntry ) 2338 { 2339 Point aPos = GetEntryPosition( pEntry ); 2340 aRect = ((SvTreeListBox*)this)->GetFocusRect( pEntry, aPos.Y() ); 2341 } 2342 Region aRegion( aRect ); 2343 return aRegion; 2344 } 2345 2346 2347 void SvTreeListBox::Command( const CommandEvent& rCEvt ) 2348 { 2349 DBG_CHKTHIS(SvTreeListBox,0); 2350 // FIXME gnumake2 resync to DEV300_m84 2351 pImp->Command( rCEvt ); 2352 } 2353 2354 2355 void SvTreeListBox::RemoveParentKeepChilds( SvLBoxEntry* pParent ) 2356 { 2357 DBG_CHKTHIS(SvTreeListBox,0); 2358 DBG_ASSERT(pParent,"RemoveParentKeepChilds:No Parent"); 2359 SvLBoxEntry* pNewParent = GetParent( pParent ); 2360 if( pParent->HasChilds()) 2361 { 2362 SvLBoxEntry* pChild = FirstChild( pParent ); 2363 while( pChild ) 2364 { 2365 pModel->Move( pChild, pNewParent, LIST_APPEND ); 2366 pChild = FirstChild( pParent ); 2367 } 2368 } 2369 pModel->Remove( pParent ); 2370 } 2371 2372 SvLBoxTab* SvTreeListBox::GetFirstTab( sal_uInt16 nFlagMask, sal_uInt16& rPos ) 2373 { 2374 sal_uInt16 nTabCount = aTabs.Count(); 2375 for( sal_uInt16 nPos = 0; nPos < nTabCount; nPos++ ) 2376 { 2377 SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nPos ); 2378 if( (pTab->nFlags & nFlagMask) ) 2379 { 2380 rPos = nPos; 2381 return pTab; 2382 } 2383 } 2384 rPos = 0xffff; 2385 return 0; 2386 } 2387 2388 SvLBoxTab* SvTreeListBox::GetLastTab( sal_uInt16 nFlagMask, sal_uInt16& rTabPos ) 2389 { 2390 short nTabCount = (short)aTabs.Count(); 2391 if( nTabCount ) 2392 { 2393 for( short nPos = nTabCount-1; nPos >= 0; nPos-- ) 2394 { 2395 SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( (sal_uInt16)nPos ); 2396 if( (pTab->nFlags & nFlagMask) ) 2397 { 2398 rTabPos = (sal_uInt16)nPos; 2399 return pTab; 2400 } 2401 } 2402 } 2403 rTabPos = 0xffff; 2404 return 0; 2405 } 2406 2407 void SvTreeListBox::SetAddMode( sal_Bool bAdd ) 2408 { 2409 pImp->SetAddMode( bAdd ); 2410 } 2411 2412 sal_Bool SvTreeListBox::IsAddMode() const 2413 { 2414 return pImp->IsAddMode(); 2415 } 2416 2417 void SvTreeListBox::RequestHelp( const HelpEvent& rHEvt ) 2418 { 2419 if( !pImp->RequestHelp( rHEvt ) ) 2420 SvLBox::RequestHelp( rHEvt ); 2421 } 2422 2423 void SvTreeListBox::CursorMoved( SvLBoxEntry* ) 2424 { 2425 } 2426 2427 IMPL_LINK( SvTreeListBox, DefaultCompare, SvSortData*, pData ) 2428 { 2429 SvLBoxEntry* pLeft = (SvLBoxEntry*)(pData->pLeft ); 2430 SvLBoxEntry* pRight = (SvLBoxEntry*)(pData->pRight ); 2431 String aLeft( ((SvLBoxString*)(pLeft->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText()); 2432 String aRight( ((SvLBoxString*)(pRight->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText()); 2433 // #102891# ---------------- 2434 pImp->UpdateIntlWrapper(); 2435 return pImp->pIntlWrapper->getCaseCollator()->compareString( aLeft, aRight ); 2436 } 2437 2438 void SvTreeListBox::ModelNotification( sal_uInt16 nActionId, SvListEntry* pEntry1, 2439 SvListEntry* pEntry2, sal_uLong nPos ) 2440 { 2441 if( nActionId == LISTACTION_CLEARING ) 2442 CancelTextEditing(); 2443 2444 SvLBox::ModelNotification( nActionId, pEntry1, pEntry2, nPos ); 2445 switch( nActionId ) 2446 { 2447 case LISTACTION_INSERTED: 2448 { 2449 SvLBoxEntry* pEntry( dynamic_cast< SvLBoxEntry* >( pEntry1 ) ); 2450 ENSURE_OR_BREAK( pEntry, "SvTreeListBox::ModelNotification: invalid entry!" ); 2451 SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) ); 2452 if ( !pBmpItem ) 2453 break; 2454 const Image& rBitmap1( pBmpItem->GetBitmap1() ); 2455 const Image& rBitmap2( pBmpItem->GetBitmap2() ); 2456 short nMaxWidth = short( Max( rBitmap1.GetSizePixel().Width(), rBitmap2.GetSizePixel().Width() ) ); 2457 nMaxWidth = pImp->UpdateContextBmpWidthVector( pEntry, nMaxWidth ); 2458 if( nMaxWidth > nContextBmpWidthMax ) 2459 { 2460 nContextBmpWidthMax = nMaxWidth; 2461 SetTabs(); 2462 } 2463 } 2464 break; 2465 2466 case LISTACTION_RESORTING: 2467 SetUpdateMode( sal_False ); 2468 break; 2469 2470 case LISTACTION_RESORTED: 2471 // nach Sortierung den ersten Eintrag anzeigen, dabei die 2472 // Selektion erhalten. 2473 MakeVisible( (SvLBoxEntry*)pModel->First(), sal_True ); 2474 SetUpdateMode( sal_True ); 2475 break; 2476 2477 case LISTACTION_CLEARED: 2478 if( IsUpdateMode() ) 2479 Update(); 2480 break; 2481 } 2482 } 2483 2484 // bei Aenderungen SetTabs beruecksichtigen 2485 long SvTreeListBox::GetTextOffset() const 2486 { 2487 DBG_CHKTHIS(SvTreeListBox,0); 2488 const WinBits nWindowStyle = GetStyle(); 2489 sal_Bool bHasButtons = (nWindowStyle & WB_HASBUTTONS)!=0; 2490 sal_Bool bHasButtonsAtRoot = (nWindowStyle & (WB_HASLINESATROOT | 2491 WB_HASBUTTONSATROOT))!=0; 2492 long nStartPos = TAB_STARTPOS; 2493 long nNodeWidthPixel = GetExpandedNodeBmp().GetSizePixel().Width(); 2494 2495 long nCheckWidth = 0; 2496 if( nTreeFlags & TREEFLAG_CHKBTN ) 2497 nCheckWidth = pCheckButtonData->aBmps[0].GetSizePixel().Width(); 2498 long nCheckWidthDIV2 = nCheckWidth / 2; 2499 2500 long nContextWidth = nContextBmpWidthMax; 2501 long nContextWidthDIV2 = nContextWidth / 2; 2502 2503 int nCase = NO_BUTTONS; 2504 if( !(nTreeFlags & TREEFLAG_CHKBTN) ) 2505 { 2506 if( bHasButtons ) 2507 nCase = NODE_BUTTONS; 2508 } 2509 else 2510 { 2511 if( bHasButtons ) 2512 nCase = NODE_AND_CHECK_BUTTONS; 2513 else 2514 nCase = CHECK_BUTTONS; 2515 } 2516 2517 switch( nCase ) 2518 { 2519 case NO_BUTTONS : 2520 nStartPos += nContextWidthDIV2; // wg. Zentrierung 2521 nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp 2522 if( nContextBmpWidthMax ) 2523 nStartPos += 5; // Abstand Context-Bmp - Text 2524 break; 2525 2526 case NODE_BUTTONS : 2527 if( bHasButtonsAtRoot ) 2528 nStartPos += ( nIndent + (nNodeWidthPixel/2) ); 2529 else 2530 nStartPos += nContextWidthDIV2; 2531 nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp 2532 if( nContextBmpWidthMax ) 2533 nStartPos += 5; // Abstand Context-Bmp - Text 2534 break; 2535 2536 case NODE_AND_CHECK_BUTTONS : 2537 if( bHasButtonsAtRoot ) 2538 nStartPos += ( nIndent + nNodeWidthPixel ); 2539 else 2540 nStartPos += nCheckWidthDIV2; 2541 nStartPos += nCheckWidthDIV2; // rechter Rand des CheckButtons 2542 nStartPos += 3; // Abstand CheckButton Context-Bmp 2543 nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp 2544 nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp 2545 // Abstand setzen nur wenn Bitmaps da 2546 if( nContextBmpWidthMax ) 2547 nStartPos += 5; // Abstand Context-Bmp - Text 2548 break; 2549 2550 case CHECK_BUTTONS : 2551 nStartPos += nCheckWidthDIV2; 2552 nStartPos += nCheckWidthDIV2; // rechter Rand CheckButton 2553 nStartPos += 3; // Abstand CheckButton Context-Bmp 2554 nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp 2555 nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp 2556 if( nContextBmpWidthMax ) 2557 nStartPos += 5; // Abstand Context-Bmp - Text 2558 break; 2559 } 2560 return nStartPos; 2561 } 2562 2563 void SvTreeListBox::EndSelection() 2564 { 2565 pImp->EndSelection(); 2566 } 2567 2568 sal_Bool SvTreeListBox::IsNodeButton( const Point& rPos ) const 2569 { 2570 SvLBoxEntry* pEntry = GetEntry( rPos ); 2571 if( pEntry ) 2572 return pImp->IsNodeButton( rPos, pEntry ); 2573 return sal_False; 2574 } 2575 2576 void SvTreeListBox::RepaintScrollBars() const 2577 { 2578 ((SvTreeListBox*)this)->pImp->RepaintScrollBars(); 2579 } 2580 2581 ScrollBar *SvTreeListBox::GetVScroll() 2582 { 2583 return &((SvTreeListBox*)this)->pImp->aVerSBar; 2584 } 2585 2586 ScrollBar *SvTreeListBox::GetHScroll() 2587 { 2588 return &((SvTreeListBox*)this)->pImp->aHorSBar; 2589 } 2590 2591 void SvTreeListBox::EnableAsyncDrag( sal_Bool b ) 2592 { 2593 pImp->EnableAsyncDrag( b ); 2594 } 2595 2596 SvLBoxEntry* SvTreeListBox::GetFirstEntryInView() const 2597 { 2598 Point aPos; 2599 return GetEntry( aPos ); 2600 } 2601 2602 SvLBoxEntry* SvTreeListBox::GetNextEntryInView(SvLBoxEntry* pEntry ) const 2603 { 2604 SvLBoxEntry* pNext = (SvLBoxEntry*)NextVisible( pEntry ); 2605 if( pNext ) 2606 { 2607 Point aPos( GetEntryPosition(pNext) ); 2608 const Size& rSize = pImp->GetOutputSize(); 2609 if( aPos.Y() < 0 || aPos.Y() >= rSize.Height() ) 2610 return 0; 2611 } 2612 return pNext; 2613 } 2614 2615 void SvTreeListBox::ShowFocusRect( const SvLBoxEntry* pEntry ) 2616 { 2617 pImp->ShowFocusRect( pEntry ); 2618 } 2619 2620 void SvTreeListBox::SetTabBar( TabBar* pTabBar ) 2621 { 2622 pImp->SetTabBar( pTabBar ); 2623 } 2624 2625 void SvTreeListBox::DataChanged( const DataChangedEvent& rDCEvt ) 2626 { 2627 if( (rDCEvt.GetType()==DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) ) 2628 { 2629 nEntryHeight = 0; // _together_ with sal_True of 1. par (bFont) of InitSettings() a zero-height 2630 // forces complete recalc of heights! 2631 InitSettings( sal_True, sal_True, sal_True ); 2632 Invalidate(); 2633 } 2634 else 2635 Control::DataChanged( rDCEvt ); 2636 } 2637 2638 void SvTreeListBox::StateChanged( StateChangedType i_nStateChange ) 2639 { 2640 SvLBox::StateChanged( i_nStateChange ); 2641 if ( i_nStateChange == STATE_CHANGE_STYLE ) 2642 ImplInitStyle(); 2643 } 2644 2645 void SvTreeListBox::InitSettings(sal_Bool bFont,sal_Bool bForeground,sal_Bool bBackground) 2646 { 2647 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 2648 if( bFont ) 2649 { 2650 Font aFont; 2651 aFont = rStyleSettings.GetFieldFont(); 2652 aFont.SetColor( rStyleSettings.GetWindowTextColor() ); 2653 SetPointFont( aFont ); 2654 AdjustEntryHeight( aFont ); 2655 RecalcViewData(); 2656 } 2657 2658 if( bForeground || bFont ) 2659 { 2660 SetTextColor( rStyleSettings.GetFieldTextColor() ); 2661 SetTextFillColor(); 2662 } 2663 2664 if( bBackground ) 2665 SetBackground( rStyleSettings.GetFieldColor() ); 2666 2667 // always try to re-create default-SvLBoxButtonData 2668 if( pCheckButtonData && pCheckButtonData->HasDefaultImages() ) 2669 pCheckButtonData->SetDefaultImages( this ); 2670 } 2671 2672 sal_Bool SvTreeListBox::IsCellFocusEnabled() const 2673 { 2674 return pImp->IsCellFocusEnabled(); 2675 } 2676 2677 bool SvTreeListBox::SetCurrentTabPos( sal_uInt16 _nNewPos ) 2678 { 2679 return pImp->SetCurrentTabPos( _nNewPos ); 2680 } 2681 2682 sal_uInt16 SvTreeListBox::GetCurrentTabPos() const 2683 { 2684 return pImp->GetCurrentTabPos(); 2685 } 2686 2687 void SvTreeListBox::InitStartEntry() 2688 { 2689 if( !pImp->pStartEntry ) 2690 pImp->pStartEntry = GetModel()->First(); 2691 } 2692 2693 void SvTreeListBox::CancelPendingEdit() 2694 { 2695 if( pImp ) 2696 pImp->CancelPendingEdit(); 2697 } 2698 2699 PopupMenu* SvTreeListBox::CreateContextMenu( void ) 2700 { 2701 return NULL; 2702 } 2703 2704 void SvTreeListBox::ExcecuteContextMenuAction( sal_uInt16 ) 2705 { 2706 DBG_WARNING( "SvTreeListBox::ExcecuteContextMenuAction(): now there's happening nothing!" ); 2707 } 2708 2709 void SvTreeListBox::EnableContextMenuHandling( void ) 2710 { 2711 DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" ); 2712 2713 pImp->bContextMenuHandling = sal_True; 2714 } 2715 2716 void SvTreeListBox::EnableContextMenuHandling( sal_Bool b ) 2717 { 2718 DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" ); 2719 2720 pImp->bContextMenuHandling = b; 2721 } 2722 2723 sal_Bool SvTreeListBox::IsContextMenuHandlingEnabled( void ) const 2724 { 2725 DBG_ASSERT( pImp, "-SvTreeListBox::IsContextMenuHandlingEnabled(): No implementation!" ); 2726 2727 return pImp->bContextMenuHandling; 2728 } 2729 2730 void SvTreeListBox::EnableList( bool _bEnable ) 2731 { 2732 // call base class method 2733 Window::Enable( _bEnable != false ); 2734 // then paint immediately 2735 Paint( Rectangle( Point(), GetSizePixel() ) ); 2736 } 2737 2738 ::com::sun::star::uno::Reference< XAccessible > SvTreeListBox::CreateAccessible() 2739 { 2740 Window* pParent = GetAccessibleParentWindow(); 2741 DBG_ASSERT( pParent, "SvTreeListBox::CreateAccessible - accessible parent not found" ); 2742 2743 ::com::sun::star::uno::Reference< XAccessible > xAccessible; 2744 if ( pParent ) 2745 { 2746 ::com::sun::star::uno::Reference< XAccessible > xAccParent = pParent->GetAccessible(); 2747 if ( xAccParent.is() ) 2748 { 2749 // need to be done here to get the vclxwindow later on in the accessbile 2750 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xTemp(GetComponentInterface()); 2751 xAccessible = pImp->m_aFactoryAccess.getFactory().createAccessibleTreeListBox( *this, xAccParent ); 2752 } 2753 } 2754 return xAccessible; 2755 } 2756 2757 void SvTreeListBox::FillAccessibleEntryStateSet( SvLBoxEntry* pEntry, ::utl::AccessibleStateSetHelper& rStateSet ) const 2758 { 2759 DBG_ASSERT( pEntry, "SvTreeListBox::FillAccessibleEntryStateSet: invalid entry" ); 2760 2761 if ( pEntry->HasChildsOnDemand() || pEntry->HasChilds() ) 2762 { 2763 rStateSet.AddState( AccessibleStateType::EXPANDABLE ); 2764 if ( IsExpanded( pEntry ) ) 2765 rStateSet.AddState( (sal_Int16)AccessibleStateType::EXPANDED ); 2766 /* 2767 else 2768 { 2769 // MT: COLLAPSE == EXPANDABLE & !EXPANDED 2770 rStateSet.AddState( (sal_Int16)AccessibleStateType::COLLAPSE ); 2771 } 2772 */ 2773 } 2774 2775 if ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED ) 2776 rStateSet.AddState( AccessibleStateType::CHECKED ); 2777 if ( IsEntryVisible( pEntry ) ) 2778 rStateSet.AddState( AccessibleStateType::VISIBLE ); 2779 if ( IsSelected( pEntry ) ) 2780 rStateSet.AddState( AccessibleStateType::SELECTED ); 2781 if ( IsEnabled() ) 2782 { 2783 rStateSet.AddState( AccessibleStateType::ENABLED ); 2784 rStateSet.AddState( AccessibleStateType::FOCUSABLE ); 2785 rStateSet.AddState( AccessibleStateType::SELECTABLE ); 2786 SvViewDataEntry* pViewDataNewCur = 0; 2787 if( pEntry ) 2788 { 2789 pViewDataNewCur= GetViewDataEntry(pEntry); 2790 if(pViewDataNewCur->HasFocus()) 2791 rStateSet.AddState( AccessibleStateType::FOCUSED ); 2792 } 2793 } 2794 } 2795 2796 Rectangle SvTreeListBox::GetBoundingRect( SvLBoxEntry* pEntry ) 2797 { 2798 Point aPos = GetEntryPosition( pEntry ); 2799 Rectangle aRect = GetFocusRect( pEntry, aPos.Y() ); 2800 return aRect; 2801 } 2802 2803 void SvTreeListBox::EnableCellFocus() 2804 { 2805 pImp->EnableCellFocus(); 2806 } 2807 2808 void SvTreeListBox::CallImplEventListeners(sal_uLong nEvent, void* pData) 2809 { 2810 CallEventListeners(nEvent, pData); 2811 } 2812 2813 void SvTreeListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& rStateSet ) const 2814 { 2815 SvLBox::FillAccessibleStateSet( rStateSet ); 2816 } 2817 2818