/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: templdlg.cxx,v $
 *
 *  $Revision: 1.49 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 18:33:28 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _MENU_HXX //autogen
#include <vcl/menu.hxx>
#endif
#ifndef _SFXINTITEM_HXX //autogen
#include <svtools/intitem.hxx>
#endif
#ifndef _SFXSTRITEM_HXX //autogen
#include <svtools/stritem.hxx>
#endif
#ifndef _SFXSTYLE_HXX //autogen
#include <svtools/style.hxx>
#endif
#ifndef GCC
#pragma hdrstop
#endif

#define _SVSTDARR_STRINGSDTOR
#include <svtools/svstdarr.hxx>

#ifndef _UNOTOOLS_PROCESSFACTORY_HXX
#include <comphelper/processfactory.hxx>
#endif
#ifndef _UNOTOOLS_INTLWRAPPER_HXX
#include <unotools/intlwrapper.hxx>
#endif
#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif

#include "sfxhelp.hxx"
#include "app.hxx"
#include "dispatch.hxx"
#include "bindings.hxx"
#include "templdlg.hxx"
#include "templdgi.hxx"
#include "tplcitem.hxx"
#include "sfxtypes.hxx"
#include "styfitem.hxx"
#include "objsh.hxx"
#include "viewsh.hxx"
#include "newstyle.hxx"
#include "tplpitem.hxx"
#include "sfxresid.hxx"

#include "templdlg.hrc"
#include "sfx.hrc"
#include "dialog.hrc"
#include "arrdecl.hxx"
#include "fltfnc.hxx"
#include "docfilt.hxx"
#include "docfac.hxx"
#include "docvor.hxx"
#include "doctempl.hxx"
#include "module.hxx"
#include "imgmgr.hxx"
#include "helpid.hrc"
#include "appdata.hxx"
#include "objshimp.hxx"
#include "viewfrm.hxx"
using namespace ::com::sun::star;
//=========================================================================

// Fenster wird ab jetzt dynamisch erstellt. Daher hier R"ander usw.

#define SFX_TEMPLDLG_HFRAME         3
#define SFX_TEMPLDLG_VTOPFRAME      3

#ifdef MAC
#define SFX_TEMPLDLG_VBOTFRAME      8
#else
#define SFX_TEMPLDLG_VBOTFRAME      3
#endif

#define SFX_TEMPLDLG_MIDHSPACE      3
#define SFX_TEMPLDLG_MIDVSPACE      3
#define SFX_TEMPLDLG_FILTERHEIGHT   100

static USHORT nLastItemId = USHRT_MAX;

// filter box has maximum 7 entries visible
#define MAX_FILTER_ENTRIES          7

//=========================================================================

TYPEINIT0(SfxCommonTemplateDialog_Impl);
TYPEINIT1(SfxTemplateDialog_Impl,SfxCommonTemplateDialog_Impl);
TYPEINIT1(SfxTemplateCatalog_Impl,SfxCommonTemplateDialog_Impl);

SFX_IMPL_DOCKINGWINDOW(SfxTemplateDialogWrapper, SID_STYLE_DESIGNER)

//-------------------------------------------------------------------------

// Redirektionsfunktionen

SfxTemplateDialog::SfxTemplateDialog
(
    SfxBindings *pBindings,
    SfxChildWindow *pCW,
    Window *pParent
)

/*  [Beschreibung]
    Gestalterklasse.
*/
    : SfxDockingWindow( pBindings, pCW, pParent, SfxResId(DLG_STYLE_DESIGNER) ),

    pImpl( new SfxTemplateDialog_Impl( pParent, pBindings, this ) )

{
    pImpl->updateNonFamilyImages();
}

//-------------------------------------------------------------------------

SfxTemplateDialog::~SfxTemplateDialog()
{
    delete pImpl;
}

ISfxTemplateCommon* SfxTemplateDialog::GetISfxTemplateCommon()
{
    return pImpl->GetISfxTemplateCommon();
}

void SfxTemplateDialog::SetParagraphFamily()
{
    // first select the paragraph family
    pImpl->FamilySelect( SFX_STYLE_FAMILY_PARA );
    // then select the automatic filter
    pImpl->SetAutomaticFilter();
}

// ------------------------------------------------------------------------

void SfxTemplateDialog::DataChanged( const DataChangedEvent& _rDCEvt )
{
    if ( ( DATACHANGED_SETTINGS == _rDCEvt.GetType() ) &&
         ( 0 != ( SETTINGS_STYLE & _rDCEvt.GetFlags() ) ) )
    {
        pImpl->updateFamilyImages();
        pImpl->updateNonFamilyImages();
    }

    SfxDockingWindow::DataChanged( _rDCEvt );
}

//-------------------------------------------------------------------------

void SfxTemplateDialog::Update()
{
    pImpl->Update();
}

//-------------------------------------------------------------------------

void SfxTemplateDialog::Resize()
{
    if(pImpl)
        pImpl->Resize();
    SfxDockingWindow::Resize();
}


//-------------------------------------------------------------------------

SfxChildAlignment SfxTemplateDialog::CheckAlignment(SfxChildAlignment eActAlign,SfxChildAlignment eAlign)
{
    switch (eAlign)
    {
        case SFX_ALIGN_TOP:
        case SFX_ALIGN_HIGHESTTOP:
        case SFX_ALIGN_LOWESTTOP:
        case SFX_ALIGN_BOTTOM:
        case SFX_ALIGN_LOWESTBOTTOM:
        case SFX_ALIGN_HIGHESTBOTTOM:
            return eActAlign;
            break;

        case SFX_ALIGN_LEFT:
        case SFX_ALIGN_RIGHT:
        case SFX_ALIGN_FIRSTLEFT:
        case SFX_ALIGN_LASTLEFT:
        case SFX_ALIGN_FIRSTRIGHT:
        case SFX_ALIGN_LASTRIGHT:
            return eAlign;
            break;

        default:
            return eAlign;
            break;
    }
}

//-------------------------------------------------------------------------

SfxTemplateCatalog::SfxTemplateCatalog(Window *pParent, SfxBindings *pBindings)
 : SfxModalDialog(pParent,SfxResId(RID_STYLECATALOG))
{
    pImpl = new SfxTemplateCatalog_Impl(pParent, pBindings, this);
}

//-------------------------------------------------------------------------

SfxTemplateCatalog::~SfxTemplateCatalog()
{
    delete pImpl;
}

//-------------------------------------------------------------------------

void DropListBox_Impl::MouseButtonDown( const MouseEvent& rMEvt )
{
    nModifier = rMEvt.GetModifier();

    BOOL bHitEmptySpace = ( NULL == GetEntry( rMEvt.GetPosPixel(), TRUE ) );
    if( bHitEmptySpace && ( rMEvt.GetClicks() == 2 ) && rMEvt.IsMod1() )
        Control::MouseButtonDown( rMEvt );
    else
        SvTreeListBox::MouseButtonDown( rMEvt );
}

sal_Int8 DropListBox_Impl::AcceptDrop( const AcceptDropEvent& rEvt )

/*  [Description: ]
    Drop is enabled as long as it is allowed to create a new style by example, i.e. to
    create a style out of the current selection.
*/

{
    if ( IsDropFormatSupported( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) )
    {
        // special case: page styles are allowed to create new styles by example
        // but not allowed to be created by drag and drop
        if( pDialog->nActFamily == SfxCommonTemplateDialog_Impl::SfxFamilyIdToNId( SFX_STYLE_FAMILY_PAGE ) ||
                pDialog->bNewByExampleDisabled )
            return DND_ACTION_NONE;
        else
            return DND_ACTION_COPY;
    }
    return SvTreeListBox::AcceptDrop( rEvt );
}

//-------------------------------------------------------------------------

sal_Int8 DropListBox_Impl::ExecuteDrop( const ExecuteDropEvent& rEvt )
{
//  rEvt.maDropEvent.Context->acceptDrop( DND_ACTION_NONE );
//  rEvt.maDropEvent.Context->dropComplete( TRUE );

    sal_Int8 nRet = DND_ACTION_NONE;
    SfxObjectShell* pDocShell = pDialog->GetObjectShell();
    TransferableDataHelper aHelper( rEvt.maDropEvent.Transferable );
    sal_uInt32 nFormatCount = aHelper.GetFormatCount();
    if ( pDocShell )
    {
        sal_Bool bFormatFound = sal_False;

        for ( sal_uInt32 i = 0; i < nFormatCount; ++i )
        {
            SotFormatStringId nId = aHelper.GetFormat(i);
            TransferableObjectDescriptor aDesc;

            if ( aHelper.GetTransferableObjectDescriptor( nId, aDesc ) )
            {
                if ( aDesc.maClassName == pDocShell->GetFactory().GetClassId() )
                {
                    PostUserEvent( LINK( this, DropListBox_Impl, OnAsyncExecuteDrop ), 0 );

                    bFormatFound = sal_True;
                    nRet =  rEvt.mnAction;
                    break;
                }
            }
        }

        if ( !bFormatFound )
            return SvTreeListBox::ExecuteDrop( rEvt );
    }

    return nRet;
}


IMPL_LINK( DropListBox_Impl, OnAsyncExecuteDrop, SvLBoxEntry*, EMPTYARG )
{
    pDialog->ActionSelect( SID_STYLE_NEW_BY_EXAMPLE );
    return 0;
}


IMPL_LINK( DropListBox_Impl, OnAsyncExecuteError, void*, NOTINTERESTEDIN )
{
    ErrorHandler::HandleError( ERRCODE_IO_WRONGFORMAT );

    return 0;
}


long DropListBox_Impl::Notify( NotifyEvent& rNEvt )
{
    long nRet = 0;
    if( rNEvt.GetType() == EVENT_KEYINPUT )
    {
        const KeyCode&  rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
        if(!rKeyCode.GetModifier())
        {
            if( pDialog->bCanDel && KEY_DELETE == rKeyCode.GetCode())
            {
                pDialog->DeleteHdl( NULL );
                nRet =  1;
            }
            else if( KEY_RETURN == rKeyCode.GetCode())
            {
                GetDoubleClickHdl().Call(this);
                nRet = 1;
            }
        }
    }
    if(!nRet)
        nRet = SvTreeListBox::Notify( rNEvt );
    return nRet;
}


//-------------------------------------------------------------------------


SfxActionListBox::SfxActionListBox
(
    SfxCommonTemplateDialog_Impl* pParent,
    WinBits nWinBits
)

/*  [Beschreibung]

    ListBox- Klasse, die im Command-Handler ein PopupMenu (Gestalter
    spezifisch) startet.

*/

:       DropListBox_Impl(pParent->GetWindow(), nWinBits, pParent)

{
    EnableContextMenuHandling();
}

//-------------------------------------------------------------------------

SfxActionListBox::SfxActionListBox( SfxCommonTemplateDialog_Impl* pParent,
                                    const ResId &rResId) :
    DropListBox_Impl(pParent->GetWindow(), rResId, pParent)
{
    EnableContextMenuHandling();
}

//-------------------------------------------------------------------------

PopupMenu* SfxActionListBox::CreateContextMenu( void )
{
    //added by BerryJia for fixing Bug102739 2002-9-9 17:00(Beijing Time)
    if( !( GetSelectionCount() > 0 ) )
    {
        pDialog->EnableEdit( FALSE );
        pDialog->EnableDel( FALSE );
    }
    return pDialog->CreateContextMenu();
}

//-------------------------------------------------------------------------

SfxTemplateDialogWrapper::SfxTemplateDialogWrapper(Window *pParent,
        USHORT nId,  SfxBindings *p, SfxChildWinInfo *pInfo) :
    SfxChildWindow(pParent, nId)
{
    SfxTemplateDialog *pWin = new SfxTemplateDialog(p, this, pParent);
    pWindow = pWin;
    eChildAlignment = SFX_ALIGN_NOALIGNMENT;

    pWin->Initialize( pInfo );
    pWin->SetMinOutputSizePixel(pWin->pImpl->GetMinOutputSizePixel());
}

void SfxTemplateDialogWrapper::SetParagraphFamily()
{
    // forward to SfxTemplateDialog, because SfxTemplateDialog isn't exported
    static_cast< SfxTemplateDialog* >( GetWindow() )->SetParagraphFamily();
}

//=========================================================================
SV_DECL_PTRARR_DEL(ExpandedEntries, StringPtr,16,8)
SV_IMPL_PTRARR(ExpandedEntries, StringPtr)

/*  [Beschreibung]

    TreeListBox- Klasse f"ur die Anzeige der hierarchischen View
    der Vorlagen

*/

class StyleTreeListBox_Impl : public DropListBox_Impl
{
private:
    SvLBoxEntry*                    pCurEntry;
    SfxCommonTemplateDialog_Impl*   pCommon;
    Link                            aDoubleClickLink;
    Link                            aDropLink;
    String                          aParent;
    String                          aStyle;

protected:
    virtual void    Command( const CommandEvent& rMEvt );
    virtual long    Notify( NotifyEvent& rNEvt );
    virtual BOOL    DoubleClickHdl();
    virtual long    ExpandingHdl();
    virtual void    ExpandedHdl();
    virtual BOOL    NotifyMoving(SvLBoxEntry*  pTarget,
                                 SvLBoxEntry*  pEntry,
                                 SvLBoxEntry*& rpNewParent,
                                 ULONG&        rNewChildPos);
public:
    StyleTreeListBox_Impl( SfxCommonTemplateDialog_Impl* pParent, WinBits nWinStyle = 0);

    void                SetDoubleClickHdl(const Link &rLink) { aDoubleClickLink = rLink; }
    void                SetDropHdl(const Link &rLink) { aDropLink = rLink; }
    const String&       GetParent() const { return aParent; }
    const String&       GetStyle() const { return aStyle; }
    void                MakeExpanded_Impl(ExpandedEntries& rEntries) const;

