[Libreoffice-commits] core.git: extras/source include/sfx2 include/svx include/vcl sd/source sfx2/source sfx2/uiconfig solenv/bin svx/source sw/source vcl/source vcl/unx

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Thu Mar 28 21:07:35 UTC 2019


 extras/source/glade/libreoffice-catalog.xml.in |    7 
 include/sfx2/emojiviewitem.hxx                 |    2 
 include/sfx2/inputdlg.hxx                      |    2 
 include/sfx2/recentdocsviewitem.hxx            |    9 
 include/sfx2/templatedlg.hxx                   |   86 -
 include/sfx2/templatelocalview.hxx             |  121 ++
 include/sfx2/templateviewitem.hxx              |    2 
 include/sfx2/thumbnailview.hxx                 |  184 +++
 include/sfx2/thumbnailviewitem.hxx             |    6 
 include/svx/SvxPresetListBox.hxx               |    2 
 include/svx/charmap.hxx                        |    4 
 include/vcl/customweld.hxx                     |    8 
 include/vcl/layout.hxx                         |    6 
 include/vcl/weld.hxx                           |   22 
 sd/source/ui/app/sdmod1.cxx                    |   11 
 sfx2/source/appl/appopen.cxx                   |    6 
 sfx2/source/appl/appserv.cxx                   |    4 
 sfx2/source/control/emojiviewitem.cxx          |    2 
 sfx2/source/control/recentdocsviewitem.cxx     |    7 
 sfx2/source/control/templatelocalview.cxx      |  888 ++++++++++++++++++
 sfx2/source/control/templatesearchview.cxx     |  143 +--
 sfx2/source/control/templateviewitem.cxx       |    2 
 sfx2/source/control/thumbnailview.cxx          | 1176 ++++++++++++++++++++++++-
 sfx2/source/control/thumbnailviewacc.cxx       |  560 +++++++++++
 sfx2/source/control/thumbnailviewacc.hxx       |  112 ++
 sfx2/source/control/thumbnailviewitem.cxx      |    2 
 sfx2/source/dialog/inputdlg.cxx                |    2 
 sfx2/source/doc/templatedlg.cxx                |  690 ++++++--------
 sfx2/source/inc/templatesearchview.hxx         |   13 
 sfx2/source/inc/templatesearchviewitem.hxx     |    2 
 sfx2/uiconfig/ui/templatedlg.ui                |  170 ++-
 solenv/bin/native-code.py                      |    2 
 svx/source/dialog/charmap.cxx                  |    4 
 svx/source/tbxctrls/SvxPresetListBox.cxx       |    5 
 sw/source/uibase/uiview/view2.cxx              |    4 
 vcl/source/app/customweld.cxx                  |    2 
 vcl/source/app/salvtables.cxx                  |   76 +
 vcl/unx/gtk3/gtk3gtkinst.cxx                   |  109 +-
 38 files changed, 3785 insertions(+), 668 deletions(-)

New commits:
commit 3e078e17ee2144fb976a7e6b9227152113cea0d4
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Tue Mar 26 16:27:17 2019 +0000
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Thu Mar 28 22:07:06 2019 +0100

    weld SfxTemplateManagerDlg
    
    like expert configuration change the gear menu not to display a down indicator
    
    and use CommandEvent to distinguish mouse/non-mouse context menus
    
    Change-Id: I64bb660a9c7dacb5b90b240d9d76d29324c5fd9f
    Reviewed-on: https://gerrit.libreoffice.org/69893
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/extras/source/glade/libreoffice-catalog.xml.in b/extras/source/glade/libreoffice-catalog.xml.in
index abeb0910a2dc..57106338489d 100644
--- a/extras/source/glade/libreoffice-catalog.xml.in
+++ b/extras/source/glade/libreoffice-catalog.xml.in
@@ -134,10 +134,6 @@
                         generic-name="Gamma Grid Widget" parent="GtkDrawingArea"
                         icon-name="widget-gtk-drawingarea"/>
 
-    <glade-widget-class title="Template Local View" name="sfxlo-TemplateLocalView"
-                        generic-name="Template Local View" parent="GtkDrawingArea"
-                        icon-name="widget-gtk-drawingarea"/>
-
     <glade-widget-class title="Mark Preview" name="swuilo-SwMarkPreview"
                         generic-name="Mark Preview Window" parent="GtkDrawingArea"
                         icon-name="widget-gtk-drawingarea"/>
@@ -437,9 +433,6 @@
     <glade-widget-class title="Template Thumbnail View" name="sfxlo-TemplateDefaultView"
                         generic-name="Template Icon View" parent="GtkIconView"
                         icon-name="widget-gtk-iconview"/>
-    <glade-widget-class title="Template Search View" name="sfxlo-TemplateSearchView"
-                        generic-name="Template Icon View" parent="GtkIconView"
-                        icon-name="widget-gtk-iconview"/>
 
     <glade-widget-class title="Driver List Control" name="cuilo-DriverListControl"
                         generic-name="DriverListControl" parent="GtkEntry"
