/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <comphelper/string.hxx>
#include <sot/formats.hxx>
#include <vcl/msgbox.hxx>
#include <svl/urlbmk.hxx>
#include <svl/stritem.hxx>
#include <svl/intitem.hxx>
#include <svl/eitem.hxx>
#include <svtools/transfer.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/sfxsids.hrc>
#include "svtools/filter.hxx"
#include <editeng/brshitem.hxx>
#include "helpid.hrc"
#include "svx/gallery.hxx"
#include "galobj.hxx"
#include "svx/gallery1.hxx"
#include "svx/galtheme.hxx"
#include "svx/galctrl.hxx"
#include "svx/galmisc.hxx"
#include "galbrws2.hxx"
#include "gallery.hrc"
#include <vcl/svapp.hxx>
#include <svx/fmmodel.hxx>
#include <svx/dialmgr.hxx>
#include <svx/svxdlg.hxx>
#include <svx/dialogs.hrc>

// -----------
// - Defines -
// -----------

#undef GALLERY_USE_CLIPBOARD

#define TBX_ID_ICON 1
#define TBX_ID_LIST 2

// -----------
// - statics -
// -----------

GalleryBrowserMode GalleryBrowser2::meInitMode = GALLERYBROWSERMODE_ICON;

// --------------------------
// - GalleryBackgroundPopup -
// --------------------------

class GalleryBackgroundPopup : public PopupMenu, public SfxControllerItem
{
    const GalleryTheme* mpTheme;
    sal_uIntPtr             mnObjectPos;

    virtual void        Select();
    virtual void        StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState );

public:

                    GalleryBackgroundPopup( const GalleryTheme* pTheme, sal_uIntPtr nObjectPos );
                    ~GalleryBackgroundPopup();
};

// ------------------------------------------------------------------------
DBG_NAME(GalleryBackgroundPopup)

GalleryBackgroundPopup::GalleryBackgroundPopup( const GalleryTheme* pTheme, sal_uIntPtr nObjectPos ) :
            SfxControllerItem   ( SID_GALLERY_BG_BRUSH, SfxViewFrame::Current()->GetBindings() ),
            mpTheme             ( pTheme ),
            mnObjectPos         ( nObjectPos )
{
    DBG_CTOR(GalleryBackgroundPopup,NULL);
    SfxViewFrame::Current()->GetBindings().Update( SID_GALLERY_BG_BRUSH );
    RemoveDisabledEntries();
}

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

GalleryBackgroundPopup::~GalleryBackgroundPopup()
{
    DBG_DTOR(GalleryBackgroundPopup,NULL);
}

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

void GalleryBackgroundPopup::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pItem )
{
    if ( ( nSID == SID_GALLERY_BG_BRUSH ) && pItem && ( eState != SFX_ITEM_DISABLED ) )
    {
        SfxStringListItem*  pStrLstItem;
        SfxStringItem*      pStrItem;

        PopupMenu::Clear();

        if( ( pStrLstItem = PTR_CAST( SfxStringListItem, pItem ) ) != NULL )
        {
            const std::vector<String> &aList = pStrLstItem->GetList();

            for ( sal_uIntPtr i = 0, nCount = aList.size(); i < nCount; i++ )
                InsertItem( (sal_uInt16) i + 1, aList[i]);
        }
        else if( ( pStrItem = PTR_CAST( SfxStringItem, pItem ) ) != NULL )
            InsertItem( 1, pStrItem->GetValue() );
        else
        {
            OSL_FAIL( "SgaBGPopup::StateChanged(...): Wrong item type!" );
        }
    }
}

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

void GalleryBackgroundPopup::Select()
{
    Menu::Select();

    const INetURLObject aURL( mpTheme->GetObjectURL( mnObjectPos ) );
    const SvxBrushItem  aBrushItem( aURL.GetMainURL( INetURLObject::NO_DECODE ), String(), GPOS_TILED, SID_GALLERY_BG_BRUSH );
    const SfxUInt16Item aPosItem( SID_GALLERY_BG_POS, GetCurItemId() - 1 );
    const SfxStringItem aPathItem( SID_FILE_NAME, aURL.GetMainURL( INetURLObject::NO_DECODE ) );

    SfxViewFrame::Current()->GetBindings().GetDispatcher()->Execute( SID_GALLERY_BG_BRUSH,
                              SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
                              &aBrushItem, &aPosItem, &aPathItem, 0L );
}

// ---------------------
// - GalleryThemePopup -
// ---------------------

class GalleryThemePopup : public PopupMenu, public SfxControllerItem
{
    GalleryBackgroundPopup  maBackgroundPopup;
    const GalleryTheme*     mpTheme;
    sal_uIntPtr                 mnObjectPos;
    sal_Bool                    mbPreview;

    virtual void            StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState );

public:

                            GalleryThemePopup( const GalleryTheme* pTheme, sal_uIntPtr nObjectPos, sal_Bool bPreview );
                            ~GalleryThemePopup();
};

// ------------------------------------------------------------------------
DBG_NAME(GalleryThemePopup)