    virtual PopupMenu*  CreateContextMenu( void );
};

//-------------------------------------------------------------------------


void StyleTreeListBox_Impl::MakeExpanded_Impl(ExpandedEntries& rEntries) const
{
    SvLBoxEntry *pEntry;
    USHORT nCount=0;
    for(pEntry=(SvLBoxEntry*)FirstVisible();pEntry;pEntry=(SvLBoxEntry*)NextVisible(pEntry))
    {
        if(IsExpanded(pEntry))
        {
            StringPtr pString=new String(GetEntryText(pEntry));
            rEntries.Insert(pString,nCount++);
        }
    }
}

PopupMenu* StyleTreeListBox_Impl::CreateContextMenu()
{
    return pDialog->CreateContextMenu();
}

BOOL StyleTreeListBox_Impl::DoubleClickHdl()

/*  [Beschreibung]


    DoubleClick-Handler; ruft entsprechenden Link.
    Virtuelle Methode aus SV.

*/
{
    aDoubleClickLink.Call(this);
    return FALSE;
}

//-------------------------------------------------------------------------

void StyleTreeListBox_Impl::Command( const CommandEvent& rCEvt )

/*  [Beschreibung]

    Command Handler; dieser executed ein PopupMenu (Gestalter
    spezifisch).
    Virtuelle Methode aus SV.

*/
{
    SvTreeListBox::Command(rCEvt);
}

//-------------------------------------------------------------------------

long StyleTreeListBox_Impl::Notify( NotifyEvent& rNEvt )
{
    // handle <RETURN> as double click

    long nRet = 0;
    if ( rNEvt.GetType() == EVENT_KEYINPUT )
    {
        const KeyCode&  rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
        if ( !rKeyCode.GetModifier() && KEY_RETURN == rKeyCode.GetCode() )
        {
            aDoubleClickLink.Call( this );
            nRet = 1;
        }
    }

    if ( !nRet )
        nRet = DropListBox_Impl::Notify( rNEvt );

    return nRet;
}

//-------------------------------------------------------------------------

BOOL StyleTreeListBox_Impl::NotifyMoving(SvLBoxEntry*  pTarget,
                                         SvLBoxEntry*  pEntry,
                                         SvLBoxEntry*& rpNewParent,
                                         ULONG& lPos)
/*  [Beschreibung]

    NotifyMoving Handler; dieser leitet per Link das Event an den Dialog
    weiter.
    Virtuelle Methode aus SV.

*/
{
    if(!pTarget || !pEntry)
        return FALSE;
    aParent = GetEntryText(pTarget);
    aStyle  = GetEntryText(pEntry);
    const BOOL bRet = (BOOL)aDropLink.Call(this);
    rpNewParent = pTarget;
    lPos=0;
    IntlWrapper aIntlWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() );
    const CollatorWrapper* pCollator = aIntlWrapper.getCaseCollator();
    for(SvLBoxEntry *pTmpEntry=FirstChild(pTarget);
        pTmpEntry && COMPARE_LESS==pCollator->compareString(
            GetEntryText(pTmpEntry),GetEntryText(pEntry));
        pTmpEntry=NextSibling(pTmpEntry),lPos++);

    return bRet? (BOOL)2: FALSE;
}

//-------------------------------------------------------------------------

long  StyleTreeListBox_Impl::ExpandingHdl()

/*  [Beschreibung]

    ExpandingHdl Handler; der aktuelle Eintrag wird gemerkt.
    Virtuelle Methode aus SV.

    [Querverweise]
    <StyleTreeListBox_Impl::ExpandedHdl()>

*/
{
    pCurEntry = GetCurEntry();
    return TRUE;
}

//-------------------------------------------------------------------------

void  StyleTreeListBox_Impl::ExpandedHdl()

/*  [Beschreibung]

    ExpandedHdl Handler;
    Virtuelle Methode aus SV.

    [Querverweise]
    <StyleTreeListBox_Impl::ExpandingHdl()>

*/

{
    SvLBoxEntry *pEntry = GetHdlEntry();
    if(!IsExpanded(pEntry) && pCurEntry != GetCurEntry())
        SelectAll( FALSE );
    pCurEntry = 0;
}

//-------------------------------------------------------------------------

StyleTreeListBox_Impl::StyleTreeListBox_Impl(
    SfxCommonTemplateDialog_Impl* pParent, WinBits nWinStyle) :
    DropListBox_Impl(pParent->GetWindow(), nWinStyle, pParent),
    pCurEntry(0),
    pCommon(pParent)

/*  [Beschreibung]

    Konstruktor StyleTreeListBox_Impl

*/
{
    EnableContextMenuHandling();
}

//-------------------------------------------------------------------------
//-------------------------------------------------------------------------

class StyleTreeArr_Impl;


/*  [Beschreibung]

    Interne Struktur f"ur den Aufbau der hierarchischen View

*/

struct StyleTree_Impl
{
    String aName;
    String aParent;
    StyleTreeArr_Impl *pChilds;
    BOOL bIsExpanded;
    BOOL HasParent() const { return aParent.Len() != 0; }

    StyleTree_Impl(const String &rName, const String &rParent):
        aName(rName), aParent(rParent), pChilds(0), bIsExpanded(0) {}
    ~StyleTree_Impl();
    void Put(StyleTree_Impl* pIns, ULONG lPos=ULONG_MAX);
    ULONG Count();
};

typedef StyleTree_Impl* StyleTree_ImplPtr;
SV_DECL_PTRARR_DEL(StyleTreeArr_Impl, StyleTree_ImplPtr, 16, 8)
SV_IMPL_PTRARR(StyleTreeArr_Impl, StyleTree_ImplPtr)


ULONG StyleTree_Impl::Count()
{
    return pChilds ? pChilds->Count() : 0L;
}

//-------------------------------------------------------------------------

StyleTree_Impl::~StyleTree_Impl()
{
    delete pChilds;
}

//-------------------------------------------------------------------------

void StyleTree_Impl::Put(StyleTree_Impl* pIns, ULONG lPos)
{
    if ( !pChilds )
        pChilds = new StyleTreeArr_Impl;

    if ( ULONG_MAX == lPos )
        lPos = pChilds->Count();
    pChilds->Insert( pIns, (USHORT)lPos );
}

//-------------------------------------------------------------------------

StyleTreeArr_Impl &MakeTree_Impl(StyleTreeArr_Impl &rArr)
{
    const USHORT nCount = rArr.Count();
    // Alle unter ihren Parents einordnen
    USHORT i;
    for(i = 0; i < nCount; ++i)
    {
        StyleTree_ImplPtr pEntry = rArr[i];
        if(pEntry->HasParent())
        {
            for(USHORT j = 0; j < nCount; ++j)
            {
                StyleTree_ImplPtr pCmp = rArr[j];
                if(pCmp->aName == pEntry->aParent)
                {
                    // initial sortiert einfuegen
                    USHORT ii;
                    IntlWrapper aIntlWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() );
                    const CollatorWrapper* pCollator = aIntlWrapper.getCaseCollator();
                    for ( ii = 0;
                         ii < pCmp->Count() && COMPARE_LESS ==
                         pCollator->compareString( (*pCmp->pChilds)[ii]->aName,
                                        pEntry->aName);++ii);
                    pCmp->Put(pEntry,ii);
                    break;
                }
            }
        }
    }
    // alle, die schon unter ihrem Parent eingeordnet wurden
    // entfernen
    for(i = 0; i < rArr.Count(); )
    {
        if(rArr[i]->HasParent())
            rArr.Remove(i);
        else
            ++i;
    }
    return rArr;
}

//-------------------------------------------------------------------------


inline BOOL IsExpanded_Impl( const ExpandedEntries& rEntries,
                             const String &rStr)
{
    USHORT nCount=rEntries.Count();
    for(USHORT n=0;n<nCount;n++)
        if(*rEntries[n]==rStr)
            return TRUE;
    return FALSE;
}



SvLBoxEntry* FillBox_Impl(SvTreeListBox *pBox,
                                 StyleTree_ImplPtr pEntry,
                                 const ExpandedEntries& rEntries,
                                 SvLBoxEntry* pParent = 0)
{
    SvLBoxEntry* pNewEntry = pBox->InsertEntry(pEntry->aName, pParent);
    const USHORT nCount = pEntry->pChilds? pEntry->pChilds->Count(): 0;
    for(USHORT i = 0; i < nCount; ++i)
        FillBox_Impl(pBox, (*pEntry->pChilds)[i], rEntries, pNewEntry);
    return pNewEntry;
}

//-------------------------------------------------------------------------

// Konstruktor

SfxCommonTemplateDialog_Impl::SfxCommonTemplateDialog_Impl( SfxBindings* pB, SfxDockingWindow* pW ) :

    aISfxTemplateCommon     ( this ),
    pBindings               ( pB ),
    pWindow                 ( pW ),
    pModule                 ( NULL ),
    pTimer                  ( NULL ),
    pStyleSheetPool         ( NULL ),
    pTreeBox                ( NULL ),
    pCurObjShell            ( NULL ),

    aFmtLb                  ( this, WB_BORDER | WB_TABSTOP | WB_SORT ),
    aFilterLb               ( pW, WB_BORDER | WB_DROPDOWN | WB_TABSTOP ),

    nActFamily              ( 0xffff ),
    nActFilter              ( 0 ),
    nAppFilter              ( 0 ),

    bDontUpdate             ( FALSE ),
    bIsWater                ( FALSE ),
    bEnabled                ( TRUE ),
    bUpdate                 ( FALSE ),
    bUpdateFamily           ( FALSE ),
    bCanEdit                ( FALSE ),
    bCanDel                 ( FALSE ),
    bCanNew                 ( TRUE ),
    bWaterDisabled          ( FALSE ),
    bNewByExampleDisabled   ( FALSE ),
    bUpdateByExampleDisabled( FALSE ),
    bTreeDrag               ( TRUE ),
    bHierarchical           ( FALSE ),
    bBindingUpdate          ( TRUE ),
    m_pStyleFamiliesId      ( NULL )
{
    aFmtLb.SetHelpId( HID_TEMPLATE_FMT );
    aFilterLb.SetHelpId( HID_TEMPLATE_FILTER );
    aFmtLb.SetWindowBits( WB_SORT | WB_HIDESELECTION );
    Font aFont = aFmtLb.GetFont();
    aFont.SetWeight( WEIGHT_NORMAL );
#ifdef MAC
    aFont.SetName( String::CreateFromAscii( "Geneva" ) );
    aFont.SetSize( Size( 0, 10 ) );
#endif
    aFmtLb.SetFont( aFont );
}

//-------------------------------------------------------------------------

SfxCommonTemplateDialog_Impl::SfxCommonTemplateDialog_Impl( SfxBindings* pB, ModalDialog* pW ) :

    aISfxTemplateCommon     ( this ),
    pBindings               ( pB ),
    pWindow                 ( pW ),
    pModule                 ( NULL ),
    pTimer                  ( NULL ),
    pStyleSheetPool         ( NULL ),
    pTreeBox                ( NULL ),
    pCurObjShell            ( NULL ),

    aFmtLb                  ( this, SfxResId( BT_VLIST ) ),
    aFilterLb               ( pW, SfxResId( BT_FLIST ) ),

    nActFamily              ( 0xffff ),
    nActFilter              ( 0 ),
    nAppFilter              ( 0 ),

    bDontUpdate             ( FALSE ),
    bIsWater                ( FALSE ),
    bEnabled                ( TRUE ),
    bUpdate                 ( FALSE ),
    bUpdateFamily           ( FALSE ),
    bCanEdit                ( FALSE ),
    bCanDel                 ( FALSE ),
    bCanNew                 ( TRUE ),
    bWaterDisabled          ( FALSE ),
    bNewByExampleDisabled   ( FALSE ),
    bUpdateByExampleDisabled( FALSE ),
    bTreeDrag               ( TRUE ),
    bHierarchical           ( FALSE ),
    bBindingUpdate          ( TRUE )

{
    aFmtLb.SetWindowBits( WB_SORT );
}

//-------------------------------------------------------------------------

USHORT SfxCommonTemplateDialog_Impl::StyleNrToInfoOffset(USHORT nId)
{
    const SfxStyleFamilyItem *pItem=pStyleFamilies->GetObject(nId);
    return SfxFamilyIdToNId(pItem->GetFamily())-1;
}

//-------------------------------------------------------------------------

void SfxTemplateDialog_Impl::EnableEdit(BOOL bEnable)
{
    SfxCommonTemplateDialog_Impl::EnableEdit( bEnable );
    if( !bEnable || !bUpdateByExampleDisabled )
        EnableItem( SID_STYLE_UPDATE_BY_EXAMPLE, bEnable);
}

//-------------------------------------------------------------------------


USHORT SfxCommonTemplateDialog_Impl::InfoOffsetToStyleNr(USHORT nId)
{
    for ( USHORT i=0;i<pStyleFamilies->Count();i++ )
        if ( SfxFamilyIdToNId(pStyleFamilies->GetObject(i)->GetFamily()) == nId+1 )
            return i;
    DBG_ERROR("Style Nummer nicht gefunden");
    return 0;
}


//-------------------------------------------------------------------------

