dbaccess/UIConfig_dbaccess.mk                 |    1 
 dbaccess/source/ui/app/AppIconControl.cxx     |  174 ++++++++++++++++++++------
 dbaccess/source/ui/app/AppIconControl.hxx     |   42 ++++--
 dbaccess/source/ui/app/AppSwapWindow.cxx      |   89 +++++--------
 dbaccess/source/ui/app/AppSwapWindow.hxx      |   20 +-
 dbaccess/source/ui/app/AppView.cxx            |    4 
 dbaccess/source/ui/inc/TableWindowListBox.hxx |    2 
 dbaccess/uiconfig/ui/appswapwindow.ui         |   59 ++++++++
 include/sfx2/thumbnailview.hxx                |   13 +
 sfx2/source/control/thumbnailview.cxx         |   17 ++
 sfx2/source/control/thumbnailviewitem.cxx     |   37 ++++-
 11 files changed, 334 insertions(+), 124 deletions(-)

New commits:
commit fd2ea8e03510c6a99ec8be6228b7422f6c5b182b
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Wed Aug 19 14:59:33 2020 +0100
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Wed Aug 26 17:14:31 2020 +0200

    weld OApplicationSwapWindow
    
    Change-Id: I71d24494b5fe7dd2949876944ab9aff41330ad50
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/101027
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/dbaccess/UIConfig_dbaccess.mk b/dbaccess/UIConfig_dbaccess.mk
index 40a06cd388a0..91dc44de9606 100644
--- a/dbaccess/UIConfig_dbaccess.mk
+++ b/dbaccess/UIConfig_dbaccess.mk
@@ -13,6 +13,7 @@ $(eval $(call gb_UIConfig_add_uifiles,dbaccess, \
     dbaccess/uiconfig/ui/admindialog \
     dbaccess/uiconfig/ui/advancedsettingsdialog \
     dbaccess/uiconfig/ui/applycolpage \
+    dbaccess/uiconfig/ui/appswapwindow \
     dbaccess/uiconfig/ui/authentificationpage \
     dbaccess/uiconfig/ui/autocharsetpage \
     dbaccess/uiconfig/ui/choosedatasourcedialog \
diff --git a/dbaccess/source/ui/app/AppIconControl.cxx 
b/dbaccess/source/ui/app/AppIconControl.cxx
index 514580014f79..84edc6a27f15 100644
--- a/dbaccess/source/ui/app/AppIconControl.cxx
+++ b/dbaccess/source/ui/app/AppIconControl.cxx
@@ -21,18 +21,53 @@
 #include <core_resource.hxx>
 #include <strings.hrc>
 #include <bitmaps.hlst>
-#include <vcl/image.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/event.hxx>
+#include <vcl/i18nhelp.hxx>
+#include <vcl/mnemonic.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
 #include <callbacks.hxx>
 #include <AppElementType.hxx>
 
-using namespace ::dbaui;
-OApplicationIconControl::OApplicationIconControl(vcl::Window* _pParent)
-    : SvtIconChoiceCtrl(_pParent,WB_ICON | WB_NOCOLUMNHEADER | 
WB_HIGHLIGHTFRAME | /*!WB_NOSELECTION |*/
-                                WB_TABSTOP | WB_CLIPCHILDREN | WB_NOVSCROLL | 
WB_SMART_ARRANGE | WB_NOHSCROLL | WB_CENTER)
-    ,DropTargetHelper(this)
-    ,m_pActionListener(nullptr)
+namespace dbaui
 {
 
+class OApplicationIconControlDropTarget final : public DropTargetHelper
+{
+private:
+    OApplicationIconControl& m_rControl;
+
+public:
+    OApplicationIconControlDropTarget(OApplicationIconControl& rControl)
+        : DropTargetHelper(rControl.GetDrawingArea()->get_drop_target())
+        , m_rControl(rControl)
+    {
+    }
+
+    virtual sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt) override
+    {
+        return m_rControl.AcceptDrop(rEvt);
+    }
+
+    virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt) override
+    {
+        return m_rControl.ExecuteDrop(rEvt);
+    }
+};
+
+OApplicationIconControl::OApplicationIconControl(std::unique_ptr<weld::ScrolledWindow>
 xScroll)
+    : SfxThumbnailView(std::move(xScroll), nullptr)
+    , m_pActionListener(nullptr)
+    , m_nMaxWidth(0)
+    , m_nMaxHeight(0)
+{
+    mnVItemSpace = 6; // row spacing
+    DrawMnemonics(true);
+}
+
+void OApplicationIconControl::Fill()
+{
     static const struct CategoryDescriptor
     {
         const char* pLabelResId;
@@ -44,63 +79,128 @@ 
OApplicationIconControl::OApplicationIconControl(vcl::Window* _pParent)
         { RID_STR_FORMS_CONTAINER,      E_FORM,     BMP_FORMFOLDER_TREE_L   },
         { RID_STR_REPORTS_CONTAINER,    E_REPORT,   BMP_REPORTFOLDER_TREE_L }
     };
+
     for (const CategoryDescriptor& aCategorie : aCategories)
     {
-        SvxIconChoiceCtrlEntry* pEntry = InsertEntry(
-            DBA_RES(aCategorie.pLabelResId) ,
-            Image(StockImage::Yes, 
OUString::createFromAscii(aCategorie.aImageResId)));
-        if ( pEntry )
-            pEntry->SetUserData( new ElementType( aCategorie.eType ) );
+        // E_TABLE is 0, but 0 means void so use id of enum + 1
+        std::unique_ptr<ThumbnailViewItem> xItem(new ThumbnailViewItem(*this, 
aCategorie.eType + 1));
+        xItem->mbBorder = false;
+        xItem->maPreview1 = 
BitmapEx(OUString::createFromAscii(aCategorie.aImageResId));
+        const Size& rSize = xItem->maPreview1.GetSizePixel();
+        m_nMaxWidth = std::max(m_nMaxWidth, rSize.Width());
+        m_nMaxHeight = std::max(m_nMaxHeight, rSize.Height());
+        xItem->maTitle = DBA_RES(aCategorie.pLabelResId);
+        m_nMaxWidth = std::max<long>(m_nMaxWidth, 
GetTextWidth(xItem->maTitle));
+        AppendItem(std::move(xItem));
     }
 
-    SetChoiceWithCursor();
-    SetSelectionMode(SelectionMode::Single);
+    const int nMargin = 12;
+    const int nWidthRequest = m_nMaxWidth + 2 * nMargin;
+    set_size_request(nWidthRequest, -1);
+    // we expect a Resize at which point we'll set the item sizes based on our 
final size
 }
 
-OApplicationIconControl::~OApplicationIconControl()
+ElementType OApplicationIconControl::GetSelectedItem() const
+{
+    for (const auto& rItem : mItemList)
+    {
+        if (!rItem->mbSelected)
+            continue;
+        return static_cast<ElementType>(rItem->mnId - 1);
+    }
+    return E_NONE;
+}
+
+void OApplicationIconControl::createIconAutoMnemonics(MnemonicGenerator& 
rMnemonics)
 {
-    disposeOnce();
+    for (const auto& rItem : mItemList)
+        rMnemonics.RegisterMnemonic(rItem->maTitle);
+
+    // exchange texts with generated mnemonics
+    for (auto& rItem : mItemList)
+        rItem->maTitle = rMnemonics.CreateMnemonic(rItem->maTitle);
 }
 
-void OApplicationIconControl::dispose()
+void OApplicationIconControl::Resize()
 {
-    sal_Int32 nCount = GetEntryCount();
-    for ( sal_Int32 i = 0; i < nCount; ++i )
+    // fill the full width of the allocated area and give two lines of space to
+    // center the title in
+    setItemDimensions(GetOutputSizePixel().Width(), m_nMaxHeight, 
GetTextHeight() * 2, 0);
+    SfxThumbnailView::Resize();
+}
+
+bool OApplicationIconControl::IsMnemonicChar(sal_Unicode cChar, ElementType& 
rType) const
+{
+    bool bRet = false;
+
+    const vcl::I18nHelper& rI18nHelper = 
Application::GetSettings().GetUILocaleI18nHelper();
+    for (const auto& rItem : mItemList)
     {
-        SvxIconChoiceCtrlEntry* pEntry = GetEntry( i );
-        if ( pEntry )
+        if (rI18nHelper.MatchMnemonic(rItem->maTitle, cChar))
         {
-            delete static_cast<ElementType*>(pEntry->GetUserData());
-            pEntry->SetUserData(nullptr);
+            bRet = true;
+            rType = static_cast<ElementType>(rItem->mnId - 1);
+            break;
         }
     }
-    DropTargetHelper::dispose();
-    SvtIconChoiceCtrl::dispose();
+
+    return bRet;
 }
 
-sal_Int8 OApplicationIconControl::AcceptDrop( const AcceptDropEvent& _rEvt )
+bool OApplicationIconControl::DoKeyShortCut(const KeyEvent& rKEvt)
 {
-    sal_Int8 nDropOption = DND_ACTION_NONE;
-    if ( m_pActionListener )
+    bool bMod2 = rKEvt.GetKeyCode().IsMod2();
+    sal_Unicode cChar = rKEvt.GetCharCode();
+    ElementType eType(E_NONE);
+    if (bMod2 && cChar && IsMnemonicChar(cChar, eType))
     {
+        // shortcut is clicked
+        deselectItems();
+        SelectItem(eType + 1);
+        return true;
+    }
+
+    return false;
+}
+
+bool OApplicationIconControl::KeyInput(const KeyEvent& rKEvt)
+{
+    return DoKeyShortCut(rKEvt) || SfxThumbnailView::KeyInput(rKEvt);
+}
+
+void OApplicationIconControl::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+    SfxThumbnailView::SetDrawingArea(pDrawingArea);
+    m_xDropTarget.reset(new OApplicationIconControlDropTarget(*this));
+}
 
