Skip to content

Commit 856c6e4

Browse files
committed
Allow using a figure as a widget
1 parent dac17a4 commit 856c6e4

File tree

5 files changed

+976
-55
lines changed

5 files changed

+976
-55
lines changed

include/xeus-octave/plotstream.hpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,27 @@
2222

2323
#include <octave/graphics.h>
2424

25+
#include <xwidgets/ximage.hpp>
26+
2527
namespace xeus_octave
2628
{
2729

2830
template <class T> inline T getPlotStream(octave::graphics_object const& o);
2931

32+
/**
33+
* Retrieve from the graphics object the plot_stream property
34+
*/
35+
template <> inline xw::image* getPlotStream<xw::image*>(octave::graphics_object const& o)
36+
{
37+
octave_value ps =
38+
dynamic_cast<octave::figure::properties const&>(o.get_ancestor("figure").get_properties()).get___plot_stream__();
39+
40+
if (ps.isnumeric() && ps.is_scalar_type())
41+
return reinterpret_cast<xw::image*>(ps.long_value());
42+
else
43+
return nullptr;
44+
}
45+
3046
/**
3147
* Retrieve from the graphics object the plot_stream property
3248
*/
@@ -41,6 +57,18 @@ template <> inline std::string getPlotStream<std::string>(octave::graphics_objec
4157
return "";
4258
}
4359

60+
/**
61+
* Set in the graphics object the plot_stream propert
62+
*/
63+
inline void setPlotStream(octave::graphics_object& o, xw::image* p)
64+
{
65+
if (o.isa("figure"))
66+
{
67+
auto& fp = dynamic_cast<octave::figure::properties&>(o.get_properties());
68+
fp.set___plot_stream__(reinterpret_cast<intptr_t>(p));
69+
}
70+
}
71+
4472
/**
4573
* Set in the graphics object the plot_stream propert
4674
*/
@@ -53,6 +81,16 @@ inline void setPlotStream(octave::graphics_object& o, std::string p)
5381
}
5482
}
5583

84+
/**
85+
* Set in the graphics object the plot_stream propert (const version)
86+
*/
87+
inline void setPlotStream(octave::graphics_object const& o, xw::image* p)
88+
{
89+
// deCONSTify the graphics_object
90+
auto _go = o;
91+
setPlotStream(_go, p);
92+
}
93+
5694
/**
5795
* Set in the graphics object the plot_stream propert (const version)
5896
*/

include/xeus-octave/tk_notebook.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,29 @@ class notebook_graphics_toolkit : public glfw_graphics_toolkit
6464
void show_figure(octave::graphics_object const&) const override;
6565
};
6666

67+
/**
68+
* Toolkit that uses a ximage as output region, updating its contents on each
69+
* redraw. When a figure is added to a widget container (e.g. xvbox or xhbox)
70+
* its toolkit is automatically converted to this one.
71+
* Does not display anything on its own, it MUST be included in a container
72+
* widget.
73+
*
74+
* Should not be used by users
75+
*/
76+
class widget_graphics_toolkit : public glfw_graphics_toolkit
77+
{
78+
public:
79+
80+
widget_graphics_toolkit() : glfw_graphics_toolkit("__widget") {}
81+
82+
bool is_valid() const override { return true; }
83+
84+
bool initialize(octave::graphics_object const&) override;
85+
void send_figure(octave::graphics_object const&, std::vector<char> const&, int, int, double) const override;
86+
void show_figure(octave::graphics_object const&) const override;
87+
void finalize(octave::graphics_object const&) override;
88+
};
89+
6790
void register_all(octave::interpreter& interpreter);
6891

6992
} // namespace xeus_octave::tk::notebook

include/xeus-octave/utils.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,26 @@ inline void from_ov(octave_value const& from, xw::xholder& to, octave::interpret
110110
from_ov(ret(0), id, interpreter);
111111
to = xw::make_id_holder(id);
112112
}
113+
// This is a figure handle
114+
else if (from.is_real_scalar())
115+
{
116+
// Get the handle
117+
graphics_handle gh = interpreter.get_gh_manager().lookup(from);
118+
119+
if (gh.ok())
120+
{
121+
// Get the object
122+
octave::graphics_object go = interpreter.get_gh_manager().get_object(gh);
123+
// Change the graphics_toolkit to widget
124+
auto& figureProperties = dynamic_cast<octave::figure::properties&>(go.get_properties());
125+
figureProperties.set___graphics_toolkit__("__widget");
126+
auto* figure = getPlotStream<xw::image*>(go);
127+
128+
assert(figure != nullptr);
129+
130+
to = xw::make_id_holder(figure->id());
131+
}
132+
}
113133
}
114134

115135
/**

notebooks/xeus-octave.ipynb

Lines changed: 855 additions & 55 deletions
Large diffs are not rendered by default.

src/tk_notebook.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <octave/ov.h>
4343
#include <png.h>
4444
#include <xtl/xbase64.hpp>
45+
#include <xwidgets/ximage.hpp>
4546

4647
#include "xeus-octave/plotstream.hpp"
4748
#include "xeus-octave/tk_notebook.hpp"
@@ -323,11 +324,50 @@ void notebook_graphics_toolkit::send_figure(
323324
dynamic_cast<xoctave_interpreter&>(xeus::get_interpreter()).update_display_data(data, meta, tran);
324325
}
325326

327+
bool widget_graphics_toolkit::initialize(oc::graphics_object const& go)
328+
{
329+
bool ret = glfw_graphics_toolkit::initialize(go);
330+
331+
if (go.isa("figure"))
332+
{
333+
// Create a new object id and store it in the figure
334+
setPlotStream(go, new xw::image());
335+
336+
return true;
337+
}
338+
339+
return ret;
340+
}
341+
342+
void widget_graphics_toolkit::show_figure(oc::graphics_object const&) const {}
343+
344+
void widget_graphics_toolkit::send_figure(
345+
octave::graphics_object const& go, std::vector<char> const& img, int width, int height, double dpr
346+
) const
347+
{
348+
// Retrieve the figure id
349+
xw::image* figure = getPlotStream<xw::image*>(go);
350+
351+
// TODO check value is changed before setting
352+
figure->width = std::to_string(width / dpr);
353+
figure->height = std::to_string(height / dpr);
354+
figure->value = img;
355+
}
356+
357+
void widget_graphics_toolkit::finalize(octave::graphics_object const& go)
358+
{
359+
xw::image* figure = getPlotStream<xw::image*>(go);
360+
361+
delete figure;
362+
}
363+
326364
void register_all(octave::interpreter& interpreter)
327365
{
328366
// Install the toolkit into the interpreter
329367
interpreter.get_gtk_manager().register_toolkit("notebook");
330368
interpreter.get_gtk_manager().load_toolkit(octave::graphics_toolkit(new notebook_graphics_toolkit()));
369+
interpreter.get_gtk_manager().register_toolkit("__widget");
370+
interpreter.get_gtk_manager().load_toolkit(octave::graphics_toolkit(new widget_graphics_toolkit()));
331371
}
332372

333373
} // namespace xeus_octave::tk::notebook

0 commit comments

Comments
 (0)