void SfxCommonTemplateDialog_Impl::ReadResource()
{
    // globale Benutzer-Resource auslesen
    USHORT i;
    for(i = 0; i < MAX_FAMILIES; ++i)
        pFamilyState[i] = 0;

    SfxViewFrame* pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame();
    pCurObjShell = pViewFrame->GetObjectShell();
    ResMgr* pMgr = pCurObjShell ? pCurObjShell->GetResMgr() : NULL;
    ResId aFamId( DLG_STYLE_DESIGNER, pMgr );
    aFamId.SetRT(RSC_SFX_STYLE_FAMILIES);
    m_pStyleFamiliesId = new ResId( aFamId );
    if( !pMgr || !pMgr->IsAvailable( aFamId ) )
        pStyleFamilies = new SfxStyleFamilies;
    else
        pStyleFamilies = new SfxStyleFamilies( aFamId );

    nActFilter = pCurObjShell ? pCurObjShell->Get_Impl()->nStyleFilter : 0xFFFF;

        // Einfuegen in die Toolbox
        // umgekehrte Reihenfolge, da immer vorne eingefuegt wird.
    USHORT nCount = pStyleFamilies->Count();

    pBindings->ENTERREGISTRATIONS();

    for(i = 0; i < nCount; ++i)
    {
        USHORT nSlot = 0;
        switch((USHORT)pStyleFamilies->GetObject(i)->GetFamily())
        {
            case SFX_STYLE_FAMILY_CHAR: nSlot = SID_STYLE_FAMILY1; break;
            case SFX_STYLE_FAMILY_PARA: nSlot = SID_STYLE_FAMILY2; break;
            case SFX_STYLE_FAMILY_FRAME:nSlot = SID_STYLE_FAMILY3; break;
            case SFX_STYLE_FAMILY_PAGE: nSlot = SID_STYLE_FAMILY4; break;
            case SFX_STYLE_FAMILY_PSEUDO: nSlot = SID_STYLE_FAMILY5; break;
            default: DBG_ERROR("unbekannte StyleFamily"); break;
        }
        pBoundItems[i] =
            new SfxTemplateControllerItem(nSlot, *this, *pBindings);
    }
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_WATERCAN, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_NEW_BY_EXAMPLE, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_UPDATE_BY_EXAMPLE, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_NEW, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_DRAGHIERARCHIE, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_EDIT, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_DELETE, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_FAMILY, *this, *pBindings);
    pBindings->LEAVEREGISTRATIONS();

    for(; i < COUNT_BOUND_FUNC; ++i)
        pBoundItems[i] = 0;

    StartListening(*pBindings);

//In umgekehrter Reihenfolge des Auftretens in den Stylefamilies einfuegen.
//Das ist fuer den Toolbar des Gestalters. Die Listbox des Kataloges achtet
//selbst auf korrekte Reihenfolge.

//Reihenfolgen: Reihenfolge in der Resource = Reihenfolge in Toolbar bzw.
//Listbox.
//Reihenfolge aufsteigender SIDs: Niedrige SIDs werden als erstes angezeigt,
//wenn Vorlagen mehrerer Familien aktiv sind.

    // in the Writer the UpdateStyleByExample Toolbox button is removed and
    // the NewStyle button gets a PopupMenu
    if(nCount > 4)
        ReplaceUpdateButtonByMenu();

    for( ; nCount--; )
    {
        const SfxStyleFamilyItem *pItem = pStyleFamilies->GetObject( nCount );
        USHORT nId = SfxFamilyIdToNId( (USHORT) pItem->GetFamily() );
        InsertFamilyItem( nId, pItem );
    }

    LoadedFamilies();

    USHORT nStart = SID_STYLE_FAMILY1;
    USHORT nEnd = SID_STYLE_FAMILY4;

    for ( i = nStart; i <= nEnd; i++ )
        pBindings->Update(i);

    pModule = pCurObjShell ? pCurObjShell->GetModule() : NULL;
}

//-------------------------------------------------------------------------

void SfxCommonTemplateDialog_Impl::ClearResource()
{
    ClearFamilyList();
    DELETEX(pStyleFamilies);
    USHORT i;
    for ( i = 0; i < MAX_FAMILIES; ++i )
        DELETEX(pFamilyState[i]);
    for ( i = 0; i < COUNT_BOUND_FUNC; ++i )
        delete pBoundItems[i];
    pCurObjShell = NULL;

    DELETEZ( m_pStyleFamiliesId );
}

//-------------------------------------------------------------------------

void SfxCommonTemplateDialog_Impl::Initialize()
{
    // globale Benutzer-Resource auslesen
    ReadResource();
    pBindings->Invalidate( SID_STYLE_FAMILY );
    pBindings->Update( SID_STYLE_FAMILY );
    Update_Impl();

    aFilterLb.SetSelectHdl( LINK( this, SfxCommonTemplateDialog_Impl, FilterSelectHdl ) );
    aFmtLb.SetDoubleClickHdl( LINK( this, SfxCommonTemplateDialog_Impl, ApplyHdl ) );
    aFmtLb.SetSelectHdl( LINK( this, SfxCommonTemplateDialog_Impl, FmtSelectHdl ) );

    aFilterLb.Show();
    aFmtLb.Show();
}

//-------------------------------------------------------------------------

SfxCommonTemplateDialog_Impl::~SfxCommonTemplateDialog_Impl()
{
    String aEmpty;
    if ( bIsWater )
        Execute_Impl(SID_STYLE_WATERCAN, aEmpty, aEmpty, 0);
    GetWindow()->Hide();
    DELETEX(pStyleFamilies);
    DELETEZ( m_pStyleFamiliesId );
    USHORT i;
    for ( i = 0; i < MAX_FAMILIES; ++i )
        DELETEX(pFamilyState[i]);
    for ( i = 0; i < COUNT_BOUND_FUNC; ++i )
        delete pBoundItems[i];
    if ( pStyleSheetPool )
        EndListening(*pStyleSheetPool);
    pStyleSheetPool = NULL;
    delete pTreeBox;
    delete pTimer;
}

//-------------------------------------------------------------------------

USHORT SfxCommonTemplateDialog_Impl::SfxFamilyIdToNId( USHORT nFamily )
{
    switch ( nFamily )
    {
        case SFX_STYLE_FAMILY_CHAR:     return 1; break;
        case SFX_STYLE_FAMILY_PARA:     return 2; break;
        case SFX_STYLE_FAMILY_FRAME:    return 3; break;
        case SFX_STYLE_FAMILY_PAGE:     return 4; break;
        case SFX_STYLE_FAMILY_PSEUDO:   return 5; break;
        default:                        return 0;
    }
}

void SfxCommonTemplateDialog_Impl::SetAutomaticFilter()
{
    USHORT nCount = aFilterLb.GetEntryCount();
    for ( USHORT i = 0; i < nCount; ++i )
    {
        ULONG nFlags = (ULONG)aFilterLb.GetEntryData(i);
        if ( SFXSTYLEBIT_AUTO == nFlags )
        {
            // automatic entry found -> select it
            aFilterLb.SelectEntryPos(i);
            // then call the handler to filter the styles
            FilterSelect( i - 1 );
            break;
        }
    }
}

//-------------------------------------------------------------------------

// Hilfsfunktion: Zugriff auf aktuelles Family-Item
const SfxStyleFamilyItem *SfxCommonTemplateDialog_Impl::GetFamilyItem_Impl() const
{
    const USHORT nCount = pStyleFamilies->Count();
    for(USHORT i = 0; i < nCount; ++i)
    {
        const SfxStyleFamilyItem *pItem = pStyleFamilies->GetObject(i);
//        if(!pItem)continue;
        USHORT nId = SfxFamilyIdToNId((USHORT)pItem->GetFamily());
        if(nId == nActFamily)
            return pItem;
    }
    return 0;
}

//-------------------------------------------------------------------------

void SfxCommonTemplateDialog_Impl::SelectStyle(const String &rStr)
{
    const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl();
    if ( !pItem )
        return;
    const SfxStyleFamily eFam = pItem->GetFamily();
    SfxStyleSheetBase* pStyle = pStyleSheetPool->Find( rStr, eFam, SFXSTYLEBIT_ALL );
    if( pStyle )
        EnableEdit( !(pStyle->GetMask() & SFXSTYLEBIT_READONLY) );
    else
        EnableEdit(FALSE);

    if ( pTreeBox )
    {
        if ( rStr.Len() )
        {
            SvLBoxEntry* pEntry = pTreeBox->First();
            while ( pEntry )
            {
                if ( pTreeBox->GetEntryText( pEntry ) == rStr )
                {
                    pTreeBox->MakeVisible( pEntry );
                    pTreeBox->Select( pEntry );
                    return;
                }
                pEntry = pTreeBox->Next( pEntry );
            }
        }
        else
            pTreeBox->SelectAll( FALSE );
    }
    else
    {
        BOOL bSelect = ( rStr.Len() > 0 );
        if ( bSelect )
        {
            SvLBoxEntry* pEntry = (SvLBoxEntry*)aFmtLb.FirstVisible();
            while ( pEntry && aFmtLb.GetEntryText( pEntry ) != rStr )
                pEntry = (SvLBoxEntry*)aFmtLb.NextVisible( pEntry );
            if ( !pEntry )
                bSelect = FALSE;
            else
            {
                aFmtLb.MakeVisible( pEntry );
                aFmtLb.Select( pEntry );
                bWaterDisabled = !HasSelectedStyle(); //added by BerryJia for fixing Bug76391 2003-1-22
                FmtSelectHdl( NULL );
            }
        }

        if ( !bSelect )
        {
            aFmtLb.SelectAll( FALSE );
            EnableEdit(FALSE);
        }
    }
}

//-------------------------------------------------------------------------

String SfxCommonTemplateDialog_Impl::GetSelectedEntry() const
{
    String aRet;
    if ( pTreeBox )
    {
        SvLBoxEntry* pEntry = pTreeBox->FirstSelected();
        if ( pEntry )
            aRet = pTreeBox->GetEntryText( pEntry );
    }
    else
    {
        SvLBoxEntry* pEntry = aFmtLb.FirstSelected();
        if ( pEntry )
            aRet = aFmtLb.GetEntryText( pEntry );
    }
    return aRet;
}

//-------------------------------------------------------------------------

void SfxCommonTemplateDialog_Impl::EnableTreeDrag( BOOL bEnable )
{
    if ( pStyleSheetPool )
    {
        SfxStyleSheetBase* pStyle = pStyleSheetPool->First();
        if ( pTreeBox )
        {
            if ( pStyle && pStyle->HasParentSupport() && bEnable )
                pTreeBox->SetDragDropMode(SV_DRAGDROP_CTRL_MOVE);
            else
                pTreeBox->SetDragDropMode(SV_DRAGDROP_NONE);
        }
    }
    bTreeDrag = bEnable;
}

//-------------------------------------------------------------------------

void SfxCommonTemplateDialog_Impl::FillTreeBox()
{
    DBG_ASSERT( pTreeBox, "FillTreeBox() without treebox");
    if(pStyleSheetPool && nActFamily != 0xffff)
    {
        const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl();
        pStyleSheetPool->SetSearchMask(pItem->GetFamily(), SFXSTYLEBIT_ALL);
        StyleTreeArr_Impl aArr;
        SfxStyleSheetBase *pStyle = pStyleSheetPool->First();
        if(pStyle && pStyle->HasParentSupport() && bTreeDrag )
            pTreeBox->SetDragDropMode(SV_DRAGDROP_CTRL_MOVE);
        else
            pTreeBox->SetDragDropMode(SV_DRAGDROP_NONE);
        while(pStyle)
        {
            StyleTree_ImplPtr pNew =
                new StyleTree_Impl(pStyle->GetName(), pStyle->GetParent());
            aArr.Insert(pNew, aArr.Count());
            pStyle = pStyleSheetPool->Next();
        }
        MakeTree_Impl(aArr);
        ExpandedEntries aEntries;
        if(pTreeBox)
            ((const StyleTreeListBox_Impl *)pTreeBox)->
                MakeExpanded_Impl( aEntries);
        pTreeBox->SetUpdateMode( FALSE );
        pTreeBox->Clear();
        const USHORT nCount = aArr.Count();
        for(USHORT i = 0; i < nCount; ++i)
            FillBox_Impl(pTreeBox, aArr[i], aEntries);

//      EnableEdit(FALSE);
        EnableItem(SID_STYLE_WATERCAN,FALSE);

        SfxTemplateItem* pState = pFamilyState[nActFamily-1];

        if ( nCount )
            pTreeBox->Expand( pTreeBox->First() );

        for ( SvLBoxEntry* pEntry = pTreeBox->First(); pEntry; pEntry = pTreeBox->Next( pEntry ) )
        {
            if ( IsExpanded_Impl( aEntries, pTreeBox->GetEntryText( pEntry ) ) )
                pTreeBox->Expand( pEntry );
        }

        pTreeBox->SetUpdateMode( TRUE );

        String aStyle;
        if(pState)  //Aktuellen Eintrag selektieren
            aStyle = pState->GetStyleName();
        SelectStyle(aStyle);
        EnableDelete();
    }
}

//-------------------------------------------------------------------------
BOOL SfxCommonTemplateDialog_Impl::HasSelectedStyle() const
{
    return pTreeBox? pTreeBox->FirstSelected() != 0:
            aFmtLb.GetSelectionCount() != 0;
}


//-------------------------------------------------------------------------