GalleryThemePopup::GalleryThemePopup( const GalleryTheme* pTheme, sal_uIntPtr nObjectPos, sal_Bool bPreview ) :
    PopupMenu           ( GAL_RES( RID_SVXMN_GALLERY2 ) ),
    SfxControllerItem   ( SID_GALLERY_ENABLE_ADDCOPY, SfxViewFrame::Current()->GetBindings() ),
    maBackgroundPopup   ( pTheme, nObjectPos ),
    mpTheme             ( pTheme ),
    mnObjectPos         ( nObjectPos ),
    mbPreview           ( bPreview )
{
    DBG_CTOR(GalleryThemePopup,NULL);

    const SgaObjKind    eObjKind = mpTheme->GetObjectKind( mnObjectPos );
    PopupMenu*          pAddMenu = GetPopupMenu( MN_ADDMENU );
    SfxBindings&        rBindings = SfxViewFrame::Current()->GetBindings();
    INetURLObject       aURL;

    const_cast< GalleryTheme* >( mpTheme )->GetURL( mnObjectPos, aURL );
    const sal_Bool bValidURL = ( aURL.GetProtocol() != INET_PROT_NOT_VALID );

    pAddMenu->EnableItem( MN_ADD, bValidURL && SGA_OBJ_SOUND != eObjKind );
    pAddMenu->EnableItem( MN_ADD_LINK, bValidURL && SGA_OBJ_SVDRAW != eObjKind );

    EnableItem( MN_ADDMENU, pAddMenu->IsItemEnabled( MN_ADD ) || pAddMenu->IsItemEnabled( MN_ADD_LINK ) );
    EnableItem( MN_PREVIEW, bValidURL );

    CheckItem( MN_PREVIEW, mbPreview );

    if( mpTheme->IsReadOnly() || !mpTheme->GetObjectCount() )
    {
        EnableItem( MN_DELETE, sal_False );
        EnableItem( MN_TITLE, sal_False );

        if( mpTheme->IsReadOnly() )
            EnableItem( MN_PASTECLIPBOARD, sal_False );

        if( !mpTheme->GetObjectCount() )
            EnableItem( MN_COPYCLIPBOARD, sal_False );
    }
    else
    {
        EnableItem( MN_DELETE, !bPreview );
        EnableItem( MN_TITLE, sal_True );
        EnableItem( MN_COPYCLIPBOARD, sal_True );
        EnableItem( MN_PASTECLIPBOARD, sal_True );
    }

#ifdef GALLERY_USE_CLIPBOARD
    if( IsItemEnabled( MN_PASTECLIPBOARD ) )
    {
        TransferableDataHelper  aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( this ) );
        sal_Bool                    bEnable = sal_False;

        if( aDataHelper.GetFormatCount() )
        {
            if( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) ||
                aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) ||
                aDataHelper.HasFormat( FORMAT_FILE ) ||
                aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) ||
                aDataHelper.HasFormat( FORMAT_GDIMETAFILE ) ||
                aDataHelper.HasFormat( FORMAT_BITMAP ) )
            {
                bEnable = sal_True;
            }
        }

        if( !bEnable )
            EnableItem( MN_PASTECLIPBOARD, sal_False );
    }
#else
    EnableItem( MN_COPYCLIPBOARD, sal_False );
    EnableItem( MN_PASTECLIPBOARD, sal_False );
#endif

    if( !maBackgroundPopup.GetItemCount() || ( eObjKind == SGA_OBJ_SVDRAW ) || ( eObjKind == SGA_OBJ_SOUND ) )
        pAddMenu->EnableItem( MN_BACKGROUND, sal_False );
    else
    {
        pAddMenu->EnableItem( MN_BACKGROUND, sal_True );
        pAddMenu->SetPopupMenu( MN_BACKGROUND, &maBackgroundPopup );
    }

    rBindings.Update( SID_GALLERY_ENABLE_ADDCOPY );
    RemoveDisabledEntries();
}

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

GalleryThemePopup::~GalleryThemePopup()
{
    DBG_DTOR(GalleryThemePopup,NULL);
}

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

void GalleryThemePopup::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pItem )
{
    if( ( nSID == SID_GALLERY_ENABLE_ADDCOPY ) && pItem && ( eState != SFX_ITEM_DISABLED ) )
    {
        SfxBoolItem*        pBoolItem = PTR_CAST( SfxBoolItem, pItem );
        const SgaObjKind    eObjKind = mpTheme->GetObjectKind( mnObjectPos );

        DBG_ASSERT( pBoolItem || pBoolItem == 0, "SfxBoolItem erwartet!");

        GetPopupMenu( MN_ADDMENU )->EnableItem( MN_ADD, pBoolItem->GetValue() && ( eObjKind != SGA_OBJ_SOUND ) );
    }
}

// ------------------
// - GalleryToolBox -
// ------------------
DBG_NAME(GalleryToolBox)

GalleryToolBox::GalleryToolBox( GalleryBrowser2* pParent ) :
    ToolBox( pParent, WB_TABSTOP )
{
    DBG_CTOR(GalleryToolBox,NULL);
}

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

GalleryToolBox::~GalleryToolBox()
{
    DBG_DTOR(GalleryToolBox,NULL);
}

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

void GalleryToolBox::KeyInput( const KeyEvent& rKEvt )
{
    if( !static_cast< GalleryBrowser2* >( GetParent() )->KeyInput( rKEvt, this ) )
        ToolBox::KeyInput( rKEvt );
}

// -------------------
// - GalleryBrowser2 -
// -------------------
DBG_NAME(GalleryBrowser2)

