2486 lines
72 KiB
C++
2486 lines
72 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_svtools.hxx"
|
|
|
|
#define _SVTREEBX_CXX
|
|
#include <vcl/svapp.hxx>
|
|
|
|
class TabBar;
|
|
|
|
#include <svtools/svlbox.hxx>
|
|
#include <svtools/svlbitm.hxx>
|
|
#include <svtools/svtreebx.hxx>
|
|
#include <tools/diagnose_ex.h>
|
|
#include <comphelper/string.hxx>
|
|
#include <svimpbox.hxx>
|
|
#include <unotools/accessiblestatesethelper.hxx>
|
|
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
|
|
#include <com/sun/star/awt/XWindowPeer.hpp>
|
|
|
|
|
|
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;
|
|
|
|
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 );
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void SvTreeListBox::SetSublistOpenWithLeftRight( sal_Bool b )
|
|
{
|
|
pImp->bSubLstOpLR = b;
|
|
}
|
|
|
|
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::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<SvLBoxString*>( pItem )->GetText().Len() > 0 )
|
|
{
|
|
sRet = static_cast<SvLBoxString*>( pItem )->GetText();
|
|
break;
|
|
}
|
|
nCur++;
|
|
}
|
|
return sRet;
|
|
}
|
|
|
|
const Image& SvTreeListBox::GetExpandedEntryBmp(SvLBoxEntry* pEntry) 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( );
|
|
}
|
|
|
|
const Image& SvTreeListBox::GetCollapsedEntryBmp( SvLBoxEntry* pEntry ) 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( );
|
|
}
|
|
|
|
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 );
|
|
|
|
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 )
|
|
{
|
|
DBG_CHKTHIS(SvTreeListBox,0);
|
|
SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
|
|
|
|
DBG_ASSERT(pItem,"SetExpBmp:Item not found");
|
|
pItem->SetBitmap2( aBmp );
|
|
|
|
GetModel()->InvalidateEntry( pEntry );
|
|
SetEntryHeight( pEntry );
|
|
Size aSize = aBmp.GetSizePixel();
|
|
short nWidth = pImp->UpdateContextBmpWidthVector( pEntry, (short)aSize.Width() );
|
|
if( nWidth > nContextBmpWidthMax )
|
|
{
|
|
nContextBmpWidthMax = nWidth;
|
|
SetTabs();
|
|
}
|
|
}
|
|
|
|
void SvTreeListBox::SetCollapsedEntryBmp(SvLBoxEntry* pEntry,const Image& aBmp )
|
|
{
|
|
DBG_CHKTHIS(SvTreeListBox,0);
|
|
SvLBoxContextBmp* pItem = (SvLBoxContextBmp*)(pEntry->GetFirstItem(SV_ITEM_ID_LBOXCONTEXTBMP));
|
|
|
|
DBG_ASSERT(pItem,"SetExpBmp:Item not found");
|
|
pItem->SetBitmap1( aBmp );
|
|
|
|
GetModel()->InvalidateEntry( pEntry );
|
|
SetEntryHeight( pEntry );
|
|
Size aSize = aBmp.GetSizePixel();
|
|
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( );
|
|
aExpEntryBmp = pBmpItem->GetBitmap2( );
|
|
}
|
|
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() );
|
|
|
|
return pClone;
|
|
}
|
|
|
|
void SvTreeListBox::SetIndent( short nNewIndent )
|
|
{
|
|
DBG_CHKTHIS(SvTreeListBox,0);
|
|
nIndent = nNewIndent;
|
|
SetTabs();
|
|
if( IsUpdateMode() )
|
|
Invalidate();
|
|
}
|
|
|
|
const Image& SvTreeListBox::GetDefaultExpandedEntryBmp( ) const
|
|
{
|
|
return pImp->GetDefaultEntryExpBmp( );
|
|
}
|
|
|
|
const Image& SvTreeListBox::GetDefaultCollapsedEntryBmp( ) const
|
|
{
|
|
return pImp->GetDefaultEntryColBmp( );
|
|
}
|
|
|
|
void SvTreeListBox::SetDefaultExpandedEntryBmp( const Image& aBmp )
|
|
{
|
|
DBG_CHKTHIS(SvTreeListBox,0);
|
|
Size aSize = aBmp.GetSizePixel();
|
|
if( aSize.Width() > nContextBmpWidthMax )
|
|
nContextBmpWidthMax = (short)aSize.Width();
|
|
SetTabs();
|
|
|
|
pImp->SetDefaultEntryExpBmp( aBmp );
|
|
}
|
|
|
|
void SvTreeListBox::SetDefaultCollapsedEntryBmp( const Image& aBmp )
|
|
{
|
|
DBG_CHKTHIS(SvTreeListBox,0);
|
|
Size aSize = aBmp.GetSizePixel();
|
|
if( aSize.Width() > nContextBmpWidthMax )
|
|
nContextBmpWidthMax = (short)aSize.Width();
|
|
SetTabs();
|
|
|
|
pImp->SetDefaultEntryColBmp( aBmp );
|
|
}
|
|
|
|
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( )
|
|
{
|
|
return SvImpLBox::GetDefaultExpandedNodeImage( );
|
|
}
|
|
|
|
const Image& SvTreeListBox::GetDefaultCollapsedNodeImage( )
|
|
{
|
|
return SvImpLBox::GetDefaultCollapsedNodeImage( );
|
|
}
|
|
|
|
void SvTreeListBox::SetNodeBitmaps( const Image& rCollapsedNodeBmp, const Image& rExpandedNodeBmp )
|
|
{
|
|
DBG_CHKTHIS(SvTreeListBox,0);
|
|
SetExpandedNodeBmp( rExpandedNodeBmp );
|
|
SetCollapsedNodeBmp( rCollapsedNodeBmp );
|
|
SetTabs();
|
|
}
|
|
|
|
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("<dummy>"), pParent, sal_False, LIST_APPEND );
|
|
}
|
|
|
|
void SvTreeListBox::GetFocus()
|
|
{
|
|
DBG_CHKTHIS(SvTreeListBox,0);
|
|
pImp->GetFocus();
|
|
SvLBox::GetFocus();
|
|
|
|
SvLBoxEntry* pEntry = FirstSelected();
|
|
if ( pEntry )
|
|
pImp->CallEventListeners( VCLEVENT_LISTBOX_SELECT, pEntry );
|
|
|
|
}
|
|
|
|
void SvTreeListBox::LoseFocus()
|
|
{
|
|
DBG_CHKTHIS(SvTreeListBox,0);
|
|
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();
|
|
}
|
|
|
|
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::ScrollToAbsPos( long nPos )
|
|
{
|
|
pImp->ScrollToAbsPos( nPos );
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
// #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();
|
|
}
|
|
|
|
// #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 );
|
|
}
|
|
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)
|
|
{
|
|
DBG_CHKTHIS(SvTreeListBox,0);
|
|
AdjustEntryHeight( rBmp );
|
|
pImp->SetCollapsedNodeBmp( rBmp );
|
|
}
|
|
|
|
void SvTreeListBox::SetExpandedNodeBmp( const Image& rBmp )
|
|
{
|
|
DBG_CHKTHIS(SvTreeListBox,0);
|
|
AdjustEntryHeight( rBmp );
|
|
pImp->SetExpandedNodeBmp( rBmp );
|
|
}
|
|
|
|
|
|
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 );
|
|
}
|
|
|
|
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::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::GetExpandedNodeBmp( ) const
|
|
{
|
|
return pImp->GetExpandedNodeBmp( );
|
|
}
|
|
|
|
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 );
|
|
EditText( pItem->GetText(), aRect, rSelection );
|
|
}
|
|
|
|
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();
|
|
long nTabPos, nNextTabPos = 0;
|
|
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 );
|
|
nNextTabPos = -1;
|
|
if( i < nCount - 1 )
|
|
{
|
|
SvLBoxItem* pNextItem = pEntry->GetItem( i + 1 );
|
|
SvLBoxTab* pNextTab = GetTab( pEntry, pNextItem );
|
|
nNextTabPos = pNextTab->GetPos();
|
|
}
|
|
|
|
if( pTab && pTab->IsEditable() )
|
|
{
|
|
nTabPos = pTab->GetPos();
|
|
if( !bIsMouseTriggered || (nClickX > nTabPos && (nNextTabPos == -1 || nClickX < nNextTabPos ) ) )
|
|
{
|
|
pItem = static_cast<SvLBoxString*>( 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
|
|
{
|
|
if( EditedEntry( pEdEntry, rStr ) )
|
|
{
|
|
((SvLBoxString*)pEdItem)->SetText( pEdEntry, rStr );
|
|
pModel->InvalidateEntry( pEdEntry );
|
|
}
|
|
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 );
|
|
}
|
|
}
|
|
|
|
|
|
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 );
|
|
|
|
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;
|
|
|
|
if( IsExpanded(pEntry) )
|
|
pImg = &pImp->GetExpandedNodeBmp( );
|
|
else
|
|
{
|
|
if( (!pEntry->HasChilds()) && pEntry->HasChildsOnDemand() &&
|
|
(!(pEntry->GetFlags() & SV_ENTRYFLAG_HAD_CHILDREN)) &&
|
|
pImp->GetDontKnowNodeBmp().GetSizePixel().Width() )
|
|
pImg = &pImp->GetDontKnowNodeBmp( );
|
|
else
|
|
pImg = &pImp->GetCollapsedNodeBmp( );
|
|
}
|
|
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) {
|
|
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<nTabCount ? (SvLBoxTab*)aTabs.GetObject(nNextItem) : 0;
|
|
long nStart = GetTabPos( pEntry, pTab );
|
|
|
|
long nNextTabPos;
|
|
if( pNextTab )
|
|
nNextTabPos = GetTabPos( pEntry, pNextTab );
|
|
else
|
|
{
|
|
nNextTabPos = nRealWidth;
|
|
if( nStart > 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 );
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
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::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());
|
|
pImp->UpdateStringSorter();
|
|
return pImp->m_pStringSorter->compare(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;
|
|
}
|
|
}
|
|
|
|
void SvTreeListBox::EndSelection()
|
|
{
|
|
pImp->EndSelection();
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
SvLBoxEntry* SvTreeListBox::GetLastEntryInView() const
|
|
{
|
|
SvLBoxEntry* pEntry = GetFirstEntryInView();
|
|
SvLBoxEntry* pNext = 0;
|
|
while( pEntry )
|
|
{
|
|
pNext = (SvLBoxEntry*)NextVisible( pEntry );
|
|
if( pNext )
|
|
{
|
|
Point aPos( GetEntryPosition(pNext) );
|
|
const Size& rSize = pImp->GetOutputSize();
|
|
if( aPos.Y() < 0 || aPos.Y() >= rSize.Height() )
|
|
break;
|
|
else
|
|
pEntry = pNext;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
return pEntry;
|
|
}
|
|
|
|
void SvTreeListBox::ShowFocusRect( const SvLBoxEntry* pEntry )
|
|
{
|
|
pImp->ShowFocusRect( pEntry );
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
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->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 );
|
|
}
|
|
|
|
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 );
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|