// intern: Aktualisierung der Anzeige
void SfxCommonTemplateDialog_Impl::UpdateStyles_Impl(USHORT nFlags)     // Flags, was aktualisiert werden soll (s.o.)
{
    DBG_ASSERT(nFlags, "nichts zu tun");
    const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl();
    if (!pItem)
    {
        // Ist beim Vorlagenkatalog der Fall
        SfxTemplateItem **ppItem = pFamilyState;
        const USHORT nFamilyCount = pStyleFamilies->Count();
        USHORT n;
        for(n=0;n<nFamilyCount;n++)
            if(ppItem[StyleNrToInfoOffset(n)])break;
        if ( n == nFamilyCount )
            // passiert gelegentlich bei Beichten, Formularen etc.; weiss der Teufel warum
            return;
        ppItem+=StyleNrToInfoOffset(n);
        nAppFilter = (*ppItem)->GetValue();
        FamilySelect(  StyleNrToInfoOffset(n)+1 );
        pItem = GetFamilyItem_Impl();
    }

    const SfxStyleFamily eFam = pItem->GetFamily();

    SfxFilterTupel *pT = pItem->GetFilterList().GetObject(nActFilter);
    USHORT nFilter = pT ? pItem->GetFilterList().GetObject(nActFilter)->nFlags : 0;
    if(!nFilter)    // automatisch
        nFilter = nAppFilter;

    DBG_ASSERT(pStyleSheetPool, "kein StyleSheetPool");
    if(pStyleSheetPool)
    {
        pStyleSheetPool->SetSearchMask(eFam, nFilter);
        const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl();
        if((nFlags & UPDATE_FAMILY) == UPDATE_FAMILY)
        {
            CheckItem(nActFamily, TRUE);    // Button in Toolbox checken
            aFilterLb.SetUpdateMode(FALSE);
            aFilterLb.Clear();
            //insert hierarchical at the beginning
            USHORT nPos = aFilterLb.InsertEntry(String(SfxResId(STR_STYLE_FILTER_HIERARCHICAL)), 0);
            aFilterLb.SetEntryData( nPos, (void*)(ULONG)SFXSTYLEBIT_ALL );
            const SfxStyleFilter& rFilter = pItem->GetFilterList();
            for(USHORT i = 0; i < rFilter.Count(); ++i)
            {
                ULONG nFlags = rFilter.GetObject(i)->nFlags;
                nPos = aFilterLb.InsertEntry( rFilter.GetObject(i)->aName );
                aFilterLb.SetEntryData( nPos, (void*)nFlags );
            }
            if(nActFilter < aFilterLb.GetEntryCount() - 1)
                aFilterLb.SelectEntryPos(nActFilter + 1);
            else
            {
                nActFilter = 0;
                aFilterLb.SelectEntryPos(1);
                SfxFilterTupel *pT = rFilter.GetObject(nActFilter);
                USHORT nFilter = pT ? rFilter.GetObject(nActFilter)->nFlags : 0;
                pStyleSheetPool->SetSearchMask(eFam, nFilter);
            }

            //Falls in Treedarstellung wieder Family Hierarchie selektieren
            if(pTreeBox)
                aFilterLb.SelectEntry(String(SfxResId(STR_STYLE_FILTER_HIERARCHICAL)));

            // show maximum seven entries
            aFilterLb.SetDropDownLineCount( MAX_FILTER_ENTRIES );
            aFilterLb.SetUpdateMode(TRUE);
        }
        else
        {
            if( nActFilter < aFilterLb.GetEntryCount() - 1)
                aFilterLb.SelectEntryPos(nActFilter + 1);
            else
            {
                nActFilter = 0;
                aFilterLb.SelectEntryPos(1);
            }
        }

        if(nFlags & UPDATE_FAMILY_LIST)
        {
//          EnableEdit(FALSE);
            EnableItem(SID_STYLE_WATERCAN,FALSE);

            SfxStyleSheetBase *pStyle = pStyleSheetPool->First();
            SvLBoxEntry* pEntry = aFmtLb.First();
            SvStringsDtor aStrings;

            while( pStyle )
            {
                //Bubblesort
                for( USHORT nPos = aStrings.Count() + 1 ; nPos-- ;)
                {
                    if( !nPos || *aStrings[nPos-1] < pStyle->GetName() )
                    {
                        // Die Namen stehen in den Styles, also nicht kopieren
                        // Reingefallen!: Writer hat insgesamt nur 1 Style
                        aStrings.Insert(
                            new String( pStyle->GetName() ), nPos );
                        break;
                    }
                }
                pStyle = pStyleSheetPool->Next();
            }


            USHORT nCount = aStrings.Count();
            USHORT nPos = 0;
            while( nPos < nCount && pEntry &&
                   *aStrings[ nPos ] == aFmtLb.GetEntryText( pEntry ) )
            {
                nPos++;
                pEntry = aFmtLb.Next( pEntry );
            }

            if( nPos < nCount || pEntry )
            {
                // Box mit den Vorlagen fuellen
                aFmtLb.SetUpdateMode(FALSE);
                aFmtLb.Clear();

                nPos = 0;
                while( nPos < nCount )
                    aFmtLb.InsertEntry( *aStrings.GetObject( nPos++ ));
                aFmtLb.SetUpdateMode(TRUE);
            }
                // aktuelle Vorlage anzeigen
            SfxTemplateItem *pState = pFamilyState[nActFamily-1];
            String aStyle;
            if(pState)  //Aktuellen Eintrag selektieren
                aStyle = pState->GetStyleName();
            SelectStyle(aStyle);
            EnableDelete();
        }
    }
}

//-------------------------------------------------------------------------

// Aktualisierung Anzeige: Gie\skanne an/aus
void SfxCommonTemplateDialog_Impl::SetWaterCanState(const SfxBoolItem *pItem)
{
//  EnableItem(SID_STYLE_WATERCAN, pItem != 0);
    bWaterDisabled =  pItem == 0;
//added by BerryJia for fixing Bug76391 2003-1-7
    if(!bWaterDisabled)
        bWaterDisabled = !HasSelectedStyle();

    if(pItem && !bWaterDisabled)
    {
        CheckItem(SID_STYLE_WATERCAN, pItem->GetValue());
        EnableItem( SID_STYLE_WATERCAN, TRUE );
    }
    else
        if(!bWaterDisabled)
            EnableItem(SID_STYLE_WATERCAN, TRUE);
        else
            EnableItem(SID_STYLE_WATERCAN, FALSE);

//Waehrend Giesskannenmodus Statusupdates ignorieren.

    USHORT nCount=pStyleFamilies->Count();
    pBindings->EnterRegistrations();
    for(USHORT n=0; n<nCount; n++)
    {
        SfxControllerItem *pCItem=pBoundItems[n];
        BOOL bChecked = pItem && pItem->GetValue();
        if( pCItem->IsBound() == bChecked )
            if( !bChecked )
                pCItem->ReBind();
            else
                pCItem->UnBind();
    }
    pBindings->LeaveRegistrations();
}

//-------------------------------------------------------------------------

// Item mit dem Status einer Family wird kopiert und gemerkt
// (Aktualisierung erfolgt, wenn alle Stati aktualisiert worden sind.
// Siehe auch: <SfxBindings::AddDoneHdl(const Link &)>

void SfxCommonTemplateDialog_Impl::SetFamilyState( USHORT nSlotId, const SfxTemplateItem* pItem )
{
    USHORT nIdx = nSlotId - SID_STYLE_FAMILY_START;
    DELETEZ(pFamilyState[nIdx]);
    if ( pItem )
        pFamilyState[nIdx] = new SfxTemplateItem(*pItem);
    bUpdate = TRUE;

    // Wenn verwendete Vorlagen ( wie zum Teufel findet man das heraus ?? )
    bUpdateFamily = TRUE;
}

//-------------------------------------------------------------------------

// Benachrichtigung durch SfxBindings, da"s die Aktualisierung
// beendet ist. St"o\st die Aktualisierung der Anzeige an.

void SfxCommonTemplateDialog_Impl::Update_Impl()
{
    BOOL bDocChanged=FALSE;
    SfxStyleSheetBasePool *pNewPool = 0;
    SfxViewFrame *pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame();
    SfxObjectShell *pDocShell = pViewFrame->GetObjectShell();
    if( pDocShell )
        pNewPool = pDocShell->GetStyleSheetPool();

    if ( pNewPool != pStyleSheetPool && pDocShell )
    {
        SfxModule* pNewModule = pDocShell->GetModule();
        if( pNewModule && pNewModule != pModule )
        {
            ClearResource();
            ReadResource();
        }
        if ( pStyleSheetPool )
        {
            EndListening(*pStyleSheetPool);
            pStyleSheetPool = 0;
        }

        if ( pNewPool )
        {
            StartListening(*pNewPool);
            pStyleSheetPool = pNewPool;
            bDocChanged=TRUE;
        }
//      InvalidateBindings();
    }

    if (bUpdateFamily)
        UpdateFamily_Impl();

    USHORT i;
    for(i = 0; i < MAX_FAMILIES; ++i)
        if(pFamilyState[i])
            break;
    if(i == MAX_FAMILIES || !pNewPool)
        // nichts erlaubt
        return;

     SfxTemplateItem *pItem = 0;
     // aktueller Bereich nicht innerhalb der erlaubten Bereiche
     // oder Default
     if(nActFamily == 0xffff || 0 == (pItem = pFamilyState[nActFamily-1] ) )
     {
         CheckItem(nActFamily, FALSE);
         SfxTemplateItem **ppItem = pFamilyState;
         const USHORT nFamilyCount = pStyleFamilies->Count();
         USHORT n;
         for(n=0;n<nFamilyCount;n++)
             if(ppItem[StyleNrToInfoOffset(n)])break;
         ppItem+=StyleNrToInfoOffset(n);

         nAppFilter = (*ppItem)->GetValue();
         FamilySelect(  StyleNrToInfoOffset(n)+1 );

         pItem = *ppItem;
     }
     else if( bDocChanged )
     {
         // andere DocShell -> alles neu
         CheckItem( nActFamily, TRUE );
         nActFilter = pDocShell->Get_Impl()->nStyleFilter;
         nAppFilter = pItem->GetValue();
         if(!pTreeBox)
         {
             UpdateStyles_Impl(UPDATE_FAMILY_LIST);
         }
         else
             FillTreeBox();
     }
     else
     {
         // anderer Filter fuer automatisch
         CheckItem( nActFamily, TRUE );
         const SfxStyleFamilyItem *pStyleItem =  GetFamilyItem_Impl();
#if OSL_DEBUG_LEVEL > 1
         SfxFilterTupel *pT = pStyleItem->GetFilterList().GetObject(nActFilter);
#endif
         if(0 == pStyleItem->GetFilterList().GetObject(nActFilter)->nFlags
            && nAppFilter != pItem->GetValue())
         {
             nAppFilter = pItem->GetValue();
             if(!pTreeBox)
                 UpdateStyles_Impl(UPDATE_FAMILY_LIST);
             else
                 FillTreeBox();
         }
         else
             nAppFilter = pItem->GetValue();
     }
     const String aStyle(pItem->GetStyleName());
     SelectStyle(aStyle);
     EnableDelete();
     EnableNew( bCanNew );
}

//-------------------------------------------------------------------------

IMPL_LINK( SfxCommonTemplateDialog_Impl, TimeOut, Timer *, pTim )
{
    if(!bDontUpdate)
    {
        bDontUpdate=TRUE;
        if(!pTreeBox)
            UpdateStyles_Impl(UPDATE_FAMILY_LIST);
        else
        {
            FillTreeBox();
            SfxTemplateItem *pState = pFamilyState[nActFamily-1];
            if(pState)
            {
                const String aStyle(pState->GetStyleName());
                SelectStyle(aStyle);
                EnableDelete();
            }
        }
        bDontUpdate=FALSE;
        DELETEZ(pTimer);
    }
    else
        pTimer->Start();
    return 0;
}


//-------------------------------------------------------------------------
void SfxCommonTemplateDialog_Impl::SFX_NOTIFY(SfxBroadcaster& rBC, const TypeId& rBCType,
                                          const SfxHint& rHint, const TypeId& rHintType)
{
    // Aktualisierung anstossen
    if(rHint.Type() == TYPE(SfxSimpleHint))
    {
        switch(((SfxSimpleHint&) rHint ).GetId())
        {
          case SFX_HINT_UPDATEDONE:
            {
                SfxViewFrame *pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame();
                SfxObjectShell *pDocShell = pViewFrame->GetObjectShell();
                if( bUpdate && (
                    !IsCheckedItem(SID_STYLE_WATERCAN) || pDocShell
                    && pDocShell->GetStyleSheetPool() != pStyleSheetPool) )
                {
                    bUpdate = FALSE;
                    Update_Impl();
                }
                else if ( bUpdateFamily )
                {
                    UpdateFamily_Impl();
                }

                if( pStyleSheetPool )
                {
                    String aStr = GetSelectedEntry();
                    if( aStr.Len() && pStyleSheetPool )
                    {
                        const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl();
                        if( !pItem ) break;
                        const SfxStyleFamily eFam = pItem->GetFamily();
                        SfxStyleSheetBase *pStyle =
                            pStyleSheetPool->Find(
                                aStr, eFam, SFXSTYLEBIT_ALL );
                        if( pStyle )
                            EnableEdit(
                                !(pStyle->GetMask() & SFXSTYLEBIT_READONLY) );
                        else
                            EnableEdit(FALSE);
                    }
                }
                break;
            }
        // noetig, wenn zwichen Dokumenten umgeschaltet wird,
        // aber in beiden Dokumenten die gleiche Vorlage gilt.
        // Nicht sofort Update_Impl rufen, fuer den Fall da\s eines
        // der Dokumente ein internes InPlaceObjekt ist!
          case SFX_HINT_DOCCHANGED:
            bUpdate = TRUE;
            break;
          case SFX_HINT_DYING:
          {
            EndListening(*pStyleSheetPool);
            pStyleSheetPool=0;
            break;
          }
        }
    }

    // Timer nicht aufsetzen, wenn der StyleSheetPool in die Kiste geht, denn
    // es kann sein, da\s sich ein neuer erst anmeldet, nachdem der Timer
    // abgelaufen ist - macht sich schlecht in UpdateStyles_Impl() !

    ULONG nId = ((SfxSimpleHint&) rHint).GetId();

    if(!bDontUpdate && nId != SFX_HINT_DYING &&
       (rHint.Type() == TYPE(SfxStyleSheetPoolHint)||
       rHint.Type() == TYPE(SfxStyleSheetHint) ||
       rHint.Type() == TYPE( SfxStyleSheetHintExtended )))
    {
        if(!pTimer)
        {
            pTimer=new Timer;
            pTimer->SetTimeout(500);
            pTimer->SetTimeoutHdl(LINK(this,SfxCommonTemplateDialog_Impl,TimeOut));
        }
        pTimer->Start();

    }
}


