move now combined ColorLB to location of last user

Change-Id: I5dc1204c28b65d5dca993bf38aea217bbb49e913
diff --git a/cui/source/options/optchart.cxx b/cui/source/options/optchart.cxx
index 3d95da7..254b464 100644
--- a/cui/source/options/optchart.cxx
+++ b/cui/source/options/optchart.cxx
@@ -21,9 +21,337 @@
#include <cuires.hrc>
#include "optchart.hxx"
#include <dialmgr.hxx>
#include <vcl/builderfactory.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/svapp.hxx>
#include <svx/svxids.hrc>

class SAL_WARN_UNUSED SVX_DLLPUBLIC ColorLB : public ListBox
{
    ImpColorList*   pColorList; // separate liste, in case of user data are required from outside
    Size            aImageSize;

    using Window::ImplInit;
    SVT_DLLPRIVATE void         ImplInit();
    SVT_DLLPRIVATE void         ImplDestroyColorEntries();

public:
                    ColorLB( vcl::Window* pParent,
                                  WinBits nWinStyle = WB_BORDER );
    virtual         ~ColorLB() override;
    virtual void    dispose() override;

    virtual void    UserDraw( const UserDrawEvent& rUDEvt ) override;

    using ListBox::InsertEntry;
    sal_Int32       InsertEntry( const OUString& rStr,
                                 sal_Int32  nPos = LISTBOX_APPEND );
    sal_Int32       InsertEntry( const Color& rColor, const OUString& rStr,
                                 sal_Int32  nPos = LISTBOX_APPEND );
    bool            IsAutomaticSelected() { return !GetSelectEntryPos(); }
    using ListBox::RemoveEntry;
    void            RemoveEntry( sal_Int32  nPos );
    void            Clear();
    void            CopyEntries( const ColorLB& rBox );

    using ListBox::GetEntryPos;
    sal_Int32       GetEntryPos( const Color& rColor ) const;
    Color           GetEntryColor( sal_Int32  nPos ) const;

    void            SelectEntry( const OUString& rStr )
                        { ListBox::SelectEntry( rStr ); }

    void SelectEntry( const Color& rColor )
    {
        sal_Int32  nPos = GetEntryPos( rColor );
        if ( nPos != LISTBOX_ENTRY_NOTFOUND )
            ListBox::SelectEntryPos( nPos );
    }

    Color GetSelectEntryColor() const
    {
        sal_Int32  nPos = GetSelectEntryPos();
        Color aColor;
        if ( nPos != LISTBOX_ENTRY_NOTFOUND )
            aColor = GetEntryColor( nPos );
        return aColor;
    }

    using ListBox::IsEntrySelected;

    bool            IsEntrySelected(const Color& rColor) const
    {
        sal_Int32  nPos = GetEntryPos( rColor );
        if ( nPos != LISTBOX_ENTRY_NOTFOUND )
            return IsEntryPosSelected( nPos );
        else
            return false;
    }

    void Fill( const XColorListRef &pTab );

    void Append( const XColorEntry& rEntry );
    void Modify( const XColorEntry& rEntry, sal_Int32 nPos );

private:
                    ColorLB( const ColorLB& ) = delete;
    ColorLB&   operator =( const ColorLB& ) = delete;
};

VCL_BUILDER_DECL_FACTORY(ColorLB)
{
    bool bDropdown = VclBuilder::extractDropdown(rMap);
    WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_SIMPLEMODE|WB_TABSTOP;
    if (bDropdown)
        nWinBits |= WB_DROPDOWN;
    OString sBorder = VclBuilder::extractCustomProperty(rMap);
    if (!sBorder.isEmpty())
        nWinBits |= WB_BORDER;
    VclPtrInstance<ColorLB> pListBox(pParent, nWinBits);
    pListBox->EnableAutoSize(true);
    rRet = pListBox;
}