-        SvxIconChoiceCtrlEntry* pEntry = GetEntry(_rEvt.maPosPixel);
-        if ( pEntry )
+sal_Int8 OApplicationIconControl::AcceptDrop(const AcceptDropEvent& rEvt)
+{
+    sal_Int8 nDropOption = DND_ACTION_NONE;
+    if (m_pActionListener)
+    {
+        sal_uInt16 nEntry = GetItemId(rEvt.maPosPixel);
+        if (nEntry)
         {
-            SetCursor(pEntry);
-            nDropOption = m_pActionListener->queryDrop( _rEvt, 
GetDataFlavorExVector() );
+            deselectItems();
+            SelectItem(nEntry);
+            nDropOption = m_pActionListener->queryDrop(rEvt, 
m_xDropTarget->GetDataFlavorExVector());
         }
     }
-
     return nDropOption;
 }
 
-sal_Int8 OApplicationIconControl::ExecuteDrop( const ExecuteDropEvent& _rEvt )
+sal_Int8 OApplicationIconControl::ExecuteDrop(const ExecuteDropEvent& rEvt)
 {
-    if ( m_pActionListener )
-        return m_pActionListener->executeDrop( _rEvt );
-
+    if (m_pActionListener)
+        m_pActionListener->executeDrop(rEvt);
     return DND_ACTION_NONE;
 }
 
