[Libreoffice-commits] core.git: 2 commits - include/vcl vcl/source vcl/unx
Caolán McNamara (via logerrit)
logerrit at kemper.freedesktop.org
Sat Apr 4 17:52:16 UTC 2020
include/vcl/svlbitm.hxx | 3
include/vcl/treelistbox.hxx | 11 +
include/vcl/weld.hxx | 26 ++
include/vcl/weldutils.hxx | 4
vcl/source/app/salvtables.cxx | 52 ++++-
vcl/source/treelist/svlbitm.cxx | 30 ++-
vcl/source/treelist/treelistbox.cxx | 10 +
vcl/source/window/builder.cxx | 19 +
vcl/unx/gtk3/gtk3gtkinst.cxx | 347 ++++++++++++++++++++++++++++++++++++
9 files changed, 493 insertions(+), 9 deletions(-)
New commits:
commit 338403833ec43539728d7609e243ae6070aafb3f
Author: Caolán McNamara <caolanm at redhat.com>
AuthorDate: Fri Apr 3 19:30:00 2020 +0100
Commit: Caolán McNamara <caolanm at redhat.com>
CommitDate: Sat Apr 4 19:51:52 2020 +0200
add ability to have custom renderer treeview rows
Change-Id: Ia085242dee0aaa19f9aefa2a3cf71bc827fcca73
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91658
Tested-by: Jenkins
Tested-by: Caolán McNamara <caolanm at redhat.com>
Reviewed-by: Caolán McNamara <caolanm at redhat.com>
diff --git a/include/vcl/svlbitm.hxx b/include/vcl/svlbitm.hxx
index dc8cde9bcb02..abe2446ade11 100644
--- a/include/vcl/svlbitm.hxx
+++ b/include/vcl/svlbitm.hxx
@@ -105,6 +105,7 @@ class VCL_DLLPUBLIC SvLBoxString : public SvLBoxItem
{
private:
bool mbEmphasized;
+ bool mbCustom;
double mfAlign;
protected:
OUString maText;
@@ -126,6 +127,8 @@ public:
void Emphasize(bool bEmphasize) { mbEmphasized = bEmphasize; }
bool IsEmphasized() const { return mbEmphasized; }
+ void SetCustomRender() { mbCustom = true; }
+
const OUString& GetText() const
{
return maText;
diff --git a/include/vcl/treelistbox.hxx b/include/vcl/treelistbox.hxx
index 179f27fe4cb6..e56fd1081fb2 100644
--- a/include/vcl/treelistbox.hxx
+++ b/include/vcl/treelistbox.hxx
@@ -177,6 +177,9 @@ namespace o3tl
struct SvTreeListBoxImpl;
+typedef std::pair<vcl::RenderContext&, const SvTreeListEntry&> svtree_measure_args;
+typedef std::tuple<vcl::RenderContext&, const tools::Rectangle&, const SvTreeListEntry&> svtree_render_args;
+
class VCL_DLLPUBLIC SvTreeListBox
:public Control
,public SvListView
@@ -186,6 +189,7 @@ class VCL_DLLPUBLIC SvTreeListBox
,public vcl::ISearchableStringList
{
friend class SvImpLBox;
+ friend class SvLBoxString;
friend class IconViewImpl;
friend class TreeControlPeer;
friend class SalInstanceIconView;
@@ -201,6 +205,8 @@ class VCL_DLLPUBLIC SvTreeListBox
Link<SvTreeListBox*,void> aDeselectHdl;
Link<const CommandEvent&, bool> aPopupMenuHdl;
Link<const HelpEvent&, bool> aTooltipHdl;
+ Link<svtree_render_args, void> aCustomRenderHdl;
+ Link<svtree_measure_args, Size> aCustomMeasureHdl;
Image aPrevInsertedExpBmp;
Image aPrevInsertedColBmp;
@@ -269,6 +275,9 @@ private:
// autowidth for the 1st checkbox column
VCL_DLLPRIVATE void CheckBoxInserted(SvTreeListEntry* pEntry);
+ VCL_DLLPRIVATE void DrawCustomEntry(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, const SvTreeListEntry& rEntry);
+ VCL_DLLPRIVATE Size MeasureCustomEntry(vcl::RenderContext& rRenderContext, const SvTreeListEntry& rEntry);
+
protected:
bool CheckDragAndDropMode( SvTreeListBox const * pSource, sal_Int8 );
@@ -434,6 +443,8 @@ public:
void SetExpandedHdl(const Link<SvTreeListBox*,void>& rNewHdl){aExpandedHdl=rNewHdl;}
void SetPopupMenuHdl(const Link<const CommandEvent&, bool>& rLink) { aPopupMenuHdl = rLink; }
void SetTooltipHdl(const Link<const HelpEvent&, bool>& rLink) { aTooltipHdl = rLink; }
+ void SetCustomRenderHdl(const Link<svtree_render_args, void>& rLink) { aCustomRenderHdl = rLink; }
+ void SetCustomMeasureHdl(const Link<svtree_measure_args, Size>& rLink) { aCustomMeasureHdl = rLink; }
virtual void ExpandedHdl();
virtual bool ExpandingHdl();
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 15dd5ad91de8..eda59f01783f 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -729,6 +729,12 @@ protected:
Link<bool&, bool> m_aDragBeginHdl;
std::function<int(const weld::TreeIter&, const weld::TreeIter&)> m_aCustomSort;
+public:
+ typedef std::pair<vcl::RenderContext&, const OUString&> get_size_args;
+ typedef std::tuple<vcl::RenderContext&, const tools::Rectangle&, bool, const OUString&>
+ render_args;
+
+protected:
std::vector<int> m_aRadioIndexes;
void signal_changed() { m_aChangeHdl.Call(*this); }
@@ -758,6 +764,21 @@ protected:
Link<const TreeIter&, OUString> m_aQueryTooltipHdl;
OUString signal_query_tooltip(const TreeIter& rIter) { return m_aQueryTooltipHdl.Call(rIter); }
+ Link<render_args, void> m_aRenderHdl;
+ void signal_custom_render(vcl::RenderContext& rDevice, const tools::Rectangle& rRect,
+ bool bSelected, const OUString& rId)
+ {
+ m_aRenderHdl.Call(
+ std::tuple<vcl::RenderContext&, const tools::Rectangle, bool, const OUString&>(
+ rDevice, rRect, bSelected, rId));
+ }
+
+ Link<get_size_args, Size> m_aGetSizeHdl;
+ Size signal_custom_get_size(vcl::RenderContext& rDevice, const OUString& rId)
+ {
+ return m_aGetSizeHdl.Call(std::pair<vcl::RenderContext&, const OUString&>(rDevice, rId));
+ }
+
public:
virtual void connect_query_tooltip(const Link<const TreeIter&, OUString>& rLink)
{
@@ -1068,6 +1089,11 @@ public:
OUString const& get_saved_value() const { return m_sSavedValue; }
bool get_value_changed_from_saved() const { return m_sSavedValue != get_selected_text(); }
+ // for custom rendering a cell
+ virtual void set_column_custom_renderer(int nColumn) = 0;
+ void connect_custom_get_size(const Link<get_size_args, Size>& rLink) { m_aGetSizeHdl = rLink; }
+ void connect_custom_render(const Link<render_args, void>& rLink) { m_aRenderHdl = rLink; }
+
// for dnd
virtual bool get_dest_row_at_pos(const Point& rPos, weld::TreeIter* pResult) = 0;
virtual tools::Rectangle get_row_area(const weld::TreeIter& rIter) const = 0;
diff --git a/include/vcl/weldutils.hxx b/include/vcl/weldutils.hxx
index 077dab0fa414..cb04f2d74915 100644
--- a/include/vcl/weldutils.hxx
+++ b/include/vcl/weldutils.hxx
@@ -153,7 +153,11 @@ public:
}
};
+// get the row the iterator is on
VCL_DLLPUBLIC size_t GetAbsPos(const weld::TreeView& rTreeView, const weld::TreeIter& rIter);
+
+// an entry is visible if all parents are expanded
+VCL_DLLPUBLIC bool IsEntryVisible(const weld::TreeView& rTreeView, const weld::TreeIter& rIter);
}
#endif
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index d43dda8ffec1..1ae61d3ee21a 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -3263,6 +3263,8 @@ private:
// currently expanding parent that logically, but not currently physically,
// contain placeholders
o3tl::sorted_vector<SvTreeListEntry*> m_aExpandingPlaceHolderParents;
+ // which columns should be custom rendered
+ o3tl::sorted_vector<int> m_aCustomRenders;
bool m_bDisableCheckBoxAutoWidth;
int m_nSortColumn;
@@ -3283,6 +3285,8 @@ private:
DECL_LINK(CompareHdl, const SvSortData&, sal_Int32);
DECL_LINK(PopupMenuHdl, const CommandEvent&, bool);
DECL_LINK(TooltipHdl, const HelpEvent&, bool);
+ DECL_LINK(CustomRenderHdl, svtree_render_args, void);
+ DECL_LINK(CustomMeasureHdl, svtree_measure_args, Size);
bool IsDummyEntry(SvTreeListEntry* pEntry) const
{
@@ -3309,6 +3313,14 @@ private:
pEntry->SetTextColor(rColor);
}
+ void AddStringItem(SvTreeListEntry* pEntry, const OUString& rStr, int nCol)
+ {
+ auto xCell = std::make_unique<SvLBoxString>(rStr);
+ if (m_aCustomRenders.count(nCol))
+ xCell->SetCustomRender();
+ pEntry->AddItem(std::move(xCell));
+ }
+
public:
SalInstanceTreeView(SvTabListBox* pTreeView, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
: SalInstanceContainer(pTreeView, pBuilder, bTakeOwnership)
@@ -3325,6 +3337,8 @@ public:
m_xTreeView->SetDoubleClickHdl(LINK(this, SalInstanceTreeView, DoubleClickHdl));
m_xTreeView->SetExpandingHdl(LINK(this, SalInstanceTreeView, ExpandingHdl));
m_xTreeView->SetPopupMenuHdl(LINK(this, SalInstanceTreeView, PopupMenuHdl));
+ m_xTreeView->SetCustomRenderHdl(LINK(this, SalInstanceTreeView, CustomRenderHdl));
+ m_xTreeView->SetCustomMeasureHdl(LINK(this, SalInstanceTreeView, CustomMeasureHdl));
const long aTabPositions[] = { 0 };
m_xTreeView->SetTabs(SAL_N_ELEMENTS(aTabPositions), aTabPositions);
LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get());
@@ -3452,6 +3466,11 @@ public:
}
}
+ virtual void set_column_custom_renderer(int nColumn) override
+ {
+ m_aCustomRenders.insert(nColumn);
+ }
+
virtual void show() override
{
if (LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()))
@@ -3496,7 +3515,7 @@ public:
pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
}
if (pStr)
- pEntry->AddItem(std::make_unique<SvLBoxString>(*pStr));
+ AddStringItem(pEntry, *pStr, 0);
pEntry->SetUserData(pUserData);
m_xTreeView->Insert(pEntry, iter, nInsertPos);
@@ -3744,11 +3763,11 @@ public:
// blank out missing entries
for (int i = pEntry->ItemCount(); i < col; ++i)
- pEntry->AddItem(std::make_unique<SvLBoxString>(""));
+ AddStringItem(pEntry, "", i - 1);
if (static_cast<size_t>(col) == pEntry->ItemCount())
{
- pEntry->AddItem(std::make_unique<SvLBoxString>(rText));
+ AddStringItem(pEntry, rText, col - 1);
SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry);
m_xTreeView->InitViewData(pViewData, pEntry);
}
@@ -3833,7 +3852,7 @@ public:
// blank out missing entries
for (int i = pEntry->ItemCount(); i < col; ++i)
- pEntry->AddItem(std::make_unique<SvLBoxString>(""));
+ AddStringItem(pEntry, "", i - 1);
if (static_cast<size_t>(col) == pEntry->ItemCount())
{
@@ -3989,7 +4008,7 @@ public:
// blank out missing entries
for (int i = pEntry->ItemCount(); i < col; ++i)
- pEntry->AddItem(std::make_unique<SvLBoxString>(""));
+ AddStringItem(pEntry, "", i - 1);
if (static_cast<size_t>(col) == pEntry->ItemCount())
{
@@ -4598,6 +4617,8 @@ public:
m_xTreeView->SetDeselectHdl(Link<SvTreeListBox*, void>());
m_xTreeView->SetScrolledHdl(Link<SvTreeListBox*, void>());
m_xTreeView->SetTooltipHdl(Link<const HelpEvent&, bool>());
+ m_xTreeView->SetCustomRenderHdl(Link<svtree_render_args, void>());
+ m_xTreeView->SetCustomMeasureHdl(Link<svtree_measure_args, Size>());
}
};
@@ -4621,6 +4642,27 @@ IMPL_LINK(SalInstanceTreeView, TooltipHdl, const HelpEvent&, rHEvt, bool)
return true;
}
+IMPL_LINK(SalInstanceTreeView, CustomRenderHdl, svtree_render_args, payload, void)
+{
+ vcl::RenderContext& rRenderDevice = std::get<0>(payload);
+ const tools::Rectangle& rRect = std::get<1>(payload);
+ const SvTreeListEntry& rEntry = std::get<2>(payload);
+ const OUString* pId = static_cast<const OUString*>(rEntry.GetUserData());
+ if (!pId)
+ return;
+ signal_custom_render(rRenderDevice, rRect, m_xTreeView->IsSelected(&rEntry), *pId);
+}
+
+IMPL_LINK(SalInstanceTreeView, CustomMeasureHdl, svtree_measure_args, payload, Size)
+{
+ vcl::RenderContext& rRenderDevice = payload.first;
+ const SvTreeListEntry& rEntry = payload.second;
+ const OUString* pId = static_cast<const OUString*>(rEntry.GetUserData());
+ if (!pId)
+ return Size();
+ return signal_custom_get_size(rRenderDevice, *pId);
+}
+
IMPL_LINK(SalInstanceTreeView, CompareHdl, const SvSortData&, rSortData, sal_Int32)
{
const SvTreeListEntry* pLHS = rSortData.pLeft;
diff --git a/vcl/source/treelist/svlbitm.cxx b/vcl/source/treelist/svlbitm.cxx
index 20407f71af2b..8fff9071dcdb 100644
--- a/vcl/source/treelist/svlbitm.cxx
+++ b/vcl/source/treelist/svlbitm.cxx
@@ -174,6 +174,7 @@ bool SvLBoxButtonData::IsRadio() const {
SvLBoxString::SvLBoxString(const OUString& rStr)
: mbEmphasized(false)
+ , mbCustom(false)
, mfAlign(0.0)
, maText(rStr)
{
@@ -181,6 +182,7 @@ SvLBoxString::SvLBoxString(const OUString& rStr)
SvLBoxString::SvLBoxString()
: mbEmphasized(false)
+ , mbCustom(false)
, mfAlign(0.0)
{
}
@@ -235,7 +237,12 @@ void SvLBoxString::Paint(
rRenderContext.SetFont(aFont);
}
- rRenderContext.DrawText(tools::Rectangle(rPos, aSize), maText, nStyle);
+ tools::Rectangle aRect(rPos, aSize);
+
+ if (mbCustom)
+ rDev.DrawCustomEntry(rRenderContext, aRect, rEntry);
+ else
+ rRenderContext.DrawText(aRect, maText, nStyle);
if (mbEmphasized)
rRenderContext.Pop();
@@ -248,6 +255,7 @@ std::unique_ptr<SvLBoxItem> SvLBoxString::Clone(SvLBoxItem const * pSource) cons
const SvLBoxString* pOther = static_cast<const SvLBoxString*>(pSource);
pNew->maText = pOther->maText;
pNew->mbEmphasized = pOther->mbEmphasized;
+ pNew->mbCustom = pOther->mbCustom;
pNew->mfAlign = pOther->mfAlign;
return std::unique_ptr<SvLBoxItem>(pNew.release());
@@ -267,8 +275,17 @@ void SvLBoxString::InitViewData(
pView->Control::SetFont( aFont );
}
- pViewData->mnWidth = -1; // calc on demand
- pViewData->mnHeight = pView->GetTextHeight();
+ if (mbCustom)
+ {
+ Size aSize = pView->MeasureCustomEntry(*pView, *pEntry);
+ pViewData->mnWidth = aSize.Width();
+ pViewData->mnHeight = aSize.Height();
+ }
+ else
+ {
+ pViewData->mnWidth = -1; // calc on demand
+ pViewData->mnHeight = pView->GetTextHeight();
+ }
if (mbEmphasized)
pView->Pop();
diff --git a/vcl/source/treelist/treelistbox.cxx b/vcl/source/treelist/treelistbox.cxx
index a57b0e45b24e..f54e184356d4 100644
--- a/vcl/source/treelist/treelistbox.cxx
+++ b/vcl/source/treelist/treelistbox.cxx
@@ -2868,6 +2868,16 @@ void SvTreeListBox::PreparePaint(vcl::RenderContext& /*rRenderContext*/, SvTreeL
{
}
+void SvTreeListBox::DrawCustomEntry(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, const SvTreeListEntry& rEntry)
+{
+ aCustomRenderHdl.Call(std::tuple<vcl::RenderContext&, const tools::Rectangle&, const SvTreeListEntry&>(rRenderContext, rRect, rEntry));
+}
+
+Size SvTreeListBox::MeasureCustomEntry(vcl::RenderContext& rRenderContext, const SvTreeListEntry& rEntry)
+{
+ return aCustomMeasureHdl.Call(std::pair<vcl::RenderContext&, const SvTreeListEntry&>(rRenderContext, rEntry));
+}
+
tools::Rectangle SvTreeListBox::GetFocusRect(const SvTreeListEntry* pEntry, long nLine )
{
pImpl->UpdateContextBmpWidthMax( pEntry );
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index f3ed31051d94..a7ea94053e7c 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -441,6 +441,25 @@ namespace weld
return nAbsPos;
}
+
+ bool IsEntryVisible(const weld::TreeView& rTreeView, const weld::TreeIter& rIter)
+ {
+ // short circuit for the common case
+ if (rTreeView.get_iter_depth(rIter) == 0)
+ return true;
+
+ std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator(&rIter));
+ bool bRetVal = false;
+ do
+ {
+ if (rTreeView.get_iter_depth(*xEntry) == 0)
+ {
+ bRetVal = true;
+ break;
+ }
+ } while (rTreeView.iter_parent(*xEntry) && rTreeView.get_row_expanded(*xEntry));
+ return bRetVal;
+ }
}
VclBuilder::VclBuilder(vcl::Window* pParent, const OUString& sUIDir, const OUString& sUIFile,
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index c804670dda7c..63f5e710f817 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -5298,6 +5298,218 @@ GType crippled_viewport_get_type()
return type;
}
+#define CUSTOM_TYPE_CELL_RENDERER_SURFACE (custom_cell_renderer_surface_get_type())
+#define CUSTOM_CELL_RENDERER_SURFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), CUSTOM_TYPE_CELL_RENDERER_SURFACE, CustomCellRendererSurface))
+
+namespace {
+
+ struct CustomCellRendererSurface
+ {
+ GtkCellRendererText parent;
+ VclPtr<VirtualDevice> device;
+ gchar *id;
+ gpointer instance;
+ };
+
+ struct CustomCellRendererSurfaceClass
+ {
+ GtkCellRendererTextClass parent_class;
+ };
+
+ enum
+ {
+ PROP_ID = 10000,
+ PROP_INSTANCE_TREE_VIEW = 10001
+ };
+}
+
+static gpointer custom_cell_renderer_surface_parent_class;
+
+static GType custom_cell_renderer_surface_get_type();
+static void custom_cell_renderer_surface_class_init(CustomCellRendererSurfaceClass *klass);
+
+GType custom_cell_renderer_surface_get_type()
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ static const GTypeInfo tinfo =
+ {
+ sizeof (CustomCellRendererSurfaceClass),
+ nullptr, /* base init */
+ nullptr, /* base finalize */
+ reinterpret_cast<GClassInitFunc>(custom_cell_renderer_surface_class_init), /* class init */
+ nullptr, /* class finalize */
+ nullptr, /* class data */
+ sizeof (CustomCellRendererSurface), /* instance size */
+ 0, /* nb preallocs */
+ nullptr, /* instance init */
+ nullptr /* value table */
+ };
+
+ // inherit from GtkCellRendererText so we can set the "text" property and get a11y support for that
+ type = g_type_register_static(GTK_TYPE_CELL_RENDERER_TEXT, "CustomCellRendererSurface",
+ &tinfo, GTypeFlags(0));
+ }
+
+ return type;
+}
+
+static void custom_cell_renderer_surface_get_property(GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CustomCellRendererSurface *cellsurface = CUSTOM_CELL_RENDERER_SURFACE(object);
+
+ switch (param_id)
+ {
+ case PROP_ID:
+ g_value_set_string(value, cellsurface->id);
+ break;
+ case PROP_INSTANCE_TREE_VIEW:
+ g_value_set_pointer(value, cellsurface->instance);
+ break;
+ default:
+ G_OBJECT_CLASS(custom_cell_renderer_surface_parent_class)->get_property(object, param_id, value, pspec);
+ break;
+ }
+}
+
+static void custom_cell_renderer_surface_set_property(GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CustomCellRendererSurface *cellsurface = CUSTOM_CELL_RENDERER_SURFACE(object);
+
+ switch (param_id)
+ {
+ case PROP_ID:
+ g_free(cellsurface->id);
+ cellsurface->id = g_value_dup_string(value);
+ break;
+ case PROP_INSTANCE_TREE_VIEW:
+ cellsurface->instance = g_value_get_pointer(value);
+ break;
+ default:
+ G_OBJECT_CLASS(custom_cell_renderer_surface_parent_class)->set_property(object, param_id, value, pspec);
+ break;
+ }
+}
+
+static bool custom_cell_renderer_surface_get_preferred_size(GtkCellRenderer *cell,
+ GtkOrientation orientation,
+ gint *minimum_size,
+ gint *natural_size);
+
+static void custom_cell_renderer_surface_render(GtkCellRenderer* cell,
+ cairo_t* cr,
+ GtkWidget* widget,
+ const GdkRectangle* background_area,
+ const GdkRectangle* cell_area,
+ GtkCellRendererState flags);
+
+static void custom_cell_renderer_surface_finalize(GObject *object)
+{
+ CustomCellRendererSurface *cellsurface = CUSTOM_CELL_RENDERER_SURFACE(object);
+
+ g_free(cellsurface->id);
+ cellsurface->device.disposeAndClear();
+
+ G_OBJECT_CLASS(custom_cell_renderer_surface_parent_class)->finalize(object);
+}
+
+static void custom_cell_renderer_surface_get_preferred_width(GtkCellRenderer *cell,
+ GtkWidget *widget,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ if (!custom_cell_renderer_surface_get_preferred_size(cell, GTK_ORIENTATION_HORIZONTAL,
+ minimum_size, natural_size))
+ {
+ // fallback to parent if we're empty
+ GTK_CELL_RENDERER_CLASS(custom_cell_renderer_surface_parent_class)->get_preferred_width(cell,
+ widget, minimum_size, natural_size);
+ }
+}
+
+static void custom_cell_renderer_surface_get_preferred_height(GtkCellRenderer *cell,
+ GtkWidget *widget,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ if (!custom_cell_renderer_surface_get_preferred_size(cell, GTK_ORIENTATION_VERTICAL,
+ minimum_size, natural_size))
+ {
+ // fallback to parent if we're empty
+ GTK_CELL_RENDERER_CLASS(custom_cell_renderer_surface_parent_class)->get_preferred_height(cell,
+ widget, minimum_size, natural_size);
+ }
+
+}
+
+static void custom_cell_renderer_surface_get_preferred_height_for_width(GtkCellRenderer *cell,
+ GtkWidget *widget,
+ gint /*width*/,
+ gint *minimum_height,
+ gint *natural_height)
+{
+ gtk_cell_renderer_get_preferred_height(cell, widget, minimum_height, natural_height);
+}
+
+static void custom_cell_renderer_surface_get_preferred_width_for_height(GtkCellRenderer *cell,
+ GtkWidget *widget,
+ gint /*height*/,
+ gint *minimum_width,
+ gint *natural_width)
+{
+ gtk_cell_renderer_get_preferred_width(cell, widget, minimum_width, natural_width);
+}
+
+void custom_cell_renderer_surface_class_init(CustomCellRendererSurfaceClass *klass)
+{
+ GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS(klass);
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+ /* Hook up functions to set and get our custom cell renderer properties */
+ object_class->get_property = custom_cell_renderer_surface_get_property;
+ object_class->set_property = custom_cell_renderer_surface_set_property;
+
+ custom_cell_renderer_surface_parent_class = g_type_class_peek_parent(klass);
+ object_class->finalize = custom_cell_renderer_surface_finalize;
+
+ cell_class->get_preferred_width = custom_cell_renderer_surface_get_preferred_width;
+ cell_class->get_preferred_height = custom_cell_renderer_surface_get_preferred_height;
+ cell_class->get_preferred_width_for_height = custom_cell_renderer_surface_get_preferred_width_for_height;
+ cell_class->get_preferred_height_for_width = custom_cell_renderer_surface_get_preferred_height_for_width;
+
+ cell_class->render = custom_cell_renderer_surface_render;
+
+ g_object_class_install_property(object_class,
+ PROP_ID,
+ g_param_spec_string("id",
+ "ID",
+ "The ID of the custom data",
+ nullptr,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property(object_class,
+ PROP_INSTANCE_TREE_VIEW,
+ g_param_spec_pointer("instance",
+ "Instance",
+ "The GtkInstanceTreeView",
+ G_PARAM_READWRITE));
+
+ gtk_cell_renderer_class_set_accessible_type(cell_class, GTK_TYPE_TEXT_CELL_ACCESSIBLE);
+}
+
+static GtkCellRenderer* custom_cell_renderer_surface_new()
+{
+ return GTK_CELL_RENDERER(g_object_new(CUSTOM_TYPE_CELL_RENDERER_SURFACE, nullptr));
+}
+
static VclPolicyType GtkToVcl(GtkPolicyType eType)
{
VclPolicyType eRet(VclPolicyType::NEVER);
@@ -9455,6 +9667,21 @@ public:
gtk_tree_view_column_set_title(pColumn, OUStringToOString(rTitle, RTL_TEXTENCODING_UTF8).getStr());
}
+ virtual void set_column_custom_renderer(int nColumn) override
+ {
+ GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(g_list_nth_data(m_pColumns, nColumn));
+ assert(pColumn && "wrong count");
+ gtk_cell_layout_clear(GTK_CELL_LAYOUT(pColumn));
+ GtkCellRenderer *pRenderer = custom_cell_renderer_surface_new();
+ GValue value = G_VALUE_INIT;
+ g_value_init(&value, G_TYPE_POINTER);
+ g_value_set_pointer(&value, static_cast<gpointer>(this));
+ g_object_set_property(G_OBJECT(pRenderer), "instance", &value);
+ gtk_tree_view_column_pack_start(pColumn, pRenderer, true);
+ gtk_tree_view_column_add_attribute(pColumn, pRenderer, "text", m_nTextCol);
+ gtk_tree_view_column_add_attribute(pColumn, pRenderer, "id", m_nIdCol);
+ }
+
virtual void insert(const weld::TreeIter* pParent, int pos, const OUString* pText, const OUString* pId, const OUString* pIconName,
VirtualDevice* pImageSurface, const OUString* pExpanderName,
bool bChildrenOnDemand, weld::TreeIter* pRet) override
@@ -10897,6 +11124,16 @@ public:
enable_notify_events();
}
+ void call_signal_custom_render(VirtualDevice& rOutput, const tools::Rectangle& rRect, bool bSelected, const OUString& rId)
+ {
+ signal_custom_render(rOutput, rRect, bSelected, rId);
+ }
+
+ Size call_signal_custom_get_size(VirtualDevice& rOutput, const OUString& rId)
+ {
+ return signal_custom_get_size(rOutput, rId);
+ }
+
virtual ~GtkInstanceTreeView() override
{
if (m_pChangeEvent)
@@ -10930,6 +11167,116 @@ public:
}
};
+void ensure_device(CustomCellRendererSurface *cellsurface, weld::TreeView* pTreeView)
+{
+ if (!cellsurface->device)
+ {
+ cellsurface->device = VclPtr<VirtualDevice>::Create();
+ cellsurface->device->SetBackground(COL_TRANSPARENT);
+ // expand the point size of the desired font to the equivalent pixel size
+ if (vcl::Window* pDefaultDevice = dynamic_cast<vcl::Window*>(Application::GetDefaultDevice()))
+ pDefaultDevice->SetPointFont(*cellsurface->device, pTreeView->get_font());
+ }
+}
+
+}
+
+bool custom_cell_renderer_surface_get_preferred_size(GtkCellRenderer *cell,
+ GtkOrientation orientation,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ GValue value = G_VALUE_INIT;
+ g_value_init(&value, G_TYPE_STRING);
+ g_object_get_property(G_OBJECT(cell), "id", &value);
+
+ const char* pStr = g_value_get_string(&value);
+
+ if (!pStr)
+ {
+ // this happens if we're empty
+ return false;
+ }
+
+ OUString sId(pStr, strlen(pStr), RTL_TEXTENCODING_UTF8);
+
+ value = G_VALUE_INIT;
+ g_value_init(&value, G_TYPE_POINTER);
+ g_object_get_property(G_OBJECT(cell), "instance", &value);
+
+ CustomCellRendererSurface *cellsurface = CUSTOM_CELL_RENDERER_SURFACE(cell);
+
+ GtkInstanceTreeView* pTreeView = static_cast<GtkInstanceTreeView*>(g_value_get_pointer(&value));
+
+ ensure_device(cellsurface, pTreeView);
+
+ Size aSize = pTreeView->call_signal_custom_get_size(*cellsurface->device, sId);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ if (minimum_size)
+ *minimum_size = aSize.Width();
+
+ if (natural_size)
+ *natural_size = aSize.Width();
+ }
+ else
+ {
+ if (minimum_size)
+ *minimum_size = aSize.Height();
+
+ if (natural_size)
+ *natural_size = aSize.Height();
+ }
+
+ return true;
+}
+
+void custom_cell_renderer_surface_render(GtkCellRenderer* cell,
+ cairo_t* cr,
+ GtkWidget* /*widget*/,
+ const GdkRectangle* /*background_area*/,
+ const GdkRectangle* cell_area,
+ GtkCellRendererState flags)
+{
+ GValue value = G_VALUE_INIT;
+ g_value_init(&value, G_TYPE_STRING);
+ g_object_get_property(G_OBJECT(cell), "id", &value);
+
+ const char* pStr = g_value_get_string(&value);
+ OUString sId(pStr, pStr ? strlen(pStr) : 0, RTL_TEXTENCODING_UTF8);
+
+ value = G_VALUE_INIT;
+ g_value_init(&value, G_TYPE_POINTER);
+ g_object_get_property(G_OBJECT(cell), "instance", &value);
+
+ CustomCellRendererSurface *cellsurface = CUSTOM_CELL_RENDERER_SURFACE(cell);
+
+ GtkInstanceTreeView* pTreeView = static_cast<GtkInstanceTreeView*>(g_value_get_pointer(&value));
+
+ ensure_device(cellsurface, pTreeView);
+
+ Size aSize(cell_area->width, cell_area->height);
+ // false to not bother setting the bg on resize as we'll do that
+ // ourself via cairo
+ cellsurface->device->SetOutputSizePixel(aSize, false);
+
+ cairo_surface_t* pSurface = get_underlying_cairo_surface(*cellsurface->device);
+
+ // fill surface as transparent so it can be blended with the potentially
+ // selected background
+ cairo_t* tempcr = cairo_create(pSurface);
+ cairo_set_source_rgba(tempcr, 0, 0, 0, 0);
+ cairo_set_operator(tempcr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(tempcr);
+ cairo_destroy(tempcr);
+ cairo_surface_flush(pSurface);
+
+ pTreeView->call_signal_custom_render(*cellsurface->device, tools::Rectangle(Point(0, 0), aSize), flags & GTK_CELL_RENDERER_SELECTED, sId);
+ cairo_surface_mark_dirty(pSurface);
+
+ cairo_set_source_surface(cr, pSurface, cell_area->x, cell_area->y);
+ cairo_paint(cr);
}
IMPL_LINK_NOARG(GtkInstanceTreeView, async_signal_changed, void*, void)
commit 6ff081689573217621a4ef012755fc5e351359af
Author: Caolán McNamara <caolanm at redhat.com>
AuthorDate: Thu Apr 2 15:36:28 2020 +0100
Commit: Caolán McNamara <caolanm at redhat.com>
CommitDate: Sat Apr 4 19:51:37 2020 +0200
fix SvLBoxString::Clone wrt newly added entries
Change-Id: I31d0b0af25fb6062b518f4c1ace25715a784ad81
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91657
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm at redhat.com>
diff --git a/vcl/source/treelist/svlbitm.cxx b/vcl/source/treelist/svlbitm.cxx
index cd7fbae06b97..20407f71af2b 100644
--- a/vcl/source/treelist/svlbitm.cxx
+++ b/vcl/source/treelist/svlbitm.cxx
@@ -244,7 +244,12 @@ void SvLBoxString::Paint(
std::unique_ptr<SvLBoxItem> SvLBoxString::Clone(SvLBoxItem const * pSource) const
{
std::unique_ptr<SvLBoxString> pNew(new SvLBoxString);
- pNew->maText = static_cast<SvLBoxString const *>(pSource)->maText;
+
+ const SvLBoxString* pOther = static_cast<const SvLBoxString*>(pSource);
+ pNew->maText = pOther->maText;
+ pNew->mbEmphasized = pOther->mbEmphasized;
+ pNew->mfAlign = pOther->mfAlign;
+
return std::unique_ptr<SvLBoxItem>(pNew.release());
}
More information about the Libreoffice-commits
mailing list