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_TREEFOCUS, pEntry ); 911 912 } 913 914 void SvTreeListBox::LoseFocus() 915 { 916 DBG_CHKTHIS(SvTreeListBox,0); 917 //Solution:If there is no item in the tree,delete visual focus. 918 if( !SvLBox::First()) 919 { 920 Invalidate(); 921 } 922 pImp->LoseFocus(); 923 SvLBox::LoseFocus(); 924 } 925 926 void SvTreeListBox::ModelHasCleared() 927 { 928 DBG_CHKTHIS(SvTreeListBox,0); 929 pImp->pCursor = 0; //sonst Absturz beim Inplace-Editieren im GetFocus 930 delete pEdCtrl; 931 pEdCtrl = NULL; 932 pImp->Clear(); 933 nFocusWidth = -1; 934 935 nContextBmpWidthMax = 0; 936 SetDefaultExpandedEntryBmp( GetDefaultExpandedEntryBmp() ); 937 SetDefaultCollapsedEntryBmp( GetDefaultCollapsedEntryBmp() ); 938 939 if( !(nTreeFlags & TREEFLAG_FIXEDHEIGHT )) 940 nEntryHeight = 0; 941 AdjustEntryHeight( GetFont() ); 942 AdjustEntryHeight( GetDefaultExpandedEntryBmp() ); 943 AdjustEntryHeight( GetDefaultCollapsedEntryBmp() ); 944 945 SvLBox::ModelHasCleared(); 946 // if( IsUpdateMode() ) 947 // Invalidate(); 948 } 949 950 void SvTreeListBox::ShowTargetEmphasis( SvLBoxEntry* pEntry, sal_Bool /* bShow */ ) 951 { 952 DBG_CHKTHIS(SvTreeListBox,0); 953 pImp->PaintDDCursor( pEntry ); 954 } 955 956 void SvTreeListBox::ScrollOutputArea( short nDeltaEntries ) 957 { 958 DBG_CHKTHIS(SvTreeListBox,0); 959 if( !nDeltaEntries || !pImp->aVerSBar.IsVisible() ) 960 return; 961 962 long nThumb = pImp->aVerSBar.GetThumbPos(); 963 long nMax = pImp->aVerSBar.GetRange().Max(); 964 965 NotifyBeginScroll(); 966 if( nDeltaEntries < 0 ) 967 { 968 // das Fenster nach oben verschieben 969 nDeltaEntries *= -1; 970 long nVis = pImp->aVerSBar.GetVisibleSize(); 971 long nTemp = nThumb + nVis; 972 if( nDeltaEntries > (nMax - nTemp) ) 973 nDeltaEntries = (short)(nMax - nTemp); 974 pImp->PageDown( (sal_uInt16)nDeltaEntries ); 975 } 976 else 977 { 978 if( nDeltaEntries > nThumb ) 979 nDeltaEntries = (short)nThumb; 980 pImp->PageUp( (sal_uInt16)nDeltaEntries ); 981 } 982 pImp->SyncVerThumb(); 983 NotifyEndScroll(); 984 } 985 986 void SvTreeListBox::SetSelectionMode( SelectionMode eSelectMode ) 987 { 988 DBG_CHKTHIS(SvTreeListBox,0); 989 SvLBox::SetSelectionMode( eSelectMode ); 990 pImp->SetSelectionMode( eSelectMode ); 991 } 992 993 void SvTreeListBox::SetDragDropMode( DragDropMode nDDMode ) 994 { 995 DBG_CHKTHIS(SvTreeListBox,0); 996 SvLBox::SetDragDropMode( nDDMode ); 997 pImp->SetDragDropMode( nDDMode ); 998 } 999 1000 short SvTreeListBox::GetHeightOffset(const Image& rBmp, Size& aSizeLogic ) 1001 { 1002 DBG_CHKTHIS(SvTreeListBox,0); 1003 short nOffset = 0; 1004 aSizeLogic = rBmp.GetSizePixel(); 1005 if( GetEntryHeight() > aSizeLogic.Height() ) 1006 nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2; 1007 return nOffset; 1008 } 1009 1010 short SvTreeListBox::GetHeightOffset(const Font& /* rFont */, Size& aSizeLogic ) 1011 { 1012 DBG_CHKTHIS(SvTreeListBox,0); 1013 short nOffset = 0; 1014 aSizeLogic = Size(GetTextWidth('X'), GetTextHeight()); 1015 if( GetEntryHeight() > aSizeLogic.Height() ) 1016 nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2; 1017 return nOffset; 1018 } 1019 1020 void SvTreeListBox::SetEntryHeight( SvLBoxEntry* pEntry ) 1021 { 1022 DBG_CHKTHIS(SvTreeListBox,0); 1023 short nHeight, nHeightMax=0; 1024 sal_uInt16 nCount = pEntry->ItemCount(); 1025 sal_uInt16 nCur = 0; 1026 SvViewDataEntry* pViewData = GetViewDataEntry( pEntry ); 1027 while( nCur < nCount ) 1028 { 1029 SvLBoxItem* pItem = pEntry->GetItem( nCur ); 1030 nHeight = (short)(pItem->GetSize( pViewData, nCur ).Height()); 1031 if( nHeight > nHeightMax ) 1032 nHeightMax = nHeight; 1033 nCur++; 1034 } 1035 1036 if( nHeightMax > nEntryHeight ) 1037 { 1038 nEntryHeight = nHeightMax; 1039 SvLBox::SetFont( GetFont() ); 1040 pImp->SetEntryHeight( nHeightMax ); 1041 } 1042 } 1043 1044 void SvTreeListBox::SetEntryHeight( short nHeight, sal_Bool bAlways ) 1045 { 1046 DBG_CHKTHIS(SvTreeListBox,0); 1047 1048 if( bAlways || nHeight > nEntryHeight ) 1049 { 1050 nEntryHeight = nHeight; 1051 if( nEntryHeight ) 1052 nTreeFlags |= TREEFLAG_FIXEDHEIGHT; 1053 else 1054 nTreeFlags &= ~TREEFLAG_FIXEDHEIGHT; 1055 SvLBox::SetFont( GetFont() ); 1056 pImp->SetEntryHeight( nHeight ); 1057 } 1058 } 1059 1060 1061 void SvTreeListBox::AdjustEntryHeight( const Image& rBmp ) 1062 { 1063 DBG_CHKTHIS(SvTreeListBox,0); 1064 Size aSize; 1065 GetHeightOffset( rBmp, aSize ); 1066 if( aSize.Height() > nEntryHeight ) 1067 { 1068 nEntryHeight = (short)aSize.Height() + nEntryHeightOffs; 1069 pImp->SetEntryHeight( nEntryHeight ); 1070 } 1071 } 1072 1073 void SvTreeListBox::AdjustEntryHeight( const Font& rFont ) 1074 { 1075 DBG_CHKTHIS(SvTreeListBox,0); 1076 Size aSize; 1077 GetHeightOffset( rFont, aSize ); 1078 if( aSize.Height() > nEntryHeight ) 1079 { 1080 nEntryHeight = (short)aSize.Height() + nEntryHeightOffs; 1081 pImp->SetEntryHeight( nEntryHeight ); 1082 } 1083 } 1084 1085 sal_Bool SvTreeListBox::Expand( SvLBoxEntry* pParent ) 1086 { 1087 DBG_CHKTHIS(SvTreeListBox,0); 1088 pHdlEntry = pParent; 1089 sal_Bool bExpanded = sal_False; 1090 sal_uInt16 nFlags; 1091 1092 if( pParent->HasChildsOnDemand() ) 1093 RequestingChilds( pParent ); 1094 if( pParent->HasChilds() ) 1095 { 1096 nImpFlags |= SVLBOX_IS_EXPANDING; 1097 if( ExpandingHdl() ) 1098 { 1099 bExpanded = sal_True; 1100 SvListView::Expand( pParent ); 1101 pImp->EntryExpanded( pParent ); 1102 pHdlEntry = pParent; 1103 ExpandedHdl(); 1104 } 1105 nFlags = pParent->GetFlags(); 1106 nFlags &= ~SV_ENTRYFLAG_NO_NODEBMP; 1107 nFlags |= SV_ENTRYFLAG_HAD_CHILDREN; 1108 pParent->SetFlags( nFlags ); 1109 } 1110 else 1111 { 1112 nFlags = pParent->GetFlags(); 1113 nFlags |= SV_ENTRYFLAG_NO_NODEBMP; 1114 pParent->SetFlags( nFlags ); 1115 GetModel()->InvalidateEntry( pParent ); // neu zeichnen 1116 } 1117 1118 // --> OD 2009-04-01 #i92103# 1119 if ( bExpanded ) 1120 { 1121 pImp->CallEventListeners( VCLEVENT_ITEM_EXPANDED, pParent ); 1122 } 1123 // <-- 1124 1125 return bExpanded; 1126 } 1127 1128 sal_Bool SvTreeListBox::Collapse( SvLBoxEntry* pParent ) 1129 { 1130 DBG_CHKTHIS(SvTreeListBox,0); 1131 nImpFlags &= ~SVLBOX_IS_EXPANDING; 1132 pHdlEntry = pParent; 1133 sal_Bool bCollapsed = sal_False; 1134 1135 if( ExpandingHdl() ) 1136 { 1137 bCollapsed = sal_True; 1138 pImp->CollapsingEntry( pParent ); 1139 SvListView::Collapse( pParent ); 1140 pImp->EntryCollapsed( pParent ); 1141 pHdlEntry = pParent; 1142 ExpandedHdl(); 1143 } 1144 1145 // --> OD 2009-04-01 #i92103# 1146 if ( bCollapsed ) 1147 { 1148 pImp->CallEventListeners( VCLEVENT_ITEM_COLLAPSED, pParent ); 1149 } 1150 // <-- 1151 1152 return bCollapsed; 1153 } 1154 1155 sal_Bool SvTreeListBox::Select( SvLBoxEntry* pEntry, sal_Bool bSelect ) 1156 { 1157 DBG_CHKTHIS(SvTreeListBox,0); 1158 DBG_ASSERT(pEntry,"Select: Null-Ptr"); 1159 sal_Bool bRetVal = SvListView::Select( pEntry, bSelect ); 1160 DBG_ASSERT(IsSelected(pEntry)==bSelect,"Select failed"); 1161 if( bRetVal ) 1162 { 1163 pImp->EntrySelected( pEntry, bSelect ); 1164 pHdlEntry = pEntry; 1165 if( bSelect ) 1166 { 1167 SelectHdl(); 1168 // pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry ); 1169 CallEventListeners( VCLEVENT_LISTBOX_TREESELECT, pEntry); 1170 } 1171 else 1172 DeselectHdl(); 1173 } 1174 return bRetVal; 1175 } 1176 1177 sal_uLong SvTreeListBox::SelectChilds( SvLBoxEntry* pParent, sal_Bool bSelect ) 1178 { 1179 DBG_CHKTHIS(SvTreeListBox,0); 1180 pImp->DestroyAnchor(); 1181 sal_uLong nRet = 0; 1182 if( !pParent->HasChilds() ) 1183 return 0; 1184 sal_uInt16 nRefDepth = pModel->GetDepth( pParent ); 1185 SvLBoxEntry* pChild = FirstChild( pParent ); 1186 do { 1187 nRet++; 1188 Select( pChild, bSelect ); 1189 pChild = Next( pChild ); 1190 } while( pChild && pModel->GetDepth( pChild ) > nRefDepth ); 1191 return nRet; 1192 } 1193 1194 void SvTreeListBox::SelectAll( sal_Bool bSelect, sal_Bool ) 1195 { 1196 DBG_CHKTHIS(SvTreeListBox,0); 1197 pImp->SelAllDestrAnch( 1198 bSelect, 1199 sal_True, // Anker loeschen, 1200 sal_True ); // auch bei SINGLE_SELECTION den Cursor deselektieren 1201 } 1202 1203 void SvTreeListBox::ModelHasInsertedTree( SvListEntry* pEntry ) 1204 { 1205 DBG_CHKTHIS(SvTreeListBox,0); 1206 sal_uInt16 nRefDepth = pModel->GetDepth( (SvLBoxEntry*)pEntry ); 1207 SvLBoxEntry* pTmp = (SvLBoxEntry*)pEntry; 1208 do 1209 { 1210 ImpEntryInserted( pTmp ); 1211 pTmp = Next( pTmp ); 1212 } while( pTmp && nRefDepth < pModel->GetDepth( pTmp ) ); 1213 pImp->TreeInserted( (SvLBoxEntry*)pEntry ); 1214 } 1215 1216 void SvTreeListBox::ModelHasInserted( SvListEntry* pEntry ) 1217 { 1218 DBG_CHKTHIS(SvTreeListBox,0); 1219 ImpEntryInserted( (SvLBoxEntry*)pEntry ); 1220 pImp->EntryInserted( (SvLBoxEntry*)pEntry ); 1221 } 1222 1223 void SvTreeListBox::ModelIsMoving(SvListEntry* pSource, 1224 SvListEntry* /* pTargetParent */, 1225 sal_uLong /* nChildPos */ ) 1226 { 1227 DBG_CHKTHIS(SvTreeListBox,0); 1228 pImp->MovingEntry( (SvLBoxEntry*)pSource ); 1229 } 1230 1231 void SvTreeListBox::ModelHasMoved( SvListEntry* pSource ) 1232 { 1233 DBG_CHKTHIS(SvTreeListBox,0); 1234 pImp->EntryMoved( (SvLBoxEntry*)pSource ); 1235 } 1236 1237 void SvTreeListBox::ModelIsRemoving( SvListEntry* pEntry ) 1238 { 1239 DBG_CHKTHIS(SvTreeListBox,0); 1240 if(pEdEntry == pEntry) 1241 pEdEntry = NULL; 1242 1243 pImp->RemovingEntry( (SvLBoxEntry*)pEntry ); 1244 NotifyRemoving( (SvLBoxEntry*)pEntry ); 1245 } 1246 1247 void SvTreeListBox::ModelHasRemoved( SvListEntry* pEntry ) 1248 { 1249 DBG_CHKTHIS(SvTreeListBox,0); 1250 if ( pEntry == pHdlEntry) 1251 pHdlEntry = NULL; 1252 pImp->EntryRemoved(); 1253 } 1254 1255 void SvTreeListBox::SetCollapsedNodeBmp( const Image& rBmp, BmpColorMode _eMode ) 1256 { 1257 DBG_CHKTHIS(SvTreeListBox,0); 1258 AdjustEntryHeight( rBmp ); 1259 pImp->SetCollapsedNodeBmp( rBmp, _eMode ); 1260 } 1261 1262 void SvTreeListBox::SetExpandedNodeBmp( const Image& rBmp, BmpColorMode _eMode ) 1263 { 1264 DBG_CHKTHIS(SvTreeListBox,0); 1265 AdjustEntryHeight( rBmp ); 1266 pImp->SetExpandedNodeBmp( rBmp, _eMode ); 1267 } 1268 1269 1270 void SvTreeListBox::SetFont( const Font& rFont ) 1271 { 1272 DBG_CHKTHIS(SvTreeListBox,0); 1273 Font aTempFont( rFont ); 1274 aTempFont.SetTransparent( sal_True ); 1275 Control::SetFont( aTempFont ); 1276 AdjustEntryHeight( aTempFont ); 1277 // immer Invalidieren, sonst fallen wir 1278 // bei SetEntryHeight auf die Nase 1279 RecalcViewData(); 1280 } 1281 1282 1283 void SvTreeListBox::Paint( const Rectangle& rRect ) 1284 { 1285 DBG_CHKTHIS(SvTreeListBox,0); 1286 SvLBox::Paint( rRect ); 1287 if( nTreeFlags & TREEFLAG_RECALCTABS ) 1288 SetTabs(); 1289 pImp->Paint( rRect ); 1290 //Solution:Add visual focus draw 1291 if( !SvLBox::First() ) 1292 { 1293 if( HasFocus() ) 1294 { 1295 long tempHeight = GetTextHeight(); 1296 Rectangle tempRect( 1297 Point(0,0),Size(GetSizePixel().Width(),tempHeight) 1298 ); 1299 ShowFocus(tempRect); 1300 } 1301 1302 else{ 1303 HideFocus(); 1304 } 1305 } 1306 } 1307 1308 void SvTreeListBox::MouseButtonDown( const MouseEvent& rMEvt ) 1309 { 1310 DBG_CHKTHIS(SvTreeListBox,0); 1311 pImp->MouseButtonDown( rMEvt ); 1312 } 1313 1314 void SvTreeListBox::MouseButtonUp( const MouseEvent& rMEvt ) 1315 { 1316 DBG_CHKTHIS(SvTreeListBox,0); 1317 pImp->MouseButtonUp( rMEvt ); 1318 } 1319 1320 void SvTreeListBox::MouseMove( const MouseEvent& rMEvt ) 1321 { 1322 DBG_CHKTHIS(SvTreeListBox,0); 1323 pImp->MouseMove( rMEvt ); 1324 } 1325 1326 1327 void SvTreeListBox::SetUpdateMode( sal_Bool bUpdate ) 1328 { 1329 DBG_CHKTHIS(SvTreeListBox,0); 1330 pImp->SetUpdateMode( bUpdate ); 1331 } 1332 1333 void SvTreeListBox::SetUpdateModeFast( sal_Bool bUpdate ) 1334 { 1335 DBG_CHKTHIS(SvTreeListBox,0); 1336 pImp->SetUpdateModeFast( bUpdate ); 1337 } 1338 1339 void SvTreeListBox::SetSpaceBetweenEntries( short nOffsLogic ) 1340 { 1341 DBG_CHKTHIS(SvTreeListBox,0); 1342 if( nOffsLogic != nEntryHeightOffs ) 1343 { 1344 nEntryHeight = nEntryHeight - nEntryHeightOffs; 1345 nEntryHeightOffs = (short)nOffsLogic; 1346 nEntryHeight = nEntryHeight + nOffsLogic; 1347 AdjustEntryHeight( GetFont() ); 1348 RecalcViewData(); 1349 pImp->SetEntryHeight( nEntryHeight ); 1350 } 1351 } 1352 1353 void SvTreeListBox::SetCursor( SvLBoxEntry* pEntry, sal_Bool bForceNoSelect ) 1354 { 1355 DBG_CHKTHIS(SvTreeListBox,0); 1356 pImp->SetCursor(pEntry, bForceNoSelect); 1357 } 1358 1359 void SvTreeListBox::SetCurEntry( SvLBoxEntry* pEntry ) 1360 { 1361 DBG_CHKTHIS(SvTreeListBox,0); 1362 pImp->SetCurEntry( pEntry ); 1363 } 1364 1365 Image SvTreeListBox::GetCollapsedNodeBmp( BmpColorMode _eMode ) const 1366 { 1367 return pImp->GetCollapsedNodeBmp( _eMode ); 1368 } 1369 1370 Image SvTreeListBox::GetExpandedNodeBmp( BmpColorMode _eMode ) const 1371 { 1372 return pImp->GetExpandedNodeBmp( _eMode ); 1373 } 1374 1375 Point SvTreeListBox::GetEntryPosition( SvLBoxEntry* pEntry ) const 1376 { 1377 return pImp->GetEntryPosition( pEntry ); 1378 } 1379 1380 void SvTreeListBox::ShowEntry( SvLBoxEntry* pEntry ) 1381 { 1382 MakeVisible( pEntry ); 1383 } 1384 1385 void SvTreeListBox::MakeVisible( SvLBoxEntry* pEntry ) 1386 { 1387 pImp->MakeVisible(pEntry); 1388 } 1389 1390 void SvTreeListBox::MakeVisible( SvLBoxEntry* pEntry, sal_Bool bMoveToTop ) 1391 { 1392 pImp->MakeVisible( pEntry, bMoveToTop ); 1393 } 1394 1395 void SvTreeListBox::ModelHasEntryInvalidated( SvListEntry* pEntry ) 1396 { 1397 DBG_CHKTHIS(SvTreeListBox,0); 1398 // die einzelnen Items des Entries reinitialisieren 1399 SvLBox::ModelHasEntryInvalidated( pEntry ); 1400 // repainten 1401 pImp->InvalidateEntry( (SvLBoxEntry*)pEntry ); 1402 } 1403 1404 void SvTreeListBox::EditItemText( SvLBoxEntry* pEntry, SvLBoxString* pItem, 1405 const Selection& rSelection ) 1406 { 1407 DBG_CHKTHIS(SvTreeListBox,0); 1408 DBG_ASSERT(pEntry&&pItem,"EditItemText: Bad params"); 1409 if( IsSelected( pEntry )) 1410 { 1411 pImp->ShowCursor( sal_False ); 1412 SvListView::Select( pEntry, sal_False ); 1413 PaintEntry( pEntry ); 1414 SvListView::Select( pEntry, sal_True ); 1415 pImp->ShowCursor( sal_True ); 1416 } 1417 pEdEntry = pEntry; 1418 pEdItem = pItem; 1419 SvLBoxTab* pTab = GetTab( pEntry, pItem ); 1420 DBG_ASSERT(pTab,"EditItemText:Tab not found"); 1421 1422 Size aItemSize( pItem->GetSize(this, pEntry) ); 1423 Point aPos = GetEntryPosition( pEntry ); 1424 aPos.Y() += ( nEntryHeight - aItemSize.Height() ) / 2; 1425 aPos.X() = GetTabPos( pEntry, pTab ); 1426 long nOutputWidth = pImp->GetOutputSize().Width(); 1427 Size aSize( nOutputWidth - aPos.X(), aItemSize.Height() ); 1428 sal_uInt16 nPos = aTabs.GetPos( pTab ); 1429 if( nPos+1 < aTabs.Count() ) 1430 { 1431 SvLBoxTab* pRightTab = (SvLBoxTab*)aTabs.GetObject( nPos + 1 ); 1432 long nRight = GetTabPos( pEntry, pRightTab ); 1433 if( nRight <= nOutputWidth ) 1434 aSize.Width() = nRight - aPos.X(); 1435 } 1436 Point aOrigin( GetMapMode().GetOrigin() ); 1437 aPos += aOrigin; // in Win-Koord umrechnen 1438 aSize.Width() -= aOrigin.X(); 1439 Rectangle aRect( aPos, aSize ); 1440 #ifdef OS2 1441 // Platz lassen fuer WB_BORDER 1442 aRect.Left() -= 2; 1443 aRect.Top() -= 3; 1444 aRect.Bottom() += 3; 1445 #endif 1446 EditText( pItem->GetText(), aRect, rSelection ); 1447 } 1448 1449 void SvTreeListBox::CancelEditing() 1450 { 1451 DBG_CHKTHIS(SvTreeListBox,0); 1452 SvLBox::CancelTextEditing(); 1453 } 1454 1455 void SvTreeListBox::EditEntry( SvLBoxEntry* pEntry ) 1456 { 1457 pImp->aEditClickPos = Point( -1, -1 ); 1458 ImplEditEntry( pEntry ); 1459 } 1460 1461 void SvTreeListBox::ImplEditEntry( SvLBoxEntry* pEntry ) 1462 { 1463 DBG_CHKTHIS(SvTreeListBox,0); 1464 if( IsEditingActive() ) 1465 EndEditing(); 1466 if( !pEntry ) 1467 pEntry = GetCurEntry(); 1468 if( pEntry ) 1469 { 1470 long nClickX = pImp->aEditClickPos.X(); 1471 bool bIsMouseTriggered = nClickX >= 0; 1472 1473 SvLBoxString* pItem = NULL; 1474 sal_uInt16 nCount = pEntry->ItemCount(); 1475 for( sal_uInt16 i = 0 ; i < nCount ; i++ ) 1476 { 1477 SvLBoxItem* pTmpItem = pEntry->GetItem( i ); 1478 if( pTmpItem->IsA() != SV_ITEM_ID_LBOXSTRING ) 1479 continue; 1480 1481 SvLBoxTab* pTab = GetTab( pEntry, pTmpItem ); 1482 long nTabPos = pTab->GetPos(); 1483 long nNextTabPos = -1; 1484 if( i < nCount - 1 ) 1485 { 1486 SvLBoxItem* pNextItem = pEntry->GetItem( i + 1 ); 1487 SvLBoxTab* pNextTab = GetTab( pEntry, pNextItem ); 1488 nNextTabPos = pNextTab->GetPos(); 1489 } 1490 1491 if( pTab && pTab->IsEditable() ) 1492 { 1493 if( !bIsMouseTriggered || (nClickX > nTabPos && (nNextTabPos == -1 || nClickX < nNextTabPos ) ) ) 1494 { 1495 pItem = static_cast<SvLBoxString*>( pTmpItem ); 1496 break; 1497 } 1498 } 1499 } 1500 1501 Selection aSel( SELECTION_MIN, SELECTION_MAX ); 1502 if( pItem && EditingEntry( pEntry, aSel ) ) 1503 { 1504 SelectAll( sal_False ); 1505 MakeVisible( pEntry ); 1506 EditItemText( pEntry, pItem, aSel ); 1507 } 1508 } 1509 } 1510 1511 sal_Bool SvTreeListBox::AreChildrenTransient() const 1512 { 1513 return pImp->AreChildrenTransient(); 1514 } 1515 1516 void SvTreeListBox::SetChildrenNotTransient() 1517 { 1518 pImp->SetChildrenNotTransient(); 1519 } 1520 1521 void SvTreeListBox::EditedText( const XubString& rStr ) 1522 1523 { 1524 DBG_CHKTHIS(SvTreeListBox,0); 1525 if(pEdEntry) // we have to check if this entry is null that means that it is removed while editing 1526 { 1527 Point aPos = GetEntryPosition( pEdEntry ); 1528 if( EditedEntry( pEdEntry, rStr ) ) 1529 { 1530 ((SvLBoxString*)pEdItem)->SetText( pEdEntry, rStr ); 1531 pModel->InvalidateEntry( pEdEntry ); 1532 } 1533 //if( GetSelectionMode() == SINGLE_SELECTION ) 1534 //{ 1535 if( GetSelectionCount() == 0 ) 1536 Select( pEdEntry ); 1537 if( GetSelectionMode() == MULTIPLE_SELECTION && !GetCurEntry() ) 1538 SetCurEntry( pEdEntry ); 1539 //} 1540 } 1541 } 1542 1543 void SvTreeListBox::EditingRequest( SvLBoxEntry* pEntry, SvLBoxItem* pItem, 1544 const Point& ) 1545 { 1546 DBG_CHKTHIS(SvTreeListBox,0); 1547 if( IsEditingActive() ) 1548 EndEditing(); 1549 if( pItem->IsA() == SV_ITEM_ID_LBOXSTRING ) 1550 { 1551 Selection aSel( SELECTION_MIN, SELECTION_MAX ); 1552 if( EditingEntry( pEntry, aSel ) ) 1553 { 1554 SelectAll( sal_False ); 1555 EditItemText( pEntry, (SvLBoxString*)pItem, aSel ); 1556 } 1557 } 1558 } 1559 1560 1561 1562 SvLBoxEntry* SvTreeListBox::GetDropTarget( const Point& rPos ) 1563 { 1564 DBG_CHKTHIS(SvTreeListBox,0); 1565 // Scrollen 1566 if( rPos.Y() < 12 ) 1567 { 1568 SvLBox::ImplShowTargetEmphasis( SvLBox::pTargetEntry, sal_False ); 1569 ScrollOutputArea( +1 ); 1570 } 1571 else 1572 { 1573 Size aSize( pImp->GetOutputSize() ); 1574 if( rPos.Y() > aSize.Height() - 12 ) 1575 { 1576 SvLBox::ImplShowTargetEmphasis( SvLBox::pTargetEntry, sal_False ); 1577 ScrollOutputArea( -1 ); 1578 } 1579 } 1580 1581 SvLBoxEntry* pTarget = pImp->GetEntry( rPos ); 1582 // bei Droppen in leere Flaeche -> den letzten Eintrag nehmen 1583 if( !pTarget ) 1584 return (SvLBoxEntry*)LastVisible(); 1585 else if( (GetDragDropMode() & SV_DRAGDROP_ENABLE_TOP) && 1586 pTarget == First() && rPos.Y() < 6 ) 1587 return 0; 1588 1589 return pTarget; 1590 } 1591 1592 1593 SvLBoxEntry* SvTreeListBox::GetEntry( const Point& rPos, sal_Bool bHit ) const 1594 { 1595 DBG_CHKTHIS(SvTreeListBox,0); 1596 SvLBoxEntry* pEntry = pImp->GetEntry( rPos ); 1597 if( pEntry && bHit ) 1598 { 1599 long nLine = pImp->GetEntryLine( pEntry ); 1600 if( !(pImp->EntryReallyHit( pEntry, rPos, nLine)) ) 1601 return 0; 1602 } 1603 return pEntry; 1604 } 1605 1606 SvLBoxEntry* SvTreeListBox::GetCurEntry() const 1607 { 1608 DBG_CHKTHIS(SvTreeListBox,0); 1609 return pImp->GetCurEntry(); 1610 } 1611 1612 void SvTreeListBox::ImplInitStyle() 1613 { 1614 DBG_CHKTHIS(SvTreeListBox,0); 1615 1616 const WinBits nWindowStyle = GetStyle(); 1617 1618 nTreeFlags |= TREEFLAG_RECALCTABS; 1619 if( nWindowStyle & WB_SORT ) 1620 { 1621 GetModel()->SetSortMode( SortAscending ); 1622 GetModel()->SetCompareHdl( LINK(this,SvTreeListBox,DefaultCompare)); 1623 } 1624 else 1625 { 1626 GetModel()->SetSortMode( SortNone ); 1627 GetModel()->SetCompareHdl( Link() ); 1628 } 1629 pImp->SetStyle( nWindowStyle ); 1630 pImp->Resize(); 1631 Invalidate(); 1632 } 1633 1634 void SvTreeListBox::PaintEntry( SvLBoxEntry* pEntry ) 1635 { 1636 DBG_CHKTHIS(SvTreeListBox,0); 1637 DBG_ASSERT(pEntry,"PaintEntry:No Entry"); 1638 if( pEntry ) 1639 pImp->PaintEntry( pEntry ); 1640 } 1641 1642 void SvTreeListBox::InvalidateEntry( SvLBoxEntry* pEntry ) 1643 { 1644 DBG_CHKTHIS(SvTreeListBox,0); 1645 DBG_ASSERT(pEntry,"InvalidateEntry:No Entry"); 1646 if( pEntry ) 1647 { 1648 GetModel()->InvalidateEntry( pEntry ); 1649 // pImp->InvalidateEntry( pEntry ); 1650 } 1651 } 1652 1653 1654 long SvTreeListBox::PaintEntry(SvLBoxEntry* pEntry,long nLine,sal_uInt16 nTabFlags) 1655 { 1656 return PaintEntry1(pEntry,nLine,nTabFlags); 1657 } 1658 1659 #define SV_TAB_BORDER 8 1660 1661 long SvTreeListBox::PaintEntry1(SvLBoxEntry* pEntry,long nLine,sal_uInt16 nTabFlags, 1662 sal_Bool bHasClipRegion ) 1663 { 1664 DBG_CHKTHIS(SvTreeListBox,0); 1665 1666 Rectangle aRect; // multi purpose 1667 1668 sal_Bool bHorSBar = pImp->HasHorScrollBar(); 1669 PreparePaint( pEntry ); 1670 1671 // #97680# ------------------ 1672 pImp->UpdateContextBmpWidthMax( pEntry ); 1673 1674 if( nTreeFlags & TREEFLAG_RECALCTABS ) 1675 SetTabs(); 1676 1677 short nTempEntryHeight = GetEntryHeight(); 1678 long nWidth = pImp->GetOutputSize().Width(); 1679 1680 // wurde innerhalb des PreparePaints die horizontale ScrollBar 1681 // angeschaltet? Wenn ja, muss die ClipRegion neu gesetzt werden 1682 if( !bHorSBar && pImp->HasHorScrollBar() ) 1683 SetClipRegion( Region(pImp->GetClipRegionRect()) ); 1684 1685 Point aEntryPos( GetMapMode().GetOrigin() ); 1686 aEntryPos.X() *= -1; // Umrechnung Dokumentkoord. 1687 long nMaxRight = nWidth + aEntryPos.X() - 1; 1688 1689 Color aBackupTextColor( GetTextColor() ); 1690 Font aBackupFont( GetFont() ); 1691 Color aBackupColor = GetFillColor(); 1692 1693 bool bCurFontIsSel = false; 1694 sal_Bool bInUse = pEntry->HasInUseEmphasis(); 1695 // wenn eine ClipRegion von aussen gesetzt wird, dann 1696 // diese nicht zuruecksetzen 1697 const WinBits nWindowStyle = GetStyle(); 1698 const sal_Bool bResetClipRegion = !bHasClipRegion; 1699 const sal_Bool bHideSelection = ((nWindowStyle & WB_HIDESELECTION) && !HasFocus())!=0; 1700 const StyleSettings& rSettings = GetSettings().GetStyleSettings(); 1701 1702 Font aHighlightFont( GetFont() ); 1703 const Color aHighlightTextColor( rSettings.GetHighlightTextColor() ); 1704 aHighlightFont.SetColor( aHighlightTextColor ); 1705 1706 Size aRectSize( 0, nTempEntryHeight ); 1707 1708 if( !bHasClipRegion && nWindowStyle & WB_HSCROLL ) 1709 { 1710 SetClipRegion( Region(pImp->GetClipRegionRect()) ); 1711 bHasClipRegion = sal_True; 1712 } 1713 1714 SvViewDataEntry* pViewDataEntry = GetViewDataEntry( pEntry ); 1715 1716 sal_uInt16 nTabCount = aTabs.Count(); 1717 sal_uInt16 nItemCount = pEntry->ItemCount(); 1718 sal_uInt16 nCurTab = 0; 1719 sal_uInt16 nCurItem = 0; 1720 1721 while( nCurTab < nTabCount && nCurItem < nItemCount ) 1722 { 1723 SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nCurTab ); 1724 sal_uInt16 nNextTab = nCurTab + 1; 1725 SvLBoxTab* pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0; 1726 SvLBoxItem* pItem = nCurItem < nItemCount ? pEntry->GetItem(nCurItem) : 0; 1727 1728 sal_uInt16 nFlags = pTab->nFlags; 1729 Size aSize( pItem->GetSize( pViewDataEntry, nCurItem )); 1730 long nTabPos = GetTabPos( pEntry, pTab ); 1731 1732 long nNextTabPos; 1733 if( pNextTab ) 1734 nNextTabPos = GetTabPos( pEntry, pNextTab ); 1735 else 1736 { 1737 nNextTabPos = nMaxRight; 1738 if( nTabPos > nMaxRight ) 1739 nNextTabPos += 50; 1740 } 1741 1742 long nX; 1743 if( pTab->nFlags & SV_LBOXTAB_ADJUST_RIGHT ) 1744 //verhindern, das rechter Rand von der Tabtrennung abgeschnitten wird 1745 nX = nTabPos + pTab->CalcOffset(aSize.Width(), (nNextTabPos-SV_TAB_BORDER-1) -nTabPos); 1746 else 1747 nX = nTabPos + pTab->CalcOffset(aSize.Width(), nNextTabPos-nTabPos); 1748 1749 if( nFlags & nTabFlags ) 1750 { 1751 if( !bHasClipRegion && nX + aSize.Width() >= nMaxRight ) 1752 { 1753 SetClipRegion( Region(pImp->GetClipRegionRect()) ); 1754 bHasClipRegion = sal_True; 1755 } 1756 aEntryPos.X() = nX; 1757 aEntryPos.Y() = nLine; 1758 1759 // Hintergrund-Muster & Farbe bestimmen 1760 1761 Wallpaper aWallpaper = GetBackground(); 1762 1763 int bSelTab = nFlags & SV_LBOXTAB_SHOW_SELECTION; 1764 sal_uInt16 nItemType = pItem->IsA(); 1765 1766 if ( pViewDataEntry->IsSelected() && bSelTab && !pViewDataEntry->IsCursored() ) 1767 { 1768 Color aNewWallColor = rSettings.GetHighlightColor(); 1769 if ( !bInUse || nItemType != SV_ITEM_ID_LBOXCONTEXTBMP ) 1770 { 1771 // if the face color is bright then the deactive color is also bright 1772 // -> so you can't see any deactive selection 1773 if ( bHideSelection && !rSettings.GetFaceColor().IsBright() && 1774 aWallpaper.GetColor().IsBright() != rSettings.GetDeactiveColor().IsBright() ) 1775 aNewWallColor = rSettings.GetDeactiveColor(); 1776 // set font color to highlight 1777 if ( !bCurFontIsSel ) 1778 { 1779 SetTextColor( aHighlightTextColor ); 1780 SetFont( aHighlightFont ); 1781 bCurFontIsSel = true; 1782 } 1783 } 1784 aWallpaper.SetColor( aNewWallColor ); 1785 } 1786 else // keine Selektion 1787 { 1788 if( bInUse && nItemType == SV_ITEM_ID_LBOXCONTEXTBMP ) 1789 aWallpaper.SetColor( rSettings.GetFieldColor() ); 1790 else if( bCurFontIsSel ) 1791 { 1792 bCurFontIsSel = false; 1793 SetTextColor( aBackupTextColor ); 1794 SetFont( aBackupFont ); 1795 } 1796 } 1797 1798 // Hintergrund zeichnen 1799 if( !(nTreeFlags & TREEFLAG_USESEL)) 1800 { 1801 // nur den Bereich zeichnen, den das Item einnimmt 1802 aRectSize.Width() = aSize.Width(); 1803 aRect.SetPos( aEntryPos ); 1804 aRect.SetSize( aRectSize ); 1805 } 1806 else 1807 { 1808 // vom aktuellen bis zum naechsten Tab zeichnen 1809 if( nCurTab != 0 ) 1810 aRect.Left() = nTabPos; 1811 else 1812 // beim nullten Tab immer ab Spalte 0 zeichnen 1813 // (sonst Probleme bei Tabs mit Zentrierung) 1814 aRect.Left() = 0; 1815 aRect.Top() = nLine; 1816 aRect.Bottom() = nLine + nTempEntryHeight - 1; 1817 if( pNextTab ) 1818 { 1819 long nRight; 1820 nRight = GetTabPos(pEntry,pNextTab)-1; 1821 if( nRight > nMaxRight ) 1822 nRight = nMaxRight; 1823 aRect.Right() = nRight; 1824 } 1825 else 1826 aRect.Right() = nMaxRight; 1827 } 1828 // bei anwenderdefinierter Selektion, die bei einer Tabposition 1829 // groesser 0 beginnt den Hintergrund des 0.ten Items nicht 1830 // fuellen, da sonst z.B. TablistBoxen mit Linien nicht 1831 // realisiert werden koennen. 1832 if( !(nCurTab==0 && (nTreeFlags & TREEFLAG_USESEL) && nFirstSelTab) ) 1833 { 1834 SetFillColor( aWallpaper.GetColor() ); 1835 // Bei kleinen hor. Resizes tritt dieser Fall auf 1836 if( aRect.Left() < aRect.Right() ) 1837 DrawRect( aRect ); 1838 } 1839 // Item zeichnen 1840 // vertikal zentrieren 1841 aEntryPos.Y() += ( nTempEntryHeight - aSize.Height() ) / 2; 1842 pItem->Paint( aEntryPos, *this, pViewDataEntry->GetFlags(), pEntry ); 1843 1844 // Trennungslinie zwischen Tabs 1845 if( pNextTab && pItem->IsA() == SV_ITEM_ID_LBOXSTRING && 1846 // nicht am rechten Fensterrand! 1847 aRect.Right() < nMaxRight ) 1848 { 1849 aRect.Left() = aRect.Right() - SV_TAB_BORDER; 1850 DrawRect( aRect ); 1851 } 1852 1853 SetFillColor( aBackupColor ); 1854 } 1855 nCurItem++; 1856 nCurTab++; 1857 } 1858 if( pViewDataEntry->IsCursored() && !HasFocus() ) 1859 { 1860 // Cursor-Emphasis 1861 SetFillColor(); 1862 Color aOldLineColor = GetLineColor(); 1863 SetLineColor( Color( COL_BLACK ) ); 1864 aRect = GetFocusRect( pEntry, nLine ); 1865 aRect.Top()++; 1866 aRect.Bottom()--; 1867 DrawRect( aRect ); 1868 SetLineColor( aOldLineColor ); 1869 SetFillColor( aBackupColor ); 1870 } 1871 1872 if( bCurFontIsSel ) 1873 { 1874 SetTextColor( aBackupTextColor ); 1875 SetFont( aBackupFont ); 1876 } 1877 1878 sal_uInt16 nFirstDynTabPos; 1879 SvLBoxTab* pFirstDynamicTab = GetFirstDynamicTab( nFirstDynTabPos ); 1880 long nDynTabPos = GetTabPos( pEntry, pFirstDynamicTab ); 1881 nDynTabPos += pImp->nNodeBmpTabDistance; 1882 nDynTabPos += pImp->nNodeBmpWidth / 2; 1883 nDynTabPos += 4; // 4 Pixel Reserve, damit die Node-Bitmap 1884 // nicht zu nah am naechsten Tab steht 1885 1886 if( (!(pEntry->GetFlags() & SV_ENTRYFLAG_NO_NODEBMP)) && 1887 (nWindowStyle & WB_HASBUTTONS) && pFirstDynamicTab && 1888 ( pEntry->HasChilds() || pEntry->HasChildsOnDemand() ) ) 1889 { 1890 // ersten festen Tab suchen, und pruefen ob die Node-Bitmap 1891 // in ihn hineinragt 1892 sal_uInt16 nNextTab = nFirstDynTabPos; 1893 SvLBoxTab* pNextTab; 1894 do 1895 { 1896 nNextTab++; 1897 pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0; 1898 } while( pNextTab && pNextTab->IsDynamic() ); 1899 1900 if( !pNextTab || (GetTabPos( pEntry, pNextTab ) > nDynTabPos) ) 1901 { 1902 if((nWindowStyle & WB_HASBUTTONSATROOT) || pModel->GetDepth(pEntry) > 0) 1903 { 1904 Point aPos( GetTabPos(pEntry,pFirstDynamicTab), nLine ); 1905 aPos.X() += pImp->nNodeBmpTabDistance; 1906 1907 const Image* pImg = 0; 1908 BmpColorMode eBitmapMode = BMP_COLOR_NORMAL; 1909 if ( GetSettings().GetStyleSettings().GetHighContrastMode() ) 1910 eBitmapMode = BMP_COLOR_HIGHCONTRAST; 1911 1912 if( IsExpanded(pEntry) ) 1913 pImg = &pImp->GetExpandedNodeBmp( eBitmapMode ); 1914 else 1915 { 1916 if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() && 1917 (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) && 1918 pImp->GetDontKnowNodeBmp().GetSizePixel().Width() ) 1919 pImg = &pImp->GetDontKnowNodeBmp( eBitmapMode ); 1920 else 1921 pImg = &pImp->GetCollapsedNodeBmp( eBitmapMode ); 1922 } 1923 aPos.Y() += (nTempEntryHeight - pImg->GetSizePixel().Height()) / 2; 1924 1925 sal_uInt16 nStyle = 0; 1926 if ( !IsEnabled() ) 1927 nStyle |= IMAGE_DRAW_DISABLE; 1928 1929 //native 1930 sal_Bool bNativeOK = sal_False; 1931 if ( IsNativeControlSupported( CTRL_LISTNODE, PART_ENTIRE_CONTROL) ) 1932 { 1933 ImplControlValue aControlValue; 1934 Rectangle aCtrlRegion( aPos, pImg->GetSizePixel() ); 1935 ControlState nState = 0; 1936 1937 if ( IsEnabled() ) nState |= CTRL_STATE_ENABLED; 1938 1939 if ( IsExpanded(pEntry) ) 1940 aControlValue.setTristateVal( BUTTONVALUE_ON );//expanded node 1941 else 1942 { 1943 if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() && 1944 (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) && 1945 pImp->GetDontKnowNodeBmp().GetSizePixel().Width() ) 1946 aControlValue.setTristateVal( BUTTONVALUE_DONTKNOW );//dont know 1947 else 1948 aControlValue.setTristateVal( BUTTONVALUE_OFF );//collapsed node 1949 } 1950 1951 bNativeOK = DrawNativeControl( CTRL_LISTNODE, PART_ENTIRE_CONTROL, 1952 aCtrlRegion, nState, aControlValue, rtl::OUString() ); 1953 } 1954 1955 if( !bNativeOK) { 1956 //non native 1957 DrawImage( aPos, *pImg ,nStyle); 1958 } 1959 } 1960 } 1961 } 1962 1963 1964 if( bHasClipRegion && bResetClipRegion ) 1965 SetClipRegion(); 1966 return 0; // nRowLen; 1967 } 1968 1969 void SvTreeListBox::PreparePaint( SvLBoxEntry* ) 1970 { 1971 } 1972 1973 Rectangle SvTreeListBox::GetFocusRect( SvLBoxEntry* pEntry, long nLine ) 1974 { 1975 DBG_CHKTHIS(SvTreeListBox,0); 1976 Size aSize; 1977 Rectangle aRect; 1978 aRect.Top() = nLine; 1979 aSize.Height() = GetEntryHeight(); 1980 1981 long nRealWidth = pImp->GetOutputSize().Width(); 1982 nRealWidth -= GetMapMode().GetOrigin().X(); 1983 1984 sal_uInt16 nCurTab; 1985 SvLBoxTab* pTab = GetFirstTab( SV_LBOXTAB_SHOW_SELECTION, nCurTab ); 1986 long nTabPos = 0; 1987 if( pTab ) 1988 nTabPos = GetTabPos( pEntry, pTab ); 1989 long nNextTabPos; 1990 if( pTab && nCurTab < aTabs.Count() - 1 ) 1991 { 1992 SvLBoxTab* pNextTab = (SvLBoxTab*)aTabs.GetObject( nCurTab + 1 ); 1993 nNextTabPos = GetTabPos( pEntry, pNextTab ); 1994 } 1995 else 1996 { 1997 nNextTabPos = nRealWidth; 1998 if( nTabPos > nRealWidth ) 1999 nNextTabPos += 50; 2000 } 2001 2002 sal_Bool bUserSelection = (sal_Bool)( nTreeFlags & TREEFLAG_USESEL ) != 0; 2003 if( !bUserSelection ) 2004 { 2005 if( pTab && nCurTab < pEntry->ItemCount() ) 2006 { 2007 SvLBoxItem* pItem = pEntry->GetItem( nCurTab ); 2008 aSize.Width() = pItem->GetSize( this, pEntry ).Width(); 2009 if( !aSize.Width() ) 2010 aSize.Width() = 15; 2011 long nX = nTabPos; //GetTabPos( pEntry, pTab ); 2012 // Ausrichtung 2013 nX += pTab->CalcOffset( aSize.Width(), nNextTabPos - nTabPos ); 2014 aRect.Left() = nX; 2015 // damit erster & letzter Buchstabe nicht angeknabbert werden 2016 aRect.SetSize( aSize ); 2017 if( aRect.Left() > 0 ) 2018 aRect.Left()--; 2019 aRect.Right()++; 2020 } 2021 } 2022 else 2023 { 2024 // wenn erster SelTab != 0, dann muessen wir auch rechnen 2025 if( nFocusWidth == -1 || nFirstSelTab ) 2026 { 2027 sal_uInt16 nLastTab; 2028 SvLBoxTab* pLastTab = GetLastTab(SV_LBOXTAB_SHOW_SELECTION,nLastTab); 2029 nLastTab++; 2030 if( nLastTab < aTabs.Count() ) // gibts noch einen ? 2031 pLastTab = (SvLBoxTab*)aTabs.GetObject( nLastTab ); 2032 else 2033 pLastTab = 0; // ueber gesamte Breite selektieren 2034 aSize.Width() = pLastTab ? pLastTab->GetPos() : 0x0fffffff; 2035 nFocusWidth = (short)aSize.Width(); 2036 if( pTab ) 2037 nFocusWidth = nFocusWidth - (short)nTabPos; //pTab->GetPos(); 2038 } 2039 else 2040 { 2041 aSize.Width() = nFocusWidth; 2042 if( pTab ) 2043 { 2044 if( nCurTab ) 2045 aSize.Width() += nTabPos; 2046 else 2047 aSize.Width() += pTab->GetPos(); // Tab0 immer ab ganz links 2048 } 2049 } 2050 // wenn Sel. beim nullten Tab anfaengt, dann ab Spalte 0 sel. zeichnen 2051 if( nCurTab != 0 ) 2052 { 2053 aRect.Left() = nTabPos; 2054 aSize.Width() -= nTabPos; 2055 } 2056 aRect.SetSize( aSize ); 2057 } 2058 // rechten Rand anpassen wg. Clipping 2059 if( aRect.Right() >= nRealWidth ) 2060 { 2061 aRect.Right() = nRealWidth-1; 2062 nFocusWidth = (short)aRect.GetWidth(); 2063 } 2064 return aRect; 2065 } 2066 2067 2068 long SvTreeListBox::GetTabPos( SvLBoxEntry* pEntry, SvLBoxTab* pTab) 2069 { 2070 DBG_CHKTHIS(SvTreeListBox,0); 2071 DBG_ASSERT(pTab,"No Tab"); 2072 long nPos = pTab->GetPos(); 2073 if( pTab->IsDynamic() ) 2074 { 2075 sal_uInt16 nDepth = pModel->GetDepth( pEntry ); 2076 nDepth = nDepth * (sal_uInt16)nIndent; 2077 nPos += (long)nDepth; 2078 } 2079 return nPos; 2080 } 2081 2082 SvLBoxItem* SvTreeListBox::GetItem_Impl( SvLBoxEntry* pEntry, long nX, 2083 SvLBoxTab** ppTab, sal_uInt16 nEmptyWidth ) 2084 { 2085 DBG_CHKTHIS(SvTreeListBox,0); 2086 SvLBoxItem* pItemClicked = 0; 2087 sal_uInt16 nTabCount = aTabs.Count(); 2088 sal_uInt16 nItemCount = pEntry->ItemCount(); 2089 SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0); 2090 SvLBoxItem* pItem = pEntry->GetItem(0); 2091 sal_uInt16 nNextItem = 1; 2092 nX -= GetMapMode().GetOrigin().X(); 2093 long nRealWidth = pImp->GetOutputSize().Width(); 2094 nRealWidth -= GetMapMode().GetOrigin().X(); 2095 2096 while( 1 ) 2097 { 2098 SvLBoxTab* pNextTab=nNextItem<nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextItem) : 0; 2099 long nStart = GetTabPos( pEntry, pTab ); 2100 2101 long nNextTabPos; 2102 if( pNextTab ) 2103 nNextTabPos = GetTabPos( pEntry, pNextTab ); 2104 else 2105 { 2106 nNextTabPos = nRealWidth; 2107 if( nStart > nRealWidth ) 2108 nNextTabPos += 50; 2109 } 2110 2111 Size aItemSize( pItem->GetSize(this, pEntry)); 2112 nStart += pTab->CalcOffset( aItemSize.Width(), nNextTabPos - nStart ); 2113 long nLen = aItemSize.Width(); 2114 if( pNextTab ) 2115 { 2116 long nTabWidth = GetTabPos( pEntry, pNextTab ) - nStart; 2117 if( nTabWidth < nLen ) 2118 nLen = nTabWidth; 2119 } 2120 2121 if( !nLen ) 2122 nLen = nEmptyWidth; 2123 2124 if( nX >= nStart && nX < (nStart+nLen ) ) 2125 { 2126 pItemClicked = pItem; 2127 if( ppTab ) 2128 { 2129 *ppTab = pTab; 2130 break; 2131 } 2132 } 2133 if( nNextItem >= nItemCount || nNextItem >= nTabCount) 2134 break; 2135 pTab = (SvLBoxTab*)aTabs.GetObject( nNextItem ); 2136 pItem = pEntry->GetItem( nNextItem ); 2137 nNextItem++; 2138 } 2139 return pItemClicked; 2140 } 2141 2142 SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX,SvLBoxTab** ppTab) 2143 { 2144 return GetItem_Impl( pEntry, nX, ppTab, 0 ); 2145 } 2146 2147 SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX ) 2148 { 2149 DBG_CHKTHIS(SvTreeListBox,0); 2150 SvLBoxTab* pDummyTab; 2151 return GetItem_Impl( pEntry, nX, &pDummyTab, 0 ); 2152 } 2153 2154 SvLBoxItem* SvTreeListBox::GetFirstDynamicItem( SvLBoxEntry* pEntry ) 2155 { 2156 DBG_CHKTHIS(SvTreeListBox,0); 2157 2158 SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0); 2159 SvLBoxItem* pItem = pEntry->GetItem(0); 2160 sal_uInt16 nTabCount = aTabs.Count(); 2161 2162 sal_uInt16 nNext = 1; 2163 while ( !pTab->IsDynamic() && nNext < nTabCount ) 2164 { 2165 pItem = pEntry->GetItem( nNext ); 2166 pTab = (SvLBoxTab*)aTabs.GetObject( nNext ); 2167 nNext++; 2168 } 2169 return pItem; 2170 } 2171 2172 void SvTreeListBox::AddTab(long nTabPos,sal_uInt16 nFlags,void* pUserData ) 2173 { 2174 DBG_CHKTHIS(SvTreeListBox,0); 2175 nFocusWidth = -1; 2176 SvLBoxTab* pTab = new SvLBoxTab( nTabPos, nFlags ); 2177 pTab->SetUserData( pUserData ); 2178 aTabs.Insert( pTab, aTabs.Count() ); 2179 if( nTreeFlags & TREEFLAG_USESEL ) 2180 { 2181 sal_uInt16 nPos = aTabs.Count() - 1; 2182 if( nPos >= nFirstSelTab && nPos <= nLastSelTab ) 2183 pTab->nFlags |= SV_LBOXTAB_SHOW_SELECTION; 2184 else 2185 // String-Items werden normalerweise immer selektiert 2186 // deshalb explizit ausschalten 2187 pTab->nFlags &= ~SV_LBOXTAB_SHOW_SELECTION; 2188 } 2189 } 2190 2191 2192 2193 SvLBoxTab* SvTreeListBox::GetFirstDynamicTab( sal_uInt16& rPos ) const 2194 { 2195 DBG_CHKTHIS(SvTreeListBox,0); 2196 sal_uInt16 nCurTab = 0; 2197 sal_uInt16 nTabCount = aTabs.Count(); 2198 while( nCurTab < nTabCount ) 2199 { 2200 SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(nCurTab); 2201 if( pTab->nFlags & SV_LBOXTAB_DYNAMIC ) 2202 { 2203 rPos = nCurTab; 2204 return pTab; 2205 } 2206 nCurTab++; 2207 } 2208 return 0; 2209 } 2210 2211 SvLBoxTab* SvTreeListBox::GetFirstDynamicTab() const 2212 { 2213 sal_uInt16 nDummy; 2214 return GetFirstDynamicTab( nDummy ); 2215 } 2216 2217 SvLBoxTab* SvTreeListBox::GetTab( SvLBoxEntry* pEntry, SvLBoxItem* pItem) const 2218 { 2219 DBG_CHKTHIS(SvTreeListBox,0); 2220 sal_uInt16 nPos = pEntry->GetPos( pItem ); 2221 return (SvLBoxTab*)aTabs.GetObject( nPos ); 2222 } 2223 2224 void SvTreeListBox::ClearTabList() 2225 { 2226 DBG_CHKTHIS(SvTreeListBox,0); 2227 sal_uInt16 nTabCount = aTabs.Count(); 2228 while( nTabCount ) 2229 { 2230 nTabCount--; 2231 SvLBoxTab* pDelTab = (SvLBoxTab*)aTabs.GetObject( nTabCount ); 2232 delete pDelTab; 2233 } 2234 aTabs.Remove(0,aTabs.Count()); 2235 } 2236 2237 2238 Size SvTreeListBox::GetOutputSizePixel() const 2239 { 2240 DBG_CHKTHIS(SvTreeListBox,0); 2241 Size aSize = pImp->GetOutputSize(); 2242 return aSize; 2243 } 2244 2245 void SvTreeListBox::NotifyBeginScroll() 2246 { 2247 DBG_CHKTHIS(SvTreeListBox,0); 2248 } 2249 2250 void SvTreeListBox::NotifyEndScroll() 2251 { 2252 DBG_CHKTHIS(SvTreeListBox,0); 2253 } 2254 2255 void SvTreeListBox::NotifyScrolling( long ) 2256 { 2257 DBG_CHKTHIS(SvTreeListBox,0); 2258 } 2259 2260 void SvTreeListBox::NotifyScrolled() 2261 { 2262 DBG_CHKTHIS(SvTreeListBox,0); 2263 aScrolledHdl.Call( this ); 2264 } 2265 2266 void SvTreeListBox::NotifyInvalidating() 2267 { 2268 DBG_CHKTHIS(SvTreeListBox,0); 2269 } 2270 2271 void SvTreeListBox::Invalidate( sal_uInt16 nInvalidateFlags ) 2272 { 2273 DBG_CHKTHIS(SvTreeListBox,0); 2274 if( nFocusWidth == -1 ) 2275 // damit Control nicht nach dem Paint ein falsches FocusRect anzeigt 2276 pImp->RecalcFocusRect(); 2277 NotifyInvalidating(); 2278 SvLBox::Invalidate( nInvalidateFlags ); 2279 pImp->Invalidate(); 2280 } 2281 2282 void SvTreeListBox::Invalidate( const Rectangle& rRect, sal_uInt16 nInvalidateFlags ) 2283 { 2284 DBG_CHKTHIS(SvTreeListBox,0); 2285 if( nFocusWidth == -1 ) 2286 // damit Control nicht nach dem Paint ein falsches FocusRect anzeigt 2287 pImp->RecalcFocusRect(); 2288 NotifyInvalidating(); 2289 SvLBox::Invalidate( rRect, nInvalidateFlags ); 2290 } 2291 2292 2293 void SvTreeListBox::SetHighlightRange( sal_uInt16 nStart, sal_uInt16 nEnd) 2294 { 2295 DBG_CHKTHIS(SvTreeListBox,0); 2296 2297 sal_uInt16 nTemp; 2298 nTreeFlags |= TREEFLAG_USESEL; 2299 if( nStart > nEnd ) 2300 { 2301 nTemp = nStart; 2302 nStart = nEnd; 2303 nEnd = nTemp; 2304 } 2305 // alle Tabs markieren, die im Bereich liegen 2306 nTreeFlags |= TREEFLAG_RECALCTABS; 2307 nFirstSelTab = nStart; 2308 nLastSelTab = nEnd; 2309 pImp->RecalcFocusRect(); 2310 } 2311 2312 void SvTreeListBox::RemoveHighlightRange() 2313 { 2314 DBG_CHKTHIS(SvTreeListBox,0); 2315 nTreeFlags &= (~TREEFLAG_USESEL); 2316 if( IsUpdateMode() ) 2317 Invalidate(); 2318 } 2319 2320 sal_uLong SvTreeListBox::GetAscInsertionPos(SvLBoxEntry*,SvLBoxEntry*) 2321 { 2322 return LIST_APPEND; 2323 } 2324 2325 sal_uLong SvTreeListBox::GetDescInsertionPos(SvLBoxEntry*,SvLBoxEntry*) 2326 { 2327 DBG_CHKTHIS(SvTreeListBox,0); 2328 return LIST_APPEND; 2329 } 2330 2331 Region SvTreeListBox::GetDragRegion() const 2332 { 2333 DBG_CHKTHIS(SvTreeListBox,0); 2334 Rectangle aRect; 2335 SvLBoxEntry* pEntry = GetCurEntry(); 2336 if( pEntry ) 2337 { 2338 Point aPos = GetEntryPosition( pEntry ); 2339 aRect = ((SvTreeListBox*)this)->GetFocusRect( pEntry, aPos.Y() ); 2340 } 2341 Region aRegion( aRect ); 2342 return aRegion; 2343 } 2344 2345 2346 void SvTreeListBox::Command( const CommandEvent& rCEvt ) 2347 { 2348 DBG_CHKTHIS(SvTreeListBox,0); 2349 // FIXME gnumake2 resync to DEV300_m84 2350 pImp->Command( rCEvt ); 2351 } 2352 2353 2354 void SvTreeListBox::RemoveParentKeepChilds( SvLBoxEntry* pParent ) 2355 { 2356 DBG_CHKTHIS(SvTreeListBox,0); 2357 DBG_ASSERT(pParent,"RemoveParentKeepChilds:No Parent"); 2358 SvLBoxEntry* pNewParent = GetParent( pParent ); 2359 if( pParent->HasChilds()) 2360 { 2361 SvLBoxEntry* pChild = FirstChild( pParent ); 2362 while( pChild ) 2363 { 2364 pModel->Move( pChild, pNewParent, LIST_APPEND ); 2365 pChild = FirstChild( pParent ); 2366 } 2367 } 2368 pModel->Remove( pParent ); 2369 } 2370 2371 SvLBoxTab* SvTreeListBox::GetFirstTab( sal_uInt16 nFlagMask, sal_uInt16& rPos ) 2372 { 2373 sal_uInt16 nTabCount = aTabs.Count(); 2374 for( sal_uInt16 nPos = 0; nPos < nTabCount; nPos++ ) 2375 { 2376 SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nPos ); 2377 if( (pTab->nFlags & nFlagMask) ) 2378 { 2379 rPos = nPos; 2380 return pTab; 2381 } 2382 } 2383 rPos = 0xffff; 2384 return 0; 2385 } 2386 2387 SvLBoxTab* SvTreeListBox::GetLastTab( sal_uInt16 nFlagMask, sal_uInt16& rTabPos ) 2388 { 2389 short nTabCount = (short)aTabs.Count(); 2390 if( nTabCount ) 2391 { 2392 for( short nPos = nTabCount-1; nPos >= 0; nPos-- ) 2393 { 2394 SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( (sal_uInt16)nPos ); 2395 if( (pTab->nFlags & nFlagMask) ) 2396 { 2397 rTabPos = (sal_uInt16)nPos; 2398 return pTab; 2399 } 2400 } 2401 } 2402 rTabPos = 0xffff; 2403 return 0; 2404 } 2405 2406 void SvTreeListBox::SetAddMode( sal_Bool bAdd ) 2407 { 2408 pImp->SetAddMode( bAdd ); 2409 } 2410 2411 sal_Bool SvTreeListBox::IsAddMode() const 2412 { 2413 return pImp->IsAddMode(); 2414 } 2415 2416 void SvTreeListBox::RequestHelp( const HelpEvent& rHEvt ) 2417 { 2418 if( !pImp->RequestHelp( rHEvt ) ) 2419 SvLBox::RequestHelp( rHEvt ); 2420 } 2421 2422 void SvTreeListBox::CursorMoved( SvLBoxEntry* ) 2423 { 2424 } 2425 2426 IMPL_LINK( SvTreeListBox, DefaultCompare, SvSortData*, pData ) 2427 { 2428 SvLBoxEntry* pLeft = (SvLBoxEntry*)(pData->pLeft ); 2429 SvLBoxEntry* pRight = (SvLBoxEntry*)(pData->pRight ); 2430 String aLeft( ((SvLBoxString*)(pLeft->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText()); 2431 String aRight( ((SvLBoxString*)(pRight->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText()); 2432 // #102891# ---------------- 2433 pImp->UpdateIntlWrapper(); 2434 return pImp->pIntlWrapper->getCaseCollator()->compareString( aLeft, aRight ); 2435 } 2436 2437 void SvTreeListBox::ModelNotification( sal_uInt16 nActionId, SvListEntry* pEntry1, 2438 SvListEntry* pEntry2, sal_uLong nPos ) 2439 { 2440 if( nActionId == LISTACTION_CLEARING ) 2441 CancelTextEditing(); 2442 2443 SvLBox::ModelNotification( nActionId, pEntry1, pEntry2, nPos ); 2444 switch( nActionId ) 2445 { 2446 case LISTACTION_INSERTED: 2447 { 2448 SvLBoxEntry* pEntry( dynamic_cast< SvLBoxEntry* >( pEntry1 ) ); 2449 ENSURE_OR_BREAK( pEntry, "SvTreeListBox::ModelNotification: invalid entry!" ); 2450 SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) ); 2451 if ( !pBmpItem ) 2452 break; 2453 const Image& rBitmap1( pBmpItem->GetBitmap1() ); 2454 const Image& rBitmap2( pBmpItem->GetBitmap2() ); 2455 short nMaxWidth = short( Max( rBitmap1.GetSizePixel().Width(), rBitmap2.GetSizePixel().Width() ) ); 2456 nMaxWidth = pImp->UpdateContextBmpWidthVector( pEntry, nMaxWidth ); 2457 if( nMaxWidth > nContextBmpWidthMax ) 2458 { 2459 nContextBmpWidthMax = nMaxWidth; 2460 SetTabs(); 2461 } 2462 } 2463 break; 2464 2465 case LISTACTION_RESORTING: 2466 SetUpdateMode( sal_False ); 2467 break; 2468 2469 case LISTACTION_RESORTED: 2470 // nach Sortierung den ersten Eintrag anzeigen, dabei die 2471 // Selektion erhalten. 2472 MakeVisible( (SvLBoxEntry*)pModel->First(), sal_True ); 2473 SetUpdateMode( sal_True ); 2474 break; 2475 2476 case LISTACTION_CLEARED: 2477 if( IsUpdateMode() ) 2478 Update(); 2479 break; 2480 } 2481 } 2482 2483 // bei Aenderungen SetTabs beruecksichtigen 2484 long SvTreeListBox::GetTextOffset() const 2485 { 2486 DBG_CHKTHIS(SvTreeListBox,0); 2487 const WinBits nWindowStyle = GetStyle(); 2488 sal_Bool bHasButtons = (nWindowStyle & WB_HASBUTTONS)!=0; 2489 sal_Bool bHasButtonsAtRoot = (nWindowStyle & (WB_HASLINESATROOT | 2490 WB_HASBUTTONSATROOT))!=0; 2491 long nStartPos = TAB_STARTPOS; 2492 long nNodeWidthPixel = GetExpandedNodeBmp().GetSizePixel().Width(); 2493 2494 long nCheckWidth = 0; 2495 if( nTreeFlags & TREEFLAG_CHKBTN ) 2496 nCheckWidth = pCheckButtonData->aBmps[0].GetSizePixel().Width(); 2497 long nCheckWidthDIV2 = nCheckWidth / 2; 2498 2499 long nContextWidth = nContextBmpWidthMax; 2500 long nContextWidthDIV2 = nContextWidth / 2; 2501 2502 int nCase = NO_BUTTONS; 2503 if( !(nTreeFlags & TREEFLAG_CHKBTN) ) 2504 { 2505 if( bHasButtons ) 2506 nCase = NODE_BUTTONS; 2507 } 2508 else 2509 { 2510 if( bHasButtons ) 2511 nCase = NODE_AND_CHECK_BUTTONS; 2512 else 2513 nCase = CHECK_BUTTONS; 2514 } 2515 2516 switch( nCase ) 2517 { 2518 case NO_BUTTONS : 2519 nStartPos += nContextWidthDIV2; // wg. Zentrierung 2520 nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp 2521 if( nContextBmpWidthMax ) 2522 nStartPos += 5; // Abstand Context-Bmp - Text 2523 break; 2524 2525 case NODE_BUTTONS : 2526 if( bHasButtonsAtRoot ) 2527 nStartPos += ( nIndent + (nNodeWidthPixel/2) ); 2528 else 2529 nStartPos += nContextWidthDIV2; 2530 nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp 2531 if( nContextBmpWidthMax ) 2532 nStartPos += 5; // Abstand Context-Bmp - Text 2533 break; 2534 2535 case NODE_AND_CHECK_BUTTONS : 2536 if( bHasButtonsAtRoot ) 2537 nStartPos += ( nIndent + nNodeWidthPixel ); 2538 else 2539 nStartPos += nCheckWidthDIV2; 2540 nStartPos += nCheckWidthDIV2; // rechter Rand des CheckButtons 2541 nStartPos += 3; // Abstand CheckButton Context-Bmp 2542 nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp 2543 nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp 2544 // Abstand setzen nur wenn Bitmaps da 2545 if( nContextBmpWidthMax ) 2546 nStartPos += 5; // Abstand Context-Bmp - Text 2547 break; 2548 2549 case CHECK_BUTTONS : 2550 nStartPos += nCheckWidthDIV2; 2551 nStartPos += nCheckWidthDIV2; // rechter Rand CheckButton 2552 nStartPos += 3; // Abstand CheckButton Context-Bmp 2553 nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp 2554 nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp 2555 if( nContextBmpWidthMax ) 2556 nStartPos += 5; // Abstand Context-Bmp - Text 2557 break; 2558 } 2559 return nStartPos; 2560 } 2561 2562 void SvTreeListBox::EndSelection() 2563 { 2564 pImp->EndSelection(); 2565 } 2566 2567 sal_Bool SvTreeListBox::IsNodeButton( const Point& rPos ) const 2568 { 2569 SvLBoxEntry* pEntry = GetEntry( rPos ); 2570 if( pEntry ) 2571 return pImp->IsNodeButton( rPos, pEntry ); 2572 return sal_False; 2573 } 2574 2575 void SvTreeListBox::RepaintScrollBars() const 2576 { 2577 ((SvTreeListBox*)this)->pImp->RepaintScrollBars(); 2578 } 2579 2580 ScrollBar *SvTreeListBox::GetVScroll() 2581 { 2582 return &((SvTreeListBox*)this)->pImp->aVerSBar; 2583 } 2584 2585 ScrollBar *SvTreeListBox::GetHScroll() 2586 { 2587 return &((SvTreeListBox*)this)->pImp->aHorSBar; 2588 } 2589 2590 void SvTreeListBox::EnableAsyncDrag( sal_Bool b ) 2591 { 2592 pImp->EnableAsyncDrag( b ); 2593 } 2594 2595 SvLBoxEntry* SvTreeListBox::GetFirstEntryInView() const 2596 { 2597 Point aPos; 2598 return GetEntry( aPos ); 2599 } 2600 2601 SvLBoxEntry* SvTreeListBox::GetNextEntryInView(SvLBoxEntry* pEntry ) const 2602 { 2603 SvLBoxEntry* pNext = (SvLBoxEntry*)NextVisible( pEntry ); 2604 if( pNext ) 2605 { 2606 Point aPos( GetEntryPosition(pNext) ); 2607 const Size& rSize = pImp->GetOutputSize(); 2608 if( aPos.Y() < 0 || aPos.Y() >= rSize.Height() ) 2609 return 0; 2610 } 2611 return pNext; 2612 } 2613 2614 void SvTreeListBox::ShowFocusRect( const SvLBoxEntry* pEntry ) 2615 { 2616 pImp->ShowFocusRect( pEntry ); 2617 } 2618 2619 void SvTreeListBox::SetTabBar( TabBar* pTabBar ) 2620 { 2621 pImp->SetTabBar( pTabBar ); 2622 } 2623 2624 void SvTreeListBox::DataChanged( const DataChangedEvent& rDCEvt ) 2625 { 2626 if( (rDCEvt.GetType()==DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) ) 2627 { 2628 nEntryHeight = 0; // _together_ with sal_True of 1. par (bFont) of InitSettings() a zero-height 2629 // forces complete recalc of heights! 2630 InitSettings( sal_True, sal_True, sal_True ); 2631 Invalidate(); 2632 } 2633 else 2634 Control::DataChanged( rDCEvt ); 2635 } 2636 2637 void SvTreeListBox::StateChanged( StateChangedType i_nStateChange ) 2638 { 2639 SvLBox::StateChanged( i_nStateChange ); 2640 if ( i_nStateChange == STATE_CHANGE_STYLE ) 2641 ImplInitStyle(); 2642 } 2643 2644 void SvTreeListBox::InitSettings(sal_Bool bFont,sal_Bool bForeground,sal_Bool bBackground) 2645 { 2646 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 2647 if( bFont ) 2648 { 2649 Font aFont; 2650 aFont = rStyleSettings.GetFieldFont(); 2651 aFont.SetColor( rStyleSettings.GetWindowTextColor() ); 2652 SetPointFont( aFont ); 2653 AdjustEntryHeight( aFont ); 2654 RecalcViewData(); 2655 } 2656 2657 if( bForeground || bFont ) 2658 { 2659 SetTextColor( rStyleSettings.GetFieldTextColor() ); 2660 SetTextFillColor(); 2661 } 2662 2663 if( bBackground ) 2664 SetBackground( rStyleSettings.GetFieldColor() ); 2665 2666 // always try to re-create default-SvLBoxButtonData 2667 if( pCheckButtonData && pCheckButtonData->HasDefaultImages() ) 2668 pCheckButtonData->SetDefaultImages( this ); 2669 } 2670 2671 sal_Bool SvTreeListBox::IsCellFocusEnabled() const 2672 { 2673 return pImp->IsCellFocusEnabled(); 2674 } 2675 2676 bool SvTreeListBox::SetCurrentTabPos( sal_uInt16 _nNewPos ) 2677 { 2678 return pImp->SetCurrentTabPos( _nNewPos ); 2679 } 2680 2681 sal_uInt16 SvTreeListBox::GetCurrentTabPos() const 2682 { 2683 return pImp->GetCurrentTabPos(); 2684 } 2685 2686 void SvTreeListBox::InitStartEntry() 2687 { 2688 if( !pImp->pStartEntry ) 2689 pImp->pStartEntry = GetModel()->First(); 2690 } 2691 2692 void SvTreeListBox::CancelPendingEdit() 2693 { 2694 if( pImp ) 2695 pImp->CancelPendingEdit(); 2696 } 2697 2698 PopupMenu* SvTreeListBox::CreateContextMenu( void ) 2699 { 2700 return NULL; 2701 } 2702 2703 void SvTreeListBox::ExcecuteContextMenuAction( sal_uInt16 ) 2704 { 2705 DBG_WARNING( "SvTreeListBox::ExcecuteContextMenuAction(): now there's happening nothing!" ); 2706 } 2707 2708 void SvTreeListBox::EnableContextMenuHandling( void ) 2709 { 2710 DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" ); 2711 2712 pImp->bContextMenuHandling = sal_True; 2713 } 2714 2715 void SvTreeListBox::EnableContextMenuHandling( sal_Bool b ) 2716 { 2717 DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" ); 2718 2719 pImp->bContextMenuHandling = b; 2720 } 2721 2722 sal_Bool SvTreeListBox::IsContextMenuHandlingEnabled( void ) const 2723 { 2724 DBG_ASSERT( pImp, "-SvTreeListBox::IsContextMenuHandlingEnabled(): No implementation!" ); 2725 2726 return pImp->bContextMenuHandling; 2727 } 2728 2729 void SvTreeListBox::EnableList( bool _bEnable ) 2730 { 2731 // call base class method 2732 Window::Enable( _bEnable != false ); 2733 // then paint immediately 2734 Paint( Rectangle( Point(), GetSizePixel() ) ); 2735 } 2736 2737 ::com::sun::star::uno::Reference< XAccessible > SvTreeListBox::CreateAccessible() 2738 { 2739 Window* pParent = GetAccessibleParentWindow(); 2740 DBG_ASSERT( pParent, "SvTreeListBox::CreateAccessible - accessible parent not found" ); 2741 2742 ::com::sun::star::uno::Reference< XAccessible > xAccessible; 2743 if ( pParent ) 2744 { 2745 ::com::sun::star::uno::Reference< XAccessible > xAccParent = pParent->GetAccessible(); 2746 if ( xAccParent.is() ) 2747 { 2748 // need to be done here to get the vclxwindow later on in the accessbile 2749 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xTemp(GetComponentInterface()); 2750 xAccessible = pImp->m_aFactoryAccess.getFactory().createAccessibleTreeListBox( *this, xAccParent ); 2751 } 2752 } 2753 return xAccessible; 2754 } 2755 2756 void SvTreeListBox::FillAccessibleEntryStateSet( SvLBoxEntry* pEntry, ::utl::AccessibleStateSetHelper& rStateSet ) const 2757 { 2758 DBG_ASSERT( pEntry, "SvTreeListBox::FillAccessibleEntryStateSet: invalid entry" ); 2759 2760 if ( pEntry->HasChildsOnDemand() || pEntry->HasChilds() ) 2761 { 2762 rStateSet.AddState( AccessibleStateType::EXPANDABLE ); 2763 if ( IsExpanded( pEntry ) ) 2764 rStateSet.AddState( (sal_Int16)AccessibleStateType::EXPANDED ); 2765 } 2766 2767 if ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED ) 2768 rStateSet.AddState( AccessibleStateType::CHECKED ); 2769 if ( IsEntryVisible( pEntry ) ) 2770 rStateSet.AddState( AccessibleStateType::VISIBLE ); 2771 if ( IsSelected( pEntry ) ) 2772 rStateSet.AddState( AccessibleStateType::SELECTED ); 2773 if ( IsEnabled() ) 2774 { 2775 rStateSet.AddState( AccessibleStateType::ENABLED ); 2776 rStateSet.AddState( AccessibleStateType::FOCUSABLE ); 2777 rStateSet.AddState( AccessibleStateType::SELECTABLE ); 2778 SvViewDataEntry* pViewDataNewCur = 0; 2779 if( pEntry ) 2780 { 2781 pViewDataNewCur= GetViewDataEntry(pEntry); 2782 if(pViewDataNewCur->HasFocus()) 2783 rStateSet.AddState( AccessibleStateType::FOCUSED ); 2784 } 2785 } 2786 } 2787 2788 Rectangle SvTreeListBox::GetBoundingRect( SvLBoxEntry* pEntry ) 2789 { 2790 Point aPos = GetEntryPosition( pEntry ); 2791 Rectangle aRect = GetFocusRect( pEntry, aPos.Y() ); 2792 return aRect; 2793 } 2794 2795 void SvTreeListBox::EnableCellFocus() 2796 { 2797 pImp->EnableCellFocus(); 2798 } 2799 2800 void SvTreeListBox::CallImplEventListeners(sal_uLong nEvent, void* pData) 2801 { 2802 CallEventListeners(nEvent, pData); 2803 } 2804 2805 void SvTreeListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& rStateSet ) const 2806 { 2807 SvLBox::FillAccessibleStateSet( rStateSet ); 2808 } 2809 2810