+OApplicationIconControl::~OApplicationIconControl()
+{
+}
+
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppIconControl.hxx 
b/dbaccess/source/ui/app/AppIconControl.hxx
index 38408af60687..7b29018c377b 100644
--- a/dbaccess/source/ui/app/AppIconControl.hxx
+++ b/dbaccess/source/ui/app/AppIconControl.hxx
@@ -19,28 +19,48 @@
 #ifndef INCLUDED_DBACCESS_SOURCE_UI_APP_APPICONCONTROL_HXX
 #define INCLUDED_DBACCESS_SOURCE_UI_APP_APPICONCONTROL_HXX
 
-#include <vcl/ivctrl.hxx>
+#include <sfx2/thumbnailview.hxx>
+#include <sfx2/thumbnailviewitem.hxx>
 #include <vcl/transfer.hxx>
+#include <vcl/customweld.hxx>
+#include <vcl/weld.hxx>
+#include <AppElementType.hxx>
+
+class MnemonicGenerator;
 
 namespace dbaui
 {
     class IControlActionListener;
-    class OApplicationIconControl   :public SvtIconChoiceCtrl
-                                    ,public DropTargetHelper
+    class IconControl;
+    class OApplicationIconControlDropTarget;
+
+    class OApplicationIconControl final : public SfxThumbnailView
     {
-        IControlActionListener*     m_pActionListener;
+        std::unique_ptr<OApplicationIconControlDropTarget> m_xDropTarget;
+        IControlActionListener* m_pActionListener;
+
+        long m_nMaxWidth;
+        long m_nMaxHeight;
+
+        bool IsMnemonicChar(sal_Unicode cChar, ElementType& rType) const;
 
     public:
-        explicit OApplicationIconControl(vcl::Window* _pParent);
+        explicit OApplicationIconControl(std::unique_ptr<weld::ScrolledWindow> 
xScroll);
+        virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+        virtual void Resize() override;
+        bool DoKeyShortCut(const KeyEvent& rKEvt);
+        virtual bool KeyInput(const KeyEvent& rKEvt) override;
         virtual ~OApplicationIconControl() override;
-        virtual void dispose() override;
 
-        void                    setControlActionListener( 
IControlActionListener* _pListener ) { m_pActionListener = _pListener; }
+        ElementType GetSelectedItem() const;
+
+        void setControlActionListener( IControlActionListener* _pListener ) { 
m_pActionListener = _pListener; }
+        void Fill();
+
+        void createIconAutoMnemonics(MnemonicGenerator& rMnemonics);
 
-    protected:
-        // DropTargetHelper overridables
-        virtual sal_Int8    AcceptDrop( const AcceptDropEvent& _rEvt ) 
override;
-        virtual sal_Int8    ExecuteDrop( const ExecuteDropEvent& _rEvt ) 
override;
+        sal_Int8 AcceptDrop(const AcceptDropEvent& rEvt);
+        sal_Int8 ExecuteDrop(const ExecuteDropEvent& rEvt);
     };
 }
 #endif // INCLUDED_DBACCESS_SOURCE_UI_APP_APPICONCONTROL_HXX
