Skip to content

Commit bd920fe

Browse files
committed
Merge remote-tracking branch 'origin/graph-widget' into devel
* Implemented new tk::Embed widget for embedding into graph widget.
2 parents be48fc3 + c88744d commit bd920fe

File tree

9 files changed

+487
-48
lines changed

9 files changed

+487
-48
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
=== 1.0.30 ===
66
* Implemented new tk::RangeSlider widget.
77
* Implemented new tk::PianoKeys widget.
8+
* Implemented new tk::Embed widget for embedding into graph widget.
89
* Fixed use after free for several scenarios when destroying the display.
910

1011
=== 1.0.29 ===

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ The full list of provided widgets:
5555
* Graph - widget for rendering 2D graphical data (graphs and plots).
5656
* GraphAxis - axis on a graph widget.
5757
* GraphDot - dot on a graph widget.
58+
* GraphEmbed - special widget to embed widgets into graph widget, acts like Align but uses axis coordinates.
5859
* GraphFrameBuffer - frame buffer for drawing on the graph widget.
5960
* GraphLineSegment - grap line segment defined by two points.
6061
* GraphMarker - marker on the graph widget.

include/lsp-plug.in/tk/tk.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
#include <lsp-plug.in/tk/widgets/graph/Graph.h>
209209
#include <lsp-plug.in/tk/widgets/graph/GraphAxis.h>
210210
#include <lsp-plug.in/tk/widgets/graph/GraphDot.h>
211+
#include <lsp-plug.in/tk/widgets/graph/GraphEmbed.h>
211212
#include <lsp-plug.in/tk/widgets/graph/GraphFrameBuffer.h>
212213
#include <lsp-plug.in/tk/widgets/graph/GraphLineSegment.h>
213214
#include <lsp-plug.in/tk/widgets/graph/GraphMarker.h>

include/lsp-plug.in/tk/widgets/graph/Graph.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ namespace lsp
6868
} w_alloc_t;
6969

7070
protected:
71-
prop::WidgetList<GraphItem> vItems; // Overall list of graph items
71+
prop::WidgetList<Widget> vItems; // Overall list of graph items
7272
lltl::parray<GraphAxis> vAxis; // List of all axes
7373
lltl::parray<GraphAxis> vBasis; // List of basises
7474
lltl::parray<GraphOrigin> vOrigins; // List of origins
@@ -121,7 +121,7 @@ namespace lsp
121121
virtual void destroy() override;
122122