diff --git a/include/sfx2/emojiviewitem.hxx b/include/sfx2/emojiviewitem.hxx
index 0ca32e78238f..e0aa57675f9a 100644
--- a/include/sfx2/emojiviewitem.hxx
+++ b/include/sfx2/emojiviewitem.hxx
@@ -15,7 +15,7 @@
 class EmojiViewItem : public ThumbnailViewItem
 {
 public:
-    EmojiViewItem (ThumbnailView &rView, sal_uInt16 nId);
+    EmojiViewItem (ThumbnailViewBase &rView, sal_uInt16 nId);
 
     virtual ~EmojiViewItem () override;
 
diff --git a/include/sfx2/inputdlg.hxx b/include/sfx2/inputdlg.hxx
index 6f50e012e997..bd54b6a5de02 100644
--- a/include/sfx2/inputdlg.hxx
+++ b/include/sfx2/inputdlg.hxx
@@ -21,7 +21,7 @@ private:
     std::unique_ptr<weld::Button> m_xHelp;
 
 public:
-    InputDialog(weld::Window* pParent, const OUString &rLabelText);
+    InputDialog(weld::Widget* pParent, const OUString &rLabelText);
     OUString GetEntryText() const;
     void SetEntryText(const OUString& rStr);
     void HideHelpBtn();
diff --git a/include/sfx2/recentdocsviewitem.hxx b/include/sfx2/recentdocsviewitem.hxx
index 8320d4710d81..2ee90de19f03 100644
--- a/include/sfx2/recentdocsviewitem.hxx
+++ b/include/sfx2/recentdocsviewitem.hxx
@@ -12,10 +12,15 @@
 
 #include <sfx2/thumbnailview.hxx>
 
+namespace sfx2
+{
+    class RecentDocsView;
+}
+
 class RecentDocsViewItem final : public ThumbnailViewItem
 {
 public:
-    RecentDocsViewItem(ThumbnailView &rView, const OUString &rURL,
+    RecentDocsViewItem(sfx2::RecentDocsView &rView, const OUString &rURL,
         const OUString &rTitle, const BitmapEx& rThumbnail, sal_uInt16 nId, long nThumbnailSize);
 
     /** Updates own highlight status based on the aPoint position.
@@ -38,6 +43,8 @@ public:
     void OpenDocument();
 
 private:
+    sfx2::RecentDocsView& mrParentView;
+
     /// Return area where is the icon to remove document from the recent documents.
     tools::Rectangle getRemoveIconArea() const;
 
diff --git a/include/sfx2/templatedlg.hxx b/include/sfx2/templatedlg.hxx
index 7f730c50161d..5e8a12853419 100644
--- a/include/sfx2/templatedlg.hxx
+++ b/include/sfx2/templatedlg.hxx
@@ -38,18 +38,16 @@ namespace com {
     }   }   }
 }
 
-class SFX2_DLLPUBLIC SfxTemplateManagerDlg : public ModalDialog
+class SFX2_DLLPUBLIC SfxTemplateManagerDlg : public weld::GenericDialogController
 {
     typedef bool (*selection_cmp_fn)(const ThumbnailViewItem*,const ThumbnailViewItem*);
 
 public:
 
-    SfxTemplateManagerDlg(vcl::Window *parent = nullptr);
+    SfxTemplateManagerDlg(weld::Window *parent);
 
     virtual ~SfxTemplateManagerDlg() override;
-    virtual void dispose() override;
-    virtual short Execute() override;
-    virtual bool EventNotify( NotifyEvent& rNEvt ) override;
+    virtual short run() override;
 
     void setDocumentModel (const css::uno::Reference<css::frame::XModel> &rModel);
 
@@ -63,21 +61,19 @@ protected:
 
     void fillFolderComboBox();
 
-    DECL_LINK(TBXDropdownHdl, ToolBox*, void);
+    DECL_LINK(SelectApplicationHdl, weld::ComboBox&, void);
+    DECL_LINK(SelectRegionHdl, weld::ComboBox&, void);
 
-    DECL_LINK(SelectApplicationHdl, ListBox&, void);
-    DECL_LINK(SelectRegionHdl, ListBox&, void);
-
-    DECL_LINK(OkClickHdl, Button*, void);
-    DECL_LINK(MoveClickHdl, Button*, void);
-    DECL_LINK(ExportClickHdl, Button*, void);
-    DECL_LINK(ImportClickHdl, Button*, void);
-    DECL_STATIC_LINK(SfxTemplateManagerDlg, LinkClickHdl, Button*, void);
+    DECL_LINK(OkClickHdl, weld::Button&, void);
+    DECL_LINK(MoveClickHdl, weld::Button&, void);
+    DECL_LINK(ExportClickHdl, weld::Button&, void);
+    DECL_LINK(ImportClickHdl, weld::Button&, void);
+    DECL_STATIC_LINK(SfxTemplateManagerDlg, LinkClickHdl, weld::Button&, void);
 
     DECL_LINK(TVItemStateHdl, const ThumbnailViewItem*, void);
 
-    DECL_LINK(MenuSelectHdl, Menu*, bool);
-    DECL_LINK(DefaultTemplateMenuSelectHdl, Menu*, bool);
+    DECL_LINK(MenuSelectHdl, const OString&, void);
+    void DefaultTemplateMenuSelectHdl(const OString& rIdent);
 
     DECL_LINK(OpenRegionHdl, void*, void);
     DECL_LINK(CreateContextMenuHdl, ThumbnailViewItem*, void);
@@ -86,8 +82,13 @@ protected:
     DECL_LINK(DeleteTemplateHdl, ThumbnailViewItem*, void);
     DECL_LINK(DefaultTemplateHdl, ThumbnailViewItem*, void);
 
-    DECL_LINK(SearchUpdateHdl, Edit&, void);
-    DECL_LINK(GetFocusHdl, Control&, void);
+    void SearchUpdate();
+
+    DECL_LINK(SearchUpdateHdl, weld::Entry&, void);
+    DECL_LINK(GetFocusHdl, weld::Widget&, void);
+    DECL_LINK(LoseFocusHdl, weld::Widget&, void);
+    DECL_LINK(ImplUpdateDataHdl, Timer*, void);
+    DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
 
     void OnTemplateImportCategory(const OUString& sCategory);
     static void OnTemplateLink ();
@@ -122,27 +123,28 @@ protected:
     FILTER_APPLICATION getCurrentApplicationFilter();
 
 protected:
-
-    VclPtr<Edit> mpSearchFilter;
-    VclPtr<ListBox> mpCBApp;
-    VclPtr<ListBox> mpCBFolder;
-
-    VclPtr<PushButton> mpOKButton;
-    VclPtr<PushButton> mpMoveButton;
-    VclPtr<PushButton> mpExportButton;
-    VclPtr<PushButton> mpImportButton;
-    VclPtr<PushButton> mpLinkButton;
-    VclPtr<CheckBox> mpCBXHideDlg;
-    VclPtr<ToolBox> mpActionBar;
-    VclPtr<TemplateSearchView> mpSearchView;
-    VclPtr<TemplateLocalView> mpLocalView;
-    VclPtr<PopupMenu> mpActionMenu;
-    VclPtr<PopupMenu> mpTemplateDefaultMenu;
-
     std::set<const ThumbnailViewItem*,selection_cmp_fn> maSelTemplates;
-
     css::uno::Reference< css::frame::XModel > m_xModel;
     css::uno::Reference< css::frame::XDesktop2 > mxDesktop;
+
+    Timer m_aUpdateDataTimer;
+
+    std::unique_ptr<weld::Entry> mxSearchFilter;
+    std::unique_ptr<weld::ComboBox> mxCBApp;
+    std::unique_ptr<weld::ComboBox> mxCBFolder;
+
+    std::unique_ptr<weld::Button> mxOKButton;
+    std::unique_ptr<weld::Button> mxMoveButton;
+    std::unique_ptr<weld::Button> mxExportButton;
+    std::unique_ptr<weld::Button> mxImportButton;
+    std::unique_ptr<weld::Button> mxLinkButton;
+    std::unique_ptr<weld::CheckButton> mxCBXHideDlg;
+    std::unique_ptr<weld::MenuButton> mxActionBar;
+    std::unique_ptr<TemplateSearchView> mxSearchView;
+    std::unique_ptr<SfxTemplateLocalView> mxLocalView;
+    std::unique_ptr<weld::Menu> mxTemplateDefaultMenu;
+    std::unique_ptr<weld::CustomWeld> mxSearchViewWeld;
+    std::unique_ptr<weld::CustomWeld> mxLocalViewWeld;
 };
 
 //  class SfxTemplateCategoryDialog -------------------------------------------------------------------
@@ -192,23 +194,21 @@ public:
 class SFX2_DLLPUBLIC SfxTemplateSelectionDlg : public SfxTemplateManagerDlg
 {
 public:
-    SfxTemplateSelectionDlg(vcl::Window *parent);
+    SfxTemplateSelectionDlg(weld::Window *parent);
 
     virtual ~SfxTemplateSelectionDlg() override;
-    virtual void dispose() override;
-    virtual short Execute() override;
+    virtual short run() override;
 
     OUString const & getTemplatePath() const { return msTemplatePath; };
-    bool IsStartWithTemplate() const { return mpCBXHideDlg->IsChecked(); };
+    bool IsStartWithTemplate() const { return mxCBXHideDlg->get_active(); };
 
 private:
     DECL_LINK(OpenTemplateHdl, ThumbnailViewItem*, void);
-    DECL_LINK(OkClickHdl, Button*, void);
+    DECL_LINK(OkClickHdl, weld::Button&, void);
 
-    OUString   msTemplatePath;
+    OUString msTemplatePath;
 };
 
-
 #endif // INCLUDED_SFX2_INC_TEMPLATEDLG_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/sfx2/templatelocalview.hxx b/include/sfx2/templatelocalview.hxx
index b739549580a8..93282b9ae9d0 100644
--- a/include/sfx2/templatelocalview.hxx
+++ b/include/sfx2/templatelocalview.hxx
@@ -193,6 +193,127 @@ protected:
     std::vector<TemplateItemProperties > maAllTemplates;
 };
 
+class SFX2_DLLPUBLIC SfxTemplateLocalView : public SfxThumbnailView
+{
+    typedef bool (*selection_cmp_fn)(const ThumbnailViewItem*,const ThumbnailViewItem*);
+
+public:
+
+    SfxTemplateLocalView(std::unique_ptr<weld::ScrolledWindow> xWindow,
+                         std::unique_ptr<weld::Menu> xMenu);
+
+    virtual ~SfxTemplateLocalView () override;
+
+    // Fill view with new item list
+    void insertItems (const std::vector<TemplateItemProperties> &rTemplates, bool isRegionSelected = true, bool bShowCategoryInTooltip = false);
+
+    // Fill view with template folders thumbnails
+    void Populate ();
+
+    virtual void reload ();
+
+    virtual void showAllTemplates ();
+
+    void showRegion (TemplateContainerItem const *pItem);
+
+    void showRegion (const OUString &rName);
+
+    void createContextMenu(const bool bIsDefault );
+
+    void ContextMenuSelectHdl(const OString& rIdent);
+
+    TemplateContainerItem* getRegion(OUString const & sStr);
+
+    sal_uInt16 getRegionId (size_t pos) const;
+
+    sal_uInt16 getRegionId (OUString const & sRegionName) const;
+
+    OUString getRegionName(const sal_uInt16 nRegionId) const;
+
+    OUString getRegionItemName(const sal_uInt16 nItemId) const;
+
+    std::vector<OUString> getFolderNames ();
+
+    std::vector<TemplateItemProperties>
+        getFilteredItems (const std::function<bool (const TemplateItemProperties&) > &rFunc) const;
+
+    sal_uInt16 createRegion (const OUString &rName);
+
+    bool renameRegion(const OUString &rTitle, const OUString &rNewTitle);
+
+    bool removeRegion (const sal_uInt16 nItemId);
+
+    bool removeTemplate (const sal_uInt16 nItemId, const sal_uInt16 nSrcItemId);
+
+    bool moveTemplate (const ThumbnailViewItem* pItem, const sal_uInt16 nSrcItem,
+                       const sal_uInt16 nTargetItem);
+
+    void moveTemplates (const std::set<const ThumbnailViewItem*,selection_cmp_fn> &rItems, const sal_uInt16 nTargetItem);
+
+    bool copyFrom(TemplateContainerItem *pItem, const OUString &rPath);
+
+    bool exportTo (const sal_uInt16 nItemId, const sal_uInt16 nRegionItemId, const OUString &rName);
+
+    virtual bool renameItem(ThumbnailViewItem* pItem, const OUString& sNewTitle) override;
+
+    virtual bool MouseButtonDown( const MouseEvent& rMEvt ) override;
+
+    virtual bool ContextMenu(const CommandEvent& rPos) override;
+
+    virtual bool KeyInput( const KeyEvent& rKEvt ) override;
+
+    sal_uInt16 getCurRegionId () const { return mnCurRegionId;}
+
+    void setOpenRegionHdl(const Link<void*,void> &rLink);
+
+    void setCreateContextMenuHdl(const Link<ThumbnailViewItem*,void> &rLink);
+
+    void setOpenTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink);
+
+    void setEditTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink);
+
+    void setDeleteTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink);
+
+    void setDefaultTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink);
+
+    void updateThumbnailDimensions(long itemMaxSize);
+
+    void RemoveDefaultTemplateIcon( const OUString& rPath);
+
+    static BitmapEx scaleImg (const BitmapEx &rImg, long width, long height);
+
+    static BitmapEx getDefaultThumbnail( const OUString& rPath );
+
+    static BitmapEx fetchThumbnail (const OUString &msURL, long width, long height);
+
+    static bool IsDefaultTemplate(const OUString& rPath);
+
+protected:
+    virtual void OnItemDblClicked(ThumbnailViewItem *pItem) override;
+
+protected:
+    sal_uInt16 mnCurRegionId;
+
+    TemplateViewItem *maSelectedItem;
+
+    long mnThumbnailWidth;
+    long mnThumbnailHeight;
+
+    Point maPosition; //store the point of click event
+
+    Link<void*,void>              maOpenRegionHdl;
+    Link<ThumbnailViewItem*,void> maCreateContextMenuHdl;
+    Link<ThumbnailViewItem*,void> maOpenTemplateHdl;
+    Link<ThumbnailViewItem*,void> maEditTemplateHdl;
+    Link<ThumbnailViewItem*,void> maDeleteTemplateHdl;
+    Link<ThumbnailViewItem*,void> maDefaultTemplateHdl;
+
+    std::unique_ptr<SfxDocumentTemplates> mpDocTemplates;
+    std::vector<std::unique_ptr<TemplateContainerItem> > maRegions;
+    std::vector<TemplateItemProperties > maAllTemplates;
+};
+
+
 #endif // INCLUDED_SFX2_TEMPLATELOCALVIEW_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/sfx2/templateviewitem.hxx b/include/sfx2/templateviewitem.hxx
index e64b82ec23a2..21433157f796 100644
--- a/include/sfx2/templateviewitem.hxx
+++ b/include/sfx2/templateviewitem.hxx
@@ -16,7 +16,7 @@ class TemplateViewItem : public ThumbnailViewItem
 {
 public:
 
-    TemplateViewItem (ThumbnailView &rView, sal_uInt16 nId);
+    TemplateViewItem (ThumbnailViewBase &rView, sal_uInt16 nId);
 
     virtual ~TemplateViewItem () override;
 
diff --git a/include/sfx2/thumbnailview.hxx b/include/sfx2/thumbnailview.hxx
index 238004cdc67b..d1807f454583 100644
--- a/include/sfx2/thumbnailview.hxx
+++ b/include/sfx2/thumbnailview.hxx
@@ -18,6 +18,7 @@
 
 #include <sfx2/thumbnailviewitem.hxx>
 #include <vcl/ctrl.hxx>
+#include <vcl/customweld.hxx>
 #include <vcl/timer.hxx>
 #include <vcl/pngread.hxx>
 
@@ -174,7 +175,26 @@ public:
  *
  **/
 
-class SFX2_DLLPUBLIC ThumbnailView : public Control
+class SFX2_DLLPUBLIC ThumbnailViewBase
+{
+    friend class ThumbnailViewAcc;
+    friend class ThumbnailViewItemAcc;
+
+    SFX2_DLLPRIVATE virtual sal_uInt16 ImplGetVisibleItemCount() const = 0;
+    SFX2_DLLPRIVATE virtual ThumbnailViewItem* ImplGetVisibleItem(sal_uInt16 nVisiblePos) = 0;
+
+    virtual css::uno::Reference<css::accessibility::XAccessible> getAccessible() = 0;
+
+public:
+    /// Updates information in the view; used only in RecentDocsView ATM.
+    virtual void Reload() {}
+
+    virtual bool renameItem(ThumbnailViewItem* pItem, const OUString& sNewTitle);
+
+    virtual ~ThumbnailViewBase();
+};
+
+class SFX2_DLLPUBLIC ThumbnailView : public Control, public ThumbnailViewBase
 {
 public:
 
@@ -191,9 +211,6 @@ public:
 
     virtual void Clear();
 
-    /// Updates information in the view; used only in RecentDocsView ATM.
-    virtual void Reload() {}
-
     // Change current thumbnail item list with new one (invalidates all pointers to a thumbnail item)
     void updateItems(std::vector<std::unique_ptr<ThumbnailViewItem>> items);
 
@@ -232,8 +249,6 @@ public:
 
     virtual void Resize() override;
 
-    virtual bool renameItem(ThumbnailViewItem* pItem, const OUString& sNewTitle);
-
     static BitmapEx readThumbnail(const OUString &msURL);
 
 protected:
@@ -256,6 +271,8 @@ protected:
 
     virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override;
 
+    virtual css::uno::Reference<css::accessibility::XAccessible> getAccessible() override;
+
 protected:
 
     // Drawing item related functions, override them to make your own custom ones.
@@ -280,8 +297,8 @@ protected:
     SFX2_DLLPRIVATE void         ImplDeleteItems();
     SFX2_DLLPRIVATE size_t       ImplGetItem( const Point& rPoint ) const;
     SFX2_DLLPRIVATE ThumbnailViewItem*    ImplGetItem( size_t nPos );
-    SFX2_DLLPRIVATE sal_uInt16   ImplGetVisibleItemCount() const;
-    SFX2_DLLPRIVATE ThumbnailViewItem*    ImplGetVisibleItem( sal_uInt16 nVisiblePos );
+    SFX2_DLLPRIVATE virtual sal_uInt16 ImplGetVisibleItemCount() const override;
+    SFX2_DLLPRIVATE virtual ThumbnailViewItem* ImplGetVisibleItem(sal_uInt16 nVisiblePos) override;
     SFX2_DLLPRIVATE void         ImplFireAccessibleEvent( short nEventId, const css::uno::Any& rOldValue, const css::uno::Any& rNewValue );
     SFX2_DLLPRIVATE bool         ImplHasAccessibleListeners();
     DECL_DLLPRIVATE_LINK( ImplScrollHdl, ScrollBar*, void );
@@ -320,6 +337,157 @@ protected:
     std::function<bool (const ThumbnailViewItem*)> maFilterFunc;
 };
 
+class SFX2_DLLPUBLIC SfxThumbnailView : public weld::CustomWidgetController, public ThumbnailViewBase
+{
+public:
+    SfxThumbnailView(std::unique_ptr<weld::ScrolledWindow> xWindow, std::unique_ptr<weld::Menu> xMenu);
+
+    virtual ~SfxThumbnailView() override;
+
+    virtual bool MouseMove(const MouseEvent& rMEvt) override;
+
+    void AppendItem(std::unique_ptr<ThumbnailViewItem> pItem);
+
+    void RemoveItem(sal_uInt16 nItemId);
+
+    virtual void Clear();
+
+    // Change current thumbnail item list with new one (invalidates all pointers to a thumbnail item)
+    void updateItems(std::vector<std::unique_ptr<ThumbnailViewItem>> items);
+
+    size_t GetItemPos( sal_uInt16 nItemId ) const;
+
+    sal_uInt16 GetItemId( size_t nPos ) const;
+
+    sal_uInt16 GetItemId( const Point& rPos ) const;
+
+    sal_uInt16 getNextItemId () const;
+
+    void setItemMaxTextLength (sal_uInt32 nLength);
+
+    void setItemDimensions (long ItemWidth, long ThumbnailHeight,
+                            long DisplayHeight, int itemPadding);
+
+    void SelectItem( sal_uInt16 nItemId );
+
+    bool IsItemSelected( sal_uInt16 nItemId ) const;
+
+    /**
+     *
+     * @brief deselect all current selected items.
+     *
+     **/
+
+    void deselectItems ();
+
+    void ShowTooltips( bool bShowTooltips );
+
+    void SetMultiSelectionEnabled( bool bIsMultiSelectionEnabled );
+
+    void filterItems (const std::function<bool (const ThumbnailViewItem*) > &func);
+
+    void setItemStateHdl (const Link<const ThumbnailViewItem*,void> &aLink) { maItemStateHdl = aLink; }
+
+    virtual void Resize() override;
+
+    static BitmapEx readThumbnail(const OUString &msURL);
+
+    virtual void Show() override
+    {
+        mxScrolledWindow->show();
+        CustomWidgetController::Show();
+    }
+
+    virtual void Hide() override
+    {
+        mxScrolledWindow->hide();
+        CustomWidgetController::Hide();
+    }
+
+    virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
+
+protected:
+
+    virtual bool KeyInput( const KeyEvent& rKEvt ) override;
+
+    virtual bool MouseButtonDown( const MouseEvent& rMEvt ) override;
+
+    virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+
+    virtual void GetFocus() override;
+
+    virtual void LoseFocus() override;
+
+    virtual OUString RequestHelp(tools::Rectangle& rRect) override;
+
+    virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override;
+
+    virtual css::uno::Reference<css::accessibility::XAccessible> getAccessible() override;
+
+protected:
+
+    // Drawing item related functions, override them to make your own custom ones.
+
+    void DrawItem (ThumbnailViewItem const *pItem);
+
+    virtual void OnItemDblClicked (ThumbnailViewItem *pItem);
+
+protected:
+
+    friend class SfxThumbnailViewAcc;
+    friend class ThumbnailViewItemAcc;
+
+    void CalculateItemPositions (bool bScrollBarUsed = false);
+    void MakeItemVisible( sal_uInt16 nId );
+
+    SFX2_DLLPRIVATE void         ImplInit();
+
+    SFX2_DLLPRIVATE void         ImplDeleteItems();
+    SFX2_DLLPRIVATE size_t       ImplGetItem( const Point& rPoint ) const;
+    SFX2_DLLPRIVATE ThumbnailViewItem*    ImplGetItem( size_t nPos );
+    SFX2_DLLPRIVATE virtual sal_uInt16 ImplGetVisibleItemCount() const override;
+    SFX2_DLLPRIVATE virtual ThumbnailViewItem* ImplGetVisibleItem(sal_uInt16 nVisiblePos) override;
+    SFX2_DLLPRIVATE void         ImplFireAccessibleEvent( short nEventId, const css::uno::Any& rOldValue, const css::uno::Any& rNewValue );
+    SFX2_DLLPRIVATE bool         ImplHasAccessibleListeners();
+    DECL_DLLPRIVATE_LINK( ImplScrollHdl, weld::ScrolledWindow&, void );
+
+protected:
+
+    std::vector< std::unique_ptr<ThumbnailViewItem> > mItemList;
+    css::uno::Reference<css::accessibility::XAccessible> mxAccessible;
+    ThumbnailValueItemList mFilteredItemList; ///< Cache to store the filtered items
+    ThumbnailValueItemList::iterator mpStartSelRange;
+    long mnItemWidth;
+    long mnItemHeight;
+    long mnItemPadding;
+    long mnThumbnailHeight;     // Maximum height of the thumbnail
+    long mnDisplayHeight;       // Height of the data display box (name, etc)
+    long mnVisLines;
+    long mnLines;
+
+    sal_uInt16 mnCols;
+    sal_uInt16 mnFirstLine;
+    bool mbScroll : 1;
+    bool mbHasVisibleItems : 1;
+    bool mbShowTooltips : 1;
+    bool mbIsMultiSelectionEnabled: 1;
+    Color maFillColor;              ///< Background color of the thumbnail view widget.
+    Color maTextColor;              ///< Text color.
+    Color maHighlightColor;         ///< Color of the highlight (background) of the hovered item.
+    Color maHighlightTextColor;     ///< Color of the text for the highlighted item.
+    Color maSelectHighlightColor;   ///< Color of the highlight (background) of the selected and hovered item.
+    Color maSelectHighlightTextColor;   ///< Color of the text of the selected and hovered item.
+    double mfHighlightTransparence; ///< Transparence of the highlight.
+
+    Link<const ThumbnailViewItem*, void> maItemStateHdl;
+    std::unique_ptr<ThumbnailItemAttributes> mpItemAttrs;
+    std::unique_ptr<weld::ScrolledWindow> mxScrolledWindow;
+    std::unique_ptr<weld::Menu> mxContextMenu;
+
+    std::function<bool (const ThumbnailViewItem*)> maFilterFunc;
+};
+
+
 #endif // INCLUDED_SFX2_THUMBNAILVIEW_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/sfx2/thumbnailviewitem.hxx b/include/sfx2/thumbnailviewitem.hxx
index 3568da70d31b..26cb96966967 100644
--- a/include/sfx2/thumbnailviewitem.hxx
+++ b/include/sfx2/thumbnailviewitem.hxx
@@ -32,7 +32,7 @@
 
 const int THUMBNAILVIEW_ITEM_CORNER = 5;
 
-class ThumbnailView;
+class ThumbnailViewBase;
 class MouseEvent;
 
 namespace basegfx {
@@ -67,7 +67,7 @@ class SFX2_DLLPUBLIC ThumbnailViewItem
 {
 public:
 
-    ThumbnailView &mrParent;
+    ThumbnailViewBase &mrParent;
     sal_uInt16 const mnId;
     bool mbVisible;
     bool mbSelected;
@@ -77,7 +77,7 @@ public:
     OUString maHelpText;
     css::uno::Reference< css::accessibility::XAccessible > mxAcc;
 
-    ThumbnailViewItem (ThumbnailView &rView, sal_uInt16 nId);
+    ThumbnailViewItem (ThumbnailViewBase &rView, sal_uInt16 nId);
 
     virtual ~ThumbnailViewItem ();
 
diff --git a/include/svx/SvxPresetListBox.hxx b/include/svx/SvxPresetListBox.hxx
index e8809eca0f61..f580ebac04fb 100644
--- a/include/svx/SvxPresetListBox.hxx
+++ b/include/svx/SvxPresetListBox.hxx
@@ -44,7 +44,7 @@ public:
     SvxPresetListBox(std::unique_ptr<weld::ScrolledWindow> pWindow);
 
     virtual void Resize() override;
-    virtual bool ContextMenu(const Point& rPos) override;
+    virtual bool ContextMenu(const CommandEvent& rEvent) override;
     static sal_uInt32 getColumnCount() { return nColCount; }
     Size const & GetIconSize() const { return aIconSize; }
 
diff --git a/include/svx/charmap.hxx b/include/svx/charmap.hxx
index 0551f2ad03c8..df6b29e1ef21 100644
--- a/include/svx/charmap.hxx
+++ b/include/svx/charmap.hxx
@@ -103,8 +103,8 @@ public:
 
     virtual sal_Int32                   getMaxCharCount() const;
 
-    void Show() { mxScrollArea->show(); }
-    void Hide() { mxScrollArea->hide(); }
+    virtual void Show() override { mxScrollArea->show(); }
+    virtual void Hide() override { mxScrollArea->hide(); }
 
     uno::Reference<css::accessibility::XAccessible> getAccessibleParent() { return GetDrawingArea()->get_accessible_parent(); }
 
diff --git a/include/vcl/customweld.hxx b/include/vcl/customweld.hxx
index db60521a195d..e8bbb2129912 100644
--- a/include/vcl/customweld.hxx
+++ b/include/vcl/customweld.hxx
@@ -33,7 +33,7 @@ public:
     virtual void GetFocus() {}
     virtual void LoseFocus() {}
     virtual void StyleUpdated() { Invalidate(); }
-    virtual bool ContextMenu(const Point&) { return false; }
+    virtual bool ContextMenu(const CommandEvent&) { return false; }
     virtual bool KeyInput(const KeyEvent&) { return false; }
     virtual tools::Rectangle GetFocusRect() { return tools::Rectangle(); }
     virtual FactoryFunction GetUITestFactory() const { return nullptr; }
@@ -49,8 +49,8 @@ public:
         m_pDrawingArea->queue_draw_area(rRect.Left(), rRect.Top(), rRect.GetWidth(),
                                         rRect.GetHeight());
     }
-    void Show() { m_pDrawingArea->show(); }
-    void Hide() { m_pDrawingArea->hide(); }
+    virtual void Show() { m_pDrawingArea->show(); }
+    virtual void Hide() { m_pDrawingArea->hide(); }
     void GrabFocus() { m_pDrawingArea->grab_focus(); }
     bool HasFocus() const { return m_pDrawingArea->has_focus(); }
     bool IsVisible() const { return m_pDrawingArea->get_visible(); }
@@ -101,7 +101,7 @@ private:
     DECL_LINK(DoLoseFocus, weld::Widget&, void);
     DECL_LINK(DoKeyPress, const KeyEvent&, bool);
     DECL_LINK(DoFocusRect, weld::Widget&, tools::Rectangle);
-    DECL_LINK(DoPopupMenu, const Point&, bool);
+    DECL_LINK(DoPopupMenu, const CommandEvent&, bool);
     DECL_LINK(DoStyleUpdated, weld::Widget&, void);
     DECL_LINK(DoRequestHelp, tools::Rectangle&, OUString);
 
diff --git a/include/vcl/layout.hxx b/include/vcl/layout.hxx
index 33a6db730a85..2ea881a31fd6 100644
--- a/include/vcl/layout.hxx
+++ b/include/vcl/layout.hxx
@@ -620,7 +620,7 @@ private:
     Link<const KeyEvent&, bool> m_aKeyPressHdl;
     Link<const KeyEvent&, bool> m_aKeyReleaseHdl;
     Link<VclDrawingArea&, void> m_aStyleUpdatedHdl;
-    Link<const Point&, bool> m_aPopupMenuHdl;
+    Link<const CommandEvent&, bool> m_aPopupMenuHdl;
     Link<tools::Rectangle&, OUString> m_aQueryTooltipHdl;
 
     virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override
@@ -677,7 +677,7 @@ private:
     }
     virtual void Command(const CommandEvent& rEvent) override
     {
-        if (rEvent.GetCommand() == CommandEventId::ContextMenu && m_aPopupMenuHdl.Call(rEvent.GetMousePosPixel()))
+        if (rEvent.GetCommand() == CommandEventId::ContextMenu && m_aPopupMenuHdl.Call(rEvent))
             return;
         Control::Command(rEvent);
     }
@@ -755,7 +755,7 @@ public:
     {
         m_aStyleUpdatedHdl = rLink;
     }
-    void SetPopupMenuHdl(const Link<const Point&, bool>& rLink)
+    void SetPopupMenuHdl(const Link<const CommandEvent&, bool>& rLink)
     {
         m_aPopupMenuHdl = rLink;
     }
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 91fc19f65a87..f258b83c2cd5 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -254,6 +254,8 @@ public:
     virtual int hadjustment_get_upper() const = 0;
     virtual void hadjustment_set_upper(int upper) = 0;
     virtual int hadjustment_get_page_size() const = 0;
+    virtual void hadjustment_set_page_size(int size) = 0;
+    virtual void hadjustment_set_page_increment(int size) = 0;
     virtual void set_hpolicy(VclPolicyType eHPolicy) = 0;
     virtual VclPolicyType get_hpolicy() const = 0;
     void connect_hadjustment_changed(const Link<ScrolledWindow&, void>& rLink)
@@ -270,6 +272,8 @@ public:
     virtual int vadjustment_get_upper() const = 0;
     virtual void vadjustment_set_upper(int upper) = 0;
     virtual int vadjustment_get_page_size() const = 0;
+    virtual void vadjustment_set_page_size(int size) = 0;
+    virtual void vadjustment_set_page_increment(int size) = 0;
     virtual int vadjustment_get_lower() const = 0;
     virtual void vadjustment_set_lower(int upper) = 0;
     virtual void set_vpolicy(VclPolicyType eVPolicy) = 0;
@@ -852,11 +856,14 @@ public:
     {
         insert_item(-1, rId, rStr, nullptr, &rImage, false);
     }
+    virtual void insert_separator(int pos, const OUString& rId) = 0;
+    void append_separator(const OUString& rId) { insert_separator(-1, rId); }
     virtual void remove_item(const OString& rId) = 0;
     virtual void set_item_sensitive(const OString& rIdent, bool bSensitive) = 0;
     virtual void set_item_active(const OString& rIdent, bool bActive) = 0;
     virtual void set_item_label(const OString& rIdent, const OUString& rLabel) = 0;
     virtual void set_item_help_id(const OString& rIdent, const OString& rHelpId) = 0;
+    virtual void set_item_visible(const OString& rIdent, bool bVisible) = 0;
     virtual OString get_item_help_id(const OString& rIdent) const = 0;
 
     virtual void set_popover(weld::Widget* pPopover) = 0;
@@ -1474,7 +1481,7 @@ public:
 protected:
     Link<draw_args, void> m_aDrawHdl;
     Link<Widget&, void> m_aStyleUpdatedHdl;
-    Link<const Point&, bool> m_aPopupMenuHdl;
+    Link<const CommandEvent&, bool> m_aPopupMenuHdl;
     Link<Widget&, tools::Rectangle> m_aGetFocusRectHdl;
     Link<tools::Rectangle&, OUString> m_aQueryTooltipHdl;
 
@@ -1486,7 +1493,10 @@ protected:
 public:
     void connect_draw(const Link<draw_args, void>& rLink) { m_aDrawHdl = rLink; }
     void connect_style_updated(const Link<Widget&, void>& rLink) { m_aStyleUpdatedHdl = rLink; }
-    void connect_popup_menu(const Link<const Point&, bool>& rLink) { m_aPopupMenuHdl = rLink; }
+    void connect_popup_menu(const Link<const CommandEvent&, bool>& rLink)
+    {
+        m_aPopupMenuHdl = rLink;
+    }
     void connect_focus_rect(const Link<Widget&, tools::Rectangle>& rLink)
     {
         m_aGetFocusRectHdl = rLink;
@@ -1512,11 +1522,17 @@ public:
     virtual OString popup_at_rect(weld::Widget* pParent, const tools::Rectangle& rRect) = 0;
     virtual void set_sensitive(const OString& rIdent, bool bSensitive) = 0;
     virtual void set_active(const OString& rIdent, bool bActive) = 0;
-    virtual void show(const OString& rIdent, bool bShow) = 0;
+    virtual void set_visible(const OString& rIdent, bool bVisible) = 0;
 
     virtual void insert(int pos, const OUString& rId, const OUString& rStr,
                         const OUString* pIconName, VirtualDevice* pImageSufface, bool bCheck)
         = 0;
+
+    virtual void clear() = 0;
+
+    virtual void insert_separator(int pos, const OUString& rId) = 0;
+    void append_separator(const OUString& rId) { insert_separator(-1, rId); }
+
     void append(const OUString& rId, const OUString& rStr)
     {
         insert(-1, rId, rStr, nullptr, nullptr, false);
diff --git a/sd/source/ui/app/sdmod1.cxx b/sd/source/ui/app/sdmod1.cxx
index 42bde350851f..f60e2ee4d0b8 100644
--- a/sd/source/ui/app/sdmod1.cxx
+++ b/sd/source/ui/app/sdmod1.cxx
@@ -475,15 +475,16 @@ SfxFrame* SdModule::ExecuteNewDocument( SfxRequest const & rReq )
         if(bStartWithTemplate)
         {
             //Launch TemplateSelectionDialog
-            ScopedVclPtrInstance< SfxTemplateSelectionDlg > aTemplDlg( SfxGetpApp()->GetTopWindow());
-            aTemplDlg->Execute();
+            vcl::Window* pTopLevel = SfxGetpApp()->GetTopWindow();
+            SfxTemplateSelectionDlg aTemplDlg(pTopLevel ? pTopLevel->GetFrameWeld() : nullptr);
+            aTemplDlg.run();
 
             //check to disable the dialog
-            pOpt->SetStartWithTemplate( aTemplDlg->IsStartWithTemplate() );
+            pOpt->SetStartWithTemplate( aTemplDlg.IsStartWithTemplate() );
 
             //pFrame is loaded with the desired template
-            if(!aTemplDlg->getTemplatePath().isEmpty())
-                pFrame = CreateFromTemplate(aTemplDlg->getTemplatePath(), xTargetFrame);
+            if (!aTemplDlg.getTemplatePath().isEmpty())
+                pFrame = CreateFromTemplate(aTemplDlg.getTemplatePath(), xTargetFrame);
         }
     }
 
diff --git a/sfx2/source/appl/appopen.cxx b/sfx2/source/appl/appopen.cxx
index 4a655f940d4c..0c5288289098 100644
--- a/sfx2/source/appl/appopen.cxx
+++ b/sfx2/source/appl/appopen.cxx
@@ -448,12 +448,12 @@ void SfxApplication::NewDocExec_Impl( SfxRequest& rReq )
         if(pCurrentShell)
             xModel = pCurrentShell->GetModel();
 
-        ScopedVclPtrInstance< SfxTemplateManagerDlg > aTemplDlg;
+        SfxTemplateManagerDlg aTemplDlg(rReq.GetFrameWeld());
 
         if (xModel.is())
-            aTemplDlg->setDocumentModel(xModel);
+            aTemplDlg.setDocumentModel(xModel);
 
-        int nRet = aTemplDlg->Execute();
+        int nRet = aTemplDlg.run();
         if ( nRet == RET_OK )
         {
             rReq.Done();
diff --git a/sfx2/source/appl/appserv.cxx b/sfx2/source/appl/appserv.cxx
index d2ac03b9c2ac..bfe3fb24abc3 100644
--- a/sfx2/source/appl/appserv.cxx
+++ b/sfx2/source/appl/appserv.cxx
@@ -660,8 +660,8 @@ void SfxApplication::MiscExec_Impl( SfxRequest& rReq )
 
         case SID_TEMPLATE_MANAGER:
         {
-            ScopedVclPtrInstance< SfxTemplateManagerDlg > dlg;
-            dlg->Execute();
+            SfxTemplateManagerDlg aDialog(rReq.GetFrameWeld());
+            aDialog.run();
             bDone = true;
             break;
         }
diff --git a/sfx2/source/control/emojiviewitem.cxx b/sfx2/source/control/emojiviewitem.cxx
index e4f1e701363e..f393738d045f 100644
--- a/sfx2/source/control/emojiviewitem.cxx
+++ b/sfx2/source/control/emojiviewitem.cxx
@@ -27,7 +27,7 @@ using namespace basegfx::utils;
 using namespace drawinglayer::attribute;
 using namespace drawinglayer::primitive2d;
 
-EmojiViewItem::EmojiViewItem (ThumbnailView &rView, sal_uInt16 nId)
+EmojiViewItem::EmojiViewItem (ThumbnailViewBase &rView, sal_uInt16 nId)
     : ThumbnailViewItem(rView, nId)
 {
 }
diff --git a/sfx2/source/control/recentdocsviewitem.cxx b/sfx2/source/control/recentdocsviewitem.cxx
index f1992285e782..cddbe57ae500 100644
--- a/sfx2/source/control/recentdocsviewitem.cxx
+++ b/sfx2/source/control/recentdocsviewitem.cxx
@@ -32,9 +32,10 @@ using namespace com::sun::star::uno;
 using namespace drawinglayer::primitive2d;
 using namespace drawinglayer::processor2d;
 
-RecentDocsViewItem::RecentDocsViewItem(ThumbnailView &rView, const OUString &rURL,
+RecentDocsViewItem::RecentDocsViewItem(sfx2::RecentDocsView &rView, const OUString &rURL,
     const OUString &rTitle, const BitmapEx &rThumbnail, sal_uInt16 nId, long nThumbnailSize)
     : ThumbnailViewItem(rView, nId),
+      mrParentView(rView),
       maURL(rURL),
       m_bRemoveIconHighlighted(false),
       m_aRemoveRecentBitmap(BMP_RECENTDOC_REMOVE),
@@ -178,7 +179,7 @@ void RecentDocsViewItem::MouseButtonUp(const MouseEvent& rMEvt)
 void RecentDocsViewItem::OpenDocument()
 {
     // show busy mouse pointer
-    mrParent.SetPointer(PointerStyle::Wait);
+    mrParentView.SetPointer(PointerStyle::Wait);
 
     Reference<frame::XDispatch> xDispatch;
     Reference<frame::XDispatchProvider> xDispatchProvider;
@@ -216,7 +217,7 @@ void RecentDocsViewItem::OpenDocument()
     pLoadRecentFile->xDispatch = xDispatch;
     pLoadRecentFile->aTargetURL = aTargetURL;
     pLoadRecentFile->aArgSeq = aArgsList;
-    pLoadRecentFile->pView.set(&mrParent);
+    pLoadRecentFile->pView = &mrParentView;
 
     Application::PostUserEvent(LINK(nullptr, sfx2::RecentDocsView, ExecuteHdl_Impl), pLoadRecentFile, true);
 }
diff --git a/sfx2/source/control/templatelocalview.cxx b/sfx2/source/control/templatelocalview.cxx
index d15109f8943b..816448a3b298 100644
--- a/sfx2/source/control/templatelocalview.cxx
+++ b/sfx2/source/control/templatelocalview.cxx
@@ -96,8 +96,6 @@ TemplateLocalView::TemplateLocalView ( vcl::Window* pParent, WinBits nWinStyle)
 {
 }
 
-VCL_BUILDER_FACTORY(TemplateLocalView)
-
 TemplateLocalView::~TemplateLocalView()
 {
     disposeOnce();
@@ -1017,4 +1015,890 @@ void TemplateLocalView::OnItemDblClicked (ThumbnailViewItem *pItem)
         maOpenTemplateHdl.Call(pViewItem);
 }
 
+SfxTemplateLocalView::SfxTemplateLocalView(std::unique_ptr<weld::ScrolledWindow> xWindow,
+                                           std::unique_ptr<weld::Menu> xMenu)
+    : SfxThumbnailView(std::move(xWindow), std::move(xMenu))
+    , mnCurRegionId(0)
+    , maSelectedItem(nullptr)
+    , mnThumbnailWidth(TEMPLATE_THUMBNAIL_MAX_WIDTH)
+    , mnThumbnailHeight(TEMPLATE_THUMBNAIL_MAX_HEIGHT)
+    , maPosition(0,0)
+    , mpDocTemplates(new SfxDocumentTemplates)
+{
+}
+
+SfxTemplateLocalView::~SfxTemplateLocalView()
+{
+}
+
+void SfxTemplateLocalView::Populate()
+{
+    maRegions.clear();
+    maAllTemplates.clear();
+
+    sal_uInt16 nCount = mpDocTemplates->GetRegionCount();
+    for (sal_uInt16 i = 0; i < nCount; ++i)
+    {
+        OUString aRegionName(mpDocTemplates->GetFullRegionName(i));
+
+        std::unique_ptr<TemplateContainerItem> pItem(new TemplateContainerItem( i+1 ));
+        pItem->mnRegionId = i;
+        pItem->maTitle = aRegionName;
+
+        sal_uInt16 nEntries = mpDocTemplates->GetCount(i);
+
+        for (sal_uInt16 j = 0; j < nEntries; ++j)
+        {
+            OUString aName = mpDocTemplates->GetName(i,j);
+            OUString aURL = mpDocTemplates->GetPath(i,j);
+
+            TemplateItemProperties aProperties;
+            aProperties.nId = j+1;
+            aProperties.nDocId = j;
+            aProperties.nRegionId = i;
+            aProperties.aName = aName;
+            aProperties.aPath = aURL;
+            aProperties.aRegionName = aRegionName;
+            aProperties.aThumbnail = TemplateLocalView::fetchThumbnail(aURL,
+                                                                          mnThumbnailWidth,
+                                                                          mnThumbnailHeight);
+
+            pItem->maTemplates.push_back(aProperties);
+            maAllTemplates.push_back(aProperties);
+        }
+
+        maRegions.push_back(std::move(pItem));
+    }
+}
+
+void SfxTemplateLocalView::reload()
+{
+    mpDocTemplates->Update();
+
+    Populate();
+
+    // Check if we are currently browsing a region or root folder
+    if (mnCurRegionId)
+    {
+        sal_uInt16 nRegionId = mnCurRegionId - 1;   //Is offset by 1
+
+        for (auto const & pRegion : maRegions)
+        {
+            if (pRegion->mnRegionId == nRegionId)
+            {
+                showRegion(pRegion.get());
+                break;
+            }
+        }
+    }
+    else
+        showAllTemplates();
+
+    //No items should be selected by default
+    deselectItems();
+}
+
+void SfxTemplateLocalView::showAllTemplates()
+{
+    mnCurRegionId = 0;
+
+    insertItems(maAllTemplates, false, true);
+
+    maOpenRegionHdl.Call(nullptr);
+}
+
+void SfxTemplateLocalView::showRegion(TemplateContainerItem const *pItem)
+{
+    mnCurRegionId = pItem->mnRegionId+1;
+
+    insertItems(pItem->maTemplates);
+
+    maOpenRegionHdl.Call(nullptr);
+}
+
+void SfxTemplateLocalView::showRegion(const OUString &rName)
+{
+    for (auto const & pRegion : maRegions)
+    {
+        if (pRegion->maTitle == rName)
+        {
+            showRegion(pRegion.get());
+            break;
+        }
+    }
+}
+
+TemplateContainerItem* SfxTemplateLocalView::getRegion(OUString const & rName)
+{
+    for (auto const & pRegion : maRegions)
+        if (pRegion->maTitle == rName)
+            return pRegion.get();
+
+    return nullptr;
+}
+
+void SfxTemplateLocalView::createContextMenu(const bool bIsDefault)
+{
+    mxContextMenu->clear();
+    mxContextMenu->append("open",SfxResId(STR_OPEN));
+    mxContextMenu->append("edit",SfxResId(STR_EDIT_TEMPLATE));
+
+    if(!bIsDefault)
+        mxContextMenu->append("default",SfxResId(STR_DEFAULT_TEMPLATE));
+    else
+        mxContextMenu->append("default",SfxResId(STR_RESET_DEFAULT));
+
+    mxContextMenu->append_separator("separator");
+    mxContextMenu->append("rename",SfxResId(STR_RENAME));
+    mxContextMenu->append("delete",SfxResId(STR_DELETE));
+    deselectItems();
+    maSelectedItem->setSelection(true);
+    maItemStateHdl.Call(maSelectedItem);
+    ContextMenuSelectHdl(mxContextMenu->popup_at_rect(GetDrawingArea(), tools::Rectangle(maPosition, Size(1,1))));
+    Invalidate();
+}
+
+void SfxTemplateLocalView::ContextMenuSelectHdl(const OString& rIdent)
+{
+    if (rIdent == "open")
+        maOpenTemplateHdl.Call(maSelectedItem);
+    else if (rIdent == "edit")
+        maEditTemplateHdl.Call(maSelectedItem);
+    else if (rIdent == "rename")
+    {
+        InputDialog aTitleEditDlg(GetDrawingArea(), SfxResId(STR_RENAME_TEMPLATE));
+        OUString sOldTitle = maSelectedItem->getTitle();
+        aTitleEditDlg.SetEntryText(sOldTitle);
+        aTitleEditDlg.HideHelpBtn();
+
+        if (!aTitleEditDlg.run())
+            return;
+        OUString sNewTitle = comphelper::string::strip(aTitleEditDlg.GetEntryText(), ' ');
+
+        if ( !sNewTitle.isEmpty() && sNewTitle != sOldTitle )
+        {
+            maSelectedItem->setTitle(sNewTitle);
+        }
+    }
+    else if (rIdent == "delete")
+    {
+        std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo,
+                                                       SfxResId(STR_QMSG_SEL_TEMPLATE_DELETE)));
+        if (xQueryDlg->run() != RET_YES)
+            return;
+
+        maDeleteTemplateHdl.Call(maSelectedItem);
+        reload();
+    }
+    else if (rIdent == "default")
+        maDefaultTemplateHdl.Call(maSelectedItem);
+}
+
+sal_uInt16 SfxTemplateLocalView::getRegionId(size_t pos) const
+{
+    assert(pos < maRegions.size());
+
+    return maRegions[pos]->mnId;
+}
+
+sal_uInt16 SfxTemplateLocalView::getRegionId(OUString const & sRegion) const
+{
+    for (auto const & pRegion : maRegions)
+    {
+        if (pRegion->maTitle == sRegion)
+            return pRegion->mnId;
+    }
+
+    return 0;
+}
+
+OUString SfxTemplateLocalView::getRegionName(const sal_uInt16 nRegionId) const
+{
+    return mpDocTemplates->GetRegionName(nRegionId);
+}
+
+OUString SfxTemplateLocalView::getRegionItemName(const sal_uInt16 nItemId) const
+{
+    for (auto const & pRegion : maRegions)
+    {
+        if (pRegion->mnId == nItemId)
+            return pRegion->maTitle;
+    }
+
+    return OUString();
+}
+
+std::vector<OUString> SfxTemplateLocalView::getFolderNames()
+{
+    size_t n = maRegions.size();
+    std::vector<OUString> ret(n);
+
+    for (size_t i = 0; i < n; ++i)
+        ret[i] = maRegions[i]->maTitle;
+
+    return ret;
+}
+
+std::vector<TemplateItemProperties>
+SfxTemplateLocalView::getFilteredItems(const std::function<bool (const TemplateItemProperties&)> &rFunc) const
+{
+    std::vector<TemplateItemProperties> aItems;
+
+    if (mnCurRegionId)
+    {
+        TemplateContainerItem *pFolderItem = maRegions[mnCurRegionId-1].get();
+
+        for (TemplateItemProperties & rItemProps : pFolderItem->maTemplates)
+        {
+            if (rFunc(rItemProps))
+                aItems.push_back(rItemProps);
+        }
+    }
+    else
+    {
+        for (auto const & pFolderItem : maRegions)
+        {
+            for (const TemplateItemProperties & rItemProps : pFolderItem->maTemplates)
+            {
+                if (rFunc(rItemProps))
+                    aItems.push_back(rItemProps);
+            }
+        }
+    }
+
+    return aItems;
+}
+
+sal_uInt16 SfxTemplateLocalView::createRegion(const OUString &rName)
+{
+    sal_uInt16 nRegionId = mpDocTemplates->GetRegionCount();    // Next regionId
+    sal_uInt16 nItemId = getNextItemId();
+
+    if (!mpDocTemplates->InsertDir(rName,nRegionId))
+        return 0;
+
+    // Insert to the region cache list and to the thumbnail item list
+    std::unique_ptr<TemplateContainerItem> pItem(new TemplateContainerItem( nItemId ));
+    pItem->mnRegionId = nRegionId;
+    pItem->maTitle = rName;
+
+    maRegions.push_back(std::move(pItem));
+
+    return nItemId;
+}
+
+bool SfxTemplateLocalView::renameRegion(const OUString &rTitle, const OUString &rNewTitle)
+{
+    TemplateContainerItem *pRegion = getRegion(rTitle);
+
+    if(pRegion)
+    {
+        sal_uInt16 nRegionId = pRegion->mnRegionId;
+        return mpDocTemplates->SetName( rNewTitle, nRegionId, USHRT_MAX/*nDocId*/ );
+    }
+    return false;
+}
+
+bool SfxTemplateLocalView::removeRegion(const sal_uInt16 nItemId)
+{
+    sal_uInt16 nRegionId = USHRT_MAX;
+
+    // Remove from the region cache list
+    for (auto pRegionIt = maRegions.begin(); pRegionIt != maRegions.end();)
+    {
+        if ( (*pRegionIt)->mnId == nItemId )
+        {
+            if (!mpDocTemplates->Delete((*pRegionIt)->mnRegionId,USHRT_MAX))
+                return false;
+
+            nRegionId = (*pRegionIt)->mnRegionId;
+
+            pRegionIt = maRegions.erase(pRegionIt);
+        }
+        else
+        {
+            // Synchronize regions cache ids with SfxDocumentTemplates
+            if (nRegionId != USHRT_MAX && (*pRegionIt)->mnRegionId > nRegionId)
+                --(*pRegionIt)->mnRegionId;
+
+            ++pRegionIt;
+        }
+    }
+
+    if (nRegionId == USHRT_MAX)
+        return false;
+
+    // Synchronize view regions ids with SfxDocumentTemplates
+    for (auto const& region : maRegions)
+    {
+        if (region->mnRegionId > nRegionId)
+            --region->mnRegionId;
+    }
+
+    return true;
+}
+
+bool SfxTemplateLocalView::removeTemplate (const sal_uInt16 nItemId, const sal_uInt16 nSrcItemId)
+{
+    for (auto const & pRegion : maRegions)
+    {
+        if (pRegion->mnId == nSrcItemId)
+        {
+            TemplateContainerItem *pItem = pRegion.get();
+            auto pIter = std::find_if(pItem->maTemplates.begin(), pItem->maTemplates.end(),
+                [nItemId](const TemplateItemProperties& rTemplate) { return rTemplate.nId == nItemId; });
+            if (pIter != pItem->maTemplates.end())
+            {
+                if (!mpDocTemplates->Delete(pItem->mnRegionId,pIter->nDocId))
+                    return false;
+
+                pIter = pItem->maTemplates.erase(pIter);
+
+                if (pRegion->mnRegionId == mnCurRegionId-1)
+                {
+                    RemoveItem(nItemId);
+                    Invalidate();
+                }
+
+                // Update Doc Idx for all templates that follow
+                for (; pIter != pItem->maTemplates.end(); ++pIter)
+                    pIter->nDocId = pIter->nDocId - 1;
+            }
+
+            CalculateItemPositions();
+            break;
+        }
+    }
+
+    return true;
+}
+
+bool SfxTemplateLocalView::moveTemplate (const ThumbnailViewItem *pItem, const sal_uInt16 nSrcItem,
+                                       const sal_uInt16 nTargetItem)
+{
+    TemplateContainerItem *pTarget = nullptr;
+    TemplateContainerItem *pSrc = nullptr;
+
+    for (auto const & pRegion : maRegions)
+    {
+        if (pRegion->mnId == nTargetItem)
+            pTarget = pRegion.get();
+        else if (pRegion->mnId == nSrcItem)
+            pSrc = pRegion.get();
+    }
+
+    if (pTarget && pSrc)
+    {
+        sal_uInt16 nSrcRegionId = pSrc->mnRegionId;
+        sal_uInt16 nTargetRegion = pTarget->mnRegionId;
+        sal_uInt16 nTargetIdx = mpDocTemplates->GetCount(nTargetRegion);    // Next Idx
+
+        const TemplateViewItem *pViewItem = static_cast<const TemplateViewItem*>(pItem);
+
+        bool bCopy = !mpDocTemplates->Move(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnDocId);
+
+        if (bCopy)
+        {
+            OUString sQuery = SfxResId(STR_MSG_QUERY_COPY).replaceFirst("$1", pViewItem->maTitle).replaceFirst("$2",
+                getRegionName(nTargetRegion));
+
+            std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo, sQuery));
+            if (xQueryDlg->run() != RET_YES)
+                return false;
+
+            if (!mpDocTemplates->Copy(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnDocId))
+                return false;
+        }
+        // move template to destination
+
+        TemplateItemProperties aTemplateItem;
+        aTemplateItem.nId = nTargetIdx + 1;
+        aTemplateItem.nDocId = nTargetIdx;
+        aTemplateItem.nRegionId = nTargetRegion;
+        aTemplateItem.aName = pViewItem->maTitle;
+        aTemplateItem.aPath = mpDocTemplates->GetPath(nTargetRegion,nTargetIdx);
+        aTemplateItem.aRegionName = pViewItem->maHelpText;
+        aTemplateItem.aThumbnail = pViewItem->maPreview1;
+
+        pTarget->maTemplates.push_back(aTemplateItem);
+
+        if (!bCopy)
+        {
+            // remove template from region cached data
+
+            std::vector<TemplateItemProperties>::iterator aIter;
+            for (aIter = pSrc->maTemplates.begin(); aIter != pSrc->maTemplates.end();)
+            {
+                if (aIter->nDocId == pViewItem->mnDocId)
+                {
+                    aIter = pSrc->maTemplates.erase(aIter);
+                }
+                else
+                {
+                    // Keep region document id synchronized with SfxDocumentTemplates
+                    if (aIter->nDocId > pViewItem->mnDocId)
+                        --aIter->nDocId;
+
+                    ++aIter;
+                }
+            }
+
+            // Keep view document id synchronized with SfxDocumentTemplates
+            for (auto const& item : mItemList)
+            {
+                auto pTemplateViewItem = static_cast<TemplateViewItem*>(item.get());
+                if (pTemplateViewItem->mnDocId > pViewItem->mnDocId)
+                    --pTemplateViewItem->mnDocId;
+            }
+        }
+
+        CalculateItemPositions();
+        Invalidate();
+
+        return true;
+    }
+
+    return false;
+}
+
+void SfxTemplateLocalView::moveTemplates(const std::set<const ThumbnailViewItem*, selection_cmp_fn> &rItems,
+                                      const sal_uInt16 nTargetItem)
+{
+    TemplateContainerItem *pTarget = nullptr;
+    TemplateContainerItem *pSrc = nullptr;
+
+    for (auto const & pRegion : maRegions)
+    {
+        if (pRegion->mnId == nTargetItem)
+            pTarget = pRegion.get();
+    }
+
+    if (!pTarget)
+        return;
+
+    bool refresh = false;
+
+    sal_uInt16 nTargetRegion = pTarget->mnRegionId;
+    sal_uInt16 nTargetIdx = mpDocTemplates->GetCount(nTargetRegion);    // Next Idx
+    std::vector<sal_uInt16> aItemIds;    // List of moved items ids (also prevents the invalidation of rItems iterators when we remove them as we go)
+
+    std::set<const ThumbnailViewItem*,selection_cmp_fn>::const_iterator aSelIter;
+    for ( aSelIter = rItems.begin(); aSelIter != rItems.end(); ++aSelIter, ++nTargetIdx )
+    {
+        const TemplateViewItem *pViewItem = static_cast<const TemplateViewItem*>(*aSelIter);
+        sal_uInt16 nSrcRegionId = pViewItem->mnRegionId;
+
+        for (auto const & pRegion : maRegions)
+        {
+            if (pRegion->mnRegionId == nSrcRegionId)
+                pSrc = pRegion.get();
+        }
+
+        if(pSrc)
+        {
+            bool bCopy = !mpDocTemplates->Move(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnDocId);
+
+            if (bCopy)
+            {
+                OUString sQuery = SfxResId(STR_MSG_QUERY_COPY).replaceFirst("$1", pViewItem->maTitle).replaceFirst("$2",
+                    getRegionName(nTargetRegion));
+                std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo, sQuery));
+                if (xQueryDlg->run() != RET_YES)
+                {
+                    OUString sMsg(SfxResId(STR_MSG_ERROR_LOCAL_MOVE));
+                    sMsg = sMsg.replaceFirst("$1",getRegionName(nTargetRegion));
+                    std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetDrawingArea(),
+                                                              VclMessageType::Warning, VclButtonsType::Ok, sMsg.replaceFirst( "$2",pViewItem->maTitle)));
+                    xBox->run();
+
+                    return; //return if any single move operation fails
+                }
+
+                if (!mpDocTemplates->Copy(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnDocId))
+                {
+                    continue;
+                }
+            }
+
+            // move template to destination
+
+            TemplateItemProperties aTemplateItem;
+            aTemplateItem.nId = nTargetIdx + 1;
+            aTemplateItem.nDocId = nTargetIdx;
+            aTemplateItem.nRegionId = nTargetRegion;
+            aTemplateItem.aName = pViewItem->maTitle;
+            aTemplateItem.aPath = mpDocTemplates->GetPath(nTargetRegion,nTargetIdx);
+            aTemplateItem.aRegionName = pViewItem->maHelpText;
+            aTemplateItem.aThumbnail = pViewItem->maPreview1;
+
+            pTarget->maTemplates.push_back(aTemplateItem);
+
+            if (!bCopy)
+            {
+                // remove template from region cached data
+
+                std::vector<TemplateItemProperties>::iterator pPropIter;
+                for (pPropIter = pSrc->maTemplates.begin(); pPropIter != pSrc->maTemplates.end();)
+                {
+                    if (pPropIter->nDocId == pViewItem->mnDocId)
+                    {
+                        pPropIter = pSrc->maTemplates.erase(pPropIter);
+                        aItemIds.push_back(pViewItem->mnDocId + 1);//mnid
+                    }
+                    else
+                    {
+                        // Keep region document id synchronized with SfxDocumentTemplates
+                        if (pPropIter->nDocId > pViewItem->mnDocId)
+                            --pPropIter->nDocId;
+
+                        ++pPropIter;
+                    }
+                }
+
+                // Keep view document id synchronized with SfxDocumentTemplates
+                for (auto const& item : mItemList)
+                {
+                    auto pTemplateViewItem = static_cast<TemplateViewItem*>(item.get());
+                    if (pTemplateViewItem->mnDocId > pViewItem->mnDocId)
+                        --pTemplateViewItem->mnDocId;
+                }
+            }
+        }
+
+        refresh = true;
+    }
+
+    // Remove items from the current view
+    for (auto const& itemId : aItemIds)
+        RemoveItem(itemId);
+
+    if (refresh)
+    {
+        CalculateItemPositions();
+        Invalidate();
+    }
+}
+
+bool SfxTemplateLocalView::copyFrom (TemplateContainerItem *pItem, const OUString &rPath)
+{
+    sal_uInt16 nId = 1;
+    sal_uInt16 nDocId = 0;
+    sal_uInt16 nRegionId = pItem->mnRegionId;
+    OUString aPath(rPath);
+
+    if (!pItem->maTemplates.empty())
+    {
+        nId = pItem->maTemplates.back().nId+1;
+        nDocId = pItem->maTemplates.back().nDocId+1;
+    }
+
+    if (mpDocTemplates->CopyFrom(nRegionId,nDocId,aPath))
+    {
+        TemplateItemProperties aTemplate;
+        aTemplate.nId = nId;
+        aTemplate.nDocId = nDocId;
+        aTemplate.nRegionId = nRegionId;
+        aTemplate.aName = aPath;
+        aTemplate.aThumbnail = SfxTemplateLocalView::fetchThumbnail(rPath,
+                                                                    TEMPLATE_THUMBNAIL_MAX_WIDTH,
+                                                                    TEMPLATE_THUMBNAIL_MAX_HEIGHT);
+        aTemplate.aPath = rPath;
+        aTemplate.aRegionName = getRegionName(nRegionId);
+
+        pItem->maTemplates.push_back(aTemplate);
+
+        CalculateItemPositions();
+
+        return true;
+    }
+
+    return false;
+}
+
+bool SfxTemplateLocalView::exportTo(const sal_uInt16 nItemId, const sal_uInt16 nRegionItemId, const OUString &rName)
+{
+    for (auto const & pRegItem : maRegions)
+    {
+        if (pRegItem->mnId == nRegionItemId)
+        {
+            for (auto const& elem : pRegItem->maTemplates)
+            {
+                if (elem.nId == nItemId)
+                {
+                    return mpDocTemplates->CopyTo(pRegItem->mnRegionId,elem.nDocId,rName);
+                }
+            }
+
+            break;
+        }
+    }
+
+    return false;
+}
+
+bool SfxTemplateLocalView::renameItem(ThumbnailViewItem* pItem, const OUString& sNewTitle)
+{
+    sal_uInt16 nRegionId = 0;
+    sal_uInt16 nDocId = USHRT_MAX;
+    TemplateViewItem* pDocItem = dynamic_cast<TemplateViewItem*>( pItem );
+
+    if ( pDocItem )
+    {
+        nRegionId = pDocItem->mnRegionId;
+        nDocId = pDocItem->mnDocId;
+    }
+
+    return mpDocTemplates->SetName( sNewTitle, nRegionId, nDocId );
+}
+
+void SfxTemplateLocalView::insertItems(const std::vector<TemplateItemProperties> &rTemplates, bool isRegionSelected, bool bShowCategoryInTooltip)
+{
+    std::vector<std::unique_ptr<ThumbnailViewItem>> aItems(rTemplates.size());
+    for (size_t i = 0, n = rTemplates.size(); i < n; ++i )
+    {
+        const TemplateItemProperties *pCur = &rTemplates[i];
+
+        std::unique_ptr<TemplateViewItem> pChild;
+        if(isRegionSelected)
+            pChild.reset(new TemplateViewItem(*this, pCur->nId));
+        else
+            pChild.reset(new TemplateViewItem(*this, i+1));
+
+        pChild->mnDocId = pCur->nDocId;
+        pChild->mnRegionId = pCur->nRegionId;
+        pChild->maTitle = pCur->aName;
+        pChild->setPath(pCur->aPath);
+
+        if(!bShowCategoryInTooltip)
+            pChild->setHelpText(pCur->aName);
+        else
+        {
+            OUString sHelpText = SfxResId(STR_TEMPLATE_TOOLTIP);
+            sHelpText = (sHelpText.replaceFirst("$1", pCur->aName)).replaceFirst("$2", pCur->aRegionName);
+            pChild->setHelpText(sHelpText);
+        }
+
+        pChild->maPreview1 = pCur->aThumbnail;
+
+        if(IsDefaultTemplate(pCur->aPath))
+            pChild->showDefaultIcon(true);
+
+        if ( pCur->aThumbnail.IsEmpty() )
+        {
+            // Use the default thumbnail if we have nothing else
+            pChild->maPreview1 = SfxTemplateLocalView::getDefaultThumbnail(pCur->aPath);
+        }
+
+        aItems[i] = std::move(pChild);
+    }
+
+    updateItems(std::move(aItems));
+}
+
+void SfxTemplateLocalView::updateThumbnailDimensions(long itemMaxSize)
+{
+    mnThumbnailWidth = itemMaxSize;
+    mnThumbnailHeight = itemMaxSize;
+}
+
+bool SfxTemplateLocalView::MouseButtonDown( const MouseEvent& rMEvt )
+{
+    GrabFocus();
+    return SfxThumbnailView::MouseButtonDown(rMEvt);
+}
+
+bool SfxTemplateLocalView::ContextMenu(const CommandEvent& rCEvt)
+{
+    if (rCEvt.IsMouseEvent())
+    {
+        deselectItems();
+        size_t nPos = ImplGetItem(rCEvt.GetMousePosPixel());
+        Point aPosition(rCEvt.GetMousePosPixel());
+        maPosition = aPosition;
+        ThumbnailViewItem* pItem = ImplGetItem(nPos);
+        const TemplateViewItem *pViewItem = dynamic_cast<const TemplateViewItem*>(pItem);
+
+        if(pViewItem)
+        {
+            maSelectedItem = dynamic_cast<TemplateViewItem*>(pItem);
+            maCreateContextMenuHdl.Call(pItem);
+        }
+    }
+    else
+    {
+        for (ThumbnailViewItem* pItem : mFilteredItemList)
+        {
+            //create context menu for the first selected item
+            if (pItem->isSelected())
+            {
+                deselectItems();
+                pItem->setSelection(true);
+                maItemStateHdl.Call(pItem);
+                tools::Rectangle aRect = pItem->getDrawArea();
+                maPosition = aRect.Center();
+                maSelectedItem = dynamic_cast<TemplateViewItem*>(pItem);
+                maCreateContextMenuHdl.Call(pItem);
+                break;
+            }
+        }
+    }
+    return true;
+}
+
+bool SfxTemplateLocalView::KeyInput( const KeyEvent& rKEvt )
+{
+    vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
+
+    if(aKeyCode == ( KEY_MOD1 | KEY_A ) )
+    {
+        for (ThumbnailViewItem* pItem : mFilteredItemList)
+        {
+            if (!pItem->isSelected())
+            {
+                pItem->setSelection(true);
+                maItemStateHdl.Call(pItem);
+            }
+        }
+
+        if (IsReallyVisible() && IsUpdateMode())
+            Invalidate();
+        return true;
+    }
+    else if( aKeyCode == KEY_DELETE && !mFilteredItemList.empty())
+    {
+        std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo,
+                                                       SfxResId(STR_QMSG_SEL_TEMPLATE_DELETE)));
+        if (xQueryDlg->run() != RET_YES)
+            return true;
+
+        //copy to avoid changing filtered item list during deletion
+        ThumbnailValueItemList mFilteredItemListCopy = mFilteredItemList;
+
+        for (ThumbnailViewItem* pItem : mFilteredItemListCopy)
+        {
+            if (pItem->isSelected())
+            {
+                maDeleteTemplateHdl.Call(pItem);
+            }
+        }
+        reload();
+    }
+
+    return SfxThumbnailView::KeyInput(rKEvt);
+}
+
+void SfxTemplateLocalView::setOpenRegionHdl(const Link<void*,void> &rLink)
+{
+    maOpenRegionHdl = rLink;
+}
+
+void SfxTemplateLocalView::setCreateContextMenuHdl(const Link<ThumbnailViewItem*,void> &rLink)
+{
+    maCreateContextMenuHdl = rLink;
+}
+
+void SfxTemplateLocalView::setOpenTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink)
+{
+    maOpenTemplateHdl = rLink;
+}
+
+void SfxTemplateLocalView::setEditTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink)
+{
+    maEditTemplateHdl = rLink;
+}
+
+void SfxTemplateLocalView::setDeleteTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink)
+{
+    maDeleteTemplateHdl = rLink;
+}
+
+void SfxTemplateLocalView::setDefaultTemplateHdl(const Link<ThumbnailViewItem*,void> &rLink)
+{
+    maDefaultTemplateHdl = rLink;
+}
+
+BitmapEx SfxTemplateLocalView::scaleImg (const BitmapEx &rImg, long width, long height)
+{
+    BitmapEx aImg = rImg;
+
+    if (!rImg.IsEmpty())
+    {
+        Size aSize = rImg.GetSizePixel();
+
+        if (aSize.Width() == 0)
+            aSize.setWidth( 1 );
+
+        if (aSize.Height() == 0)
+            aSize.setHeight( 1 );
+
+        // make the picture fit the given width/height constraints
+        double nRatio = std::min(double(width)/double(aSize.Width()), double(height)/double(aSize.Height()));
+
+        aImg.Scale(Size(aSize.Width() * nRatio, aSize.Height() * nRatio));
+    }
+
+    return aImg;
+}
+
+bool SfxTemplateLocalView::IsDefaultTemplate(const OUString& rPath)
+{
+    SvtModuleOptions aModOpt;
+    const css::uno::Sequence<OUString> &aServiceNames = aModOpt.GetAllServiceNames();
+
+    for( sal_Int32 i=0, nCount = aServiceNames.getLength(); i < nCount; ++i )
+    {
+        const OUString defaultPath = SfxObjectFactory::GetStandardTemplate( aServiceNames[i] );
+        if(defaultPath.match(rPath))
+            return true;
+    }
+
+    return false;
+}
+
+void SfxTemplateLocalView::RemoveDefaultTemplateIcon(const OUString& rPath)
+{
+    for (std::unique_ptr<ThumbnailViewItem>& pItem : mItemList)
+    {
+        TemplateViewItem* pViewItem = dynamic_cast<TemplateViewItem*>(pItem.get());
+        if (pViewItem && pViewItem->getPath().match(rPath))
+        {
+            pViewItem->showDefaultIcon(false);
+            Invalidate();
+            return;
+        }
+    }
+}
+
+BitmapEx SfxTemplateLocalView::getDefaultThumbnail( const OUString& rPath )
+{
+    BitmapEx aImg;
+    INetURLObject aUrl(rPath);
+    OUString aExt = aUrl.getExtension();
+
+    if ( ViewFilter_Application::isFilteredExtension( FILTER_APPLICATION::WRITER, aExt) )
+        aImg = BitmapEx(SFX_THUMBNAIL_TEXT);
+    else if ( ViewFilter_Application::isFilteredExtension( FILTER_APPLICATION::CALC, aExt) )
+        aImg = BitmapEx(SFX_THUMBNAIL_SHEET);
+    else if ( ViewFilter_Application::isFilteredExtension( FILTER_APPLICATION::IMPRESS, aExt) )
+        aImg = BitmapEx(SFX_THUMBNAIL_PRESENTATION);
+    else if ( ViewFilter_Application::isFilteredExtension( FILTER_APPLICATION::DRAW, aExt) )
+        aImg = BitmapEx(SFX_THUMBNAIL_DRAWING);
+
+    return aImg;
+}
+
+BitmapEx SfxTemplateLocalView::fetchThumbnail (const OUString &msURL, long width, long height)
+{
+    return SfxTemplateLocalView::scaleImg(ThumbnailView::readThumbnail(msURL), width, height);
+}
+
+void SfxTemplateLocalView::OnItemDblClicked (ThumbnailViewItem *pItem)
+{
+    TemplateViewItem* pViewItem = dynamic_cast<TemplateViewItem*>(pItem);
+
+    if( pViewItem )
+        maOpenTemplateHdl.Call(pViewItem);
+}
+
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/control/templatesearchview.cxx b/sfx2/source/control/templatesearchview.cxx
index 279b8bc596ad..97848d65e28a 100644
--- a/sfx2/source/control/templatesearchview.cxx
+++ b/sfx2/source/control/templatesearchview.cxx
@@ -22,27 +22,26 @@
 
 #include <vcl/builderfactory.hxx>
 