//-------------------------------------------------------------------------

// Anderer Filter; kann durch den Benutzer umgeschaltet werden
// oder als Folge von Neu oder Bearbeiten, wenn die aktuelle
// Vorlage einem anderen Filter zugewiesen wurde.
void SfxCommonTemplateDialog_Impl::FilterSelect(
                USHORT nEntry,                  // Idx des neuen Filters
                BOOL bForce )                   // Aktualisierung erzwingen, auch wenn der neue Filter gleich dem aktuellen ist
{
    if( nEntry != nActFilter || bForce )
    {
        nActFilter = nEntry;
        SfxViewFrame *pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame();
        SfxObjectShell *pDocShell = pViewFrame->GetObjectShell();
        if (pDocShell)
            pDocShell->Get_Impl()->nStyleFilter = nActFilter;

        SfxStyleSheetBasePool *pOldStyleSheetPool = pStyleSheetPool;
        pStyleSheetPool = pDocShell? pDocShell->GetStyleSheetPool(): 0;
        if ( pOldStyleSheetPool != pStyleSheetPool )
        {
            if ( pOldStyleSheetPool )
                EndListening(*pOldStyleSheetPool);
            if ( pStyleSheetPool )
                StartListening(*pOldStyleSheetPool);
        }

        UpdateStyles_Impl(UPDATE_FAMILY_LIST);
    }
}

//-------------------------------------------------------------------------

// Intern: Ausf"uhren von Funktionen "uber den Dispatcher
BOOL SfxCommonTemplateDialog_Impl::Execute_Impl(
    USHORT nId, const String &rStr, const String& rRefStr, USHORT nFamily,
    USHORT nMask, USHORT *pIdx, const USHORT* pModifier)
{
    SfxDispatcher &rDispatcher = *SFX_APP()->GetDispatcher_Impl();
    SfxStringItem aItem(nId, rStr);
    SfxUInt16Item aFamily(SID_STYLE_FAMILY, nFamily);
    SfxUInt16Item aMask( SID_STYLE_MASK, nMask );
    SfxStringItem aUpdName(SID_STYLE_UPD_BY_EX_NAME, rStr);
    SfxStringItem aRefName( SID_STYLE_REFERENCE, rRefStr );
    const SfxPoolItem* pItems[ 6 ];
    USHORT nCount = 0;
    if( rStr.Len() )
        pItems[ nCount++ ] = &aItem;
    pItems[ nCount++ ] = &aFamily;
    if( nMask )
        pItems[ nCount++ ] = &aMask;
    if(SID_STYLE_UPDATE_BY_EXAMPLE == nId)
    {
        //Sonderloesung fuer Numerierungsupdate im Writer
        const String aTemplName(GetSelectedEntry());
        aUpdName.SetValue(aTemplName);
        pItems[ nCount++ ] = &aUpdName;
    }
    if ( rRefStr.Len() )
        pItems[ nCount++ ] = &aRefName;

    pItems[ nCount++ ] = 0;

    const SfxPoolItem* pItem;
    USHORT nModi = pModifier ? *pModifier : 0;
    pItem = rDispatcher.Execute(
        nId, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD | SFX_CALLMODE_MODAL,
        pItems, nModi );

    if ( !pItem )
        return FALSE;

    if ( nId == SID_STYLE_NEW || SID_STYLE_EDIT == nId )
    {
        SfxUInt16Item *pFilterItem = PTR_CAST(SfxUInt16Item, pItem);
        DBG_ASSERT(pFilterItem, "SfxUINT16Item erwartet");
        USHORT nFilterFlags = pFilterItem->GetValue() & ~SFXSTYLEBIT_USERDEF;
        if(!nFilterFlags)       // Benutzervorlage?
            nFilterFlags = pFilterItem->GetValue();
        const SfxStyleFamilyItem *pFamilyItem = GetFamilyItem_Impl();
        const USHORT nCount = (USHORT) pFamilyItem->GetFilterList().Count();

        for ( USHORT i = 0; i < nCount; ++i )
        {
            const SfxFilterTupel *pTupel =
                pFamilyItem->GetFilterList().GetObject(i);

            if ( ( pTupel->nFlags & nFilterFlags ) == nFilterFlags && pIdx )
                *pIdx = i;
        }
    }
    return TRUE;
}

//-------------------------------------------------------------------------

// Handler der Listbox der Filter
IMPL_LINK( SfxCommonTemplateDialog_Impl, FilterSelectHdl, ListBox *, pBox )
{
    if ( pBox->GetSelectEntry() ==  String(SfxResId(STR_STYLE_FILTER_HIERARCHICAL)) )
    {
        if ( !bHierarchical )
        {
            // TreeView einschalten
            bHierarchical=TRUE;
            const String aSelectEntry( GetSelectedEntry());
            aFmtLb.Hide();
            // aFilterLb.Disable();

            pTreeBox = new StyleTreeListBox_Impl(
                    this, WB_HASBUTTONS | WB_HASLINES |
                    WB_BORDER | WB_TABSTOP | WB_HASLINESATROOT |
                    WB_HASBUTTONSATROOT | WB_HIDESELECTION );
            pTreeBox->SetFont( aFmtLb.GetFont() );

            pTreeBox->SetPosSizePixel(aFmtLb.GetPosPixel(), aFmtLb.GetSizePixel());
            pTreeBox->SetNodeDefaultImages();
            pTreeBox->SetSelectHdl(
                LINK(this, SfxCommonTemplateDialog_Impl, FmtSelectHdl));
            ((StyleTreeListBox_Impl*)pTreeBox)->
                SetDoubleClickHdl(
                    LINK(this, SfxCommonTemplateDialog_Impl,  ApplyHdl));
            ((StyleTreeListBox_Impl*)pTreeBox)->
                SetDropHdl(LINK(this, SfxCommonTemplateDialog_Impl,  DropHdl));
            pTreeBox->SetIndent(10);

            FillTreeBox();
            SelectStyle(aSelectEntry);
            pTreeBox->Show();
        }
    }

    else
    {
        DELETEZ(pTreeBox);
        aFmtLb.Show();
        //                              aFilterLb.Enable();
        // Falls bHierarchical, kann sich die Familie geaendert haben
        // minus one since hierarchical is inserted at the start
        FilterSelect(pBox->GetSelectEntryPos() - 1, bHierarchical );
        bHierarchical=FALSE;
//      UpdateStyles_Impl(UPDATE_FAMILY_LIST);  // Anzeige aktualisieren
    }

    return 0;
}

//-------------------------------------------------------------------------

// Select-Handler der Toolbox
void SfxCommonTemplateDialog_Impl::FamilySelect(USHORT nEntry)
{
    if( nEntry != nActFamily )
    {
        CheckItem( nActFamily, FALSE );
        nActFamily = nEntry;
        SfxDispatcher* pDispat = pBindings->GetDispatcher_Impl();
        SfxUInt16Item aItem( SID_STYLE_FAMILY, nEntry );
        pDispat->Execute( SID_STYLE_FAMILY, SFX_CALLMODE_SYNCHRON, &aItem, 0L );
        pBindings->Invalidate( SID_STYLE_FAMILY );
        pBindings->Update( SID_STYLE_FAMILY );
        UpdateFamily_Impl();
    }
}

//-------------------------------------------------------------------------

void SfxCommonTemplateDialog_Impl::ActionSelect(USHORT nEntry)
{
    String aEmpty;
    switch(nEntry)
    {
        case SID_STYLE_WATERCAN:
        {
            const BOOL bState = IsCheckedItem(nEntry);
            BOOL bCheck;
            SfxBoolItem aBool;
            // wenn eine Vorlage ausgewaehlt ist.
            if(!bState && aFmtLb.GetSelectionCount())
            {
                const String aTemplName(
                    GetSelectedEntry());
                Execute_Impl(
                    SID_STYLE_WATERCAN, aTemplName, aEmpty,
                    (USHORT)GetFamilyItem_Impl()->GetFamily() );
                bCheck = TRUE;
            }
            else
            {
                Execute_Impl(SID_STYLE_WATERCAN, aEmpty, aEmpty, 0);
                bCheck = FALSE;
            }
            CheckItem(nEntry, bCheck);
            aBool.SetValue(bCheck);
            SetWaterCanState(&aBool);
            break;
        }
        case SID_STYLE_NEW_BY_EXAMPLE:
        {
            if(pStyleSheetPool && nActFamily != 0xffff)
            {
                const SfxStyleFamily eFam=GetFamilyItem_Impl()->GetFamily();
//pStyleSheetPool->GetSearchFamily();
                const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl();
                USHORT nFilter;
                if(pItem&&nActFilter!=0xffff)
                {
                    nFilter = pItem->GetFilterList().GetObject(
                        nActFilter)->nFlags;
                    if(!nFilter)    // automatisch
                        nFilter = nAppFilter;
                }
                else
                    nFilter=pStyleSheetPool->GetSearchMask();
                pStyleSheetPool->SetSearchMask( eFam, SFXSTYLEBIT_USERDEF );

                SfxNewStyleDlg *pDlg =
                    // FloatingWindow must not be parent of a modal dialog
                    new SfxNewStyleDlg(SFX_APP()->GetTopWindow(), *pStyleSheetPool);
                if(RET_OK == pDlg->Execute())
                {
                    pStyleSheetPool->SetSearchMask(eFam, nFilter);
                    const String aTemplName(pDlg->GetName());
                    Execute_Impl(SID_STYLE_NEW_BY_EXAMPLE,
                                 aTemplName, aEmpty,
                                 (USHORT)GetFamilyItem_Impl()->GetFamily(),
                                 nFilter);
                }
                pStyleSheetPool->SetSearchMask( eFam, nFilter );
                delete pDlg;
            }
            break;
        }
        case SID_STYLE_UPDATE_BY_EXAMPLE:
        {
            Execute_Impl(SID_STYLE_UPDATE_BY_EXAMPLE,
                    aEmpty, aEmpty,
                    (USHORT)GetFamilyItem_Impl()->GetFamily());
            break;
        }
        case SID_TEMPLATE_LOAD:
            SFX_APP()->GetDispatcher_Impl()->Execute(nEntry);
        break;
        default: DBG_ERROR("not implemented"); break;
    }
}


//-------------------------------------------------------------------------

IMPL_LINK( SfxCommonTemplateDialog_Impl, DropHdl, StyleTreeListBox_Impl *, pBox )
{
    bDontUpdate=TRUE;
    const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl();
    const SfxStyleFamily eFam = pItem->GetFamily();
    long ret= pStyleSheetPool->SetParent(eFam,pBox->GetStyle(), pBox->GetParent())? 1L: 0L;
    bDontUpdate=FALSE;
    return ret;
}

//-------------------------------------------------------------------------

// Handler des Neu-Buttons
void SfxCommonTemplateDialog_Impl::NewHdl(void *)
{
    String aEmpty;
    if ( nActFamily != 0xffff )
    {
        Window* pTmp;
        pTmp = Application::GetDefDialogParent();
        if ( ISA(SfxTemplateDialog_Impl) )
            Application::SetDefDialogParent( pWindow->GetParent() );
        else
            Application::SetDefDialogParent( pWindow );

        const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl();
        const SfxStyleFamily eFam=pItem->GetFamily();
        USHORT nMask;
        if(pItem&&nActFilter!=0xffff)
        {
            nMask = pItem->GetFilterList().GetObject(
                nActFilter)->nFlags;
            if(!nMask)    // automatisch
                nMask = nAppFilter;
        }
        else
            nMask=pStyleSheetPool->GetSearchMask();

        pStyleSheetPool->SetSearchMask(eFam,nMask);

        Execute_Impl(SID_STYLE_NEW,
                     aEmpty, GetSelectedEntry(),
                     ( USHORT )GetFamilyItem_Impl()->GetFamily(),
                     nMask);

        Application::SetDefDialogParent( pTmp );

/*              {
            DBG_ASSERT(nFilter < aFilterLb.GetEntryCount(),
                       "Filter ueberindiziert");

            if(!pTreeBox)
            {
//                              aFilterLb.SelectEntryPos(nFilter);
                FilterSelect(nActFilter, TRUE);
            }
            else
            {
                FillTreeBox();
                SfxTemplateItem *pState = pFamilyState[nActFamily-1];
                if(pState)
                {
                    const String aStyle(pState->GetStyleName());
                    SelectStyle(aStyle);
                }
                EnableDelete();
            }*/
//              }
    }
}

//-------------------------------------------------------------------------

// Handler des Bearbeiten-Buttons
void SfxCommonTemplateDialog_Impl::EditHdl(void *)
{
    if(IsInitialized() && HasSelectedStyle())
    {
        USHORT nFilter = nActFilter;
        String aTemplName(GetSelectedEntry());
        const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl();
        const SfxStyleFamily eFam = pItem->GetFamily();
        pStyleSheetPool->Find(aTemplName,eFam,SFXSTYLEBIT_ALL);  // -Wall required??
        Window* pTmp;
        //DefModalDialogParent setzen fuer
        //Modalitaet der nachfolgenden Dialoge
        pTmp = Application::GetDefDialogParent();
        if ( ISA(SfxTemplateDialog_Impl) )
            Application::SetDefDialogParent( pWindow->GetParent() );
        else
            Application::SetDefDialogParent( pWindow );
        if ( Execute_Impl( SID_STYLE_EDIT, aTemplName, String(),
                          (USHORT)GetFamilyItem_Impl()->GetFamily(), 0, &nFilter ) )
        {
//          DBG_ASSERT(nFilter < aFilterLb.GetEntryCount(), "Filter ueberindiziert");
//          aTemplName = pStyle->GetName();
// kann durch Bearbeiten umbenannt worden sein
/*                      if(!pTreeBox)
            {
                //                              aFilterLb.SelectEntryPos(nFilter);
                //                              FilterSelect(nFilter, TRUE);
            }
            else
                FillTreeBox();*/
        }
        Application::SetDefDialogParent( pTmp );
    }
}