diff --git a/dbaccess/source/ui/app/AppSwapWindow.cxx 
b/dbaccess/source/ui/app/AppSwapWindow.cxx
index e291bdb8a6ac..9ab50e8a0b4c 100644
--- a/dbaccess/source/ui/app/AppSwapWindow.cxx
+++ b/dbaccess/source/ui/app/AppSwapWindow.cxx
@@ -31,18 +31,28 @@ using namespace ::com::sun::star::sdbc;
 using namespace ::com::sun::star::lang;
 using namespace ::com::sun::star::container;
 
-OApplicationSwapWindow::OApplicationSwapWindow( vcl::Window* _pParent, 
OAppBorderWindow& _rBorderWindow )
-    :Window(_pParent,WB_DIALOGCONTROL )
-    ,m_aIconControl(VclPtr<OApplicationIconControl>::Create(this))
-    ,m_eLastType(E_NONE)
-    ,m_rBorderWin( _rBorderWindow )
+OApplicationSwapWindow::OApplicationSwapWindow(vcl::Window* pParent, 
OAppBorderWindow& rBorderWindow)
+    : InterimItemWindow(pParent, "dbaccess/ui/appswapwindow.ui", 
"AppSwapWindow")
+    , m_xIconControl(new 
OApplicationIconControl(m_xBuilder->weld_scrolled_window("scroll")))
+    , m_xIconControlWin(new weld::CustomWeld(*m_xBuilder, "valueset", 
*m_xIconControl))
+    , m_eLastType(E_NONE)
+    , m_rBorderWin(rBorderWindow)
 {
+    m_xContainer->set_stack_background();
+
     ImplInitSettings();
 
-    m_aIconControl->SetClickHdl(LINK(this, OApplicationSwapWindow, 
OnContainerSelectHdl));
-    m_aIconControl->setControlActionListener( 
&m_rBorderWin.getView()->getAppController() );
-    m_aIconControl->SetHelpId(HID_APP_SWAP_ICONCONTROL);
-    m_aIconControl->Show();
+    m_xIconControl->SetHelpId(HID_APP_SWAP_ICONCONTROL);
+    m_xIconControl->Fill();
+    m_xIconControl->setItemStateHdl(LINK(this, OApplicationSwapWindow, 
OnContainerSelectHdl));
+    m_xIconControl->setControlActionListener( 
&m_rBorderWin.getView()->getAppController() );
+}
+
+void OApplicationSwapWindow::GetFocus()
+{
+    if (m_xIconControl)
+        m_xIconControl->GrabFocus();
+    InterimItemWindow::GetFocus();
 }
 
 OApplicationSwapWindow::~OApplicationSwapWindow()
@@ -52,21 +62,9 @@ OApplicationSwapWindow::~OApplicationSwapWindow()
 
 void OApplicationSwapWindow::dispose()
 {
-    m_aIconControl.disposeAndClear();
-    vcl::Window::dispose();
-}
-
-void OApplicationSwapWindow::Resize()
-{
-    Size aFLSize = LogicToPixel(Size(8, 0), MapMode(MapUnit::MapAppFont));
-    long nX = 0;
-    if ( m_aIconControl->GetEntryCount() != 0 )
-        nX = m_aIconControl->GetBoundingBox( m_aIconControl->GetEntry(0) 
).GetWidth() + aFLSize.Width();
-
-    Size aOutputSize = GetOutputSize();
-
-    m_aIconControl->SetPosSizePixel( 
Point(static_cast<long>((aOutputSize.Width() - nX)*0.5), 0)  
,Size(nX,aOutputSize.Height()));
-    m_aIconControl->ArrangeIcons();
+    m_xIconControlWin.reset();
+    m_xIconControl.reset();
+    InterimItemWindow::dispose();
 }
 
 void OApplicationSwapWindow::ImplInitSettings()
@@ -99,32 +97,27 @@ void OApplicationSwapWindow::DataChanged( const 
DataChangedEvent& rDCEvt )
 
 void OApplicationSwapWindow::clearSelection()
 {
-    m_aIconControl->SetNoSelection();
-    SvxIconChoiceCtrlEntry* pEntry = m_aIconControl->GetSelectedEntry();
-    if ( pEntry )
-        m_aIconControl->InvalidateEntry(pEntry);
-    m_aIconControl->GetClickHdl().Call(m_aIconControl.get());
+    m_xIconControl->deselectItems();
+    onContainerSelected(E_NONE);
 }
 