-#define MNI_OPEN               1
-#define MNI_EDIT               2
-#define MNI_DEFAULT_TEMPLATE   3
-#define MNI_DELETE             4
-
-TemplateSearchView::TemplateSearchView (vcl::Window *pParent)
-    : ThumbnailView(pParent,WB_TABSTOP | WB_VSCROLL | WB_BORDER),
-    maSelectedItem(nullptr),
-    maPosition(0,0)
+#define MNI_OPEN               "open"
+#define MNI_EDIT               "edit"
+#define MNI_DEFAULT_TEMPLATE   "default"
+#define MNI_DELETE             "delete"
+
+TemplateSearchView::TemplateSearchView(std::unique_ptr<weld::ScrolledWindow> xWindow,
+                                       std::unique_ptr<weld::Menu> xMenu)
+    : SfxThumbnailView(std::move(xWindow), std::move(xMenu))
+    , maSelectedItem(nullptr)
+    , maPosition(0,0)
 {
 }
 
-VCL_BUILDER_FACTORY(TemplateSearchView)
-
-void TemplateSearchView::MouseButtonDown( const MouseEvent& rMEvt )
+bool TemplateSearchView::MouseButtonDown( const MouseEvent& rMEvt )
 {
     GrabFocus();
-    ThumbnailView::MouseButtonDown(rMEvt);
+    return SfxThumbnailView::MouseButtonDown(rMEvt);
 }
 