//-------------------------------------------------------------------------

// Handler des L"oschen-Buttons
void SfxCommonTemplateDialog_Impl::DeleteHdl(void *)
{
    if ( IsInitialized() && HasSelectedStyle() )
    {
        const String aTemplName( GetSelectedEntry() );
        const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl();
        SfxStyleSheetBase* pStyle =
            pStyleSheetPool->Find( aTemplName, pItem->GetFamily(), SFXSTYLEBIT_ALL );
        if ( pStyle )
        {
            String aMsg;
            if ( pStyle->IsUsed() )
                aMsg = String( SfxResId( STR_DELETE_STYLE_USED ) );
            aMsg += String ( SfxResId( STR_DELETE_STYLE ) );
            aMsg.SearchAndReplaceAscii( "$1", aTemplName );
#if defined UNX
            QueryBox aBox( SFX_APP()->GetTopWindow(), WB_YES_NO | WB_DEF_NO, aMsg );
#else
            QueryBox aBox( GetWindow(), WB_YES_NO | WB_DEF_NO , aMsg );
#endif
            if ( RET_YES == aBox.Execute() )
            {
                PrepareDeleteAction();

                if ( pTreeBox ) // Damit die Treelistbox beim L"oschen nicht zuklappt
                {
                    bDontUpdate = TRUE;
                }
                Execute_Impl( SID_STYLE_DELETE, aTemplName,
                              String(), (USHORT)GetFamilyItem_Impl()->GetFamily() );

                if ( pTreeBox )
                {
                    pTreeBox->RemoveParentKeepChilds( pTreeBox->FirstSelected() );
                    bDontUpdate = FALSE;
                }
            }
        }
    }
}

//-------------------------------------------------------------------------

void    SfxCommonTemplateDialog_Impl::EnableDelete()
{
    if(IsInitialized() && HasSelectedStyle())
    {
        DBG_ASSERT(pStyleSheetPool, "Kein StyleSheetPool");
        const String aTemplName(GetSelectedEntry());
        const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl();
        const SfxStyleFamily eFam = pItem->GetFamily();
        USHORT nFilter = 0;
        if(pItem->GetFilterList().Count() > nActFilter)
            nFilter = pItem->GetFilterList().GetObject(nActFilter)->nFlags;
        if(!nFilter)    // automatisch
            nFilter = nAppFilter;
        const SfxStyleSheetBase *pStyle =
            pStyleSheetPool->Find(aTemplName,eFam,
                                  pTreeBox? SFXSTYLEBIT_ALL: nFilter);
        DBG_ASSERT(pStyle, "Style nicht gefunden");
        if(pStyle && pStyle->IsUserDefined())
        {
            EnableDel(TRUE);
        }
        else
        {
            EnableDel(FALSE);
        }
    }
    else
    {
        EnableDel(FALSE);
    }
//  rBindings.Invalidate( SID_STYLE_DELETE );
//  rBindings.Update( SID_STYLE_DELETE );
}

//-------------------------------------------------------------------------

// nach Selektion eines Eintrags den Focus gfs. wieder auf das App-Fenster
// setzen
void    SfxCommonTemplateDialog_Impl::ResetFocus()
{
    if(ISA(SfxTemplateDialog_Impl))
    {
        SfxViewFrame *pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame();
        SfxViewShell *pVu = pViewFrame->GetViewShell();
        Window *pAppWin = pVu ? pVu->GetWindow(): 0;
        if(pAppWin)
            pAppWin->GrabFocus();
    }
}

//-------------------------------------------------------------------------

// Doppelclick auf ein StyleSheet in der ListBox, wird angewendet.
IMPL_LINK( SfxCommonTemplateDialog_Impl, ApplyHdl, Control *, pControl )
{
        // nur, wenn dieser Bereich erlaubt ist
    if ( IsInitialized() && 0 != pFamilyState[nActFamily-1] &&
         GetSelectedEntry().Len() )
    {
        USHORT nModifier = aFmtLb.GetModifier();
        Execute_Impl(SID_STYLE_APPLY,
                     GetSelectedEntry(), String(),
                     ( USHORT )GetFamilyItem_Impl()->GetFamily(),
                     0, 0, &nModifier );
        if(ISA(SfxTemplateCatalog_Impl))
            ((SfxTemplateCatalog_Impl*) this)->pReal->EndDialog(RET_OK);
    }
    ResetFocus();
    return 0;
}

//-------------------------------------------------------------------------

// Selektion einer Vorlage w"ahrend des Watercan-Status
IMPL_LINK( SfxCommonTemplateDialog_Impl, FmtSelectHdl, SvTreeListBox *, pListBox )
{
    // HilfePI antriggern, wenn von Call als Handler und Bereich erlaubt ist
    if( !pListBox || pListBox->IsSelected( pListBox->GetHdlEntry() ) )
    {
#ifdef WIR_KOENNEN_WIEDER_HILFE_FUER_STYLESHEETS
        SfxHelpPI* pHelpPI = SFX_APP()->GetHelpPI();
        if ( pHelpPI && pListBox && IsInitialized() &&
             GetSelectedEntry().Len() )
        {
            const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl();
            const SfxStyleFamily eFam = pItem->GetFamily();
            DBG_ASSERT(pStyleSheetPool, "Kein Pool");
            // SfxStyleSheetBase* pStyle = pStyleSheetPool
            //      ? pStyleSheetPool->Find( GetSelectedEntry(), eFam ) : 0;
            SfxStyleSheetBase *pStyle;
            if ( pStyleSheetPool )
                pStyle = pStyleSheetPool->Find ( GetSelectedEntry(), eFam );
            else
                pStyle = 0;

            if ( pStyle )
            {
                String aHelpFile;
                ULONG nHelpId=pStyle->GetHelpId(aHelpFile);
                if ( nHelpId )
                    pHelpPI->LoadTopic( nHelpId );
            }
        }
#endif

        // nur, wenn Giesskanne an ist
        if ( IsInitialized() &&
             IsCheckedItem(SID_STYLE_WATERCAN) &&
             // nur, wenn dieser Bereich erlaubt ist
             0 != pFamilyState[nActFamily-1] )
        {
            String aEmpty;
            Execute_Impl(SID_STYLE_WATERCAN,
                         aEmpty, aEmpty, 0);
            Execute_Impl(SID_STYLE_WATERCAN,
                         GetSelectedEntry(), aEmpty,
                         ( USHORT )GetFamilyItem_Impl()->GetFamily());
        }
//      EnableEdit(TRUE);
        EnableItem(SID_STYLE_WATERCAN, !bWaterDisabled);
        EnableDelete();
    }
    if( pListBox )
        SelectStyle( pListBox->GetEntryText( pListBox->GetHdlEntry() ));

    return 0;
}

//-------------------------------------------------------------------------

IMPL_LINK( SfxCommonTemplateDialog_Impl, MenuSelectHdl, Menu *, pMenu )
{
    if( pMenu )
    {
        nLastItemId = pMenu->GetCurItemId();
        Application::PostUserEvent(
            LINK( this, SfxCommonTemplateDialog_Impl, MenuSelectHdl ), 0 );
        return TRUE;
    }

    switch(nLastItemId) {
    case ID_NEW: NewHdl(0); break;
    case ID_EDIT: EditHdl(0); break;
    case ID_DELETE: DeleteHdl(0); break;
    default: return FALSE;
    }
    return TRUE;
}

// -----------------------------------------------------------------------

void SfxCommonTemplateDialog_Impl::ExecuteContextMenu_Impl( const Point& rPos, Window* pWin )
{
    // Bug# 94152: This part should never be called, because before this happens, the TreeListBox should captured this!
    DBG_ASSERT( FALSE, "+SfxCommonTemplateDialog_Impl::ExecuteContextMenu_Impl(): How could this happen? Please infirm developer ASAP!" );

    PopupMenu* pMenu = CreateContextMenu();
    pMenu->Execute( pWin, rPos );
    delete pMenu;
}

// -----------------------------------------------------------------------

SfxStyleFamily SfxCommonTemplateDialog_Impl::GetActualFamily() const
{
    const SfxStyleFamilyItem *pFamilyItem = GetFamilyItem_Impl();
    if( !pFamilyItem || nActFamily == 0xffff )
        return SFX_STYLE_FAMILY_PARA;
    else
        return pFamilyItem->GetFamily();
}

// -----------------------------------------------------------------------

void SfxCommonTemplateDialog_Impl::EnableExample_Impl(USHORT nId, BOOL bEnable)
{
    if( nId == SID_STYLE_NEW_BY_EXAMPLE )
        bNewByExampleDisabled = !bEnable;
    else if( nId == SID_STYLE_UPDATE_BY_EXAMPLE )
        bUpdateByExampleDisabled = !bEnable;
    EnableItem(nId, bEnable);
}

void SfxCommonTemplateDialog_Impl::PrepareDeleteAction()
{
}

// -----------------------------------------------------------------------

PopupMenu* SfxCommonTemplateDialog_Impl::CreateContextMenu( void )
{
    if ( bBindingUpdate )
    {
        pBindings->Invalidate( SID_STYLE_NEW, TRUE, FALSE );
        pBindings->Update( SID_STYLE_NEW );
        bBindingUpdate = FALSE;
    }
    PopupMenu* pMenu = new PopupMenu( SfxResId( MN_CONTEXT_TEMPLDLG ) );
    pMenu->SetSelectHdl( LINK( this, SfxCommonTemplateDialog_Impl, MenuSelectHdl ) );
    pMenu->EnableItem( ID_EDIT, bCanEdit );
    pMenu->EnableItem( ID_DELETE, bCanDel );
    pMenu->EnableItem( ID_NEW, bCanNew );

    return pMenu;
}

// ------------------------------------------------------------------------

SfxTemplateDialog_Impl::SfxTemplateDialog_Impl(
    Window* pParent, SfxBindings* pB, SfxTemplateDialog* pWindow ) :

    SfxCommonTemplateDialog_Impl( pB, pWindow ),

    m_pFloat            ( pWindow ),
    m_bZoomIn           ( FALSE ),
    m_aActionTbL        ( pWindow, this ),
    m_aActionTbR        ( pWindow, ResId( TB_ACTION ) )

{
    pWindow->FreeResource();
    Initialize();

    m_aActionTbL.SetSelectHdl(LINK(this, SfxTemplateDialog_Impl, ToolBoxLSelect));
    m_aActionTbR.SetSelectHdl(LINK(this, SfxTemplateDialog_Impl, ToolBoxRSelect));
    m_aActionTbR.SetDropdownClickHdl(LINK(this, SfxTemplateDialog_Impl, ToolBoxRClick));
    m_aActionTbL.Show();
    m_aActionTbR.Show();
    Font aFont=aFilterLb.GetFont();
    aFont.SetWeight( WEIGHT_NORMAL );
    aFilterLb.SetFont( aFont );
    m_aActionTbL.SetHelpId( HID_TEMPLDLG_TOOLBOX_LEFT );
}

// ------------------------------------------------------------------------

void SfxTemplateDialog_Impl::EnableFamilyItem( USHORT nId, BOOL bEnable )
{
    m_aActionTbL.EnableItem( nId, bEnable );
}

//-------------------------------------------------------------------------

void SfxTemplateDialog_Impl::InsertFamilyItem(USHORT nId,const SfxStyleFamilyItem *pItem)
{
    USHORT nHelpId = 0;
    switch( (USHORT) pItem->GetFamily() )
    {
        case SFX_STYLE_FAMILY_CHAR: nHelpId = SID_STYLE_FAMILY1; break;
        case SFX_STYLE_FAMILY_PARA: nHelpId = SID_STYLE_FAMILY2; break;
        case SFX_STYLE_FAMILY_FRAME:nHelpId = SID_STYLE_FAMILY3; break;
        case SFX_STYLE_FAMILY_PAGE: nHelpId = SID_STYLE_FAMILY4; break;
        case SFX_STYLE_FAMILY_PSEUDO: nHelpId = SID_STYLE_FAMILY5; break;
        default: DBG_ERROR("unbekannte StyleFamily"); break;
    }
    m_aActionTbL.InsertItem( nId, pItem->GetImage(), pItem->GetText(), 0, 0);
    m_aActionTbL.SetHelpId( nId, nHelpId );
}

// ------------------------------------------------------------------------

void SfxTemplateDialog_Impl::ReplaceUpdateButtonByMenu()
{
    m_aActionTbR.HideItem(SID_STYLE_UPDATE_BY_EXAMPLE);
    m_aActionTbR.SetItemBits( SID_STYLE_NEW_BY_EXAMPLE,
            TIB_DROPDOWNONLY|m_aActionTbR.GetItemBits( SID_STYLE_NEW_BY_EXAMPLE ));
}

