Skip to content

Commit dac17a4

Browse files
committed
Add initial xwidgets implementation
1 parent 171f864 commit dac17a4

30 files changed

+1876
-3
lines changed

CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ option(
7272
# ============
7373

7474
find_package(xeus-zmq REQUIRED)
75+
find_package(xwidgets REQUIRED)
76+
find_package(xproperty REQUIRED)
7577
find_package(PNG REQUIRED)
7678
find_package(glad REQUIRED)
7779
find_package(glfw3)
@@ -112,6 +114,7 @@ set(
112114
include/xeus-octave/plotstream.hpp
113115
include/xeus-octave/tex2html.hpp
114116
include/xeus-octave/display.hpp
117+
include/xeus-octave/xwidgets.hpp
115118
)
116119

117120
set(
@@ -122,6 +125,7 @@ set(
122125
src/xinterpreter.cpp
123126
src/input.cpp
124127
src/output.cpp
128+
src/xwidgets.cpp
125129
)
126130

127131
set(XEUS_OCTAVE_MAIN_SRC src/main.cpp)
@@ -226,7 +230,7 @@ macro(xeus_octave_create_target target_name linkage output_name)
226230

227231
target_link_libraries(
228232
${target_name}
229-
PUBLIC xtl PkgConfig::octinterp
233+
PUBLIC xtl xwidgets PkgConfig::octinterp
230234
PRIVATE glad::glad glfw PNG::PNG
231235
)
232236
if(XEUS_OCTAVE_USE_SHARED_XEUS)

environment-dev.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ channels:
33
dependencies:
44
# Build dependencies
55
- cxx-compiler
6+
- fortran-compiler
67
- c-compiler
78
- cmake
89
- make
@@ -11,6 +12,7 @@ dependencies:
1112
- libuuid
1213
- xtl
1314
- xeus-zmq =1.*
15+
- xwidgets =0.27.3
1416
- nlohmann_json
1517
- cppzmq
1618
- octave =7.*
@@ -37,4 +39,5 @@ dependencies:
3739
- cmake-format
3840
- plotly
3941
- ipywidgets
42+
- widgetsnbextension =3.6.1
4043
- jupyter-dash

include/xeus-octave/utils.hpp

Lines changed: 197 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@
1717
* along with xeus-octave. If not, see <http://www.gnu.org/licenses/>.
1818
*/
1919

20-
#ifndef XEUS_OCTAVE_UTILS_HPP
21-
#define XEUS_OCTAVE_UTILS_HPP
20+
#ifndef XEUS_OCTAVE_UTILS_H
21+
#define XEUS_OCTAVE_UTILS_H
2222

23+
#include <octave/dim-vector.h>
24+
#include <octave/graphics-handle.h>
25+
#include <octave/graphics.h>
26+
#include <octave/int8NDArray.h>
2327
#include <octave/interpreter.h>
2428
#include <octave/ov-builtin.h>
29+
#include <octave/ov-classdef.h>
2530
#include <octave/ov-fcn-handle.h>
2631
#include <octave/ov-null-mat.h>
2732
#include <octave/ov.h>
@@ -30,10 +35,200 @@
3035

3136
#include <xeus/xguid.hpp>
3237
#include <xtl/xoptional.hpp>
38+
#include <xwidgets/xholder.hpp>
39+
#include <xwidgets/ximage.hpp>
40+
41+
#include "xeus-octave/plotstream.hpp"
3342

3443
namespace xeus_octave::utils
3544
{
3645

46+
/**
47+
* Convert octave_value to any generic type. Fails at runtime if not implemented in
48+
* octave default conversions
49+
*/
50+
template <class T> inline void from_ov(octave_value const&, T&, octave::interpreter&)
51+
{
52+
static_assert(!sizeof(T*), "Please implement a proper conversion function");
53+
}
54+
55+
/**
56+
* Convert octave_value to int
57+
*/
58+
inline void from_ov(octave_value const& from, int& to, octave::interpreter&)
59+
{
60+
to = from.int_value();
61+
}
62+
63+
/**
64+
* Convert octave_value to bool
65+
*/
66+
inline void from_ov(octave_value const& from, bool& to, octave::interpreter&)
67+
{
68+
to = from.bool_value();
69+
}
70+
71+
/**
72+
* Convert octave_value to std::string
73+
*/
74+
inline void from_ov(octave_value const& from, std::string& to, octave::interpreter&)
75+
{
76+
to = from.string_value();
77+
}
78+
79+
/**
80+
* Convert octave_value to double
81+
*/
82+
inline void from_ov(octave_value const& from, double& to, octave::interpreter&)
83+
{
84+
to = from.scalar_value();
85+
}
86+
87+
/**
88+
* Convert octave_value to xguid.
89+
* Used for xwidgets
90+
*/
91+
inline void from_ov(octave_value const& from, xeus::xguid& to, octave::interpreter& interpreter)
92+
{
93+
std::string _to;
94+
from_ov(from, _to, interpreter);
95+
to = xeus::xguid(_to);
96+
}
97+
98+
/**
99+
* Convert octave_value to widget (holder)
100+
*/
101+
inline void from_ov(octave_value const& from, xw::xholder& to, octave::interpreter& interpreter)
102+
{
103+
// This is an xwidget
104+
if (from.is_classdef_object())
105+
{
106+
octave_classdef* cls = from.classdef_object_value();
107+
octave_value_list ret = cls->subsref(".", {ovl("id")}, 1);
108+
xeus::xguid id;
109+
110+
from_ov(ret(0), id, interpreter);
111+
to = xw::make_id_holder(id);
112+
}
113+
}
114+
115+
/**
116+
* Convert octave value to a generic vector
117+
*/
118+
template <class T> inline void from_ov(octave_value const& from, std::vector<T>& to, octave::interpreter& interpreter)
119+
{
120+
Cell cell = from.cell_value();
121+
122+
for (int i = 0; i < cell.numel(); i++)
123+
{
124+
T element;
125+
from_ov(cell(0, i), element, interpreter);
126+
to.push_back(element);
127+
}
128+
}
129+
130+
/**
131+
* Convert octave_value to a vector of chars (i.e. byte array)
132+
*/
133+
inline void from_ov(octave_value const& from, std::vector<char>& to, octave::interpreter&)
134+
{
135+
if (from.is_string())
136+
{
137+
std::string _to = from.string_value();
138+
std::copy(_to.begin(), _to.end(), std::back_inserter(to));
139+
}
140+
else
141+
{
142+
auto array = from.uint8_array_value();
143+
for (int i = 0; i < array.numel(); i++)
144+
to.push_back(array.xelem(i).char_value());
145+
}
146+
}
147+
148+
/**
149+
* Convert octave_value to a xtl::xoptional generic value
150+
*/
151+
template <class T>
152+
inline void from_ov(octave_value const& from, xtl::xoptional<T>& to, octave::interpreter& interpreter)
153+
{
154+
if (!from.isnull())
155+
{
156+
T _to;
157+
from_ov(from, _to, interpreter);
158+
to = _to;
159+
}
160+
else
161+
to = xtl::xoptional<T>();
162+
}
163+
164+
/**
165+
* Convert generic type to octave_value
166+
*/
167+
template <class T> inline void to_ov(octave_value& to, T const& from, octave::interpreter&)
168+
{
169+
to = octave_value(from);
170+
}
171+
172+
/**
173+
* Convert widget to octave_value.
174+
* Simply returns string containing id
175+
*/
176+
inline void to_ov(octave_value& to, xw::xholder const& from, octave::interpreter&)
177+
{
178+
to = octave_value(from.id().c_str());
179+
}
180+
181+
/**
182+
* Convert a generic std::vector to octave_value (cell array)
183+
*/
184+
template <class T> inline void to_ov(octave_value& to, std::vector<T> const& from, octave::interpreter& interpreter)
185+
{
186+
Cell a;
187+
octave_idx_type i = 0;
188+
189+
a.resize(dim_vector(static_cast<octave_idx_type>(from.size()), 1));
190+
191+
for (auto e : from)
192+
to_ov(a.elem(i++, 0), e, interpreter);
193+
194+
to = a;
195+
}
196+
197+
/**
198+
* Convert a vector of char (i.e. bytearray) to octave_value (uint8 matrix)
199+
*/
200+
inline void to_ov(octave_value& to, std::vector<char> const& from, octave::interpreter&)
201+
{
202+
auto dv = dim_vector(1, static_cast<octave_idx_type>(from.size()));
203+
uint8NDArray _to(Array<char>(from, dv));
204+
to = _to;
205+
}
206+
207+
/**
208+
* Convert a generic xtl::xoptional to octave_value (value or null matrix)
209+
*/
210+
template <class T> inline void to_ov(octave_value& to, xtl::xoptional<T> const& from, octave::interpreter& interpreter)
211+
{
212+
if (from.has_value())
213+
to_ov(to, from.value(), interpreter);
214+
else
215+
to = octave_null_matrix::instance;
216+
}
217+
218+
/**
219+
* Convert a xguid to octave_value (sq_string)
220+
*/
221+
inline void to_ov(octave_value& to, xeus::xguid const& from, octave::interpreter& interpreter)
222+
{
223+
to_ov(to, std::string(from), interpreter);
224+
}
225+
226+
template <typename M> inline octave_value make_fcn_handle(M ff, std::string const& nm)
227+
{
228+
octave_value fcn(new octave_builtin(ff, nm));
229+
return octave_value(new octave_fcn_handle(fcn));
230+
}
231+
37232
inline void add_native_binding(octave::interpreter& interpreter, std::string const& name, octave_builtin::fcn ff)
38233
{
39234
octave_builtin* fcn = new octave_builtin(ff, name, __FILE__, "");

0 commit comments

Comments
 (0)