-void TemplateSearchView::KeyInput( const KeyEvent& rKEvt )
+bool TemplateSearchView::KeyInput( const KeyEvent& rKEvt )
 {
     vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
 
@@ -59,14 +58,14 @@ void TemplateSearchView::KeyInput( const KeyEvent& rKEvt )
 
         if (IsReallyVisible() && IsUpdateMode())
             Invalidate();
-        return;
+        return true;
     }
     else if( aKeyCode == KEY_DELETE && !mFilteredItemList.empty())
     {
-        std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo,
+        std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo,
                                                        SfxResId(STR_QMSG_SEL_TEMPLATE_DELETE)));
         if (xQueryDlg->run() != RET_YES)
-            return;
+            return true;
 
         //copy to avoid changing filtered item list during deletion
         ThumbnailValueItemList mFilteredItemListCopy = mFilteredItemList;
@@ -83,104 +82,86 @@ void TemplateSearchView::KeyInput( const KeyEvent& rKEvt )
         }
     }
 
-    ThumbnailView::KeyInput(rKEvt);
+    return SfxThumbnailView::KeyInput(rKEvt);
 }
 
-void TemplateSearchView::Command( const CommandEvent& rCEvt )
+bool TemplateSearchView::ContextMenu(const CommandEvent& rCEvt)
 {
-    if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
+    if (rCEvt.IsMouseEvent())
     {
-        if(rCEvt.IsMouseEvent())
+        deselectItems();
+        size_t nPos = ImplGetItem(rCEvt.GetMousePosPixel());
+        Point aPosition(rCEvt.GetMousePosPixel());
+        maPosition = aPosition;
+        ThumbnailViewItem* pItem = ImplGetItem(nPos);
+        const TemplateViewItem *pViewItem = dynamic_cast<const TemplateViewItem*>(pItem);
+
+        if(pViewItem)
         {
-            deselectItems();
-            size_t nPos = ImplGetItem(rCEvt.GetMousePosPixel());
-            Point aPosition (rCEvt.GetMousePosPixel());
-            maPosition = aPosition;
-            ThumbnailViewItem* pItem = ImplGetItem(nPos);
-            const TemplateViewItem *pViewItem = dynamic_cast<const TemplateViewItem*>(pItem);
-
-            if(pViewItem)
-            {
-                maSelectedItem = dynamic_cast<TemplateViewItem*>(pItem);
-                maCreateContextMenuHdl.Call(pItem);
-            }
+            maSelectedItem = dynamic_cast<TemplateViewItem*>(pItem);
+            maCreateContextMenuHdl.Call(pItem);
         }
-        else
+    }
+    else
+    {
+        for (ThumbnailViewItem* pItem : mFilteredItemList)
         {
-            for (ThumbnailViewItem* pItem : mFilteredItemList)
+            //create context menu for the first selected item
+            if (pItem->isSelected())
             {
-                //create context menu for the first selected item
-                if (pItem->isSelected())
-                {
-                    deselectItems();
-                    pItem->setSelection(true);
-                    maItemStateHdl.Call(pItem);
-                    tools::Rectangle aRect = pItem->getDrawArea();
-                    maPosition = aRect.Center();
-                    maSelectedItem = dynamic_cast<TemplateViewItem*>(pItem);
-                    maCreateContextMenuHdl.Call(pItem);
-                    break;
-                }
+                deselectItems();
+                pItem->setSelection(true);
+                maItemStateHdl.Call(pItem);
+                tools::Rectangle aRect = pItem->getDrawArea();
+                maPosition = aRect.Center();
+                maSelectedItem = dynamic_cast<TemplateViewItem*>(pItem);
+                maCreateContextMenuHdl.Call(pItem);
+                break;
             }
         }
     }
-
-    ThumbnailView::Command(rCEvt);
+    return true;
 }
 
