[Libreoffice-commits] core.git: include/vcl vcl/inc vcl/source vcl/unx
Caolán McNamara (via logerrit)
logerrit at kemper.freedesktop.org
Tue Jun 2 14:21:01 UTC 2020
include/vcl/treelistentry.hxx | 4 -
include/vcl/weld.hxx | 3
vcl/inc/strings.hrc | 2
vcl/source/app/salvtables.cxx | 121 ++++++++++++++++++++++++----------------
vcl/source/treelist/svlbitm.cxx | 33 ++++++++++
vcl/unx/gtk3/gtk3gtkinst.cxx | 79 +++++++++++++++++++-------
6 files changed, 171 insertions(+), 71 deletions(-)
New commits:
commit 9b498e2b88ffae77717bab2f7a308b83d0a7ae80
Author: Caolán McNamara <caolanm at redhat.com>
AuthorDate: Mon Jun 1 10:39:30 2020 +0100
Commit: Caolán McNamara <caolanm at redhat.com>
CommitDate: Tue Jun 2 16:20:18 2020 +0200
add separators to TreeView
Change-Id: I5e49913dfac82c1243d16ed0a0267a3647f51311
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95270
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm at redhat.com>
diff --git a/include/vcl/treelistentry.hxx b/include/vcl/treelistentry.hxx
index 8cc808bb09c1..093fa1751d8e 100644
--- a/include/vcl/treelistentry.hxx
+++ b/include/vcl/treelistentry.hxx
@@ -39,13 +39,15 @@ enum class SvTLEntryFlags
DISABLE_DROP = 0x0002,
// is set if RequestingChildren has not set any children
NO_NODEBMP = 0x0004,
+ // is set if this is a separator line
+ IS_SEPARATOR = 0x0008,
// entry had or has children
HAD_CHILDREN = 0x0010,
SEMITRANSPARENT = 0x8000, // draw semi-transparent entry bitmaps
};
namespace o3tl
{
- template<> struct typed_flags<SvTLEntryFlags> : is_typed_flags<SvTLEntryFlags, 0x8017> {};
+ template<> struct typed_flags<SvTLEntryFlags> : is_typed_flags<SvTLEntryFlags, 0x801f> {};
}
class VCL_DLLPUBLIC SvTreeListEntry
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 9d01a0fc7022..d8d6b1a0492d 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -888,6 +888,9 @@ public:
insert(nullptr, -1, &rStr, &rId, nullptr, &rImage, nullptr, false, nullptr);
}
+ virtual void insert_separator(int pos, const OUString& rId) = 0;
+ void append_separator(const OUString& rId) { insert_separator(-1, rId); }
+
void connect_changed(const Link<TreeView&, void>& rLink) { m_aChangeHdl = rLink; }
/* A row is "activated" when the user double clicks a treeview row. It may
diff --git a/vcl/inc/strings.hrc b/vcl/inc/strings.hrc
index e378b54814bd..d97ef387d9f4 100644
--- a/vcl/inc/strings.hrc
+++ b/vcl/inc/strings.hrc
@@ -153,6 +153,8 @@
#define STR_WIZDLG_NEXT NC_("STR_WIZDLG_NEXT", "~Next >")
#define STR_WIZDLG_PREVIOUS NC_("STR_WIZDLG_PREVIOUS", "< Bac~k")
+#define STR_SEPARATOR NC_("STR_SEPARATOR", "Separator")
+
#endif // INCLUDED_VCL_INC_STRINGS_HRC
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 1f0c05e292db..2b0e1c9c28cb 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -3258,6 +3258,71 @@ private:
pEntry->AddItem(std::move(xCell));
}
+ void do_insert(const weld::TreeIter* pParent, int pos, const OUString* pStr,
+ const OUString* pId, const OUString* pIconName,
+ VirtualDevice* pImageSurface, const OUString* pExpanderName,
+ bool bChildrenOnDemand, weld::TreeIter* pRet, bool bIsSeparator)
+ {
+ disable_notify_events();
+ const SalInstanceTreeIter* pVclIter = static_cast<const SalInstanceTreeIter*>(pParent);
+ SvTreeListEntry* iter = pVclIter ? pVclIter->iter : nullptr;
+ auto nInsertPos = pos == -1 ? TREELIST_APPEND : pos;
+ void* pUserData;
+ if (pId)
+ {
+ m_aUserData.emplace_back(std::make_unique<OUString>(*pId));
+ pUserData = m_aUserData.back().get();
+ }
+ else
+ pUserData = nullptr;
+
+ SvTreeListEntry* pEntry = new SvTreeListEntry;
+ if (bIsSeparator)
+ pEntry->SetFlags(pEntry->GetFlags() | SvTLEntryFlags::IS_SEPARATOR);
+ if (pIconName || pImageSurface)
+ {
+ Image aImage(pIconName ? createImage(*pIconName) : createImage(*pImageSurface));
+ pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aImage, aImage, false));
+ }
+ else
+ {
+ Image aDummy;
+ pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
+ }
+ if (pStr)
+ AddStringItem(pEntry, *pStr, 0);
+ pEntry->SetUserData(pUserData);
+ m_xTreeView->Insert(pEntry, iter, nInsertPos);
+
+ if (pExpanderName)
+ {
+ Image aImage(createImage(*pExpanderName));
+ m_xTreeView->SetExpandedEntryBmp(pEntry, aImage);
+ m_xTreeView->SetCollapsedEntryBmp(pEntry, aImage);
+ }
+
+ if (pRet)
+ {
+ SalInstanceTreeIter* pVclRetIter = static_cast<SalInstanceTreeIter*>(pRet);
+ pVclRetIter->iter = pEntry;
+ }
+
+ if (bChildrenOnDemand)
+ {
+ SvTreeListEntry* pPlaceHolder = m_xTreeView->InsertEntry("<dummy>", pEntry, false, 0, nullptr);
+ SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pPlaceHolder);
+ pViewData->SetSelectable(false);
+ }
+
+ if (bIsSeparator)
+ {
+ SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
+ pViewData->SetSelectable(false);
+ }
+
+ enable_notify_events();
+ }
+
public:
SalInstanceTreeView(SvTabListBox* pTreeView, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
: SalInstanceContainer(pTreeView, pBuilder, bTakeOwnership)
@@ -3433,55 +3498,15 @@ public:
VirtualDevice* pImageSurface, const OUString* pExpanderName,
bool bChildrenOnDemand, weld::TreeIter* pRet) override
{
- disable_notify_events();
- const SalInstanceTreeIter* pVclIter = static_cast<const SalInstanceTreeIter*>(pParent);
- SvTreeListEntry* iter = pVclIter ? pVclIter->iter : nullptr;
- auto nInsertPos = pos == -1 ? TREELIST_APPEND : pos;
- void* pUserData;
- if (pId)
- {
- m_aUserData.emplace_back(std::make_unique<OUString>(*pId));
- pUserData = m_aUserData.back().get();
- }
- else
- pUserData = nullptr;
-
- SvTreeListEntry* pEntry = new SvTreeListEntry;
- if (pIconName || pImageSurface)
- {
- Image aImage(pIconName ? createImage(*pIconName) : createImage(*pImageSurface));
- pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aImage, aImage, false));
- }
- else
- {
- Image aDummy;
- pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
- }
- if (pStr)
- AddStringItem(pEntry, *pStr, 0);
- pEntry->SetUserData(pUserData);
- m_xTreeView->Insert(pEntry, iter, nInsertPos);
-
- if (pExpanderName)
- {
- Image aImage(createImage(*pExpanderName));
- m_xTreeView->SetExpandedEntryBmp(pEntry, aImage);
- m_xTreeView->SetCollapsedEntryBmp(pEntry, aImage);
- }
-
- if (pRet)
- {
- SalInstanceTreeIter* pVclRetIter = static_cast<SalInstanceTreeIter*>(pRet);
- pVclRetIter->iter = pEntry;
- }
+ do_insert(pParent, pos, pStr, pId, pIconName, pImageSurface, pExpanderName,
+ bChildrenOnDemand, pRet, false);
+ }
- if (bChildrenOnDemand)
- {
- SvTreeListEntry* pPlaceHolder = m_xTreeView->InsertEntry("<dummy>", pEntry, false, 0, nullptr);
- SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pPlaceHolder);
- pViewData->SetSelectable(false);
- }
- enable_notify_events();
+ virtual void insert_separator(int pos, const OUString& /*rId*/) override
+ {
+ OUString sSep(VclResId(STR_SEPARATOR));
+ do_insert(nullptr, pos, &sSep, nullptr, nullptr, nullptr, nullptr,
+ false, nullptr, true);
}
virtual void
diff --git a/vcl/source/treelist/svlbitm.cxx b/vcl/source/treelist/svlbitm.cxx
index da5074283545..6467efcbf8ff 100644
--- a/vcl/source/treelist/svlbitm.cxx
+++ b/vcl/source/treelist/svlbitm.cxx
@@ -25,6 +25,7 @@
#include <vcl/toolkit/button.hxx>
#include <vcl/decoview.hxx>
#include <vcl/salnativewidgets.hxx>
+#include <vcl/settings.hxx>
struct SvLBoxButtonData_Impl
{
@@ -196,12 +197,35 @@ SvLBoxItemType SvLBoxString::GetType() const
return SvLBoxItemType::String;
}
+namespace
+{
+ void drawSeparator(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRegion)
+ {
+ Color aOldLineColor(rRenderContext.GetLineColor());
+ const StyleSettings& rStyle = rRenderContext.GetSettings().GetStyleSettings();
+ Point aTmpPos = rRegion.TopLeft();
+ Size aSize = rRegion.GetSize();
+ aTmpPos.AdjustY(aSize.Height() / 2 );
+ rRenderContext.SetLineColor(rStyle.GetShadowColor());
+ rRenderContext.DrawLine(aTmpPos, Point(aSize.Width() + aTmpPos.X(), aTmpPos.Y()));
+ rRenderContext.SetLineColor(aOldLineColor);
+ }
+}
+
void SvLBoxString::Paint(
const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
const SvViewDataEntry* /*pView*/, const SvTreeListEntry& rEntry)
{
- Size aSize;
DrawTextFlags nStyle = (rDev.IsEnabled() && !mbDisabled) ? DrawTextFlags::NONE : DrawTextFlags::Disable;
+ if (bool(rEntry.GetFlags() & SvTLEntryFlags::IS_SEPARATOR))
+ {
+ Point aStartPos(0, rPos.Y() - 2);
+ tools::Rectangle aRegion(aStartPos, Size(rDev.GetSizePixel().Width(), 4));
+ drawSeparator(rRenderContext, aRegion);
+ return;
+ }
+
+ Size aSize;
if (rDev.IsEntryMnemonicsEnabled())
nStyle |= DrawTextFlags::Mnemonic;
if (rDev.TextCenterAndClipEnabled())
@@ -267,6 +291,13 @@ void SvLBoxString::InitViewData(
if( !pViewData )
pViewData = pView->GetViewDataItem( pEntry, this );
+ if (bool(pEntry->GetFlags() & SvTLEntryFlags::IS_SEPARATOR))
+ {
+ pViewData->mnWidth = -1;
+ pViewData->mnHeight = 0;
+ return;
+ }
+
if (mbEmphasized)
{
pView->Push();
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index c0bc216f0011..7e851797806c 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -9050,6 +9050,31 @@ tools::Rectangle get_row_area(GtkTreeView* pTreeView, GList* pColumns, GtkTreePa
return aRet;
}
+struct GtkTreeRowReferenceDeleter
+{
+ void operator()(GtkTreeRowReference* p) const
+ {
+ gtk_tree_row_reference_free(p);
+ }
+};
+
+bool separator_function(GtkTreePath* path, const std::vector<std::unique_ptr<GtkTreeRowReference, GtkTreeRowReferenceDeleter>>& rSeparatorRows)
+{
+ bool bFound = false;
+ for (auto& a : rSeparatorRows)
+ {
+ GtkTreePath* seppath = gtk_tree_row_reference_get_path(a.get());
+ if (seppath)
+ {
+ bFound = gtk_tree_path_compare(path, seppath) == 0;
+ gtk_tree_path_free(seppath);
+ }
+ if (bFound)
+ break;
+ }
+ return bFound;
+}
+
class GtkInstanceTreeView : public GtkInstanceContainer, public virtual weld::TreeView
{
private:
@@ -9073,6 +9098,8 @@ private:
// currently expanding parent that logically, but not currently physically,
// contain placeholders
o3tl::sorted_vector<GtkTreePath*, CompareGtkTreePath> m_aExpandingPlaceHolderParents;
+ // which rows are separators (rare)
+ std::vector<std::unique_ptr<GtkTreeRowReference, GtkTreeRowReferenceDeleter>> m_aSeparatorRows;
std::vector<GtkSortType> m_aSavedSortTypes;
std::vector<int> m_aSavedSortColumns;
std::vector<int> m_aViewColToModelCol;
@@ -9183,6 +9210,20 @@ private:
}
}
+ bool separator_function(GtkTreePath* path)
+ {
+ return ::separator_function(path, m_aSeparatorRows);
+ }
+
+ static gboolean separatorFunction(GtkTreeModel* pTreeModel, GtkTreeIter* pIter, gpointer widget)
+ {
+ GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget);
+ GtkTreePath* path = gtk_tree_model_get_path(pTreeModel, pIter);
+ bool bRet = pThis->separator_function(path);
+ gtk_tree_path_free(path);
+ return bRet;
+ }
+
OUString get(const GtkTreeIter& iter, int col) const
{
GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore);
@@ -9942,6 +9983,20 @@ public:
enable_notify_events();
}
+ virtual void insert_separator(int pos, const OUString& rId) override
+ {
+ disable_notify_events();
+ GtkTreeIter iter;
+ if (!gtk_tree_view_get_row_separator_func(m_pTreeView))
+ gtk_tree_view_set_row_separator_func(m_pTreeView, separatorFunction, this, nullptr);
+ insert_row(iter, nullptr, pos, &rId, nullptr, nullptr, nullptr, nullptr);
+ GtkTreeModel* pTreeModel = GTK_TREE_MODEL(m_pTreeStore);
+ GtkTreePath* pPath = gtk_tree_model_get_path(pTreeModel, &iter);
+ m_aSeparatorRows.emplace_back(gtk_tree_row_reference_new(pTreeModel, pPath));
+ gtk_tree_path_free(pPath);
+ enable_notify_events();
+ }
+
virtual void set_font_color(int pos, const Color& rColor) override
{
GtkTreeIter iter;
@@ -10018,6 +10073,8 @@ public:
virtual void clear() override
{
disable_notify_events();
+ gtk_tree_view_set_row_separator_func(m_pTreeView, nullptr, nullptr, nullptr);
+ m_aSeparatorRows.clear();
gtk_tree_store_clear(m_pTreeStore);
enable_notify_events();
}
@@ -12668,14 +12725,6 @@ GtkBuilder* makeComboBoxBuilder()
return gtk_builder_new_from_file(OUStringToOString(aPath, RTL_TEXTENCODING_UTF8).getStr());
}
-struct GtkTreeRowReferenceDeleter
-{
- void operator()(GtkTreeRowReference* p) const
- {
- gtk_tree_row_reference_free(p);
- }
-};
-
// pop down the toplevel combobox menu when something is activated from a custom
// submenu, i.e. wysiwyg style menu
class CustomRenderMenuButtonHelper : public MenuHelper
@@ -13077,19 +13126,7 @@ private:
bool separator_function(GtkTreePath* path)
{
- bool bFound = false;
- for (auto& a : m_aSeparatorRows)
- {
- GtkTreePath* seppath = gtk_tree_row_reference_get_path(a.get());
- if (seppath)
- {
- bFound = gtk_tree_path_compare(path, seppath) == 0;
- gtk_tree_path_free(seppath);
- }
- if (bFound)
- break;
- }
- return bFound;
+ return ::separator_function(path, m_aSeparatorRows);
}
bool separator_function(int pos)
More information about the Libreoffice-commits
mailing list