class ImplColorListData
{
public:
    Color       aColor;
    bool        bColor;

                ImplColorListData() : aColor( COL_BLACK ) { bColor = false; }
                explicit ImplColorListData( const Color& rColor ) : aColor( rColor ) { bColor = true; }
};

void ColorLB::ImplInit()
{
    pColorList = new ImpColorList();

    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
    aImageSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize();
    EnableUserDraw( true );
    SetUserItemSize( aImageSize );
}

void ColorLB::ImplDestroyColorEntries()
{
    for ( size_t n = pColorList->size(); n; )
        delete (*pColorList)[ --n ];
    pColorList->clear();
}

ColorLB::ColorLB( vcl::Window* pParent, WinBits nWinStyle ) :
    ListBox( pParent, nWinStyle )
{
    ImplInit();
    SetEdgeBlending(true);
}

ColorLB::~ColorLB()
{
    disposeOnce();
}

void ColorLB::dispose()
{
    if ( pColorList )
    {
        ImplDestroyColorEntries();
        delete pColorList;
        pColorList = nullptr;
    }
    ListBox::dispose();
}

sal_Int32 ColorLB::InsertEntry( const OUString& rStr, sal_Int32 nPos )
{
    nPos = ListBox::InsertEntry( rStr, nPos );
    if ( nPos != LISTBOX_ERROR )
    {
        ImplColorListData* pData = new ImplColorListData;
        if ( static_cast<size_t>(nPos) < pColorList->size() )
        {
            ImpColorList::iterator it = pColorList->begin();
            ::std::advance( it, nPos );
            pColorList->insert( it, pData );
        }
        else
        {
            pColorList->push_back( pData );
            nPos = pColorList->size() - 1;
        }
    }
    return nPos;
}

sal_Int32 ColorLB::InsertEntry( const Color& rColor, const OUString& rStr,
                                sal_Int32 nPos )
{
    nPos = ListBox::InsertEntry( rStr, nPos );
    if ( nPos != LISTBOX_ERROR )
    {
        ImplColorListData* pData = new ImplColorListData( rColor );
        if ( static_cast<size_t>(nPos) < pColorList->size() )
        {
            ImpColorList::iterator it = pColorList->begin();
            ::std::advance( it, nPos );
            pColorList->insert( it, pData );
        }
        else
        {
            pColorList->push_back( pData );
            nPos = pColorList->size() - 1;
        }
    }
    return nPos;
}

void ColorLB::RemoveEntry( sal_Int32 nPos )
{
    ListBox::RemoveEntry( nPos );
    if ( 0 <= nPos && static_cast<size_t>(nPos) < pColorList->size() )
    {
            ImpColorList::iterator it = pColorList->begin();
            ::std::advance( it, nPos );
            delete *it;
            pColorList->erase( it );
    }
}

void ColorLB::Clear()
{
    ImplDestroyColorEntries();
    ListBox::Clear();
}

void ColorLB::CopyEntries( const ColorLB& rBox )
{
    // Liste leeren
    ImplDestroyColorEntries();

    // Daten kopieren
    size_t nCount = rBox.pColorList->size();
    for ( size_t n = 0; n < nCount; n++ )
    {
        ImplColorListData* pData = (*rBox.pColorList)[ n ];
        sal_Int32 nPos = InsertEntry( rBox.GetEntry( n ) );
        if ( nPos != LISTBOX_ERROR )
        {
            if ( static_cast<size_t>(nPos) < pColorList->size() )
            {
                ImpColorList::iterator it = pColorList->begin();
                ::std::advance( it, nPos );
                pColorList->insert( it, new ImplColorListData( *pData ) );
            }
            else
            {
                pColorList->push_back( new ImplColorListData( *pData ) );
            }
        }
    }
}