-void TemplateSearchView::createContextMenu( const bool bIsDefault)
+void TemplateSearchView::createContextMenu(const bool bIsDefault)
 {
-    ScopedVclPtrInstance<PopupMenu> pItemMenu;
-    pItemMenu->InsertItem(MNI_OPEN,SfxResId(STR_OPEN));
-    pItemMenu->InsertItem(MNI_EDIT,SfxResId(STR_EDIT_TEMPLATE));
+    mxContextMenu->clear();
+    mxContextMenu->append(MNI_OPEN,SfxResId(STR_OPEN));
+    mxContextMenu->append(MNI_EDIT,SfxResId(STR_EDIT_TEMPLATE));
 
-    if(!bIsDefault)
-        pItemMenu->InsertItem(MNI_DEFAULT_TEMPLATE,SfxResId(STR_DEFAULT_TEMPLATE));
+    if (!bIsDefault)
+        mxContextMenu->append(MNI_DEFAULT_TEMPLATE,SfxResId(STR_DEFAULT_TEMPLATE));
     else
-        pItemMenu->InsertItem(MNI_DEFAULT_TEMPLATE,SfxResId(STR_RESET_DEFAULT));
+        mxContextMenu->append(MNI_DEFAULT_TEMPLATE,SfxResId(STR_RESET_DEFAULT));
 
-    pItemMenu->InsertSeparator();
-    pItemMenu->InsertItem(MNI_DELETE,SfxResId(STR_DELETE));
+    mxContextMenu->append_separator("separator");
+    mxContextMenu->append(MNI_DELETE,SfxResId(STR_DELETE));
     maSelectedItem->setSelection(true);
     maItemStateHdl.Call(maSelectedItem);
-    pItemMenu->SetSelectHdl(LINK(this, TemplateSearchView, ContextMenuSelectHdl));
-    pItemMenu->Execute(this, tools::Rectangle(maPosition,Size(1,1)), PopupMenuFlags::ExecuteDown);
+    ContextMenuSelectHdl(mxContextMenu->popup_at_rect(GetDrawingArea(), tools::Rectangle(maPosition, Size(1,1))));
     Invalidate();
 }
 