-void OApplicationSwapWindow::createIconAutoMnemonics( MnemonicGenerator& 
_rMnemonics )
+void OApplicationSwapWindow::createIconAutoMnemonics(MnemonicGenerator& 
rMnemonics)
 {
-    m_aIconControl->CreateAutoMnemonics( _rMnemonics );
+    m_xIconControl->createIconAutoMnemonics(rMnemonics);
 }
 
 bool OApplicationSwapWindow::interceptKeyInput( const KeyEvent& _rEvent )
 {
     const vcl::KeyCode& rKeyCode = _rEvent.GetKeyCode();
     if ( rKeyCode.GetModifier() == KEY_MOD2 )
-        return m_aIconControl->DoKeyInput( _rEvent );
-
+        return m_xIconControl->DoKeyShortCut( _rEvent );
     // not handled
     return false;
 }
 
 ElementType OApplicationSwapWindow::getElementType() const
 {
-    SvxIconChoiceCtrlEntry* pEntry = m_aIconControl->GetSelectedEntry();
-    return pEntry ? *static_cast<ElementType*>(pEntry->GetUserData()) : E_NONE;
+    return m_xIconControl->GetSelectedItem();
 }
 
 bool OApplicationSwapWindow::onContainerSelected( ElementType _eType )
@@ -143,13 +136,11 @@ bool OApplicationSwapWindow::onContainerSelected( 
ElementType _eType )
     return false;
 }
 
-IMPL_LINK(OApplicationSwapWindow, OnContainerSelectHdl, SvtIconChoiceCtrl*, 
_pControl, void)
+IMPL_LINK(OApplicationSwapWindow, OnContainerSelectHdl, const 
ThumbnailViewItem*, pEntry, void)
 {
-    SvxIconChoiceCtrlEntry* pEntry = _pControl->GetSelectedEntry();
-    ElementType eType = E_NONE;
-    if ( pEntry )
+    if (pEntry->mbSelected)
     {
-        eType = *static_cast<ElementType*>(pEntry->GetUserData());
+        ElementType eType = static_cast<ElementType>(pEntry->mnId - 1);
         onContainerSelected( eType ); // i87582
     }
 }
@@ -159,22 +150,10 @@ IMPL_LINK_NOARG(OApplicationSwapWindow, 
ChangeToLastSelected, void*, void)
     selectContainer(m_eLastType);
 }
 