123123
public:
124-
LSP_TK_PROPERTY(WidgetList<GraphItem>, items, &vItems);
124+
LSP_TK_PROPERTY(WidgetList<Widget>, items, &vItems);
125125
LSP_TK_PROPERTY(SizeConstraints, constraints, &sConstraints);
126126
LSP_TK_PROPERTY(Integer, border_size, &sBorder);
127127
LSP_TK_PROPERTY(Integer, border_radius, &sBorderRadius);
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Copyright (C) 2025 Linux Studio Plugins Project <https://lsp-plug.in/>
3+
* (C) 2025 Vladimir Sadovnikov <[email protected]>
4+
*
5+
* This file is part of lsp-tk-lib
6+
* Created on: 29 сент. 2025 г.
7+
*
8+
* lsp-tk-lib is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* any later version.
12+
*
13+
* lsp-tk-lib is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU Lesser General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License
19+
* along with lsp-tk-lib. If not, see <https://www.gnu.org/licenses/>.
20+
*/
21+
22+
#ifndef LSP_PLUG_IN_TK_WIDGETS_GRAPH_GRAPHEMBED_H_
23+
#define LSP_PLUG_IN_TK_WIDGETS_GRAPH_GRAPHEMBED_H_
24+
25+
#ifndef LSP_PLUG_IN_TK_IMPL
26+
#error "use <lsp-plug.in/tk/tk.h>"
27+
#endif
28+
29+
namespace lsp
30+
{
31+
namespace tk
32+
{
33+
// Style definition
34+
namespace style
35+
{
36+
LSP_TK_STYLE_DEF_BEGIN(GraphEmbed, GraphItem)
37+
prop::Integer sOrigin; // Index of origin widget
38+
prop::Integer sHAxis; // Horizontal axis
39+
prop::Integer sVAxis; // Vertical axis
40+
prop::Float sHStartValue; // Horizontal axis start value
41+
prop::Float sVStartValue; // Vertical axis start value
42+
prop::Float sHEndValue; // Horizontal axis end value
43+
prop::Float sVEndValue; // Vertical axis end value
44+
prop::Layout sLayout; // Layout
45+
prop::Float sTransparency; // Transparency
46+
LSP_TK_STYLE_DEF_END
47+
}
48+
49+
class GraphEmbed: public WidgetContainer
50+
{
51+
public:
52+
static const w_class_t metadata;
53+
54+
protected:
55+
prop::Integer sOrigin; // Index of origin widget
56+
prop::Integer sHAxis; // Horizontal axis
57+
prop::Integer sVAxis; // Vertical axis
58+
prop::Float sHStartValue; // Horizontal axis start value
59+
prop::Float sVStartValue; // Vertical axis start value
60+
prop::Float sHEndValue; // Horizontal axis end value
61+
prop::Float sVEndValue; // Vertical axis end value
62+
prop::Layout sLayout; // Layout
63+
prop::Float sTransparency; // Transparency
64+
ws::rectangle_t sLocation; // Old widget location
65+
tk::Widget *wWidget; // Widget
66+
67+
protected:
68+
status_t calc_point(ssize_t *x, ssize_t *y, Graph *cv, float hvalue, float vvalue);
69+
void do_destroy();
70+
void realize_child(Graph *cv, ws::rectangle_t *widget, const ws::rectangle_t *location);
71+
void invalidate_location();
72+
73+
protected:
74+
virtual void property_changed(Property *prop) override;
75+
76+
public:
77+
explicit GraphEmbed(Display *dpy);
78+
GraphEmbed(const GraphEmbed &) = delete;
79+
GraphEmbed(GraphEmbed &&) = delete;
80+
virtual ~GraphEmbed() override;
81+
82+
GraphEmbed & operator = (const GraphEmbed &) = delete;
83+
GraphEmbed & operator = (GraphEmbed &&) = delete;
84+
85+
virtual status_t init() override;
86+
virtual void destroy() override;
87+
88+
public:
89+
Graph *graph();
90+
91+
public:
92+
LSP_TK_PROPERTY(Integer, origin, &sOrigin)
93+
LSP_TK_PROPERTY(Integer, haxis, &sHAxis)
94+
LSP_TK_PROPERTY(Integer, vaxis, &sVAxis)
95+
LSP_TK_PROPERTY(Float, hvalue_start, &sHStartValue)
96+
LSP_TK_PROPERTY(Float, hvalue_end, &sHEndValue)
97+
LSP_TK_PROPERTY(Float, vvalue_start, &sVStartValue)
98+
LSP_TK_PROPERTY(Float, vvalue_end, &sVEndValue)
99+
LSP_TK_PROPERTY(Layout, layout, &sLayout)
100+
LSP_TK_PROPERTY(Float, transparency, &sTransparency)
101+
102+
public:
103+
virtual void render(ws::ISurface *s, const ws::rectangle_t *area, bool force) override;
104+
virtual void draw(ws::ISurface *s, bool force) override;
105+
virtual status_t add(Widget *widget) override;
106+
virtual status_t remove(Widget *widget) override;
107+
virtual Widget *find_widget(ssize_t x, ssize_t y) override;
108+
};
109+
110+
} /* namespace tk */
111+
} /* namespace lsp */
112+
113+
#endif /* LSP_PLUG_IN_TK_WIDGETS_GRAPH_GRAPHEMBED_H_ */