-IMPL_LINK(TemplateSearchView, ContextMenuSelectHdl, Menu*, pMenu, bool)
+void TemplateSearchView::ContextMenuSelectHdl(const OString& rIdent)
 {
-    sal_uInt16 nMenuId = pMenu->GetCurItemId();
-
-    switch(nMenuId)
-    {
-    case MNI_OPEN:
+    if (rIdent == MNI_OPEN)
         maOpenTemplateHdl.Call(maSelectedItem);
-        break;
-    case MNI_EDIT:
+    else if (rIdent == MNI_EDIT)
         maEditTemplateHdl.Call(maSelectedItem);
-        break;
-    case MNI_DELETE:
+    else if (rIdent ==  MNI_DELETE)
     {
-        std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo,
+        std::unique_ptr<weld::MessageDialog> xQueryDlg(Application::CreateMessageDialog(GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo,
                                                        SfxResId(STR_QMSG_SEL_TEMPLATE_DELETE)));
         if (xQueryDlg->run() != RET_YES)
-            break;
+            return;
 
         maDeleteTemplateHdl.Call(maSelectedItem);
         RemoveItem(maSelectedItem->mnId);
 
         CalculateItemPositions();
     }
-        break;
-    case MNI_DEFAULT_TEMPLATE:
+    else if (rIdent == MNI_DEFAULT_TEMPLATE)
         maDefaultTemplateHdl.Call(maSelectedItem);
-        break;
-    default:
-        break;
-    }
-
-    return false;
 }
 
 void TemplateSearchView::setCreateContextMenuHdl(const Link<ThumbnailViewItem*,void> &rLink)