// ------------------------------------------------------------------------
void SfxTemplateDialog_Impl::updateFamilyImages()
{
    if ( !m_pStyleFamiliesId )
        // we do not have a resource id to load the new images from
        return;

    // let the families collection update the images
    sal_Bool bIsHighContrast = m_pFloat->GetDisplayBackground().GetColor().IsDark();
    pStyleFamilies->updateImages( *m_pStyleFamiliesId, bIsHighContrast ? BMP_COLOR_HIGHCONTRAST : BMP_COLOR_NORMAL );

    // and set the new images on our toolbox
    USHORT nLoop = pStyleFamilies->Count();
    for( ; nLoop--; )
    {
        const SfxStyleFamilyItem *pItem = pStyleFamilies->GetObject( nLoop );
        USHORT nId = SfxFamilyIdToNId( (USHORT) pItem->GetFamily() );
        m_aActionTbL.SetItemImage( nId, pItem->GetImage() );
    }
}

// ------------------------------------------------------------------------
void SfxTemplateDialog_Impl::updateNonFamilyImages()
{
    m_aActionTbR.SetImageList( ImageList( SfxResId(
        m_pFloat->GetDisplayBackground().GetColor().IsDark() ? IMG_LST_STYLE_DESIGNER_HC
                                                             : DLG_STYLE_DESIGNER ) ) );
}

// ------------------------------------------------------------------------

void SfxTemplateDialog_Impl::ClearFamilyList()
{
    m_aActionTbL.Clear();
}

//-------------------------------------------------------------------------

void SfxCommonTemplateDialog_Impl::InvalidateBindings()
{
    pBindings->Invalidate(SID_STYLE_NEW_BY_EXAMPLE, TRUE, FALSE);
    pBindings->Update( SID_STYLE_NEW_BY_EXAMPLE );
    pBindings->Invalidate(SID_STYLE_UPDATE_BY_EXAMPLE, TRUE, FALSE);
    pBindings->Update( SID_STYLE_UPDATE_BY_EXAMPLE );
    pBindings->Invalidate( SID_STYLE_WATERCAN, TRUE, FALSE);
    pBindings->Update( SID_STYLE_WATERCAN );
    pBindings->Invalidate( SID_STYLE_NEW, TRUE, FALSE );
    pBindings->Update( SID_STYLE_NEW );
    pBindings->Invalidate( SID_STYLE_DRAGHIERARCHIE, TRUE, FALSE );
    pBindings->Update( SID_STYLE_DRAGHIERARCHIE );
}

//-------------------------------------------------------------------------

SfxTemplateDialog_Impl::~SfxTemplateDialog_Impl()
{
/*
    SfxImageManager* pImgMgr = pBindings->GetImageManager();
    if ( pImgMgr )
    {
        pImgMgr->ReleaseToolBox( &m_aActionTbL );
        pImgMgr->ReleaseToolBox( &m_aActionTbR );
    }
*/
}

//-------------------------------------------------------------------------

void SfxTemplateDialog_Impl::LoadedFamilies()
{
    updateFamilyImages();
    Resize();
}

//-------------------------------------------------------------------------

// "Uberladener Resize-Handler ( StarView )
// Die Groesse der Listboxen wird angepasst
void SfxTemplateDialog_Impl::Resize()
{
    FloatingWindow *pF = m_pFloat->GetFloatingWindow();
    if ( pF )
    {
//      if(pF->IsZoomedIn() && m_bZoomIn==FALSE)
//          pF->SetText(String(SfxResId( DLG_STYLE_DESIGNER )));
//      if(!pF->IsZoomedIn() && m_bZoomIn==TRUE && GetFamilyItem_Impl())
//          UpdateStyles_Impl(UPDATE_FAMILY); //Bereich wieder in Titel schreiben
        m_bZoomIn = pF->IsRollUp();
        if ( m_bZoomIn )
            return;
    }

    Size aDlgSize=m_pFloat->PixelToLogic(m_pFloat->GetOutputSizePixel());
    Size aSizeATL=m_pFloat->PixelToLogic(m_aActionTbL.CalcWindowSizePixel());
    Size aSizeATR=m_pFloat->PixelToLogic(m_aActionTbR.CalcWindowSizePixel());
    Size aMinSize = GetMinOutputSizePixel();

    long nListHeight = m_pFloat->PixelToLogic( aFilterLb.GetSizePixel() ).Height();
    long nWidth = aDlgSize.Width()- 2 * SFX_TEMPLDLG_HFRAME;

    m_aActionTbL.SetPosSizePixel(m_pFloat->LogicToPixel(Point(SFX_TEMPLDLG_HFRAME,SFX_TEMPLDLG_VTOPFRAME)),
                                 m_pFloat->LogicToPixel(aSizeATL));

    // Die Position der rechten Toolbox nur ver"andern, wenn das Fenster
    // breit genug ist
    Point aPosATR(aDlgSize.Width()-SFX_TEMPLDLG_HFRAME-aSizeATR.Width(),SFX_TEMPLDLG_VTOPFRAME);
    if(aDlgSize.Width() >= aMinSize.Width())
        m_aActionTbR.SetPosPixel(m_pFloat->LogicToPixel(aPosATR));
    else
        m_aActionTbR.SetPosPixel( m_pFloat->LogicToPixel(
            Point( SFX_TEMPLDLG_HFRAME + aSizeATL.Width() + SFX_TEMPLDLG_MIDHSPACE,
                   SFX_TEMPLDLG_VTOPFRAME ) ) );

    m_aActionTbR.SetSizePixel(m_pFloat->LogicToPixel(aSizeATR));

    Point aFilterPos(
        m_pFloat->LogicToPixel(Point(SFX_TEMPLDLG_HFRAME,
            aDlgSize.Height()-SFX_TEMPLDLG_VBOTFRAME-nListHeight)) );

    Size aFilterSize(
        m_pFloat->LogicToPixel(Size(nWidth,SFX_TEMPLDLG_FILTERHEIGHT)) );

    Point aFmtPos(
        m_pFloat->LogicToPixel(Point(SFX_TEMPLDLG_HFRAME, SFX_TEMPLDLG_VTOPFRAME +
                            SFX_TEMPLDLG_MIDVSPACE+aSizeATL.Height())) );
    Size aFmtSize(
        m_pFloat->LogicToPixel(Size(nWidth,
                    aDlgSize.Height() - SFX_TEMPLDLG_VBOTFRAME -
                    SFX_TEMPLDLG_VTOPFRAME - 2*SFX_TEMPLDLG_MIDVSPACE-
                    nListHeight-aSizeATL.Height())) );

    // Die Position der Listboxen nur ver"andern, wenn das Fenster
    // hoch genug ist
    if(aDlgSize.Height() >= aMinSize.Height())
    {
        aFilterLb.SetPosPixel(aFilterPos);
        aFmtLb.SetPosPixel( aFmtPos );
        if(pTreeBox)
            pTreeBox->SetPosPixel(aFmtPos);
    }
    else
        aFmtSize.Height() += aFilterSize.Height();

    aFilterLb.SetSizePixel(aFilterSize);
    aFmtLb.SetSizePixel( aFmtSize );
    if(pTreeBox)
        pTreeBox->SetSizePixel(aFmtSize);
}

// -----------------------------------------------------------------------


Size SfxTemplateDialog_Impl::GetMinOutputSizePixel()
{
    Size aSizeATL=m_pFloat->PixelToLogic(m_aActionTbL.CalcWindowSizePixel());
    Size aSizeATR=m_pFloat->PixelToLogic(m_aActionTbR.CalcWindowSizePixel());
    Size aMinSize=Size(
        aSizeATL.Width()+aSizeATR.Width()+
        2*SFX_TEMPLDLG_HFRAME + SFX_TEMPLDLG_MIDHSPACE,
        4*aSizeATL.Height()+2*SFX_TEMPLDLG_MIDVSPACE);
    return aMinSize;
}

//-------------------------------------------------------------------------

void SfxTemplateDialog_Impl::Command( const CommandEvent& rCEvt )
{
    if(COMMAND_CONTEXTMENU  == rCEvt.GetCommand())
        ExecuteContextMenu_Impl( rCEvt.GetMousePosPixel(), m_pFloat );
    else
        m_pFloat->Command(rCEvt);
}

//-------------------------------------------------------------------------

void SfxTemplateDialog_Impl::EnableItem(USHORT nMesId, BOOL bCheck)
{
    String aEmpty;
    switch(nMesId)
    {
      case SID_STYLE_WATERCAN :
          if(!bCheck && IsCheckedItem(SID_STYLE_WATERCAN))
            Execute_Impl(SID_STYLE_WATERCAN, aEmpty, aEmpty, 0);
      case SID_STYLE_NEW_BY_EXAMPLE:
      case SID_STYLE_UPDATE_BY_EXAMPLE:
        m_aActionTbR.EnableItem(nMesId,bCheck);
        break;
    }
}

//-------------------------------------------------------------------------

void SfxTemplateDialog_Impl::CheckItem(USHORT nMesId, BOOL bCheck)
{
    switch(nMesId)
    {
        case SID_STYLE_WATERCAN :
            bIsWater=bCheck;
            m_aActionTbR.CheckItem(SID_STYLE_WATERCAN,bCheck);
            break;
        default:
            m_aActionTbL.CheckItem(nMesId,bCheck); break;
    }
}

//-------------------------------------------------------------------------

BOOL SfxTemplateDialog_Impl::IsCheckedItem(USHORT nMesId)
{
    switch(nMesId)
    {
        case SID_STYLE_WATERCAN :
            return m_aActionTbR.GetItemState(SID_STYLE_WATERCAN)==STATE_CHECK;
        default:
            return m_aActionTbL.GetItemState(nMesId)==STATE_CHECK;
    }
}

//-------------------------------------------------------------------------

IMPL_LINK_INLINE_START( SfxTemplateDialog_Impl, ToolBoxLSelect, ToolBox *, pBox )
{
    const USHORT nEntry = pBox->GetCurItemId();
    FamilySelect(nEntry);
    return 0;
}
IMPL_LINK_INLINE_END( SfxTemplateDialog_Impl, ToolBoxLSelect, ToolBox *, pBox )