src/main/prop/multi/Layout.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,8 @@ namespace lsp
241241
h = lsp_min(h, req->nMaxHeight);
242242

243243
// Estimate the amount of free space and update position (if possible)
244-
xgap = lsp_max(0, src->nWidth - w);
245-
ygap = lsp_max(0, src->nHeight - h);
244+
xgap = src->nWidth - w;
245+
ygap = src->nHeight - h;
246246

247247
// Scale position (if possible) and store results
248248
dst->nLeft = src->nLeft + xgap * (hAlign + 1.0f) * 0.5f;

src/main/widgets/graph/Graph.cpp

Lines changed: 52 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ namespace lsp
105105
// Unlink all items
106106
for (size_t i=0, n=vItems.size(); i<n; ++i)
107107
{
108-
GraphItem *item = vItems.get(i);
108+
Widget *item = vItems.get(i);
109109
if (item == NULL)
110110
continue;
111111

@@ -237,10 +237,10 @@ namespace lsp
237237

238238
for (size_t i=0, n = vItems.size(); i<n; ++i)
239239
{
240-
tk::GraphItem *gi = vItems.get(i);
241-
if (gi == NULL)
240+
tk::Widget *w = vItems.get(i);
241+
if (w == NULL)
242242
continue;
243-
tk::Slot *slot = gi->slot(SLOT_RESIZE_PARENT);
243+
tk::Slot *slot = w->slot(SLOT_RESIZE_PARENT);
244244
if (slot != NULL)
245245
{
246246
ws::rectangle_t xr = *r;
@@ -346,14 +346,14 @@ namespace lsp
346346
sync_lists();
347347

348348
// Compute list of discarded widgets
349-
lltl::ptrset<GraphItem> discarded;
349+
lltl::ptrset<tk::Widget> discarded;
350350
{
351351
lltl::darray<w_alloc_t> grouped;
352352

353353
// Fill all grouped widgets
354354
for (size_t i=0, n=vItems.size(); i<n; ++i)
355355
{
356-
GraphItem *gi = vItems.get(i);
356+
tk::GraphItem *gi = tk::widget_cast<tk::GraphItem>(vItems.get(i));
357357
if ((gi == NULL) || (!gi->visibility()->get()))
358358
continue;
359359

@@ -397,14 +397,14 @@ namespace lsp
397397
// Draw all objects
398398
for (size_t i=0, n=vItems.size(); i<n; ++i)
399399
{
400-
GraphItem *gi = vItems.get(i);
401-
if ((gi == NULL) || (!gi->visibility()->get()))
400+
tk::Widget *w = vItems.get(i);
401+
if ((w == NULL) || (!w->visibility()->get()))
402402
continue;
403-
if (discarded.contains(gi))
403+
if (discarded.contains(w))
404404
continue;
405405

406-
gi->render(s, &sICanvas, true);
407-
gi->commit_redraw();
406+
w->render(s, &sICanvas, true);
407+
w->commit_redraw();
408408
}
409409
}
410410

@@ -416,14 +416,14 @@ namespace lsp
416416

417417
for (size_t i=0, n=vItems.size(); i<n; ++i)
418418
{
419-
GraphItem *gi = vItems.get(i);
420-
if (gi == NULL)
419+
tk::Widget *w = vItems.get(i);
420+
if (w == NULL)
421421
continue;
422422

423-
GraphOrigin *go = widget_cast<GraphOrigin>(gi);
423+
tk::GraphOrigin *go = widget_cast<tk::GraphOrigin>(w);
424424
if (go != NULL)
425425
vOrigins.add(go);
426-
GraphAxis *ga = widget_cast<GraphAxis>(gi);
426+
tk::GraphAxis *ga = widget_cast<tk::GraphAxis>(w);
427427
if (ga != NULL)
428428
{
429429
vAxis.add(ga);
@@ -449,43 +449,46 @@ namespace lsp
449449
// Lookup widgets
450450
for (size_t i=0, n=vItems.size(); i<n; ++i)
451451
{
452-
GraphItem *gi = vItems.get(i);
453-
if ((gi == NULL) || (!gi->is_visible_child_of(this)))
452+
tk::Widget *w = vItems.get(i);
453+
if (!w->is_visible_child_of(this))
454454
continue;
455455

456-
if (gi->inside(x, y))
457-
return gi;
456+
if ((w != NULL) && (w->inside(x, y)))
457+
{
458+
Widget *child = w->find_widget(x, y);
459+
return (child != NULL) ? child : w;
460+
}
458461
}
459462
return NULL;
460463
}
461464

462465
void Graph::on_add_item(void *obj, Property *prop, void *w)
463466
{
464-
GraphItem *item = widget_ptrcast<GraphItem>(w);
467+
Widget *item = widget_ptrcast<Widget>(w);
465468
if (item == NULL)
466469
return;
467470

468-
Graph *_this = widget_ptrcast<Graph>(obj);
469-
if (_this == NULL)
471+
Graph *self = widget_ptrcast<Graph>(obj);
472+
if (self == NULL)
470473
return;
471474

472-
item->set_parent(_this);
473-
_this->query_draw();
475+
item->set_parent(self);
476+
self->query_draw();
474477
}
475478

476479
void Graph::on_remove_item(void *obj, Property *prop, void *w)
477480
{
478-
GraphItem *item = widget_ptrcast<GraphItem>(w);
481+
Widget *item = widget_ptrcast<Widget>(w);
479482
if (item == NULL)
480483
return;
481484

482-
Graph *_this = widget_ptrcast<Graph>(obj);
483-
if (_this == NULL)
485+
Graph *self = widget_ptrcast<Graph>(obj);
486+
if (self == NULL)
484487
return;
485488

486489
// Remove widget from supplementary structures
487-
_this->unlink_widget(item);
488-
_this->query_draw();
490+
self->unlink_widget(item);
491+
self->query_draw();
489492
}
490493

491494
bool Graph::origin(size_t index, float *x, float *y)
@@ -512,22 +515,27 @@ namespace lsp
512515
{
513516
GraphItem *item = widget_cast<GraphItem>(child);
514517
if (item == NULL)
515-
return STATUS_BAD_TYPE;
518+
{
519+
GraphEmbed *embed = widget_cast<GraphEmbed>(child);
520+
if (embed == NULL)
521+
return STATUS_BAD_TYPE;
522+
}
516523

517-
status_t res = vItems.add(item);
518-
if (res == STATUS_OK)
524+
status_t res = vItems.add(child);
525+
if (res != STATUS_OK)
526+
return res;
527+
528+
GraphOrigin *go = widget_cast<GraphOrigin>(child);
529+
if (go != NULL)
530+
vOrigins.add(go);
531+
GraphAxis *ga = widget_cast<GraphAxis>(child);
532+
if (ga != NULL)
519533
{
520-
GraphOrigin *go = widget_cast<GraphOrigin>(child);
521-
if (go != NULL)
522-
vOrigins.add(go);
523-
GraphAxis *ga = widget_cast<GraphAxis>(child);
524-
if (ga != NULL)
525-
{
526-
vAxis.add(ga);
527-
if (ga->basis()->get())
528-
vBasis.add(ga);
529-
}
534+
vAxis.add(ga);
535+
if (ga->basis()->get())
536+
vBasis.add(ga);
530537
}
538+
531539
return res;
532540
}
533541

@@ -608,9 +616,9 @@ namespace lsp
608616

609617
// Return success
610618
if (x != NULL)
611-
*x = xx;
619+
*x = xx + canvas_aleft();
612620
if (y != NULL)
613-
*y = yy;
621+
*y = yy + canvas_atop();
614622

615623
return STATUS_OK;
616624
}

0 commit comments

Comments
 (0)