@@ -235,7 +216,7 @@ void TemplateSearchView::AppendItem(sal_uInt16 nAssocItemId, sal_uInt16 nRegionI
     if(TemplateLocalView::IsDefaultTemplate(rPath))
         pItem->showDefaultIcon(true);
 
-    ThumbnailView::AppendItem(std::move(pItem));
+    SfxThumbnailView::AppendItem(std::move(pItem));
 
     CalculateItemPositions();
 }
diff --git a/sfx2/source/control/templateviewitem.cxx b/sfx2/source/control/templateviewitem.cxx
index 6d6207554382..b6918de9445b 100644
--- a/sfx2/source/control/templateviewitem.cxx
+++ b/sfx2/source/control/templateviewitem.cxx
@@ -29,7 +29,7 @@ using namespace basegfx::utils;
 using namespace drawinglayer::attribute;
 using namespace drawinglayer::primitive2d;
 
-TemplateViewItem::TemplateViewItem (ThumbnailView &rView, sal_uInt16 nId)
+TemplateViewItem::TemplateViewItem (ThumbnailViewBase &rView, sal_uInt16 nId)
     : ThumbnailViewItem(rView, nId),
       mnRegionId(USHRT_MAX),
       mnDocId(USHRT_MAX),
diff --git a/sfx2/source/control/thumbnailview.cxx b/sfx2/source/control/thumbnailview.cxx
index 04c47f81ffc0..9c4986a16220 100644
--- a/sfx2/source/control/thumbnailview.cxx
+++ b/sfx2/source/control/thumbnailview.cxx
@@ -229,6 +229,11 @@ css::uno::Reference< css::accessibility::XAccessible > ThumbnailView::CreateAcce
     return new ThumbnailViewAcc( this );
 }
 
