/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svtools.hxx" #define _SVTREEBX_CXX #include #ifndef GCC #endif class TabBar; // #102891# ----------------------- #include #include #include #include #include #include #include #include using namespace ::com::sun::star::accessibility; /* Bugs/ToDo - Berechnung Rectangle beim Inplace-Editing (Bug bei manchen Fonts) - SetSpaceBetweenEntries: Offset wird in SetEntryHeight nicht beruecksichtigt */ #define TREEFLAG_FIXEDHEIGHT 0x0010 DBG_NAME(SvTreeListBox) #define SV_LBOX_DEFAULT_INDENT_PIXEL 20 SvTreeListBox::SvTreeListBox( Window* pParent, WinBits nWinStyle ) : SvLBox( pParent, nWinStyle ) { DBG_CTOR(SvTreeListBox,0); InitTreeView(); SetSublistOpenWithLeftRight(); } SvTreeListBox::SvTreeListBox( Window* pParent , const ResId& rResId ) : SvLBox( pParent,rResId ) { DBG_CTOR(SvTreeListBox,0); InitTreeView(); Resize(); SetSublistOpenWithLeftRight(); } void SvTreeListBox::InitTreeView() { DBG_CHKTHIS(SvTreeListBox,0); pCheckButtonData = NULL; pEdEntry = NULL; pEdItem = NULL; nEntryHeight = 0; pEdCtrl = NULL; nFirstSelTab = 0; nLastSelTab = 0; nFocusWidth = -1; nAllItemAccRoleType = 0; Link* pLink = new Link( LINK(this,SvTreeListBox, DefaultCompare) ); pLBoxImpl->m_pLink = pLink; nTreeFlags = TREEFLAG_RECALCTABS; nIndent = SV_LBOX_DEFAULT_INDENT_PIXEL; nEntryHeightOffs = SV_ENTRYHEIGHTOFFS_PIXEL; pImp = new SvImpLBox( this, GetModel(), GetStyle() ); aContextBmpMode = SVLISTENTRYFLAG_EXPANDED; nContextBmpWidthMax = 0; SetFont( GetFont() ); SetSpaceBetweenEntries( 0 ); SetLineColor(); InitSettings( sal_True, sal_True, sal_True ); ImplInitStyle(); SetTabs(); } SvTreeListBox::~SvTreeListBox() { DBG_DTOR(SvTreeListBox,0); pImp->CallEventListeners( VCLEVENT_OBJECT_DYING ); delete pImp; delete pLBoxImpl->m_pLink; ClearTabList(); } void SvTreeListBox::SetExtendedWinBits( ExtendedWinBits _nBits ) { pImp->SetExtendedWindowBits( _nBits ); } ExtendedWinBits SvTreeListBox::GetExtendedWinBits() const { return pImp->GetExtendedWindowBits(); } void SvTreeListBox::SetModel( SvLBoxTreeList* pNewModel ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->SetModel( pNewModel ); SvLBox::SetModel( pNewModel ); } void SvTreeListBox::DisconnectFromModel() { DBG_CHKTHIS(SvTreeListBox,0); SvLBox::DisconnectFromModel(); pImp->SetModel( GetModel() ); } sal_uInt16 SvTreeListBox::IsA() { DBG_CHKTHIS(SvTreeListBox,0); return SV_LISTBOX_ID_TREEBOX; } void SvTreeListBox::SetSublistOpenWithReturn( sal_Bool b ) { pImp->bSubLstOpRet = b; } sal_Bool SvTreeListBox::IsSublistOpenWithReturn() const { return pImp->bSubLstOpRet; } void SvTreeListBox::SetSublistOpenWithLeftRight( sal_Bool b ) { pImp->bSubLstOpLR = b; } sal_Bool SvTreeListBox::IsSublistOpenWithLeftRight() const { return pImp->bSubLstOpLR; } void SvTreeListBox::Resize() { DBG_CHKTHIS(SvTreeListBox,0); if( IsEditingActive() ) EndEditing( sal_True ); SvLBox::Resize(); pImp->Resize(); nFocusWidth = -1; pImp->ShowCursor( sal_False ); pImp->ShowCursor( sal_True ); } /* Faelle: A) Entries haben Bitmaps 0. Keine Buttons 1. Node-Buttons (optional auch an Root-Items) 2. Node-Buttons (optional auch an Root-Items) + CheckButton 3. CheckButton B) Entries haben keine Bitmaps (->ueber WindowBits wg. D&D !!!!!!) 0. Keine Buttons 1. Node-Buttons (optional auch an Root-Items) 2. Node-Buttons (optional auch an Root-Items) + CheckButton 3. CheckButton */ #define NO_BUTTONS 0 #define NODE_BUTTONS 1 #define NODE_AND_CHECK_BUTTONS 2 #define CHECK_BUTTONS 3 #define TABFLAGS_TEXT (SV_LBOXTAB_DYNAMIC | \ SV_LBOXTAB_ADJUST_LEFT | \ SV_LBOXTAB_EDITABLE | \ SV_LBOXTAB_SHOW_SELECTION) #define TABFLAGS_CONTEXTBMP (SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER) #define TABFLAGS_CHECKBTN (SV_LBOXTAB_DYNAMIC | \ SV_LBOXTAB_ADJUST_CENTER | \ SV_LBOXTAB_PUSHABLE) #define TAB_STARTPOS 2 // bei Aenderungen GetTextOffset beruecksichtigen void SvTreeListBox::SetTabs() { DBG_CHKTHIS(SvTreeListBox,0); if( IsEditingActive() ) EndEditing( sal_True ); nTreeFlags &= (~TREEFLAG_RECALCTABS); nFocusWidth = -1; const WinBits nStyle( GetStyle() ); sal_Bool bHasButtons = (nStyle & WB_HASBUTTONS)!=0; sal_Bool bHasButtonsAtRoot = (nStyle & (WB_HASLINESATROOT | WB_HASBUTTONSATROOT))!=0; long nStartPos = TAB_STARTPOS; long nNodeWidthPixel = GetExpandedNodeBmp().GetSizePixel().Width(); long nCheckWidth = 0; if( nTreeFlags & TREEFLAG_CHKBTN ) nCheckWidth = pCheckButtonData->aBmps[0].GetSizePixel().Width(); long nCheckWidthDIV2 = nCheckWidth / 2; long nContextWidth = nContextBmpWidthMax; long nContextWidthDIV2 = nContextWidth / 2; ClearTabList(); int nCase = NO_BUTTONS; if( !(nTreeFlags & TREEFLAG_CHKBTN) ) { if( bHasButtons ) nCase = NODE_BUTTONS; } else { if( bHasButtons ) nCase = NODE_AND_CHECK_BUTTONS; else nCase = CHECK_BUTTONS; } switch( nCase ) { case NO_BUTTONS : nStartPos += nContextWidthDIV2; // wg. Zentrierung AddTab( nStartPos, TABFLAGS_CONTEXTBMP ); nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp // Abstand setzen nur wenn Bitmaps da if( nContextBmpWidthMax ) nStartPos += 5; // Abstand Context-Bmp - Text AddTab( nStartPos, TABFLAGS_TEXT ); break; case NODE_BUTTONS : if( bHasButtonsAtRoot ) nStartPos += ( nIndent + (nNodeWidthPixel/2) ); else nStartPos += nContextWidthDIV2; AddTab( nStartPos, TABFLAGS_CONTEXTBMP ); nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp // Abstand setzen nur wenn Bitmaps da if( nContextBmpWidthMax ) nStartPos += 5; // Abstand Context-Bmp - Text AddTab( nStartPos, TABFLAGS_TEXT ); break; case NODE_AND_CHECK_BUTTONS : if( bHasButtonsAtRoot ) nStartPos += ( nIndent + nNodeWidthPixel ); else nStartPos += nCheckWidthDIV2; AddTab( nStartPos, TABFLAGS_CHECKBTN ); nStartPos += nCheckWidthDIV2; // rechter Rand des CheckButtons nStartPos += 3; // Abstand CheckButton Context-Bmp nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp AddTab( nStartPos, TABFLAGS_CONTEXTBMP ); nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp // Abstand setzen nur wenn Bitmaps da if( nContextBmpWidthMax ) nStartPos += 5; // Abstand Context-Bmp - Text AddTab( nStartPos, TABFLAGS_TEXT ); break; case CHECK_BUTTONS : nStartPos += nCheckWidthDIV2; AddTab( nStartPos, TABFLAGS_CHECKBTN ); nStartPos += nCheckWidthDIV2; // rechter Rand CheckButton nStartPos += 3; // Abstand CheckButton Context-Bmp nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp AddTab( nStartPos, TABFLAGS_CONTEXTBMP ); nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp // Abstand setzen nur wenn Bitmaps da if( nContextBmpWidthMax ) nStartPos += 5; // Abstand Context-Bmp - Text AddTab( nStartPos, TABFLAGS_TEXT ); break; } pImp->NotifyTabsChanged(); } void SvTreeListBox::InitEntry( SvLBoxEntry* pEntry, const XubString& aStr, const Image& aCollEntryBmp, const Image& aExpEntryBmp, SvLBoxButtonKind eButtonKind) { DBG_CHKTHIS(SvTreeListBox,0); SvLBoxButton* pButton; SvLBoxString* pString; SvLBoxContextBmp* pContextBmp; if( nTreeFlags & TREEFLAG_CHKBTN ) { pButton= new SvLBoxButton( pEntry,eButtonKind,0,pCheckButtonData ); pEntry->AddItem( pButton ); } pContextBmp= new SvLBoxContextBmp( pEntry,0, aCollEntryBmp,aExpEntryBmp, aContextBmpMode ); pEntry->AddItem( pContextBmp ); pString = new SvLBoxString( pEntry, 0, aStr ); pEntry->AddItem( pString ); } String SvTreeListBox::GetEntryText(SvLBoxEntry* pEntry) const { DBG_CHKTHIS(SvTreeListBox,0); DBG_ASSERT( pEntry, "SvTreeListBox::GetEntryText(): no entry" ); SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); DBG_ASSERT( pEntry, "SvTreeListBox::GetEntryText(): item not found" ); return pItem->GetText(); } String SvTreeListBox::GetEntryAltText( SvLBoxEntry* ) const { String tmp; return tmp; } String SvTreeListBox::GetEntryLongDescription( SvLBoxEntry* ) const { String tmp; return tmp; } String SvTreeListBox::SearchEntryTextWithHeadTitle( SvLBoxEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); DBG_ASSERT( pEntry, "SvTreeListBox::SearchEntryText(): no entry" ); String sRet; sal_uInt16 nCount = pEntry->ItemCount(); sal_uInt16 nCur = 0; sal_uInt16 nHeaderCur = 0; SvLBoxItem* pItem; while( nCur < nCount ) { // MT: SV_ITEM_ID_EXTENDRLBOXSTRING / GetExtendText() was in use in IA2 cws, but only used in sc: ScSolverOptionsString. Needed? pItem = pEntry->GetItem( nCur ); if ( (pItem->IsA() == SV_ITEM_ID_LBOXSTRING /* || pItem->IsA() == SV_ITEM_ID_EXTENDRLBOXSTRING */ ) && static_cast( pItem )->GetText().Len() > 0 ) { //want to the column header if( headString.Len() > 0) { xub_StrLen nEnd = headString.Search( sal_Unicode( '\t' ) ); if( nEnd == STRING_NOTFOUND ) { if(sRet.Len()>0) { sRet += ','; } if(headString.Len()>0) { sRet += headString ; sRet += ':' ; } } else { String aString=headString.GetToken(nHeaderCur, sal_Unicode( '\t' ) ); if(sRet.Len()>0) { sRet += ','; } if( aString.Len() > 0) { sRet += aString ; sRet += ':' ; } nHeaderCur++; } // if (pItem->IsA() == SV_ITEM_ID_LBOXSTRING) sRet += static_cast( pItem )->GetText(); // else // sRet += static_cast( pItem )->GetExtendText(); } else { // if (pItem->IsA() == SV_ITEM_ID_LBOXSTRING) sRet += static_cast( pItem )->GetText(); // else // sRet += static_cast( pItem )->GetExtendText(); sRet += ','; } //end want to the column header } nCur++; } if (sRet.Len() > 0) sRet = sRet.Erase(sRet.Len() - 1); return sRet; } String SvTreeListBox::SearchEntryText( SvLBoxEntry* pEntry ) const { DBG_CHKTHIS(SvTreeListBox,0); DBG_ASSERT( pEntry, "SvTreeListBox::SearchEntryText(): no entry" ); String sRet; sal_uInt16 nCount = pEntry->ItemCount(); sal_uInt16 nCur = 0; SvLBoxItem* pItem; while( nCur < nCount ) { pItem = pEntry->GetItem( nCur ); if ( pItem->IsA() == SV_ITEM_ID_LBOXSTRING && static_cast( pItem )->GetText().Len() > 0 ) { sRet = static_cast( pItem )->GetText(); break; } nCur++; } return sRet; } const Image& SvTreeListBox::GetExpandedEntryBmp(SvLBoxEntry* pEntry, BmpColorMode _eMode) const { DBG_CHKTHIS(SvTreeListBox,0); DBG_ASSERT(pEntry,"Entry?"); SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); DBG_ASSERT(pItem,"GetContextBmp:Item not found"); return pItem->GetBitmap2( _eMode ); } const Image& SvTreeListBox::GetCollapsedEntryBmp( SvLBoxEntry* pEntry, BmpColorMode _eMode ) const { DBG_CHKTHIS(SvTreeListBox,0); DBG_ASSERT(pEntry,"Entry?"); SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); DBG_ASSERT(pItem,"GetContextBmp:Item not found"); return pItem->GetBitmap1( _eMode ); } IMPL_LINK_INLINE_START( SvTreeListBox, CheckButtonClick, SvLBoxButtonData *, pData ) { DBG_CHKTHIS(SvTreeListBox,0); pHdlEntry = pData->GetActEntry(); CheckButtonHdl(); return 0; } IMPL_LINK_INLINE_END( SvTreeListBox, CheckButtonClick, SvLBoxButtonData *, pData ) SvLBoxEntry* SvTreeListBox::InsertEntry( const XubString& aText,SvLBoxEntry* pParent, sal_Bool bChildsOnDemand, sal_uLong nPos, void* pUser, SvLBoxButtonKind eButtonKind ) { DBG_CHKTHIS(SvTreeListBox,0); nTreeFlags |= TREEFLAG_MANINS; const Image& rDefExpBmp = pImp->GetDefaultEntryExpBmp( ); const Image& rDefColBmp = pImp->GetDefaultEntryColBmp( ); aCurInsertedExpBmp = rDefExpBmp; aCurInsertedColBmp = rDefColBmp; SvLBoxEntry* pEntry = CreateEntry(); pEntry->SetUserData( pUser ); InitEntry( pEntry, aText, rDefColBmp, rDefExpBmp, eButtonKind ); pEntry->EnableChildsOnDemand( bChildsOnDemand ); // Add the HC versions of the default images SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) ); if( pBmpItem ) { pBmpItem->SetBitmap1( pImp->GetDefaultEntryColBmp( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST ); pBmpItem->SetBitmap2( pImp->GetDefaultEntryExpBmp( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST ); } if( !pParent ) SvLBox::Insert( pEntry, nPos ); else SvLBox::Insert( pEntry, pParent, nPos ); aPrevInsertedExpBmp = rDefExpBmp; aPrevInsertedColBmp = rDefColBmp; nTreeFlags &= (~TREEFLAG_MANINS); return pEntry; } SvLBoxEntry* SvTreeListBox::InsertEntry( const XubString& aText, const Image& aExpEntryBmp, const Image& aCollEntryBmp, SvLBoxEntry* pParent, sal_Bool bChildsOnDemand, sal_uLong nPos, void* pUser, SvLBoxButtonKind eButtonKind ) { DBG_CHKTHIS(SvTreeListBox,0); nTreeFlags |= TREEFLAG_MANINS; aCurInsertedExpBmp = aExpEntryBmp; aCurInsertedColBmp = aCollEntryBmp; SvLBoxEntry* pEntry = CreateEntry(); pEntry->SetUserData( pUser ); InitEntry( pEntry, aText, aCollEntryBmp, aExpEntryBmp, eButtonKind ); pEntry->EnableChildsOnDemand( bChildsOnDemand ); if( !pParent ) SvLBox::Insert( pEntry, nPos ); else SvLBox::Insert( pEntry, pParent, nPos ); aPrevInsertedExpBmp = aExpEntryBmp; aPrevInsertedColBmp = aCollEntryBmp; nTreeFlags &= (~TREEFLAG_MANINS); return pEntry; } void SvTreeListBox::SetEntryText( SvLBoxEntry* pEntry, const XubString& aStr) { DBG_CHKTHIS(SvTreeListBox,0); SvLBoxString* pItem = (SvLBoxString*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); DBG_ASSERT(pItem,"SetText:Item not found"); pItem->SetText( pEntry, aStr ); pItem->InitViewData( this, pEntry, 0 ); GetModel()->InvalidateEntry( pEntry ); } void SvTreeListBox::SetExpandedEntryBmp( SvLBoxEntry* pEntry, const Image& aBmp, BmpColorMode _eMode ) { DBG_CHKTHIS(SvTreeListBox,0); SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); DBG_ASSERT(pItem,"SetExpBmp:Item not found"); pItem->SetBitmap2( aBmp, _eMode ); GetModel()->InvalidateEntry( pEntry ); SetEntryHeight( pEntry ); Size aSize = aBmp.GetSizePixel(); // #97680# --------------- short nWidth = pImp->UpdateContextBmpWidthVector( pEntry, (short)aSize.Width() ); if( nWidth > nContextBmpWidthMax ) { nContextBmpWidthMax = nWidth; SetTabs(); } } void SvTreeListBox::SetCollapsedEntryBmp(SvLBoxEntry* pEntry,const Image& aBmp, BmpColorMode _eMode ) { DBG_CHKTHIS(SvTreeListBox,0); SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); DBG_ASSERT(pItem,"SetExpBmp:Item not found"); pItem->SetBitmap1( aBmp, _eMode ); GetModel()->InvalidateEntry( pEntry ); SetEntryHeight( pEntry ); Size aSize = aBmp.GetSizePixel(); // #97680# ----------- short nWidth = pImp->UpdateContextBmpWidthVector( pEntry, (short)aSize.Width() ); if( nWidth > nContextBmpWidthMax ) { nContextBmpWidthMax = nWidth; SetTabs(); } } void SvTreeListBox::ImpEntryInserted( SvLBoxEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); SvLBoxEntry* pParent = (SvLBoxEntry*)pModel->GetParent( pEntry ); if( pParent ) { sal_uInt16 nFlags = pParent->GetFlags(); nFlags &= ~SV_ENTRYFLAG_NO_NODEBMP; pParent->SetFlags( nFlags ); } if(!((nTreeFlags & TREEFLAG_MANINS) && (aPrevInsertedExpBmp == aCurInsertedExpBmp) && (aPrevInsertedColBmp == aCurInsertedColBmp) )) { Size aSize = GetCollapsedEntryBmp( pEntry ).GetSizePixel(); if( aSize.Width() > nContextBmpWidthMax ) { nContextBmpWidthMax = (short)aSize.Width(); nTreeFlags |= TREEFLAG_RECALCTABS; } aSize = GetExpandedEntryBmp( pEntry ).GetSizePixel(); if( aSize.Width() > nContextBmpWidthMax ) { nContextBmpWidthMax = (short)aSize.Width(); nTreeFlags |= TREEFLAG_RECALCTABS; } } SetEntryHeight( (SvLBoxEntry*)pEntry ); } void SvTreeListBox::SetCheckButtonState( SvLBoxEntry* pEntry, SvButtonState eState) { DBG_CHKTHIS(SvTreeListBox,0); if( nTreeFlags & TREEFLAG_CHKBTN ) { SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON)); if(!(pItem && pItem->CheckModification())) return ; switch( eState ) { case SV_BUTTON_CHECKED: pItem->SetStateChecked(); break; case SV_BUTTON_UNCHECKED: pItem->SetStateUnchecked(); break; case SV_BUTTON_TRISTATE: pItem->SetStateTristate(); break; } InvalidateEntry( pEntry ); } } SvButtonState SvTreeListBox::GetCheckButtonState( SvLBoxEntry* pEntry ) const { DBG_CHKTHIS(SvTreeListBox,0); SvButtonState eState = SV_BUTTON_UNCHECKED; if( nTreeFlags & TREEFLAG_CHKBTN ) { SvLBoxButton* pItem = (SvLBoxButton*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON)); if(!pItem) return SV_BUTTON_TRISTATE; sal_uInt16 nButtonFlags = pItem->GetButtonFlags(); eState = pCheckButtonData->ConvertToButtonState( nButtonFlags ); } return eState; } void SvTreeListBox::CheckButtonHdl() { DBG_CHKTHIS(SvTreeListBox,0); aCheckButtonHdl.Call( this ); if ( pCheckButtonData ) pImp->CallEventListeners( VCLEVENT_CHECKBOX_TOGGLE, (void*)pCheckButtonData->GetActEntry() ); } // ********************************************************************* // ********************************************************************* // // TODO: Momentan werden die Daten so geklont, dass sie dem // Standard-TreeView-Format entsprechen. Hier sollte eigentlich // das Model als Referenz dienen. Dies fuehrt dazu, dass // SvLBoxEntry::Clone _nicht_ gerufen wird, sondern nur dessen // Basisklasse SvListEntry // SvLBoxEntry* SvTreeListBox::CloneEntry( SvLBoxEntry* pSource ) { DBG_CHKTHIS(SvTreeListBox,0); XubString aStr; Image aCollEntryBmp; Image aExpEntryBmp; SvLBoxButtonKind eButtonKind = SvLBoxButtonKind_enabledCheckbox; SvLBoxString* pStringItem = (SvLBoxString*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXSTRING)); if( pStringItem ) aStr = pStringItem->GetText(); SvLBoxContextBmp* pBmpItem = (SvLBoxContextBmp*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP)); if( pBmpItem ) { aCollEntryBmp = pBmpItem->GetBitmap1( BMP_COLOR_NORMAL ); aExpEntryBmp = pBmpItem->GetBitmap2( BMP_COLOR_NORMAL ); } SvLBoxButton* pButtonItem = (SvLBoxButton*)(pSource->GetFirstItem(SV_ITEM_ID_LBOXBUTTON)); if( pButtonItem ) eButtonKind = pButtonItem->GetKind(); SvLBoxEntry* pClone = CreateEntry(); InitEntry( pClone, aStr, aCollEntryBmp, aExpEntryBmp, eButtonKind ); pClone->SvListEntry::Clone( pSource ); pClone->EnableChildsOnDemand( pSource->HasChildsOnDemand() ); pClone->SetUserData( pSource->GetUserData() ); if ( pBmpItem ) { SvLBoxContextBmp* pCloneBitmap = static_cast< SvLBoxContextBmp* >( pClone->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) ); if ( pCloneBitmap ) { pCloneBitmap->SetBitmap1( pBmpItem->GetBitmap1( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST ); pCloneBitmap->SetBitmap2( pBmpItem->GetBitmap2( BMP_COLOR_HIGHCONTRAST ), BMP_COLOR_HIGHCONTRAST ); } } return pClone; } // ********************************************************************* // ********************************************************************* void SvTreeListBox::ShowExpandBitmapOnCursor( sal_Bool bYes ) { DBG_CHKTHIS(SvTreeListBox,0); if( bYes ) aContextBmpMode = SVLISTENTRYFLAG_FOCUSED; else aContextBmpMode = SVLISTENTRYFLAG_EXPANDED; } void SvTreeListBox::SetIndent( short nNewIndent ) { DBG_CHKTHIS(SvTreeListBox,0); nIndent = nNewIndent; SetTabs(); if( IsUpdateMode() ) Invalidate(); } const Image& SvTreeListBox::GetDefaultExpandedEntryBmp( BmpColorMode _eMode ) const { return pImp->GetDefaultEntryExpBmp( _eMode ); } const Image& SvTreeListBox::GetDefaultCollapsedEntryBmp( BmpColorMode _eMode ) const { return pImp->GetDefaultEntryColBmp( _eMode ); } void SvTreeListBox::SetDefaultExpandedEntryBmp( const Image& aBmp, BmpColorMode _eMode ) { DBG_CHKTHIS(SvTreeListBox,0); Size aSize = aBmp.GetSizePixel(); if( aSize.Width() > nContextBmpWidthMax ) nContextBmpWidthMax = (short)aSize.Width(); SetTabs(); pImp->SetDefaultEntryExpBmp( aBmp, _eMode ); } void SvTreeListBox::SetDefaultCollapsedEntryBmp( const Image& aBmp, BmpColorMode _eMode ) { DBG_CHKTHIS(SvTreeListBox,0); Size aSize = aBmp.GetSizePixel(); if( aSize.Width() > nContextBmpWidthMax ) nContextBmpWidthMax = (short)aSize.Width(); SetTabs(); pImp->SetDefaultEntryColBmp( aBmp, _eMode ); } void SvTreeListBox::EnableCheckButton( SvLBoxButtonData* pData ) { DBG_CHKTHIS(SvTreeListBox,0); DBG_ASSERT(!GetEntryCount(),"EnableCheckButton: Entry count != 0"); if( !pData ) nTreeFlags &= (~TREEFLAG_CHKBTN); else { SetCheckButtonData( pData ); nTreeFlags |= TREEFLAG_CHKBTN; pData->SetLink( LINK(this, SvTreeListBox, CheckButtonClick)); } SetTabs(); if( IsUpdateMode() ) Invalidate(); } void SvTreeListBox::SetCheckButtonData( SvLBoxButtonData* pData ) { DBG_CHKTHIS(SvTreeListBox,0); if ( pData ) pCheckButtonData = pData; } const Image& SvTreeListBox::GetDefaultExpandedNodeImage( BmpColorMode _eMode ) { return SvImpLBox::GetDefaultExpandedNodeImage( _eMode ); } const Image& SvTreeListBox::GetDefaultCollapsedNodeImage( BmpColorMode _eMode ) { return SvImpLBox::GetDefaultCollapsedNodeImage( _eMode ); } void SvTreeListBox::SetNodeBitmaps( const Image& rCollapsedNodeBmp, const Image& rExpandedNodeBmp, BmpColorMode _eMode ) { DBG_CHKTHIS(SvTreeListBox,0); SetExpandedNodeBmp( rExpandedNodeBmp, _eMode ); SetCollapsedNodeBmp( rCollapsedNodeBmp, _eMode ); SetTabs(); } void SvTreeListBox::SetDontKnowNodeBitmap( const Image& rDontKnowBmp, BmpColorMode _eMode ) { pImp->SetDontKnowNodeBmp( rDontKnowBmp, _eMode ); } sal_Bool SvTreeListBox::EditingEntry( SvLBoxEntry*, Selection& ) { DBG_CHKTHIS(SvTreeListBox,0); return sal_True; } sal_Bool SvTreeListBox::EditedEntry( SvLBoxEntry* /*pEntry*/,const XubString& /*rNewText*/) { DBG_CHKTHIS(SvTreeListBox,0); return sal_True; } void SvTreeListBox::EnableInplaceEditing( sal_Bool bOn ) { DBG_CHKTHIS(SvTreeListBox,0); SvLBox::EnableInplaceEditing( bOn ); } void SvTreeListBox::KeyInput( const KeyEvent& rKEvt ) { DBG_CHKTHIS(SvTreeListBox,0); // unter OS/2 bekommen wir auch beim Editieren Key-Up/Down if( IsEditingActive() ) return; nImpFlags |= SVLBOX_IS_TRAVELSELECT; #ifdef OVDEBUG sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); switch ( nCode ) { case KEY_F1: { SvLBoxEntry* pEntry = First(); pEntry = NextVisible( pEntry ); SetEntryText( pEntry, "SetEntryText" ); Sound::Beep(); } break; } #endif if( !pImp->KeyInput( rKEvt ) ) SvLBox::KeyInput( rKEvt ); nImpFlags &= ~SVLBOX_IS_TRAVELSELECT; } void SvTreeListBox::RequestingChilds( SvLBoxEntry* pParent ) { DBG_CHKTHIS(SvTreeListBox,0); if( !pParent->HasChilds() ) InsertEntry( String::CreateFromAscii(""), pParent, sal_False, LIST_APPEND ); } void SvTreeListBox::GetFocus() { DBG_CHKTHIS(SvTreeListBox,0); //Solution:If there is no item in the tree,draw focus. if( !SvLBox::First()) { Invalidate(); } pImp->GetFocus(); SvLBox::GetFocus(); SvLBoxEntry* pEntry = FirstSelected(); if ( !pEntry ) { pEntry = pImp->GetCurrentEntry(); } if (pImp->pCursor) { if (pEntry != pImp->pCursor) pEntry = pImp->pCursor; } if ( pEntry ) pImp->CallEventListeners( VCLEVENT_LISTBOX_TREEFOCUS, pEntry ); } void SvTreeListBox::LoseFocus() { DBG_CHKTHIS(SvTreeListBox,0); //Solution:If there is no item in the tree,delete visual focus. if( !SvLBox::First()) { Invalidate(); } pImp->LoseFocus(); SvLBox::LoseFocus(); } void SvTreeListBox::ModelHasCleared() { DBG_CHKTHIS(SvTreeListBox,0); pImp->pCursor = 0; //sonst Absturz beim Inplace-Editieren im GetFocus delete pEdCtrl; pEdCtrl = NULL; pImp->Clear(); nFocusWidth = -1; nContextBmpWidthMax = 0; SetDefaultExpandedEntryBmp( GetDefaultExpandedEntryBmp() ); SetDefaultCollapsedEntryBmp( GetDefaultCollapsedEntryBmp() ); if( !(nTreeFlags & TREEFLAG_FIXEDHEIGHT )) nEntryHeight = 0; AdjustEntryHeight( GetFont() ); AdjustEntryHeight( GetDefaultExpandedEntryBmp() ); AdjustEntryHeight( GetDefaultCollapsedEntryBmp() ); SvLBox::ModelHasCleared(); // if( IsUpdateMode() ) // Invalidate(); } void SvTreeListBox::ShowTargetEmphasis( SvLBoxEntry* pEntry, sal_Bool /* bShow */ ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->PaintDDCursor( pEntry ); } void SvTreeListBox::ScrollOutputArea( short nDeltaEntries ) { DBG_CHKTHIS(SvTreeListBox,0); if( !nDeltaEntries || !pImp->aVerSBar.IsVisible() ) return; long nThumb = pImp->aVerSBar.GetThumbPos(); long nMax = pImp->aVerSBar.GetRange().Max(); NotifyBeginScroll(); if( nDeltaEntries < 0 ) { // das Fenster nach oben verschieben nDeltaEntries *= -1; long nVis = pImp->aVerSBar.GetVisibleSize(); long nTemp = nThumb + nVis; if( nDeltaEntries > (nMax - nTemp) ) nDeltaEntries = (short)(nMax - nTemp); pImp->PageDown( (sal_uInt16)nDeltaEntries ); } else { if( nDeltaEntries > nThumb ) nDeltaEntries = (short)nThumb; pImp->PageUp( (sal_uInt16)nDeltaEntries ); } pImp->SyncVerThumb(); NotifyEndScroll(); } void SvTreeListBox::SetSelectionMode( SelectionMode eSelectMode ) { DBG_CHKTHIS(SvTreeListBox,0); SvLBox::SetSelectionMode( eSelectMode ); pImp->SetSelectionMode( eSelectMode ); } void SvTreeListBox::SetDragDropMode( DragDropMode nDDMode ) { DBG_CHKTHIS(SvTreeListBox,0); SvLBox::SetDragDropMode( nDDMode ); pImp->SetDragDropMode( nDDMode ); } short SvTreeListBox::GetHeightOffset(const Image& rBmp, Size& aSizeLogic ) { DBG_CHKTHIS(SvTreeListBox,0); short nOffset = 0; aSizeLogic = rBmp.GetSizePixel(); if( GetEntryHeight() > aSizeLogic.Height() ) nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2; return nOffset; } short SvTreeListBox::GetHeightOffset(const Font& /* rFont */, Size& aSizeLogic ) { DBG_CHKTHIS(SvTreeListBox,0); short nOffset = 0; aSizeLogic = Size(GetTextWidth('X'), GetTextHeight()); if( GetEntryHeight() > aSizeLogic.Height() ) nOffset = ( GetEntryHeight() - (short)aSizeLogic.Height()) / 2; return nOffset; } void SvTreeListBox::SetEntryHeight( SvLBoxEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); short nHeight, nHeightMax=0; sal_uInt16 nCount = pEntry->ItemCount(); sal_uInt16 nCur = 0; SvViewDataEntry* pViewData = GetViewDataEntry( pEntry ); while( nCur < nCount ) { SvLBoxItem* pItem = pEntry->GetItem( nCur ); nHeight = (short)(pItem->GetSize( pViewData, nCur ).Height()); if( nHeight > nHeightMax ) nHeightMax = nHeight; nCur++; } if( nHeightMax > nEntryHeight ) { nEntryHeight = nHeightMax; SvLBox::SetFont( GetFont() ); pImp->SetEntryHeight( nHeightMax ); } } void SvTreeListBox::SetEntryHeight( short nHeight, sal_Bool bAlways ) { DBG_CHKTHIS(SvTreeListBox,0); if( bAlways || nHeight > nEntryHeight ) { nEntryHeight = nHeight; if( nEntryHeight ) nTreeFlags |= TREEFLAG_FIXEDHEIGHT; else nTreeFlags &= ~TREEFLAG_FIXEDHEIGHT; SvLBox::SetFont( GetFont() ); pImp->SetEntryHeight( nHeight ); } } void SvTreeListBox::AdjustEntryHeight( const Image& rBmp ) { DBG_CHKTHIS(SvTreeListBox,0); Size aSize; GetHeightOffset( rBmp, aSize ); if( aSize.Height() > nEntryHeight ) { nEntryHeight = (short)aSize.Height() + nEntryHeightOffs; pImp->SetEntryHeight( nEntryHeight ); } } void SvTreeListBox::AdjustEntryHeight( const Font& rFont ) { DBG_CHKTHIS(SvTreeListBox,0); Size aSize; GetHeightOffset( rFont, aSize ); if( aSize.Height() > nEntryHeight ) { nEntryHeight = (short)aSize.Height() + nEntryHeightOffs; pImp->SetEntryHeight( nEntryHeight ); } } sal_Bool SvTreeListBox::Expand( SvLBoxEntry* pParent ) { DBG_CHKTHIS(SvTreeListBox,0); pHdlEntry = pParent; sal_Bool bExpanded = sal_False; sal_uInt16 nFlags; if( pParent->HasChildsOnDemand() ) RequestingChilds( pParent ); if( pParent->HasChilds() ) { nImpFlags |= SVLBOX_IS_EXPANDING; if( ExpandingHdl() ) { bExpanded = sal_True; SvListView::Expand( pParent ); pImp->EntryExpanded( pParent ); pHdlEntry = pParent; ExpandedHdl(); } nFlags = pParent->GetFlags(); nFlags &= ~SV_ENTRYFLAG_NO_NODEBMP; nFlags |= SV_ENTRYFLAG_HAD_CHILDREN; pParent->SetFlags( nFlags ); } else { nFlags = pParent->GetFlags(); nFlags |= SV_ENTRYFLAG_NO_NODEBMP; pParent->SetFlags( nFlags ); GetModel()->InvalidateEntry( pParent ); // neu zeichnen } // --> OD 2009-04-01 #i92103# if ( bExpanded ) { pImp->CallEventListeners( VCLEVENT_ITEM_EXPANDED, pParent ); } // <-- return bExpanded; } sal_Bool SvTreeListBox::Collapse( SvLBoxEntry* pParent ) { DBG_CHKTHIS(SvTreeListBox,0); nImpFlags &= ~SVLBOX_IS_EXPANDING; pHdlEntry = pParent; sal_Bool bCollapsed = sal_False; if( ExpandingHdl() ) { bCollapsed = sal_True; pImp->CollapsingEntry( pParent ); SvListView::Collapse( pParent ); pImp->EntryCollapsed( pParent ); pHdlEntry = pParent; ExpandedHdl(); } // --> OD 2009-04-01 #i92103# if ( bCollapsed ) { pImp->CallEventListeners( VCLEVENT_ITEM_COLLAPSED, pParent ); } // <-- return bCollapsed; } sal_Bool SvTreeListBox::Select( SvLBoxEntry* pEntry, sal_Bool bSelect ) { DBG_CHKTHIS(SvTreeListBox,0); DBG_ASSERT(pEntry,"Select: Null-Ptr"); sal_Bool bRetVal = SvListView::Select( pEntry, bSelect ); DBG_ASSERT(IsSelected(pEntry)==bSelect,"Select failed"); if( bRetVal ) { pImp->EntrySelected( pEntry, bSelect ); pHdlEntry = pEntry; if( bSelect ) { SelectHdl(); // pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry ); CallEventListeners( VCLEVENT_LISTBOX_TREESELECT, pEntry); } else DeselectHdl(); } return bRetVal; } sal_uLong SvTreeListBox::SelectChilds( SvLBoxEntry* pParent, sal_Bool bSelect ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->DestroyAnchor(); sal_uLong nRet = 0; if( !pParent->HasChilds() ) return 0; sal_uInt16 nRefDepth = pModel->GetDepth( pParent ); SvLBoxEntry* pChild = FirstChild( pParent ); do { nRet++; Select( pChild, bSelect ); pChild = Next( pChild ); } while( pChild && pModel->GetDepth( pChild ) > nRefDepth ); return nRet; } void SvTreeListBox::SelectAll( sal_Bool bSelect, sal_Bool ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->SelAllDestrAnch( bSelect, sal_True, // Anker loeschen, sal_True ); // auch bei SINGLE_SELECTION den Cursor deselektieren } void SvTreeListBox::ModelHasInsertedTree( SvListEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); sal_uInt16 nRefDepth = pModel->GetDepth( (SvLBoxEntry*)pEntry ); SvLBoxEntry* pTmp = (SvLBoxEntry*)pEntry; do { ImpEntryInserted( pTmp ); pTmp = Next( pTmp ); } while( pTmp && nRefDepth < pModel->GetDepth( pTmp ) ); pImp->TreeInserted( (SvLBoxEntry*)pEntry ); } void SvTreeListBox::ModelHasInserted( SvListEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); ImpEntryInserted( (SvLBoxEntry*)pEntry ); pImp->EntryInserted( (SvLBoxEntry*)pEntry ); } void SvTreeListBox::ModelIsMoving(SvListEntry* pSource, SvListEntry* /* pTargetParent */, sal_uLong /* nChildPos */ ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->MovingEntry( (SvLBoxEntry*)pSource ); } void SvTreeListBox::ModelHasMoved( SvListEntry* pSource ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->EntryMoved( (SvLBoxEntry*)pSource ); } void SvTreeListBox::ModelIsRemoving( SvListEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); if(pEdEntry == pEntry) pEdEntry = NULL; pImp->RemovingEntry( (SvLBoxEntry*)pEntry ); NotifyRemoving( (SvLBoxEntry*)pEntry ); } void SvTreeListBox::ModelHasRemoved( SvListEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); if ( pEntry == pHdlEntry) pHdlEntry = NULL; pImp->EntryRemoved(); } void SvTreeListBox::SetCollapsedNodeBmp( const Image& rBmp, BmpColorMode _eMode ) { DBG_CHKTHIS(SvTreeListBox,0); AdjustEntryHeight( rBmp ); pImp->SetCollapsedNodeBmp( rBmp, _eMode ); } void SvTreeListBox::SetExpandedNodeBmp( const Image& rBmp, BmpColorMode _eMode ) { DBG_CHKTHIS(SvTreeListBox,0); AdjustEntryHeight( rBmp ); pImp->SetExpandedNodeBmp( rBmp, _eMode ); } void SvTreeListBox::SetFont( const Font& rFont ) { DBG_CHKTHIS(SvTreeListBox,0); Font aTempFont( rFont ); aTempFont.SetTransparent( sal_True ); Control::SetFont( aTempFont ); AdjustEntryHeight( aTempFont ); // immer Invalidieren, sonst fallen wir // bei SetEntryHeight auf die Nase RecalcViewData(); } void SvTreeListBox::Paint( const Rectangle& rRect ) { DBG_CHKTHIS(SvTreeListBox,0); SvLBox::Paint( rRect ); if( nTreeFlags & TREEFLAG_RECALCTABS ) SetTabs(); pImp->Paint( rRect ); //Solution:Add visual focus draw if( !SvLBox::First() ) { if( HasFocus() ) { long tempHeight = GetTextHeight(); Rectangle tempRect( Point(0,0),Size(GetSizePixel().Width(),tempHeight) ); ShowFocus(tempRect); } else{ HideFocus(); } } } void SvTreeListBox::MouseButtonDown( const MouseEvent& rMEvt ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->MouseButtonDown( rMEvt ); } void SvTreeListBox::MouseButtonUp( const MouseEvent& rMEvt ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->MouseButtonUp( rMEvt ); } void SvTreeListBox::MouseMove( const MouseEvent& rMEvt ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->MouseMove( rMEvt ); } void SvTreeListBox::SetUpdateMode( sal_Bool bUpdate ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->SetUpdateMode( bUpdate ); } void SvTreeListBox::SetUpdateModeFast( sal_Bool bUpdate ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->SetUpdateModeFast( bUpdate ); } void SvTreeListBox::SetSpaceBetweenEntries( short nOffsLogic ) { DBG_CHKTHIS(SvTreeListBox,0); if( nOffsLogic != nEntryHeightOffs ) { nEntryHeight = nEntryHeight - nEntryHeightOffs; nEntryHeightOffs = (short)nOffsLogic; nEntryHeight = nEntryHeight + nOffsLogic; AdjustEntryHeight( GetFont() ); RecalcViewData(); pImp->SetEntryHeight( nEntryHeight ); } } void SvTreeListBox::SetCursor( SvLBoxEntry* pEntry, sal_Bool bForceNoSelect ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->SetCursor(pEntry, bForceNoSelect); } void SvTreeListBox::SetCurEntry( SvLBoxEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); pImp->SetCurEntry( pEntry ); } Image SvTreeListBox::GetCollapsedNodeBmp( BmpColorMode _eMode ) const { return pImp->GetCollapsedNodeBmp( _eMode ); } Image SvTreeListBox::GetExpandedNodeBmp( BmpColorMode _eMode ) const { return pImp->GetExpandedNodeBmp( _eMode ); } Point SvTreeListBox::GetEntryPosition( SvLBoxEntry* pEntry ) const { return pImp->GetEntryPosition( pEntry ); } void SvTreeListBox::ShowEntry( SvLBoxEntry* pEntry ) { MakeVisible( pEntry ); } void SvTreeListBox::MakeVisible( SvLBoxEntry* pEntry ) { pImp->MakeVisible(pEntry); } void SvTreeListBox::MakeVisible( SvLBoxEntry* pEntry, sal_Bool bMoveToTop ) { pImp->MakeVisible( pEntry, bMoveToTop ); } void SvTreeListBox::ModelHasEntryInvalidated( SvListEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); // die einzelnen Items des Entries reinitialisieren SvLBox::ModelHasEntryInvalidated( pEntry ); // repainten pImp->InvalidateEntry( (SvLBoxEntry*)pEntry ); } void SvTreeListBox::EditItemText( SvLBoxEntry* pEntry, SvLBoxString* pItem, const Selection& rSelection ) { DBG_CHKTHIS(SvTreeListBox,0); DBG_ASSERT(pEntry&&pItem,"EditItemText: Bad params"); if( IsSelected( pEntry )) { pImp->ShowCursor( sal_False ); SvListView::Select( pEntry, sal_False ); PaintEntry( pEntry ); SvListView::Select( pEntry, sal_True ); pImp->ShowCursor( sal_True ); } pEdEntry = pEntry; pEdItem = pItem; SvLBoxTab* pTab = GetTab( pEntry, pItem ); DBG_ASSERT(pTab,"EditItemText:Tab not found"); Size aItemSize( pItem->GetSize(this, pEntry) ); Point aPos = GetEntryPosition( pEntry ); aPos.Y() += ( nEntryHeight - aItemSize.Height() ) / 2; aPos.X() = GetTabPos( pEntry, pTab ); long nOutputWidth = pImp->GetOutputSize().Width(); Size aSize( nOutputWidth - aPos.X(), aItemSize.Height() ); sal_uInt16 nPos = aTabs.GetPos( pTab ); if( nPos+1 < aTabs.Count() ) { SvLBoxTab* pRightTab = (SvLBoxTab*)aTabs.GetObject( nPos + 1 ); long nRight = GetTabPos( pEntry, pRightTab ); if( nRight <= nOutputWidth ) aSize.Width() = nRight - aPos.X(); } Point aOrigin( GetMapMode().GetOrigin() ); aPos += aOrigin; // in Win-Koord umrechnen aSize.Width() -= aOrigin.X(); Rectangle aRect( aPos, aSize ); #ifdef OS2 // Platz lassen fuer WB_BORDER aRect.Left() -= 2; aRect.Top() -= 3; aRect.Bottom() += 3; #endif EditText( pItem->GetText(), aRect, rSelection ); } void SvTreeListBox::CancelEditing() { DBG_CHKTHIS(SvTreeListBox,0); SvLBox::CancelTextEditing(); } void SvTreeListBox::EditEntry( SvLBoxEntry* pEntry ) { pImp->aEditClickPos = Point( -1, -1 ); ImplEditEntry( pEntry ); } void SvTreeListBox::ImplEditEntry( SvLBoxEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); if( IsEditingActive() ) EndEditing(); if( !pEntry ) pEntry = GetCurEntry(); if( pEntry ) { long nClickX = pImp->aEditClickPos.X(); bool bIsMouseTriggered = nClickX >= 0; SvLBoxString* pItem = NULL; sal_uInt16 nCount = pEntry->ItemCount(); for( sal_uInt16 i = 0 ; i < nCount ; i++ ) { SvLBoxItem* pTmpItem = pEntry->GetItem( i ); if( pTmpItem->IsA() != SV_ITEM_ID_LBOXSTRING ) continue; SvLBoxTab* pTab = GetTab( pEntry, pTmpItem ); long nTabPos = pTab->GetPos(); long nNextTabPos = -1; if( i < nCount - 1 ) { SvLBoxItem* pNextItem = pEntry->GetItem( i + 1 ); SvLBoxTab* pNextTab = GetTab( pEntry, pNextItem ); nNextTabPos = pNextTab->GetPos(); } if( pTab && pTab->IsEditable() ) { if( !bIsMouseTriggered || (nClickX > nTabPos && (nNextTabPos == -1 || nClickX < nNextTabPos ) ) ) { pItem = static_cast( pTmpItem ); break; } } } Selection aSel( SELECTION_MIN, SELECTION_MAX ); if( pItem && EditingEntry( pEntry, aSel ) ) { SelectAll( sal_False ); MakeVisible( pEntry ); EditItemText( pEntry, pItem, aSel ); } } } sal_Bool SvTreeListBox::AreChildrenTransient() const { return pImp->AreChildrenTransient(); } void SvTreeListBox::SetChildrenNotTransient() { pImp->SetChildrenNotTransient(); } void SvTreeListBox::EditedText( const XubString& rStr ) { DBG_CHKTHIS(SvTreeListBox,0); if(pEdEntry) // we have to check if this entry is null that means that it is removed while editing { Point aPos = GetEntryPosition( pEdEntry ); if( EditedEntry( pEdEntry, rStr ) ) { ((SvLBoxString*)pEdItem)->SetText( pEdEntry, rStr ); pModel->InvalidateEntry( pEdEntry ); } //if( GetSelectionMode() == SINGLE_SELECTION ) //{ if( GetSelectionCount() == 0 ) Select( pEdEntry ); if( GetSelectionMode() == MULTIPLE_SELECTION && !GetCurEntry() ) SetCurEntry( pEdEntry ); //} } } void SvTreeListBox::EditingRequest( SvLBoxEntry* pEntry, SvLBoxItem* pItem, const Point& ) { DBG_CHKTHIS(SvTreeListBox,0); if( IsEditingActive() ) EndEditing(); if( pItem->IsA() == SV_ITEM_ID_LBOXSTRING ) { Selection aSel( SELECTION_MIN, SELECTION_MAX ); if( EditingEntry( pEntry, aSel ) ) { SelectAll( sal_False ); EditItemText( pEntry, (SvLBoxString*)pItem, aSel ); } } } SvLBoxEntry* SvTreeListBox::GetDropTarget( const Point& rPos ) { DBG_CHKTHIS(SvTreeListBox,0); // Scrollen if( rPos.Y() < 12 ) { SvLBox::ImplShowTargetEmphasis( SvLBox::pTargetEntry, sal_False ); ScrollOutputArea( +1 ); } else { Size aSize( pImp->GetOutputSize() ); if( rPos.Y() > aSize.Height() - 12 ) { SvLBox::ImplShowTargetEmphasis( SvLBox::pTargetEntry, sal_False ); ScrollOutputArea( -1 ); } } SvLBoxEntry* pTarget = pImp->GetEntry( rPos ); // bei Droppen in leere Flaeche -> den letzten Eintrag nehmen if( !pTarget ) return (SvLBoxEntry*)LastVisible(); else if( (GetDragDropMode() & SV_DRAGDROP_ENABLE_TOP) && pTarget == First() && rPos.Y() < 6 ) return 0; return pTarget; } SvLBoxEntry* SvTreeListBox::GetEntry( const Point& rPos, sal_Bool bHit ) const { DBG_CHKTHIS(SvTreeListBox,0); SvLBoxEntry* pEntry = pImp->GetEntry( rPos ); if( pEntry && bHit ) { long nLine = pImp->GetEntryLine( pEntry ); if( !(pImp->EntryReallyHit( pEntry, rPos, nLine)) ) return 0; } return pEntry; } SvLBoxEntry* SvTreeListBox::GetCurEntry() const { DBG_CHKTHIS(SvTreeListBox,0); return pImp->GetCurEntry(); } void SvTreeListBox::ImplInitStyle() { DBG_CHKTHIS(SvTreeListBox,0); const WinBits nWindowStyle = GetStyle(); nTreeFlags |= TREEFLAG_RECALCTABS; if( nWindowStyle & WB_SORT ) { GetModel()->SetSortMode( SortAscending ); GetModel()->SetCompareHdl( LINK(this,SvTreeListBox,DefaultCompare)); } else { GetModel()->SetSortMode( SortNone ); GetModel()->SetCompareHdl( Link() ); } pImp->SetStyle( nWindowStyle ); pImp->Resize(); Invalidate(); } void SvTreeListBox::PaintEntry( SvLBoxEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); DBG_ASSERT(pEntry,"PaintEntry:No Entry"); if( pEntry ) pImp->PaintEntry( pEntry ); } void SvTreeListBox::InvalidateEntry( SvLBoxEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); DBG_ASSERT(pEntry,"InvalidateEntry:No Entry"); if( pEntry ) { GetModel()->InvalidateEntry( pEntry ); // pImp->InvalidateEntry( pEntry ); } } long SvTreeListBox::PaintEntry(SvLBoxEntry* pEntry,long nLine,sal_uInt16 nTabFlags) { return PaintEntry1(pEntry,nLine,nTabFlags); } #define SV_TAB_BORDER 8 long SvTreeListBox::PaintEntry1(SvLBoxEntry* pEntry,long nLine,sal_uInt16 nTabFlags, sal_Bool bHasClipRegion ) { DBG_CHKTHIS(SvTreeListBox,0); Rectangle aRect; // multi purpose sal_Bool bHorSBar = pImp->HasHorScrollBar(); PreparePaint( pEntry ); // #97680# ------------------ pImp->UpdateContextBmpWidthMax( pEntry ); if( nTreeFlags & TREEFLAG_RECALCTABS ) SetTabs(); short nTempEntryHeight = GetEntryHeight(); long nWidth = pImp->GetOutputSize().Width(); // wurde innerhalb des PreparePaints die horizontale ScrollBar // angeschaltet? Wenn ja, muss die ClipRegion neu gesetzt werden if( !bHorSBar && pImp->HasHorScrollBar() ) SetClipRegion( Region(pImp->GetClipRegionRect()) ); Point aEntryPos( GetMapMode().GetOrigin() ); aEntryPos.X() *= -1; // Umrechnung Dokumentkoord. long nMaxRight = nWidth + aEntryPos.X() - 1; Color aBackupTextColor( GetTextColor() ); Font aBackupFont( GetFont() ); Color aBackupColor = GetFillColor(); bool bCurFontIsSel = false; sal_Bool bInUse = pEntry->HasInUseEmphasis(); // wenn eine ClipRegion von aussen gesetzt wird, dann // diese nicht zuruecksetzen const WinBits nWindowStyle = GetStyle(); const sal_Bool bResetClipRegion = !bHasClipRegion; const sal_Bool bHideSelection = ((nWindowStyle & WB_HIDESELECTION) && !HasFocus())!=0; const StyleSettings& rSettings = GetSettings().GetStyleSettings(); Font aHighlightFont( GetFont() ); const Color aHighlightTextColor( rSettings.GetHighlightTextColor() ); aHighlightFont.SetColor( aHighlightTextColor ); Size aRectSize( 0, nTempEntryHeight ); if( !bHasClipRegion && nWindowStyle & WB_HSCROLL ) { SetClipRegion( Region(pImp->GetClipRegionRect()) ); bHasClipRegion = sal_True; } SvViewDataEntry* pViewDataEntry = GetViewDataEntry( pEntry ); sal_uInt16 nTabCount = aTabs.Count(); sal_uInt16 nItemCount = pEntry->ItemCount(); sal_uInt16 nCurTab = 0; sal_uInt16 nCurItem = 0; while( nCurTab < nTabCount && nCurItem < nItemCount ) { SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nCurTab ); sal_uInt16 nNextTab = nCurTab + 1; SvLBoxTab* pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0; SvLBoxItem* pItem = nCurItem < nItemCount ? pEntry->GetItem(nCurItem) : 0; sal_uInt16 nFlags = pTab->nFlags; Size aSize( pItem->GetSize( pViewDataEntry, nCurItem )); long nTabPos = GetTabPos( pEntry, pTab ); long nNextTabPos; if( pNextTab ) nNextTabPos = GetTabPos( pEntry, pNextTab ); else { nNextTabPos = nMaxRight; if( nTabPos > nMaxRight ) nNextTabPos += 50; } long nX; if( pTab->nFlags & SV_LBOXTAB_ADJUST_RIGHT ) //verhindern, das rechter Rand von der Tabtrennung abgeschnitten wird nX = nTabPos + pTab->CalcOffset(aSize.Width(), (nNextTabPos-SV_TAB_BORDER-1) -nTabPos); else nX = nTabPos + pTab->CalcOffset(aSize.Width(), nNextTabPos-nTabPos); if( nFlags & nTabFlags ) { if( !bHasClipRegion && nX + aSize.Width() >= nMaxRight ) { SetClipRegion( Region(pImp->GetClipRegionRect()) ); bHasClipRegion = sal_True; } aEntryPos.X() = nX; aEntryPos.Y() = nLine; // Hintergrund-Muster & Farbe bestimmen Wallpaper aWallpaper = GetBackground(); int bSelTab = nFlags & SV_LBOXTAB_SHOW_SELECTION; sal_uInt16 nItemType = pItem->IsA(); if ( pViewDataEntry->IsSelected() && bSelTab && !pViewDataEntry->IsCursored() ) { Color aNewWallColor = rSettings.GetHighlightColor(); if ( !bInUse || nItemType != SV_ITEM_ID_LBOXCONTEXTBMP ) { // if the face color is bright then the deactive color is also bright // -> so you can't see any deactive selection if ( bHideSelection && !rSettings.GetFaceColor().IsBright() && aWallpaper.GetColor().IsBright() != rSettings.GetDeactiveColor().IsBright() ) aNewWallColor = rSettings.GetDeactiveColor(); // set font color to highlight if ( !bCurFontIsSel ) { SetTextColor( aHighlightTextColor ); SetFont( aHighlightFont ); bCurFontIsSel = true; } } aWallpaper.SetColor( aNewWallColor ); } else // keine Selektion { if( bInUse && nItemType == SV_ITEM_ID_LBOXCONTEXTBMP ) aWallpaper.SetColor( rSettings.GetFieldColor() ); else if( bCurFontIsSel ) { bCurFontIsSel = false; SetTextColor( aBackupTextColor ); SetFont( aBackupFont ); } } // Hintergrund zeichnen if( !(nTreeFlags & TREEFLAG_USESEL)) { // nur den Bereich zeichnen, den das Item einnimmt aRectSize.Width() = aSize.Width(); aRect.SetPos( aEntryPos ); aRect.SetSize( aRectSize ); } else { // vom aktuellen bis zum naechsten Tab zeichnen if( nCurTab != 0 ) aRect.Left() = nTabPos; else // beim nullten Tab immer ab Spalte 0 zeichnen // (sonst Probleme bei Tabs mit Zentrierung) aRect.Left() = 0; aRect.Top() = nLine; aRect.Bottom() = nLine + nTempEntryHeight - 1; if( pNextTab ) { long nRight; nRight = GetTabPos(pEntry,pNextTab)-1; if( nRight > nMaxRight ) nRight = nMaxRight; aRect.Right() = nRight; } else aRect.Right() = nMaxRight; } // bei anwenderdefinierter Selektion, die bei einer Tabposition // groesser 0 beginnt den Hintergrund des 0.ten Items nicht // fuellen, da sonst z.B. TablistBoxen mit Linien nicht // realisiert werden koennen. if( !(nCurTab==0 && (nTreeFlags & TREEFLAG_USESEL) && nFirstSelTab) ) { SetFillColor( aWallpaper.GetColor() ); // Bei kleinen hor. Resizes tritt dieser Fall auf if( aRect.Left() < aRect.Right() ) DrawRect( aRect ); } // Item zeichnen // vertikal zentrieren aEntryPos.Y() += ( nTempEntryHeight - aSize.Height() ) / 2; pItem->Paint( aEntryPos, *this, pViewDataEntry->GetFlags(), pEntry ); // Trennungslinie zwischen Tabs if( pNextTab && pItem->IsA() == SV_ITEM_ID_LBOXSTRING && // nicht am rechten Fensterrand! aRect.Right() < nMaxRight ) { aRect.Left() = aRect.Right() - SV_TAB_BORDER; DrawRect( aRect ); } SetFillColor( aBackupColor ); } nCurItem++; nCurTab++; } if( pViewDataEntry->IsCursored() && !HasFocus() ) { // Cursor-Emphasis SetFillColor(); Color aOldLineColor = GetLineColor(); SetLineColor( Color( COL_BLACK ) ); aRect = GetFocusRect( pEntry, nLine ); aRect.Top()++; aRect.Bottom()--; DrawRect( aRect ); SetLineColor( aOldLineColor ); SetFillColor( aBackupColor ); } if( bCurFontIsSel ) { SetTextColor( aBackupTextColor ); SetFont( aBackupFont ); } sal_uInt16 nFirstDynTabPos; SvLBoxTab* pFirstDynamicTab = GetFirstDynamicTab( nFirstDynTabPos ); long nDynTabPos = GetTabPos( pEntry, pFirstDynamicTab ); nDynTabPos += pImp->nNodeBmpTabDistance; nDynTabPos += pImp->nNodeBmpWidth / 2; nDynTabPos += 4; // 4 Pixel Reserve, damit die Node-Bitmap // nicht zu nah am naechsten Tab steht if( (!(pEntry->GetFlags() & SV_ENTRYFLAG_NO_NODEBMP)) && (nWindowStyle & WB_HASBUTTONS) && pFirstDynamicTab && ( pEntry->HasChilds() || pEntry->HasChildsOnDemand() ) ) { // ersten festen Tab suchen, und pruefen ob die Node-Bitmap // in ihn hineinragt sal_uInt16 nNextTab = nFirstDynTabPos; SvLBoxTab* pNextTab; do { nNextTab++; pNextTab = nNextTab < nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextTab) : 0; } while( pNextTab && pNextTab->IsDynamic() ); if( !pNextTab || (GetTabPos( pEntry, pNextTab ) > nDynTabPos) ) { if((nWindowStyle & WB_HASBUTTONSATROOT) || pModel->GetDepth(pEntry) > 0) { Point aPos( GetTabPos(pEntry,pFirstDynamicTab), nLine ); aPos.X() += pImp->nNodeBmpTabDistance; const Image* pImg = 0; BmpColorMode eBitmapMode = BMP_COLOR_NORMAL; if ( GetSettings().GetStyleSettings().GetHighContrastMode() ) eBitmapMode = BMP_COLOR_HIGHCONTRAST; if( IsExpanded(pEntry) ) pImg = &pImp->GetExpandedNodeBmp( eBitmapMode ); else { if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() && (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) && pImp->GetDontKnowNodeBmp().GetSizePixel().Width() ) pImg = &pImp->GetDontKnowNodeBmp( eBitmapMode ); else pImg = &pImp->GetCollapsedNodeBmp( eBitmapMode ); } aPos.Y() += (nTempEntryHeight - pImg->GetSizePixel().Height()) / 2; sal_uInt16 nStyle = 0; if ( !IsEnabled() ) nStyle |= IMAGE_DRAW_DISABLE; //native sal_Bool bNativeOK = sal_False; if ( IsNativeControlSupported( CTRL_LISTNODE, PART_ENTIRE_CONTROL) ) { ImplControlValue aControlValue; Rectangle aCtrlRegion( aPos, pImg->GetSizePixel() ); ControlState nState = 0; if ( IsEnabled() ) nState |= CTRL_STATE_ENABLED; if ( IsExpanded(pEntry) ) aControlValue.setTristateVal( BUTTONVALUE_ON );//expanded node else { if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() && (!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) && pImp->GetDontKnowNodeBmp().GetSizePixel().Width() ) aControlValue.setTristateVal( BUTTONVALUE_DONTKNOW );//dont know else aControlValue.setTristateVal( BUTTONVALUE_OFF );//collapsed node } bNativeOK = DrawNativeControl( CTRL_LISTNODE, PART_ENTIRE_CONTROL, aCtrlRegion, nState, aControlValue, rtl::OUString() ); } if( !bNativeOK) { //non native DrawImage( aPos, *pImg ,nStyle); } } } } if( bHasClipRegion && bResetClipRegion ) SetClipRegion(); return 0; // nRowLen; } void SvTreeListBox::PreparePaint( SvLBoxEntry* ) { } Rectangle SvTreeListBox::GetFocusRect( SvLBoxEntry* pEntry, long nLine ) { DBG_CHKTHIS(SvTreeListBox,0); Size aSize; Rectangle aRect; aRect.Top() = nLine; aSize.Height() = GetEntryHeight(); long nRealWidth = pImp->GetOutputSize().Width(); nRealWidth -= GetMapMode().GetOrigin().X(); sal_uInt16 nCurTab; SvLBoxTab* pTab = GetFirstTab( SV_LBOXTAB_SHOW_SELECTION, nCurTab ); long nTabPos = 0; if( pTab ) nTabPos = GetTabPos( pEntry, pTab ); long nNextTabPos; if( pTab && nCurTab < aTabs.Count() - 1 ) { SvLBoxTab* pNextTab = (SvLBoxTab*)aTabs.GetObject( nCurTab + 1 ); nNextTabPos = GetTabPos( pEntry, pNextTab ); } else { nNextTabPos = nRealWidth; if( nTabPos > nRealWidth ) nNextTabPos += 50; } sal_Bool bUserSelection = (sal_Bool)( nTreeFlags & TREEFLAG_USESEL ) != 0; if( !bUserSelection ) { if( pTab && nCurTab < pEntry->ItemCount() ) { SvLBoxItem* pItem = pEntry->GetItem( nCurTab ); aSize.Width() = pItem->GetSize( this, pEntry ).Width(); if( !aSize.Width() ) aSize.Width() = 15; long nX = nTabPos; //GetTabPos( pEntry, pTab ); // Ausrichtung nX += pTab->CalcOffset( aSize.Width(), nNextTabPos - nTabPos ); aRect.Left() = nX; // damit erster & letzter Buchstabe nicht angeknabbert werden aRect.SetSize( aSize ); if( aRect.Left() > 0 ) aRect.Left()--; aRect.Right()++; } } else { // wenn erster SelTab != 0, dann muessen wir auch rechnen if( nFocusWidth == -1 || nFirstSelTab ) { sal_uInt16 nLastTab; SvLBoxTab* pLastTab = GetLastTab(SV_LBOXTAB_SHOW_SELECTION,nLastTab); nLastTab++; if( nLastTab < aTabs.Count() ) // gibts noch einen ? pLastTab = (SvLBoxTab*)aTabs.GetObject( nLastTab ); else pLastTab = 0; // ueber gesamte Breite selektieren aSize.Width() = pLastTab ? pLastTab->GetPos() : 0x0fffffff; nFocusWidth = (short)aSize.Width(); if( pTab ) nFocusWidth = nFocusWidth - (short)nTabPos; //pTab->GetPos(); } else { aSize.Width() = nFocusWidth; if( pTab ) { if( nCurTab ) aSize.Width() += nTabPos; else aSize.Width() += pTab->GetPos(); // Tab0 immer ab ganz links } } // wenn Sel. beim nullten Tab anfaengt, dann ab Spalte 0 sel. zeichnen if( nCurTab != 0 ) { aRect.Left() = nTabPos; aSize.Width() -= nTabPos; } aRect.SetSize( aSize ); } // rechten Rand anpassen wg. Clipping if( aRect.Right() >= nRealWidth ) { aRect.Right() = nRealWidth-1; nFocusWidth = (short)aRect.GetWidth(); } return aRect; } long SvTreeListBox::GetTabPos( SvLBoxEntry* pEntry, SvLBoxTab* pTab) { DBG_CHKTHIS(SvTreeListBox,0); DBG_ASSERT(pTab,"No Tab"); long nPos = pTab->GetPos(); if( pTab->IsDynamic() ) { sal_uInt16 nDepth = pModel->GetDepth( pEntry ); nDepth = nDepth * (sal_uInt16)nIndent; nPos += (long)nDepth; } return nPos; } SvLBoxItem* SvTreeListBox::GetItem_Impl( SvLBoxEntry* pEntry, long nX, SvLBoxTab** ppTab, sal_uInt16 nEmptyWidth ) { DBG_CHKTHIS(SvTreeListBox,0); SvLBoxItem* pItemClicked = 0; sal_uInt16 nTabCount = aTabs.Count(); sal_uInt16 nItemCount = pEntry->ItemCount(); SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0); SvLBoxItem* pItem = pEntry->GetItem(0); sal_uInt16 nNextItem = 1; nX -= GetMapMode().GetOrigin().X(); long nRealWidth = pImp->GetOutputSize().Width(); nRealWidth -= GetMapMode().GetOrigin().X(); while( 1 ) { SvLBoxTab* pNextTab=nNextItem nRealWidth ) nNextTabPos += 50; } Size aItemSize( pItem->GetSize(this, pEntry)); nStart += pTab->CalcOffset( aItemSize.Width(), nNextTabPos - nStart ); long nLen = aItemSize.Width(); if( pNextTab ) { long nTabWidth = GetTabPos( pEntry, pNextTab ) - nStart; if( nTabWidth < nLen ) nLen = nTabWidth; } if( !nLen ) nLen = nEmptyWidth; if( nX >= nStart && nX < (nStart+nLen ) ) { pItemClicked = pItem; if( ppTab ) { *ppTab = pTab; break; } } if( nNextItem >= nItemCount || nNextItem >= nTabCount) break; pTab = (SvLBoxTab*)aTabs.GetObject( nNextItem ); pItem = pEntry->GetItem( nNextItem ); nNextItem++; } return pItemClicked; } SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX,SvLBoxTab** ppTab) { return GetItem_Impl( pEntry, nX, ppTab, 0 ); } SvLBoxItem* SvTreeListBox::GetItem(SvLBoxEntry* pEntry,long nX ) { DBG_CHKTHIS(SvTreeListBox,0); SvLBoxTab* pDummyTab; return GetItem_Impl( pEntry, nX, &pDummyTab, 0 ); } SvLBoxItem* SvTreeListBox::GetFirstDynamicItem( SvLBoxEntry* pEntry ) { DBG_CHKTHIS(SvTreeListBox,0); SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(0); SvLBoxItem* pItem = pEntry->GetItem(0); sal_uInt16 nTabCount = aTabs.Count(); sal_uInt16 nNext = 1; while ( !pTab->IsDynamic() && nNext < nTabCount ) { pItem = pEntry->GetItem( nNext ); pTab = (SvLBoxTab*)aTabs.GetObject( nNext ); nNext++; } return pItem; } void SvTreeListBox::AddTab(long nTabPos,sal_uInt16 nFlags,void* pUserData ) { DBG_CHKTHIS(SvTreeListBox,0); nFocusWidth = -1; SvLBoxTab* pTab = new SvLBoxTab( nTabPos, nFlags ); pTab->SetUserData( pUserData ); aTabs.Insert( pTab, aTabs.Count() ); if( nTreeFlags & TREEFLAG_USESEL ) { sal_uInt16 nPos = aTabs.Count() - 1; if( nPos >= nFirstSelTab && nPos <= nLastSelTab ) pTab->nFlags |= SV_LBOXTAB_SHOW_SELECTION; else // String-Items werden normalerweise immer selektiert // deshalb explizit ausschalten pTab->nFlags &= ~SV_LBOXTAB_SHOW_SELECTION; } } SvLBoxTab* SvTreeListBox::GetFirstDynamicTab( sal_uInt16& rPos ) const { DBG_CHKTHIS(SvTreeListBox,0); sal_uInt16 nCurTab = 0; sal_uInt16 nTabCount = aTabs.Count(); while( nCurTab < nTabCount ) { SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(nCurTab); if( pTab->nFlags & SV_LBOXTAB_DYNAMIC ) { rPos = nCurTab; return pTab; } nCurTab++; } return 0; } SvLBoxTab* SvTreeListBox::GetFirstDynamicTab() const { sal_uInt16 nDummy; return GetFirstDynamicTab( nDummy ); } SvLBoxTab* SvTreeListBox::GetTab( SvLBoxEntry* pEntry, SvLBoxItem* pItem) const { DBG_CHKTHIS(SvTreeListBox,0); sal_uInt16 nPos = pEntry->GetPos( pItem ); return (SvLBoxTab*)aTabs.GetObject( nPos ); } void SvTreeListBox::ClearTabList() { DBG_CHKTHIS(SvTreeListBox,0); sal_uInt16 nTabCount = aTabs.Count(); while( nTabCount ) { nTabCount--; SvLBoxTab* pDelTab = (SvLBoxTab*)aTabs.GetObject( nTabCount ); delete pDelTab; } aTabs.Remove(0,aTabs.Count()); } Size SvTreeListBox::GetOutputSizePixel() const { DBG_CHKTHIS(SvTreeListBox,0); Size aSize = pImp->GetOutputSize(); return aSize; } void SvTreeListBox::NotifyBeginScroll() { DBG_CHKTHIS(SvTreeListBox,0); } void SvTreeListBox::NotifyEndScroll() { DBG_CHKTHIS(SvTreeListBox,0); } void SvTreeListBox::NotifyScrolling( long ) { DBG_CHKTHIS(SvTreeListBox,0); } void SvTreeListBox::NotifyScrolled() { DBG_CHKTHIS(SvTreeListBox,0); aScrolledHdl.Call( this ); } void SvTreeListBox::NotifyInvalidating() { DBG_CHKTHIS(SvTreeListBox,0); } void SvTreeListBox::Invalidate( sal_uInt16 nInvalidateFlags ) { DBG_CHKTHIS(SvTreeListBox,0); if( nFocusWidth == -1 ) // damit Control nicht nach dem Paint ein falsches FocusRect anzeigt pImp->RecalcFocusRect(); NotifyInvalidating(); SvLBox::Invalidate( nInvalidateFlags ); pImp->Invalidate(); } void SvTreeListBox::Invalidate( const Rectangle& rRect, sal_uInt16 nInvalidateFlags ) { DBG_CHKTHIS(SvTreeListBox,0); if( nFocusWidth == -1 ) // damit Control nicht nach dem Paint ein falsches FocusRect anzeigt pImp->RecalcFocusRect(); NotifyInvalidating(); SvLBox::Invalidate( rRect, nInvalidateFlags ); } void SvTreeListBox::SetHighlightRange( sal_uInt16 nStart, sal_uInt16 nEnd) { DBG_CHKTHIS(SvTreeListBox,0); sal_uInt16 nTemp; nTreeFlags |= TREEFLAG_USESEL; if( nStart > nEnd ) { nTemp = nStart; nStart = nEnd; nEnd = nTemp; } // alle Tabs markieren, die im Bereich liegen nTreeFlags |= TREEFLAG_RECALCTABS; nFirstSelTab = nStart; nLastSelTab = nEnd; pImp->RecalcFocusRect(); } void SvTreeListBox::RemoveHighlightRange() { DBG_CHKTHIS(SvTreeListBox,0); nTreeFlags &= (~TREEFLAG_USESEL); if( IsUpdateMode() ) Invalidate(); } sal_uLong SvTreeListBox::GetAscInsertionPos(SvLBoxEntry*,SvLBoxEntry*) { return LIST_APPEND; } sal_uLong SvTreeListBox::GetDescInsertionPos(SvLBoxEntry*,SvLBoxEntry*) { DBG_CHKTHIS(SvTreeListBox,0); return LIST_APPEND; } Region SvTreeListBox::GetDragRegion() const { DBG_CHKTHIS(SvTreeListBox,0); Rectangle aRect; SvLBoxEntry* pEntry = GetCurEntry(); if( pEntry ) { Point aPos = GetEntryPosition( pEntry ); aRect = ((SvTreeListBox*)this)->GetFocusRect( pEntry, aPos.Y() ); } Region aRegion( aRect ); return aRegion; } void SvTreeListBox::Command( const CommandEvent& rCEvt ) { DBG_CHKTHIS(SvTreeListBox,0); // FIXME gnumake2 resync to DEV300_m84 pImp->Command( rCEvt ); } void SvTreeListBox::RemoveParentKeepChilds( SvLBoxEntry* pParent ) { DBG_CHKTHIS(SvTreeListBox,0); DBG_ASSERT(pParent,"RemoveParentKeepChilds:No Parent"); SvLBoxEntry* pNewParent = GetParent( pParent ); if( pParent->HasChilds()) { SvLBoxEntry* pChild = FirstChild( pParent ); while( pChild ) { pModel->Move( pChild, pNewParent, LIST_APPEND ); pChild = FirstChild( pParent ); } } pModel->Remove( pParent ); } SvLBoxTab* SvTreeListBox::GetFirstTab( sal_uInt16 nFlagMask, sal_uInt16& rPos ) { sal_uInt16 nTabCount = aTabs.Count(); for( sal_uInt16 nPos = 0; nPos < nTabCount; nPos++ ) { SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( nPos ); if( (pTab->nFlags & nFlagMask) ) { rPos = nPos; return pTab; } } rPos = 0xffff; return 0; } SvLBoxTab* SvTreeListBox::GetLastTab( sal_uInt16 nFlagMask, sal_uInt16& rTabPos ) { short nTabCount = (short)aTabs.Count(); if( nTabCount ) { for( short nPos = nTabCount-1; nPos >= 0; nPos-- ) { SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject( (sal_uInt16)nPos ); if( (pTab->nFlags & nFlagMask) ) { rTabPos = (sal_uInt16)nPos; return pTab; } } } rTabPos = 0xffff; return 0; } void SvTreeListBox::SetAddMode( sal_Bool bAdd ) { pImp->SetAddMode( bAdd ); } sal_Bool SvTreeListBox::IsAddMode() const { return pImp->IsAddMode(); } void SvTreeListBox::RequestHelp( const HelpEvent& rHEvt ) { if( !pImp->RequestHelp( rHEvt ) ) SvLBox::RequestHelp( rHEvt ); } void SvTreeListBox::CursorMoved( SvLBoxEntry* ) { } IMPL_LINK( SvTreeListBox, DefaultCompare, SvSortData*, pData ) { SvLBoxEntry* pLeft = (SvLBoxEntry*)(pData->pLeft ); SvLBoxEntry* pRight = (SvLBoxEntry*)(pData->pRight ); String aLeft( ((SvLBoxString*)(pLeft->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText()); String aRight( ((SvLBoxString*)(pRight->GetFirstItem(SV_ITEM_ID_LBOXSTRING)))->GetText()); // #102891# ---------------- pImp->UpdateIntlWrapper(); return pImp->pIntlWrapper->getCaseCollator()->compareString( aLeft, aRight ); } void SvTreeListBox::ModelNotification( sal_uInt16 nActionId, SvListEntry* pEntry1, SvListEntry* pEntry2, sal_uLong nPos ) { if( nActionId == LISTACTION_CLEARING ) CancelTextEditing(); SvLBox::ModelNotification( nActionId, pEntry1, pEntry2, nPos ); switch( nActionId ) { case LISTACTION_INSERTED: { SvLBoxEntry* pEntry( dynamic_cast< SvLBoxEntry* >( pEntry1 ) ); ENSURE_OR_BREAK( pEntry, "SvTreeListBox::ModelNotification: invalid entry!" ); SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) ); if ( !pBmpItem ) break; const Image& rBitmap1( pBmpItem->GetBitmap1() ); const Image& rBitmap2( pBmpItem->GetBitmap2() ); short nMaxWidth = short( Max( rBitmap1.GetSizePixel().Width(), rBitmap2.GetSizePixel().Width() ) ); nMaxWidth = pImp->UpdateContextBmpWidthVector( pEntry, nMaxWidth ); if( nMaxWidth > nContextBmpWidthMax ) { nContextBmpWidthMax = nMaxWidth; SetTabs(); } } break; case LISTACTION_RESORTING: SetUpdateMode( sal_False ); break; case LISTACTION_RESORTED: // nach Sortierung den ersten Eintrag anzeigen, dabei die // Selektion erhalten. MakeVisible( (SvLBoxEntry*)pModel->First(), sal_True ); SetUpdateMode( sal_True ); break; case LISTACTION_CLEARED: if( IsUpdateMode() ) Update(); break; } } // bei Aenderungen SetTabs beruecksichtigen long SvTreeListBox::GetTextOffset() const { DBG_CHKTHIS(SvTreeListBox,0); const WinBits nWindowStyle = GetStyle(); sal_Bool bHasButtons = (nWindowStyle & WB_HASBUTTONS)!=0; sal_Bool bHasButtonsAtRoot = (nWindowStyle & (WB_HASLINESATROOT | WB_HASBUTTONSATROOT))!=0; long nStartPos = TAB_STARTPOS; long nNodeWidthPixel = GetExpandedNodeBmp().GetSizePixel().Width(); long nCheckWidth = 0; if( nTreeFlags & TREEFLAG_CHKBTN ) nCheckWidth = pCheckButtonData->aBmps[0].GetSizePixel().Width(); long nCheckWidthDIV2 = nCheckWidth / 2; long nContextWidth = nContextBmpWidthMax; long nContextWidthDIV2 = nContextWidth / 2; int nCase = NO_BUTTONS; if( !(nTreeFlags & TREEFLAG_CHKBTN) ) { if( bHasButtons ) nCase = NODE_BUTTONS; } else { if( bHasButtons ) nCase = NODE_AND_CHECK_BUTTONS; else nCase = CHECK_BUTTONS; } switch( nCase ) { case NO_BUTTONS : nStartPos += nContextWidthDIV2; // wg. Zentrierung nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp if( nContextBmpWidthMax ) nStartPos += 5; // Abstand Context-Bmp - Text break; case NODE_BUTTONS : if( bHasButtonsAtRoot ) nStartPos += ( nIndent + (nNodeWidthPixel/2) ); else nStartPos += nContextWidthDIV2; nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp if( nContextBmpWidthMax ) nStartPos += 5; // Abstand Context-Bmp - Text break; case NODE_AND_CHECK_BUTTONS : if( bHasButtonsAtRoot ) nStartPos += ( nIndent + nNodeWidthPixel ); else nStartPos += nCheckWidthDIV2; nStartPos += nCheckWidthDIV2; // rechter Rand des CheckButtons nStartPos += 3; // Abstand CheckButton Context-Bmp nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp // Abstand setzen nur wenn Bitmaps da if( nContextBmpWidthMax ) nStartPos += 5; // Abstand Context-Bmp - Text break; case CHECK_BUTTONS : nStartPos += nCheckWidthDIV2; nStartPos += nCheckWidthDIV2; // rechter Rand CheckButton nStartPos += 3; // Abstand CheckButton Context-Bmp nStartPos += nContextWidthDIV2; // Mitte der Context-Bmp nStartPos += nContextWidthDIV2; // rechter Rand der Context-Bmp if( nContextBmpWidthMax ) nStartPos += 5; // Abstand Context-Bmp - Text break; } return nStartPos; } void SvTreeListBox::EndSelection() { pImp->EndSelection(); } sal_Bool SvTreeListBox::IsNodeButton( const Point& rPos ) const { SvLBoxEntry* pEntry = GetEntry( rPos ); if( pEntry ) return pImp->IsNodeButton( rPos, pEntry ); return sal_False; } void SvTreeListBox::RepaintScrollBars() const { ((SvTreeListBox*)this)->pImp->RepaintScrollBars(); } ScrollBar *SvTreeListBox::GetVScroll() { return &((SvTreeListBox*)this)->pImp->aVerSBar; } ScrollBar *SvTreeListBox::GetHScroll() { return &((SvTreeListBox*)this)->pImp->aHorSBar; } void SvTreeListBox::EnableAsyncDrag( sal_Bool b ) { pImp->EnableAsyncDrag( b ); } SvLBoxEntry* SvTreeListBox::GetFirstEntryInView() const { Point aPos; return GetEntry( aPos ); } SvLBoxEntry* SvTreeListBox::GetNextEntryInView(SvLBoxEntry* pEntry ) const { SvLBoxEntry* pNext = (SvLBoxEntry*)NextVisible( pEntry ); if( pNext ) { Point aPos( GetEntryPosition(pNext) ); const Size& rSize = pImp->GetOutputSize(); if( aPos.Y() < 0 || aPos.Y() >= rSize.Height() ) return 0; } return pNext; } void SvTreeListBox::ShowFocusRect( const SvLBoxEntry* pEntry ) { pImp->ShowFocusRect( pEntry ); } void SvTreeListBox::SetTabBar( TabBar* pTabBar ) { pImp->SetTabBar( pTabBar ); } void SvTreeListBox::DataChanged( const DataChangedEvent& rDCEvt ) { if( (rDCEvt.GetType()==DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) ) { nEntryHeight = 0; // _together_ with sal_True of 1. par (bFont) of InitSettings() a zero-height // forces complete recalc of heights! InitSettings( sal_True, sal_True, sal_True ); Invalidate(); } else Control::DataChanged( rDCEvt ); } void SvTreeListBox::StateChanged( StateChangedType i_nStateChange ) { SvLBox::StateChanged( i_nStateChange ); if ( i_nStateChange == STATE_CHANGE_STYLE ) ImplInitStyle(); } void SvTreeListBox::InitSettings(sal_Bool bFont,sal_Bool bForeground,sal_Bool bBackground) { const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); if( bFont ) { Font aFont; aFont = rStyleSettings.GetFieldFont(); aFont.SetColor( rStyleSettings.GetWindowTextColor() ); SetPointFont( aFont ); AdjustEntryHeight( aFont ); RecalcViewData(); } if( bForeground || bFont ) { SetTextColor( rStyleSettings.GetFieldTextColor() ); SetTextFillColor(); } if( bBackground ) SetBackground( rStyleSettings.GetFieldColor() ); // always try to re-create default-SvLBoxButtonData if( pCheckButtonData && pCheckButtonData->HasDefaultImages() ) pCheckButtonData->SetDefaultImages( this ); } sal_Bool SvTreeListBox::IsCellFocusEnabled() const { return pImp->IsCellFocusEnabled(); } bool SvTreeListBox::SetCurrentTabPos( sal_uInt16 _nNewPos ) { return pImp->SetCurrentTabPos( _nNewPos ); } sal_uInt16 SvTreeListBox::GetCurrentTabPos() const { return pImp->GetCurrentTabPos(); } void SvTreeListBox::InitStartEntry() { if( !pImp->pStartEntry ) pImp->pStartEntry = GetModel()->First(); } void SvTreeListBox::CancelPendingEdit() { if( pImp ) pImp->CancelPendingEdit(); } PopupMenu* SvTreeListBox::CreateContextMenu( void ) { return NULL; } void SvTreeListBox::ExcecuteContextMenuAction( sal_uInt16 ) { DBG_WARNING( "SvTreeListBox::ExcecuteContextMenuAction(): now there's happening nothing!" ); } void SvTreeListBox::EnableContextMenuHandling( void ) { DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" ); pImp->bContextMenuHandling = sal_True; } void SvTreeListBox::EnableContextMenuHandling( sal_Bool b ) { DBG_ASSERT( pImp, "-SvTreeListBox::EnableContextMenuHandling(): No implementation!" ); pImp->bContextMenuHandling = b; } sal_Bool SvTreeListBox::IsContextMenuHandlingEnabled( void ) const { DBG_ASSERT( pImp, "-SvTreeListBox::IsContextMenuHandlingEnabled(): No implementation!" ); return pImp->bContextMenuHandling; } void SvTreeListBox::EnableList( bool _bEnable ) { // call base class method Window::Enable( _bEnable != false ); // then paint immediately Paint( Rectangle( Point(), GetSizePixel() ) ); } ::com::sun::star::uno::Reference< XAccessible > SvTreeListBox::CreateAccessible() { Window* pParent = GetAccessibleParentWindow(); DBG_ASSERT( pParent, "SvTreeListBox::CreateAccessible - accessible parent not found" ); ::com::sun::star::uno::Reference< XAccessible > xAccessible; if ( pParent ) { ::com::sun::star::uno::Reference< XAccessible > xAccParent = pParent->GetAccessible(); if ( xAccParent.is() ) { // need to be done here to get the vclxwindow later on in the accessbile ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xTemp(GetComponentInterface()); xAccessible = pImp->m_aFactoryAccess.getFactory().createAccessibleTreeListBox( *this, xAccParent ); } } return xAccessible; } void SvTreeListBox::FillAccessibleEntryStateSet( SvLBoxEntry* pEntry, ::utl::AccessibleStateSetHelper& rStateSet ) const { DBG_ASSERT( pEntry, "SvTreeListBox::FillAccessibleEntryStateSet: invalid entry" ); if ( pEntry ) { if ( pEntry->HasChildsOnDemand() || pEntry->HasChilds() ) { rStateSet.AddState( AccessibleStateType::EXPANDABLE ); if ( IsExpanded( pEntry ) ) rStateSet.AddState( (sal_Int16)AccessibleStateType::EXPANDED ); } if ( GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED ) rStateSet.AddState( AccessibleStateType::CHECKED ); if ( IsEntryVisible( pEntry ) ) rStateSet.AddState( AccessibleStateType::VISIBLE ); if ( IsSelected( pEntry ) ) rStateSet.AddState( AccessibleStateType::SELECTED ); if ( IsEnabled() ) { rStateSet.AddState( AccessibleStateType::ENABLED ); rStateSet.AddState( AccessibleStateType::FOCUSABLE ); rStateSet.AddState( AccessibleStateType::SELECTABLE ); SvViewDataEntry* pViewDataNewCur = 0; pViewDataNewCur = GetViewDataEntry(pEntry); if( pViewDataNewCur && pViewDataNewCur->HasFocus() ) rStateSet.AddState( AccessibleStateType::FOCUSED ); } } } Rectangle SvTreeListBox::GetBoundingRect( SvLBoxEntry* pEntry ) { Point aPos = GetEntryPosition( pEntry ); Rectangle aRect = GetFocusRect( pEntry, aPos.Y() ); return aRect; } void SvTreeListBox::EnableCellFocus() { pImp->EnableCellFocus(); } void SvTreeListBox::CallImplEventListeners(sal_uLong nEvent, void* pData) { CallEventListeners(nEvent, pData); } void SvTreeListBox::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& rStateSet ) const { SvLBox::FillAccessibleStateSet( rStateSet ); }