GalleryBrowser2::GalleryBrowser2( GalleryBrowser* pParent, const ResId& rResId, Gallery* pGallery ) :
    Control             ( pParent, rResId ),
    mpGallery           ( pGallery ),
    mpCurTheme          ( NULL ),
    mpIconView          ( new GalleryIconView( this, NULL ) ),
    mpListView          ( new GalleryListView( this, NULL ) ),
    mpPreview           ( new GalleryPreview( this, NULL ) ),
    maViewBox           ( this ),
    maSeparator         ( this, WB_VERT ),
    maInfoBar           ( this, WB_LEFT | WB_VCENTER ),
    mnCurActionPos      ( 0xffffffff ),
    meMode              ( GALLERYBROWSERMODE_NONE ),
    meLastMode          ( GALLERYBROWSERMODE_NONE ),
    mbCurActionIsLinkage( sal_False )
{
    DBG_CTOR(GalleryBrowser2,NULL);

    Image       aDummyImage;
    const Link  aSelectHdl( LINK( this, GalleryBrowser2, SelectObjectHdl ) );
    Font        aInfoFont( maInfoBar.GetControlFont() );

    maMiscOptions.AddListenerLink( LINK( this, GalleryBrowser2, MiscHdl ) );

    maViewBox.InsertItem( TBX_ID_ICON, aDummyImage );
    maViewBox.SetItemBits( TBX_ID_ICON, TIB_RADIOCHECK | TIB_AUTOCHECK );
    maViewBox.SetHelpId( TBX_ID_ICON, HID_GALLERY_ICONVIEW );
    maViewBox.SetQuickHelpText( TBX_ID_ICON, GAL_RESSTR(RID_SVXSTR_GALLERY_ICONVIEW) );

    maViewBox.InsertItem( TBX_ID_LIST, aDummyImage );
    maViewBox.SetItemBits( TBX_ID_LIST, TIB_RADIOCHECK | TIB_AUTOCHECK );
    maViewBox.SetHelpId( TBX_ID_LIST, HID_GALLERY_LISTVIEW );
    maViewBox.SetQuickHelpText( TBX_ID_LIST, GAL_RESSTR(RID_SVXSTR_GALLERY_LISTVIEW) );

    MiscHdl( NULL );
    maViewBox.SetSelectHdl( LINK( this, GalleryBrowser2, SelectTbxHdl ) );
    maViewBox.Show();

    mpIconView->SetAccessibleName(SVX_RESSTR(RID_SVXSTR_GALLERY_THEMEITEMS));
    mpListView->SetAccessibleName(SVX_RESSTR(RID_SVXSTR_GALLERY_THEMEITEMS));

    maInfoBar.Show();
    maSeparator.Show();

    mpIconView->SetSelectHdl( aSelectHdl );
    mpListView->SetSelectHdl( aSelectHdl );

    InitSettings();

    SetMode( ( GALLERYBROWSERMODE_PREVIEW != GalleryBrowser2::meInitMode ) ? GalleryBrowser2::meInitMode : GALLERYBROWSERMODE_ICON );

    if(maInfoBar.GetText().Len() == 0)
        mpIconView->SetAccessibleRelationLabeledBy(mpIconView);
    else
        mpIconView->SetAccessibleRelationLabeledBy(&maInfoBar);
    mpIconView->SetAccessibleRelationMemberOf(mpIconView);
}

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

GalleryBrowser2::~GalleryBrowser2()
{
    maMiscOptions.RemoveListenerLink( LINK( this, GalleryBrowser2, MiscHdl ) );

    delete mpPreview;
    delete mpListView;
    delete mpIconView;

    if( mpCurTheme )
        mpGallery->ReleaseTheme( mpCurTheme, *this );

    DBG_DTOR(GalleryBrowser2,NULL);
}

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

void GalleryBrowser2::InitSettings()
{
    Font  aInfoFont( maInfoBar.GetControlFont() );

    aInfoFont.SetWeight( WEIGHT_BOLD );
    aInfoFont.SetColor( GALLERY_FG_COLOR );
    maInfoBar.SetControlFont( aInfoFont );

    maInfoBar.SetBackground( Wallpaper( GALLERY_DLG_COLOR ) );
    maInfoBar.SetControlBackground( GALLERY_DLG_COLOR );

    maSeparator.SetBackground( Wallpaper( GALLERY_BG_COLOR ) );
    maSeparator.SetControlBackground( GALLERY_BG_COLOR );
    maSeparator.SetControlForeground( GALLERY_FG_COLOR );
}

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

void GalleryBrowser2::DataChanged( const DataChangedEvent& rDCEvt )
{
    if ( ( rDCEvt.GetType() == DATACHANGED_SETTINGS ) && ( rDCEvt.GetFlags() & SETTINGS_STYLE ) )
        InitSettings();
    else
        Control::DataChanged( rDCEvt );
}

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

void GalleryBrowser2::Resize()
{
    Control::Resize();

    mpIconView->Hide();
    mpListView->Hide();
    mpPreview->Hide();

    const Size  aOutSize( GetOutputSizePixel() );
    const Size  aBoxSize( maViewBox.GetOutputSizePixel() );
    const long  nOffset = 2, nSepWidth = 2;
    const long  nInfoBarX = aBoxSize.Width() + ( nOffset * 3 ) + nSepWidth;
    const Point aPt( 0, aBoxSize.Height() + 3 );
    const Size  aSz( aOutSize.Width(), aOutSize.Height() - aPt.Y() );

    maSeparator.SetPosSizePixel( Point( aBoxSize.Width() + nOffset, 0 ), Size( nSepWidth, aBoxSize.Height() ) );
    maInfoBar.SetPosSizePixel( Point( nInfoBarX, 0 ), Size( aOutSize.Width() - nInfoBarX, aBoxSize.Height() ) );

    mpIconView->SetPosSizePixel( aPt, aSz );
    mpListView->SetPosSizePixel( aPt, aSz );
    mpPreview->SetPosSizePixel( aPt, aSz );

    switch( GetMode() )
    {
        case( GALLERYBROWSERMODE_ICON ): mpIconView->Show(); break;
        case( GALLERYBROWSERMODE_LIST ): mpListView->Show(); break;
        case( GALLERYBROWSERMODE_PREVIEW ): mpPreview->Show(); break;

        default:
        break;
    }
}

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