-void OApplicationSwapWindow::selectContainer(ElementType _eType)
+void OApplicationSwapWindow::selectContainer(ElementType eType)
 {
-    sal_Int32 nCount = m_aIconControl->GetEntryCount();
-    SvxIconChoiceCtrlEntry* pEntry = nullptr;
-    for (sal_Int32 i=0; i < nCount; ++i)
-    {
-        pEntry = m_aIconControl->GetEntry(i);
-        if ( pEntry && *static_cast<ElementType*>(pEntry->GetUserData()) == 
_eType )
-            break;
-        pEntry = nullptr;
-    }
-
-    if ( pEntry )
-        m_aIconControl->SetCursor(pEntry); // this call also initiates a 
onContainerSelected call
-    else
-        onContainerSelected( _eType );
+    m_xIconControl->deselectItems();
+    m_xIconControl->SelectItem(eType + 1); // will trigger onContainerSelected
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/app/AppSwapWindow.hxx 
b/dbaccess/source/ui/app/AppSwapWindow.hxx
index 62f58c15248d..b63d563e496b 100644
--- a/dbaccess/source/ui/app/AppSwapWindow.hxx
+++ b/dbaccess/source/ui/app/AppSwapWindow.hxx
@@ -20,32 +20,36 @@
 #define INCLUDED_DBACCESS_SOURCE_UI_APP_APPSWAPWINDOW_HXX
 
 #include <IClipBoardTest.hxx>
+#include <vcl/InterimItemWindow.hxx>
 #include <vcl/vclptr.hxx>
 #include "AppIconControl.hxx"
 #include <AppElementType.hxx>
 
+class MnemonicGenerator;
+
 namespace dbaui
 {
     class OAppBorderWindow;
-    class OApplicationSwapWindow :  public vcl::Window,
-                                    public IClipboardTest
+    class OApplicationSwapWindow : public InterimItemWindow
+                                 , public IClipboardTest
     {
-        VclPtr<OApplicationIconControl>     m_aIconControl;
+        std::unique_ptr<OApplicationIconControl> m_xIconControl;
+        std::unique_ptr<weld::CustomWeld>   m_xIconControlWin;
         ElementType                         m_eLastType;
         OAppBorderWindow&                   m_rBorderWin;
 
         void ImplInitSettings();
 
-        DECL_LINK( OnContainerSelectHdl, SvtIconChoiceCtrl*, void );
+        DECL_LINK( OnContainerSelectHdl, const ThumbnailViewItem*, void );
         DECL_LINK( ChangeToLastSelected, void*, void );
     protected:
         virtual void DataChanged(const DataChangedEvent& rDCEvt) override;
     public:
-        OApplicationSwapWindow( vcl::Window* _pParent, OAppBorderWindow& 
_rBorderWindow );
+        OApplicationSwapWindow(vcl::Window* pParent, OAppBorderWindow& 
rBorderWindow);
         virtual ~OApplicationSwapWindow() override;
         // Window overrides
         virtual void dispose() override;
-        virtual void Resize() override;
+        virtual void GetFocus() override;
 
         bool isCutAllowed() override      { return false; }
         bool isCopyAllowed() override     { return false; }
@@ -54,10 +58,6 @@ namespace dbaui
         void cut() override   { }
         void paste() override { }
 
-        sal_Int32                GetEntryCount() const { return 
m_aIconControl->GetEntryCount(); }
-        SvxIconChoiceCtrlEntry*  GetEntry( sal_uLong nPos ) const { return 
m_aIconControl->GetEntry(nPos); }
-        tools::Rectangle                GetBoundingBox( 
SvxIconChoiceCtrlEntry* pEntry ) const { return 
m_aIconControl->GetBoundingBox(pEntry); }
-
         /** automatically creates mnemonics for the icon/texts in our left 
hand side panel
         */
         void    createIconAutoMnemonics( MnemonicGenerator& _rMnemonics );
diff --git a/dbaccess/source/ui/app/AppView.cxx 
b/dbaccess/source/ui/app/AppView.cxx
index b92917c4615b..c6770a1eafd9 100644
--- a/dbaccess/source/ui/app/AppView.cxx
+++ b/dbaccess/source/ui/app/AppView.cxx
@@ -100,8 +100,8 @@ void OAppBorderWindow::Resize()
     if ( m_pPanel )
     {
         OApplicationSwapWindow* pSwap = getPanel();
-        if ( pSwap && pSwap->GetEntryCount() != 0 )
-            nX = pSwap->GetBoundingBox( pSwap->GetEntry(0) ).GetWidth() + 
aFLSize.Height();
+        if (pSwap)
+            nX = pSwap->get_preferred_size().Width();
         nX = std::max(m_pPanel->GetWidthPixel() ,nX);
         m_pPanel->SetPosSizePixel(Point(0,0),Size(nX,nOutputHeight));
     }
diff --git a/dbaccess/source/ui/inc/TableWindowListBox.hxx 
b/dbaccess/source/ui/inc/TableWindowListBox.hxx
index 5ca01098266b..6d4ded28f97f 100644
--- a/dbaccess/source/ui/inc/TableWindowListBox.hxx
+++ b/dbaccess/source/ui/inc/TableWindowListBox.hxx
@@ -93,7 +93,7 @@ namespace dbaui
         int GetEntryFromText( const OUString& rEntryText );
     };
 
-    class TableWindowListBoxHelper : public DropTargetHelper
+    class TableWindowListBoxHelper final : public DropTargetHelper
     {
     private:
         OTableWindowListBox& m_rParent;
diff --git a/dbaccess/uiconfig/ui/appswapwindow.ui 
b/dbaccess/uiconfig/ui/appswapwindow.ui
new file mode 100644
index 000000000000..d2dfc1b397c3
--- /dev/null
+++ b/dbaccess/uiconfig/ui/appswapwindow.ui
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="dba">
+  <requires lib="gtk+" version="3.18"/>
+  <object class="GtkBox" id="AppSwapWindow">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="hexpand">True</property>
+    <property name="vexpand">True</property>
+    <property name="orientation">vertical</property>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="border_width">12</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkScrolledWindow" id="scroll">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="hscrollbar_policy">never</property>
+            <property name="vscrollbar_policy">never</property>
+            <child>
+              <object class="GtkViewport">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <child>
+                  <object class="GtkDrawingArea" id="valueset">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="events">GDK_BUTTON_MOTION_MASK | 
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+                    <property name="hexpand">True</property>
+                    <property name="vexpand">True</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/include/sfx2/thumbnailview.hxx b/include/sfx2/thumbnailview.hxx
index f2e90f94ac59..45f4a6753286 100644
--- a/include/sfx2/thumbnailview.hxx
+++ b/include/sfx2/thumbnailview.hxx
@@ -176,6 +176,8 @@ public:
 
     virtual bool renameItem(ThumbnailViewItem* pItem, const OUString& 
sNewTitle);
 
+    virtual bool isDrawMnemonic() const = 0;
+
     virtual ~ThumbnailViewBase();
 };
 
@@ -205,6 +207,8 @@ public:
 
     sal_uInt16 getNextItemId () const;
 
+    virtual bool isDrawMnemonic() const override { return false; }
+
     void setItemMaxTextLength (sal_uInt32 nLength);
 
     void setItemDimensions (long ItemWidth, long ThumbnailHeight,
@@ -340,6 +344,8 @@ public:
 
     sal_uInt16 getNextItemId () const;
 
+    virtual bool isDrawMnemonic() const override { return mbDrawMnemonics; }
+
     void setItemMaxTextLength (sal_uInt32 nLength);
 
     void setItemDimensions (long ItemWidth, long ThumbnailHeight,
@@ -359,6 +365,8 @@ public:
 
     void ShowTooltips( bool bShowTooltips );
 
+    void DrawMnemonics( bool bDrawMnemonics );
+
     void SetMultiSelectionEnabled( bool bIsMultiSelectionEnabled );
 
     void filterItems (const std::function<bool (const ThumbnailViewItem*) > 
&func);
@@ -437,14 +445,17 @@ protected:
     long mnItemPadding;
     long mnThumbnailHeight;     // Maximum height of the thumbnail
     long mnDisplayHeight;       // Height of the data display box (name, etc)
+    long mnVItemSpace;          // Vertical spacing between rows, -1 to use 
excess unused height split up between items
     long mnVisLines;
     long mnLines;
 
     sal_uInt16 mnCols;
     sal_uInt16 mnFirstLine;
-    bool mbScroll : 1;
+    bool mbScroll : 1;          // Whether we need to scroll
+    bool mbAllowVScrollBar : 1; // Whether to show a visible scrollbar
     bool mbHasVisibleItems : 1;
     bool mbShowTooltips : 1;
+    bool mbDrawMnemonics : 1;
     bool mbIsMultiSelectionEnabled: 1;
     Color maFillColor;              ///< Background color of the thumbnail 
view widget.
     Color maTextColor;              ///< Text color.
diff --git a/sfx2/source/control/thumbnailview.cxx 
b/sfx2/source/control/thumbnailview.cxx
index a607493119a4..f0f31700fb39 100644
--- a/sfx2/source/control/thumbnailview.cxx
+++ b/sfx2/source/control/thumbnailview.cxx
@@ -1221,6 +1221,8 @@ BitmapEx ThumbnailView::readThumbnail(const OUString 
&msURL)
 SfxThumbnailView::SfxThumbnailView(std::unique_ptr<weld::ScrolledWindow> 
xWindow, std::unique_ptr<weld::Menu> xMenu)
     : mnThumbnailHeight(0)
     , mnDisplayHeight(0)
+    , mnVItemSpace(-1)
+    , mbAllowVScrollBar(xWindow->get_vpolicy() != VclPolicyType::NEVER)
     , mpItemAttrs(new ThumbnailItemAttributes)
     , mxScrolledWindow(std::move(xWindow))
     , mxContextMenu(std::move(xMenu))
@@ -1314,6 +1316,7 @@ void SfxThumbnailView::ImplInit()
     mbScroll = false;
     mbHasVisibleItems = false;
     mbShowTooltips = false;
+    mbDrawMnemonics = false;
     mbIsMultiSelectionEnabled = true;
     maFilterFunc = ViewFilterAll();
 
@@ -1418,7 +1421,7 @@ void SfxThumbnailView::CalculateItemPositions(bool 
bScrollBarUsed)
         nScrollRatio = 0;
 
     // calculate ScrollBar width
-    long nScrBarWidth = mxScrolledWindow->get_vscroll_width();
+    long nScrBarWidth = mbAllowVScrollBar ? 
mxScrolledWindow->get_vscroll_width() : 0;
 
     // calculate maximum number of visible columns
     mnCols = static_cast<sal_uInt16>((aWinSize.Width()-nScrBarWidth) / 
mnItemWidth);
@@ -1433,7 +1436,9 @@ void SfxThumbnailView::CalculateItemPositions(bool 
bScrollBarUsed)
     long nHSpace = aWinSize.Width()-nScrBarWidth - mnCols*mnItemWidth;
     long nVSpace = aWinSize.Height() - mnVisLines*mnItemHeight;
     long nHItemSpace = nHSpace / (mnCols+1);
-    long nVItemSpace = nVSpace / (mnVisLines+1);
+    long nVItemSpace = mnVItemSpace;
+    if (nVItemSpace == -1) // auto, split up extra space to use as vertical 
spacing
+        nVItemSpace = nVSpace / (mnVisLines+1);
 
     // calculate maximum number of rows
     // Floor( (M+N-1)/N )==Ceiling( M/N )
@@ -1545,7 +1550,8 @@ void SfxThumbnailView::CalculateItemPositions(bool 
bScrollBarUsed)
     if ( nPageSize < 1 )
         nPageSize = 1;
     mxScrolledWindow->vadjustment_set_page_increment(nPageSize);
-    mxScrolledWindow->set_vpolicy(mbScroll ? VclPolicyType::ALWAYS : 
VclPolicyType::NEVER);
+    if (mbAllowVScrollBar)
+        mxScrolledWindow->set_vpolicy(mbScroll ? VclPolicyType::ALWAYS : 
VclPolicyType::NEVER);
 }
 
 size_t SfxThumbnailView::ImplGetItem( const Point& rPos ) const
@@ -2237,6 +2243,11 @@ void SfxThumbnailView::ShowTooltips( bool bShowTooltips )
     mbShowTooltips = bShowTooltips;
 }
 
+void SfxThumbnailView::DrawMnemonics( bool bDrawMnemonics )
+{
+    mbDrawMnemonics = bDrawMnemonics;
+}
+
 void SfxThumbnailView::SetMultiSelectionEnabled( bool bIsMultiSelectionEnabled 
)
 {
     mbIsMultiSelectionEnabled = bIsMultiSelectionEnabled;
diff --git a/sfx2/source/control/thumbnailviewitem.cxx 
b/sfx2/source/control/thumbnailviewitem.cxx
index 474f415e73cb..b3a6e7d4af97 100644
--- a/sfx2/source/control/thumbnailviewitem.cxx
+++ b/sfx2/source/control/thumbnailviewitem.cxx
@@ -27,6 +27,7 @@
 #include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
 #include <drawinglayer/primitive2d/PolyPolygonSelectionPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
@@ -213,27 +214,30 @@ void ThumbnailViewItem::addTextPrimitives (const 
OUString& rText, const Thumbnai
 
     aPos.setY(aPos.getY() + aTextDev.getTextHeight());
 
-    OUString aText (rText);
+    sal_Int32 nMnemonicPos = -1;
+    OUString aOrigText(mrParent.isDrawMnemonic() ? 
OutputDevice::GetNonMnemonicString(rText, nMnemonicPos) : rText);
 
     TextEngine aTextEngine;
     aTextEngine.SetFont(getVclFontFromFontAttribute(pAttrs->aFontAttr,
                               pAttrs->aFontSize.getX(), 
pAttrs->aFontSize.getY(), 0,
                               css::lang::Locale()));
     aTextEngine.SetMaxTextWidth(maDrawArea.getWidth());
-    aTextEngine.SetText(rText);
+    aTextEngine.SetText(aOrigText);
 
     sal_Int32 nPrimitives = rSeq.size();
-    rSeq.resize(nPrimitives + aTextEngine.GetLineCount(0));
+    sal_Int32 nFinalPrimCount = nPrimitives + aTextEngine.GetLineCount(0);
+    rSeq.resize(nFinalPrimCount);
 
     // Create the text primitives
     sal_uInt16 nLineStart = 0;
+    OUString aText(aOrigText);
     for (sal_uInt16 i=0; i < aTextEngine.GetLineCount(0); ++i)
     {
         sal_Int32 nLineLength = aTextEngine.GetLineLen(0, i);
         double nLineWidth = aTextDev.getTextWidth (aText, nLineStart, 
nLineLength);
 
         bool bTooLong = (aPos.getY() + aTextEngine.GetCharHeight()) > 
maDrawArea.Bottom();
-        if (bTooLong && (nLineLength + nLineStart) < rText.getLength())
+        if (bTooLong && (nLineLength + nLineStart) < aOrigText.getLength())
         {
             // Add the '...' to the last line to show, even though it may 
require to shorten the line
             double nDotsWidth = aTextDev.getTextWidth("...",0,3);
@@ -271,6 +275,31 @@ void ThumbnailViewItem::addTextPrimitives (const OUString& 
rText, const Thumbnai
                                                      pAttrs->aFontAttr,
                                                      css::lang::Locale(),
                                                      aTextColor));
+
+        if (nMnemonicPos != -1 && nMnemonicPos >= nLineStart && nMnemonicPos < 
nLineStart + nLineLength)
+        {
+            rSeq.resize(nFinalPrimCount + 1);
+
+            auto aCaretPositions = aTextDev.getCaretPositions(aText, 
nLineStart, nLineLength);
+
+            auto lc_x1 = aCaretPositions[2*(nMnemonicPos - nLineStart)];
+            auto lc_x2 = aCaretPositions[2*(nMnemonicPos - nLineStart)+1];
+            auto fMnemonicWidth = std::abs(lc_x1 - lc_x2);
+            auto fMnemonicHeight = aTextDev.getUnderlineHeight();
+
+            auto fPosX = nLineX + std::min(lc_x1, lc_x2);
+            auto fPosY = aPos.Y() + aTextDev.getUnderlineOffset();
+
+            B2DPolygon aLine;
+            aLine.append(B2DPoint(fPosX, fPosY));
+            aLine.append(B2DPoint(fPosX + fMnemonicWidth, fPosY));
+
+            drawinglayer::attribute::LineAttribute 
aLineAttribute(Color(aTextColor).getBColor(), fMnemonicHeight);
+
+            rSeq[nPrimitives++] = 
drawinglayer::primitive2d::Primitive2DReference(
+                        new PolygonStrokePrimitive2D(aLine, aLineAttribute));
+        }
+
         nLineStart += nLineLength;
         aPos.setY(aPos.getY() + aTextEngine.GetCharHeight());
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to