+css::uno::Reference< css::accessibility::XAccessible > ThumbnailView::getAccessible()
+{
+    return GetAccessible();
+}
+
 void ThumbnailView::CalculateItemPositions (bool bScrollBarUsed)
 {
     if (!mnItemHeight || !mnItemWidth)
@@ -1206,12 +1211,16 @@ void ThumbnailView::filterItems(const std::function<bool (const ThumbnailViewIte
     Invalidate();
 }
 
-bool ThumbnailView::renameItem(ThumbnailViewItem*, const OUString&)
+bool ThumbnailViewBase::renameItem(ThumbnailViewItem*, const OUString&)
 {
     // Do nothing by default
     return false;
 }
 
+ThumbnailViewBase::~ThumbnailViewBase()
+{
+}
+
 BitmapEx ThumbnailView::readThumbnail(const OUString &msURL)
 {
     using namespace ::com::sun::star;
@@ -1306,4 +1315,1169 @@ BitmapEx ThumbnailView::readThumbnail(const OUString &msURL)
     return aThumbnail;
 }
 
+SfxThumbnailView::SfxThumbnailView(std::unique_ptr<weld::ScrolledWindow> xWindow, std::unique_ptr<weld::Menu> xMenu)
+    : mpItemAttrs(new ThumbnailItemAttributes)
+    , mxScrolledWindow(std::move(xWindow))
+    , mxContextMenu(std::move(xMenu))
+{
+    mxScrolledWindow->set_user_managed_scrolling();
+    ImplInit();
+    mxScrolledWindow->connect_vadjustment_changed(LINK(this, SfxThumbnailView, ImplScrollHdl));
+}
+
+SfxThumbnailView::~SfxThumbnailView()
+{
+    css::uno::Reference< css::lang::XComponent> xComponent(mxAccessible, css::uno::UNO_QUERY);
+
+    if (xComponent.is())
+        xComponent->dispose();
+
+    mpItemAttrs.reset();
+
+    ImplDeleteItems();
+}
+
+bool SfxThumbnailView::MouseMove(const MouseEvent& rMEvt)
+{
+    size_t nItemCount = mFilteredItemList.size();
+    Point aPoint = rMEvt.GetPosPixel();
+
+    for (size_t i = 0; i < nItemCount; i++)
+    {
+        ThumbnailViewItem *pItem = mFilteredItemList[i];
+        ::tools::Rectangle aToInvalidate(pItem->updateHighlight(pItem->mbVisible && !rMEvt.IsLeaveWindow(), aPoint));
+        if (!aToInvalidate.IsEmpty() && IsReallyVisible() && IsUpdateMode())
+            Invalidate(aToInvalidate);
+    }
+
+    return true;
+}
+
+OUString SfxThumbnailView::RequestHelp(tools::Rectangle& rHelpRect)
+{
+    if (!mbShowTooltips)
+        return OUString();
+
+    Point aPos = rHelpRect.TopLeft();
+    size_t nItemCount = mFilteredItemList.size();
+    for (size_t i = 0; i < nItemCount; i++)
+    {
+        ThumbnailViewItem *pItem = mFilteredItemList[i];
+        if (!pItem->mbVisible)
+            continue;
+        const tools::Rectangle& rDrawArea = pItem->getDrawArea();
+        if (pItem->mbVisible && rDrawArea.IsInside(aPos))
+        {
+            rHelpRect = rDrawArea;
+            return pItem->getHelpText();
+        }
+    }
+
+    return OUString();
+}
+
+void SfxThumbnailView::AppendItem(std::unique_ptr<ThumbnailViewItem> pItem)
+{
+    if (maFilterFunc(pItem.get()))
+    {
+        // Save current start,end range, iterator might get invalidated
+        size_t nSelStartPos = 0;
+        ThumbnailViewItem *pSelStartItem = nullptr;
+
+        if (mpStartSelRange != mFilteredItemList.end())
+        {
+            pSelStartItem = *mpStartSelRange;
+            nSelStartPos = mpStartSelRange - mFilteredItemList.begin();
+        }
+
+        mFilteredItemList.push_back(pItem.get());
+        mpStartSelRange = pSelStartItem != nullptr ? mFilteredItemList.begin() + nSelStartPos : mFilteredItemList.end();
+    }
+
+    mItemList.push_back(std::move(pItem));
+}
+
+void SfxThumbnailView::ImplInit()
+{
+    mnItemWidth = 0;
+    mnItemHeight = 0;
+    mnItemPadding = 0;
+    mnVisLines = 0;
+    mnLines = 0;
+    mnFirstLine = 0;
+    mnCols = 0;
+    mbScroll = false;
+    mbHasVisibleItems = false;
+    mbShowTooltips = false;
+    mbIsMultiSelectionEnabled = true;
+    maFilterFunc = ViewFilterAll();
+
+    const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
+    maFillColor = rSettings.GetFieldColor();
+    maTextColor = rSettings.GetWindowTextColor();
+    maHighlightColor = rSettings.GetHighlightColor();
+    maHighlightTextColor = rSettings.GetWindowTextColor();
+    maSelectHighlightColor = rSettings.GetActiveColor();
+    maSelectHighlightTextColor = rSettings.GetActiveTextColor();
+
+    const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
+    mfHighlightTransparence = aSvtOptionsDrawinglayer.GetTransparentSelectionPercent() * 0.01;
+
+    mpStartSelRange = mFilteredItemList.end();
+
+    mpItemAttrs->aFillColor = maFillColor.getBColor();
+    mpItemAttrs->aTextColor = maTextColor.getBColor();
+    mpItemAttrs->aHighlightColor = maHighlightColor.getBColor();
+    mpItemAttrs->aHighlightTextColor = maHighlightTextColor.getBColor();
+    mpItemAttrs->aSelectHighlightColor = maSelectHighlightColor.getBColor();
+    mpItemAttrs->aSelectHighlightTextColor = maSelectHighlightTextColor.getBColor();
+    mpItemAttrs->fHighlightTransparence = mfHighlightTransparence;
+
+    mpItemAttrs->nMaxTextLength = 0;
+}
+
+void SfxThumbnailView::ImplDeleteItems()
+{
+    const size_t n = mItemList.size();
+
+    for ( size_t i = 0; i < n; ++i )
+    {
+        ThumbnailViewItem *const pItem = mItemList[i].get();
+
+        // deselect all current selected items and fire events
+        if (pItem->isSelected())
+        {
+            pItem->setSelection(false);
+            maItemStateHdl.Call(pItem);
+
+            // fire accessible event???
+        }
+
+        if ( pItem->isVisible() && ImplHasAccessibleListeners() )
+        {
+            css::uno::Any aOldAny, aNewAny;
+
+            aOldAny <<= pItem->GetAccessible( false );
+            ImplFireAccessibleEvent( css::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
+        }
+
+        mItemList[i].reset();
+    }
+
+    mItemList.clear();
+    mFilteredItemList.clear();
+
+    mpStartSelRange = mFilteredItemList.end();
+}
+
+void SfxThumbnailView::DrawItem(ThumbnailViewItem const *pItem)
+{
+    if (pItem->isVisible())
+    {
+        ::tools::Rectangle aRect = pItem->getDrawArea();
+
+        if ((aRect.GetHeight() > 0) && (aRect.GetWidth() > 0))
+            Invalidate(aRect);
+    }
+}
+
+void SfxThumbnailView::OnItemDblClicked (ThumbnailViewItem*)
+{
+}
+
+css::uno::Reference< css::accessibility::XAccessible > SfxThumbnailView::CreateAccessible()
+{
+    mxAccessible.set(new SfxThumbnailViewAcc(this));
+    return mxAccessible;
+}
+
+css::uno::Reference< css::accessibility::XAccessible > SfxThumbnailView::getAccessible()
+{
+    return mxAccessible;
+}
+
+void SfxThumbnailView::CalculateItemPositions(bool bScrollBarUsed)
+{
+    if (!mnItemHeight || !mnItemWidth)
+        return;
+
+    Size        aWinSize = GetOutputSizePixel();
+    size_t      nItemCount = mFilteredItemList.size();
+
+    // calculate window scroll ratio
+    float nScrollRatio;
+    if (bScrollBarUsed)
+        nScrollRatio = static_cast<float>(mxScrolledWindow->vadjustment_get_value()) /
+                        static_cast<float>(mxScrolledWindow->vadjustment_get_upper()-2);
+    else
+        nScrollRatio = 0;
+
+    // calculate ScrollBar width
+    long nScrBarWidth = mxScrolledWindow->get_vscroll_width();
+
+    // calculate maximum number of visible columns
+    mnCols = static_cast<sal_uInt16>((aWinSize.Width()-nScrBarWidth) / mnItemWidth);
+
+    if (!mnCols)
+        mnCols = 1;
+
+    // calculate maximum number of visible rows
+    mnVisLines = static_cast<sal_uInt16>(aWinSize.Height() / mnItemHeight);
+
+    // calculate empty space
+    long nHSpace = aWinSize.Width()-nScrBarWidth - mnCols*mnItemWidth;
+    long nVSpace = aWinSize.Height() - mnVisLines*mnItemHeight;
+    long nHItemSpace = nHSpace / (mnCols+1);
+    long nVItemSpace = nVSpace / (mnVisLines+1);
+
+    // calculate maximum number of rows
+    // Floor( (M+N-1)/N )==Ceiling( M/N )
+    mnLines = (static_cast<long>(nItemCount)+mnCols-1) / mnCols;
+
+    if ( !mnLines )
+        mnLines = 1;
+
+    if ( mnLines <= mnVisLines )
+        mnFirstLine = 0;
+    else if ( mnFirstLine > static_cast<sal_uInt16>(mnLines-mnVisLines) )
+        mnFirstLine = static_cast<sal_uInt16>(mnLines-mnVisLines);
+
+    mbHasVisibleItems = true;
+
+    long nItemHeightOffset = mnItemHeight + nVItemSpace;
+    long nHiddenLines = (static_cast<long>(
+        ( mnLines - 1 ) * nItemHeightOffset * nScrollRatio ) -
+        nVItemSpace ) /
+        nItemHeightOffset;
+
+    // calculate offsets
+    long nStartX = nHItemSpace;
+    long nStartY = nVItemSpace;
+
+    // calculate and draw items
+    long x = nStartX;
+    long y = nStartY - ( mnLines - 1 ) * nItemHeightOffset * nScrollRatio +
+        nHiddenLines * nItemHeightOffset;
+
+    // draw items
+    // Unless we are scrolling (via scrollbar) we just use the precalculated
+    // mnFirstLine -- our nHiddenLines calculation takes into account only
+    // what the user has done with the scrollbar but not any changes of selection
+    // using the keyboard, meaning we could accidentally hide the selected item
+    // if we believe the scrollbar (fdo#72287).
+    size_t nFirstItem = (bScrollBarUsed ? nHiddenLines : mnFirstLine) * mnCols;
+    size_t nLastItem = nFirstItem + (mnVisLines + 1) * mnCols;
+
+    // If want also draw parts of items in the last line,
+    // then we add one more line if parts of these line are
+    // visible
+
+    size_t nCurCount = 0;
+    for ( size_t i = 0; i < nItemCount; i++ )
+    {
+        ThumbnailViewItem *const pItem = mFilteredItemList[i];
+
+        if ((nCurCount >= nFirstItem) && (nCurCount < nLastItem))
+        {
+            if( !pItem->isVisible())
+            {
+                if ( ImplHasAccessibleListeners() )
+                {
+                    css::uno::Any aOldAny, aNewAny;
+
+                    aNewAny <<= pItem->GetAccessible( false );
+                    ImplFireAccessibleEvent( css::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
+                }
+
+                pItem->show(true);
+
+                maItemStateHdl.Call(pItem);
+            }
+
+            pItem->setDrawArea(::tools::Rectangle( Point(x,y), Size(mnItemWidth, mnItemHeight) ));
+            pItem->calculateItemsPosition(mnThumbnailHeight,mnDisplayHeight,mnItemPadding,mpItemAttrs->nMaxTextLength,mpItemAttrs.get());
+
+            if ( !((nCurCount+1) % mnCols) )
+            {
+                x = nStartX;
+                y += mnItemHeight+nVItemSpace;
+            }
+            else
+                x += mnItemWidth+nHItemSpace;
+        }
+        else
+        {
+            if( pItem->isVisible())
+            {
+                if ( ImplHasAccessibleListeners() )
+                {
+                    css::uno::Any aOldAny, aNewAny;
+
+                    aOldAny <<= pItem->GetAccessible( false );
+                    ImplFireAccessibleEvent( css::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
+                }
+
+                pItem->show(false);
+
+                maItemStateHdl.Call(pItem);
+            }
+
+        }
+
+        ++nCurCount;
+    }
+
+    // arrange ScrollBar, set values and show it
+    mnLines = (nCurCount+mnCols-1)/mnCols;
+
+    // check if scroll is needed
+    mbScroll = mnLines > mnVisLines;
+
+    mxScrolledWindow->vadjustment_set_upper((nCurCount+mnCols-1)*gnFineness/mnCols);
+    mxScrolledWindow->vadjustment_set_page_size(mnVisLines);
+    if (!bScrollBarUsed)
+        mxScrolledWindow->vadjustment_set_value(static_cast<long>(mnFirstLine)*gnFineness);
+    long nPageSize = mnVisLines;
+    if ( nPageSize < 1 )
+        nPageSize = 1;
+    mxScrolledWindow->vadjustment_set_page_increment(nPageSize);
+    mxScrolledWindow->set_vpolicy(mbScroll ? VclPolicyType::ALWAYS : VclPolicyType::NEVER);
+}
+
+size_t SfxThumbnailView::ImplGetItem( const Point& rPos ) const
+{
+    if ( !mbHasVisibleItems )
+    {
+        return THUMBNAILVIEW_ITEM_NOTFOUND;
+    }
+
+    for (size_t i = 0; i < mFilteredItemList.size(); ++i)
+    {
+        if (mFilteredItemList[i]->isVisible() && mFilteredItemList[i]->getDrawArea().IsInside(rPos))
+            return i;
+    }
+
+    return THUMBNAILVIEW_ITEM_NOTFOUND;
+}
+
+ThumbnailViewItem* SfxThumbnailView::ImplGetItem( size_t nPos )
+{
+    return ( nPos < mFilteredItemList.size() ) ? mFilteredItemList[nPos] : nullptr;
+}
+
+sal_uInt16 SfxThumbnailView::ImplGetVisibleItemCount() const
+{
+    sal_uInt16 nRet = 0;
+    const size_t nItemCount = mItemList.size();
+
+    for ( size_t n = 0; n < nItemCount; ++n )
+    {
+        if ( mItemList[n]->isVisible() )
+            ++nRet;
+    }
+
+    return nRet;
+}
+
+ThumbnailViewItem* SfxThumbnailView::ImplGetVisibleItem( sal_uInt16 nVisiblePos )
+{
+    const size_t nItemCount = mItemList.size();
+
+    for ( size_t n = 0; n < nItemCount; ++n )
+    {
+        ThumbnailViewItem *const pItem = mItemList[n].get();
+
+        if ( pItem->isVisible() && !nVisiblePos-- )
+            return pItem;
+    }
+
+    return nullptr;
+}
+
+void SfxThumbnailView::ImplFireAccessibleEvent( short nEventId, const css::uno::Any& rOldValue, const css::uno::Any& rNewValue )
+{
+    ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation(mxAccessible);
+
+    if( pAcc )
+        pAcc->FireAccessibleEvent( nEventId, rOldValue, rNewValue );
+}
+
+bool SfxThumbnailView::ImplHasAccessibleListeners()
+{
+    ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation(mxAccessible);
+    return( pAcc && pAcc->HasAccessibleListeners() );
+}
+
+IMPL_LINK_NOARG(SfxThumbnailView, ImplScrollHdl, weld::ScrolledWindow&, void)
+{
+    CalculateItemPositions(true);
+    if (IsReallyVisible() && IsUpdateMode())
+        Invalidate();
+}
+
+bool SfxThumbnailView::KeyInput( const KeyEvent& rKEvt )
+{
+    bool bHandled = true;
+
+    // Get the last selected item in the list
+    size_t nLastPos = 0;
+    bool bFoundLast = false;
+    for ( long i = mFilteredItemList.size() - 1; !bFoundLast && i >= 0; --i )
+    {
+        ThumbnailViewItem* pItem = mFilteredItemList[i];
+        if ( pItem->isSelected() )
+        {
+            nLastPos = i;
+            bFoundLast = true;
+        }
+    }
+
+    bool bValidRange = false;
+    bool bHasSelRange = mpStartSelRange != mFilteredItemList.end();
+    size_t nNextPos = nLastPos;
+    vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
+    ThumbnailViewItem* pNext = nullptr;
+
+    if (aKeyCode.IsShift() && bHasSelRange)
+    {
+        //If the last element selected is the start range position
+        //search for the first selected item
+        size_t nSelPos = mpStartSelRange - mFilteredItemList.begin();
+
+        if (nLastPos == nSelPos)
+        {
+            while (nLastPos && mFilteredItemList[nLastPos-1]->isSelected())
+                --nLastPos;
+        }
+    }
+
+    switch ( aKeyCode.GetCode() )
+    {
+        case KEY_RIGHT:
+            if (!mFilteredItemList.empty())
+            {
+                if ( bFoundLast && nLastPos + 1 < mFilteredItemList.size() )
+                {
+                    bValidRange = true;
+                    nNextPos = nLastPos + 1;
+                }
+
+                pNext = mFilteredItemList[nNextPos];
+            }
+            break;
+        case KEY_LEFT:
+            if (!mFilteredItemList.empty())
+            {
+                if ( nLastPos > 0 )
+                {
+                    bValidRange = true;
+                    nNextPos = nLastPos - 1;
+                }
+
+                pNext = mFilteredItemList[nNextPos];
+            }
+            break;
+        case KEY_DOWN:
+            if (!mFilteredItemList.empty())
+            {
+                if ( bFoundLast )
+                {
+                    //If we are in the second last row just go the one in
+                    //the row below, if there's not row below just go to the
+                    //last item but for the last row don't do anything.
+                    if ( nLastPos + mnCols < mFilteredItemList.size( ) )
+                    {
+                        bValidRange = true;
+                        nNextPos = nLastPos + mnCols;
+                    }
+                    else
+                    {
+                        int curRow = nLastPos/mnCols;
+
+                        if (curRow < mnLines-1)
+                            nNextPos = mFilteredItemList.size()-1;
+                    }
+                }
+
+                pNext = mFilteredItemList[nNextPos];
+            }
+            break;
+        case KEY_UP:
+            if (!mFilteredItemList.empty())
+            {
+                if ( nLastPos >= mnCols )
+                {
+                    bValidRange = true;
+                    nNextPos = nLastPos - mnCols;
+                }
+
+                pNext = mFilteredItemList[nNextPos];
+            }
+            break;
+        case KEY_RETURN:
+            {
+                if ( bFoundLast )
+                    OnItemDblClicked( mFilteredItemList[nLastPos] );
+            }
+            [[fallthrough]];
+        default:
+            bHandled = CustomWidgetController::KeyInput(rKEvt);
+    }
+
+    if ( pNext  && mbIsMultiSelectionEnabled)
+    {
+        if (aKeyCode.IsShift() && bValidRange)
+        {
+            std::pair<size_t,size_t> aRange;
+            size_t nSelPos = mpStartSelRange - mFilteredItemList.begin();
+
+            if (nLastPos < nSelPos)
+            {
+                if (nNextPos > nLastPos)
+                {
+                    if ( nNextPos > nSelPos)
+                        aRange = std::make_pair(nLastPos,nNextPos);
+                    else
+                        aRange = std::make_pair(nLastPos,nNextPos-1);
+                }
+                else
+                    aRange = std::make_pair(nNextPos,nLastPos-1);
+            }
+            else if (nLastPos == nSelPos)
+            {
+                if (nNextPos > nLastPos)
+                    aRange = std::make_pair(nLastPos+1,nNextPos);
+                else
+                    aRange = std::make_pair(nNextPos,nLastPos-1);
+            }
+            else
+            {
+                if (nNextPos > nLastPos)
+                    aRange = std::make_pair(nLastPos+1,nNextPos);
+                else
+                {
+                    if ( nNextPos < nSelPos)
+                        aRange = std::make_pair(nNextPos,nLastPos);
+                    else
+                        aRange = std::make_pair(nNextPos+1,nLastPos);
+                }
+            }
+
+            for (size_t i = aRange.first; i <= aRange.second; ++i)
+            {
+                if (i != nSelPos)
+                {
+                    ThumbnailViewItem *pCurItem = mFilteredItemList[i];
+
+                    pCurItem->setSelection(!pCurItem->isSelected());
+
+                    if (pCurItem->isVisible())
+                        DrawItem(pCurItem);
+
+                    maItemStateHdl.Call(pCurItem);
+                }
+            }
+        }
+        else if (!aKeyCode.IsShift())
+        {
+            deselectItems();
+            SelectItem(pNext->mnId);
+
+            //Mark it as the selection range start position
+            mpStartSelRange = mFilteredItemList.begin() + nNextPos;
+        }
+
+        MakeItemVisible(pNext->mnId);
+    }
+    else if(pNext && !mbIsMultiSelectionEnabled)
+    {
+        deselectItems();
+        SelectItem(pNext->mnId);
+        MakeItemVisible(pNext->mnId);
+    }
+    return bHandled;
+}
+
+void SfxThumbnailView::MakeItemVisible( sal_uInt16 nItemId )
+{
+    // Get the item row
+    size_t nPos = 0;
+    bool bFound = false;
+    for ( size_t i = 0; !bFound && i < mFilteredItemList.size(); ++i )
+    {
+        ThumbnailViewItem* pItem = mFilteredItemList[i];
+        if ( pItem->mnId == nItemId )
+        {
+            nPos = i;
+            bFound = true;
+        }
+    }
+    sal_uInt16 nRow = mnCols ? nPos / mnCols : 0;
+
+    // Move the visible rows as little as possible to include that one
+    if ( nRow < mnFirstLine )
+        mnFirstLine = nRow;
+    else if ( nRow > mnFirstLine + mnVisLines )
+        mnFirstLine = nRow - mnVisLines;
+
+    CalculateItemPositions();
+    Invalidate();
+}
+
+bool SfxThumbnailView::MouseButtonDown( const MouseEvent& rMEvt )
+{
+    if (!rMEvt.IsLeft())
+    {
+        return CustomWidgetController::MouseButtonDown( rMEvt );
+    }
+
+    size_t nPos = ImplGetItem(rMEvt.GetPosPixel());
+    ThumbnailViewItem* pItem = ImplGetItem(nPos);
+
+    if ( !pItem )
+    {
+        deselectItems();
+        return CustomWidgetController::MouseButtonDown( rMEvt );
+    }
+
+    if ( rMEvt.GetClicks() == 2 )
+    {
+        OnItemDblClicked(pItem);
+        return true;
+    }
+
+    if ( rMEvt.GetClicks() == 1 && !mbIsMultiSelectionEnabled )
+    {
+        deselectItems();
+        pItem->setSelection(!pItem->isSelected());
+
+        if (!pItem->isHighlighted())
+            DrawItem(pItem);
+
+        maItemStateHdl.Call(pItem);
+    }
+    else if(rMEvt.GetClicks() == 1)
+    {
+        if (rMEvt.IsMod1())
+        {
+            //Keep selected item group state and just invert current desired one state
+            pItem->setSelection(!pItem->isSelected());
+
+            //This one becomes the selection range start position if it changes its state to selected otherwise resets it
+            mpStartSelRange = pItem->isSelected() ? mFilteredItemList.begin() + nPos : mFilteredItemList.end();
+        }
+        else if (rMEvt.IsShift() && mpStartSelRange != mFilteredItemList.end())
+        {
+            std::pair<size_t,size_t> aNewRange;
+            aNewRange.first = mpStartSelRange - mFilteredItemList.begin();
+            aNewRange.second = nPos;
+
+            if (aNewRange.first > aNewRange.second)
+                std::swap(aNewRange.first,aNewRange.second);
+
+            //Deselect the ones outside of it
+            for (size_t i = 0, n = mFilteredItemList.size(); i < n; ++i)
+            {
+                ThumbnailViewItem *pCurItem  = mFilteredItemList[i];
+
+                if (pCurItem->isSelected() && (i < aNewRange.first || i > aNewRange.second))
+                {
+                    pCurItem->setSelection(false);
+
+                    if (pCurItem->isVisible())
+                        DrawItem(pCurItem);
+
+                    maItemStateHdl.Call(pCurItem);
+                }
+            }
+
+            size_t nSelPos = mpStartSelRange - mFilteredItemList.begin();
+
+            //Select the items between start range and the selected item
+            if (nSelPos != nPos)
+            {
+                int dir = nSelPos < nPos ? 1 : -1;
+                size_t nCurPos = nSelPos + dir;
+
+                while (nCurPos != nPos)
+                {
+                    ThumbnailViewItem *pCurItem  = mFilteredItemList[nCurPos];
+
+                    if (!pCurItem->isSelected())
+                    {
+                        pCurItem->setSelection(true);
+
+                        if (pCurItem->isVisible())
+                            DrawItem(pCurItem);
+
+                        maItemStateHdl.Call(pCurItem);
+                    }
+
+                    nCurPos += dir;
+                }
+            }
+
+            pItem->setSelection(true);
+        }
+        else
+        {
+            //If we got a group of selected items deselect the rest and only keep the desired one
+            //mark items as not selected to not fire unnecessary change state events.
+            pItem->setSelection(false);
+            deselectItems();
+            pItem->setSelection(true);
+
+            //Mark as initial selection range position and reset end one
+            mpStartSelRange = mFilteredItemList.begin() + nPos;
+        }
+
+        if (!pItem->isHighlighted())
+            DrawItem(pItem);
+
+        maItemStateHdl.Call(pItem);
+
+        //fire accessible event??
+    }
+    return true;
+}
+
+void SfxThumbnailView::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+    CustomWidgetController::SetDrawingArea(pDrawingArea);
+
+    if (vcl::Window* pDefaultDevice = dynamic_cast<vcl::Window*>(Application::GetDefaultDevice()))
+    {
+        OutputDevice& rDevice = pDrawingArea->get_ref_device();
+        pDefaultDevice->SetPointFont(rDevice, pDrawingArea->get_font());
+        mpItemAttrs->aFontAttr = getFontAttributeFromVclFont(mpItemAttrs->aFontSize, rDevice.GetFont(), false, true);
+    }
+
+    SetOutputSizePixel(pDrawingArea->get_preferred_size());
+}
+
+void SfxThumbnailView::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& /*rRect*/)
+{

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list