void GalleryBrowser2::Notify( SfxBroadcaster&, const SfxHint& rHint )
{
    const GalleryHint& rGalleryHint = (const GalleryHint&) rHint;

    switch( rGalleryHint.GetType() )
    {
        case( GALLERY_HINT_THEME_UPDATEVIEW ):
        {
            if( GALLERYBROWSERMODE_PREVIEW == GetMode() )
                SetMode( meLastMode );

            ImplUpdateViews( (sal_uInt16) rGalleryHint.GetData1() + 1 );
        }
        break;

        default:
        break;
    }
}

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

sal_Int8 GalleryBrowser2::AcceptDrop( DropTargetHelper& rTarget, const AcceptDropEvent& )
{
    sal_Int8 nRet = DND_ACTION_NONE;

    if( mpCurTheme && !mpCurTheme->IsReadOnly() )
    {
        if( !mpCurTheme->IsDragging() )
        {
            if( rTarget.IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) ||
                rTarget.IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
                rTarget.IsDropFormatSupported( FORMAT_FILE ) ||
                rTarget.IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) ||
                rTarget.IsDropFormatSupported( FORMAT_GDIMETAFILE ) ||
                rTarget.IsDropFormatSupported( FORMAT_BITMAP ) )
            {
                nRet = DND_ACTION_COPY;
            }
        }
        else
            nRet = DND_ACTION_COPY;
    }

    return nRet;
}

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

sal_Int8 GalleryBrowser2::ExecuteDrop( DropTargetHelper&, const ExecuteDropEvent& rEvt )
{
    sal_Int8 nRet = DND_ACTION_NONE;

    if( mpCurTheme )
    {
        Point       aSelPos;
        const sal_uIntPtr nItemId = ImplGetSelectedItemId( &rEvt.maPosPixel, aSelPos );
        const sal_uIntPtr nInsertPos = (nItemId ? (nItemId - 1) : mpCurTheme->GetObjectCount());

        if( mpCurTheme->IsDragging() )
            mpCurTheme->ChangeObjectPos( mpCurTheme->GetDragPos(), nInsertPos );
        else
            nRet = mpCurTheme->InsertTransferable( rEvt.maDropEvent.Transferable, nInsertPos );
    }

    return nRet;
}

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

void GalleryBrowser2::StartDrag( Window*, const Point* pDragPoint )
{
    if( mpCurTheme )
    {
        Point       aSelPos;
        const sal_uIntPtr nItemId = ImplGetSelectedItemId( pDragPoint, aSelPos );

        if( nItemId )
            mpCurTheme->StartDrag( this, nItemId - 1 );
    }
}

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

void GalleryBrowser2::TogglePreview( Window*, const Point* )
{
    SetMode( ( GALLERYBROWSERMODE_PREVIEW != GetMode() ) ? GALLERYBROWSERMODE_PREVIEW : meLastMode );
    GetViewWindow()->GrabFocus();
}

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

void GalleryBrowser2::ShowContextMenu( Window*, const Point* pContextPoint )
{
    Point       aSelPos;
    const sal_uIntPtr nItemId = ImplGetSelectedItemId( pContextPoint, aSelPos );

    if( mpCurTheme && nItemId && ( nItemId <= mpCurTheme->GetObjectCount() ) )
    {
        ImplSelectItemId( nItemId );

        SfxViewFrame* pCurrentViewFrame = SfxViewFrame::Current();
        if ( pCurrentViewFrame )
        {
            SfxBindings& rBindings = pCurrentViewFrame->GetBindings();
            rBindings.ENTERREGISTRATIONS();
            GalleryThemePopup aMenu( mpCurTheme, nItemId - 1, GALLERYBROWSERMODE_PREVIEW == GetMode() );
            rBindings.LEAVEREGISTRATIONS();
            aMenu.SetSelectHdl( LINK( this, GalleryBrowser2, MenuSelectHdl ) );
            aMenu.Execute( this, aSelPos  );
        }
    }
}

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