sal_Int32 ColorLB::GetEntryPos( const Color& rColor ) const
{
    for( sal_Int32 n = (sal_Int32) pColorList->size(); n; )
    {
        ImplColorListData* pData = (*pColorList)[ --n ];
        if ( pData->bColor && ( pData->aColor == rColor ) )
            return n;
    }
    return LISTBOX_ENTRY_NOTFOUND;
}

Color ColorLB::GetEntryColor( sal_Int32 nPos ) const
{
    Color aColor;
    ImplColorListData* pData = ( 0 <= nPos && static_cast<size_t>(nPos) < pColorList->size() ) ?
        (*pColorList)[ nPos ] : nullptr;
    if ( pData && pData->bColor )
        aColor = pData->aColor;
    return aColor;
}

void ColorLB::UserDraw( const UserDrawEvent& rUDEvt )
{
    size_t nPos = rUDEvt.GetItemId();
    ImplColorListData* pData = ( nPos < pColorList->size() ) ? (*pColorList)[ nPos ] : nullptr;
    if ( pData )
    {
        if ( pData->bColor )
        {
            Point aPos( rUDEvt.GetRect().TopLeft() );

            aPos.X() += 2;
            aPos.Y() += ( rUDEvt.GetRect().GetHeight() - aImageSize.Height() ) / 2;

            const Rectangle aRect(aPos, aImageSize);

            vcl::RenderContext* pRenderContext = rUDEvt.GetRenderContext();
            pRenderContext->Push();
            pRenderContext->SetFillColor(pData->aColor);
            pRenderContext->SetLineColor(pRenderContext->GetTextColor());
            pRenderContext->DrawRect(aRect);
            pRenderContext->Pop();

            const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
            const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);

            if(nEdgeBlendingPercent)
            {
                const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
                const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
                const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
                const BitmapEx aBlendFrame(createBlendFrame(aRect.GetSize(), nAlpha, rTopLeft, rBottomRight));

                if(!aBlendFrame.IsEmpty())
                {
                    pRenderContext->DrawBitmapEx(aRect.TopLeft(), aBlendFrame);
                }
            }

            ListBox::DrawEntry( rUDEvt, false, false );
        }
        else
            ListBox::DrawEntry( rUDEvt, false, true );
    }
    else
        ListBox::DrawEntry( rUDEvt, true, false );
}


// Fills the Listbox with color and strings

void ColorLB::Fill( const XColorListRef &pColorTab )
{
    if( !pColorTab.is() )
        return;

    long nCount = pColorTab->Count();
    SetUpdateMode( false );

    for( long i = 0; i < nCount; i++ )
    {
        const XColorEntry* pEntry = pColorTab->GetColor(i);
        InsertEntry( pEntry->GetColor(), pEntry->GetName() );
    }

    AdaptDropDownLineCountToMaximum();
    SetUpdateMode( true );
}

void ColorLB::Append( const XColorEntry& rEntry )
{
    InsertEntry( rEntry.GetColor(), rEntry.GetName() );
    AdaptDropDownLineCountToMaximum();
}

void ColorLB::Modify( const XColorEntry& rEntry, sal_Int32 nPos )
{
    RemoveEntry( nPos );
    InsertEntry( rEntry.GetColor(), rEntry.GetName(), nPos );
}