//-------------------------------------------------------------------------
::rtl::OUString lcl_GetLabel(uno::Any& rAny)
{
    ::rtl::OUString sRet;
    uno::Sequence< beans::PropertyValue >aPropSeq;
    if ( rAny >>= aPropSeq )
    {
        for( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
        {
            if ( aPropSeq[i].Name.equalsAscii( "Label" ))
            {
                aPropSeq[i].Value >>= sRet;
                break;
            }
        }
    }
    return sRet;
}
//-------------------------------------------------------------------------

IMPL_LINK( SfxTemplateDialog_Impl, ToolBoxRSelect, ToolBox *, pBox )
{
    const USHORT nEntry = pBox->GetCurItemId();
    if(nEntry != SID_STYLE_NEW_BY_EXAMPLE ||
            TIB_DROPDOWN != (pBox->GetItemBits(nEntry)&TIB_DROPDOWN))
        ActionSelect(nEntry);
    return 0;
}
//-------------------------------------------------------------------------
IMPL_LINK( SfxTemplateDialog_Impl, ToolBoxRClick, ToolBox *, pBox )
{
    const USHORT nEntry = pBox->GetCurItemId();
    if(nEntry == SID_STYLE_NEW_BY_EXAMPLE &&
            TIB_DROPDOWN == (pBox->GetItemBits(nEntry)&TIB_DROPDOWN))
    {
        //create a popup menu in Writer
        PopupMenu *pMenu = new PopupMenu;
        uno::Reference< container::XNameAccess > xNameAccess(
                    ::comphelper::getProcessServiceFactory()->
                    createInstance( ::rtl::OUString::createFromAscii(
                            "com.sun.star.frame.UICommandDescription") ), uno::UNO_QUERY );
        uno::Reference< container::XNameAccess > xUICommands;
        if ( xNameAccess.is() )
        {
            rtl::OUString sTextDoc = ::rtl::OUString::createFromAscii("com.sun.star.text.TextDocument");
            if(xNameAccess->hasByName(sTextDoc))
            {
                uno::Any a = xNameAccess->getByName( sTextDoc );
                a >>= xUICommands;
            }
        }
        if(!xUICommands.is())
            return 0;
        try
        {
            uno::Sequence< beans::PropertyValue > aPropSeq;
            uno::Any aCommand = xUICommands->getByName(::rtl::OUString::createFromAscii(".uno:StyleNewByExample"));
            ::rtl::OUString sLabel = lcl_GetLabel( aCommand );
            pMenu->InsertItem( SID_STYLE_NEW_BY_EXAMPLE, sLabel );
            pMenu->SetHelpId(SID_STYLE_NEW_BY_EXAMPLE, HID_TEMPLDLG_NEWBYEXAMPLE);

            aCommand = xUICommands->getByName(::rtl::OUString::createFromAscii(".uno:StyleUpdateByExample"));
            sLabel = lcl_GetLabel( aCommand );

            pMenu->InsertItem( SID_STYLE_UPDATE_BY_EXAMPLE, sLabel );
            pMenu->SetHelpId(SID_STYLE_UPDATE_BY_EXAMPLE, HID_TEMPLDLG_UPDATEBYEXAMPLE);

            aCommand = xUICommands->getByName(::rtl::OUString::createFromAscii(".uno:LoadStyles"));
            sLabel = lcl_GetLabel( aCommand );
            pMenu->InsertItem( SID_TEMPLATE_LOAD, sLabel );
            pMenu->SetHelpId(SID_TEMPLATE_LOAD, SID_TEMPLATE_LOAD);

            pMenu->SetSelectHdl(LINK(this, SfxTemplateDialog_Impl, MenuSelectHdl));
            pMenu->Execute( pBox,
                            pBox->GetItemRect(nEntry),
                            POPUPMENU_EXECUTE_DOWN );
            pBox->EndSelection();
        }
        catch(uno::Exception&)
        {
        }
        delete pMenu;
        pBox->Invalidate();
    }
    return 0;
}
//-------------------------------------------------------------------------
IMPL_LINK( SfxTemplateDialog_Impl, MenuSelectHdl, Menu*, pMenu)
{
    USHORT nMenuId = pMenu->GetCurItemId();
    ActionSelect(nMenuId);
    return 0;
}
//-------------------------------------------------------------------------

SfxTemplateCatalog_Impl::SfxTemplateCatalog_Impl( Window* pParent, SfxBindings* pB,
                                                  SfxTemplateCatalog* pWindow ) :

    SfxCommonTemplateDialog_Impl( pB, pWindow ),

    aFamList    ( pWindow, SfxResId( BT_TOOL ) ),
    aOkBtn      ( pWindow, SfxResId( BT_OK ) ),
    aCancelBtn  ( pWindow, SfxResId( BT_CANCEL ) ),
    aNewBtn     ( pWindow, SfxResId( BT_NEW ) ),
    aChangeBtn  ( pWindow, SfxResId( BT_EDIT ) ),
    aDelBtn     ( pWindow, SfxResId( BT_DEL ) ),
    aOrgBtn     ( pWindow, SfxResId( BT_ORG ) ),
    aHelpBtn    ( pWindow, SfxResId( BT_HELP ) ),
    pReal       ( pWindow ),
    aHelper     ( pWindow )

{
    aNewBtn.Disable();
    aDelBtn.Disable();
    aChangeBtn.Disable();

    SFX_APP()->Get_Impl()->pTemplateCommon = GetISfxTemplateCommon();
    pWindow->FreeResource();

    Initialize();

    aFamList.SetSelectHdl(  LINK( this, SfxTemplateCatalog_Impl, FamListSelect ) );
    aOkBtn.SetClickHdl(     LINK( this, SfxTemplateCatalog_Impl, OkHdl ) );
    aCancelBtn.SetClickHdl( LINK( this, SfxTemplateCatalog_Impl, CancelHdl ) );
    aNewBtn.SetClickHdl(    LINK( this, SfxTemplateCatalog_Impl, NewHdl ) );
    aDelBtn.SetClickHdl(    LINK( this, SfxTemplateCatalog_Impl, DelHdl ) );
    aChangeBtn.SetClickHdl( LINK( this, SfxTemplateCatalog_Impl, ChangeHdl ) );
    aOrgBtn.SetClickHdl(    LINK( this, SfxTemplateCatalog_Impl, OrgHdl ) );
}

//-------------------------------------------------------------------------

SfxTemplateCatalog_Impl::~SfxTemplateCatalog_Impl()
{
    SFX_APP()->Get_Impl()->pTemplateCommon = 0;
}

//-------------------------------------------------------------------------

IMPL_LINK_INLINE_START( SfxTemplateCatalog_Impl, OkHdl, Button *, pButton )
{
    ApplyHdl( NULL );
    pReal->EndDialog( RET_OK );
    return 0;
}
IMPL_LINK_INLINE_END( SfxTemplateCatalog_Impl, OkHdl, Button *, pButton )

//-------------------------------------------------------------------------

IMPL_LINK_INLINE_START( SfxTemplateCatalog_Impl, CancelHdl, Button *, pButton )
{
    pReal->EndDialog( RET_CANCEL );
    return 0;
}
IMPL_LINK_INLINE_END( SfxTemplateCatalog_Impl, CancelHdl, Button *, pButton )

//-------------------------------------------------------------------------

IMPL_LINK_INLINE_START( SfxTemplateCatalog_Impl, NewHdl, Button *, pButton )
{
    aCancelBtn.SetText( String( SfxResId( STR_CLOSE ) ) );
    SfxCommonTemplateDialog_Impl::NewHdl( NULL );
    return 0;
}
IMPL_LINK_INLINE_END( SfxTemplateCatalog_Impl, NewHdl, Button *, pButton )

//-------------------------------------------------------------------------

IMPL_LINK_INLINE_START( SfxTemplateCatalog_Impl, ChangeHdl, Button *, pButton )
{
    aCancelBtn.SetText( String( SfxResId( STR_CLOSE ) ) );
    SfxCommonTemplateDialog_Impl::EditHdl( NULL );
    return 0;
}
IMPL_LINK_INLINE_END( SfxTemplateCatalog_Impl, ChangeHdl, Button *, pButton )

//-------------------------------------------------------------------------

IMPL_LINK_INLINE_START( SfxTemplateCatalog_Impl, DelHdl, Button *, pButton )
{
    SfxCommonTemplateDialog_Impl::DeleteHdl( NULL );
    return 0;
}
IMPL_LINK_INLINE_END( SfxTemplateCatalog_Impl, DelHdl, Button *, pButton )

//-------------------------------------------------------------------------

IMPL_LINK( SfxTemplateCatalog_Impl, OrgHdl, Button *, pButton )
{
    aCancelBtn.SetText( String( SfxResId( STR_CLOSE ) ) );
    SfxDocumentTemplates aTemplates;
    aTemplates.Construct();
    SfxTemplateOrganizeDlg* pDlg = new SfxTemplateOrganizeDlg( pReal, &aTemplates );
    const short nRet = pDlg->Execute();
    delete pDlg;
    if ( RET_OK == nRet )
        Update_Impl();
    else if ( RET_EDIT_STYLE == nRet )
        pReal->EndDialog( RET_CANCEL );
    return 0;
}

//-------------------------------------------------------------------------

void SfxTemplateCatalog_Impl::EnableEdit( BOOL bEnable )
{
    SfxCommonTemplateDialog_Impl::EnableEdit( bEnable );
    aChangeBtn.Enable( bEnable );
}

//-------------------------------------------------------------------------

void SfxTemplateCatalog_Impl::EnableDel( BOOL bEnable )
{
    SfxCommonTemplateDialog_Impl::EnableDel( bEnable );
    aDelBtn.Enable( bEnable );
}

void SfxTemplateCatalog_Impl::EnableNew(BOOL bEnable)
{
    SfxCommonTemplateDialog_Impl::EnableNew( bEnable );
    aNewBtn.Enable( bEnable );
}

//-------------------------------------------------------------------------

IMPL_LINK_INLINE_START( SfxTemplateCatalog_Impl, FamListSelect, ListBox *, pList )
{
    const USHORT nEntry = aFamIds[pList->GetSelectEntryPos()];
    FamilySelect(nEntry);
    return 0;
}
IMPL_LINK_INLINE_END( SfxTemplateCatalog_Impl, FamListSelect, ListBox *, pList )

//-------------------------------------------------------------------------

void SfxTemplateCatalog_Impl::EnableItem( USHORT nMesId, BOOL bCheck )
{
    if ( nMesId == SID_STYLE_WATERCAN )
        aOkBtn.Enable( bCheck );
    if ( nMesId > SFX_STYLE_FAMILY_PSEUDO || nMesId < SFX_STYLE_FAMILY_CHAR )
        return;

/*      for(USHORT i=0;i<aFamIds.Count&&aFamIds[i]!=nMesId;i++);
    if(i!=aFamIds.Count())
        aFamList.SelectEntry(aFamIds[i]);
    else
        DBG_ERROR("Entry nicht gefunden");*/

}

//-------------------------------------------------------------------------

void SfxTemplateCatalog_Impl::CheckItem(USHORT nMesId, BOOL bCheck)
{
    if ( nMesId > SFX_STYLE_FAMILY_PSEUDO || nMesId < SFX_STYLE_FAMILY_CHAR )
        return;
    USHORT i;
    for ( i = 0; i < aFamIds.Count() && aFamIds[i] != nMesId; i++ );
    aFamList.SelectEntryPos(i);
}

//-------------------------------------------------------------------------

BOOL SfxTemplateCatalog_Impl::IsCheckedItem(USHORT nMesId)
{
    if ( nMesId > SFX_STYLE_FAMILY_PSEUDO || nMesId < SFX_STYLE_FAMILY_CHAR )
        return FALSE;
    USHORT i;
    for ( i = 0; i < aFamIds.Count() && aFamIds[i] != nMesId; i++ )
        ;
    return aFamList.IsEntrySelected( String::CreateFromInt32(i) );
}

//-------------------------------------------------------------------------

// Der Katalog muss nur das Disablen beherrschen, da waehrend seiner
// Lebenszeit keine Selektionsaenderungen vorgenommen werden koennen
void SfxTemplateCatalog_Impl::EnableFamilyItem( USHORT nId, BOOL bEnable )
{
    if ( !bEnable )
        for ( USHORT nPos = aFamIds.Count(); nPos--; )
            if ( aFamIds[ nPos ] == nId )
            {
                aFamIds.Remove( nPos );
                aFamList.RemoveEntry( nPos );
            }
}

void SfxTemplateCatalog_Impl::InsertFamilyItem( USHORT nId, const SfxStyleFamilyItem* pItem )
{
    if ( nId > SFX_STYLE_FAMILY_PSEUDO || nId < SFX_STYLE_FAMILY_CHAR )
        return;
    aFamList.InsertEntry( pItem->GetText(), 0 );
    aFamIds.Insert( nId, 0 );
}

void SfxTemplateCatalog_Impl::ClearFamilyList()
{
    aFamList.Clear();
    aFamIds.Remove( 0, aFamIds.Count() );
}

void SfxTemplateCatalog_Impl::PrepareDeleteAction()
{
    aDelBtn.Disable();
    aCancelBtn.SetText( String( SfxResId( STR_CLOSE ) ) );
}


void SfxCommonTemplateDialog_Impl::SetFamily( USHORT nId )
{
    if ( nId != nActFamily )
    {
        if ( nActFamily != 0xFFFF )
            CheckItem( nActFamily, FALSE );
        nActFamily = nId;
        if ( nId != 0xFFFF )
            bUpdateFamily = TRUE;
    }
}

void SfxCommonTemplateDialog_Impl::UpdateFamily_Impl()
{
    bUpdateFamily = FALSE;

    SfxDispatcher* pDispat = pBindings->GetDispatcher_Impl();
    SfxViewFrame *pViewFrame = pDispat->GetFrame();
    SfxObjectShell *pDocShell = pViewFrame->GetObjectShell();

    SfxStyleSheetBasePool *pOldStyleSheetPool = pStyleSheetPool;
    pStyleSheetPool = pDocShell? pDocShell->GetStyleSheetPool(): 0;
    if ( pOldStyleSheetPool != pStyleSheetPool )
    {
        if ( pOldStyleSheetPool )
            EndListening(*pOldStyleSheetPool);
        if ( pStyleSheetPool )
            StartListening(*pOldStyleSheetPool);
    }

    bWaterDisabled = FALSE;
    bCanNew = TRUE;
    bTreeDrag = TRUE;
    bUpdateByExampleDisabled = FALSE;

    if ( pStyleSheetPool )
    {
        if(!pTreeBox)
            UpdateStyles_Impl(UPDATE_FAMILY | UPDATE_FAMILY_LIST);
        else
        {
            UpdateStyles_Impl(UPDATE_FAMILY);
            FillTreeBox();
        }
    }

    InvalidateBindings();

    if ( IsCheckedItem( SID_STYLE_WATERCAN ) &&
         // nur, wenn dieser Bereich erlaubt ist
         0 != pFamilyState[ nActFamily - 1 ] )
        Execute_Impl( SID_STYLE_APPLY, GetSelectedEntry(),
                      String(), (USHORT)GetFamilyItem_Impl()->GetFamily() );
}
void SfxCommonTemplateDialog_Impl::ReplaceUpdateButtonByMenu()
{
    //does nothing
}

void SfxTemplateDialog::StateChanged( StateChangedType nStateChange )
{
    if ( nStateChange == STATE_CHANGE_INITSHOW )
    {
        SfxViewFrame *pFrame = GetBindings().GetDispatcher_Impl()->GetFrame();
        Window* pEditWin = pFrame->GetViewShell()->GetWindow();

        Size aSize = pEditWin->GetSizePixel();
        Point aPoint = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() );
        aPoint = GetParent()->ScreenToOutputPixel( aPoint );
        Size aWinSize = GetSizePixel();
        aPoint.X() += aSize.Width() - aWinSize.Width() - 20;
        aPoint.Y() += aSize.Height() / 2 - aWinSize.Height() / 2;
        SetFloatingPos( aPoint );
    }

    SfxDockingWindow::StateChanged( nStateChange );
}

/*-- 10.12.2003 11:44:35---------------------------------------------------

  -----------------------------------------------------------------------*/
DropToolBox_Impl::DropToolBox_Impl(Window* pParent, SfxTemplateDialog_Impl* pTemplateDialog) :
    ToolBox(pParent),
    DropTargetHelper(this),
    rParent(*pTemplateDialog)
{
}
/*-- 10.12.2003 11:44:35---------------------------------------------------

  -----------------------------------------------------------------------*/
DropToolBox_Impl::~DropToolBox_Impl()
{
}
/*-- 10.12.2003 11:44:35---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Int8    DropToolBox_Impl::AcceptDrop( const AcceptDropEvent& rEvt )
{
    sal_Int8 nReturn = DND_ACTION_NONE;
    USHORT nItemId = GetItemId( rEvt.maPosPixel );
    if(USHRT_MAX != nItemId && !IsItemChecked( nItemId ))
    {
        SetCurItemId(nItemId);
        GetSelectHdl().Call(this);
    }
    // special case: page styles are allowed to create new styles by example
    // but not allowed to be created by drag and drop
    if ( nItemId != SfxCommonTemplateDialog_Impl::SfxFamilyIdToNId( SFX_STYLE_FAMILY_PAGE )&&
        IsDropFormatSupported( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) &&
        !rParent.bNewByExampleDisabled )
    {
        nReturn = DND_ACTION_COPY;
    }
    return nReturn;
}
/*-- 10.12.2003 11:44:35---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Int8    DropToolBox_Impl::ExecuteDrop( const ExecuteDropEvent& rEvt )
{
     return rParent.aFmtLb.ExecuteDrop(rEvt);
}