sal_Bool GalleryBrowser2::KeyInput( const KeyEvent& rKEvt, Window* pWindow )
{
    Point       aSelPos;
    const sal_uIntPtr   nItemId = ImplGetSelectedItemId( NULL, aSelPos );
    sal_Bool        bRet = static_cast< GalleryBrowser* >( GetParent() )->KeyInput( rKEvt, pWindow );

    if( !bRet && !maViewBox.HasFocus() && nItemId && mpCurTheme )
    {
        sal_uInt16              nExecuteId = 0;
        const SgaObjKind    eObjKind = mpCurTheme->GetObjectKind( nItemId - 1 );
        INetURLObject       aURL;

        const_cast< GalleryTheme* >( mpCurTheme )->GetURL( nItemId - 1, aURL );

        const sal_Bool  bValidURL = ( aURL.GetProtocol() != INET_PROT_NOT_VALID );
        sal_Bool        bPreview = bValidURL;
        sal_Bool        bAdd = bValidURL;
        sal_Bool        bAddLink = ( bValidURL && SGA_OBJ_SVDRAW != eObjKind );
        sal_Bool        bDelete = sal_False;
        sal_Bool        bTitle = sal_False;

        if( !mpCurTheme->IsReadOnly() && mpCurTheme->GetObjectCount() )
        {
            bDelete = ( GALLERYBROWSERMODE_PREVIEW != GetMode() );
            bTitle = sal_True;
        }

        switch( rKEvt.GetKeyCode().GetCode() )
        {
            case( KEY_SPACE ):
            case( KEY_RETURN ):
            case( KEY_P ):
            {
                if( bPreview )
                {
                    TogglePreview( pWindow );
                    bRet = sal_True;
                }
            }
            break;

            case( KEY_INSERT ):
            case( KEY_I ):
            {
                if( bAddLink && rKEvt.GetKeyCode().IsShift() && rKEvt.GetKeyCode().IsMod1() )
                    nExecuteId = MN_ADD_LINK;
                else if( bAdd )
                    nExecuteId = MN_ADD;
            }
            break;

            case( KEY_DELETE ):
            case( KEY_D ):
            {
                if( bDelete )
                    nExecuteId = MN_DELETE;
            }
            break;

            case( KEY_T ):
            {
                if( bTitle )
                    nExecuteId = MN_TITLE;
            }
            break;

            default:
            break;
        }

        if( nExecuteId )
        {
            ImplExecute( nExecuteId );
            bRet = sal_True;
        }
    }

    return bRet;
}

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

void GalleryBrowser2::SelectTheme( const String& rThemeName )
{
    delete mpIconView, mpIconView = NULL;
    delete mpListView, mpListView = NULL;
    delete mpPreview, mpPreview = NULL;

    if( mpCurTheme )
        mpGallery->ReleaseTheme( mpCurTheme, *this );

    mpCurTheme = mpGallery->AcquireTheme( rThemeName, *this );

    mpIconView = new GalleryIconView( this, mpCurTheme );
    mpListView = new GalleryListView( this, mpCurTheme );
    mpPreview = new GalleryPreview( this, mpCurTheme );

    mpIconView->SetAccessibleName(SVX_RESSTR(RID_SVXSTR_GALLERY_THEMEITEMS));
    mpListView->SetAccessibleName(SVX_RESSTR(RID_SVXSTR_GALLERY_THEMEITEMS));
    mpPreview->SetAccessibleName(SVX_RESSTR(RID_SVXSTR_GALLERY_PREVIEW));

    const Link aSelectHdl( LINK( this, GalleryBrowser2, SelectObjectHdl ) );

    mpIconView->SetSelectHdl( aSelectHdl );
    mpListView->SetSelectHdl( aSelectHdl );

    if( GALLERYBROWSERMODE_PREVIEW == GetMode() )
        meMode = meLastMode;

    Resize();
    ImplUpdateViews( 1 );

    maViewBox.EnableItem( TBX_ID_ICON, sal_True );
    maViewBox.EnableItem( TBX_ID_LIST, sal_True );
    maViewBox.CheckItem( ( GALLERYBROWSERMODE_ICON == GetMode() ) ? TBX_ID_ICON : TBX_ID_LIST, sal_True );

    if(maInfoBar.GetText().Len() == 0)
        mpIconView->SetAccessibleRelationLabeledBy(mpIconView);
    else
        mpIconView->SetAccessibleRelationLabeledBy(&maInfoBar);
    mpIconView->SetAccessibleRelationMemberOf(mpIconView);
}

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

void GalleryBrowser2::SetMode( GalleryBrowserMode eMode )
{
    if( GetMode() != eMode )
    {
        meLastMode = GetMode();

        switch( eMode )
        {
            case( GALLERYBROWSERMODE_ICON ):
            {
                mpListView->Hide();

                mpPreview->Hide();
                mpPreview->SetGraphic( Graphic() );
                mpPreview->PreviewMedia( INetURLObject() );

                mpIconView->Show();

                maViewBox.EnableItem( TBX_ID_ICON, sal_True );
                maViewBox.EnableItem( TBX_ID_LIST, sal_True );

                maViewBox.CheckItem( TBX_ID_ICON, sal_True );
                maViewBox.CheckItem( TBX_ID_LIST, sal_False );
            }
            break;

            case( GALLERYBROWSERMODE_LIST ):
            {
                mpIconView->Hide();

                mpPreview->Hide();
                mpPreview->SetGraphic( Graphic() );
                mpPreview->PreviewMedia( INetURLObject() );

                mpListView->Show();

                maViewBox.EnableItem( TBX_ID_ICON, sal_True );
                maViewBox.EnableItem( TBX_ID_LIST, sal_True );

                maViewBox.CheckItem( TBX_ID_ICON, sal_False );
                maViewBox.CheckItem( TBX_ID_LIST, sal_True );
            }
            break;

            case( GALLERYBROWSERMODE_PREVIEW ):
            {
                Graphic     aGraphic;
                Point       aSelPos;
                const sal_uIntPtr   nItemId = ImplGetSelectedItemId( NULL, aSelPos );

                if( nItemId )
                {
                    const sal_uIntPtr nPos = nItemId - 1;

                       mpIconView->Hide();
                    mpListView->Hide();

                    if( mpCurTheme )
                        mpCurTheme->GetGraphic( nPos, aGraphic );

                    mpPreview->SetGraphic( aGraphic );
                     mpPreview->Show();

                    if( mpCurTheme && mpCurTheme->GetObjectKind( nPos ) == SGA_OBJ_SOUND )
                        mpPreview->PreviewMedia( mpCurTheme->GetObjectURL( nPos ) );

                    maViewBox.EnableItem( TBX_ID_ICON, sal_False );
                    maViewBox.EnableItem( TBX_ID_LIST, sal_False );
                }
            }
            break;

            default:
                break;
        }

        GalleryBrowser2::meInitMode = meMode = eMode;
    }
}

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