namespace
{
    void FillBoxChartColorLB(ColorLB *pLB, const SvxChartColorTable & rTab)
diff --git a/cui/source/options/optchart.hxx b/cui/source/options/optchart.hxx
index 34cd211..30f3196 100644
--- a/cui/source/options/optchart.hxx
+++ b/cui/source/options/optchart.hxx
@@ -29,6 +29,8 @@

#include "cfgchart.hxx"

class ColorLB;

class SvxDefaultColorOptPage : public SfxTabPage
{

diff --git a/cui/uiconfig/ui/optchartcolorspage.ui b/cui/uiconfig/ui/optchartcolorspage.ui
index 3cadc55..f01beda 100644
--- a/cui/uiconfig/ui/optchartcolorspage.ui
+++ b/cui/uiconfig/ui/optchartcolorspage.ui
@@ -26,7 +26,7 @@
            <property name="top_padding">6</property>
            <property name="left_padding">12</property>
            <child>
              <object class="svxlo-ColorLB" id="colors:border">
              <object class="cuilo-ColorLB" id="colors:border">
                <property name="dropdown">False</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
diff --git a/include/svx/dlgctrl.hxx b/include/svx/dlgctrl.hxx
index cb0eec0..39cc688 100644
--- a/include/svx/dlgctrl.hxx
+++ b/include/svx/dlgctrl.hxx
@@ -207,80 +207,6 @@ public:

/************************************************************************/

class SAL_WARN_UNUSED SVX_DLLPUBLIC ColorLB : public ListBox
{
    ImpColorList*   pColorList; // separate liste, in case of user data are required from outside
    Size            aImageSize;

    using Window::ImplInit;
    SVT_DLLPRIVATE void         ImplInit();
    SVT_DLLPRIVATE void         ImplDestroyColorEntries();

public:
                    ColorLB( vcl::Window* pParent,
                                  WinBits nWinStyle = WB_BORDER );
    virtual         ~ColorLB() override;
    virtual void    dispose() override;

    virtual void    UserDraw( const UserDrawEvent& rUDEvt ) override;

    using ListBox::InsertEntry;
    sal_Int32       InsertEntry( const OUString& rStr,
                                 sal_Int32  nPos = LISTBOX_APPEND );
    sal_Int32       InsertEntry( const Color& rColor, const OUString& rStr,
                                 sal_Int32  nPos = LISTBOX_APPEND );
    bool            IsAutomaticSelected() { return !GetSelectEntryPos(); }
    using ListBox::RemoveEntry;
    void            RemoveEntry( sal_Int32  nPos );
    void            Clear();
    void            CopyEntries( const ColorLB& rBox );

    using ListBox::GetEntryPos;
    sal_Int32       GetEntryPos( const Color& rColor ) const;
    Color           GetEntryColor( sal_Int32  nPos ) const;

    void            SelectEntry( const OUString& rStr )
                        { ListBox::SelectEntry( rStr ); }

    void SelectEntry( const Color& rColor )
    {
        sal_Int32  nPos = GetEntryPos( rColor );
        if ( nPos != LISTBOX_ENTRY_NOTFOUND )
            ListBox::SelectEntryPos( nPos );
    }

    Color GetSelectEntryColor() const
    {
        sal_Int32  nPos = GetSelectEntryPos();
        Color aColor;
        if ( nPos != LISTBOX_ENTRY_NOTFOUND )
            aColor = GetEntryColor( nPos );
        return aColor;
    }

    using ListBox::IsEntrySelected;

    bool            IsEntrySelected(const Color& rColor) const
    {
        sal_Int32  nPos = GetEntryPos( rColor );
        if ( nPos != LISTBOX_ENTRY_NOTFOUND )
            return IsEntryPosSelected( nPos );
        else
            return false;
    }

    void Fill( const XColorListRef &pTab );

    void Append( const XColorEntry& rEntry );
    void Modify( const XColorEntry& rEntry, sal_Int32 nPos );

private:
                    ColorLB( const ColorLB& ) = delete;
    ColorLB&   operator =( const ColorLB& ) = delete;
};

/************************************************************************/

class SAL_WARN_UNUSED SVX_DLLPUBLIC HatchingLB : public ListBox
{
public:
diff --git a/svx/source/dialog/dlgctrl.cxx b/svx/source/dialog/dlgctrl.cxx
index 3751903..d8f312bd 100644
--- a/svx/source/dialog/dlgctrl.cxx
+++ b/svx/source/dialog/dlgctrl.cxx
@@ -1103,259 +1103,6 @@ void SvxPixelCtl::Reset()
    Invalidate();
}

VCL_BUILDER_DECL_FACTORY(ColorLB)
{
    bool bDropdown = VclBuilder::extractDropdown(rMap);
    WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_SIMPLEMODE|WB_TABSTOP;
    if (bDropdown)
        nWinBits |= WB_DROPDOWN;
    OString sBorder = VclBuilder::extractCustomProperty(rMap);
    if (!sBorder.isEmpty())
        nWinBits |= WB_BORDER;
    VclPtrInstance<ColorLB> pListBox(pParent, nWinBits);
    pListBox->EnableAutoSize(true);
    rRet = pListBox;
}

class ImplColorListData
{
public:
    Color       aColor;
    bool        bColor;