Window* GalleryBrowser2::GetViewWindow() const
{
    Window* pRet;

    switch( GetMode() )
    {
        case( GALLERYBROWSERMODE_LIST ): pRet = mpListView; break;
        case( GALLERYBROWSERMODE_PREVIEW ): pRet = mpPreview; break;

        default:
            pRet = mpIconView;
        break;
    }

    return pRet;
}

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

void GalleryBrowser2::Travel( GalleryBrowserTravel eTravel )
{
    if( mpCurTheme )
    {
        Point       aSelPos;
        const sal_uIntPtr nItemId = ImplGetSelectedItemId( NULL, aSelPos );

        if( nItemId )
        {
            sal_uIntPtr nNewItemId = nItemId;

            switch( eTravel )
            {
                case( GALLERYBROWSERTRAVEL_FIRST ):     nNewItemId = 1; break;
                case( GALLERYBROWSERTRAVEL_LAST ):      nNewItemId = mpCurTheme->GetObjectCount(); break;
                case( GALLERYBROWSERTRAVEL_PREVIOUS ):  nNewItemId--; break;
                case( GALLERYBROWSERTRAVEL_NEXT ):      nNewItemId++; break;
                default:
                    break;
            }

            if( nNewItemId < 1 )
                nNewItemId = 1;
            else if( nNewItemId > mpCurTheme->GetObjectCount() )
                nNewItemId = mpCurTheme->GetObjectCount();

            if( nNewItemId != nItemId )
            {
                ImplSelectItemId( nNewItemId );
                ImplUpdateInfoBar();

                if( GALLERYBROWSERMODE_PREVIEW == GetMode() )
                {
                    Graphic     aGraphic;
                    const sal_uIntPtr nPos = nNewItemId - 1;

                    mpCurTheme->GetGraphic( nPos, aGraphic );
                    mpPreview->SetGraphic( aGraphic );

                    if( SGA_OBJ_SOUND == mpCurTheme->GetObjectKind( nPos ) )
                        mpPreview->PreviewMedia( mpCurTheme->GetObjectURL( nPos ) );

                    mpPreview->Invalidate();
                }
            }
        }
    }
}

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

void GalleryBrowser2::ImplUpdateViews( sal_uInt16 nSelectionId )
{
    mpIconView->Hide();
    mpListView->Hide();
    mpPreview->Hide();

    mpIconView->Clear();
    mpListView->Clear();

    if( mpCurTheme )
    {
        for( sal_uIntPtr i = 0, nCount = mpCurTheme->GetObjectCount(); i < nCount; )
        {
            mpListView->RowInserted( i++ );
            mpIconView->InsertItem( (sal_uInt16) i );
        }

        ImplSelectItemId( ( ( nSelectionId > mpCurTheme->GetObjectCount() ) ? mpCurTheme->GetObjectCount() : nSelectionId ) );
    }

    switch( GetMode() )
    {
        case( GALLERYBROWSERMODE_ICON ): mpIconView->Show(); break;
        case( GALLERYBROWSERMODE_LIST ): mpListView->Show(); break;
        case( GALLERYBROWSERMODE_PREVIEW ): mpPreview->Show(); break;

        default:
        break;
    }

    ImplUpdateInfoBar();
}

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

void GalleryBrowser2::ImplUpdateInfoBar()
{
    String aInfoText;

    if( mpCurTheme )
    {
        Point       aSelPos;
        const sal_uIntPtr nItemId = ImplGetSelectedItemId( NULL, aSelPos );

        if( nItemId )
        {
            const sal_uIntPtr nPos = nItemId - 1;

            aInfoText = mpCurTheme->GetName();

            if( nPos < mpCurTheme->GetObjectCount() )
            {
                SgaObject* pObj = mpCurTheme->AcquireObject( nPos );

                if( pObj )
                {
                    aInfoText = GetItemText( *mpCurTheme, *pObj, GALLERY_ITEM_THEMENAME | GALLERY_ITEM_TITLE | GALLERY_ITEM_PATH );
                    mpCurTheme->ReleaseObject( pObj );
                }
            }
        }
    }

    maInfoBar.SetText( aInfoText );
}

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

sal_uIntPtr GalleryBrowser2::ImplGetSelectedItemId( const Point* pSelPos, Point& rSelPos )
{
    const Size  aOutputSizePixel( GetOutputSizePixel() );
    sal_uIntPtr       nRet = 0;

    if( GALLERYBROWSERMODE_PREVIEW == GetMode() )
    {
        nRet = ( ( GALLERYBROWSERMODE_ICON == meLastMode ) ? mpIconView->GetSelectItemId() : ( mpListView->FirstSelectedRow() + 1 ) );

        if( pSelPos )
            rSelPos = GetPointerPosPixel();
        else
            rSelPos = Point( aOutputSizePixel.Width() >> 1, aOutputSizePixel.Height() >> 1 );
    }
    else if( GALLERYBROWSERMODE_ICON == GetMode() )
    {
        if( pSelPos )
        {
            nRet = mpIconView->GetItemId( *pSelPos );
            rSelPos = GetPointerPosPixel();
        }
        else
        {
            nRet = mpIconView->GetSelectItemId();
            rSelPos = mpIconView->GetItemRect( (sal_uInt16) nRet ).Center();
        }
    }
    else
    {
        if( pSelPos )
        {
            nRet = mpListView->GetRowAtYPosPixel( pSelPos->Y() ) + 1;
            rSelPos = GetPointerPosPixel();
        }
        else
        {
            nRet = mpListView->FirstSelectedRow() + 1;
            rSelPos = mpListView->GetFieldRectPixel( (sal_uInt16) nRet, 1 ).Center();
        }
    }

    rSelPos.X() = Max( Min( rSelPos.X(), aOutputSizePixel.Width() - 1L ), 0L );
    rSelPos.Y() = Max( Min( rSelPos.Y(), aOutputSizePixel.Height() - 1L ), 0L );

    if( nRet && ( !mpCurTheme || ( nRet > mpCurTheme->GetObjectCount() ) ) )
    {
        nRet = 0;
    }

    return nRet;
}

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

void GalleryBrowser2::ImplSelectItemId( sal_uIntPtr nItemId )
{
    if( nItemId )
    {

        mpIconView->SelectItem( (sal_uInt16) nItemId );
        mpListView->SelectRow( nItemId - 1 );
    }
}

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

void GalleryBrowser2::ImplExecute( sal_uInt16 nId )
{
    Point       aSelPos;
    const sal_uIntPtr nItemId = ImplGetSelectedItemId( NULL, aSelPos );

    if( mpCurTheme && nItemId )
    {
        mnCurActionPos = nItemId - 1;

        switch( nId )
        {
            case( MN_ADD ):
            case( MN_ADD_LINK ):
            {
                sal_uInt32 nFormat = 0;

                mbCurActionIsLinkage = ( MN_ADD_LINK == nId );

                switch( mpCurTheme->GetObjectKind( mnCurActionPos ) )
                {
                    case( SGA_OBJ_BMP ):
                    case( SGA_OBJ_ANIM ):
                    case( SGA_OBJ_INET ):
                        nFormat = SGA_FORMAT_GRAPHIC | SGA_FORMAT_STRING;
                    break;

                    case ( SGA_OBJ_SOUND ) :
                        nFormat = SGA_FORMAT_SOUND | SGA_FORMAT_STRING;
                    break;

                    case( SGA_OBJ_SVDRAW ):
                        nFormat = SGA_FORMAT_GRAPHIC | SGA_FORMAT_SVDRAW | SGA_FORMAT_STRING;
                    break;

                    default :
                    break;
                }

                const SfxUInt32Item aItem( SID_GALLERY_FORMATS, nFormat );
                SfxViewFrame::Current()->GetBindings().GetDispatcher()->Execute(
                    SID_GALLERY_FORMATS, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD, &aItem, 0L );
            }
            break;

            case( MN_PREVIEW ):
                SetMode( ( GALLERYBROWSERMODE_PREVIEW != GetMode() ) ? GALLERYBROWSERMODE_PREVIEW : meLastMode );
            break;

            case( MN_DELETE ):
            {
                if( !mpCurTheme->IsReadOnly() &&
                    QueryBox(NULL, WB_YES_NO, GAL_RESSTR(RID_SVXSTR_GALLERY_DELETEOBJ)).Execute() == RET_YES )
                {
                    mpCurTheme->RemoveObject( mnCurActionPos );
                }
            }
            break;

            case( MN_TITLE ):
            {
                SgaObject* pObj = mpCurTheme->AcquireObject( mnCurActionPos );

                if( pObj )
                {
                    const String    aOldTitle( GetItemText( *mpCurTheme, *pObj, GALLERY_ITEM_TITLE ) );

                    SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
                    if(pFact)
                    {
                        AbstractTitleDialog* aDlg = pFact->CreateTitleDialog( this, aOldTitle );
                        DBG_ASSERT(aDlg, "Dialogdiet fail!");
                        if( aDlg->Execute() == RET_OK )
                        {
                            String aNewTitle( aDlg->GetTitle() );

                            if( ( !aNewTitle.Len() && pObj->GetTitle().Len() ) || ( aNewTitle != aOldTitle ) )
                            {
                                if( !aNewTitle.Len() )
                                    aNewTitle = String( RTL_CONSTASCII_USTRINGPARAM( "__<empty>__" ) );

                                pObj->SetTitle( aNewTitle );
                                mpCurTheme->InsertObject( *pObj );
                            }
                        }

                        mpCurTheme->ReleaseObject( pObj );
                        delete aDlg;
                    }
                }
            }
            break;

            case( MN_COPYCLIPBOARD ):
            {
                Window* pWindow;

                switch( GetMode() )
                {
                    case( GALLERYBROWSERMODE_ICON ): pWindow = (Window*) mpIconView; break;
                    case( GALLERYBROWSERMODE_LIST ): pWindow = (Window*) mpListView; break;
                    case( GALLERYBROWSERMODE_PREVIEW ): pWindow = (Window*) mpPreview; break;

                    default:
                        pWindow = NULL;
                    break;
                }

                mpCurTheme->CopyToClipboard( pWindow, mnCurActionPos );
            }
            break;

            case( MN_PASTECLIPBOARD ):
            {
                if( !mpCurTheme->IsReadOnly() )
                {
                    TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( this ) );
                    mpCurTheme->InsertTransferable( aDataHelper.GetTransferable(), mnCurActionPos );
                }
            }
            break;

            default:
            break;
        }
    }
}

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