                ImplColorListData() : aColor( COL_BLACK ) { bColor = false; }
                explicit ImplColorListData( const Color& rColor ) : aColor( rColor ) { bColor = true; }
};

void ColorLB::ImplInit()
{
    pColorList = new ImpColorList();

    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
    aImageSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize();
    EnableUserDraw( true );
    SetUserItemSize( aImageSize );
}

void ColorLB::ImplDestroyColorEntries()
{
    for ( size_t n = pColorList->size(); n; )
        delete (*pColorList)[ --n ];
    pColorList->clear();
}

ColorLB::ColorLB( vcl::Window* pParent, WinBits nWinStyle ) :
    ListBox( pParent, nWinStyle )
{
    ImplInit();
    SetEdgeBlending(true);
}

ColorLB::~ColorLB()
{
    disposeOnce();
}

void ColorLB::dispose()
{
    if ( pColorList )
    {
        ImplDestroyColorEntries();
        delete pColorList;
        pColorList = nullptr;
    }
    ListBox::dispose();
}

sal_Int32 ColorLB::InsertEntry( const OUString& rStr, sal_Int32 nPos )
{
    nPos = ListBox::InsertEntry( rStr, nPos );
    if ( nPos != LISTBOX_ERROR )
    {
        ImplColorListData* pData = new ImplColorListData;
        if ( static_cast<size_t>(nPos) < pColorList->size() )
        {
            ImpColorList::iterator it = pColorList->begin();
            ::std::advance( it, nPos );
            pColorList->insert( it, pData );
        }
        else
        {
            pColorList->push_back( pData );
            nPos = pColorList->size() - 1;
        }
    }
    return nPos;
}

sal_Int32 ColorLB::InsertEntry( const Color& rColor, const OUString& rStr,
                                sal_Int32 nPos )
{
    nPos = ListBox::InsertEntry( rStr, nPos );
    if ( nPos != LISTBOX_ERROR )
    {
        ImplColorListData* pData = new ImplColorListData( rColor );
        if ( static_cast<size_t>(nPos) < pColorList->size() )
        {
            ImpColorList::iterator it = pColorList->begin();
            ::std::advance( it, nPos );
            pColorList->insert( it, pData );
        }
        else
        {
            pColorList->push_back( pData );
            nPos = pColorList->size() - 1;
        }
    }
    return nPos;
}

void ColorLB::RemoveEntry( sal_Int32 nPos )
{
    ListBox::RemoveEntry( nPos );
    if ( 0 <= nPos && static_cast<size_t>(nPos) < pColorList->size() )
    {
            ImpColorList::iterator it = pColorList->begin();
            ::std::advance( it, nPos );
            delete *it;
            pColorList->erase( it );
    }
}

void ColorLB::Clear()
{
    ImplDestroyColorEntries();
    ListBox::Clear();
}

void ColorLB::CopyEntries( const ColorLB& rBox )
{
    // Liste leeren
    ImplDestroyColorEntries();

    // Daten kopieren
    size_t nCount = rBox.pColorList->size();
    for ( size_t n = 0; n < nCount; n++ )
    {
        ImplColorListData* pData = (*rBox.pColorList)[ n ];
        sal_Int32 nPos = InsertEntry( rBox.GetEntry( n ) );
        if ( nPos != LISTBOX_ERROR )
        {
            if ( static_cast<size_t>(nPos) < pColorList->size() )
            {
                ImpColorList::iterator it = pColorList->begin();
                ::std::advance( it, nPos );
                pColorList->insert( it, new ImplColorListData( *pData ) );
            }
            else
            {
                pColorList->push_back( new ImplColorListData( *pData ) );
            }
        }
    }
}

sal_Int32 ColorLB::GetEntryPos( const Color& rColor ) const
{
    for( sal_Int32 n = (sal_Int32) pColorList->size(); n; )
    {
        ImplColorListData* pData = (*pColorList)[ --n ];
        if ( pData->bColor && ( pData->aColor == rColor ) )
            return n;
    }
    return LISTBOX_ENTRY_NOTFOUND;
}

Color ColorLB::GetEntryColor( sal_Int32 nPos ) const
{
    Color aColor;
    ImplColorListData* pData = ( 0 <= nPos && static_cast<size_t>(nPos) < pColorList->size() ) ?
        (*pColorList)[ nPos ] : nullptr;
    if ( pData && pData->bColor )
        aColor = pData->aColor;
    return aColor;
}

void ColorLB::UserDraw( const UserDrawEvent& rUDEvt )
{
    size_t nPos = rUDEvt.GetItemId();
    ImplColorListData* pData = ( nPos < pColorList->size() ) ? (*pColorList)[ nPos ] : nullptr;
    if ( pData )
    {
        if ( pData->bColor )
        {
            Point aPos( rUDEvt.GetRect().TopLeft() );

            aPos.X() += 2;
            aPos.Y() += ( rUDEvt.GetRect().GetHeight() - aImageSize.Height() ) / 2;

            const Rectangle aRect(aPos, aImageSize);

            vcl::RenderContext* pRenderContext = rUDEvt.GetRenderContext();
            pRenderContext->Push();
            pRenderContext->SetFillColor(pData->aColor);
            pRenderContext->SetLineColor(pRenderContext->GetTextColor());
            pRenderContext->DrawRect(aRect);
            pRenderContext->Pop();

            const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
            const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);

            if(nEdgeBlendingPercent)
            {
                const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
                const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
                const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
                const BitmapEx aBlendFrame(createBlendFrame(aRect.GetSize(), nAlpha, rTopLeft, rBottomRight));

                if(!aBlendFrame.IsEmpty())
                {
                    pRenderContext->DrawBitmapEx(aRect.TopLeft(), aBlendFrame);
                }
            }

            ListBox::DrawEntry( rUDEvt, false, false );
        }
        else
            ListBox::DrawEntry( rUDEvt, false, true );
    }
    else
        ListBox::DrawEntry( rUDEvt, true, false );
}


// Fills the Listbox with color and strings

void ColorLB::Fill( const XColorListRef &pColorTab )
{
    if( !pColorTab.is() )
        return;

    long nCount = pColorTab->Count();
    SetUpdateMode( false );

    for( long i = 0; i < nCount; i++ )
    {
        const XColorEntry* pEntry = pColorTab->GetColor(i);
        InsertEntry( pEntry->GetColor(), pEntry->GetName() );
    }

    AdaptDropDownLineCountToMaximum();
    SetUpdateMode( true );
}

void ColorLB::Append( const XColorEntry& rEntry )
{
    InsertEntry( rEntry.GetColor(), rEntry.GetName() );
    AdaptDropDownLineCountToMaximum();
}

void ColorLB::Modify( const XColorEntry& rEntry, sal_Int32 nPos )
{
    RemoveEntry( nPos );
    InsertEntry( rEntry.GetColor(), rEntry.GetName(), nPos );
}

// Fills the listbox (provisional) with strings

HatchingLB::HatchingLB( vcl::Window* pParent, WinBits nWinStyle)