String GalleryBrowser2::GetItemText( const GalleryTheme& rTheme, const SgaObject& rObj, sal_uIntPtr nItemTextFlags )
{
    String          aRet;

    INetURLObject aURL(rObj.GetURL());

    if( nItemTextFlags & GALLERY_ITEM_THEMENAME )
    {
        aRet += rTheme.GetName();
        aRet += String( RTL_CONSTASCII_USTRINGPARAM( " - " ) );
    }

    if( nItemTextFlags & GALLERY_ITEM_TITLE )
    {
        String aTitle( rObj.GetTitle() );

        if( !aTitle.Len() )
            aTitle = aURL.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_UNAMBIGUOUS );

        if( !aTitle.Len() )
        {
            aTitle = aURL.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS );
            aTitle = aTitle.GetToken( comphelper::string::getTokenCount(aTitle, '/') - 1, '/' );
        }

        aRet += aTitle;
    }

    if( nItemTextFlags & GALLERY_ITEM_PATH )
    {
        const String aPath( aURL.getFSysPath( INetURLObject::FSYS_DETECT ) );

        if( aPath.Len() && ( nItemTextFlags & GALLERY_ITEM_TITLE ) )
            aRet += String( RTL_CONSTASCII_USTRINGPARAM( " (" ) );

        aRet += String(aURL.getFSysPath( INetURLObject::FSYS_DETECT ));

        if( aPath.Len() && ( nItemTextFlags & GALLERY_ITEM_TITLE ) )
            aRet += ')';
    }

    return aRet;
}

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

INetURLObject GalleryBrowser2::GetURL() const
{
    INetURLObject aURL;

    if( mpCurTheme && mnCurActionPos != 0xffffffff )
        aURL = mpCurTheme->GetObjectURL( mnCurActionPos );

    return aURL;
}

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

String GalleryBrowser2::GetFilterName() const
{
    String aFilterName;

    if( mpCurTheme && mnCurActionPos != 0xffffffff )
    {
        const SgaObjKind eObjKind = mpCurTheme->GetObjectKind( mnCurActionPos );

        if( ( SGA_OBJ_BMP == eObjKind ) || ( SGA_OBJ_ANIM == eObjKind ) )
        {
            GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
            INetURLObject       aURL; mpCurTheme->GetURL( mnCurActionPos, aURL );
            sal_uInt16          nFilter = rFilter.GetImportFormatNumberForShortName( aURL.GetExtension() );

            if( GRFILTER_FORMAT_DONTKNOW != nFilter )
                aFilterName = rFilter.GetImportFormatName( nFilter );
        }
    }

    return aFilterName;
}

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

Graphic GalleryBrowser2::GetGraphic() const
{
    Graphic aGraphic;

    if( mpCurTheme && mnCurActionPos != 0xffffffff )
        mpCurTheme->GetGraphic( mnCurActionPos, aGraphic );

    return aGraphic;
}

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

sal_Bool GalleryBrowser2::IsLinkage() const
{
    return mbCurActionIsLinkage;
}

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

IMPL_LINK( GalleryBrowser2, MenuSelectHdl, Menu*, pMenu )
{
    if( pMenu )
        ImplExecute( pMenu->GetCurItemId() );

    return 0;
}

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

IMPL_LINK_NOARG(GalleryBrowser2, SelectObjectHdl)
{
    ImplUpdateInfoBar();
    return 0L;
}

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

IMPL_LINK( GalleryBrowser2, SelectTbxHdl, ToolBox*, pBox )
{
    if( pBox->GetCurItemId() == TBX_ID_ICON )
        SetMode( GALLERYBROWSERMODE_ICON );
    else if( pBox->GetCurItemId() == TBX_ID_LIST )
        SetMode( GALLERYBROWSERMODE_LIST );

    return 0L;
}

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

IMPL_LINK_NOARG(GalleryBrowser2, MiscHdl)
{
    maViewBox.SetOutStyle( maMiscOptions.GetToolboxStyle() );

    BitmapEx aIconBmpEx = BitmapEx( Image( GAL_RES( RID_SVXIMG_GALLERY_VIEW_ICON ) ).GetBitmapEx() );
    BitmapEx aListBmpEx = BitmapEx( Image( GAL_RES( RID_SVXIMG_GALLERY_VIEW_LIST ) ).GetBitmapEx() );

    if( maMiscOptions.AreCurrentSymbolsLarge() )
    {
        const Size aLargeSize( 24, 24);

        aIconBmpEx.Scale( aLargeSize );
        aListBmpEx.Scale( aLargeSize );
    }

    maViewBox.SetItemImage( TBX_ID_ICON, aIconBmpEx );
    maViewBox.SetItemImage( TBX_ID_LIST, aListBmpEx );
    maViewBox.SetSizePixel( maViewBox.CalcWindowSizePixel() );

    Resize();

    return 0L;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */