diff --git a/.gitmodules b/.gitmodules index ae417d0bd..1e1377a22 100644 --- a/.gitmodules +++ b/.gitmodules @@ -11,3 +11,6 @@ [submodule "libclipboard"] path = libclipboard url = https://github.com/OfficialKris/libclipboard.git +[submodule "mansoura"] + path = mansoura + url = https://github.com/highperformancecoder/mansoura.git diff --git a/Makefile b/Makefile index 731dc7fba..f6e3f5b00 100644 --- a/Makefile +++ b/Makefile @@ -61,6 +61,8 @@ ifneq ($(build_ecolab),ecolab built) $(warning $(shell cat ecolab/build.log)) $(error Making ecolab failed: check ecolab/build.log) endif +# mansoura/src needs to be before EcoLab's include directory, as it overrides them +FLAGS+=-Imansoura/src include $(ECOLAB_HOME)/include/Makefile ifndef MXE @@ -99,6 +101,14 @@ ifneq ($(strip $(build_ravelcapi)),ravelcapi built) $(error Making RavelCAPI failed: check RavelCAPI/build.log) endif +# Mansoura +build_mansoura:=$(shell cd mansoura; if $(MAKE) $(JOBS) $(MAKEOVERRIDES) libmansoura.a >build.log 2>&1; then echo "mansoura built"; fi) +$(warning $(build_mansoura)) +ifneq ($(strip $(build_mansoura)),mansoura built) +$(error Making Mansoura failed: check mansoura/build.log) +endif + + ifndef MXE # libclipboard build_libclipboard:=$(shell cd libclipboard; if cmake -DBUILD_SHARED_LIBS=0 -DCMAKE_C_FLAGS=-fPIC . &>build.log && $(MAKE) $(JOBS) >>build.log 2>&1; then echo "libclipboard built"; fi) @@ -182,8 +192,8 @@ PREFIX=/usr/local # custom one that picks up its scripts from a relative library # directory MODLINK=$(LIBMODS:%=$(ECOLAB_HOME)/lib/%) -MODEL_OBJS=autoLayout.o cairoItems.o canvas.o CSVDialog.o dataOp.o equationDisplay.o godleyIcon.o godleyTable.o godleyTableWindow.o group.o item.o intOp.o lasso.o lock.o minsky.o operation.o operationRS.o operationRS1.o operationRS2.o phillipsDiagram.o plotWidget.o port.o pubTab.o ravelWrap.o renderNativeWindow.o selection.o sheet.o SVGItem.o switchIcon.o userFunction.o userFunction_units.o variableInstanceList.o variable.o windowInformation.o wire.o -ENGINE_OBJS=clipboard.o cairoShimCairo.o databaseIngestor.o derivative.o equationDisplayRender.o equations.o evalGodley.o evalOp.o flowCoef.o \ +MODEL_OBJS=autoLayout.o cairoItems.o canvas.o CSVDialog.o dataOp.o equationDisplay.o godleyIcon.o godleyTable.o godleyTableEditor.o group.o item.o intOp.o lasso.o lock.o minsky.o operation.o operationRS.o operationRS1.o operationRS2.o phillipsDiagram.o plotWidget.o port.o pubTab.o ravelWrap.o renderNativeWindow.o selection.o sheet.o switchIcon.o userFunction.o userFunction_units.o variableInstanceList.o variable.o windowInformation.o wire.o +ENGINE_OBJS=clipboard.o databaseIngestor.o derivative.o equationDisplayRender.o equations.o evalGodley.o evalOp.o flowCoef.o \ godleyExport.o latexMarkup.o valueId.o variableValue.o node_latex.o node_matlab.o CSVParser.o \ minskyTensorOps.o mdlReader.o saver.o rungeKutta.o SCHEMA_OBJS=schema3.o schema2.o schema1.o schema0.o schemaHelper.o variableType.o \ @@ -201,7 +211,7 @@ LIBS+=-Wl,-framework -Wl,Security -Wl,-headerpad_max_install_names MODEL_OBJS+=getContext.o endif -ALL_OBJS=$(MODEL_OBJS) $(ENGINE_OBJS) $(SCHEMA_OBJS) $(RESTSERVICE_OBJS) RESTService.o addon.o typescriptAPI.o pyminsky.o createLinkGroupIcons.o +ALL_OBJS=$(MODEL_OBJS) $(ENGINE_OBJS) $(SCHEMA_OBJS) $(RESTSERVICE_OBJS) RESTService.o addon.o typescriptAPI.o pyminsky.o createLinkGroupIcons.o EXES=RESTService/minsky-RESTService$(EXE) @@ -229,7 +239,7 @@ ifdef CLASSDESC_ARITIES FLAGS+=-DUSE_UNROLLED -DCLASSDESC_ARITIES=$(CLASSDESC_ARITIES) endif -FLAGS+=-UTR1 -Ischema -Iengine -Imodel -Icertify/include -IRESTService -IRavelCAPI/civita -IRavelCAPI -Ilibclipboard/include -DCLASSDESC $(OPT) -UECOLAB_LIB -DECOLAB_LIB=\"library\" -DJSON_PACK_NO_FALL_THROUGH_TO_STREAMING -Wno-unused-local-typedefs -Wno-pragmas -Wno-unused-command-line-argument -Wno-unknown-warning-option -Wno-attributes -DCIVITA_ALLOCATOR=civita::LibCAllocator +FLAGS+=-UTR1 -Ischema -Iengine -Imodel -Icertify/include -Imansoura/src -IRESTService -IRavelCAPI/civita -IRavelCAPI -Ilibclipboard/include -DCLASSDESC $(OPT) -UECOLAB_LIB -DECOLAB_LIB=\"library\" -DJSON_PACK_NO_FALL_THROUGH_TO_STREAMING -Wno-unused-local-typedefs -Wno-pragmas -Wno-unused-command-line-argument -Wno-unknown-warning-option -Wno-attributes -DCIVITA_ALLOCATOR=civita::LibCAllocator ifdef OBS # Fedora environments make duplicated macros a fatal error, and then @@ -260,7 +270,7 @@ ifeq ($(DEBUG), 1) FLAGS+=-Wp,-D_GLIBCXX_ASSERTIONS endif -VPATH= schema model engine RESTService RavelCAPI/civita RavelCAPI $(ECOLAB_HOME)/include $(ECOLAB_HOME)/graphcode $(ECOLAB_HOME)/classdesc +VPATH= schema model engine RESTService RavelCAPI/civita RavelCAPI mansoura/src $(ECOLAB_HOME)/include $(ECOLAB_HOME)/graphcode $(ECOLAB_HOME)/classdesc # Classdesc rules CDINC=-I $(CDINCLUDE) -I $(ECOLAB_HOME)/include -I RESTService @@ -345,7 +355,7 @@ ifeq ($(OS),CYGWIN) FLAGS+=-Wa,-mbig-obj -Wl,-x -Wl,--oformat,pe-bigobj-x86-64 endif -LIBS:=-LRavelCAPI -lravelCAPI -LRavelCAPI/civita -lcivita -lboost_date_time$(BOOST_EXT) -lgsl -lgslcblas -lssl -lcrypto $(LIBS) +LIBS:=-Lmansoura -lmansoura -LRavelCAPI -lravelCAPI -LRavelCAPI/civita -lcivita -lboost_date_time$(BOOST_EXT) -lgsl -lgslcblas -lssl -lcrypto $(LIBS) ifdef MXE LIBS+=-lgdi32 -lcrypt32 -lbcrypt -lshcore @@ -465,7 +475,7 @@ gui-js/build/minskyRESTService.node:| $(DLLS:%=$(DYNAMIC_LIB_DIR)/%) endif # N-API node embedded RESTService -gui-js/build/minskyRESTService.node: addon.o $(NODE_API) $(RESTSERVICE_OBJS) $(MODEL_OBJS) $(SCHEMA_OBJS) $(ENGINE_OBJS) RavelCAPI/libravelCAPI.a RavelCAPI/civita/libcivita.a +gui-js/build/minskyRESTService.node: addon.o $(NODE_API) $(RESTSERVICE_OBJS) $(MODEL_OBJS) $(SCHEMA_OBJS) $(ENGINE_OBJS) mansoura/libmansoura.a RavelCAPI/libravelCAPI.a RavelCAPI/civita/libcivita.a mkdir -p gui-js/build ifdef MXE $(LINK) -shared -o $@ $^ $(LIBS) @@ -515,7 +525,7 @@ $(EXES): tests: $(EXES) cd test; $(MAKE) $(MAKEOVERRIDES) CPLUSPLUS="$(CPLUSPLUS)" -BASIC_CLEAN=rm -rf *.o *~ "\#*\#" core *.d *.cd *.rcd *.tcd *.xcd *.gcda *.gcno *.so *.dll *.dylib +BASIC_CLEAN=rm -rf *.o *~ "\#*\#" core *.d *.cd *.rcd *.tcd *.xcd *.gcda *.gcno *.so *.dll *.dylib *.a clean: -$(BASIC_CLEAN) minsky.xsd @@ -525,8 +535,9 @@ clean: -cd engine && $(BASIC_CLEAN) -cd schema && $(BASIC_CLEAN) -cd ecolab && $(MAKE) clean + -cd mansoura && $(MAKE) clean -cd RavelCAPI && $(MAKE) clean - -cd libclipboard && $(MAKE) clean && rm -f CMakeCache.txt + -cd libclipboard && $(MAKE) clean ; rm -f CMakeCache.txt mac-dist: # force rebuild of the node file to force rewriting of dependent dylibs diff --git a/RESTService/pyminsky.cc b/RESTService/pyminsky.cc index 232fb5b86..b24d73ff2 100644 --- a/RESTService/pyminsky.cc +++ b/RESTService/pyminsky.cc @@ -21,6 +21,10 @@ //#define REST_PROCESS_BUFFER classdesc::PythonBuffer #include "minsky.h" #include "CSVTools.xcd" +#include "plot.xcd" +#include "plot.rcd" +#include "SVGItem.xcd" +#include "SVGItem.rcd" #include "minsky_epilogue.h" #include "pythonBuffer.h" diff --git a/RESTService/typescriptAPI.cc b/RESTService/typescriptAPI.cc index e32c4a5c1..91e4097c8 100644 --- a/RESTService/typescriptAPI.cc +++ b/RESTService/typescriptAPI.cc @@ -6,8 +6,6 @@ #include "assetClass.tcd" #include "bookmark.h" #include "bookmark.tcd" -#include "cairoSurfaceImage.tcd" -#include "cairoRenderer.tcd" #include "callableFunction.tcd" #include "canvas.tcd" #define CLASSDESC_typescriptAPI___CAPIRenderer @@ -29,7 +27,7 @@ #include "fontDisplay.tcd" #include "godleyIcon.tcd" #include "godleyTable.tcd" -#include "godleyTableWindow.tcd" +#include "godleyTableEditor.tcd" #include "group.tcd" #include "handleLockInfo.tcd" #include "hypercube.tcd" @@ -39,14 +37,13 @@ #include "itemT.tcd" #include "lasso.tcd" #include "lock.tcd" +#include "mansouraPlot.tcd" #include "noteBase.tcd" #include "operation.tcd" #include "operationBase.tcd" #include "operationType.tcd" -#include "pango.tcd" #include "pannableTab.tcd" #include "phillipsDiagram.tcd" -#include "plot.tcd" #include "plotOptions.tcd" #include "plotWidget.tcd" #include "polyRESTProcessBase.tcd" @@ -63,6 +60,7 @@ #include "simulation.tcd" #include "slider.tcd" #include "SVGItem.tcd" +#include "SVGItem.xcd" #include "switchIcon.tcd" #include "tensorInterface.tcd" #include "tensorVal.tcd" @@ -253,11 +251,11 @@ int main() api.addClass(); api.addClass(); api.addClass(); - api.addClass(); api.addClass(); api.addClass(); api.addClass(); api.addClass(); + api.addClass(); api.addClass(); api.addClass(); api.addClass(); @@ -313,7 +311,7 @@ int main() cout << "class classdesc__pack_t {}\n"; cout << "class classdesc__RESTProcess_t {}\n"; cout << "class ecolab__cairo__Surface {}\n"; - cout << "class ICairoShim {}\n"; + cout << "class mansoura__IMansoura {}\n"; cout< -using namespace ecolab; +using namespace mansoura; using namespace std; int main() @@ -10,7 +10,7 @@ int main() const double width=30, height=10; for (int i=0; i -#undef CAIRO_WIN32_STATIC_BUILD -#include -#include - -// if not #ifdef protected, you get a deprecated warning, which is -// made fatal by -Werror -#ifndef RSVG_CAIRO_H -#include -#endif - -using namespace std; -using ecolab::Pango; - -namespace minsky -{ - CairoShimCairo::CairoShimCairo(cairo_t* c) : cairo(c) {} - - CairoShimCairo::~CairoShimCairo() = default; - - // Drawing operations - void CairoShimCairo::moveTo(double x, double y) const - {cairo_move_to(cairo,x,y);} - - void CairoShimCairo::lineTo(double x, double y) const - {cairo_line_to(cairo,x,y);} - - void CairoShimCairo::relMoveTo(double x, double y) const - {cairo_rel_move_to(cairo,x,y);} - - void CairoShimCairo::relLineTo(double x, double y) const - {cairo_rel_line_to(cairo,x,y);} - - void CairoShimCairo::arc(double x, double y, double radius, double start, double end) const - {cairo_arc(cairo,x,y,radius,start,end);} - - void CairoShimCairo::curveTo(double x1, double y1, double x2, double y2, double x3, double y3) const - {cairo_curve_to(cairo,x1,y1,x2,y2,x3,y3);} - - void CairoShimCairo::rectangle(double x, double y, double width, double height) const - {cairo_rectangle(cairo,x,y,width,height);} - - // Path operations - void CairoShimCairo::newPath() const - {cairo_new_path(cairo);} - - void CairoShimCairo::newSubPath() const - {cairo_new_sub_path(cairo);} - - void CairoShimCairo::closePath() const - {cairo_close_path(cairo);} - - void CairoShimCairo::getCurrentPoint(double& x, double& y) const - {cairo_get_current_point(cairo, &x, &y);} - - // Fill and stroke operations - void CairoShimCairo::fill() const - {cairo_fill(cairo);} - - void CairoShimCairo::fillPreserve() const - {cairo_fill_preserve(cairo);} - - void CairoShimCairo::clip() const - {cairo_clip(cairo);} - - void CairoShimCairo::resetClip() const - {cairo_reset_clip(cairo);} - - void CairoShimCairo::stroke() const - {cairo_stroke(cairo);} - - void CairoShimCairo::strokePreserve() const - {cairo_stroke_preserve(cairo);} - - void CairoShimCairo::paint() const - {cairo_paint(cairo);} - - // Line properties - void CairoShimCairo::setLineWidth(double w) const - {cairo_set_line_width(cairo, w);} - - double CairoShimCairo::getLineWidth() const - {return cairo_get_line_width(cairo);} - - void CairoShimCairo::setDash(const double* dashes, int num_dashes, double offset) const - {cairo_set_dash(cairo, dashes, num_dashes, offset);} - - void CairoShimCairo::setFillRule(cairo_fill_rule_t fill_rule) const - {cairo_set_fill_rule(cairo, fill_rule);} - - // Color operations - void CairoShimCairo::setSourceRGB(double r, double g, double b) const - {cairo_set_source_rgb(cairo,r,g,b);} - - void CairoShimCairo::setSourceRGBA(double r, double g, double b, double a) const - {cairo_set_source_rgba(cairo,r,g,b,a);} - - // Text operations - void CairoShimCairo::initPango(Pango& pango,const TextProperties& tp) const - { - if (!tp.markup.empty()) - pango.setMarkup(tp.markup); - else if (!tp.plainText.empty()) - pango.setText(tp.plainText); - pango.angle=tp.angle; - if (isfinite(tp.fontSize)) - pango.setFontSize(tp.fontSize); - if (!tp.fontFamily.empty()) - pango.setFontFamily(tp.fontFamily.c_str()); - } - - void CairoShimCairo::showText(const TextProperties& tp) const - { - if (tp.markup.empty() && tp.plainText.empty()) return; - Pango pango(cairo); - initPango(pango,tp); - pango.show(); - } - - TextExtents CairoShimCairo::textExtents(const TextProperties& tp) const - { - Pango pango(cairo); - initPango(pango,tp); - return {pango.left(), pango.top(), pango.width(), pango.height()}; - } - - // Transformation operations - void CairoShimCairo::identityMatrix() const - {cairo_identity_matrix(cairo);} - - void CairoShimCairo::translate(double x, double y) const - {cairo_translate(cairo,x,y);} - - void CairoShimCairo::scale(double sx, double sy) const - {cairo_scale(cairo,sx,sy);} - - void CairoShimCairo::rotate(double angle) const - {cairo_rotate(cairo,angle);} - - void CairoShimCairo::userToDevice(double& x, double& y) const - {cairo_user_to_device(cairo, &x, &y);} - - // Context state operations - void CairoShimCairo::save() const - {cairo_save(cairo);} - - void CairoShimCairo::restore() const - {cairo_restore(cairo);} - - // Tolerance - void CairoShimCairo::setTolerance(double tolerance) const - {cairo_set_tolerance(cairo, tolerance);} - - // SVG rendering support - void CairoShimCairo::renderSVG(const SVGRenderer& svgRenderer, double width, double height) const - { -#ifdef MXE // MXE doesn't currently have a Rust compiler, so librsvg can be no later than 2.40.21 - RsvgDimensionData dims; - rsvg_handle_get_dimensions(svgRenderer.svg, &dims); - cairo_scale(cairo, width/dims.width, height/dims.height); - rsvg_handle_render_cairo(svgRenderer.svg, cairo); -#else - GError* err=nullptr; - const RsvgRectangle rect{0,0,width,height}; - rsvg_handle_render_document(svgRenderer.svg, cairo, &rect, &err); - if (err) - g_error_free(err); -#endif - } - - struct PangoCache: public ICacheRender, public Pango - { - PangoCache(cairo_t* cr, const TextProperties& tp): Pango(cr) - { - if (!tp.markup.empty()) - setMarkup(tp.markup); - else - setText(tp.plainText); - setFontSize(tp.fontSize); - if (!tp.fontFamily.empty()) - setFontFamily(tp.fontFamily.c_str()); - angle=tp.angle; - } - void show() override {Pango::show();} - TextExtents extents() const override - {return TextExtents{left(),top(),width(),height()};} - - void* context() const override - {return cairoContext();} - }; - - std::unique_ptr - CairoShimCairo::cachedRender(const TextProperties& tp) const - {return make_unique(cairo,tp);} -} diff --git a/engine/cairoShimCairo.h b/engine/cairoShimCairo.h deleted file mode 100644 index 45eaaa888..000000000 --- a/engine/cairoShimCairo.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef CAIROSHIMCAIRO_H -#define CAIROSHIMCAIRO_H -#include "ICairoShim.h" -#include "SVGItem.h" -#include -#include -#include - -namespace ecolab { class Pango; } - -namespace minsky -{ - /// Concrete implementation of ICairoShim using actual Cairo library - class CairoShimCairo: public ICairoShim - { - cairo_t* cairo; - void initPango(ecolab::Pango&,const TextProperties&) const; - CairoShimCairo(const CairoShimCairo&)=delete; - void operator=(const CairoShimCairo&)=delete; - public: - CairoShimCairo(cairo_t* c); - ~CairoShimCairo() override; - - // Drawing operations - void moveTo(double x, double y) const override; - void lineTo(double x, double y) const override; - void relMoveTo(double x, double y) const override; - void relLineTo(double x, double y) const override; - void arc(double x, double y, double radius, double start, double end) const override; - void curveTo(double x1, double y1, double x2, double y2, double x3, double y3) const override; - void rectangle(double x, double y, double width, double height) const override; - - // Path operations - void newPath() const override; - void newSubPath() const override; - void closePath() const override; - void getCurrentPoint(double& x, double& y) const override; - - // Fill and stroke operations - void fill() const override; - void fillPreserve() const override; - void stroke() const override; - void strokePreserve() const override; - void clip() const override; - void resetClip() const override; - void paint() const override; - - // Line properties - void setLineWidth(double width) const override; - double getLineWidth() const override; - void setDash(const double* dashes, int num_dashes, double offset) const override; - void setFillRule(cairo_fill_rule_t fill_rule) const override; - - // Color operations - void setSourceRGB(double r, double g, double b) const override; - void setSourceRGBA(double r, double g, double b, double a) const override; - - // Text operations - void showText(const TextProperties& text) const override; - TextExtents textExtents(const TextProperties& text) const override; - - // Transformation operations - void identityMatrix() const override; - void translate(double x, double y) const override; - void scale(double sx, double sy) const override; - void rotate(double angle) const override; - void userToDevice(double& x, double& y) const override; - - // Context state operations - void save() const override; - void restore() const override; - - // Tolerance - void setTolerance(double tolerance) const override; - - // SVG rendering support - void renderSVG(const SVGRenderer& svgRenderer, double width, double height) const override; - - // TEMPORARY: Internal accessor for migration - to be removed once all implementations are updated - cairo_t* _internalGetCairoContext() const { return cairo; } - - void* context() const override {return cairo;} - - std::unique_ptr - cachedRender(const TextProperties& tp) const override; - }; -} - -#include "cairoShimCairo.xcd" -#endif diff --git a/engine/equationDisplayRender.cc b/engine/equationDisplayRender.cc index 55c0015c2..d2e4b2c8c 100644 --- a/engine/equationDisplayRender.cc +++ b/engine/equationDisplayRender.cc @@ -23,11 +23,11 @@ #include "selection.h" #include "lasso.h" #include "userFunction.h" -#include +#include "mansouraCairo.h" #include "minsky_epilogue.h" using namespace ecolab; -using ecolab::cairo::Surface; -using ecolab::cairo::CairoSave; +using mansoura::IMansoura; +using mansoura::PreserveContext; namespace MathDAG { @@ -38,112 +38,131 @@ namespace MathDAG // move pen to the anchor point of \a object template - void moveToAnchor(cairo_t* cairo, const T& object, Anchor anchor) + void moveToAnchor(const IMansoura& cairo, const T& object, Anchor anchor) { switch (anchor) { case Anchor::n: - cairo_rel_move_to(cairo, -0.5*object.width(), 0); break; + cairo.relMoveTo(-0.5*object.width(), 0); break; case Anchor::s: - cairo_rel_move_to(cairo, -0.5*object.width(), -object.height()); break; + cairo.relMoveTo(-0.5*object.width(), -object.height()); break; case Anchor::e: - cairo_rel_move_to(cairo, object.width(), -0.5*object.height()); break; + cairo.relMoveTo(object.width(), -0.5*object.height()); break; case Anchor::w: - cairo_rel_move_to(cairo, 0, -0.5*object.height()); break; + cairo.relMoveTo(0, -0.5*object.height()); break; case Anchor::ne: - cairo_rel_move_to(cairo, -object.width(), 0); break; + cairo.relMoveTo(-object.width(), 0); break; case Anchor::nw: break; case Anchor::se: - cairo_rel_move_to(cairo, -object.width(), -object.height()); break; + cairo.relMoveTo(-object.width(), -object.height()); break; case Anchor::sw: - cairo_rel_move_to(cairo, 0, -object.height()); break; + cairo.relMoveTo(0, -object.height()); break; } } + /// text laid out with pango markup, drawn at the current point of a context + class Text + { + std::unique_ptr r; + public: + Text(const IMansoura& ctx): r(ctx.cachedRender(mansoura::TextProperties())) {} + void setMarkup(const string& m) {r->setMarkup(m);} + void setFontSize(double sz) {r->setFontSize(sz);} + double getFontSize() const {return r->fontSize();} + void show() {r->show();} + double width() const {return r->extents().width;} + double height() const {return r->extents().height;} + }; + // renders latex string to \a cairo, anchored at \a anchor // move current point to RHS of text, and returns the height - double print(cairo_t* cairo, const string& text, Anchor anchor) + double print(const IMansoura& cairo, const string& text, Anchor anchor) { - Pango pango(cairo); + Text pango(cairo); { - const CairoSave cs(cairo); + const PreserveContext cs(cairo); pango.setMarkup(text); moveToAnchor(cairo, pango, anchor); pango.show(); } - cairo_rel_move_to(cairo, pango.width(), 0); + cairo.relMoveTo(pango.width(), 0); return pango.height(); } - struct RecordingSurface: public Surface + /// a context that records what is drawn to it, for measuring purposes + struct RecordingSurface { - RecordingSurface(): Surface(cairo_recording_surface_create - (CAIRO_CONTENT_COLOR, nullptr)) - {cairo_move_to(cairo(),0,0);} + std::unique_ptr ctx=mansoura::makeRecordingContext(); + RecordingSurface() {ctx->moveTo(0,0);} + operator const IMansoura&() const {return *ctx;} + double left() const {return mansoura::recordedInkExtents(*ctx).left;} + double top() const {return mansoura::recordedInkExtents(*ctx).top;} + double width() const {return mansoura::recordedInkExtents(*ctx).width;} + double height() const {return mansoura::recordedInkExtents(*ctx).height;} }; // renders \a x a function taking a Surface, with big enough brackets around them template - double parenthesise(Surface& s, X x, const string& left="(", const string& right=")") + double parenthesise(const IMansoura& s, X x, const string& left="(", const string& right=")") { double xx,yy; - cairo_get_current_point(s.cairo(),&xx,&yy); + s.getCurrentPoint(xx,yy); RecordingSurface r; x(r); - Pango pango(s.cairo()); + Text pango(s); const double oldFs=pango.getFontSize(); pango.setFontSize(r.height()); pango.setMarkup(left); - cairo_rel_move_to(s.cairo(),0,-(r.height()-oldFs)); + s.relMoveTo(0,-(r.height()-oldFs)); pango.show(); - cairo_rel_move_to(s.cairo(),0,(r.height()-oldFs)); - cairo_rel_move_to(s.cairo(),pango.width(),0); + s.relMoveTo(0,(r.height()-oldFs)); + s.relMoveTo(pango.width(),0); x(s); xx+=pango.width()+r.width(); pango.setMarkup(right); - cairo_move_to(s.cairo(),xx,yy-r.height()+oldFs); + s.moveTo(xx,yy-r.height()+oldFs); pango.show(); - cairo_move_to(s.cairo(),xx+pango.width(),yy); + s.moveTo(xx+pango.width(),yy); return r.height(); } // render list of arguments separated by \a op, or \a empty if arglist is empty - void naryRender(Surface& dest, const vector& arglist, int BODMASlevel, const char* op, const char *empty) + void naryRender(const IMansoura& dest, const vector& arglist, int BODMASlevel, const char* op, const char *empty) { if (arglist.empty()) - print(dest.cairo(),empty,Anchor::nw); + print(dest,empty,Anchor::nw); else for (size_t j=0; jBODMASlevel()>BODMASlevel) - parenthesise(dest, [&](Surface& dest) {arglist[j]->render(dest);}); + parenthesise(dest, [&](const IMansoura& dest) {arglist[j]->render(dest);}); else arglist[j]->render(dest); if (j!=arglist.size()-1) - print(dest.cairo(),op,Anchor::nw); + print(dest,op,Anchor::nw); } } - void variableRender(Surface& surf, const VariableDAG& v) + void variableRender(const IMansoura& surf, const VariableDAG& v) { - print(surf.cairo(), latexToPango(v.name)+" = ", Anchor::nw); + print(surf, latexToPango(v.name)+" = ", Anchor::nw); if (v.rhs) v.rhs->render(surf); else - print(surf.cairo(), latexToPango(latexInit(v.init)), Anchor::nw); + print(surf, latexToPango(latexInit(v.init)), Anchor::nw); } } - void SystemOfEquations::renderEquations(Surface& dest, double height) const + void SystemOfEquations::renderEquations(const IMansoura& dest, double height) const { double x, y; // starting position of current line - cairo_get_current_point(dest.cairo(),&x,&y); + dest.getCurrentPoint(x,y); const double origin=-y; - Pango den(dest.cairo()); + Text den(dest); den.setMarkup("dt"); const double fontHeight=30; @@ -157,10 +176,10 @@ namespace MathDAG if (eqnNo++ < baseEqn) continue; RecordingSurface line; variableRender(line,*i); - cairo_move_to(dest.cairo(), x, y-line.top()); + dest.moveTo(x, y-line.top()); variableRender(dest,*i); y+=line.height()+4; - cairo_move_to(dest.cairo(), x, y); + dest.moveTo(x, y); if (y>height) return; } @@ -168,12 +187,12 @@ namespace MathDAG { if (eqnNo++ < baseEqn) continue; // initial conditions - cairo_move_to(dest.cairo(), x, y); // needed to define a current point on the equations tab. for ticket 1256 - y+=print(dest.cairo(), latexToPango(mathrm(i->name))+"(0) = "+ + dest.moveTo(x, y); // needed to define a current point on the equations tab. for ticket 1256 + y+=print(dest, latexToPango(mathrm(i->name))+"(0) = "+ latexToPango(latexInit(i->init)),Anchor::nw); // differential equation - Pango num(dest.cairo()); + Text num(dest); num.setMarkup("d"+latexToPango(mathrm(i->name))); double lineSpacing=num.height()+den.height()+2; @@ -188,89 +207,89 @@ namespace MathDAG // vertical location of the = sign const double eqY=y+max(num.height(), 0.5*lineSpacing); - cairo_move_to(dest.cairo(), x, eqY-num.height()); + dest.moveTo(x, eqY-num.height()); num.show(); - cairo_move_to(dest.cairo(), x, eqY); + dest.moveTo(x, eqY); const double solidusLength = max(num.width(),den.width()); - cairo_rel_line_to(dest.cairo(), solidusLength, 0); - cairo_stroke(dest.cairo()); - cairo_move_to(dest.cairo(), x+solidusLength, eqY); + dest.relLineTo(solidusLength, 0); + dest.stroke(); + dest.moveTo(x+solidusLength, eqY); // display RHS here if (input && input->rhs) { - print(dest.cairo()," = ", Anchor::w); + print(dest," = ", Anchor::w); input->rhs->render(dest); } else - print(dest.cairo()," = 0", Anchor::w); - cairo_move_to(dest.cairo(), x+0.5*(num.width()-den.width()), eqY); + print(dest," = 0", Anchor::w); + dest.moveTo(x+0.5*(num.width()-den.width()), eqY); den.show(); - cairo_move_to(dest.cairo(), x, y+=lineSpacing);// move to next line + dest.moveTo(x, y+=lineSpacing);// move to next line if (y>height) return; } } - void ConstantDAG::render(ecolab::cairo::Surface& surf) const + void ConstantDAG::render(const IMansoura& surf) const { - print(surf.cairo(), latexToPango(value),Anchor::nw); + print(surf, latexToPango(value),Anchor::nw); } - void VariableDAG::render(ecolab::cairo::Surface& surf) const + void VariableDAG::render(const IMansoura& surf) const { - print(surf.cairo(), latexToPango(mathrm(name)), Anchor::nw); + print(surf, latexToPango(mathrm(name)), Anchor::nw); } - void LockDAG::render(ecolab::cairo::Surface& surf) const + void LockDAG::render(const IMansoura& surf) const { - print(surf.cairo(), "locked", Anchor::nw); + print(surf, "locked", Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { assert(!"constant deprecated"); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { for (size_t i=0; i - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty()) naryRender(surf, arguments[0], BODMASlevel(), " + ","0"); if (arguments.size()>1) { - print(surf.cairo()," - ",Anchor::nw); + print(surf," - ",Anchor::nw); if (arguments[1].size()>1 || (!arguments[1].empty() && BODMASlevel() == arguments[1][0]->BODMASlevel())) - parenthesise(surf, [&](Surface& s){naryRender(s,arguments[1], BODMASlevel(), " + ","0");}); + parenthesise(surf, [&](const IMansoura& s){naryRender(s,arguments[1], BODMASlevel(), " + ","0");}); else naryRender(surf, arguments[1], BODMASlevel(), " + ","0"); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { for (size_t i=0; i - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { RecordingSurface num, den; if (!arguments.empty()) @@ -282,23 +301,23 @@ namespace MathDAG if (!arguments[1].empty()) { double x, y; // starting position of current line - cairo_get_current_point(surf.cairo(),&x,&y); + surf.getCurrentPoint(x,y); const double solidusLength = std::max(num.width(),den.width()); - cairo_move_to(surf.cairo(), x+0.5*(solidusLength-num.width()), y-num.height()); + surf.moveTo(x+0.5*(solidusLength-num.width()), y-num.height()); naryRender(surf, arguments[0], BODMASlevel()," × ","1"); - cairo_move_to(surf.cairo(), x+0.5*(solidusLength-den.width()), y+0.5*num.height()+5); + surf.moveTo(x+0.5*(solidusLength-den.width()), y+0.5*num.height()+5); naryRender(surf, arguments[1], BODMASlevel()," × ","1"); - cairo_move_to(surf.cairo(), x, y+0.5*num.height()+5); - cairo_rel_line_to(surf.cairo(), solidusLength, 0); + surf.moveTo(x, y+0.5*num.height()+5); + surf.relLineTo(solidusLength, 0); { - const CairoSave cs(surf.cairo()); - cairo_set_line_width(surf.cairo(),1); - cairo_stroke(surf.cairo()); + const PreserveContext cs(surf); + surf.setLineWidth(1); + surf.stroke(); } - cairo_move_to(surf.cairo(),x+solidusLength,y); + surf.moveTo(x+solidusLength,y); } else // denominator =1, so just render the numerator naryRender(surf, arguments[0], BODMASlevel()," × ","1"); @@ -308,126 +327,126 @@ namespace MathDAG } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (arguments.empty() || arguments[0].empty() || !arguments[0][0]) - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); else { if (arguments.size()>1 && !arguments[1].empty() && arguments[1][0]) { - const double h=print(surf.cairo(),"log",Anchor::nw); - cairo_rel_move_to(surf.cairo(), 0, 0.5*h); + const double h=print(surf,"log",Anchor::nw); + surf.relMoveTo(0, 0.5*h); arguments[1][0]->render(surf); - cairo_rel_move_to(surf.cairo(), 0, -0.5*h); + surf.relMoveTo(0, -0.5*h); } else - print(surf.cairo(),"ln",Anchor::nw); + print(surf,"ln",Anchor::nw); arguments[0][0]->render(surf); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),""+dynamic_cast(*state).description()+"",Anchor::nw); + print(surf,""+dynamic_cast(*state).description()+"",Anchor::nw); if (arguments.empty() || arguments[0].empty() || !arguments[0][0]) - print(surf.cairo(),"(0,0)",Anchor::nw); + print(surf,"(0,0)",Anchor::nw); else - parenthesise(surf, [&](Surface& surf){ + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); - print(surf.cairo(),",",Anchor::nw); + print(surf,",",Anchor::nw); if (arguments.size()>1 && !arguments[1].empty() && arguments[1][0]) arguments[1][0]->render(surf); else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); }); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (arguments.empty() || arguments[0].empty() || !arguments[0][0]) - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); else { if (arguments.size()>1 && !arguments[1].empty() && arguments[1][0]) { if (arguments[0][0]->BODMASlevel()>BODMASlevel()) - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); else arguments[0][0]->render(surf); RecordingSurface base; arguments[0][0]->render(base); - cairo_rel_move_to(surf.cairo(), 0, -0.5*base.height()); + surf.relMoveTo(0, -0.5*base.height()); arguments[1][0]->render(surf); - cairo_rel_move_to(surf.cairo(), 0, 0.5*base.height()); + surf.relMoveTo(0, 0.5*base.height()); } else - print(surf.cairo(),"1",Anchor::nw); + print(surf,"1",Anchor::nw); } } template <> - void OperationDAG::render(Surface& surf) const - {print(surf.cairo(),"t",Anchor::nw);} + void OperationDAG::render(const IMansoura& surf) const + {print(surf,"t",Anchor::nw);} template <> - void OperationDAG::render(Surface& surf) const - {print(surf.cairo(),"e",Anchor::nw);} + void OperationDAG::render(const IMansoura& surf) const + {print(surf,"e",Anchor::nw);} template <> - void OperationDAG::render(Surface& surf) const - {print(surf.cairo(),"π",Anchor::nw);} + void OperationDAG::render(const IMansoura& surf) const + {print(surf,"π",Anchor::nw);} template <> - void OperationDAG::render(Surface& surf) const - {print(surf.cairo(),"0",Anchor::nw);} + void OperationDAG::render(const IMansoura& surf) const + {print(surf,"0",Anchor::nw);} template <> - void OperationDAG::render(Surface& surf) const - {print(surf.cairo(),"1",Anchor::nw);} + void OperationDAG::render(const IMansoura& surf) const + {print(surf,"1",Anchor::nw);} template <> - void OperationDAG::render(Surface& surf) const - {print(surf.cairo(),"∞",Anchor::nw);} + void OperationDAG::render(const IMansoura& surf) const + {print(surf,"∞",Anchor::nw);} template <> - void OperationDAG::render(Surface& s) const + void OperationDAG::render(const IMansoura& s) const { double xx,yy; - cairo_get_current_point(s.cairo(),&xx,&yy); + s.getCurrentPoint(xx,yy); RecordingSurface r; arguments[0][0]->render(r); - Pango pango(s.cairo()); + Text pango(s); const double oldFs=pango.getFontSize(); pango.setFontSize(r.height()); - cairo_rel_move_to(s.cairo(),0,-(r.height()-oldFs)); + s.relMoveTo(0,-(r.height()-oldFs)); pango.show(); - cairo_rel_move_to(s.cairo(),0,(r.height()-oldFs)); - cairo_rel_move_to(s.cairo(),pango.width(),0); + s.relMoveTo(0,(r.height()-oldFs)); + s.relMoveTo(pango.width(),0); arguments[0][0]->render(s); xx+=pango.width()+r.width(); pango.setMarkup("%"); - cairo_move_to(s.cairo(),xx,yy-r.height()+oldFs); + s.moveTo(xx,yy-r.height()+oldFs); pango.show(); - cairo_move_to(s.cairo(),xx+pango.width(),yy); + s.moveTo(xx+pango.width(),yy); } template <> - void OperationDAG::render(Surface& surf) const - {print(surf.cairo(),"=",Anchor::nw);} + void OperationDAG::render(const IMansoura& surf) const + {print(surf,"=",Anchor::nw);} template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const {throw error("should not be rendering integration operations");} // if (IntOp* i=dynamic_cast(state.get())) // if (VariablePtr v=i->intVar) -// print(surf.cairo(), latexToPango(mathrm(v->name())),Anchor::nw); +// print(surf, latexToPango(mathrm(v->name())),Anchor::nw); // } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const {throw error("should not be rendering differentiation operations");} template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { @@ -435,400 +454,400 @@ namespace MathDAG arguments[0][0]->render(arg); // display a scaled surd. - Pango pango(surf.cairo()); + Text pango(surf); { - const CairoSave cs(surf.cairo()); + const PreserveContext cs(surf); const double oldFs=pango.getFontSize(); pango.setFontSize(arg.height()); pango.setMarkup("√"); - cairo_rel_move_to(surf.cairo(),0,oldFs-arg.height()); + surf.relMoveTo(0,oldFs-arg.height()); pango.show(); } - cairo_rel_move_to(surf.cairo(),pango.width(),0); + surf.relMoveTo(pango.width(),0); // draw an overbar double x,y; - cairo_get_current_point(surf.cairo(),&x,&y); + surf.getCurrentPoint(x,y); { - const CairoSave cs(surf.cairo()); - cairo_rel_line_to(surf.cairo(),arg.width(),0); - cairo_set_line_width(surf.cairo(),1); - cairo_stroke(surf.cairo()); + const PreserveContext cs(surf); + surf.relLineTo(arg.width(),0); + surf.setLineWidth(1); + surf.stroke(); } - cairo_move_to(surf.cairo(),x,y-arg.top()+2); + surf.moveTo(x,y-arg.top()+2); arguments[0][0]->render(surf); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (auto d=dynamic_cast(state.get())) - print(surf.cairo(),latexToPango(mathrm(d->description())),Anchor::nw); + print(surf,latexToPango(mathrm(d->description())),Anchor::nw); else - print(surf.cairo(),latexToPango(mathrm("\\uplus")),Anchor::nw); + print(surf,latexToPango(mathrm("\\uplus")),Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (auto d=dynamic_cast(state.get())) - print(surf.cairo(),latexToPango(mathrm(d->description())),Anchor::nw); + print(surf,latexToPango(mathrm(d->description())),Anchor::nw); else - print(surf.cairo(),latexToPango(mathrm("\\uplus")),Anchor::nw); + print(surf,latexToPango(mathrm("\\uplus")),Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"exp",Anchor::nw); + print(surf,"exp",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"ln",Anchor::nw); + print(surf,"ln",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"sin",Anchor::nw); + print(surf,"sin",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"cos",Anchor::nw); + print(surf,"cos",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"tan",Anchor::nw); + print(surf,"tan",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"sin-1",Anchor::nw); + print(surf,"sin-1",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"cos-1",Anchor::nw); + print(surf,"cos-1",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"tan-1",Anchor::nw); + print(surf,"tan-1",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"sinh",Anchor::nw); + print(surf,"sinh",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"cosh",Anchor::nw); + print(surf,"cosh",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"tanh",Anchor::nw); + print(surf,"tanh",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& s) const + void OperationDAG::render(const IMansoura& s) const { double xx,yy; - cairo_get_current_point(s.cairo(),&xx,&yy); + s.getCurrentPoint(xx,yy); RecordingSurface r; arguments[0][0]->render(r); - Pango pango(s.cairo()); + Text pango(s); const double oldFs=pango.getFontSize(); pango.setFontSize(r.height()); pango.setMarkup("|"); - cairo_rel_move_to(s.cairo(),0,-(r.height()-oldFs)); + s.relMoveTo(0,-(r.height()-oldFs)); pango.show(); - cairo_rel_move_to(s.cairo(),0,(r.height()-oldFs)); - cairo_rel_move_to(s.cairo(),pango.width(),0); + s.relMoveTo(0,(r.height()-oldFs)); + s.relMoveTo(pango.width(),0); arguments[0][0]->render(s); xx+=pango.width()+r.width(); pango.setMarkup("|"); - cairo_move_to(s.cairo(),xx,yy-r.height()+oldFs); + s.moveTo(xx,yy-r.height()+oldFs); pango.show(); - cairo_move_to(s.cairo(),xx+pango.width(),yy); + s.moveTo(xx+pango.width(),yy); } template <> - void OperationDAG::render(Surface& s) const + void OperationDAG::render(const IMansoura& s) const { double xx,yy; - cairo_get_current_point(s.cairo(),&xx,&yy); + s.getCurrentPoint(xx,yy); RecordingSurface r; arguments[0][0]->render(r); - Pango pango(s.cairo()); + Text pango(s); const double oldFs=pango.getFontSize(); pango.setFontSize(r.height()); pango.setMarkup("⌊"); - cairo_rel_move_to(s.cairo(),0,-(r.height()-oldFs)); + s.relMoveTo(0,-(r.height()-oldFs)); pango.show(); - cairo_rel_move_to(s.cairo(),0,(r.height()-oldFs)); - cairo_rel_move_to(s.cairo(),pango.width(),0); + s.relMoveTo(0,(r.height()-oldFs)); + s.relMoveTo(pango.width(),0); arguments[0][0]->render(s); xx+=pango.width()+r.width(); pango.setMarkup("⌋"); - cairo_move_to(s.cairo(),xx,yy-r.height()+oldFs); + s.moveTo(xx,yy-r.height()+oldFs); pango.show(); - cairo_move_to(s.cairo(),xx+pango.width(),yy); + s.moveTo(xx+pango.width(),yy); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"frac",Anchor::nw); + print(surf,"frac",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"Γ",Anchor::nw); + print(surf,"Γ",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) - {parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);});} + {parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);});} } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"ψ",Anchor::nw); + print(surf,"ψ",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { if (arguments.size()>1 && !arguments[1].empty() && arguments[1][0]) { RecordingSurface base; arguments[1][0]->render(base); - cairo_rel_move_to(surf.cairo(), 0, -0.5*base.height()); - parenthesise(surf, [&](Surface& surf){arguments[1][0]->render(surf);}); + surf.relMoveTo(0, -0.5*base.height()); + parenthesise(surf, [&](const IMansoura& surf){arguments[1][0]->render(surf);}); arguments[0][0]->render(base); - cairo_rel_move_to(surf.cairo(), 0, 0.5*base.height()); - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); + surf.relMoveTo(0, 0.5*base.height()); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); } else - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); } } template <> - void OperationDAG::render(Surface& s) const + void OperationDAG::render(const IMansoura& s) const { double xx,yy; - cairo_get_current_point(s.cairo(),&xx,&yy); + s.getCurrentPoint(xx,yy); RecordingSurface r; arguments[0][0]->render(r); - Pango pango(s.cairo()); + Text pango(s); const double oldFs=pango.getFontSize(); pango.setFontSize(r.height()); - cairo_rel_move_to(s.cairo(),0,-(r.height()-oldFs)); + s.relMoveTo(0,-(r.height()-oldFs)); pango.show(); - cairo_rel_move_to(s.cairo(),0,(r.height()-oldFs)); - cairo_rel_move_to(s.cairo(),pango.width(),0); + s.relMoveTo(0,(r.height()-oldFs)); + s.relMoveTo(pango.width(),0); arguments[0][0]->render(s); xx+=pango.width()+r.width(); pango.setMarkup("!"); - cairo_move_to(s.cairo(),xx,yy-r.height()+oldFs); + s.moveTo(xx,yy-r.height()+oldFs); pango.show(); - cairo_move_to(s.cairo(),xx+pango.width(),yy); + s.moveTo(xx+pango.width(),yy); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"∑i",Anchor::nw); + print(surf,"∑i",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - const double h=parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); - cairo_rel_move_to(surf.cairo(), 0, 0.5*h); - print(surf.cairo(),"i",Anchor::nw); - cairo_rel_move_to(surf.cairo(), 0, -0.5*h); + const double h=parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); + surf.relMoveTo(0, 0.5*h); + print(surf,"i",Anchor::nw); + surf.relMoveTo(0, -0.5*h); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"∏i",Anchor::nw); + print(surf,"∏i",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); - print(surf.cairo(),"i",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); + print(surf,"i",Anchor::nw); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"mini",Anchor::nw); + print(surf,"mini",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); - print(surf.cairo(),"i",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); + print(surf,"i",Anchor::nw); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"mini",Anchor::nw); + print(surf,"mini",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); - print(surf.cairo(),"i",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); + print(surf,"i",Anchor::nw); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"indexOf",Anchor::nw); - parenthesise(surf, [&](Surface& surf){OperationDAG().render(surf);}); + print(surf,"indexOf",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){OperationDAG().render(surf);}); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"indexOf",Anchor::nw); - parenthesise(surf, [&](Surface& surf){OperationDAG().render(surf);}); + print(surf,"indexOf",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){OperationDAG().render(surf);}); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"Θ(maxi",Anchor::nw); + print(surf,"Θ(maxi",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); - print(surf.cairo(),"i>0.5)",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); + print(surf,"i>0.5)",Anchor::nw); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"∏iΘ(",Anchor::nw); + print(surf,"∏iΘ(",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); - print(surf.cairo(),"i>0.5)",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); + print(surf,"i>0.5)",Anchor::nw); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"∑j=0i",Anchor::nw); + print(surf,"∑j=0i",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); - print(surf.cairo(),"j",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); + print(surf,"j",Anchor::nw); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"(1/i)∑j=0i",Anchor::nw); + print(surf,"(1/i)∑j=0i",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); - print(surf.cairo(),"j",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); + print(surf,"j",Anchor::nw); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"∏j=0i",Anchor::nw); + print(surf,"∏j=0i",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); - print(surf.cairo(),"j",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); + print(surf,"j",Anchor::nw); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"Δ⁻ᵢ",Anchor::nw); + print(surf,"Δ⁻ᵢ",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); - print(surf.cairo(),"i",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); + print(surf,"i",Anchor::nw); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"Δ⁺ᵢ",Anchor::nw); + print(surf,"Δ⁺ᵢ",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); - print(surf.cairo(),"i",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); + print(surf,"i",Anchor::nw); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { - print(surf.cairo(),"index",Anchor::nw); + print(surf,"index",Anchor::nw); if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty()) { if (!arguments[1].empty() && arguments[1][0]) if (!arguments[0].empty() && arguments[0][0]) { - print(surf.cairo(),"θ",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"θ",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ arguments[1][0]->render(surf); - print(surf.cairo()," - ",Anchor::nw); + print(surf," - ",Anchor::nw); if (arguments[0][0]->BODMASlevel()>1) - parenthesise(surf, [&](Surface& surf){ + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); }); else @@ -837,17 +856,17 @@ namespace MathDAG } else { - print(surf.cairo(),"θ",Anchor::nw); - parenthesise(surf, [&](Surface& surf){arguments[1][0]->render(surf);}); + print(surf,"θ",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[1][0]->render(surf);}); } else if (!arguments[0].empty() && arguments[0][0]) { - print(surf.cairo(),"θ",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ - print(surf.cairo()," - ",Anchor::nw); + print(surf,"θ",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ + print(surf," - ",Anchor::nw); if (arguments[0][0]->BODMASlevel()>1) - parenthesise(surf, [&](Surface& surf){ + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); }); else @@ -855,47 +874,47 @@ namespace MathDAG }); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty()) { if (!arguments[1].empty() && arguments[1][0]) if (!arguments[0].empty() && arguments[0][0]) { - print(surf.cairo(),"δ",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"δ",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); - print(surf.cairo()," - ",Anchor::nw); + print(surf," - ",Anchor::nw); arguments[1][0]->render(surf); }); } else { - print(surf.cairo(),"δ",Anchor::nw); - parenthesise(surf, [&](Surface& surf){arguments[1][0]->render(surf);}); + print(surf,"δ",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[1][0]->render(surf);}); } else if (!arguments[0].empty() && arguments[0][0]) { - print(surf.cairo(),"δ",Anchor::nw); - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); + print(surf,"δ",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); } else - print(surf.cairo(),"1",Anchor::nw); + print(surf,"1",Anchor::nw); } else - print(surf.cairo(),"1",Anchor::nw); + print(surf,"1",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if ((!arguments.empty() && !arguments[0].empty() && arguments[0][0]) || (arguments.size()>1 && !arguments[1].empty() && arguments[1][0])) @@ -903,349 +922,349 @@ namespace MathDAG OperationDAG lt; lt.arguments=arguments; OperationDAG eq; eq.arguments=arguments; lt.render(surf); - print(surf.cairo(),"+",Anchor::nw); + print(surf,"+",Anchor::nw); eq.render(surf); } else - print(surf.cairo(),"1",Anchor::nw); + print(surf,"1",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty()) { - print(surf.cairo(),"min",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"min",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ naryRender(surf,arguments[0],BODMASlevel(),",","∞"); if (!arguments[1].empty()) { - print(surf.cairo(),",",Anchor::nw); + print(surf,",",Anchor::nw); naryRender(surf,arguments[1],BODMASlevel(),",","∞"); } }); } else - print(surf.cairo(),"∞",Anchor::nw); + print(surf,"∞",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty()) { - print(surf.cairo(),"max",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"max",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ naryRender(surf,arguments[0],BODMASlevel(),",","-∞"); if (!arguments[1].empty()) { - print(surf.cairo(),",",Anchor::nw); + print(surf,",",Anchor::nw); naryRender(surf,arguments[1],BODMASlevel(),",","-∞"); } }); } else - print(surf.cairo(),"-∞",Anchor::nw); + print(surf,"-∞",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty()) { naryRender(surf,arguments[0],BODMASlevel(),"∧","1"); if (!arguments[1].empty()) { - print(surf.cairo(),"∧",Anchor::nw); + print(surf,"∧",Anchor::nw); naryRender(surf,arguments[0],BODMASlevel(),"∧","1"); } } else - print(surf.cairo(),"1",Anchor::nw); + print(surf,"1",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty()) { naryRender(surf,arguments[0],BODMASlevel(),"∨","0"); if (!arguments[1].empty()) { - print(surf.cairo(),"∨",Anchor::nw); + print(surf,"∨",Anchor::nw); naryRender(surf,arguments[0],BODMASlevel(),"∨","0"); } } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty()) { if (!arguments[0].empty() && arguments[0][0]) { - print(surf.cairo(),"¬",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"¬",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); }); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty() && !arguments[0].empty() && arguments[0][0] && arguments.size()>1 && !arguments[1].empty() && arguments[1][0]) { - print(surf.cairo(),"cov",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"cov",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); - print(surf.cairo(),",",Anchor::nw); + print(surf,",",Anchor::nw); arguments[1][0]->render(surf); }); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty() && !arguments[0].empty() && arguments[0][0] && arguments.size()>1 && !arguments[1].empty() && arguments[1][0]) { - print(surf.cairo(),"ρ",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"ρ",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); - print(surf.cairo(),",",Anchor::nw); + print(surf,",",Anchor::nw); arguments[1][0]->render(surf); }); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty() && !arguments[0].empty() && arguments[0][0] && arguments.size()>1 && !arguments[1].empty() && arguments[1][0]) { - print(surf.cairo(),"linReg",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"linReg",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); - print(surf.cairo(),",",Anchor::nw); + print(surf,",",Anchor::nw); arguments[1][0]->render(surf); }); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty() && !arguments[0].empty() && arguments[0][0] && arguments.size()>1 && !arguments[1].empty() && arguments[1][0]) { - print(surf.cairo(),"bLinReg",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"bLinReg",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); - print(surf.cairo(),",",Anchor::nw); + print(surf,",",Anchor::nw); arguments[1][0]->render(surf); }); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - print(surf.cairo(),"dim",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"dim",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); - print(surf.cairo(),",i",Anchor::nw); // TODO - can we extract the actual argument here? + print(surf,",i",Anchor::nw); // TODO - can we extract the actual argument here? }); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - print(surf.cairo(),"shape",Anchor::nw); - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); + print(surf,"shape",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}, "<",">"); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}, "<",">"); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - print(surf.cairo(),"median",Anchor::nw); - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); + print(surf,"median",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - print(surf.cairo(),"σ",Anchor::nw); - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); + print(surf,"σ",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - parenthesise(surf, [&](Surface& surf){ - print(surf.cairo(),"Δ",Anchor::nw); - parenthesise(surf,[&](Surface& surf){arguments[0][0]->render(surf);}); + parenthesise(surf, [&](const IMansoura& surf){ + print(surf,"Δ",Anchor::nw); + parenthesise(surf,[&](const IMansoura& surf){arguments[0][0]->render(surf);}); RecordingSurface base; arguments[0][0]->render(base); - cairo_rel_move_to(surf.cairo(), 0, -0.5*base.height()); - print(surf.cairo(),"k",Anchor::nw); // TODO can we extract the actual exponent here? - cairo_rel_move_to(surf.cairo(), 0, 0.5*base.height()); + surf.relMoveTo(0, -0.5*base.height()); + print(surf,"k",Anchor::nw); // TODO can we extract the actual exponent here? + surf.relMoveTo(0, 0.5*base.height()); },"<",">"); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (!arguments.empty() && !arguments[0].empty() && arguments[0][0]) { - print(surf.cairo(),"histogram",Anchor::nw); - parenthesise(surf, [&](Surface& surf){arguments[0][0]->render(surf);}); + print(surf,"histogram",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){arguments[0][0]->render(surf);}); } else - print(surf.cairo(),"0",Anchor::nw); + print(surf,"0",Anchor::nw); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (arguments.size()<2 || arguments[0].empty() || arguments[1].empty()) throw error("incorrectly wired"); - parenthesise(surf, [&](Surface& surf){ + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); }); - print(surf.cairo(),"·",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"·",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ arguments[1][0]->render(surf); }); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (arguments.size()<2 || arguments[0].empty() || arguments[1].empty()) throw error("incorrectly wired"); - parenthesise(surf, [&](Surface& surf){ + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); }); - print(surf.cairo(),"⊗",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"⊗",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ arguments[1][0]->render(surf); }); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (arguments.size()<2 || arguments[0].empty() || arguments[1].empty()) throw error("incorrectly wired"); - parenthesise(surf, [&](Surface& surf){ + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf);}); - parenthesise(surf, [&](Surface& surf){ + parenthesise(surf, [&](const IMansoura& surf){ arguments[1][0]->render(surf);},"[","]"); } template <> - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (arguments.size()<2 || arguments[0].empty() || arguments[1].empty()) throw error("incorrectly wired"); - print(surf.cairo(),"meld",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"meld",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ for (size_t i=0; i - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (arguments.size()<2 || arguments[0].empty() || arguments[1].empty()) throw error("incorrectly wired"); - print(surf.cairo(),"merge",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"merge",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ for (size_t i=0; i - void OperationDAG::render(Surface& surf) const + void OperationDAG::render(const IMansoura& surf) const { if (arguments.empty() || arguments[0].empty()) throw error("incorrectly wired"); - print(surf.cairo(),"slice",Anchor::nw); - parenthesise(surf, [&](Surface& surf){ + print(surf,"slice",Anchor::nw); + parenthesise(surf, [&](const IMansoura& surf){ arguments[0][0]->render(surf); - print(surf.cairo(),",",Anchor::nw); + print(surf,",",Anchor::nw); string slice="0"; if (state) if (auto o=state->operationCast()) slice=to_string(o->arg); - print(surf.cairo(),slice,Anchor::nw); + print(surf,slice,Anchor::nw); }); } diff --git a/engine/equations.h b/engine/equations.h index f20e68112..c36fed0c6 100644 --- a/engine/equations.h +++ b/engine/equations.h @@ -30,7 +30,7 @@ #include "model/lock.h" // to avoid clash with python header file of same name #include "operation.h" -#include +#include "IMansoura.h" #include #include #include @@ -98,7 +98,7 @@ namespace MathDAG /// needs to be defined), and pen is moved to the right edge of /// the graphic. The determine bounding box, render into a /// recording surface, and use width()/height() - virtual void render(ecolab::cairo::Surface& surf) const=0; + virtual void render(const mansoura::IMansoura& surf) const=0; /// adds EvalOps to an EvalOpVector representing this node. /// @return a variable where the result is stored. If a @@ -163,7 +163,7 @@ namespace MathDAG bool tensorEval(std::set&) const override {return false;} ostream& latex(ostream& o) const override {return o<order(maxOrder-1)+1:0;} bool tensorEval(std::set&) const override {return true;} @@ -442,7 +442,7 @@ namespace MathDAG ostringstream getDefFromIntVar(const VariableBase& v); /// render equations into a cairo context - void renderEquations(ecolab::cairo::Surface&, double height) const; + void renderEquations(const mansoura::IMansoura&, double height) const; }; /// creates a new name to represent the derivative of a variable diff --git a/gui-js/apps/minsky-electron/src/app/events/electron.events.ts b/gui-js/apps/minsky-electron/src/app/events/electron.events.ts index 34c16da71..13adb9cc9 100644 --- a/gui-js/apps/minsky-electron/src/app/events/electron.events.ts +++ b/gui-js/apps/minsky-electron/src/app/events/electron.events.ts @@ -138,14 +138,14 @@ ipcMain.on( ipcMain.handle( events.GODLEY_VIEW_MOUSEDOWN,async (event, payload: MinskyProcessPayload) => { - let window=new GodleyIcon(minsky.namedItems.elem(payload.command)).popup; + let window=new GodleyIcon(minsky.namedItems.elem(payload.command)).editor; GodleyMenuManager.mouseDown(window,payload.mouseX,payload.mouseY); } ); ipcMain.handle( events.GODLEY_VIEW_IMPORT_STOCK,async (event, payload: ImportStockPayload) => { - let window=new GodleyIcon(minsky.namedItems.elem(payload.command)).popup; + let window=new GodleyIcon(minsky.namedItems.elem(payload.command)).editor; GodleyMenuManager.importStock(window, payload.columnIndex, event); } ); @@ -154,7 +154,7 @@ ipcMain.handle( events.GODLEY_POPUP_UNDO, async (event, payload: { itemId: string; changes: number }) => { const godley = new GodleyIcon(minsky.namedItems.elem(payload.itemId)); - await godley.popup.undo(payload.changes); + await godley.editor.undo(payload.changes); event.sender.send(events.GODLEY_POPUP_REFRESH); } ); diff --git a/gui-js/apps/minsky-electron/src/app/managers/CommandsManager.ts b/gui-js/apps/minsky-electron/src/app/managers/CommandsManager.ts index 5f14efa7c..e7a3f898b 100644 --- a/gui-js/apps/minsky-electron/src/app/managers/CommandsManager.ts +++ b/gui-js/apps/minsky-electron/src/app/managers/CommandsManager.ts @@ -916,7 +916,6 @@ export class CommandsManager { }); Object.defineProperty(window,'dontCloseOnEscape',{value: true,writable:false}); - godley.adjustPopupWidgets(); let systemWindowId = WindowManager.getWindowByUid(id).systemWindowId; diff --git a/gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts b/gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts index de41d17ab..c87895d57 100644 --- a/gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts +++ b/gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts @@ -1208,9 +1208,9 @@ export class ContextMenuManager { private static async initContextMenuForGodleyPopup(namedItemSubCommand: string, x: number, y: number) { const godley=new GodleyIcon(namedItemSubCommand); - const r=await godley.popup.rowYZoomed(y); - const c=await godley.popup.colXZoomed(x); - const clickType = await godley.popup.clickTypeZoomed(x, y); + const r=await godley.editor.rowYZoomed(y); + const c=await godley.editor.colXZoomed(x); + const clickType = await godley.editor.clickTypeZoomed(x, y); this.initContextMenuForGodley(godley, r, c, clickType, CommandsManager.requestRedraw); } @@ -1238,18 +1238,18 @@ export class ContextMenuManager { menu.append(new MenuItem({ label: "Add new stock variable", click: async ()=> { - await godley.popup.addStockVarByCol(c); + await godley.editor.addStockVarByCol(c); await refreshFunction(); }, })); var importMenu=new Menu(); - var importables=await godley.popup.matchingTableColumnsByCol(c); + var importables=await godley.editor.matchingTableColumnsByCol(c); for (var i in importables) importMenu.append(new MenuItem({ label: importables[i], click: async (item)=> { - await godley.popup.importStockVarByCol(item.label, c); + await godley.editor.importStockVarByCol(item.label, c); await refreshFunction(); }, })); @@ -1262,7 +1262,7 @@ export class ContextMenuManager { menu.append(new MenuItem({ label: "Delete stock variable", click: async ()=> { - await godley.popup.deleteStockVarByCol(c); + await godley.editor.deleteStockVarByCol(c); await refreshFunction(); }, })); @@ -1271,14 +1271,14 @@ export class ContextMenuManager { menu.append(new MenuItem({ label: "Add flow", click: async ()=> { - await godley.popup.addFlowByRow(r); + await godley.editor.addFlowByRow(r); await refreshFunction(); }, })); menu.append(new MenuItem({ label: "Delete flow", click: async ()=> { - await godley.popup.deleteFlowByRow(r); + await godley.editor.deleteFlowByRow(r); await refreshFunction(); }, })); @@ -1286,10 +1286,10 @@ export class ContextMenuManager { case "internal": break; } // switch clickType - const selecteds = await Promise.all([godley.popup.selectedRow(),godley.popup.selectedCol()]); + const selecteds = await Promise.all([godley.editor.selectedRow(),godley.editor.selectedCol()]); if (r!=selecteds[0] || c!=selecteds[1]) { - await Promise.all([godley.popup.selectedRow(r), godley.popup.selectedCol(c), godley.popup.insertIdx(0), godley.popup.selectIdx(0)]); + await Promise.all([godley.editor.selectedRow(r), godley.editor.selectedCol(c), godley.editor.insertIdx(0), godley.editor.selectIdx(0)]); } var cell=await godley.table.getCell(r,c); if (cell.length>0 && (r!=1 || c!=0)) @@ -1297,13 +1297,13 @@ export class ContextMenuManager { menu.append(new MenuItem({ label: "Cut", click: async ()=> { - await godley.popup.cut(); + await godley.editor.cut(); await refreshFunction(); } })); menu.append(new MenuItem({ label: "Copy", - click: async ()=> {godley.popup.copy();} + click: async ()=> {godley.editor.copy();} })); } @@ -1314,7 +1314,7 @@ export class ContextMenuManager { label: "Paste", enabled: !clip, click: async ()=> { - await godley.popup.paste(); + await godley.editor.paste(); await refreshFunction(); } })); diff --git a/gui-js/apps/minsky-electron/src/app/managers/GodleyMenuManager.ts b/gui-js/apps/minsky-electron/src/app/managers/GodleyMenuManager.ts index 8950cfaf3..67cf21242 100644 --- a/gui-js/apps/minsky-electron/src/app/managers/GodleyMenuManager.ts +++ b/gui-js/apps/minsky-electron/src/app/managers/GodleyMenuManager.ts @@ -4,7 +4,7 @@ import { GodleyTableOutputStyles, Functions, minsky, GodleyIcon, - GodleyTableWindow, + GodleyTableEditor, events } from '@minsky/shared'; import { Menu, MenuItem, IpcMainInvokeEvent } from 'electron'; @@ -218,17 +218,17 @@ export class GodleyMenuManager { { label: 'Cut', accelerator: 'CmdOrCtrl + x', - click: () => {godley.popup.cut();}, + click: () => {godley.editor.cut();}, }, { label: 'Copy', accelerator: 'CmdOrCtrl + c', - click: () => {godley.popup.copy();} + click: () => {godley.editor.copy();} }, { label: 'Paste', accelerator: 'CmdOrCtrl + v', - click: () => {godley.popup.paste();} + click: () => {godley.editor.paste();} }, ], }); @@ -266,7 +266,7 @@ export class GodleyMenuManager { } /// handle mouse down events in a Godley view - static async mouseDown(window: GodleyTableWindow, x: number, y: number) { + static async mouseDown(window: GodleyTableEditor, x: number, y: number) { var clickType=await window.clickTypeZoomed(x,y); if (clickType==="importStock") { @@ -275,7 +275,7 @@ export class GodleyMenuManager { } else {window.mouseDown(x,y);} } - static async importStock(window: GodleyTableWindow, c, event?: IpcMainInvokeEvent) { + static async importStock(window: GodleyTableEditor, c, event?: IpcMainInvokeEvent) { var importOptions=await window.matchingTableColumnsByCol(c); var menu=new Menu(); for (var v in importOptions) diff --git a/gui-js/libs/shared/src/lib/backend/minsky.ts b/gui-js/libs/shared/src/lib/backend/minsky.ts index 00fe8b0fb..ea07ad48d 100644 --- a/gui-js/libs/shared/src/lib/backend/minsky.ts +++ b/gui-js/libs/shared/src/lib/backend/minsky.ts @@ -17,7 +17,7 @@ class classdesc__json_pack_t {} class classdesc__pack_t {} class classdesc__RESTProcess_t {} class ecolab__cairo__Surface {} -class ICairoShim {} +class mansoura__IMansoura {} export class EventInterface extends CppClass { item: Item; @@ -65,11 +65,11 @@ export class Item extends CppClass { async detailedText(...args: any[]): Promise {return this.$callMethod('detailedText',...args);} async disableDelayedTooltip(): Promise {return this.$callMethod('disableDelayedTooltip');} async displayDelayedTooltip(a1: number,a2: number): Promise {return this.$callMethod('displayDelayedTooltip',a1,a2);} - async displayTooltip(a1: ICairoShim,a2: string): Promise {return this.$callMethod('displayTooltip',a1,a2);} - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} - async drawPorts(a1: ICairoShim): Promise {return this.$callMethod('drawPorts',a1);} - async drawResizeHandles(a1: ICairoShim): Promise {return this.$callMethod('drawResizeHandles',a1);} - async drawSelected(a1: ICairoShim): Promise {return this.$callMethod('drawSelected',a1);} + async displayTooltip(a1: mansoura__IMansoura,a2: string): Promise {return this.$callMethod('displayTooltip',a1,a2);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} + async drawPorts(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawPorts',a1);} + async drawResizeHandles(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawResizeHandles',a1);} + async drawSelected(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawSelected',a1);} async dummyDraw(): Promise {return this.$callMethod('dummyDraw');} async editorMode(): Promise {return this.$callMethod('editorMode');} async ensureBBValid(): Promise {return this.$callMethod('ensureBBValid');} @@ -138,11 +138,11 @@ export class OperationBase extends Item { async classify(a1: string): Promise {return this.$callMethod('classify',a1);} async create(a1: string): Promise {return this.$callMethod('create',a1);} async dimensions(): Promise {return this.$callMethod('dimensions');} - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} - async drawResizeHandles(a1: ICairoShim): Promise {return this.$callMethod('drawResizeHandles',a1);} - async drawUserFunction(a1: ICairoShim): Promise {return this.$callMethod('drawUserFunction',a1);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} + async drawResizeHandles(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawResizeHandles',a1);} + async drawUserFunction(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawUserFunction',a1);} async h(...args: number[]): Promise {return this.$callMethod('h',...args);} - async iconDraw(a1: ICairoShim): Promise {return this.$callMethod('iconDraw',a1);} + async iconDraw(a1: mansoura__IMansoura): Promise {return this.$callMethod('iconDraw',a1);} async l(...args: number[]): Promise {return this.$callMethod('l',...args);} async multiWire(): Promise {return this.$callMethod('multiWire');} async numPorts(): Promise {return this.$callMethod('numPorts');} @@ -160,20 +160,19 @@ export class OperationBase extends Item { } export class RenderNativeWindow extends EventInterface { - backgroundColour: ecolab__cairo__Colour; + backgroundColour: mansoura__Colour; constructor(prefix: string|EventInterface){ if (typeof prefix==='string') super(prefix) else super(prefix.$prefix()) - this.backgroundColour=new ecolab__cairo__Colour(this.$prefix()+'.backgroundColour'); + this.backgroundColour=new mansoura__Colour(this.$prefix()+'.backgroundColour'); } async destroyFrame(): Promise {return this.$callMethod('destroyFrame');} async draw(): Promise {return this.$callMethod('draw');} async frameArgs(): Promise {return this.$callMethod('frameArgs');} async hasScrollBars(): Promise {return this.$callMethod('hasScrollBars');} async init(): Promise {return this.$callMethod('init');} - async registerImage(): Promise {return this.$callMethod('registerImage');} async renderFrame(a1: minsky__RenderNativeWindow__RenderFrameArgs): Promise {return this.$callMethod('renderFrame',a1);} async renderToEMF(a1: string): Promise {return this.$callMethod('renderToEMF',a1);} async renderToPDF(a1: string): Promise {return this.$callMethod('renderToPDF',a1);} @@ -222,11 +221,11 @@ export class VariableBase extends Item { async dims(): Promise {return this.$callMethod('dims');} async disableDelayedTooltip(): Promise {return this.$callMethod('disableDelayedTooltip');} async displayDelayedTooltip(a1: number,a2: number): Promise {return this.$callMethod('displayDelayedTooltip',a1,a2);} - async displayTooltip(a1: ICairoShim,a2: string): Promise {return this.$callMethod('displayTooltip',a1,a2);} - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} - async drawPorts(a1: ICairoShim): Promise {return this.$callMethod('drawPorts',a1);} - async drawResizeHandles(a1: ICairoShim): Promise {return this.$callMethod('drawResizeHandles',a1);} - async drawSelected(a1: ICairoShim): Promise {return this.$callMethod('drawSelected',a1);} + async displayTooltip(a1: mansoura__IMansoura,a2: string): Promise {return this.$callMethod('displayTooltip',a1,a2);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} + async drawPorts(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawPorts',a1);} + async drawResizeHandles(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawResizeHandles',a1);} + async drawSelected(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawSelected',a1);} async dummyDraw(): Promise {return this.$callMethod('dummyDraw');} async editorMode(): Promise {return this.$callMethod('editorMode');} async enableSlider(...args: any[]): Promise {return this.$callMethod('enableSlider',...args);} @@ -329,7 +328,7 @@ export class Wire extends CppClass { async coords(...args: any[]): Promise {return this.$callMethod('coords',...args);} async deleteHandle(a1: number,a2: number): Promise {return this.$callMethod('deleteHandle',a1,a2);} async detailedText(...args: any[]): Promise {return this.$callMethod('detailedText',...args);} - async draw(a1: ICairoShim,a2: boolean): Promise {return this.$callMethod('draw',a1,a2);} + async draw(a1: mansoura__IMansoura,a2: boolean): Promise {return this.$callMethod('draw',a1,a2);} async editHandle(a1: number,a2: number,a3: number): Promise {return this.$callMethod('editHandle',a1,a2,a3);} async from(): Promise {return this.$callMethod('from');} async insertHandle(a1: number,a2: number,a3: number): Promise {return this.$callMethod('insertHandle',a1,a2,a3);} @@ -340,7 +339,6 @@ export class Wire extends CppClass { async nearestHandle(a1: number,a2: number): Promise {return this.$callMethod('nearestHandle',a1,a2);} async selected(...args: boolean[]): Promise {return this.$callMethod('selected',...args);} async split(): Promise {return this.$callMethod('split');} - async storeCairoCoords(a1: minsky__dummy): Promise {return this.$callMethod('storeCairoCoords',a1);} async straighten(): Promise {return this.$callMethod('straighten');} async to(): Promise {return this.$callMethod('to');} async tooltip(...args: any[]): Promise {return this.$callMethod('tooltip',...args);} @@ -396,7 +394,7 @@ export class CSVDialog extends CppClass { } export class Canvas extends RenderNativeWindow { - backgroundColour: ecolab__cairo__Colour; + backgroundColour: mansoura__Colour; item: Item; itemFocus: Item; itemIndicator: Item; @@ -411,7 +409,7 @@ export class Canvas extends RenderNativeWindow { super(prefix) else super(prefix.$prefix()) - this.backgroundColour=new ecolab__cairo__Colour(this.$prefix()+'.backgroundColour'); + this.backgroundColour=new mansoura__Colour(this.$prefix()+'.backgroundColour'); this.item=new Item(this.$prefix()+'.item'); this.itemFocus=new Item(this.$prefix()+'.itemFocus'); this.itemIndicator=new Item(this.$prefix()+'.itemIndicator'); @@ -469,11 +467,9 @@ export class Canvas extends RenderNativeWindow { async position(): Promise {return this.$callMethod('position');} async ravelsSelected(): Promise {return this.$callMethod('ravelsSelected');} async recentre(): Promise {return this.$callMethod('recentre');} - async redraw(): Promise {return this.$callMethod('redraw');} async redrawAll(...args: boolean[]): Promise {return this.$callMethod('redrawAll',...args);} async redrawRequested(): Promise {return this.$callMethod('redrawRequested');} - async redrawUpdateRegion(): Promise {return this.$callMethod('redrawUpdateRegion');} - async registerImage(): Promise {return this.$callMethod('registerImage');} + async redrawUpdateRegion(a1: mansoura__IMansoura): Promise {return this.$callMethod('redrawUpdateRegion',a1);} async removeItemFromItsGroup(): Promise {return this.$callMethod('removeItemFromItsGroup');} async renameAllInstances(a1: string): Promise {return this.$callMethod('renameAllInstances',a1);} async renameItem(a1: string): Promise {return this.$callMethod('renameItem',a1);} @@ -496,7 +492,6 @@ export class Canvas extends RenderNativeWindow { async setDefaultPlotOptions(): Promise {return this.$callMethod('setDefaultPlotOptions');} async setItemFocus(a1: Item): Promise {return this.$callMethod('setItemFocus',a1);} async setItemFromItemFocus(): Promise {return this.$callMethod('setItemFromItemFocus');} - async surface(): Promise {return this.$callMethod('surface');} async termX(...args: number[]): Promise {return this.$callMethod('termX',...args);} async termY(...args: number[]): Promise {return this.$callMethod('termY',...args);} async ungroupItem(): Promise {return this.$callMethod('ungroupItem');} @@ -628,7 +623,7 @@ export class EngNotation extends CppClass { } export class EquationDisplay extends RenderNativeWindow { - backgroundColour: ecolab__cairo__Colour; + backgroundColour: mansoura__Colour; item: Item; wire: Wire; constructor(prefix: string|RenderNativeWindow){ @@ -636,7 +631,7 @@ export class EquationDisplay extends RenderNativeWindow { super(prefix) else super(prefix.$prefix()) - this.backgroundColour=new ecolab__cairo__Colour(this.$prefix()+'.backgroundColour'); + this.backgroundColour=new mansoura__Colour(this.$prefix()+'.backgroundColour'); this.item=new Item(this.$prefix()+'.item'); this.wire=new Wire(this.$prefix()+'.wire'); } @@ -658,7 +653,6 @@ export class EquationDisplay extends RenderNativeWindow { async offsx(...args: number[]): Promise {return this.$callMethod('offsx',...args);} async offsy(...args: number[]): Promise {return this.$callMethod('offsy',...args);} async position(): Promise {return this.$callMethod('position');} - async registerImage(): Promise {return this.$callMethod('registerImage');} async renderFrame(a1: minsky__RenderNativeWindow__RenderFrameArgs): Promise {return this.$callMethod('renderFrame',a1);} async renderToEMF(a1: string): Promise {return this.$callMethod('renderToEMF',a1);} async renderToPDF(a1: string): Promise {return this.$callMethod('renderToPDF',a1);} @@ -683,12 +677,12 @@ export class EvalGodley extends CppClass { } export class FontDisplay extends CppClass { - backgroundColour: ecolab__cairo__Colour; + backgroundColour: mansoura__Colour; item: Item; wire: Wire; constructor(prefix: string){ super(prefix); - this.backgroundColour=new ecolab__cairo__Colour(this.$prefix()+'.backgroundColour'); + this.backgroundColour=new mansoura__Colour(this.$prefix()+'.backgroundColour'); this.item=new Item(this.$prefix()+'.item'); this.wire=new Wire(this.$prefix()+'.wire'); } @@ -706,7 +700,6 @@ export class FontDisplay extends CppClass { async mouseUp(a1: number,a2: number): Promise {return this.$callMethod('mouseUp',a1,a2);} async moveTo(a1: number,a2: number): Promise {return this.$callMethod('moveTo',a1,a2);} async position(): Promise {return this.$callMethod('position');} - async registerImage(): Promise {return this.$callMethod('registerImage');} async renderFrame(a1: minsky__RenderNativeWindow__RenderFrameArgs): Promise {return this.$callMethod('renderFrame',a1);} async renderToEMF(a1: string): Promise {return this.$callMethod('renderToEMF',a1);} async renderToPDF(a1: string): Promise {return this.$callMethod('renderToPDF',a1);} @@ -723,8 +716,7 @@ export class FontDisplay extends CppClass { export class GodleyIcon extends Item { editor: GodleyTableEditor; - popup: GodleyTableWindow; - svgRenderer: SVGRenderer; + svgRenderer: mansoura__SVGRenderer; table: GodleyTable; constructor(prefix: string|Item){ if (typeof prefix==='string') @@ -732,20 +724,17 @@ export class GodleyIcon extends Item { else super(prefix.$prefix()) this.editor=new GodleyTableEditor(this.$prefix()+'.editor'); - this.popup=new GodleyTableWindow(this.$prefix()+'.popup'); - this.svgRenderer=new SVGRenderer(this.$prefix()+'.svgRenderer'); + this.svgRenderer=new mansoura__SVGRenderer(this.$prefix()+'.svgRenderer'); this.table=new GodleyTable(this.$prefix()+'.table'); } - async adjustPopupWidgets(): Promise {return this.$callMethod('adjustPopupWidgets');} async bottomMargin(): Promise {return this.$callMethod('bottomMargin');} async buttonDisplay(): Promise {return this.$callMethod('buttonDisplay');} async clickType(a1: number,a2: number): Promise {return this.$callMethod('clickType',a1,a2);} async clone(): Promise {return this.$callMethod('clone');} async currency(...args: string[]): Promise {return this.$callMethod('currency',...args);} async deleteRow(a1: number): Promise {return this.$callMethod('deleteRow',a1);} - async destroyFrame(): Promise {return this.$callMethod('destroyFrame');} async displayValues(...args: boolean[]): Promise {return this.$callMethod('displayValues',...args);} - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} async editorMode(): Promise {return this.$callMethod('editorMode');} async flowSignature(a1: number): Promise {return this.$callMethod('flowSignature',a1);} async flowVars(): Promise> {return this.$callMethod('flowVars');} @@ -852,14 +841,14 @@ export class GodleyTableEditor extends CppClass { async deleteStockVar(a1: number): Promise {return this.$callMethod('deleteStockVar',a1);} async deleteStockVarByCol(a1: number): Promise {return this.$callMethod('deleteStockVarByCol',a1);} async disableButtons(): Promise {return this.$callMethod('disableButtons');} - async draw(...args: any[]): Promise {return this.$callMethod('draw',...args);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} async drawButtons(...args: boolean[]): Promise {return this.$callMethod('drawButtons',...args);} async enableButtons(): Promise {return this.$callMethod('enableButtons');} async godleyIcon(): Promise {return this.$callMethod('godleyIcon');} async height(): Promise {return this.$callMethod('height');} - async highlightCell(a1: minsky__dummy,a2: number,a3: number): Promise {return this.$callMethod('highlightCell',a1,a2,a3);} - async highlightColumn(a1: minsky__dummy,a2: number): Promise {return this.$callMethod('highlightColumn',a1,a2);} - async highlightRow(a1: minsky__dummy,a2: number): Promise {return this.$callMethod('highlightRow',a1,a2);} + async highlightCell(a1: mansoura__IMansoura,a2: number,a3: number): Promise {return this.$callMethod('highlightCell',a1,a2,a3);} + async highlightColumn(a1: mansoura__IMansoura,a2: number): Promise {return this.$callMethod('highlightColumn',a1,a2);} + async highlightRow(a1: mansoura__IMansoura,a2: number): Promise {return this.$callMethod('highlightRow',a1,a2);} async historyPtr(...args: number[]): Promise {return this.$callMethod('historyPtr',...args);} async hoverCol(...args: number[]): Promise {return this.$callMethod('hoverCol',...args);} async hoverRow(...args: number[]): Promise {return this.$callMethod('hoverRow',...args);} @@ -904,110 +893,6 @@ export class GodleyTableEditor extends CppClass { async zoomFactor(...args: number[]): Promise {return this.$callMethod('zoomFactor',...args);} } -export class GodleyTableWindow extends CppClass { - backgroundColour: ecolab__cairo__Colour; - colLeftMargin: Sequence; - item: Item; - wire: Wire; - constructor(prefix: string){ - super(prefix); - this.backgroundColour=new ecolab__cairo__Colour(this.$prefix()+'.backgroundColour'); - this.colLeftMargin=new Sequence(this.$prefix()+'.colLeftMargin'); - this.item=new Item(this.$prefix()+'.item'); - this.wire=new Wire(this.$prefix()+'.wire'); - } - async addFlow(a1: number): Promise {return this.$callMethod('addFlow',a1);} - async addFlowByRow(a1: number): Promise {return this.$callMethod('addFlowByRow',a1);} - async addStockVar(a1: number): Promise {return this.$callMethod('addStockVar',a1);} - async addStockVarByCol(a1: number): Promise {return this.$callMethod('addStockVarByCol',a1);} - async adjustWidgets(): Promise {return this.$callMethod('adjustWidgets');} - async clickType(a1: number,a2: number): Promise {return this.$callMethod('clickType',a1,a2);} - async clickTypeZoomed(a1: number,a2: number): Promise {return this.$callMethod('clickTypeZoomed',a1,a2);} - async colX(a1: number): Promise {return this.$callMethod('colX',a1);} - async colXZoomed(a1: number): Promise {return this.$callMethod('colXZoomed',a1);} - async columnButtonsOffset(...args: number[]): Promise {return this.$callMethod('columnButtonsOffset',...args);} - async controlMouseDown(a1: number,a2: number): Promise {return this.$callMethod('controlMouseDown',a1,a2);} - async copy(): Promise {return this.$callMethod('copy');} - async cut(): Promise {return this.$callMethod('cut');} - async delSelection(): Promise {return this.$callMethod('delSelection');} - async deleteFlow(a1: number): Promise {return this.$callMethod('deleteFlow',a1);} - async deleteFlowByRow(a1: number): Promise {return this.$callMethod('deleteFlowByRow',a1);} - async deleteStockVar(a1: number): Promise {return this.$callMethod('deleteStockVar',a1);} - async deleteStockVarByCol(a1: number): Promise {return this.$callMethod('deleteStockVarByCol',a1);} - async destroyFrame(): Promise {return this.$callMethod('destroyFrame');} - async disableButtons(): Promise {return this.$callMethod('disableButtons');} - async draw(...args: any[]): Promise {return this.$callMethod('draw',...args);} - async drawButtons(...args: boolean[]): Promise {return this.$callMethod('drawButtons',...args);} - async enableButtons(): Promise {return this.$callMethod('enableButtons');} - async frameArgs(): Promise {return this.$callMethod('frameArgs');} - async getItemAt(a1: number,a2: number): Promise {return this.$callMethod('getItemAt',a1,a2);} - async getWireAt(a1: number,a2: number): Promise {return this.$callMethod('getWireAt',a1,a2);} - async godleyIcon(): Promise {return this.$callMethod('godleyIcon');} - async hasScrollBars(): Promise {return this.$callMethod('hasScrollBars');} - async height(): Promise {return this.$callMethod('height');} - async highlightCell(a1: minsky__dummy,a2: number,a3: number): Promise {return this.$callMethod('highlightCell',a1,a2,a3);} - async highlightColumn(a1: minsky__dummy,a2: number): Promise {return this.$callMethod('highlightColumn',a1,a2);} - async highlightRow(a1: minsky__dummy,a2: number): Promise {return this.$callMethod('highlightRow',a1,a2);} - async historyPtr(...args: number[]): Promise {return this.$callMethod('historyPtr',...args);} - async hoverCol(...args: number[]): Promise {return this.$callMethod('hoverCol',...args);} - async hoverRow(...args: number[]): Promise {return this.$callMethod('hoverRow',...args);} - async importStockVar(a1: string,a2: number): Promise {return this.$callMethod('importStockVar',a1,a2);} - async importStockVarByCol(a1: string,a2: number): Promise {return this.$callMethod('importStockVarByCol',a1,a2);} - async init(): Promise {return this.$callMethod('init');} - async insertIdx(...args: number[]): Promise {return this.$callMethod('insertIdx',...args);} - async keyPress(...args: any[]): Promise {return this.$callMethod('keyPress',...args);} - async leftTableOffset(...args: number[]): Promise {return this.$callMethod('leftTableOffset',...args);} - async matchingTableColumns(a1: number): Promise {return this.$callMethod('matchingTableColumns',a1);} - async matchingTableColumnsByCol(a1: number): Promise {return this.$callMethod('matchingTableColumnsByCol',a1);} - async maxHistory(...args: number[]): Promise {return this.$callMethod('maxHistory',...args);} - async minColumnWidth(...args: number[]): Promise {return this.$callMethod('minColumnWidth',...args);} - async mouseDown(a1: number,a2: number): Promise {return this.$callMethod('mouseDown',a1,a2);} - async mouseMove(a1: number,a2: number): Promise {return this.$callMethod('mouseMove',a1,a2);} - async mouseMoveB1(a1: number,a2: number): Promise {return this.$callMethod('mouseMoveB1',a1,a2);} - async mouseUp(a1: number,a2: number): Promise {return this.$callMethod('mouseUp',a1,a2);} - async moveAssetClass(a1: number,a2: number): Promise {return this.$callMethod('moveAssetClass',a1,a2);} - async moveTo(a1: number,a2: number): Promise {return this.$callMethod('moveTo',a1,a2);} - async navigateDown(): Promise {return this.$callMethod('navigateDown');} - async navigateLeft(): Promise {return this.$callMethod('navigateLeft');} - async navigateRight(): Promise {return this.$callMethod('navigateRight');} - async navigateUp(): Promise {return this.$callMethod('navigateUp');} - async paste(): Promise {return this.$callMethod('paste');} - async position(): Promise {return this.$callMethod('position');} - async pulldownHot(...args: number[]): Promise {return this.$callMethod('pulldownHot',...args);} - async pushHistory(): Promise {return this.$callMethod('pushHistory');} - async registerImage(): Promise {return this.$callMethod('registerImage');} - async renderFrame(a1: minsky__RenderNativeWindow__RenderFrameArgs): Promise {return this.$callMethod('renderFrame',a1);} - async renderToEMF(a1: string): Promise {return this.$callMethod('renderToEMF',a1);} - async renderToPDF(a1: string): Promise {return this.$callMethod('renderToPDF',a1);} - async renderToPNG(a1: string): Promise {return this.$callMethod('renderToPNG',a1);} - async renderToPS(a1: string): Promise {return this.$callMethod('renderToPS',a1);} - async renderToSVG(a1: string): Promise {return this.$callMethod('renderToSVG',a1);} - async reportDrawTime(a1: number): Promise {return this.$callMethod('reportDrawTime',a1);} - async requestRedraw(): Promise {return this.$callMethod('requestRedraw');} - async requestRedrawCanvas(): Promise {return this.$callMethod('requestRedrawCanvas');} - async resolutionScaleFactor(...args: any[]): Promise {return this.$callMethod('resolutionScaleFactor',...args);} - async rowHeight(...args: number[]): Promise {return this.$callMethod('rowHeight',...args);} - async rowY(a1: number): Promise {return this.$callMethod('rowY',a1);} - async rowYZoomed(a1: number): Promise {return this.$callMethod('rowYZoomed',a1);} - async scaleFactor(): Promise {return this.$callMethod('scaleFactor');} - async scrollColStart(...args: number[]): Promise {return this.$callMethod('scrollColStart',...args);} - async scrollRowStart(...args: number[]): Promise {return this.$callMethod('scrollRowStart',...args);} - async selectIdx(...args: number[]): Promise {return this.$callMethod('selectIdx',...args);} - async selectedCellInTable(): Promise {return this.$callMethod('selectedCellInTable');} - async selectedCol(...args: number[]): Promise {return this.$callMethod('selectedCol',...args);} - async selectedRow(...args: number[]): Promise {return this.$callMethod('selectedRow',...args);} - async srcCol(...args: number[]): Promise {return this.$callMethod('srcCol',...args);} - async srcRow(...args: number[]): Promise {return this.$callMethod('srcRow',...args);} - async swapAssetClass(a1: number,a2: number): Promise {return this.$callMethod('swapAssetClass',a1,a2);} - async textIdx(a1: number): Promise {return this.$callMethod('textIdx',a1);} - async topTableOffset(...args: number[]): Promise {return this.$callMethod('topTableOffset',...args);} - async undo(a1: number): Promise {return this.$callMethod('undo',a1);} - async update(): Promise {return this.$callMethod('update');} - async width(): Promise {return this.$callMethod('width');} - async zoom(a1: number,a2: number,a3: number): Promise {return this.$callMethod('zoom',a1,a2,a3);} - async zoomFactor(): Promise {return this.$callMethod('zoomFactor');} -} - export class Group extends Item { bb: BoundingBox; bookmarks: Container; @@ -1016,7 +901,7 @@ export class Group extends Item { inVariables: Sequence; items: Sequence; outVariables: Sequence; - svgRenderer: SVGRenderer; + svgRenderer: mansoura__SVGRenderer; wires: Sequence; constructor(prefix: string|Item){ if (typeof prefix==='string') @@ -1030,7 +915,7 @@ export class Group extends Item { this.inVariables=new Sequence(this.$prefix()+'.inVariables',VariableBase); this.items=new Sequence(this.$prefix()+'.items',Item); this.outVariables=new Sequence(this.$prefix()+'.outVariables',VariableBase); - this.svgRenderer=new SVGRenderer(this.$prefix()+'.svgRenderer'); + this.svgRenderer=new mansoura__SVGRenderer(this.$prefix()+'.svgRenderer'); this.wires=new Sequence(this.$prefix()+'.wires',Wire); } async RESTProcess(a1: classdesc__RESTProcess_t,a2: string): Promise {return this.$callMethod('RESTProcess',a1,a2);} @@ -1076,15 +961,15 @@ export class Group extends Item { async displayContents(): Promise {return this.$callMethod('displayContents');} async displayContentsChanged(): Promise {return this.$callMethod('displayContentsChanged');} async displayDelayedTooltip(a1: number,a2: number): Promise {return this.$callMethod('displayDelayedTooltip',a1,a2);} - async displayTooltip(a1: ICairoShim,a2: string): Promise {return this.$callMethod('displayTooltip',a1,a2);} + async displayTooltip(a1: mansoura__IMansoura,a2: string): Promise {return this.$callMethod('displayTooltip',a1,a2);} async displayZoom(...args: number[]): Promise {return this.$callMethod('displayZoom',...args);} - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} - async draw1edge(a1: Sequence,a2: minsky__dummy,a3: number): Promise {return this.$callMethod('draw1edge',a1,a2,a3);} - async drawEdgeVariables(a1: minsky__dummy): Promise {return this.$callMethod('drawEdgeVariables',a1);} - async drawIORegion(a1: minsky__dummy): Promise {return this.$callMethod('drawIORegion',a1);} - async drawPorts(a1: ICairoShim): Promise {return this.$callMethod('drawPorts',a1);} - async drawResizeHandles(a1: ICairoShim): Promise {return this.$callMethod('drawResizeHandles',a1);} - async drawSelected(a1: ICairoShim): Promise {return this.$callMethod('drawSelected',a1);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} + async draw1edge(a1: Sequence,a2: mansoura__IMansoura,a3: number): Promise {return this.$callMethod('draw1edge',a1,a2,a3);} + async drawEdgeVariables(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawEdgeVariables',a1);} + async drawIORegion(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawIORegion',a1);} + async drawPorts(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawPorts',a1);} + async drawResizeHandles(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawResizeHandles',a1);} + async drawSelected(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawSelected',a1);} async dummyDraw(): Promise {return this.$callMethod('dummyDraw');} async edgeScale(): Promise {return this.$callMethod('edgeScale');} async editorMode(): Promise {return this.$callMethod('editorMode');} @@ -1244,7 +1129,7 @@ export class IntOp extends Item { } async coupled(): Promise {return this.$callMethod('coupled');} async description(...args: string[]): Promise {return this.$callMethod('description',...args);} - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} async intVarOffset(...args: number[]): Promise {return this.$callMethod('intVarOffset',...args);} async onKeyPress(a1: number,a2: string,a3: number): Promise {return this.$callMethod('onKeyPress',a1,a2,a3);} async pack(a1: classdesc__pack_t,a2: string): Promise {return this.$callMethod('pack',a1,a2);} @@ -1269,21 +1154,21 @@ export class LassoBox extends CppClass { } export class Lock extends Item { - lockedIcon: SVGRenderer; + lockedIcon: mansoura__SVGRenderer; lockedState: ravel__RavelState; - unlockedIcon: SVGRenderer; + unlockedIcon: mansoura__SVGRenderer; constructor(prefix: string|Item){ if (typeof prefix==='string') super(prefix) else super(prefix.$prefix()) - this.lockedIcon=new SVGRenderer(this.$prefix()+'.lockedIcon'); + this.lockedIcon=new mansoura__SVGRenderer(this.$prefix()+'.lockedIcon'); this.lockedState=new ravel__RavelState(this.$prefix()+'.lockedState'); - this.unlockedIcon=new SVGRenderer(this.$prefix()+'.unlockedIcon'); + this.unlockedIcon=new mansoura__SVGRenderer(this.$prefix()+'.unlockedIcon'); } async addPorts(): Promise {return this.$callMethod('addPorts');} async applyLockedStateToRavel(): Promise {return this.$callMethod('applyLockedStateToRavel');} - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} async locked(): Promise {return this.$callMethod('locked');} async ravelInput(): Promise {return this.$callMethod('ravelInput');} async toggleLocked(): Promise {return this.$callMethod('toggleLocked');} @@ -1299,7 +1184,7 @@ export class Minsky extends CppClass { evalGodley: EvalGodley; flowVars: Sequence; fontSampler: FontDisplay; - histogramResource: SVGRenderer; + histogramResource: mansoura__SVGRenderer; logVarList: Container; maxFlowValue: Map; maxValue: Map; @@ -1320,7 +1205,7 @@ export class Minsky extends CppClass { this.evalGodley=new EvalGodley(this.$prefix()+'.evalGodley'); this.flowVars=new Sequence(this.$prefix()+'.flowVars'); this.fontSampler=new FontDisplay(this.$prefix()+'.fontSampler'); - this.histogramResource=new SVGRenderer(this.$prefix()+'.histogramResource'); + this.histogramResource=new mansoura__SVGRenderer(this.$prefix()+'.histogramResource'); this.logVarList=new Container(this.$prefix()+'.logVarList'); this.maxFlowValue=new Map(this.$prefix()+'.maxFlowValue'); this.maxValue=new Map(this.$prefix()+'.maxValue'); @@ -1426,7 +1311,6 @@ export class Minsky extends CppClass { async ravelAvailable(): Promise {return this.$callMethod('ravelAvailable');} async ravelExpired(): Promise {return this.$callMethod('ravelExpired');} async ravelVersion(): Promise {return this.$callMethod('ravelVersion');} - async redrawAllGodleyTables(): Promise {return this.$callMethod('redrawAllGodleyTables');} async reloadAllCSVParameters(): Promise {return this.$callMethod('reloadAllCSVParameters');} async renameDimension(a1: string,a2: string): Promise {return this.$callMethod('renameDimension',a1,a2);} async renderAllPlotsAsSVG(a1: string): Promise {return this.$callMethod('renderAllPlotsAsSVG',a1);} @@ -1472,7 +1356,7 @@ export class Minsky extends CppClass { } export class PhillipsDiagram extends RenderNativeWindow { - backgroundColour: ecolab__cairo__Colour; + backgroundColour: mansoura__Colour; flows: Map,PhillipsFlow>; item: Item; stocks: Map; @@ -1482,7 +1366,7 @@ export class PhillipsDiagram extends RenderNativeWindow { super(prefix) else super(prefix.$prefix()) - this.backgroundColour=new ecolab__cairo__Colour(this.$prefix()+'.backgroundColour'); + this.backgroundColour=new mansoura__Colour(this.$prefix()+'.backgroundColour'); this.flows=new Map,PhillipsFlow>(this.$prefix()+'.flows',PhillipsFlow); this.item=new Item(this.$prefix()+'.item'); this.stocks=new Map(this.$prefix()+'.stocks',PhillipsStock); @@ -1503,7 +1387,6 @@ export class PhillipsDiagram extends RenderNativeWindow { async mouseUp(a1: number,a2: number): Promise {return this.$callMethod('mouseUp',a1,a2);} async moveTo(a1: number,a2: number): Promise {return this.$callMethod('moveTo',a1,a2);} async position(): Promise {return this.$callMethod('position');} - async registerImage(): Promise {return this.$callMethod('registerImage');} async renderFrame(a1: minsky__RenderNativeWindow__RenderFrameArgs): Promise {return this.$callMethod('renderFrame',a1);} async renderToEMF(a1: string): Promise {return this.$callMethod('renderToEMF',a1);} async renderToPDF(a1: string): Promise {return this.$callMethod('renderToPDF',a1);} @@ -1529,7 +1412,7 @@ export class PhillipsFlow extends Wire { this.maxFlow=new Map(this.$prefix()+'.maxFlow'); } async addTerm(a1: number,a2: string): Promise {return this.$callMethod('addTerm',a1,a2);} - async draw(a1: ICairoShim,a2: boolean): Promise {return this.$callMethod('draw',a1,a2);} + async draw(a1: mansoura__IMansoura,a2: boolean): Promise {return this.$callMethod('draw',a1,a2);} async units(): Promise {return this.$callMethod('units');} async value(): Promise {return this.$callMethod('value');} } @@ -1545,16 +1428,16 @@ export class PhillipsStock extends Item { } async classType(): Promise {return this.$callMethod('classType');} async clone(): Promise> {return this.$callMethod('clone');} - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} async numPorts(): Promise {return this.$callMethod('numPorts');} async type(): Promise {return this.$callMethod('type');} } export class PlotWidget extends Item { - backgroundColour: ecolab__cairo__Colour; + backgroundColour: mansoura__Colour; horizontalMarkers: Sequence; item: Item; - palette: Sequence; + palette: Sequence; penLabels: Sequence; verticalMarkers: Sequence; wire: Wire; @@ -1571,10 +1454,10 @@ export class PlotWidget extends Item { super(prefix) else super(prefix.$prefix()) - this.backgroundColour=new ecolab__cairo__Colour(this.$prefix()+'.backgroundColour'); + this.backgroundColour=new mansoura__Colour(this.$prefix()+'.backgroundColour'); this.horizontalMarkers=new Sequence(this.$prefix()+'.horizontalMarkers'); this.item=new Item(this.$prefix()+'.item'); - this.palette=new Sequence(this.$prefix()+'.palette',ecolab__Plot__LineStyle); + this.palette=new Sequence(this.$prefix()+'.palette',mansoura__Plot__LineStyle); this.penLabels=new Sequence(this.$prefix()+'.penLabels'); this.verticalMarkers=new Sequence(this.$prefix()+'.verticalMarkers'); this.wire=new Wire(this.$prefix()+'.wire'); @@ -1588,7 +1471,6 @@ export class PlotWidget extends Item { this.yvars=new Sequence>(this.$prefix()+'.yvars',Sequence); } async AssignSide(a1: number,a2: string): Promise {return this.$callMethod('AssignSide',a1,a2);} - async LabelPen(a1: number,a2: ecolab__cairo__Surface): Promise {return this.$callMethod('LabelPen',a1,a2);} async addConstantCurves(): Promise {return this.$callMethod('addConstantCurves');} async addPlotPt(a1: number): Promise {return this.$callMethod('addPlotPt',a1);} async addPorts(): Promise {return this.$callMethod('addPorts');} @@ -1656,8 +1538,6 @@ export class PlotWidget extends Item { async plotWidgetCast(): Promise {return this.$callMethod('plotWidgetCast');} async position(): Promise {return this.$callMethod('position');} async redraw(): Promise {return this.$callMethod('redraw');} - async redrawWithBounds(): Promise {return this.$callMethod('redrawWithBounds');} - async registerImage(): Promise {return this.$callMethod('registerImage');} async removePensFrom(a1: number): Promise {return this.$callMethod('removePensFrom',a1);} async renderFrame(a1: minsky__RenderNativeWindow__RenderFrameArgs): Promise {return this.$callMethod('renderFrame',a1);} async renderToEMF(a1: string): Promise {return this.$callMethod('renderToEMF',a1);} @@ -1765,7 +1645,7 @@ export class Ravel extends Item { db: ravelCAPI__Database; lockGroup: RavelLockGroup; popup: RavelPopup; - svgRenderer: SVGRenderer; + svgRenderer: mansoura__SVGRenderer; constructor(prefix: string|Item){ if (typeof prefix==='string') super(prefix) @@ -1775,7 +1655,7 @@ export class Ravel extends Item { this.db=new ravelCAPI__Database(this.$prefix()+'.db'); this.lockGroup=new RavelLockGroup(this.$prefix()+'.lockGroup'); this.popup=new RavelPopup(this.$prefix()+'.popup'); - this.svgRenderer=new SVGRenderer(this.$prefix()+'.svgRenderer'); + this.svgRenderer=new mansoura__SVGRenderer(this.$prefix()+'.svgRenderer'); } async adjustSlicer(a1: number): Promise {return this.$callMethod('adjustSlicer',a1);} async allSliceLabels(): Promise {return this.$callMethod('allSliceLabels');} @@ -1790,7 +1670,7 @@ export class Ravel extends Item { async dimensionUnitsFormat(...args: any[]): Promise {return this.$callMethod('dimensionUnitsFormat',...args);} async displayDelayedTooltip(a1: number,a2: number): Promise {return this.$callMethod('displayDelayedTooltip',a1,a2);} async displayFilterCaliper(): Promise {return this.$callMethod('displayFilterCaliper');} - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} async editorMode(): Promise {return this.$callMethod('editorMode');} async exportAsCSV(a1: string,a2: boolean): Promise {return this.$callMethod('exportAsCSV',a1,a2);} async flipped(...args: boolean[]): Promise {return this.$callMethod('flipped',...args);} @@ -1859,12 +1739,12 @@ export class RavelLockGroup extends CppClass { } export class RavelPopup extends CppClass { - backgroundColour: ecolab__cairo__Colour; + backgroundColour: mansoura__Colour; item: Item; wire: Wire; constructor(prefix: string){ super(prefix); - this.backgroundColour=new ecolab__cairo__Colour(this.$prefix()+'.backgroundColour'); + this.backgroundColour=new mansoura__Colour(this.$prefix()+'.backgroundColour'); this.item=new Item(this.$prefix()+'.item'); this.wire=new Wire(this.$prefix()+'.wire'); } @@ -1884,7 +1764,6 @@ export class RavelPopup extends CppClass { async mouseUp(a1: number,a2: number): Promise {return this.$callMethod('mouseUp',a1,a2);} async moveTo(a1: number,a2: number): Promise {return this.$callMethod('moveTo',a1,a2);} async position(): Promise {return this.$callMethod('position');} - async registerImage(): Promise {return this.$callMethod('registerImage');} async renderFrame(a1: minsky__RenderNativeWindow__RenderFrameArgs): Promise {return this.$callMethod('renderFrame',a1);} async renderToEMF(a1: string): Promise {return this.$callMethod('renderToEMF',a1);} async renderToPDF(a1: string): Promise {return this.$callMethod('renderToPDF',a1);} @@ -1899,14 +1778,6 @@ export class RavelPopup extends CppClass { async zoomFactor(): Promise {return this.$callMethod('zoomFactor');} } -export class SVGRenderer extends CppClass { - constructor(prefix: string){ - super(prefix); - } - async render(a1: minsky__dummy,a2: number,a3: number): Promise {return this.$callMethod('render',a1,a2,a3);} - async setResource(a1: string): Promise {return this.$callMethod('setResource',a1);} -} - export class Selection extends CppClass { bb: BoundingBox; bookmarks: Container; @@ -1915,7 +1786,7 @@ export class Selection extends CppClass { inVariables: Sequence; items: Sequence; outVariables: Sequence; - svgRenderer: SVGRenderer; + svgRenderer: mansoura__SVGRenderer; wires: Sequence; constructor(prefix: string){ super(prefix); @@ -1926,7 +1797,7 @@ export class Selection extends CppClass { this.inVariables=new Sequence(this.$prefix()+'.inVariables',VariableBase); this.items=new Sequence(this.$prefix()+'.items',Item); this.outVariables=new Sequence(this.$prefix()+'.outVariables',VariableBase); - this.svgRenderer=new SVGRenderer(this.$prefix()+'.svgRenderer'); + this.svgRenderer=new mansoura__SVGRenderer(this.$prefix()+'.svgRenderer'); this.wires=new Sequence(this.$prefix()+'.wires',Wire); } async RESTProcess(a1: classdesc__RESTProcess_t,a2: string): Promise {return this.$callMethod('RESTProcess',a1,a2);} @@ -1973,15 +1844,15 @@ export class Selection extends CppClass { async displayContents(): Promise {return this.$callMethod('displayContents');} async displayContentsChanged(): Promise {return this.$callMethod('displayContentsChanged');} async displayDelayedTooltip(a1: number,a2: number): Promise {return this.$callMethod('displayDelayedTooltip',a1,a2);} - async displayTooltip(a1: ICairoShim,a2: string): Promise {return this.$callMethod('displayTooltip',a1,a2);} + async displayTooltip(a1: mansoura__IMansoura,a2: string): Promise {return this.$callMethod('displayTooltip',a1,a2);} async displayZoom(...args: number[]): Promise {return this.$callMethod('displayZoom',...args);} - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} - async draw1edge(a1: Sequence,a2: minsky__dummy,a3: number): Promise {return this.$callMethod('draw1edge',a1,a2,a3);} - async drawEdgeVariables(a1: minsky__dummy): Promise {return this.$callMethod('drawEdgeVariables',a1);} - async drawIORegion(a1: minsky__dummy): Promise {return this.$callMethod('drawIORegion',a1);} - async drawPorts(a1: ICairoShim): Promise {return this.$callMethod('drawPorts',a1);} - async drawResizeHandles(a1: ICairoShim): Promise {return this.$callMethod('drawResizeHandles',a1);} - async drawSelected(a1: ICairoShim): Promise {return this.$callMethod('drawSelected',a1);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} + async draw1edge(a1: Sequence,a2: mansoura__IMansoura,a3: number): Promise {return this.$callMethod('draw1edge',a1,a2,a3);} + async drawEdgeVariables(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawEdgeVariables',a1);} + async drawIORegion(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawIORegion',a1);} + async drawPorts(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawPorts',a1);} + async drawResizeHandles(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawResizeHandles',a1);} + async drawSelected(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawSelected',a1);} async dummyDraw(): Promise {return this.$callMethod('dummyDraw');} async edgeScale(): Promise {return this.$callMethod('edgeScale');} async editorMode(): Promise {return this.$callMethod('editorMode');} @@ -2093,8 +1964,8 @@ export class Sheet extends Item { async computeValue(): Promise {return this.$callMethod('computeValue');} async contains(a1: number,a2: number): Promise {return this.$callMethod('contains',a1,a2);} async corners(): Promise {return this.$callMethod('corners');} - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} - async drawResizeHandles(a1: ICairoShim): Promise {return this.$callMethod('drawResizeHandles',a1);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} + async drawResizeHandles(a1: mansoura__IMansoura): Promise {return this.$callMethod('drawResizeHandles',a1);} async exportAsCSV(a1: string,a2: boolean): Promise {return this.$callMethod('exportAsCSV',a1,a2);} async inItem(a1: number,a2: number): Promise {return this.$callMethod('inItem',a1,a2);} async inRavel(a1: number,a2: number): Promise {return this.$callMethod('inRavel',a1,a2);} @@ -2116,7 +1987,7 @@ export class SwitchIcon extends Item { else super(prefix.$prefix()) } - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} async flip(): Promise {return this.$callMethod('flip');} async flipped(...args: boolean[]): Promise {return this.$callMethod('flipped',...args);} async numCases(): Promise {return this.$callMethod('numCases');} @@ -2153,8 +2024,8 @@ export class UserFunction extends Item { async compile(): Promise {return this.$callMethod('compile');} async create(a1: string): Promise {return this.$callMethod('create',a1);} async description(...args: any[]): Promise {return this.$callMethod('description',...args);} - async displayTooltip(a1: ICairoShim,a2: string): Promise {return this.$callMethod('displayTooltip',a1,a2);} - async draw(a1: ICairoShim): Promise {return this.$callMethod('draw',a1);} + async displayTooltip(a1: mansoura__IMansoura,a2: string): Promise {return this.$callMethod('displayTooltip',a1,a2);} + async draw(a1: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} async evaluate(a1: number,a2: number): Promise {return this.$callMethod('evaluate',a1,a2);} async expression(...args: string[]): Promise {return this.$callMethod('expression',...args);} async name(): Promise {return this.$callMethod('name');} @@ -2378,11 +2249,21 @@ export class civita__XVector extends CppClass { async timeFormat(): Promise {return this.$callMethod('timeFormat');} } -export class ecolab__Plot__LineStyle extends CppClass { - colour: ecolab__cairo__Colour; +export class mansoura__Colour extends CppClass { constructor(prefix: string){ super(prefix); - this.colour=new ecolab__cairo__Colour(this.$prefix()+'.colour'); + } + async a(...args: number[]): Promise {return this.$callMethod('a',...args);} + async b(...args: number[]): Promise {return this.$callMethod('b',...args);} + async g(...args: number[]): Promise {return this.$callMethod('g',...args);} + async r(...args: number[]): Promise {return this.$callMethod('r',...args);} +} + +export class mansoura__Plot__LineStyle extends CppClass { + colour: mansoura__Colour; + constructor(prefix: string){ + super(prefix); + this.colour=new mansoura__Colour(this.$prefix()+'.colour'); } async barWidth(...args: number[]): Promise {return this.$callMethod('barWidth',...args);} async dashPattern(): Promise {return this.$callMethod('dashPattern');} @@ -2391,14 +2272,12 @@ export class ecolab__Plot__LineStyle extends CppClass { async width(...args: number[]): Promise {return this.$callMethod('width',...args);} } -export class ecolab__cairo__Colour extends CppClass { +export class mansoura__SVGRenderer extends CppClass { constructor(prefix: string){ super(prefix); } - async a(...args: number[]): Promise {return this.$callMethod('a',...args);} - async b(...args: number[]): Promise {return this.$callMethod('b',...args);} - async g(...args: number[]): Promise {return this.$callMethod('g',...args);} - async r(...args: number[]): Promise {return this.$callMethod('r',...args);} + async render(a1: minsky__dummy,a2: number,a3: number): Promise {return this.$callMethod('render',a1,a2,a3);} + async setResource(a1: string): Promise {return this.$callMethod('setResource',a1);} } export class minsky__Canvas__ZoomCrop extends CppClass { diff --git a/gui-js/libs/ui-components/src/lib/godley-widget-view/godley-widget-view.component.ts b/gui-js/libs/ui-components/src/lib/godley-widget-view/godley-widget-view.component.ts index f01e2991d..6a2932a0f 100644 --- a/gui-js/libs/ui-components/src/lib/godley-widget-view/godley-widget-view.component.ts +++ b/gui-js/libs/ui-components/src/lib/godley-widget-view/godley-widget-view.component.ts @@ -18,7 +18,7 @@ import { ZOOM_OUT_FACTOR, events, GodleyIcon, - GodleyTableWindow + GodleyTableEditor } from '@minsky/shared'; import { fromEvent, Observable } from 'rxjs'; import { sampleTime } from 'rxjs/operators'; @@ -47,7 +47,7 @@ export class GodleyWidgetViewComponent implements OnDestroy, OnInit, AfterViewIn systemWindowId: string; windowId: number; godleyIcon: GodleyIcon; - namedItemSubCommand: GodleyTableWindow; + namedItemSubCommand: GodleyTableEditor; destroy$ = new Subject<{}>(); @@ -99,7 +99,7 @@ export class GodleyWidgetViewComponent implements OnDestroy, OnInit, AfterViewIn async ngOnInit() { this.godleyIcon = new GodleyIcon(this.electronService.minsky.namedItems.elem(this.itemId)); - this.namedItemSubCommand = this.godleyIcon.popup; + this.namedItemSubCommand = this.godleyIcon.editor; this.windowId = (await this.electronService.getCurrentWindow()).id; @@ -130,9 +130,6 @@ export class GodleyWidgetViewComponent implements OnDestroy, OnInit, AfterViewIn async windowResize() { await this.getWindowRectInfo(); - - clearTimeout(this.renderTimeout); - this.renderTimeout = setTimeout(() => this.renderFrame(), 300); } private async getWindowRectInfo() { @@ -147,25 +144,6 @@ export class GodleyWidgetViewComponent implements OnDestroy, OnInit, AfterViewIn this.width = Math.round(this.godleyCanvasContainer.clientWidth); } - renderFrame() { - if ( - this.canvasMode && - this.systemWindowId && - this.itemId && - this.height && - this.width - ) { - this.namedItemSubCommand.renderFrame({ - parentWindowId: this.systemWindowId.toString(), - offsetLeft: this.leftOffset, - offsetTop: this.topOffset, - childWidth: this.width, - childHeight: this.height, - scalingFactor: -1 - }); - } - } - initEvents() { this.godleyCanvasContainer.addEventListener('scroll', async () => { await this.handleScroll( @@ -205,23 +183,8 @@ export class GodleyWidgetViewComponent implements OnDestroy, OnInit, AfterViewIn }); this.godleyCanvasContainer.onwheel = this.onMouseWheelZoom; - document.onkeydown = this.onKeyDown; - } - async redraw() { - this.namedItemSubCommand.requestRedraw(); - } - - onKeyDown = async (event: KeyboardEvent) => { - await this.communicationService.handleKeyDown({ - event, - command: `minsky.namedItems.@elem."${this.itemId}".popup`, - }); - - await this.redraw(); - }; - onMouseWheelZoom = async (event: WheelEvent) => { event.preventDefault(); const zoomFactor = event.deltaY<0 ? ZOOM_IN_FACTOR : ZOOM_OUT_FACTOR; @@ -229,7 +192,7 @@ export class GodleyWidgetViewComponent implements OnDestroy, OnInit, AfterViewIn const area = this.windowUtilityService.getDrawableArea(); //TODO: throttle here if required - this.namedItemSubCommand.zoom(area.width/2, area.height/2, zoomFactor); + //this.namedItemSubCommand.zoom(area.width/2, area.height/2, zoomFactor); }; async handleScroll(scrollTop: number, scrollLeft: number) { @@ -246,7 +209,7 @@ export class GodleyWidgetViewComponent implements OnDestroy, OnInit, AfterViewIn this.namedItemSubCommand.scrollColStart(currentStepX); this.namedItemSubCommand.scrollRowStart(currentStepY); - this.redraw(); +// this.redraw(); } async contextMenu(i: number, j: number, clickType: string) { diff --git a/makeDist.sh b/makeDist.sh index 975a33932..47bd94fa9 100755 --- a/makeDist.sh +++ b/makeDist.sh @@ -12,7 +12,7 @@ if [ $# -ge 1 ]; then fi # add in submodules -for sub in ecolab ecolab/classdesc ecolab/classdesc/json5_parser ecolab/graphcode RavelCAPI RavelCAPI/civita exprtk libclipboard; do +for sub in ecolab ecolab/classdesc ecolab/classdesc/json5_parser ecolab/graphcode RavelCAPI RavelCAPI/civita exprtk libclipboard mansoura; do pushd $sub git archive --format=tar --prefix=$MINSKY_VERSION/$sub/ HEAD -o /tmp/$$.tar tar tvf /tmp/$$.tar diff --git a/mansoura b/mansoura new file mode 160000 index 000000000..6a8e8c69c --- /dev/null +++ b/mansoura @@ -0,0 +1 @@ +Subproject commit 6a8e8c69ca688e76d58007dd04838eb0d2b9d5ed diff --git a/model/CSVDialog.cc b/model/CSVDialog.cc index 22f1c8ccf..d00b54069 100644 --- a/model/CSVDialog.cc +++ b/model/CSVDialog.cc @@ -44,8 +44,6 @@ using namespace std; using namespace minsky; using namespace civita; -using ecolab::Pango; -using ecolab::cairo::CairoSave; #include using std::filesystem::file_size; diff --git a/model/ICairoShim.h b/model/ICairoShim.h deleted file mode 100644 index fd1ef1330..000000000 --- a/model/ICairoShim.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - Abstract interface for Cairo operations to enable testing and mocking - @copyright Steve Keen 2012 - @author Russell Standish - This file is part of Minsky. - - Minsky is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Minsky is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Minsky. If not, see . -*/ -#ifndef ICAIROSHIM_H -#define ICAIROSHIM_H - -#include -#include -#include -#include - -namespace minsky -{ - class SVGRenderer; - - struct TextProperties - { - // markup overrides the text entry - std::string markup, plainText; - double fontSize=std::nan(""); - double angle=0; - std::string fontFamily; - TextProperties(const std::string& markup="", const std::string& plainText="", double fontSize=std::nan("")): - markup(markup), plainText(plainText), fontSize(fontSize) {} - TextProperties(const std::string& markup, double fontSize): - markup(markup), fontSize(fontSize) {} - }; - - struct TextExtents - { - double left, top, width, height; - }; - - /// cache results of font rendering to amortise setup costs - class ICacheRender - { - public: - virtual ~ICacheRender()=default; - virtual void show()=0; - virtual TextExtents extents() const=0; - virtual void* context() const=0; - }; - - class ICairoShim; - - /// Abstract interface for Cairo drawing operations - class ICairoShim - { - public: - virtual ~ICairoShim() = default; - - /// @{ Drawing operations - virtual void moveTo(double x, double y) const = 0; - virtual void lineTo(double x, double y) const = 0; - virtual void relMoveTo(double x, double y) const = 0; - virtual void relLineTo(double x, double y) const = 0; - virtual void arc(double x, double y, double radius, double start, double end) const = 0; - virtual void curveTo(double x1, double y1, double x2, double y2, double x3, double y3) const = 0; - virtual void rectangle(double x, double y, double width, double height) const = 0; - /// @} - - /// @{ Path operations - virtual void newPath() const = 0; - virtual void newSubPath() const = 0; - virtual void closePath() const = 0; - virtual void getCurrentPoint(double& x, double& y) const = 0; - /// @} - - /// @{ Fill and stroke operations - virtual void fill() const = 0; - virtual void fillPreserve() const = 0; - virtual void stroke() const = 0; - virtual void strokePreserve() const = 0; - virtual void clip() const = 0; - virtual void resetClip() const = 0; - virtual void paint() const = 0; - /// @} - - /// @{ Line properties - virtual void setLineWidth(double width) const = 0; - virtual double getLineWidth() const = 0; - virtual void setDash(const double* dashes, int num_dashes, double offset) const = 0; - virtual void setFillRule(cairo_fill_rule_t fill_rule) const = 0; - /// @} - - /// @{ Color operations - virtual void setSourceRGB(double r, double g, double b) const = 0; - virtual void setSourceRGBA(double r, double g, double b, double a) const = 0; - /// @} - - /// render text - virtual void showText(const TextProperties& text) const = 0; - /// show markup text - void showText(const std::string& s, double fs=std::nan("")) const - {showText(TextProperties(s,fs));} - /// show text with no markup interpretation - void showPlainText(const std::string& s, double fs=std::nan("")) const - {showText(TextProperties("",s,fs));} -// virtual void setFontSize(double size) const = 0; -// virtual void selectFontFace(const std::string& family, cairo_font_slant_t slant, cairo_font_weight_t weight) const = 0; - /// return metrics for a given bit of text - virtual TextExtents textExtents(const TextProperties& text) const = 0; - - /// @{ Transformation operations - virtual void identityMatrix() const = 0; - virtual void translate(double x, double y) const = 0; - virtual void scale(double sx, double sy) const = 0; - virtual void rotate(double angle) const = 0; - virtual void userToDevice(double& x, double& y) const = 0; - /// @} - - /// @{ Context state operations - virtual void save() const = 0; - virtual void restore() const = 0; - /// @} - - /// Tolerance - virtual void setTolerance(double tolerance) const = 0; - - // SVG rendering support - /// Render an SVG resource into a region of size width x height - /// @param svgRenderer - Reference to SVGRenderer containing the loaded SVG resource - /// @param width - target width for rendering - /// @param height - target height for rendering - virtual void renderSVG(const SVGRenderer& svgRenderer, double width, double height) const = 0; - - /// returns reference to underlying context for caching purposes - virtual void* context() const=0; - - /// return a cached object of rendered text - virtual std::unique_ptr cachedRender(const TextProperties& tp) const=0; - }; - - /// RAII wrapper around save/restore - struct CairoShimSave - { - const ICairoShim& shim; - CairoShimSave(const ICairoShim& shim): shim(shim) {shim.save();} - ~CairoShimSave() {shim.restore();} - }; - -} - -#include "ICairoShim.xcd" -#endif // ICAIROSHIM_H diff --git a/model/SVGItem.cc b/model/SVGItem.cc deleted file mode 100644 index c3d10e570..000000000 --- a/model/SVGItem.cc +++ /dev/null @@ -1,104 +0,0 @@ -/* - @copyright Steve Keen 2012 - @author Russell Standish - This file is part of Minsky. - - Minsky is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Minsky is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Minsky. If not, see . -*/ -// Implementations of canvas items representing operations and variables. - -/* - @copyright Steve Keen 2014 - @author Russell Standish - This file is part of Minsky. - - Minsky is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Minsky is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Minsky. If not, see . -*/ -#include "SVGItem.h" -#include "SVGItem.rcd" -#include "cairo_base.h" -#include "minsky_epilogue.h" -#include - -// if not #ifdef protected, you get a deprecated warning, which is -// made fatal by -Werror -#ifndef RSVG_CAIRO_H -#include -#endif - -#include -using namespace std; - -namespace minsky -{ - - void SVGRenderer::setResource(const std::string& resource) - { - if (svg) g_object_unref(svg); - GError* err=nullptr; - svg=rsvg_handle_new_from_file(resource.c_str(),&err); - if (err) - { - std::string msg="SVGRenderer failed to initialise: "; - msg+=err->message; - g_error_free(err); - throw runtime_error(msg); - } -#ifdef MXE // MXE doesn't currently have a Rust compiler, so librsvg can be no later than 2.40.21 - if (!svg) - throw runtime_error("SVGRenderer failed to initialise"); - RsvgDimensionData dims; - rsvg_handle_get_dimensions(svg, &dims); - m_width=dims.width; - m_height=dims.height; -#endif - } - - - SVGRenderer::~SVGRenderer() - { - if (svg) - g_object_unref(svg); - } - - void SVGRenderer::render(cairo_t* cairo, double width, double height) const - { - if (svg) - { -#ifdef MXE // MXE doesn't currently have a Rust compiler, so librsvg can be no later than 2.40.21 - cairo_scale(cairo,width/m_width, height/m_height); - rsvg_handle_render_cairo(svg,cairo); -#else - GError* err=nullptr; - const RsvgRectangle rect{0,0,width,height}; - rsvg_handle_render_document(svg,cairo,&rect,&err); -#endif - } - } - -} -CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::SVGRenderer); - - diff --git a/model/SVGItem.h b/model/SVGItem.h deleted file mode 100644 index 188ae7fe2..000000000 --- a/model/SVGItem.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - @copyright Steve Keen 2014 - @author Russell Standish - This file is part of Minsky. - - Minsky is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Minsky is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Minsky. If not, see . -*/ -#ifndef SVGITEM_H -#define SVGITEM_H -#include -#include "classdesc_access.h" -#include -#include -#include - -namespace minsky -{ - class SVGRenderer - { - classdesc::Exclude svg=nullptr; - CLASSDESC_ACCESS(SVGRenderer); -#ifdef MXE - double m_width=0, m_height=0; -#endif - friend class CairoShimCairo; - public: - SVGRenderer() {} - SVGRenderer(const std::string& resource) {setResource(resource);} - SVGRenderer(const SVGRenderer&)=delete; - void operator=(const SVGRenderer&)=delete; - ~SVGRenderer(); - - /// initialise object from an SVG file - void setResource(const std::string& resource); - /// render SVG into region of size \a width \a height - void render(cairo_t*, double width, double height) const; - }; - - -} - -namespace classdesc -{ -#define CLASSDESC_TYPENAME___RsvgHandle - template <> - struct tn { - static string name() {return "RsvgHandle";} - }; -} - - -#include "SVGItem.cd" -#include "SVGItem.xcd" -#endif diff --git a/model/cairoItems.cc b/model/cairoItems.cc index a0249f653..bb93a6c16 100644 --- a/model/cairoItems.cc +++ b/model/cairoItems.cc @@ -28,30 +28,20 @@ #include "minsky.h" #include "cairoItems.h" -#include "cairoShimCairo.h" #include "operation.h" #include "latexMarkup.h" #include -#include #include "ravelWrap.xcd" #include "minsky_epilogue.h" #include -using namespace ecolab; -using ecolab::cairo::CairoSave; +using namespace mansoura; using namespace std; using namespace minsky; using namespace boost::geometry; -namespace -{ - // for use when calculating bounding boxes, but not drawing to anything? - cairo::Surface dummySurf(cairo_image_surface_create(CAIRO_FORMAT_A1, 100,100)); - CairoShimCairo dummyCairoShim(dummySurf.cairo()); -} - -RenderVariable::RenderVariable(const VariableBase& var, const ICairoShim& shim): +RenderVariable::RenderVariable(const VariableBase& var, const mansoura::IMansoura& shim): var(var), cairoShim(shim), m_context(cairoShim.context()) { TextProperties textProperties; @@ -90,7 +80,7 @@ RenderVariable::RenderVariable(const VariableBase& var, const ICairoShim& shim): } RenderVariable::RenderVariable(const VariableBase& var): - RenderVariable(var, dummyCairoShim) {} + RenderVariable(var, measuringContext()) {} bool RenderVariable::inImage(float x, float y) { @@ -113,21 +103,7 @@ double RenderVariable::handlePos() const } void minsky::drawTriangle -(cairo_t* cairo, double x, double y, const cairo::Colour& col, double angle) -{ - const CairoSave cs(cairo); - cairo_new_path(cairo); - cairo_set_source_rgba(cairo,col.r,col.g,col.b,col.a); - cairo_translate(cairo,x,y); - cairo_rotate(cairo, angle); - cairo_move_to(cairo,10,0); - cairo_line_to(cairo,0,-3); - cairo_line_to(cairo,0,3); - cairo_fill(cairo); -} - -void minsky::drawTriangle -(const ICairoShim& cairoShim, double x, double y, const cairo::Colour& col, double angle) +(const mansoura::IMansoura& cairoShim, double x, double y, const Colour& col, double angle) { cairoShim.save(); cairoShim.newPath(); diff --git a/model/cairoItems.h b/model/cairoItems.h index 712e559ec..d3da8ffa2 100644 --- a/model/cairoItems.h +++ b/model/cairoItems.h @@ -20,9 +20,8 @@ #define CAIRO_ITEMS_H #include #include -#include -#include -#include +#include "IMansoura.h" +#include "IMansoura.cd" #include "operation.h" #include "variable.h" @@ -34,14 +33,14 @@ namespace minsky class RenderVariable { const VariableBase& var; - const ICairoShim& cairoShim; + const mansoura::IMansoura& cairoShim; // caching of text rendering - std::shared_ptr cachedRenderer; + std::shared_ptr cachedRenderer; void* m_context; float w, h, hoffs; public: RenderVariable(const VariableBase& var); - RenderVariable(const VariableBase& var, const ICairoShim& shim); + RenderVariable(const VariableBase& var, const mansoura::IMansoura& shim); /// render the cairo image void draw() {var.draw(cairoShim);} /// render cached text @@ -59,7 +58,6 @@ namespace minsky void* context() const {return m_context;} }; - void drawTriangle(cairo_t* cairo, double x, double y, const ecolab::cairo::Colour& col, double angle=0); - void drawTriangle(const ICairoShim& cairoShim, double x, double y, const ecolab::cairo::Colour& col, double angle=0); + void drawTriangle(const mansoura::IMansoura& cairoShim, double x, double y, const mansoura::Colour& col, double angle=0); } #endif diff --git a/model/canvas.cc b/model/canvas.cc index ed2f2ce21..917301d05 100644 --- a/model/canvas.cc +++ b/model/canvas.cc @@ -26,7 +26,7 @@ #include "ravelWrap.h" #include -#include "cairoShimCairo.h" +#include "mansouraCairo.h" #include "canvas.rcd" #include "canvas.xcd" #include "eventInterface.rcd" @@ -37,6 +37,7 @@ using namespace std; using namespace ecolab::cairo; using namespace minsky; +using namespace mansoura; namespace minsky { @@ -796,7 +797,7 @@ namespace minsky return false; } - bool Canvas::redraw(int x0, int y0, int width, int height) + bool Canvas::redraw(const IMansoura& cairoShim, int x0, int y0, int width, int height) { updateRegion.x0=x0; updateRegion.y0=y0; @@ -805,7 +806,7 @@ namespace minsky // redraw of canvas may throw if called during a reset operation try { - return redrawUpdateRegion(); + return redrawUpdateRegion(cairoShim); } #ifndef NDEBUG catch (std::exception& ex) @@ -822,45 +823,36 @@ namespace minsky return false; } - bool Canvas::redraw() - { - // nb using maxint here doesn't seem to work - return redraw(-1e6,-1e6,2e6,2e6); - } - - bool Canvas::redrawUpdateRegion() + bool Canvas::redrawUpdateRegion(const IMansoura& mans) { bool didDrawSomething = false; - if (!surface().get()) { - return didDrawSomething; - } m_redrawRequested=false; - auto cairo=surface()->cairo(); - const CairoSave cs(cairo); - cairo_rectangle(cairo,updateRegion.x0,updateRegion.y0,updateRegion.x1-updateRegion.x0,updateRegion.y1-updateRegion.y0); - cairo_clip(cairo); - cairo_set_line_width(cairo, 1); + + mans.rectangle(updateRegion.x0,updateRegion.y0,updateRegion.x1-updateRegion.x0,updateRegion.y1-updateRegion.y0); + mans.clip(); + mans.setLineWidth(1); // items model->recursiveDo (&GroupItems::items, [&](const Items&, Items::const_iterator i) { auto& it=**i; if (it.visible() && updateRegion.intersects(it)) - { - didDrawSomething = true; - const CairoSave cs(cairo); - cairo_identity_matrix(cairo); - cairo_translate(cairo,it.x(), it.y()); - try - { - CairoShimCairo shim(cairo); - it.draw(shim); - } - catch (const std::exception& ex) - { - cerr << ex.what() << endl; - } - } + try + { + didDrawSomething = true; + const PreserveContext cs(mans); + mans.identityMatrix(); + mans.translate(it.x(), it.y()); + it.draw(mans); + } + catch (const std::exception& ex) + { + cout<name(); + cout<x(),fromPort->y()); - cairo_line_to(cairo,termX,termY); - cairo_stroke(cairo); + mans.moveTo(fromPort->x(),fromPort->y()); + mans.lineTo(termX,termY); + mans.stroke(); // draw arrow - const CairoSave cs(cairo); - cairo_translate(cairo, termX,termY); - cairo_rotate(cairo,atan2(termY-fromPort->y(), termX-fromPort->x())); - cairo_move_to(cairo,0,0); - cairo_line_to(cairo,-5,-3); - cairo_line_to(cairo,-3,0); - cairo_line_to(cairo,-5,3); - cairo_close_path(cairo); - cairo_fill(cairo); + const PreserveContext cs(mans); + mans.translate(termX,termY); + mans.rotate(atan2(termY-fromPort->y(), termX-fromPort->x())); + mans.moveTo(0,0); + mans.lineTo(-5,-3); + mans.lineTo(-3,0); + mans.lineTo(-5,3); + mans.closePath(); + mans.fill(); } if (lassoMode!=LassoMode::none) { didDrawSomething = true; - cairo_rectangle(cairo,lasso.x0,lasso.y0,lasso.x1-lasso.x0,lasso.y1-lasso.y0); - cairo_stroke(cairo); + mans.rectangle(lasso.x0,lasso.y0,lasso.x1-lasso.x0,lasso.y1-lasso.y0); + mans.stroke(); } if (itemIndicator) // draw a red circle to indicate an error or other marker { - const CairoSave cs(surface()->cairo()); - cairo_set_source_rgb(surface()->cairo(),1,0,0); - cairo_arc(surface()->cairo(),itemIndicator->x(),itemIndicator->y(),15,0,2*M_PI); - cairo_stroke(surface()->cairo()); + const PreserveContext cs(mans); + mans.setSourceRGB(1,0,0); + mans.arc(itemIndicator->x(),itemIndicator->y(),15,0,2*M_PI); + mans.stroke(); } - surface()->blit(); return didDrawSomething; } void Canvas::recentre() { - const SurfacePtr tmp(surface()); - surface().reset(new Surface(cairo_recording_surface_create(CAIRO_CONTENT_COLOR,nullptr))); - redraw(); - model->moveTo(model->x()-surface()->left(), model->y()-surface()->top()); - surface()=tmp; + const auto ink=mansoura::inkExtents([this](const IMansoura& shim){redraw(shim,-1e6,-1e6,2e6,2e6);}); + model->moveTo(model->x()-ink.left, model->y()-ink.top); requestRedraw(); } @@ -949,18 +935,18 @@ namespace minsky minsky().maxWaitMS=(t>0.03)? 3000*t: 100.0; } - void Canvas::renderToPNGCropped(const std::string& filename, const ZoomCrop& z) + void Canvas::renderToPNGCropped(const std::string& filename, const ZoomCrop& z) { model->zoom(model->x(),model->y(),z.zoom); model->moveTo(model->x()-z.left,model->y()-z.top); - cairo::SurfacePtr tmp(new cairo::Surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32,z.width,z.height))); - tmp.swap(surface()); - redraw(0,0,z.width,z.height); - tmp.swap(surface()); - cairo_surface_write_to_png(tmp->surface(),filename.c_str()); - model->moveTo(model->x()+z.left,model->y()+z.top); - model->zoom(model->x(),model->y(),1/z.zoom); - } + // RAII zoom and move operations to make things exception safe + auto zoomUndo=onStackExit([&](){ + model->moveTo(model->x()+z.left,model->y()+z.top); + model->zoom(model->x(),model->y(),1/z.zoom); + }); + mansoura::renderToPNG(filename,z.width,z.height, + [&](const IMansoura& shim){redraw(shim,0,0,z.width,z.height);}); + } diff --git a/model/canvas.h b/model/canvas.h index e4555547f..51d02e623 100644 --- a/model/canvas.h +++ b/model/canvas.h @@ -55,7 +55,7 @@ namespace minsky void copyVars(const std::vector&); void reportDrawTime(double) override; void mouseDownCommon(float x, float y); - bool redraw(int x0, int y0, int width, int height) override; + bool redraw(const mansoura::IMansoura& cairoShim, int x0, int y0, int width, int height) override; void mouseMoveOnItem(float x, float y); /// flag indicating that a redraw is requested, but not yet redrawn @@ -145,8 +145,6 @@ namespace minsky Canvas() {} Canvas(const GroupPtr& m): model(m) {} - ecolab::cairo::SurfacePtr& surface() {return ecolab::CairoSurface::surface;} - /// event handling for the canvas void mouseDown(float x, float y) override; void controlMouseDown(float x, float y) override; @@ -276,12 +274,10 @@ namespace minsky /// draw a red circle around item // void indicateItem() {itemIndicator=true;} - /// redraw whole model - bool redraw(); /// region to be updated LassoBox updateRegion{0,0,0,0}; /// update region given by updateRegion - bool redrawUpdateRegion(); + bool redrawUpdateRegion(const mansoura::IMansoura& cairoShim); struct ZoomCrop { @@ -298,7 +294,7 @@ namespace minsky /// flag indicating that a redraw is requested, but not yet redrawn bool redrawRequested() const {return m_redrawRequested;} /// request a redraw on the screen - void requestRedraw() {m_redrawRequested=true; if (surface().get()) surface()->requestRedraw();} + void requestRedraw() {m_redrawRequested=true; RenderNativeWindow::requestRedraw();} bool hasScrollBars() const override {return true;} void setDefaultPlotOptions() { diff --git a/model/dataOp.h b/model/dataOp.h index fe1385227..7497b01e9 100644 --- a/model/dataOp.h +++ b/model/dataOp.h @@ -31,7 +31,7 @@ namespace minsky CLASSDESC_ACCESS(DataOp); friend struct SchemaHelper; void updateBB() override {bb.update(*this);} - void draw(const ICairoShim& cairoShim) const override { + void draw(const mansoura::IMansoura& cairoShim) const override { if (description().empty()) OperationBase::draw(cairoShim); else diff --git a/model/equationDisplay.cc b/model/equationDisplay.cc index d3a6a4df8..532552d0e 100644 --- a/model/equationDisplay.cc +++ b/model/equationDisplay.cc @@ -29,32 +29,33 @@ #include "item.rcd" #include "noteBase.rcd" #include "port.rcd" +#include "IMansoura.h" +#include "IMansoura.cd" #include "minsky_epilogue.h" namespace minsky { - bool EquationDisplay::redraw(int x0, int y0, int width, int height) + bool EquationDisplay::redraw(const mansoura::IMansoura& shim, int x0, int y0, int width, int height) { - if (surface.get()) { - const BusyCursor busy(m); - const MathDAG::SystemOfEquations system(m); - cairo_rectangle(surface->cairo(),0,0,width,height); - cairo_clip(surface->cairo()); - cairo_move_to(surface->cairo(),offsx,offsy); - cairo_scale(surface->cairo(),m_zoomFactor,m_zoomFactor); - system.renderEquations(*surface,height); - if (m.flags & Minsky::fullEqnDisplay_needed) + const BusyCursor busy(m); + const MathDAG::SystemOfEquations system(m); + shim.rectangle(0,0,width,height); + shim.clip(); + shim.moveTo(offsx,offsy); + shim.scale(m_zoomFactor,m_zoomFactor); + system.renderEquations(shim,height); + if (m.flags & Minsky::fullEqnDisplay_needed) + { + const auto ink=mansoura::inkExtents([&](const mansoura::IMansoura& rec) { - ecolab::cairo::Surface surf - (cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,NULL)); - system.renderEquations(surf,std::numeric_limits::max()); - m_width=surf.width(); - m_height=surf.height(); - m.flags &= ~Minsky::fullEqnDisplay_needed; - } - return true; - } - return surface.get(); + rec.moveTo(0,0); + system.renderEquations(rec,std::numeric_limits::max()); + }); + m_width=ink.width; + m_height=ink.height; + m.flags &= ~Minsky::fullEqnDisplay_needed; + } + return true; } } diff --git a/model/equationDisplay.h b/model/equationDisplay.h index 6d288059b..ce88f5917 100644 --- a/model/equationDisplay.h +++ b/model/equationDisplay.h @@ -30,7 +30,7 @@ namespace minsky { Minsky& m; double m_width=0, m_height=0; - bool redraw(int x0, int y0, int width, int height) override; + bool redraw(const mansoura::IMansoura& cairoShim, int x0, int y0, int width, int height) override; CLASSDESC_ACCESS(EquationDisplay); public: float offsx=0, offsy=0, m_zoomFactor=1 ; // pan & zooming controls @@ -39,7 +39,7 @@ namespace minsky EquationDisplay(Minsky& m): m(m) {} EquationDisplay& operator=(const EquationDisplay& x) {RenderNativeWindow::operator=(x); return *this;} EquationDisplay(const EquationDisplay&)=default; - void requestRedraw() {if (surface.get()) surface->requestRedraw();} + void requestRedraw() {RenderNativeWindow::requestRedraw();} bool hasScrollBars() const override {return true;} }; diff --git a/model/fontDisplay.h b/model/fontDisplay.h index 0f00b72d8..4a13a1cc9 100644 --- a/model/fontDisplay.h +++ b/model/fontDisplay.h @@ -21,24 +21,20 @@ #define FONTDISPLAY_H #include "renderNativeWindow.h" #include "classdesc_access.h" -#include namespace minsky { // display a sample of the current selected font class FontDisplay: public RenderNativeWindow { - bool redraw(int, int, int width, int height) override { - cairo_move_to(surface->cairo(),0,0); - ecolab::Pango pango(surface->cairo()); - pango.setFontSize(10); - pango.setText("←→↑↓—▼αΣ∫√⊗≤"); - pango.show(); + bool redraw(const mansoura::IMansoura& mans, int, int, int width, int height) override { + mans.moveTo(0,0); + mans.showPlainText("←→↑↓—▼αΣ∫√⊗≤",10); return true; } CLASSDESC_ACCESS(FontDisplay); public: - void requestRedraw() {if (surface.get()) surface->requestRedraw();} + void requestRedraw() {RenderNativeWindow::requestRedraw();} FontDisplay()=default; FontDisplay(const FontDisplay&)=default; FontDisplay& operator=(const FontDisplay&) {return *this;} diff --git a/model/godleyIcon.cc b/model/godleyIcon.cc index 189c792be..81678d4b3 100644 --- a/model/godleyIcon.cc +++ b/model/godleyIcon.cc @@ -19,23 +19,20 @@ #include "minsky.h" #include "variable.h" #include "godleyIcon.h" -#include "godleyTableWindow.h" #include "cairoItems.h" #include "selection.h" #include #include #include -#include #include -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "godleyIcon.rcd" #include "itemT.rcd" -#include "godleyTableWindow.xcd" +#include "godleyTableEditor.xcd" #include "minsky_epilogue.h" #include using namespace boost::locale::conv; -using namespace ecolab::cairo; -using namespace ecolab; +using namespace mansoura; using namespace std; // width of draggable border @@ -53,9 +50,9 @@ namespace minsky struct DrawVarsShim { - const ICairoShim& cairoShim; + const mansoura::IMansoura& cairoShim; float x, y; - DrawVarsShim(const ICairoShim& cairoShim, float x, float y): + DrawVarsShim(const mansoura::IMansoura& cairoShim, float x, float y): cairoShim(cairoShim), x(x), y(y) {} void operator()(const GodleyIcon::Variables& vars) const @@ -230,7 +227,7 @@ namespace minsky bool recordHistory) { if (!table.cellInTable(row,col)) return; - if (recordHistory) popup.pushHistory(); + if (recordHistory) editor.pushHistory(); // if this operation is clearing an initial condition cell, set it to 0 string& c=table.cell(row,col); if (newVal.empty() && !c.empty() && table.initialConditionRow(row)) @@ -248,7 +245,7 @@ namespace minsky { if (row>0 && row<=table.rows()) { - popup.pushHistory(); + editor.pushHistory(); table.deleteRow(row-1); // if shared column data is deleted, remove it from the other tables too for (size_t col=1; col(editor).zoomFactor=1; - const_cast(editor).draw(surf.cairo()); - const_cast(editor).zoomFactor=min((w-leftMargin()-2*border*z)/surf.width(),(h-bottomMargin()-2*border*z-titleOffs())/surf.height()); + auto recorder=makeRecordingContext(); + const_cast(editor).draw(*recorder); + auto extents=recordedInkExtents(*recorder); + const_cast(editor).zoomFactor=min((w-leftMargin()-2*border*z)/extents.width,(h-bottomMargin()-2*border*z-titleOffs())/extents.height); const_cast(editor).draw(cairoShim); titley=-0.5*h; w+=2*border*z; h+=2*border*z; left-=border*z; top-=border*z; - cairoShim.restore(); } else { - cairoShim.save(); + PreserveContext stash(cairoShim); cairoShim.translate(left+leftMargin(),top); - // Render SVG using ICairoShim abstraction + // Render SVG using mansoura::IMansoura abstraction cairoShim.renderSVG(svgRenderer, w-leftMargin(), h-bottomMargin()); titley=top+0.1*(h-bottomMargin()); - cairoShim.restore(); } if (!table.title.empty()) { - cairoShim.save(); + PreserveContext stash(cairoShim); TextProperties tp(""+latexToPango(table.title)+""); tp.fontSize=titleOffs(); auto bbox=cairoShim.textExtents(tp); cairoShim.moveTo(-0.5*(bbox.width-leftMargin()), titley); cairoShim.showText(tp); - cairoShim.restore(); } diff --git a/model/godleyIcon.h b/model/godleyIcon.h index f2501be05..0bf97cb32 100644 --- a/model/godleyIcon.h +++ b/model/godleyIcon.h @@ -21,18 +21,17 @@ #include "variable.h" #include "godleyTable.h" -#include "godleyTableWindow.h" +#include "godleyTableEditor.h" #include "zoom.h" #include "intrusiveMap.h" #include "classdesc_access.h" #include "SVGItem.h" +#include "SVGItem.cd" #include "group.h" #include "valueId.h" #include "variableValue.h" #include -#include -#include namespace minsky { @@ -60,7 +59,7 @@ namespace minsky void setCellImpl(int row, int col, const string& val, bool recordHistory); public: - static SVGRenderer svgRenderer; ///< SVG icon to display when not in editor mode + static mansoura::SVGRenderer svgRenderer; ///< SVG icon to display when not in editor mode GodleyIcon(); GodleyIcon(const GodleyIcon&)=default; @@ -81,15 +80,11 @@ namespace minsky GodleyTable table; /// rendering as a godley table GodleyTableEditor editor{*this}; - /// for rendering the popup window - GodleyTableWindow popup{*this}; /// whether to display values in this table bool displayValues=false; void toggleDisplayValues() {displayValues=!displayValues;} - void adjustPopupWidgets() {popup.adjustWidgets();} - /// scale icon until it's height or width matches \a h or \a w depending on which is minimum void scaleIcon(float w, float h); @@ -140,7 +135,7 @@ namespace minsky ClickType::Type clickType(float x, float y) const override; /// draw icon to \a context - void draw(const ICairoShim& cairoShim) const override; + void draw(const mansoura::IMansoura& cairoShim) const override; /// return the A-L-E row sum for \a row std::string rowSum(int row) const; @@ -166,9 +161,6 @@ namespace minsky bool onKeyPress(int, const std::string&, int) override; bool inItem(float, float) const override; - /// clean up popup window structures on window close - void destroyFrame() override {popup.destroyFrame();} - /// return true if any wires are attached to the variables bool wiresAttached() const; diff --git a/model/godleyTableWindow.cc b/model/godleyTableEditor.cc similarity index 88% rename from model/godleyTableWindow.cc rename to model/godleyTableEditor.cc index b3e37dd4e..e9af4b8e0 100644 --- a/model/godleyTableWindow.cc +++ b/model/godleyTableEditor.cc @@ -19,28 +19,23 @@ #include "cairoItems.h" #include "minsky.h" -#include "godleyTableWindow.h" -#include "../engine/cairoShimCairo.h" +#include "godleyTableEditor.h" #include "selection.h" #include "latexMarkup.h" -#include #include "assetClass.rcd" -#include "godleyTableWindow.rcd" -#include "godleyTableWindow.xcd" +#include "godleyTableEditor.rcd" +#include "godleyTableEditor.xcd" +#include "IMansoura.cd" #include "minsky_epilogue.h" #include using namespace std; using namespace minsky; -using ecolab::Pango; -using namespace ecolab::cairo; +using namespace mansoura; using namespace boost::locale::conv; -#include -#include -#include namespace { @@ -60,11 +55,11 @@ namespace {.6,.5,0} }; - void showAsset(Pango& pango, cairo_t* cairo, GodleyAssetClass::AssetClass assetClass) + void showAsset(ICacheRender& pango, const IMansoura& mans, GodleyAssetClass::AssetClass assetClass) { - const CairoSave cs(cairo); + const PreserveContext cs(mans); auto& colour=assetColour[assetClass]; - cairo_set_source_rgb(cairo,colour.r,colour.g,colour.b); + mans.setSourceRGB(colour.r,colour.g,colour.b); pango.show(); } @@ -154,11 +149,12 @@ namespace minsky return m_godleyIcon.table.cellInTable(selectedRow, selectedCol); } - void GodleyTableEditor::draw(cairo_t *cairo) + void GodleyTableEditor::draw(const IMansoura& cairo) { - const CairoSave cs(cairo); - cairo_scale(cairo,zoomFactor,zoomFactor); - Pango pango(cairo); + const PreserveContext cs(cairo); + cairo.scale(zoomFactor,zoomFactor); + auto pangoPtr=cairo.cachedRender(TextProperties()); + ICacheRender& pango=*pangoPtr; pango.setMarkup("Flows ↓ / Stock Vars →"); rowHeight=pango.height()+2; const double tableHeight=(m_godleyIcon.table.rows()-scrollRowStart+1)*rowHeight; @@ -166,7 +162,8 @@ namespace minsky double lastAssetBoundary=x; auto assetClass=GodleyAssetClass::noAssetClass; // only recalculate colmn widths when no cell is selected. - const bool resizeGrid=selectedCol<0 || selectedRow<0 || motionRow>=0 || motionCol>=0; + const bool resizeGrid=selectedCol<0 || selectedRow<0 || motionRow>=0 || motionCol>=0 || + colLeftMargin.size()0 && col1) { - cairo_move_to(cairo,x-pulldownHot,topTableOffset); + cairo.moveTo(x-pulldownHot,topTableOffset); pango.setMarkup("▼"); pango.show(); } @@ -219,12 +216,12 @@ namespace minsky if (drawButtons && col==0 && row>0 && row0 && col>0) { // handle DR/CR mode and colouring of text if (fc.coef<0) - cairo_set_source_rgb(cairo,1,0,0); + cairo.setSourceRGB(1,0,0); if (cminsky().displayStyle==GodleyTable::DRCR) { if (assetClass==GodleyAssetClass::asset || @@ -286,7 +283,7 @@ namespace minsky pango.setMarkup(text); } colWidth=max(colWidth,pango.width() + (row==0? pulldownHot:0)); - cairo_move_to(cairo,x+3,y); + cairo.moveTo(x+3,y); pango.show(); y+=rowHeight; } @@ -302,7 +299,7 @@ namespace minsky } // display pulldown for last column - cairo_move_to(cairo,x-pulldownHot,topTableOffset); + cairo.moveTo(x-pulldownHot,topTableOffset); pango.setMarkup("▼"); pango.show(); @@ -311,23 +308,23 @@ namespace minsky // increase column by enough to fit asset class label if (x < pango.width()+lastAssetBoundary+3) x=pango.width()+lastAssetBoundary+3; - cairo_move_to(cairo,0.5*(x+lastAssetBoundary-pango.width()),0); + cairo.moveTo(0.5*(x+lastAssetBoundary-pango.width()),0); showAsset(pango, cairo, assetClass); // final column vertical line colLeftMargin.push_back(x); - cairo_move_to(cairo,x,topTableOffset); - cairo_rel_line_to(cairo,0,tableHeight); - cairo_move_to(cairo,x+3,topTableOffset); - cairo_rel_line_to(cairo,0,tableHeight); - cairo_set_line_width(cairo,0.5); - cairo_stroke(cairo); + cairo.moveTo(x,topTableOffset); + cairo.relLineTo(0,tableHeight); + cairo.moveTo(x+3,topTableOffset); + cairo.relLineTo(0,tableHeight); + cairo.setLineWidth(0.5); + cairo.stroke(); - cairo_move_to(cairo,x-pulldownHot,topTableOffset); + cairo.moveTo(x-pulldownHot,topTableOffset); // now row sum column x+=3; double y=topTableOffset; - cairo_move_to(cairo,x,0); // display A-L-E above the final column. for ticket 1285 + cairo.moveTo(x,0); // display A-L-E above the final column. for ticket 1285 pango.setMarkup("A-L-E"); pango.show(); double colWidth=pango.width(); @@ -337,7 +334,7 @@ namespace minsky if (row >0 && row0 && row0 || hoverCol>0) && size_t(hoverRow)=int(scrollRowStart) && selectedRow=int(scrollColStart)) i=selectedCol-scrollColStart+1; const double xx=colLeftMargin[i], yy=j*rowHeight+topTableOffset; { - const cairo::CairoSave cs(cairo); - cairo_set_source_rgba(cairo,1,1,1,1); - cairo_rectangle(cairo,xx,yy,colLeftMargin[i+1]-xx,rowHeight); - cairo_fill_preserve(cairo); - cairo_set_source_rgba(cairo,1,.55,0,1); - cairo_set_line_width(cairo,2); - cairo_stroke(cairo); + const PreserveContext cs(cairo); + cairo.setSourceRGBA(1,1,1,1); + cairo.rectangle(xx,yy,colLeftMargin[i+1]-xx,rowHeight); + cairo.fillPreserve(); + cairo.setSourceRGBA(1,.55,0,1); + cairo.setLineWidth(2); + cairo.stroke(); } pango.setMarkup(defang(m_godleyIcon.table.cell(selectedRow,selectedCol))); - cairo_move_to(cairo,xx,yy); + cairo.moveTo(xx,yy); pango.show(); // show insertion cursor - cairo_move_to(cairo,xx+pango.idxToPos(insertIdx),yy); - cairo_rel_line_to(cairo,0,rowHeight); - cairo_set_line_width(cairo,1); - cairo_stroke(cairo); + cairo.moveTo(xx+pango.idxToPos(insertIdx),yy); + cairo.relLineTo(0,rowHeight); + cairo.setLineWidth(1); + cairo.stroke(); if (motionRow>0 && motionCol>0) highlightCell(cairo,motionRow,motionCol); if (selectIdx!=insertIdx) { // indicate some text has been selected - cairo_rectangle(cairo,xx+pango.idxToPos(insertIdx),yy, + cairo.rectangle(xx+pango.idxToPos(insertIdx),yy, pango.idxToPos(selectIdx)-pango.idxToPos(insertIdx),rowHeight); - cairo_set_source_rgba(cairo,0.5,0.5,0.5,0.5); - cairo_fill(cairo); + cairo.setSourceRGBA(0.5,0.5,0.5,0.5); + cairo.fill(); } } } @@ -459,8 +455,8 @@ namespace minsky int GodleyTableEditor::textIdx(double x) const { - const cairo::Surface surf(cairo_recording_surface_create(CAIRO_CONTENT_COLOR,NULL)); - Pango pango(surf.cairo()); + auto pangoPtr=mansoura::measuringContext().cachedRender(TextProperties()); + ICacheRender& pango=*pangoPtr; if (selectedCellInTable() && (selectedRow!=1 || selectedCol!=0)) // No text index needed for a cell that is immutable. For ticket 1064 { // Make sure non-utf8 chars converted to utf8 as far as possible. for ticket 1166. @@ -828,7 +824,7 @@ namespace minsky if (r==0) { - if (colLeftMargin[c+1]-x < pulldownHot) + if (c+1update(); } minsky().canvas.requestRedraw(); - minsky().redrawAllGodleyTables(); } void GodleyTableEditor::checkCell00() @@ -1216,35 +1211,36 @@ namespace { } template - void ButtonWidget::drawButton(cairo_t* cairo, const std::string& label, double r, double g, double b, int idx) + void ButtonWidget::drawButton(const IMansoura& cairo, const std::string& label, double r, double g, double b, int idx) { // stash current point for drawing a box double x0, y0; - cairo_get_current_point(cairo,&x0, &y0); + cairo.getCurrentPoint(x0,y0); - const CairoSave cs(cairo); - Pango pango(cairo); + const PreserveContext cs(cairo); + auto pangoPtr=cairo.cachedRender(TextProperties()); + ICacheRender& pango=*pangoPtr; // increase text size a bit for the buttons pango.setFontSize(0.8*buttonSpacing); pango.setMarkup(label); - cairo_set_source_rgb(cairo,r,g,b); + cairo.setSourceRGB(r,g,b); pango.show(); // draw box around button - cairo_rectangle(cairo, x0, y0+0.2*pango.height(), buttonSpacing, buttonSpacing); + cairo.rectangle(x0, y0+0.2*pango.height(), buttonSpacing, buttonSpacing); if (idx==m_mouseOver) - cairo_set_source_rgb(cairo,0,0,0); // draw in black if mouse over button + cairo.setSourceRGB(0,0,0); // draw in black if mouse over button else - cairo_set_source_rgb(cairo,0.5,0.5,0.5); // draw in grey - cairo_set_line_width(cairo,1); - cairo_stroke(cairo); - cairo_move_to(cairo,x0+buttonSpacing,y0); + cairo.setSourceRGB(0.5,0.5,0.5); // draw in grey + cairo.setLineWidth(1); + cairo.stroke(); + cairo.moveTo(x0+buttonSpacing,y0); } template - void ButtonWidget::draw(cairo_t* cairo) + void ButtonWidget::draw(const IMansoura& cairo) { - const CairoSave cs(cairo); + const PreserveContext cs(cairo); int idx=0; if (rowCol==row || (!cminsky().multipleEquities() && godleyIcon.table.singleEquity())) { // no column widgets on equity column in single equity column mode if (rowCol == row || (rowCol == col && pos!=last)) @@ -1267,21 +1263,7 @@ namespace { } - template - void ButtonWidget::draw(const ICairoShim& cairoShim) - { - auto& shimImpl = dynamic_cast(cairoShim); - draw(shimImpl._internalGetCairoContext()); - } - - void GodleyTableEditor::draw(const ICairoShim& cairoShim) - { - auto& shimImpl = dynamic_cast(cairoShim); - draw(shimImpl._internalGetCairoContext()); - } - template class ButtonWidget; template class ButtonWidget; } -CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::GodleyTableWindow); CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::GodleyTableEditor); diff --git a/model/godleyTableWindow.h b/model/godleyTableEditor.h similarity index 83% rename from model/godleyTableWindow.h rename to model/godleyTableEditor.h index 388dcf960..260db5176 100644 --- a/model/godleyTableWindow.h +++ b/model/godleyTableEditor.h @@ -25,7 +25,8 @@ #define GODLEYTABLEWINDOW_H #include "assetClass.h" #include "godleyTable.h" -#include "ICairoShim.h" +#include "IMansoura.h" +#include "IMansoura.cd" #include "renderNativeWindow.h" #include #include @@ -54,10 +55,9 @@ namespace minsky Pos pos=middle; unsigned idx=0; ///< row or column this widget is located in - void draw(cairo_t*); - void draw(const ICairoShim&); + void draw(const mansoura::IMansoura&); /// draw button \a idx, with label \a label and colour \a r, \a b, \a g - void drawButton(cairo_t*, const std::string& label, + void drawButton(const mansoura::IMansoura&, const std::string& label, double r, double g, double b, int idx); /// invoke action associated with button at x void invoke(double x); @@ -85,6 +85,7 @@ namespace minsky drawButtons=true; leftTableOffset=4*ButtonWidget::buttonSpacing; topTableOffset=30;adjustWidgets(); } + protected: public: static constexpr double columnButtonsOffset=12; /// offset of the table within the window @@ -124,8 +125,7 @@ namespace minsky GodleyTableEditor(GodleyIcon& g): m_godleyIcon(g) {m_enableButtons(); adjustWidgets();} - void draw(cairo_t* cairo); - void draw(const ICairoShim& cairoShim); + void draw(const mansoura::IMansoura& cairoShim); double width() const {return colLeftMargin.empty()? 0: colLeftMargin.back();} double height() const; @@ -168,9 +168,9 @@ namespace minsky // warn user when a stock variable column is going to be swapped with a column from a different asset class on mouse click and drag. For ticket 1072. std::string swapAssetClass(double x, double y); - void highlightColumn(cairo_t* cairo,unsigned col); - void highlightRow(cairo_t* cairo,unsigned row); - void highlightCell(cairo_t* cairo,unsigned row, unsigned col); + void highlightColumn(const mansoura::IMansoura& cairo,unsigned col); + void highlightRow(const mansoura::IMansoura& cairo,unsigned row); + void highlightCell(const mansoura::IMansoura& cairo,unsigned row, unsigned col); // support cut/copy/paste operations void delSelection(); @@ -218,35 +218,7 @@ namespace minsky void handleDelete(); virtual void requestRedrawCanvas() {} // request redraw of canvas if a canvas }; - - class GodleyTableWindow: public RenderNativeWindow, public GodleyTableEditor - { - CLASSDESC_ACCESS(GodleyTableWindow); - protected: - bool redraw(int, int, int width, int height) override { - if (surface.get()) { - draw(surface->cairo()); - return true; - } - return false; - } - public: - using GodleyTableEditor::draw; - GodleyTableWindow(GodleyIcon& g): GodleyTableEditor(g) {} - void requestRedraw() {if (surface.get()) surface->requestRedraw();} - void requestRedrawCanvas() override {requestRedraw();} - - void mouseDown(float x, float y) override {GodleyTableEditor::mouseDown(x,y);} - void mouseUp(float x, float y) override {GodleyTableEditor::mouseUp(x,y);} - void mouseMove(float x, float y) override {GodleyTableEditor::mouseMove(x,y);} - void zoom(double, double, double z) override {GodleyTableEditor::zoomFactor*=z; requestRedraw();} - double zoomFactor() const override {return GodleyTableEditor::zoomFactor;} - bool keyPress(const EventInterface::KeyPressArgs& args) override - {GodleyTableEditor::keyPress(args.keySym,args.utf8); return true;} - bool hasScrollBars() const override {return true;} - }; - } -#include "godleyTableWindow.cd" +#include "godleyTableEditor.cd" #endif diff --git a/model/group.cc b/model/group.cc index 26db812d6..d30f39eb1 100644 --- a/model/group.cc +++ b/model/group.cc @@ -24,15 +24,13 @@ #include "operation.h" #include "autoLayout.h" #include "equations.h" -#include -#include "../engine/cairoShimCairo.h" #include "group.rcd" #include "itemT.rcd" #include "bookmark.rcd" #include "progress.h" #include "minsky_epilogue.h" using namespace std; -using namespace ecolab::cairo; +using namespace mansoura; // size of the top and bottom margins of the group icon static const int topMargin=10; @@ -927,7 +925,7 @@ namespace minsky return ClickType::outside; } - void Group::draw(const ICairoShim& cairoShim) const + void Group::draw(const mansoura::IMansoura& cairoShim) const { auto [angle,flipped]=rotationAsRadians(); @@ -951,10 +949,7 @@ namespace minsky // draw default group icon // display I/O region in grey - // drawIORegion needs cairo_t* for now - auto& shimImpl = dynamic_cast(cairoShim); - cairo_t* cairo = shimImpl._internalGetCairoContext(); - drawIORegion(cairo); + drawIORegion(cairoShim); { cairoShim.save(); @@ -985,30 +980,29 @@ namespace minsky cairoShim.rotate(M_PI); // rotate plot to keep it right way up. } // propagate plot type to underling ecolab::Plot - auto& pt=const_cast(static_cast(displayPlot.get()))->plotType; + auto& pt=const_cast(static_cast(displayPlot.get()))->plotType; switch (displayPlot->plotType) { - case PlotWidget::line: pt=Plot::line; break; - case PlotWidget::bar: pt=Plot::bar; break; + case PlotWidget::line: + case PlotWidget::bar: + pt=displayPlot->plotType; break; default: break; } - // Plot::draw needs cairo_t* - displayPlot->Plot::draw(cairo, width, height); + displayPlot->Plot::draw(cairoShim, width, height); cairoShim.restore(); } else { cairoShim.rectangle(0, 0,width, height); cairoShim.clip(); - // Render SVG using ICairoShim abstraction + // Render SVG using mansoura::IMansoura abstraction cairoShim.renderSVG(svgRenderer, width, height); } } cairoShim.restore(); } - // drawEdgeVariables needs cairo_t* for now - drawEdgeVariables(cairo); + drawEdgeVariables(cairoShim); // display text label @@ -1082,7 +1076,7 @@ namespace minsky } } - void Group::draw1edge(const vector& vars, cairo_t* cairo, + void Group::draw1edge(const vector& vars, const IMansoura& cairoShim, float xEdge) const { layoutEdgeVariables(vars, xEdge, this, rotation()); @@ -1099,14 +1093,11 @@ namespace minsky auto t = v->bb.top() * z, b = v->bb.bottom() * z; if (i > 0) yOff = i % 2 ? top - b : bottom - t; - const cairo::CairoSave cs(cairo); - cairo_translate(cairo,xEdge,yOff); + const PreserveContext cs(cairoShim); + cairoShim.translate(xEdge,yOff); // cairo context is already rotated, so antirotate - cairo_rotate(cairo,-angle); - { - CairoShimCairo shim(cairo); - v->draw(shim); - } + cairoShim.rotate(-angle); + v->draw(cairoShim); if (i == 0) { @@ -1120,13 +1111,13 @@ namespace minsky } } - void Group::drawEdgeVariables(cairo_t* cairo) const + void Group::drawEdgeVariables(const IMansoura& cairoShim) const { float left, right; margins(left,right); - const cairo::CairoSave cs(cairo); + const PreserveContext cs(cairoShim); const float z=zoomFactor(); - draw1edge(inVariables, cairo, -0.5*(iWidth()*z-left)); - draw1edge(outVariables, cairo, 0.5*(iWidth()*z-right)); + draw1edge(inVariables, cairoShim, -0.5*(iWidth()*z-left)); + draw1edge(outVariables, cairoShim, 0.5*(iWidth()*z-right)); } namespace @@ -1149,50 +1140,50 @@ namespace minsky } // draw notches in the I/O region to indicate docking capability - void Group::drawIORegion(cairo_t* cairo) const + void Group::drawIORegion(const IMansoura& cairoShim) const { - const cairo::CairoSave cs(cairo); + const PreserveContext cs(cairoShim); float left, right; margins(left,right); const float z=zoomFactor(); float y=notchY(inVariables), dy=topMargin*edgeScale(); - cairo_set_source_rgba(cairo,0,1,1,0.5); + cairoShim.setSourceRGBA(0,1,1,0.5); const float w=0.5*z*iWidth(), h=0.5*z*iHeight(); - cairo_move_to(cairo,-w,-h); + cairoShim.moveTo(-w,-h); // create notch in input region - cairo_line_to(cairo,-w,y-dy); - cairo_line_to(cairo,left-w-4*z,y-dy); - cairo_line_to(cairo,left-w,y); - cairo_line_to(cairo,left-w-4*z,y+dy); - cairo_line_to(cairo,-w,y+dy); - cairo_line_to(cairo,-w,h); - cairo_line_to(cairo,left-w,h); - cairo_line_to(cairo,left-w,-h); - cairo_close_path(cairo); - cairo_fill(cairo); + cairoShim.lineTo(-w,y-dy); + cairoShim.lineTo(left-w-4*z,y-dy); + cairoShim.lineTo(left-w,y); + cairoShim.lineTo(left-w-4*z,y+dy); + cairoShim.lineTo(-w,y+dy); + cairoShim.lineTo(-w,h); + cairoShim.lineTo(left-w,h); + cairoShim.lineTo(left-w,-h); + cairoShim.closePath(); + cairoShim.fill(); y=notchY(outVariables); - cairo_move_to(cairo,w,-h); + cairoShim.moveTo(w,-h); // create notch in output region - cairo_line_to(cairo,w,y-dy); - cairo_line_to(cairo,w-right-2*z,y-dy); - cairo_line_to(cairo,w-right+2*z,y); - cairo_line_to(cairo,w-right-2*z,y+dy); - cairo_line_to(cairo,w,y+dy); - cairo_line_to(cairo,w,h); - cairo_line_to(cairo,w-right,h); - cairo_line_to(cairo,w-right,-h); - cairo_close_path(cairo); - cairo_fill(cairo); + cairoShim.lineTo(w,y-dy); + cairoShim.lineTo(w-right-2*z,y-dy); + cairoShim.lineTo(w-right+2*z,y); + cairoShim.lineTo(w-right-2*z,y+dy); + cairoShim.lineTo(w,y+dy); + cairoShim.lineTo(w,h); + cairoShim.lineTo(w-right,h); + cairoShim.lineTo(w-right,-h); + cairoShim.closePath(); + cairoShim.fill(); // draw top margin. for feature 88 - cairo_rectangle(cairo,-w,-h,2*w,-topMargin*z); - cairo_fill(cairo); + cairoShim.rectangle(-w,-h,2*w,-topMargin*z); + cairoShim.fill(); // draw bottom margin. for feature 88 - cairo_rectangle(cairo,-w,h,2*w,topMargin*z); - cairo_fill(cairo); + cairoShim.rectangle(-w,h,2*w,topMargin*z); + cairoShim.fill(); } diff --git a/model/group.h b/model/group.h index eb276ec51..57d615d58 100644 --- a/model/group.h +++ b/model/group.h @@ -20,6 +20,7 @@ #ifndef GROUP_H #define GROUP_H #include "SVGItem.h" +#include "SVGItem.cd" #include "callableFunction.h" #include // for assert @@ -30,7 +31,6 @@ #include // for vector #include "arrays.h" // for array #include "bookmark.h" // for Bookmark -#include "cairo.h" // for cairo_t #include "classdesc.h" // for Exclude, NullDescriptor #include "error.h" // for error #include "item.h" // for ItemPtr, Item, ItemPortVector, ItemT, Items @@ -254,7 +254,7 @@ namespace minsky /// make a copy of this, that is not owned by any group GroupPtr copyUnowned() const; Group* clone() const override {throw error("Groups cannot be cloned");} - static SVGRenderer svgRenderer; + static mansoura::SVGRenderer svgRenderer; using GroupItems::addItem; ItemPtr addItem(const std::shared_ptr& it, bool inSchema=false) override @@ -268,16 +268,16 @@ namespace minsky /// Make all variables not present in outerscope local to this group void makeSubroutine(); - void draw(const ICairoShim&) const override; + void draw(const mansoura::IMansoura&) const override; /// draw representations of edge variables around group icon - void drawEdgeVariables(cairo_t*) const; + void drawEdgeVariables(const mansoura::IMansoura&) const; /// draw the variables of one of the edges - void draw1edge(const std::vector& vars, cairo_t* cairo, + void draw1edge(const std::vector& vars, const mansoura::IMansoura& cairoShim, float x) const; /// draw notches in the I/O region to indicate dockability of /// variables there - void drawIORegion(cairo_t*) const; + void drawIORegion(const mansoura::IMansoura&) const; /// position edge I/O variables at their correct rendered locations /// without requiring a Cairo context (used by select() for hit-testing) void positionEdgeVariables() const; diff --git a/model/intOp.cc b/model/intOp.cc index 6d243852e..4067b7db9 100644 --- a/model/intOp.cc +++ b/model/intOp.cc @@ -19,12 +19,13 @@ #include "minsky.h" #include "cairoItems.h" -#include "cairoShimCairo.h" #include "intOp.h" #include "intOp.rcd" #include "itemT.rcd" #include "minsky_epilogue.h" +using namespace mansoura; + namespace minsky { Units IntOp::units(bool check) const { @@ -35,7 +36,7 @@ namespace minsky return r; } - void IntOp::draw(const ICairoShim& cairoShim) const + void IntOp::draw(const mansoura::IMansoura& cairoShim) const { // if rotation is in 1st or 3rd quadrant, rotate as // normal, otherwise flip the text so it reads L->R @@ -125,8 +126,7 @@ namespace minsky cairoShim.closePath(); } - auto cairo=dynamic_cast(cairoShim)._internalGetCairoContext(); - cairo::Path clipPath(cairo); + auto clipPath=cairoShim.copyPath(); double x0=r, y0=0, x1=l, y1=numPorts() > 2? -h+3: 0, x2=l, y2=numPorts() > 2? h-3: 0; @@ -162,7 +162,7 @@ namespace minsky if (onResizeHandles) drawResizeHandles(cairoShim); cairoShim.newPath(); - clipPath.appendToCurrent(cairo); + clipPath->appendToCurrent(cairoShim); cairoShim.clip(); if (selected) drawSelected(cairoShim); } diff --git a/model/intOp.h b/model/intOp.h index 0d256397c..09e186df6 100644 --- a/model/intOp.h +++ b/model/intOp.h @@ -63,7 +63,7 @@ namespace minsky std::string valueId() const {return intVar->valueId();} - void draw(const ICairoShim&) const override; + void draw(const mansoura::IMansoura&) const override; void resize(const LassoBox& b) override; /// return reference to integration variable diff --git a/model/item.cc b/model/item.cc index 7e78feb24..5a8ab19fe 100644 --- a/model/item.cc +++ b/model/item.cc @@ -20,7 +20,7 @@ #include "cairoItems.h" #include "minsky.h" #include "item.h" -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "group.h" #include "zoom.h" #include "variable.h" @@ -28,8 +28,7 @@ #include "geometry.h" #include "selection.h" #include "lasso.h" -#include -#include +#include #include "item.rcd" #include "noteBase.rcd" #include "noteBase.xcd" @@ -37,8 +36,7 @@ #include "minsky_epilogue.h" #include -using ecolab::Pango; -using ecolab::cairo::CairoSave; +using namespace mansoura; using namespace std; namespace minsky @@ -46,8 +44,6 @@ namespace minsky void BoundingBox::update(const Item& x) { - const ecolab::cairo::Surface surf - (cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,NULL)); auto savedMouseFocus=x.mouseFocus; x.mouseFocus=false; // do not mark up icon with tooltips etc, which might invalidate this calc x.onResizeHandles=false; @@ -57,27 +53,27 @@ namespace minsky stashedZf=parent->relZoom; parent->relZoom/=x.zoomFactor(); // undo any zooming coming from owning group } - try - { - const cairo::CairoSave cs(surf.cairo()); - cairo_rotate(surf.cairo(),-x.rotation()*M_PI/180); - CairoShimCairo shim(surf.cairo()); - x.draw(shim); - } + const auto ink=inkExtents([&](const IMansoura& shim) + { + try + { + const PreserveContext cs(shim); + shim.rotate(-x.rotation()*M_PI/180); + x.draw(shim); + } #ifndef NDEBUG - catch (const std::exception& e) - {cerr<<"illegal exception caught in draw(): "<relZoom=stashedZf; - double l,t,w,h; - cairo_recording_surface_ink_extents(surf.surface(), - &l,&t,&w,&h); + const double l=ink.left, t=ink.top, w=ink.width, h=ink.height; // note (0,0) is relative to the (x,y) of icon. m_left=l; m_right=(l+w); @@ -293,7 +289,7 @@ namespace minsky return ClickType::outside; } - void Item::drawPorts(const ICairoShim& cairoShim) const + void Item::drawPorts(const mansoura::IMansoura& cairoShim) const { cairoShim.save(); cairoShim.newPath(); @@ -308,7 +304,7 @@ namespace minsky cairoShim.restore(); } - void Item::drawSelected(const ICairoShim& cairoShim) + void Item::drawSelected(const mansoura::IMansoura& cairoShim) { // implemented by filling the clip region with a transparent grey cairoShim.save(); @@ -317,7 +313,7 @@ namespace minsky cairoShim.restore(); } - void Item::drawResizeHandle(const ICairoShim& cairoShim, double x, double y, double sf, double angle) + void Item::drawResizeHandle(const mansoura::IMansoura& cairoShim, double x, double y, double sf, double angle) { cairoShim.save(); cairoShim.translate(x,y); @@ -345,7 +341,7 @@ namespace minsky scaleFactor(std::max(1.0f,std::min(iWidth()/w,iHeight()/h))); } - void Item::drawResizeHandles(const ICairoShim& cairoShim) const + void Item::drawResizeHandles(const mansoura::IMansoura& cairoShim) const { auto sf=resizeHandleSize(); double angle=0.5*M_PI; @@ -357,14 +353,14 @@ namespace minsky cairoShim.stroke(); } - void BottomRightResizerItem::drawResizeHandles(const ICairoShim& cairoShim) const + void BottomRightResizerItem::drawResizeHandles(const mansoura::IMansoura& cairoShim) const { const Point p=resizeHandleCoords(); drawResizeHandle(cairoShim,p.x()-x(),p.y()-y(),resizeHandleSize(),0); cairoShim.stroke(); } - void Item::draw(const ICairoShim& cairoShim) const + void Item::draw(const mansoura::IMansoura& cairoShim) const { auto [angle,flipped]=rotationAsRadians(); const Rotate r(rotation()+(flipped? 180:0),0,0); @@ -395,12 +391,10 @@ namespace minsky void Item::dummyDraw() const { - const ecolab::cairo::Surface s(cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,NULL)); - CairoShimCairo shim(s.cairo()); - draw(shim); + inkExtents([this](const IMansoura& shim) {draw(shim);}); } - void Item::displayTooltip(const ICairoShim& cairoShim, const std::string& tooltip) const + void Item::displayTooltip(const mansoura::IMansoura& cairoShim, const std::string& tooltip) const { const string unitstr=units().latexStr(); if (!tooltip.empty() || !unitstr.empty()) diff --git a/model/item.h b/model/item.h index ea8f07d4b..f8abb65d8 100644 --- a/model/item.h +++ b/model/item.h @@ -26,7 +26,8 @@ #include "geometry.h" #include "str.h" #include "polyRESTProcessBase.h" -#include "ICairoShim.h" +#include "IMansoura.h" +#include "IMansoura.cd" #include @@ -161,7 +162,7 @@ namespace minsky } } memoisedRotator; - static void drawResizeHandle(const ICairoShim& cairoShim, double x, double y, double sf, double angle); + static void drawResizeHandle(const mansoura::IMansoura& cairoShim, double x, double y, double sf, double angle); public: @@ -287,7 +288,7 @@ namespace minsky void moveTo(float x, float y); /// draw this item into a cairo context - virtual void draw(const ICairoShim& cairoShim) const; + virtual void draw(const mansoura::IMansoura& cairoShim) const; /// resize this item on the canvas virtual void resize(const LassoBox& b); /// factor by which item has been resized @@ -299,7 +300,7 @@ namespace minsky void dummyDraw() const; /// display tooltip text, eg on mouseover - virtual void displayTooltip(const ICairoShim&, const std::string&) const; + virtual void displayTooltip(const mansoura::IMansoura&, const std::string&) const; /// update display after a step() virtual void updateIcon(double t) {} @@ -308,9 +309,9 @@ namespace minsky Item& operator=(const Item&)=default; virtual ~Item() {} - void drawPorts(const ICairoShim& cairoShim) const; - static void drawSelected(const ICairoShim& cairoShim); - virtual void drawResizeHandles(const ICairoShim& cairoShim) const; + void drawPorts(const mansoura::IMansoura& cairoShim) const; + static void drawSelected(const mansoura::IMansoura& cairoShim); + virtual void drawResizeHandles(const mansoura::IMansoura& cairoShim) const; /// returns the clicktype given a mouse click at \a x, \a y. virtual ClickType::Type clickType(float x, float y) const; @@ -361,7 +362,7 @@ namespace minsky struct BottomRightResizerItem: public Item { bool onResizeHandle(float x, float y) const override; - void drawResizeHandles(const ICairoShim& cairoShim) const override; + void drawResizeHandles(const mansoura::IMansoura& cairoShim) const override; /// returns coordinates of the resizer handle virtual Point resizeHandleCoords() const; }; diff --git a/model/lock.cc b/model/lock.cc index 72542db69..f6293b133 100644 --- a/model/lock.cc +++ b/model/lock.cc @@ -27,14 +27,15 @@ #include "lock.rcd" #include "lock.xcd" #include "minsky.h" -#include "cairoShimCairo.h" +#include "mansouraCairo.h" #include "minsky_epilogue.h" using namespace std; +using namespace mansoura; namespace minsky { - SVGRenderer Lock::lockedIcon; - SVGRenderer Lock::unlockedIcon; + mansoura::SVGRenderer Lock::lockedIcon; + mansoura::SVGRenderer Lock::unlockedIcon; Lock::Lock() { @@ -79,7 +80,7 @@ namespace minsky throw_error("Locks can only be applied to Ravels"); } - void Lock::draw(const ICairoShim& cairoShim) const + void Lock::draw(const IMansoura& cairoShim) const { const float z=zoomFactor()*scaleFactor(); const float w=iWidth()*z, h=iHeight()*z; diff --git a/model/lock.h b/model/lock.h index fc415c19c..30ffb80ec 100644 --- a/model/lock.h +++ b/model/lock.h @@ -24,6 +24,7 @@ #include "ravelState.h" #include "ravelWrap.h" #include "SVGItem.h" +#include "SVGItem.cd" namespace minsky { @@ -39,9 +40,9 @@ namespace minsky bool locked() const {return !lockedState.empty();} void toggleLocked(); - static SVGRenderer lockedIcon; - static SVGRenderer unlockedIcon; - void draw(const ICairoShim& cairoShim) const override; + static mansoura::SVGRenderer lockedIcon; + static mansoura::SVGRenderer unlockedIcon; + void draw(const mansoura::IMansoura& cairoShim) const override; Units units(bool) const override; /// Ravel this is connected to. nullptr if not connected to a Ravel Ravel* ravelInput() const; diff --git a/model/minsky.cc b/model/minsky.cc index 7709d20c6..8249fedb4 100644 --- a/model/minsky.cc +++ b/model/minsky.cc @@ -18,6 +18,7 @@ */ #include "minsky.h" #include "cairoItems.h" +#include #include "classdesc_access.h" #include "flowCoef.h" #include "userFunction.h" @@ -25,6 +26,7 @@ #include "variableInstanceList.h" #include +#include "ecolab/include/pango.h" #include "schema3.h" @@ -54,6 +56,8 @@ #include "pannableTab.rcd" #include "pannableTab.xcd" #include "polyRESTProcessBase.h" +#include "SVGItem.rcd" +#include "SVGItem.xcd" #include "xvector.rcd" #include "minsky_epilogue.h" @@ -99,7 +103,6 @@ namespace minsky bool Minsky::multipleEquities(const bool& m) { m_multipleEquities=m; canvas.requestRedraw(); - redrawAllGodleyTables(); return m_multipleEquities; } @@ -1732,16 +1735,6 @@ namespace minsky } - void Minsky::redrawAllGodleyTables() - { - model->recursiveDo(&Group::items, - [&](Items&,Items::iterator i) { - if (auto g=dynamic_cast(i->get())) - g->popup.requestRedraw(); - return false; - }); - } - vector Minsky::allGodleyTables() const { vector r; @@ -1783,15 +1776,20 @@ namespace minsky { _defaultFont.reset(new char[x.length()+1]); strncpy(_defaultFont.get(),x.c_str(),x.length()+1); + mansoura::Pango::defaultFamily=_defaultFont.get(); + // TODO: remove once ecolab::Pango has been eradicated ecolab::Pango::defaultFamily=_defaultFont.get(); return x; } double Minsky::fontScale() - {return ecolab::Pango::scaleFactor;} + {return mansoura::Pango::scaleFactor;} double Minsky::fontScale(double s) - {return ecolab::Pango::scaleFactor=s;} + { + ecolab::Pango::scaleFactor=s; + return mansoura::Pango::scaleFactor=s; + } void Minsky::latex(const string& filename, bool wrapLaTeXLines) { @@ -1858,3 +1856,4 @@ CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(classdesc::Signature); CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(classdesc::PolyRESTProcessBase); CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::CallableFunction); CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(ravelCAPI::Database); +CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(mansoura::SVGRenderer); diff --git a/model/minsky.h b/model/minsky.h index 8f86c0bea..72a89838d 100644 --- a/model/minsky.h +++ b/model/minsky.h @@ -20,6 +20,7 @@ #ifndef MINSKY_H #define MINSKY_H +#include #include "stringKeyMap.h" #include "intrusiveMap.h" #include "bookmark.h" @@ -218,7 +219,7 @@ namespace minsky } void setRavelIconResource(const string& s) {Ravel::svgRenderer.setResource(s);} - SVGRenderer histogramResource; + mansoura::SVGRenderer histogramResource; /// @return available matching columns from other Godley tables /// @param currTable - this table, not included in the matching process @@ -427,9 +428,6 @@ namespace minsky /// import a Vensim file void importVensim(const std::string&); - /// request all Godley table windows to redraw - void redrawAllGodleyTables(); - /// returns list of ids of all Godley tables in the current top level canvas std::vector allGodleyTables() const; diff --git a/model/minskyCairoRenderer.h b/model/minskyCairoRenderer.h deleted file mode 100644 index 493e8fc62..000000000 --- a/model/minskyCairoRenderer.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - @copyright Steve Keen 2023 - @author Russell Standish - This file is part of Minsky. - - Minsky is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Minsky is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Minsky. If not, see . -*/ - -#ifndef MINSKYCAIRORENDERER_H -#define MINSKYCAIRORENDERER_H -#include "cairoRenderer.h" -#include "pango.h" - -namespace minsky -{ - struct CairoRenderer: public ravel::CairoRenderer - { - ecolab::Pango m_pango; - - static ecolab::Pango& pango(CAPIRenderer* r) {return static_cast(r)->m_pango;} - - static void s_showText(CAPIRenderer* c, const char* s) - { - double x,y; - cairo_get_current_point(cairo(c),&x,&y); - pango(c).setText(s); - // paint a partially obscure white rectange to make the text pop - cairo_save(cairo(c)); - cairo_rectangle(cairo(c),x,y,pango(c).width(),pango(c).height()); - cairo_set_source_rgba(cairo(c),1,1,1,0.3); - cairo_fill(cairo(c)); - cairo_restore(cairo(c)); - cairo_move_to(cairo(c),x,y); - pango(c).show(); - } - static void s_setTextExtents(CAPIRenderer* c, const char* s) - {pango(c).setText(s);} - static double s_textWidth(CAPIRenderer* c) {return pango(c).width();} - static double s_textHeight(CAPIRenderer* c) {return pango(c).height();} - - CairoRenderer(cairo_t* cairo): ravel::CairoRenderer(cairo), m_pango(cairo) { - showText=s_showText; - setTextExtents=s_setTextExtents; - textWidth=s_textWidth; - textHeight=s_textHeight; - } - - }; -} - -#endif diff --git a/model/operation.cc b/model/operation.cc index 527556ba0..98339c898 100644 --- a/model/operation.cc +++ b/model/operation.cc @@ -25,9 +25,7 @@ #include "str.h" #include "cairoItems.h" -#include #include -#include "../engine/cairoShimCairo.h" #include "minsky_epilogue.h" #include @@ -38,7 +36,7 @@ #endif using namespace ecolab; -using ecolab::cairo::CairoSave; +using namespace mansoura; namespace minsky { @@ -149,7 +147,7 @@ namespace minsky return std::max(1.0f,std::min(0.5f*iWidth()*z/std::max(l,r),0.5f*iHeight()*z/h)); } - void OperationBase::drawUserFunction(const ICairoShim& cairoShim) const + void OperationBase::drawUserFunction(const IMansoura& cairoShim) const { // if rotation is in 1st or 3rd quadrant, rotate as // normal, otherwise flip the text so it reads L->R @@ -237,15 +235,7 @@ namespace minsky if (selected) drawSelected(cairoShim); } - void OperationBase::setCachedText(cairo_t* cairo, const std::string& text, double size) const - { - if (cachedPango && cairo==cachedPango->cairoContext()) return; - cachedPango=make_shared(cairo); - cachedPango->setMarkup(text); - cachedPango->setFontSize(size); - } - - void OperationBase::draw(const ICairoShim& cairoShim) const + void OperationBase::draw(const IMansoura& cairoShim) const { // if rotation is in 1st or 3rd quadrant, rotate as // normal, otherwise flip the text so it reads L->R @@ -282,8 +272,7 @@ namespace minsky cairoShim.setSourceRGB(0,0,1); cairoShim.strokePreserve(); - auto& shimImpl = dynamic_cast(cairoShim); - cairo::Path clipPath(shimImpl._internalGetCairoContext()); + auto clipPath=cairoShim.copyPath(); // compute port coordinates relative to the icon's // point of reference. Move outport 2 pixels right for ticket For ticket 362. @@ -334,7 +323,7 @@ namespace minsky } cairoShim.newPath(); - clipPath.appendToCurrent(shimImpl._internalGetCairoContext()); + clipPath->appendToCurrent(cairoShim); cairoShim.clip(); if (selected) drawSelected(cairoShim); } @@ -621,19 +610,19 @@ namespace minsky // operations.cc because it is more related to the functionality in // this file. - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { assert(false); //shouldn't be here } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { assert(false); //shouldn't be here } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.translate(-1,0); @@ -650,7 +639,7 @@ namespace minsky } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -659,7 +648,7 @@ namespace minsky } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -667,7 +656,7 @@ namespace minsky cairoShim.showText("e"); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -675,7 +664,7 @@ namespace minsky cairoShim.showText("π"); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -683,7 +672,7 @@ namespace minsky cairoShim.showText("0"); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -691,7 +680,7 @@ namespace minsky cairoShim.showText("1"); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-4,-8); @@ -700,7 +689,7 @@ namespace minsky } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-4,-8); @@ -708,7 +697,7 @@ namespace minsky cairoShim.showText("%",9); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-4,-10); @@ -716,10 +705,10 @@ namespace minsky cairoShim.showText("→",10); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const {/* moved to IntOp::draw() but needs to be here, and is actually called */} - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { cairoShim.save(); const double sf = scaleFactor(); @@ -733,7 +722,7 @@ namespace minsky cairoShim.restore(); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { cairoShim.save(); const double sf = scaleFactor(); @@ -743,7 +732,7 @@ namespace minsky cairoShim.restore(); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -753,7 +742,7 @@ namespace minsky } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -770,7 +759,7 @@ namespace minsky #endif } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -781,7 +770,7 @@ namespace minsky d.drawPort([&](){d.drawSymbol("y");}, l, h, rotation()); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -792,7 +781,7 @@ namespace minsky d.drawPort([&](){d.drawSymbol("y");}, l, h, rotation()); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -803,7 +792,7 @@ namespace minsky d.drawPort([&](){d.drawSymbol("y");}, l, h, rotation()); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -811,7 +800,7 @@ namespace minsky cairoShim.showText("min",9); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -819,7 +808,7 @@ namespace minsky cairoShim.showText("max",9); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { cairoShim.save(); const double sf = scaleFactor(); @@ -832,7 +821,7 @@ namespace minsky cairoShim.restore(); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { cairoShim.save(); const double sf = scaleFactor(); @@ -845,14 +834,14 @@ namespace minsky cairoShim.restore(); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); cairoShim.moveTo(-6,-10); cairoShim.showText("¬"); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf*.7,sf); @@ -860,7 +849,7 @@ namespace minsky cairoShim.showPlainText("<ΔxΔy>",5); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -868,7 +857,7 @@ namespace minsky cairoShim.showText("ρ"); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -883,7 +872,7 @@ namespace minsky cairoShim.stroke(); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -907,7 +896,7 @@ namespace minsky cairoShim.lineTo(6,7.5); cairoShim.stroke(); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -915,7 +904,7 @@ namespace minsky cairoShim.showText(" ln"); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -926,7 +915,7 @@ namespace minsky d.drawPort([&](){d.drawSymbol("b");}, l, h, rotation()); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -934,7 +923,7 @@ namespace minsky cairoShim.showText("sin",9); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -942,7 +931,7 @@ namespace minsky cairoShim.showText("cos",9); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -950,7 +939,7 @@ namespace minsky cairoShim.showText("tan",9); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -958,7 +947,7 @@ namespace minsky cairoShim.showText("sin⁻¹",7); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -966,7 +955,7 @@ namespace minsky cairoShim.showText("cos⁻¹",7); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -974,7 +963,7 @@ namespace minsky cairoShim.showText("tan⁻¹",7); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -982,7 +971,7 @@ namespace minsky cairoShim.showText("sinh",8); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -990,7 +979,7 @@ namespace minsky cairoShim.showText("cosh",8); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -998,7 +987,7 @@ namespace minsky cairoShim.showText("tanh",8); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1006,7 +995,7 @@ namespace minsky cairoShim.showText("|x|",9); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-5,-5); @@ -1023,7 +1012,7 @@ namespace minsky cairoShim.stroke(); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1031,7 +1020,7 @@ namespace minsky cairoShim.showText("frac",8); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1039,7 +1028,7 @@ namespace minsky cairoShim.showText("Γ"); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1054,7 +1043,7 @@ namespace minsky d.drawPort([&](){d.drawSymbol("n");}, l, h, rotation()); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1062,7 +1051,7 @@ namespace minsky cairoShim.showText("x!"); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1073,7 +1062,7 @@ namespace minsky } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1084,7 +1073,7 @@ namespace minsky } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1095,7 +1084,7 @@ namespace minsky } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1105,7 +1094,7 @@ namespace minsky d.drawPort([&](){d.drawDivide();}, l, h, rotation()); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-4,-7); @@ -1113,7 +1102,7 @@ namespace minsky cairoShim.showText("∑",7); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-4,-7); @@ -1121,7 +1110,7 @@ namespace minsky cairoShim.showText("∏",7); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1129,7 +1118,7 @@ namespace minsky cairoShim.showText("inf",9); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1137,7 +1126,7 @@ namespace minsky cairoShim.showText("sup",9); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1145,7 +1134,7 @@ namespace minsky cairoShim.showText("infi",9); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1153,7 +1142,7 @@ namespace minsky cairoShim.showText("supi",9); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1161,7 +1150,7 @@ namespace minsky cairoShim.showText("any",10); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1169,7 +1158,7 @@ namespace minsky cairoShim.showText("all",10); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1177,7 +1166,7 @@ namespace minsky cairoShim.showText("nᵢ",10); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1185,7 +1174,7 @@ namespace minsky cairoShim.showText("{nᵢ}",10); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1193,7 +1182,7 @@ namespace minsky cairoShim.showPlainText("",10); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1203,7 +1192,7 @@ namespace minsky cairoShim.showText("~",10); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1211,7 +1200,7 @@ namespace minsky cairoShim.showText("σ",10); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf*.85,sf); @@ -1219,13 +1208,13 @@ namespace minsky cairoShim.showPlainText("<Δxᵏ>",7); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { cairoShim.translate(-0.5*iWidth(),-0.5*iHeight()); cairoShim.renderSVG(cminsky().histogramResource, iWidth(), iHeight()); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-7,-7); @@ -1233,7 +1222,7 @@ namespace minsky cairoShim.showText("∑+",7); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-7,-7); @@ -1241,7 +1230,7 @@ namespace minsky cairoShim.showText("av+",7); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-6,-7); @@ -1249,7 +1238,7 @@ namespace minsky cairoShim.showText("∏×",7); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-4,-7); @@ -1257,7 +1246,7 @@ namespace minsky cairoShim.showText("Δ⁻",7); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-4,-7); @@ -1265,7 +1254,7 @@ namespace minsky cairoShim.showText("Δ⁺",7); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-4,-10); @@ -1273,7 +1262,7 @@ namespace minsky cairoShim.showText("·",14); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1288,7 +1277,7 @@ namespace minsky cairoShim.stroke(); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1296,7 +1285,7 @@ namespace minsky cairoShim.showText("idx",10); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.scale(sf,sf); @@ -1307,7 +1296,7 @@ namespace minsky drawBinOp.drawPort([&](){drawBinOp.drawSymbol("i");},l,h,rotation()); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-4,-5); @@ -1321,7 +1310,7 @@ namespace minsky cairoShim.stroke(); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-4,-3); @@ -1334,7 +1323,7 @@ namespace minsky cairoShim.stroke(); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const { const double sf = scaleFactor(); cairoShim.moveTo(-10,-10); @@ -1347,7 +1336,7 @@ namespace minsky cairoShim.stroke(); } - template <> void Operation::iconDraw(const ICairoShim& cairoShim) const + template <> void Operation::iconDraw(const IMansoura& cairoShim) const {/* needs to be here, and is actually called */} diff --git a/model/operation.h b/model/operation.h index ee530dfb6..099319ee8 100644 --- a/model/operation.h +++ b/model/operation.h @@ -46,7 +46,7 @@ namespace minsky public: typedef OperationType::Type Type; Type type() const override {return T;} - void iconDraw(const ICairoShim&) const override; + void iconDraw(const mansoura::IMansoura&) const override; std::size_t numPorts() const override {return OperationTypeInfo::numArguments()+1;} Operation() { @@ -108,12 +108,12 @@ namespace minsky }; - /// helper class to draw port label symbols using ICairoShim + /// helper class to draw port label symbols using mansoura::IMansoura struct DrawBinOpShim { - const ICairoShim& cairoShim; + const mansoura::IMansoura& cairoShim; double zoomFactor; - DrawBinOpShim(const ICairoShim& cairoShim, double z=1): cairoShim(cairoShim), zoomFactor(z) {} + DrawBinOpShim(const mansoura::IMansoura& cairoShim, double z=1): cairoShim(cairoShim), zoomFactor(z) {} void drawPlus() const { diff --git a/model/operationBase.h b/model/operationBase.h index a380693d7..67fc47235 100644 --- a/model/operationBase.h +++ b/model/operationBase.h @@ -34,8 +34,6 @@ #include #include "operationType.h" -namespace ecolab {class Pango;} - namespace minsky { class OperationPtr; @@ -46,9 +44,8 @@ namespace minsky { CLASSDESC_ACCESS(OperationBase); protected: - mutable classdesc::Exclude> cachedPango; + mutable classdesc::Exclude> cachedPango; /// check if cachedPango is up to date, and if not recreate - void setCachedText(cairo_t*, const std::string&, double) const; public: static constexpr float l=-8, h=12, r=12; typedef OperationType::Type Type; @@ -62,7 +59,7 @@ namespace minsky OperationBase* operationCast() override {return this;} /// visual representation of operation on the canvas - virtual void iconDraw(const ICairoShim&) const=0; + virtual void iconDraw(const mansoura::IMansoura&) const=0; /// returns a list of values the ports currently have std::string portValues() const; @@ -73,9 +70,9 @@ namespace minsky // manage the port structures associated with this operation virtual void addPorts(); - void drawUserFunction(const ICairoShim& cairoShim) const; + void drawUserFunction(const mansoura::IMansoura& cairoShim) const; - void draw(const ICairoShim&) const override; + void draw(const mansoura::IMansoura&) const override; void resize(const LassoBox& b) override; float scaleFactor() const override; diff --git a/model/operationRS.cc b/model/operationRS.cc index 5cadb3221..6fe8880b9 100644 --- a/model/operationRS.cc +++ b/model/operationRS.cc @@ -23,6 +23,7 @@ #include "item.rcd" #include "operationBase.rcd" #include "operationType.rcd" +#include "IMansoura.cd" #include "minsky_epilogue.h" CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::OperationBase); diff --git a/model/operationRS1.cc b/model/operationRS1.cc index ac9894ddb..a9fc7650b 100644 --- a/model/operationRS1.cc +++ b/model/operationRS1.cc @@ -24,6 +24,7 @@ #include "itemT.rcd" #include "operationType.rcd" #include "operation.rcd" +#include "IMansoura.cd" #include "minsky_epilogue.h" template diff --git a/model/operationRS2.cc b/model/operationRS2.cc index 6d96066da..e24f07921 100644 --- a/model/operationRS2.cc +++ b/model/operationRS2.cc @@ -24,6 +24,7 @@ #include "itemT.rcd" #include "operation.rcd" #include "operationType.rcd" +#include "IMansoura.cd" #include "minsky_epilogue.h" template diff --git a/model/phillipsDiagram.cc b/model/phillipsDiagram.cc index 565ca0ab2..94915e459 100644 --- a/model/phillipsDiagram.cc +++ b/model/phillipsDiagram.cc @@ -22,9 +22,10 @@ #include "phillipsDiagram.rcd" #include "phillipsDiagram.xcd" #include "minsky.h" -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "minsky_epilogue.h" -using ecolab::cairo::CairoSave; + +using namespace mansoura; namespace minsky { @@ -50,7 +51,7 @@ namespace minsky // Wire::draw(cairo,value>=0); // } - void PhillipsFlow::draw(const ICairoShim& cairoShim, bool) const + void PhillipsFlow::draw(const mansoura::IMansoura& cairoShim, bool) const { cairoShim.save(); const double value=this->value(); @@ -70,7 +71,7 @@ namespace minsky cairoShim.restore(); } - void PhillipsStock::draw(const ICairoShim& cairoShim) const + void PhillipsStock::draw(const mansoura::IMansoura& cairoShim) const { // Call parent draw (VariableBase still uses _internalGetCairoContext internally) StockVar::draw(cairoShim); @@ -100,23 +101,19 @@ namespace minsky } - bool PhillipsDiagram::redraw(int, int, int width, int height) + bool PhillipsDiagram::redraw(const IMansoura& shim, int, int, int width, int height) { - if (!surface.get()) return false; - auto cairo=surface->cairo(); - const CairoSave cs(cairo); - cairo_translate(cairo,x,y); + const PreserveContext cs(shim); + shim.translate(x,y); for (auto& i: stocks) { - const CairoSave cs(cairo); - cairo_identity_matrix(cairo); - cairo_translate(cairo,i.second.x()+x, i.second.y()+y); - CairoShimCairo shim(cairo); + const PreserveContext cs(shim); + shim.identityMatrix(); + shim.translate(i.second.x()+x, i.second.y()+y); i.second.draw(shim); } for (auto& i: flows) { - CairoShimCairo shim(cairo); i.second.draw(shim,true); } return true; diff --git a/model/phillipsDiagram.h b/model/phillipsDiagram.h index 4c3ceba8d..940990bd7 100644 --- a/model/phillipsDiagram.h +++ b/model/phillipsDiagram.h @@ -54,7 +54,7 @@ namespace minsky return r; } //void draw(cairo_t*); - void draw(const ICairoShim&, bool) const override; + void draw(const mansoura::IMansoura&, bool) const override; }; @@ -70,23 +70,23 @@ namespace minsky } static std::map maxStock; std::size_t numPorts() const override {return 2;} - void draw(const ICairoShim& cairoShim) const override; + void draw(const mansoura::IMansoura& cairoShim) const override; }; class PhillipsDiagram: public RenderNativeWindow { - bool redraw(int, int, int width, int height) override; + bool redraw(const mansoura::IMansoura&, int, int, int width, int height) override; CLASSDESC_ACCESS(PhillipsDiagram); PhillipsStock* stockBeingMoved=nullptr; // weak reference PhillipsStock* stockBeingRotated=nullptr; // weak reference - Exclude rotateOrigin; + classdesc::Exclude rotateOrigin; PhillipsFlow* flowBeingEdited=nullptr; // weak reference int handleSelected=0; float x=0,y=0; ///< position for panning public: std::map stocks; std::map, PhillipsFlow> flows; - void requestRedraw() {if (surface.get()) surface->requestRedraw();} + void requestRedraw() {RenderNativeWindow::requestRedraw();} /// populate phillips diagram from Godley tables in model void init() override; void clear() { diff --git a/model/plotWidget.cc b/model/plotWidget.cc index d52b3a814..b77e8ae42 100644 --- a/model/plotWidget.cc +++ b/model/plotWidget.cc @@ -21,18 +21,14 @@ #include "variable.h" #include "cairoItems.h" #include "latexMarkup.h" -#include "pango.h" #include -#include -#include -#include -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "CSVTools.xcd" #include "itemT.rcd" #include "plotOptions.rcd" -#include "plot.rcd" -#include "plot.xcd" +#include "mansouraPlot.rcd" +#include "mansouraPlot.xcd" #include "tensorInterface.rcd" #include "tensorInterface.xcd" #include "tensorVal.rcd" @@ -42,8 +38,7 @@ #include #include -using namespace ecolab::cairo; -using namespace ecolab; +using namespace mansoura; using namespace std; using namespace boost; using namespace boost::posix_time; @@ -89,39 +84,38 @@ namespace minsky m_ports.emplace_back(make_shared(*this)); } - void PlotWidget::draw(cairo_t* cairo) const + void PlotWidget::draw(const mansoura::IMansoura& cairoShim) const { - CairoSave cs(cairo); const double z=Item::zoomFactor(); - cairo_scale(cairo,z,z); const double w=iWidth(); double h=iHeight(); + { + const PreserveContext cs(cairoShim); + cairoShim.scale(z,z); // if any titling, draw an extra bounding box (ticket #285) if (!title.empty()||!xlabel().empty()||!ylabel().empty()||!y1label().empty()) { - cairo_rectangle(cairo,-0.5*w+10,-0.5*h,w-20,h-10); - cairo_set_line_width(cairo,1); - cairo_stroke(cairo); + cairoShim.rectangle(-0.5*w+10,-0.5*h,w-20,h-10); + cairoShim.setLineWidth(1); + cairoShim.stroke(); } - cairo_translate(cairo,-0.5*w,-0.5*h); + cairoShim.translate(-0.5*w,-0.5*h); yoffs=0; if (!title.empty()) { - const CairoSave cs(cairo); + const PreserveContext cs(cairoShim); const double fy=titleHeight*iHeight(); - Pango pango(cairo); - pango.setFontSize(fabs(fy)); - pango.setMarkup(latexToPango(title)); - cairo_set_source_rgb(cairo,0,0,0); - cairo_move_to(cairo,0.5*(w-pango.width()), 0); - pango.show(); + auto pango=cairoShim.cachedRender(TextProperties(latexToPango(title),fabs(fy))); + cairoShim.setSourceRGB(0,0,0); + cairoShim.moveTo(0.5*(w-pango->extents().width), 0); + pango->show(); // allow some room for the title - yoffs=pango.height(); + yoffs=pango->extents().height; h-=yoffs; } @@ -134,7 +128,7 @@ namespace minsky const float x=boundX[i]*w, y=boundY[i]*h; if (!justDataChanged) m_ports[i]->moveTo(x*z + this->x(), y*z + this->y()+0.5*yoffs); - drawTriangle(cairo, x+0.5*w, y+0.5*h+yoffs, palette[(i/2)%palette.size()].colour, orient[i]); + drawTriangle(cairoShim, x+0.5*w, y+0.5*h+yoffs, palette[(i/2)%palette.size()].colour, orient[i]); } @@ -146,7 +140,7 @@ namespace minsky const float y=0.5*(dy-h) + (i-nBoundsPorts)*dy; if (!justDataChanged) m_ports[i]->moveTo(xLeft*z + this->x(), y*z + this->y()+0.5*yoffs); - drawTriangle(cairo, xLeft+0.5*w, y+0.5*h+yoffs, palette[(i-nBoundsPorts)%palette.size()].colour, 0); + drawTriangle(cairoShim, xLeft+0.5*w, y+0.5*h+yoffs, palette[(i-nBoundsPorts)%palette.size()].colour, 0); } // draw RHS y data ports @@ -155,7 +149,7 @@ namespace minsky const float y=0.5*(dy-h) + (i-m_numLines-nBoundsPorts)*dy, x=0.5*w; if (!justDataChanged) m_ports[i]->moveTo(x*z + this->x(), y*z + this->y()+0.5*yoffs); - drawTriangle(cairo, x+0.5*w, y+0.5*h+yoffs, palette[(i-nBoundsPorts)%palette.size()].colour, M_PI); + drawTriangle(cairoShim, x+0.5*w, y+0.5*h+yoffs, palette[(i-nBoundsPorts)%palette.size()].colour, M_PI); } // draw x data ports @@ -165,41 +159,40 @@ namespace minsky const float x=dx-0.5*w + (i-2*m_numLines-nBoundsPorts)*dx; if (!justDataChanged) m_ports[i]->moveTo(x*z + this->x(), yBottom*z + this->y()+0.5*yoffs); - drawTriangle(cairo, x+0.5*w, yBottom+0.5*h+yoffs, palette[(i-2*m_numLines-nBoundsPorts)%palette.size()].colour, -0.5*M_PI); + drawTriangle(cairoShim, x+0.5*w, yBottom+0.5*h+yoffs, palette[(i-2*m_numLines-nBoundsPorts)%palette.size()].colour, -0.5*M_PI); } - cairo_translate(cairo, portSpace, yoffs); - cairo_set_line_width(cairo,1); + cairoShim.translate(portSpace, yoffs); + cairoShim.setLineWidth(1); const double gw=w-2*portSpace, gh=h-portSpace; - Plot::draw(cairo,gw,gh); + Plot::draw(cairoShim,gw,gh); if (mouseFocus && legend) { double width,height,x,y; - legendSize(x,y,width,height,gw,gh); + legendSize(cairoShim,x,y,width,height,gw,gh); // following code puts x,y at centre point of legend x+=0.5*width; const double arrowLength=6; y=(h-portSpace)-y+0.5*height; - cairo_move_to(cairo,x-arrowLength,y); - cairo_rel_line_to(cairo,2*arrowLength,0); - cairo_move_to(cairo,x,y-arrowLength); - cairo_rel_line_to(cairo,0,2*arrowLength); - - cairo_move_to(cairo,x,y+0.5*height); - cairo_rel_line_to(cairo,0,arrowLength); - cairo_stroke(cairo); - drawTriangle(cairo,x-arrowLength,y,{0,0,0,1},M_PI); - drawTriangle(cairo,x+arrowLength,y,{0,0,0,1},0); - drawTriangle(cairo,x,y-arrowLength,{0,0,0,1},3*M_PI/2); - drawTriangle(cairo,x,y+arrowLength,{0,0,0,1},M_PI/2); - drawTriangle(cairo,x,y+0.5*height+arrowLength,{0,0,0,1},M_PI/2); - - cairo_rectangle(cairo,x-0.5*width,y-0.5*height,width,height); + cairoShim.moveTo(x-arrowLength,y); + cairoShim.relLineTo(2*arrowLength,0); + cairoShim.moveTo(x,y-arrowLength); + cairoShim.relLineTo(0,2*arrowLength); + + cairoShim.moveTo(x,y+0.5*height); + cairoShim.relLineTo(0,arrowLength); + cairoShim.stroke(); + drawTriangle(cairoShim,x-arrowLength,y,{0,0,0,1},M_PI); + drawTriangle(cairoShim,x+arrowLength,y,{0,0,0,1},0); + drawTriangle(cairoShim,x,y-arrowLength,{0,0,0,1},3*M_PI/2); + drawTriangle(cairoShim,x,y+arrowLength,{0,0,0,1},M_PI/2); + drawTriangle(cairoShim,x,y+0.5*height+arrowLength,{0,0,0,1},M_PI/2); + + cairoShim.rectangle(x-0.5*width,y-0.5*height,width,height); } - cs.restore(); + }// cs restored - CairoShimCairo cairoShim(cairo); if (mouseFocus) { drawPorts(cairoShim); @@ -209,20 +202,13 @@ namespace minsky } justDataChanged=false; - cairo_new_path(cairo); - cairo_rectangle(cairo,-0.5*w,-0.5*h,w,h); - cairo_clip(cairo); + cairoShim.newPath(); + cairoShim.rectangle(-0.5*w,-0.5*h,w,h); + cairoShim.clip(); if (selected) drawSelected(cairoShim); } - void PlotWidget::draw(const ICairoShim& cairoShim) const - { - // TODO: Implement properly without cairo_t* delegation - auto& shimImpl = dynamic_cast(cairoShim); - draw(shimImpl._internalGetCairoContext()); - } - void PlotWidget::scalePlot() { // set any scale overrides @@ -373,19 +359,14 @@ namespace minsky justDataChanged=true; // assume plot same size, don't do unnecessary stuff // store previous min/max values to determine if plot scale changes scalePlot(); - if (surface.get()) - surface->requestRedraw(); + RenderNativeWindow::requestRedraw(); } - bool PlotWidget::redraw(int x0, int y0, int width, int height) + bool PlotWidget::redraw(const IMansoura& mans, int x0, int y0, int width, int height) { - if (surface.get()) - { - auto sf=RenderNativeWindow::scaleFactor(); - Plot::draw(surface->cairo(),width/sf,height/sf); - surface->blit(); - } - return surface.get(); + auto sf=RenderNativeWindow::scaleFactor(); + Plot::draw(mans,width/sf,height/sf); + return true; } @@ -415,7 +396,8 @@ namespace minsky } double legendWidth, legendHeight, lx, ly; - legendSize(lx, ly, legendWidth, legendHeight, z*(iWidth()-2*portSpace), z*(iHeight()-portSpace-yoffs)); + // uses legend extents cached when last drawn + legendSizeFromCache(lx, ly, legendWidth, legendHeight, z*(iWidth()-2*portSpace), z*(iHeight()-portSpace-yoffs)); // xx & yy are in plot user coordinates const double xx= x-this->x() + z*(0.5*iWidth()-portSpace) - lx; const double yy= z*(0.5*iHeight()-portSpace)-y+this->y() - ly+legendHeight; @@ -861,3 +843,4 @@ namespace minsky } } CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::PlotWidget); +CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(mansoura::Plot); diff --git a/model/plotWidget.h b/model/plotWidget.h index 235380daf..89e80f557 100644 --- a/model/plotWidget.h +++ b/model/plotWidget.h @@ -22,7 +22,9 @@ #include "renderNativeWindow.h" #include "classdesc_access.h" #include "latexMarkup.h" -#include "plot.h" +#include "mansouraPlot.h" +#include "mansouraPlot.cd" +#include "mansouraPlot.xcd" #include "variable.h" #include "variableValue.h" #include "zoom.h" @@ -39,7 +41,7 @@ namespace minsky using namespace ecolab; struct PlotWidgetSuper: public ItemT, - public ecolab::Plot, public RenderNativeWindow {}; + public mansoura::Plot, public RenderNativeWindow {}; /// a container item for a plot widget class PlotWidget: public PlotWidgetSuper @@ -61,8 +63,9 @@ namespace minsky friend struct PlotItem; bool xIsSecsSinceEpoch=false; - bool redraw(int, int, int, int) override; + bool redraw(const mansoura::IMansoura&, int, int, int, int) override; using Plot::redraw; + void redrawWithBounds(const mansoura::IMansoura& shim) override {redraw(shim,0,0,500,500);} // shadow labels, so we can interpret as LaTeX code rather than Pango markup std::string m_xlabel, m_ylabel, m_y1label; @@ -78,11 +81,9 @@ namespace minsky bool clearPensOnLabelling=false; - void draw(cairo_t* cairoShim) const; public: using Item::x; using Item::y; - using RenderNativeWindow::surface; using RenderNativeWindow::requestRedraw; using RenderNativeWindow::renderToSVG; @@ -139,17 +140,17 @@ namespace minsky /// shadowed label commands to allow latex intepretation std::string const& xlabel() const {return m_xlabel;} std::string const& xlabel(const std::string& x) { - ecolab::Plot::xlabel=latexToPangoNonItalicised(x); + mansoura::Plot::xlabel=latexToPangoNonItalicised(x); return m_xlabel=x; } std::string const& ylabel() const {return m_ylabel;} std::string const& ylabel(const std::string& x) { - ecolab::Plot::ylabel=latexToPangoNonItalicised(x); + mansoura::Plot::ylabel=latexToPangoNonItalicised(x); return m_ylabel=x; } std::string const& y1label() const {return m_y1label;} std::string const& y1label(const std::string& x) { - ecolab::Plot::y1label=latexToPangoNonItalicised(x); + mansoura::Plot::y1label=latexToPangoNonItalicised(x); return m_y1label=x; } @@ -166,10 +167,9 @@ namespace minsky /// connect variable \a var to port \a port. void connectVar(const std::shared_ptr& var, unsigned port); void disconnectAllVars(); - using ecolab::Plot::draw; - void draw(const ICairoShim& cairoShim) const override; + using mansoura::Plot::draw; + void draw(const mansoura::IMansoura& cairoShim) const override; void requestRedraw(); ///< redraw plot using current data to all open windows - void redrawWithBounds() override {redraw(0,0,500,500);} /// add this as a display plot to its group void makeDisplayPlot(); @@ -203,7 +203,7 @@ namespace minsky /// export the plotted data as a CSV file // implemented as a single argument function here for exposure to TCL - void exportAsCSV(const string& filename) {ecolab::Plot::exportAsCSV(filename);} + void exportAsCSV(const string& filename) {mansoura::Plot::exportAsCSV(filename);} void destroyFrame() override {RenderNativeWindow::destroyFrame();} @@ -219,8 +219,8 @@ namespace minsky #pragma omit unpack PlotItem #endif -inline void xml_pack(classdesc::xml_pack_t&,const ecolab::string&,ecolab::Plot&) {} -inline void xml_unpack(classdesc::xml_unpack_t&,const ecolab::string&,ecolab::Plot&) {} +//inline void xml_pack(classdesc::xml_pack_t&,const ecolab::string&,ecolab::Plot&) {} +//inline void xml_unpack(classdesc::xml_unpack_t&,const ecolab::string&,ecolab::Plot&) {} #include "plotWidget.cd" #include "plotWidget.xcd" diff --git a/model/pubTab.cc b/model/pubTab.cc index 280350282..80eb37e34 100644 --- a/model/pubTab.cc +++ b/model/pubTab.cc @@ -21,14 +21,14 @@ #include "minsky.h" #include "cairoItems.h" #include "pubTab.h" -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "publication.rcd" #include "pubTab.xcd" #include "pubTab.rcd" #include "pannableTab.rcd" #include "pannableTab.xcd" #include "minsky_epilogue.h" -using namespace ecolab::cairo; +using namespace mansoura; namespace minsky { @@ -143,33 +143,28 @@ namespace minsky } } - bool PubTab::redraw(int x0, int y0, int width, int height) + bool PubTab::redraw(const IMansoura& cairo, int x0, int y0, int width, int height) { - if (!surface.get()) { - return false; - } - auto cairo=surface->cairo(); - const CairoSave cs(cairo); - cairo_translate(cairo, offsx, offsy); - cairo_scale(cairo, m_zoomFactor, m_zoomFactor); - cairo_set_line_width(cairo, 1); + const PreserveContext cs(cairo); + cairo.translate(offsx, offsy); + cairo.scale(m_zoomFactor, m_zoomFactor); + cairo.setLineWidth(1); for (auto& i: items) { - const CairoSave cs(cairo); - cairo_translate(cairo, i.x, i.y); + const PreserveContext cs(cairo); + cairo.translate(i.x, i.y); try { const EnsureEditorMode ensureEditorMode(i); - CairoShimCairo shim(cairo); - i.itemRef->draw(shim); + i.itemRef->draw(cairo); } catch (...) {} } if (clickType==ClickType::onResize) { - cairo_rectangle(cairo,std::min(lasso.x0,lasso.x1), std::min(lasso.y0,lasso.y1), + cairo.rectangle(std::min(lasso.x0,lasso.x1), std::min(lasso.y0,lasso.y1), abs(lasso.x0-lasso.x1), abs(lasso.y0-lasso.y1)); - cairo_stroke(cairo); + cairo.stroke(); } return !items.empty() || clickType!=ClickType::outside; } diff --git a/model/pubTab.h b/model/pubTab.h index 416df134b..6c6e7c4d1 100644 --- a/model/pubTab.h +++ b/model/pubTab.h @@ -50,7 +50,7 @@ namespace minsky class PubTab: public PannableTab { - bool redraw(int x0, int y0, int width, int height) override; + bool redraw(const mansoura::IMansoura& cairoShim, int x0, int y0, int width, int height) override; CLASSDESC_ACCESS(PubTab); PubItem* item=nullptr; // weak reference for moving items PubItem* m_getItemAt(float x, float y); diff --git a/model/ravelRenderer.h b/model/ravelRenderer.h new file mode 100644 index 000000000..b5ffec7a1 --- /dev/null +++ b/model/ravelRenderer.h @@ -0,0 +1,92 @@ +/* + @copyright Steve Keen 2023 + @author Russell Standish + This file is part of Minsky. + + Minsky is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Minsky is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Minsky. If not, see . +*/ + +#ifndef RAVELRENDERER_H +#define RAVELRENDERER_H +#include "capiRenderer.h" +#include "IMansoura.h" +#include + +namespace minsky +{ + /// adapts a mansoura::IMansoura drawing context to the Ravel + /// CAPIRenderer interface + struct RavelRenderer: public CAPIRenderer + { + const mansoura::IMansoura& shim; + std::unique_ptr text; + + static const mansoura::IMansoura& s(CAPIRenderer* r) + {return static_cast(r)->shim;} + static mansoura::ICacheRender& txt(CAPIRenderer* r) + {return *static_cast(r)->text;} + + static void s_showText(CAPIRenderer* c, const char* str) + { + double x,y; + s(c).getCurrentPoint(x,y); + txt(c).setText(str); + // paint a partially obscure white rectange to make the text pop + { + const mansoura::PreserveContext pc(s(c)); + auto e=txt(c).extents(); + s(c).rectangle(x,y,e.width,e.height); + s(c).setSourceRGBA(1,1,1,0.3); + s(c).fill(); + } + s(c).moveTo(x,y); + txt(c).show(); + } + static void s_setTextExtents(CAPIRenderer* c, const char* str) + {txt(c).setText(str);} + static double s_textWidth(CAPIRenderer* c) {return txt(c).extents().width;} + static double s_textHeight(CAPIRenderer* c) {return txt(c).extents().height;} + + RavelRenderer(const mansoura::IMansoura& shim): + shim(shim), text(shim.cachedRender(mansoura::TextProperties())) + { + moveTo=[](CAPIRenderer* c, double x, double y){s(c).moveTo(x,y);}; + lineTo=[](CAPIRenderer* c, double x, double y){s(c).lineTo(x,y);}; + relMoveTo=[](CAPIRenderer* c, double x, double y){s(c).relMoveTo(x,y);}; + relLineTo=[](CAPIRenderer* c, double x, double y){s(c).relLineTo(x,y);}; + arc=[](CAPIRenderer* c, double x, double y, double r, double a0, double a1){s(c).arc(x,y,r,a0,a1);}; + setLineWidth=[](CAPIRenderer* c, double w){s(c).setLineWidth(w);}; + newPath=[](CAPIRenderer* c){s(c).newPath();}; + closePath=[](CAPIRenderer* c){s(c).closePath();}; + fill=[](CAPIRenderer* c){s(c).fill();}; + clip=[](CAPIRenderer* c){s(c).clip();}; + stroke=[](CAPIRenderer* c){s(c).stroke();}; + strokePreserve=[](CAPIRenderer* c){s(c).strokePreserve();}; + setSourceRGB=[](CAPIRenderer* c, double r, double g, double b){s(c).setSourceRGB(r,g,b);}; + setSourceRGBA=[](CAPIRenderer* c, double r, double g, double b, double a){s(c).setSourceRGBA(r,g,b,a);}; + showText=s_showText; + setTextExtents=s_setTextExtents; + textWidth=s_textWidth; + textHeight=s_textHeight; + identityMatrix=[](CAPIRenderer* c){s(c).identityMatrix();}; + translate=[](CAPIRenderer* c, double x, double y){s(c).translate(x,y);}; + scale=[](CAPIRenderer* c, double x, double y){s(c).scale(x,y);}; + rotate=[](CAPIRenderer* c, double a){s(c).rotate(a);}; + save=[](CAPIRenderer* c){s(c).save();}; + restore=[](CAPIRenderer* c){s(c).restore();}; + } + }; +} + +#endif diff --git a/model/ravelWrap.cc b/model/ravelWrap.cc index c60829ad6..45fee9b59 100644 --- a/model/ravelWrap.cc +++ b/model/ravelWrap.cc @@ -23,8 +23,7 @@ #include "selection.h" #include "dimension.h" #include "minskyTensorOps.h" -#include "pango.h" -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "capiRenderer.xcd" #include "CSVTools.xcd" @@ -46,14 +45,15 @@ #include "tensorInterface.rcd" #include "tensorInterface.xcd" #include "xvector.rcd" -#include "minskyCairoRenderer.h" +#include "ravelRenderer.h" +#include "SVGItem.h" #include "minsky_epilogue.h" #include #include using namespace std; - +using namespace mansoura; namespace minsky { @@ -83,7 +83,7 @@ namespace minsky wrappedRavel.setOutputHandleIds({0,2}); } - void Ravel::draw(const ICairoShim& cairoShim) const + void Ravel::draw(const IMansoura& cairoShim) const { const double z=zoomFactor(), r=m_editorMode? 1.1*z*wrappedRavel.radius(): 30*z; if (flipped) @@ -111,9 +111,9 @@ namespace minsky if (onBorder || lockGroup) { // shadow the border when mouse is over it cairoShim.save(); - cairo::Colour c{1,1,1,0}; + Colour c{1,1,1,0}; if (lockGroup) - c=palette[ lockGroup->colour() % paletteSz ]; + c=mansoura::palette[ lockGroup->colour() % mansoura::paletteSz ]; c.r*=0.5; c.g*=0.5; c.b*=0.5; c.a=onBorder? 0.5:0.3; cairoShim.setSourceRGBA(c.r,c.g,c.b,c.a); @@ -131,15 +131,13 @@ namespace minsky if (m_editorMode) { cairoShim.scale(z,z); - // TODO: CairoRenderer needs ICairoShim support - auto& shimImpl = dynamic_cast(cairoShim); - CairoRenderer cr(shimImpl._internalGetCairoContext()); + RavelRenderer cr(cairoShim); wrappedRavel.render(cr); } else { cairoShim.translate(-r,-r); - // Render SVG using ICairoShim abstraction + // Render SVG using IMansoura abstraction cairoShim.renderSVG(svgRenderer, 2*r, 2*r); } cairoShim.restore(); @@ -890,16 +888,15 @@ namespace minsky r->lockGroup.reset(); // this may delete this, so should be last } - bool RavelPopup::redraw(int x0, int y0, int width, int height) + bool RavelPopup::redraw(const IMansoura& shim, int x0, int y0, int width, int height) { - if (!surface.get()) return false; this->width=width; this->height=height; - const ecolab::cairo::CairoSave cs(surface->cairo()); - cairo_translate(surface->cairo(),0.5*width,0.5*height); + const PreserveContext cs(shim); + shim.translate(0.5*width,0.5*height); auto z=0.4*min(width,height)/ravel.wrappedRavel.radius(); scale=1/z; - cairo_scale(surface->cairo(), z,z); - CairoRenderer cr(surface->cairo()); + shim.scale(z,z); + RavelRenderer cr(shim); ravel.wrappedRavel.render(cr); return true; } diff --git a/model/ravelWrap.h b/model/ravelWrap.h index 6b322a26e..2e3a859d3 100644 --- a/model/ravelWrap.h +++ b/model/ravelWrap.h @@ -21,12 +21,13 @@ #define RAVELWRAP_H #include "operation.h" -#include "cairoRenderer.h" +#include "capiRenderer.h" #include "dynamicRavelCAPI.h" #include "hypercube.h" #include "handleLockInfo.h" #include "renderNativeWindow.h" #include "SVGItem.h" +#include "SVGItem.cd" namespace minsky { @@ -40,7 +41,7 @@ namespace minsky float width, height, scale=1; float localX(float x) const; float localY(float y) const; - bool redraw(int x0, int y0, int width, int height) override; + bool redraw(const mansoura::IMansoura& cairoShim, int x0, int y0, int width, int height) override; CLASSDESC_ACCESS(RavelPopup); public: RavelPopup(Ravel& ravel): ravel(ravel) {} @@ -84,7 +85,7 @@ namespace minsky ravel::Op::ReductionOp m_nextReduction=ravel::Op::sum; public: - static SVGRenderer svgRenderer; ///< SVG icon to display when not in editor mode + static mansoura::SVGRenderer svgRenderer; ///< SVG icon to display when not in editor mode RavelPopup popup; ///< popup Ravel control window bool flipped=false; ravelCAPI::Database db; ///< backing database @@ -110,7 +111,7 @@ namespace minsky void leaveLockGroup(); void broadcastStateToLockGroup() const; - void draw(const ICairoShim& cairoShim) const override; + void draw(const mansoura::IMansoura& cairoShim) const override; void resize(const LassoBox&) override; bool inItem(float x, float y) const override; void onMouseDown(float x, float y) override; diff --git a/model/renderNativeWindow.cc b/model/renderNativeWindow.cc index 975a34358..5269b14e8 100644 --- a/model/renderNativeWindow.cc +++ b/model/renderNativeWindow.cc @@ -30,12 +30,8 @@ Please especially review the lifecycle (constructors, desctructors and copy cons #include "minsky.h" #include "renderNativeWindow.h" #include "windowInformation.h" -#include "cairoSurfaceImage.rcd" -#include "cairoSurfaceImage.xcd" #include "renderNativeWindow.rcd" #include "renderNativeWindow.xcd" -#include "plot.rcd" -#include "plot.xcd" #include "minsky_epilogue.h" @@ -44,7 +40,6 @@ Please especially review the lifecycle (constructors, desctructors and copy cons #include using namespace std; -using namespace ecolab; //#define FPS_PROFILING_ON #ifdef WIN32 @@ -56,21 +51,8 @@ using namespace ecolab; namespace minsky { - ecolab::cairo::Colour RenderNativeWindow::backgroundColour{0.8,0.8,0.8,1}; + mansoura::Colour RenderNativeWindow::backgroundColour{0.8,0.8,0.8,1}; - namespace - { - // default dummy surface to arrange a callback on requestRedraw - class NativeSurface : public cairo::Surface - { - RenderNativeWindow &renderNativeWindow; - - public: - NativeSurface(RenderNativeWindow &r, cairo_surface_t *s = nullptr, int width = -1, int height = -1) : cairo::Surface(s, width, height), renderNativeWindow(r) {} - void requestRedraw() override {renderNativeWindow.requestRedraw();} - }; - } // namespace - RenderNativeWindow::~RenderNativeWindow() { minsky().nativeWindowsToRedraw.erase(this); @@ -83,7 +65,6 @@ namespace minsky m_frameArgs=args; init(); winInfoPtr = std::make_shared(stoull(args.parentWindowId), args.offsetLeft, args.offsetTop, args.childWidth, args.childHeight, args.scalingFactor, hasScrollBars(), [this](){draw();}); - surface.reset(new NativeSurface(*this)); // ensure callback on requestRedraw works } draw(); } @@ -123,17 +104,9 @@ void macOSXRedraw(RenderNativeWindow& window,std::recursive_mutex& cmdMutex) #endif - auto surfaceToDraw = winInfoPtr->getBufferSurface(); - if (!surfaceToDraw) return; - surfaceToDraw.swap(surface); - - cairo_reset_clip(surface->cairo()); - const ecolab::cairo::CairoSave cs(surface->cairo()); - cairo_set_source_rgba(surface->cairo(), backgroundColour.r,backgroundColour.g,backgroundColour.b,backgroundColour.a); - cairo_rectangle(surface->cairo(), 0, 0, winInfoPtr->childWidth, winInfoPtr->childHeight); - cairo_fill(surface->cairo()); - cairo_set_source_rgb(surface->cairo(), 0, 0, 0); - redraw(0, 0, winInfoPtr->childWidth, winInfoPtr->childHeight); + winInfoPtr->render([this](const mansoura::IMansoura& shim, int width, int height) + {return redraw(shim, 0, 0, width, height);}, + backgroundColour); #ifdef FPS_PROFILING_ON unsigned long t1_png_stream_start = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); @@ -143,8 +116,6 @@ void macOSXRedraw(RenderNativeWindow& window,std::recursive_mutex& cmdMutex) unsigned long t2_window_copy_start = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); #endif - surfaceToDraw.swap(surface); - winInfoPtr->copyBufferToMain(); #ifdef FPS_PROFILING_ON @@ -159,6 +130,12 @@ void macOSXRedraw(RenderNativeWindow& window,std::recursive_mutex& cmdMutex) } + void RenderNativeWindow::renderTo(mansoura::ExportFormat format, const std::string& filename) + { + mansoura::exportTo(format, filename, m_resolutionScaleFactor, + [this](const mansoura::IMansoura& shim){redrawWithBounds(shim);}); + } + double RenderNativeWindow::scaleFactor() { #ifdef WIN32 diff --git a/model/renderNativeWindow.h b/model/renderNativeWindow.h index ca13fbe2d..a35acd87a 100644 --- a/model/renderNativeWindow.h +++ b/model/renderNativeWindow.h @@ -22,8 +22,8 @@ #include "eventInterface.h" -#include -#include +#include +#include #include @@ -41,10 +41,10 @@ namespace classdesc namespace minsky { class WindowInformation; - class RenderNativeWindow : public ecolab::CairoSurface, public EventInterface + class RenderNativeWindow : public EventInterface { public: - static ecolab::cairo::Colour backgroundColour; + static mansoura::Colour backgroundColour; struct RenderFrameArgs { @@ -59,25 +59,49 @@ namespace minsky const RenderFrameArgs& frameArgs() const {return m_frameArgs;} - ~RenderNativeWindow() override; + virtual ~RenderNativeWindow(); /// perform any initialisation of any subclasses of this virtual void init() {}; void renderFrame(const RenderFrameArgs& args); void destroyFrame(); void draw(); void requestRedraw(); + + /// @{ export the window's contents to a file + void renderToPS(const std::string& filename) {renderTo(mansoura::ExportFormat::PS,filename);} + void renderToPDF(const std::string& filename) {renderTo(mansoura::ExportFormat::PDF,filename);} + void renderToSVG(const std::string& filename) {renderTo(mansoura::ExportFormat::SVG,filename);} + void renderToPNG(const std::string& filename) {renderTo(mansoura::ExportFormat::PNG,filename);} + /// render to an EMF file. Windows only. + void renderToEMF(const std::string& filename) {renderTo(mansoura::ExportFormat::EMF,filename);} + /// @} + /// increase output resolution of pixmap surfaces by this factor + double resolutionScaleFactor() const {return m_resolutionScaleFactor;} + double resolutionScaleFactor(double rsf) {return m_resolutionScaleFactor=rsf;} + /// arrange a callback with the drawing time in seconds + virtual void reportDrawTime(double) {} + + // implemented as a free function to avoid Classdesc exposing this to Typescript friend void macOSXRedraw(RenderNativeWindow&,std::recursive_mutex&); // do not clobber winInfoPtr on load of model - RenderNativeWindow& operator=(const RenderNativeWindow& x) {ecolab::CairoSurface::operator=(x); return *this;} + RenderNativeWindow& operator=(const RenderNativeWindow& x) {m_resolutionScaleFactor=x.m_resolutionScaleFactor; return *this;} RenderNativeWindow()=default; RenderNativeWindow(const RenderNativeWindow&)=default; static double scaleFactor(); /// return whether this window has scrollbars (needed for MacOSX). virtual bool hasScrollBars() const {return false;} + protected: + /// draw the window's contents into \a cairoShim. x0,y0,width,height give the region to redraw + /// @return true if something drawn + virtual bool redraw(const mansoura::IMansoura& cairoShim, int x0, int y0, int width, int height)=0; + /// draw the entire contents of the window, unclipped + virtual void redrawWithBounds(const mansoura::IMansoura& cairoShim) {redraw(cairoShim,-1e6,-1e6,2e6,2e6);} + void renderTo(mansoura::ExportFormat format, const std::string& filename); private: CLASSDESC_ACCESS(RenderNativeWindow); + double m_resolutionScaleFactor=1.0; classdesc::Exclude> winInfoPtr; RenderFrameArgs m_frameArgs; diff --git a/model/sheet.cc b/model/sheet.cc index 870c3fd10..65a2ff891 100644 --- a/model/sheet.cc +++ b/model/sheet.cc @@ -22,19 +22,15 @@ #include "lasso.h" #include "minsky.h" #include "plotWidget.h" -#include -#include -#include "../engine/cairoShimCairo.h" #include "itemT.rcd" #include "sheet.rcd" -#include "minskyCairoRenderer.h" #include "ravelWrap.h" #include "tensorOp.h" #include "minsky_epilogue.h" using namespace minsky; -using namespace ecolab; +using namespace mansoura; using namespace std; // width of draggable border @@ -74,7 +70,7 @@ bool Sheet::onResizeHandle(float xx, float yy) const } -void Sheet::drawResizeHandles(const ICairoShim& cairo) const +void Sheet::drawResizeHandles(const IMansoura& cairo) const { auto sf=resizeHandleSize(); const float w=0.5f*m_width*zoomFactor(), h=0.5f*m_height*zoomFactor(); @@ -271,59 +267,64 @@ void Sheet::computeValue() namespace { - /// A pango that clips text to a standard area suitable for numbers - struct ClippedPango: public Pango + /// text renderer that clips text to a standard area suitable for numbers + struct ClippedPango { + const IMansoura& cairo; + unique_ptr render; double m_width, m_height; - ClippedPango(cairo_t* cairo): Pango(cairo) { - setText(str(-std::numeric_limits::max())); + ClippedPango(const IMansoura& cairo): cairo(cairo) { + render=cairo.cachedRender(TextProperties("",str(-std::numeric_limits::max()))); m_width=5+width(); m_height=height(); } + double width() const {return render->extents().width;} + double height() const {return render->extents().height;} + void setMarkup(const string& m) {render->setMarkup(m);} + void setText(const string& t) {render->setText(t);} void show() { - const cairo::CairoSave cs(cairoContext()); + const PreserveContext cs(cairo); double x,y; - cairo_get_current_point(cairoContext(),&x,&y); - cairo_rectangle(cairoContext(),x,y,m_width,m_height); - cairo_clip(cairoContext()); - cairo_move_to(cairoContext(),x,y); - Pango::show(); + cairo.getCurrentPoint(x,y); + cairo.rectangle(x,y,m_width,m_height); + cairo.clip(); + cairo.moveTo(x,y); + render->show(); } }; } -void Sheet::draw(cairo_t* cairo) const +void Sheet::draw(const IMansoura& cairo) const { - CairoShimCairo cairoShim(cairo); auto z=zoomFactor(); m_ports[0]->moveTo(x()-0.5*m_width*z,y()); if (mouseFocus) { - drawPorts(cairoShim); - displayTooltip(cairoShim,tooltip()); + drawPorts(cairo); + displayTooltip(cairo,tooltip()); // Resize handles always visible on mousefocus. For ticket 92. - drawResizeHandles(cairoShim); + drawResizeHandles(cairo); } - cairo_scale(cairo,z,z); + cairo.scale(z,z); - cairo_rectangle(cairo,-0.5*m_width+border,-0.5*m_height+border,m_width-2*border,m_height-2*border); - cairo_stroke_preserve(cairo); - cairo_rectangle(cairo,-0.5*m_width,-0.5*m_height,m_width,m_height); - cairo_stroke_preserve(cairo); + cairo.rectangle(-0.5*m_width+border,-0.5*m_height+border,m_width-2*border,m_height-2*border); + cairo.strokePreserve(); + cairo.rectangle(-0.5*m_width,-0.5*m_height,m_width,m_height); + cairo.strokePreserve(); // draw border if (onBorder) { // shadow the border when mouse is over it - const cairo::CairoSave cs(cairo); - cairo_set_source_rgba(cairo,0.5,0.5,0.5,0.5); - cairo_set_fill_rule(cairo,CAIRO_FILL_RULE_EVEN_ODD); - cairo_fill(cairo); + const PreserveContext cs(cairo); + cairo.setSourceRGBA(0.5,0.5,0.5,0.5); + cairo.setFillRule(CAIRO_FILL_RULE_EVEN_ODD); + cairo.fill(); } - cairo_new_path(cairo); - cairo_rectangle(cairo,-0.5*m_width+border,-0.5*m_height+border,m_width-2*border,m_height-2*border); - cairo_clip(cairo); + cairo.newPath(); + cairo.rectangle(-0.5*m_width+border,-0.5*m_height+border,m_width-2*border,m_height-2*border); + cairo.clip(); - if (selected) drawSelected(cairoShim); + if (selected) drawSelected(cairo); static const regex pangoMarkup("<[^<>]*>"); smatch match; @@ -331,8 +332,8 @@ void Sheet::draw(cairo_t* cairo) const try { if (!value || !m_ports[0] || m_ports[0]->numWires()==0) return; - Pango pango(cairo); - pango.setFontSize(12.0); + auto pango=cairo.cachedRender(TextProperties()); + pango->setFontSize(12.0); double x0=-0.5*m_width+border, y0=-0.5*m_height+border; const size_t vertDim=value->rank()>1? 1: 0, horizDim=0; @@ -342,9 +343,9 @@ void Sheet::draw(cairo_t* cairo) const if (value->hypercube().rank()==0) { - cairo_move_to(cairo,x0,y0); - pango.setMarkup(str((*value)[0])); - pango.show(); + cairo.moveTo(x0,y0); + pango->setMarkup(str((*value)[0])); + pango->show(); } else { @@ -352,23 +353,23 @@ void Sheet::draw(cairo_t* cairo) const if (!value->hypercube().xvectors[vertDim].name.empty()) { - const cairo::CairoSave cs(cairo); - pango.setMarkup(value->hypercube().xvectors[vertDim].name); - x0+=pango.height(); - cairo_move_to(cairo,x0, -0.5*pango.width()); - pango.angle=0.5*M_PI; - pango.show(); - pango.angle=0; + const PreserveContext cs(cairo); + pango->setMarkup(value->hypercube().xvectors[vertDim].name); + x0+=pango->extents().height; + cairo.moveTo(x0, -0.5*pango->extents().width); + pango->setAngle(0.5*M_PI); + pango->show(); + pango->setAngle(0); { // draw vertical grid line - const cairo::CairoSave cs(cairo); - cairo_set_source_rgba(cairo,0,0,0,0.5); - cairo_move_to(cairo,x0,-0.5*m_height); - cairo_line_to(cairo,x0,0.5*m_height); - cairo_stroke(cairo); + const PreserveContext cs(cairo); + cairo.setSourceRGBA(0,0,0,0.5); + cairo.moveTo(x0,-0.5*m_height); + cairo.lineTo(x0,0.5*m_height); + cairo.stroke(); } } - pango.setMarkup("9999"); + pango->setMarkup("9999"); ClippedPango cpango(cairo); const double rowHeight=cpango.m_height; @@ -383,30 +384,30 @@ void Sheet::draw(cairo_t* cairo) const if (value->hypercube().rank()>2) // allow room for slice indicator { y+=rowHeight; - const cairo::CairoSave cs(cairo); + const PreserveContext cs(cairo); cpango.setMarkup(sliceIndicator); - cairo_move_to(cairo,0.5*(x0+colWidth+0.5*m_width-cpango.width()), y0); + cairo.moveTo(0.5*(x0+colWidth+0.5*m_width-cpango.width()), y0); y0+=cpango.height(); cpango.show(); } if (!value->hypercube().xvectors[horizDim].name.empty()) { - const cairo::CairoSave cs(cairo); + const PreserveContext cs(cairo); cpango.setMarkup(value->hypercube().xvectors[horizDim].name); - cairo_move_to(cairo,0.5*(x0+colWidth+0.5*m_width-cpango.width()), y0); + cairo.moveTo(0.5*(x0+colWidth+0.5*m_width-cpango.width()), y0); y0+=cpango.height(); cpango.show(); } { // draw horizontal grid lines - const cairo::CairoSave cs(cairo); - cairo_set_source_rgba(cairo,0,0,0,0.5); - cairo_move_to(cairo,-0.5*m_width,y0-2.5); - cairo_line_to(cairo,0.5*m_width,y0-2.5); - cairo_stroke(cairo); - cairo_move_to(cairo,x,y0+rowHeight-2.5); - cairo_line_to(cairo,0.5*m_width,y0+rowHeight-2.5); - cairo_stroke(cairo); + const PreserveContext cs(cairo); + cairo.setSourceRGBA(0,0,0,0.5); + cairo.moveTo(-0.5*m_width,y0-2.5); + cairo.lineTo(0.5*m_width,y0-2.5); + cairo.stroke(); + cairo.moveTo(x,y0+rowHeight-2.5); + cairo.lineTo(0.5*m_width,y0+rowHeight-2.5); + cairo.stroke(); } } @@ -426,7 +427,7 @@ void Sheet::draw(cairo_t* cairo) const for (size_t i=adjustRowAndFinish.startRow; ihypercube().rank()==1) { { // draw vertical grid line - const cairo::CairoSave cs(cairo); - cairo_set_source_rgba(cairo,0,0,0,0.5); - cairo_move_to(cairo,x,-0.5*m_height); - cairo_line_to(cairo,x,0.5*m_height); - cairo_stroke(cairo); + const PreserveContext cs(cairo); + cairo.setSourceRGBA(0,0,0,0.5); + cairo.moveTo(x,-0.5*m_height); + cairo.lineTo(x,0.5*m_height); + cairo.stroke(); } for (size_t i=adjustRowAndFinish.startRow; iatHCIndex(i); if (!std::isnan(v)) { @@ -468,10 +469,10 @@ void Sheet::draw(cairo_t* cairo) const if (adjustColAndFinish(i,x)) break; y=y0; { - const cairo::CairoSave cs(cairo); - cairo_rectangle(cairo,x,y,colWidth,rowHeight); - cairo_clip(cairo); - cairo_move_to(cairo,x,y); + const PreserveContext cs(cairo); + cairo.rectangle(x,y,colWidth,rowHeight); + cairo.clip(); + cairo.moveTo(x,y); auto sliceLabel=trimWS(str(value->hypercube().xvectors[horizDim][i],format)); if (regex_search(sliceLabel,match,pangoMarkup)) cpango.setMarkup(sliceLabel); @@ -480,17 +481,17 @@ void Sheet::draw(cairo_t* cairo) const cpango.show(); } { // draw vertical grid line - const cairo::CairoSave cs(cairo); - cairo_set_source_rgba(cairo,0,0,0,0.5); - cairo_move_to(cairo,x-2.5,y0); - cairo_line_to(cairo,x-2.5,0.5*m_height); - cairo_stroke(cairo); + const PreserveContext cs(cairo); + cairo.setSourceRGBA(0,0,0,0.5); + cairo.moveTo(x-2.5,y0); + cairo.lineTo(x-2.5,0.5*m_height); + cairo.stroke(); } for (size_t j=adjustRowAndFinish.startRow; jatHCIndex(i+j*dims[0]+scrollOffset); if (!std::isnan(v)) @@ -505,29 +506,23 @@ void Sheet::draw(cairo_t* cairo) const } // draw grid { - const cairo::CairoSave cs(cairo); - cairo_set_source_rgba(cairo,0,0,0,0.2); + const PreserveContext cs(cairo); + cairo.setSourceRGBA(0,0,0,0.2); for (y=y0+0.8*rowHeight; y<0.5*m_height; y+=2*rowHeight) { - cairo_rectangle(cairo,x0,y,m_width,rowHeight); - cairo_fill(cairo); + cairo.rectangle(x0,y,m_width,rowHeight); + cairo.fill(); } } } } catch (...) {/* exception most likely invalid variable value */} - cairo_reset_clip(cairo); - cairo_rectangle(cairo,-0.5*m_width,-0.5*m_height,m_width,m_height); - cairo_clip(cairo); + cairo.resetClip(); + cairo.rectangle(-0.5*m_width,-0.5*m_height,m_width,m_height); + cairo.clip(); } -void Sheet::draw(const ICairoShim& cairoShim) const -{ - // TODO: Implement properly without cairo_t* delegation - auto& shimImpl = dynamic_cast(cairoShim); - draw(shimImpl._internalGetCairoContext()); -} void Sheet::exportAsCSV(const string& filename, bool tabular) const { diff --git a/model/sheet.h b/model/sheet.h index ffb786a5a..5f6c5503a 100644 --- a/model/sheet.h +++ b/model/sheet.h @@ -46,7 +46,6 @@ namespace minsky size_t scrollOffset=0, scrollMax=1; size_t scrollDelta=0; std::string sliceIndicator; - void draw(cairo_t* cairoShim) const; public: Sheet(); @@ -70,8 +69,8 @@ namespace minsky /// @return sliceIndicator const std::string& setSliceIndicator(); - void draw(const ICairoShim& cairoShim) const override; - void drawResizeHandles(const ICairoShim& cairo) const override; + void draw(const mansoura::IMansoura& cairoShim) const override; + void drawResizeHandles(const mansoura::IMansoura& cairo) const override; /// calculates the input value void computeValue(); diff --git a/model/switchIcon.cc b/model/switchIcon.cc index e67f6ebfc..7187e677e 100644 --- a/model/switchIcon.cc +++ b/model/switchIcon.cc @@ -21,10 +21,9 @@ #include "itemT.rcd" #include "switchIcon.h" #include "switchIcon.rcd" -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "minsky_epilogue.h" -using namespace ecolab::cairo; -using namespace ecolab; +using namespace mansoura; using namespace std; namespace minsky @@ -73,7 +72,7 @@ namespace minsky return r; } - void SwitchIcon::draw(const ICairoShim& cairoShim) const + void SwitchIcon::draw(const IMansoura& cairoShim) const { auto z=zoomFactor(); const float width=m_width*z, height=m_height*z; @@ -84,17 +83,17 @@ namespace minsky const float w=flipped? -width: width; const float o=flipped? -8: 8; // output port - drawTriangle(cairoShim, 0.5*w, 0, palette[0], flipped? M_PI: 0); + drawTriangle(cairoShim, 0.5*w, 0, mansoura::palette[0], flipped? M_PI: 0); m_ports[0]->moveTo(x()+0.5*w, y()); // control port - drawTriangle(cairoShim, 0, -0.5*height-8, palette[0], M_PI/2); + drawTriangle(cairoShim, 0, -0.5*height-8, mansoura::palette[0], M_PI/2); m_ports[1]->moveTo(x(), y()-0.5*height-8); const float dy=height/numCases(); float y1=-0.5*height+0.5*dy; // case ports for (size_t i=2; imoveTo(x()+-0.5*w-o, y()+y1); } // draw indicating arrow diff --git a/model/switchIcon.h b/model/switchIcon.h index face72cca..3bed9da3c 100644 --- a/model/switchIcon.h +++ b/model/switchIcon.h @@ -64,7 +64,7 @@ namespace minsky Units units(bool) const override; /// draw icon to \a context - void draw(const ICairoShim& cairoShim) const override; + void draw(const mansoura::IMansoura& cairoShim) const override; /// whether icon is oriented so input ports are on the rhs, and output on the lhs bool flipped=false; diff --git a/model/userFunction.cc b/model/userFunction.cc index bd24621c2..23e163488 100644 --- a/model/userFunction.cc +++ b/model/userFunction.cc @@ -64,11 +64,13 @@ #endif #endif +using namespace mansoura; + namespace minsky { int UserFunction::nextId=0; - template <> void Operation::iconDraw(const ICairoShim&) const + template <> void Operation::iconDraw(const IMansoura&) const {assert(false);} #ifdef NO_EXPRTK diff --git a/model/userFunction.h b/model/userFunction.h index 85806f577..f43c55f6e 100644 --- a/model/userFunction.h +++ b/model/userFunction.h @@ -45,7 +45,7 @@ namespace minsky double operator()(const std::vector& p) override; Units units(bool check=false) const override; - void displayTooltip(const ICairoShim& cr, const std::string& tt) const override + void displayTooltip(const mansoura::IMansoura& cr, const std::string& tt) const override {Item::displayTooltip(cr,tt.empty()? expression: tt+" "+expression);} using NamedOp::description; @@ -57,7 +57,7 @@ namespace minsky static UserFunction* create(OperationType::Type t) {return (t==OperationType::userFunction)? new UserFunction: nullptr;} - void draw(const ICairoShim& cairoShim) const override {drawUserFunction(cairoShim);} + void draw(const mansoura::IMansoura& cairoShim) const override {drawUserFunction(cairoShim);} }; diff --git a/model/variable.cc b/model/variable.cc index a02665ae4..5175430da 100644 --- a/model/variable.cc +++ b/model/variable.cc @@ -18,7 +18,6 @@ */ #include "minsky.h" -#include "cairoShimCairo.h" #include "geometry.h" #include "valueId.h" #include "variable.h" @@ -48,10 +47,9 @@ using namespace boost::locale::conv; using namespace classdesc; -using namespace ecolab; +using namespace mansoura; using namespace minsky; -using namespace ecolab::cairo; void VariableBase::addPorts() { @@ -86,16 +84,17 @@ ClickType::Type VariableBase::clickType(float xx, float yy) const const Rotate r(rotation()+(flipped(rotation())? 180: 0),0,0); // rotate into variable's frame of reference const RenderVariable rv(*this); const double z=zoomFactor(); - try - { - const double hpx=z*rv.handlePos(); - double hpy=-z*rv.height(); - if (rv.height()<0.5*iHeight()) hpy=-z*0.5*iHeight(); - const double dx=xx-x(), dy=yy-y(); - if (type()!=constant && hypot(dx - r.x(hpx,hpy), dy-r.y(hpx,hpy)) < 5) - return ClickType::inItem; - } - catch (...) {} + if (sliderVisible()) + try + { + const double hpx=z*rv.handlePos(); + double hpy=-z*rv.height(); + if (rv.height()<0.5*iHeight()) hpy=-z*0.5*iHeight(); + const double dx=xx-x(), dy=yy-y(); + if (type()!=constant && hypot(dx - r.x(hpx,hpy), dy-r.y(hpx,hpy)) < 5) + return ClickType::inItem; + } + catch (...) {} return Item::clickType(xx,yy); } @@ -602,8 +601,8 @@ bool VariableBase::miniPlotEnabled(bool enabled) { if (enabled) { - miniPlot=make_shared(); - miniPlot->plotType=ecolab::Plot::PlotType::bar; + miniPlot=make_shared(); + miniPlot->plotType=mansoura::Plot::PlotType::bar; } else miniPlot=nullptr; @@ -706,7 +705,7 @@ bool VariableBase::enableSlider(bool x) const return false; } -void VariableBase::draw(const ICairoShim& cairoShim) const +void VariableBase::draw(const IMansoura& cairoShim) const { auto [angle,flipped]=rotationAsRadians(); const float z=zoomFactor(); @@ -727,9 +726,7 @@ void VariableBase::draw(const ICairoShim& cairoShim) const const double h=std::max(l_cachedNameRender->height(), 0.5f*iHeight()); const double hoffs=l_cachedNameRender->top(); - auto cairo=dynamic_cast(cairoShim)._internalGetCairoContext(); - - unique_ptr clipPath; + unique_ptr clipPath; { cairoShim.save(); cairoShim.scale(z,z); @@ -755,7 +752,7 @@ void VariableBase::draw(const ICairoShim& cairoShim) const } cairoShim.save(); cairoShim.translate(-w,-h); - miniPlot->draw(cairo,2*w,2*h); + miniPlot->draw(cairoShim,2*w,2*h); cairoShim.restore(); } catch (...) {} // ignore errors in obtaining values @@ -803,7 +800,7 @@ void VariableBase::draw(const ICairoShim& cairoShim) const cairoShim.moveTo(r.x(w-mantissaBB.width-2,-h-hoffs+2), r.y(w-mantissaBB.width-2,-h-hoffs+2)); { - CairoShimSave cs(cairoShim); + PreserveContext cs(cairoShim); cairoShim.rotate(angle+(flipped? M_PI:0)); l_cachedMantissa->show(); } @@ -812,7 +809,7 @@ void VariableBase::draw(const ICairoShim& cairoShim) const { auto exponentBB=l_cachedExponent->extents(); cairoShim.moveTo(r.x(w-exponentBB.width-2,0),r.y(w-exponentBB.width-2,0)); - CairoShimSave cs(cairoShim); + PreserveContext cs(cairoShim); cairoShim.rotate(angle+(flipped? M_PI:0)); l_cachedExponent->show(); } @@ -841,7 +838,7 @@ void VariableBase::draw(const ICairoShim& cairoShim) const cairoShim.lineTo(w+2,0); cairoShim.lineTo(w,-h); cairoShim.closePath(); - clipPath.reset(new cairo::Path(cairo)); + clipPath=cairoShim.copyPath(); cairoShim.stroke(); if (sliderVisible()) { @@ -881,7 +878,7 @@ void VariableBase::draw(const ICairoShim& cairoShim) const } cairoShim.newPath(); - clipPath->appendToCurrent(cairo); + clipPath->appendToCurrent(cairoShim); // Rescale size of variable attached to intop. For ticket 94 cairoShim.clip(); if (selected) drawSelected(cairoShim); diff --git a/model/variable.h b/model/variable.h index 2c787edf8..14888daa6 100644 --- a/model/variable.h +++ b/model/variable.h @@ -36,12 +36,7 @@ #include #include "variableType.h" #include "itemT.h" -#include - -namespace ecolab { - class Pango; - class Plot; -} +#include "mansouraPlot.h" namespace minsky { @@ -65,9 +60,9 @@ namespace minsky protected: /// cached font rendering objects mutable std::shared_ptr cachedNameRender; - mutable std::shared_ptr cachedMantissa; - mutable std::shared_ptr cachedExponent; - mutable double cachedValue, cachedTime, cachedMaxSliderSteps; + mutable std::shared_ptr cachedMantissa; + mutable std::shared_ptr cachedExponent; + mutable double cachedMaxSliderSteps, cachedValue, cachedTime; public: VariableCaches()=default; VariableCaches(const VariableCaches&) {} @@ -94,7 +89,7 @@ namespace minsky void insertControlled(Selection& selection) override; /// miniature plot feature - classdesc::Exclude> miniPlot; + classdesc::Exclude> miniPlot; protected: void addPorts(); @@ -198,7 +193,7 @@ namespace minsky /** draws the icon onto the given cairo context @return cairo path of icon outline */ - void draw(const ICairoShim&) const override; + void draw(const mansoura::IMansoura&) const override; void resize(const LassoBox& b) override; ClickType::Type clickType(float x, float y) const override; diff --git a/model/windowInformation.cc b/model/windowInformation.cc index 3c7c28366..6ec23092a 100644 --- a/model/windowInformation.cc +++ b/model/windowInformation.cc @@ -18,6 +18,7 @@ */ #define NTDDI_VERSION NTDDI_WINBLUE #include "windowInformation.h" +#include "mansouraCairo.h" #include "minsky_epilogue.h" #include @@ -120,6 +121,25 @@ namespace minsky return bufferSurface; } + bool WindowInformation::render(const std::function& redraw, + const mansoura::Colour& bg) + { + if (!bufferSurface) return false; + bool r=false; + { + mansoura::MansouraCairo shim(bufferSurface->cairo()); + shim.resetClip(); + const mansoura::PreserveContext cs(shim); + shim.setSourceRGBA(bg.r,bg.g,bg.b,bg.a); + shim.rectangle(0,0,childWidth,childHeight); + shim.fill(); + shim.setSourceRGB(0,0,0); + r=redraw(shim,childWidth,childHeight); + } + copyBufferToMain(); + return r; + } + void WindowInformation::copyBufferToMain() { cairo_surface_flush(bufferSurface->surface()); diff --git a/model/windowInformation.h b/model/windowInformation.h index 0686e6699..57aea2226 100644 --- a/model/windowInformation.h +++ b/model/windowInformation.h @@ -21,6 +21,8 @@ #define WINDOW_INFORMATION_H #include +#include +#include #if defined(CAIRO_HAS_WIN32_SURFACE) && !defined(__CYGWIN__) #define USE_WIN32_SURFACE #include @@ -96,6 +98,12 @@ namespace minsky const ecolab::cairo::SurfacePtr& getBufferSurface() const; void requestRedraw(); + /// paint \a background over the whole buffer, call \a redraw on a + /// drawing context for the buffer (arguments being the context, + /// and the buffer's width and height), then copy the buffer to the screen + /// @return the return value of \a redraw + bool render(const std::function& redraw, + const mansoura::Colour& background); WindowInformation(const WindowInformation&)=delete; void operator=(const WindowInformation&)=delete; diff --git a/model/wire.cc b/model/wire.cc index c54f7c0fe..21cbd6c88 100644 --- a/model/wire.cc +++ b/model/wire.cc @@ -25,17 +25,15 @@ #include "selection.h" #include "lasso.h" #include "operation.h" -#include "pango.h" #include "plotWidget.h" #include "SVGItem.h" -#include "../engine/cairoShimCairo.h" #include "wire.rcd" #include "minsky_epilogue.h" #include #include using namespace std; -using ecolab::cairo::CairoSave; +using namespace mansoura; namespace minsky { @@ -344,31 +342,7 @@ namespace } - void Wire::storeCairoCoords(cairo_t* cairo) const - { - cairoCoords.clear(); - cairo_path_t *path; - cairo_path_data_t *data; - - path = cairo_copy_path_flat(cairo); - - for (int j=0; j < path->num_data; j += path->data[j].header.length) { - data = &path->data[j]; - switch (data->header.type) { - case CAIRO_PATH_MOVE_TO: - break; - case CAIRO_PATH_LINE_TO: - cairoCoords.push_back(make_pair(data[1].point.x,data[1].point.y)); - break; - case CAIRO_PATH_CURVE_TO: - case CAIRO_PATH_CLOSE_PATH: - break; - } - } - cairo_path_destroy (path); - } - - void Wire::draw(cairo_t* cairo, bool reverseArrow) const + void Wire::draw(const IMansoura& cairo, bool reverseArrow) const { auto coords=this->coords(); if (coords.size()<4 || !visible()) return; @@ -376,8 +350,8 @@ namespace float angle, lastx, lasty; if (coords.size()==4) { - cairo_move_to(cairo,coords[0],coords[1]); - cairo_line_to(cairo, coords[2], coords[3]); + cairo.moveTo(coords[0],coords[1]); + cairo.lineTo(coords[2], coords[3]); if (reverseArrow) { angle=atan2(coords[3]-coords[1], coords[2]-coords[0])+M_PI; @@ -391,7 +365,7 @@ namespace } else { - cairo_move_to(cairo, coords[0], coords[1]); + cairo.moveTo(coords[0], coords[1]); /** * @@ -423,47 +397,52 @@ namespace vector> controlPoints = computeControlPoints(A, points, target); // Decrease tolerance a bit, since it's going to be magnified - cairo_set_tolerance (cairo, 0.01); + cairo.setTolerance(0.01); for (int i = 0; i < n; i++) { - cairo_curve_to(cairo, controlPoints[i].first,controlPoints[i].second,controlPoints[n+i].first,controlPoints[n+i].second,points[i+1].first,points[i+1].second); + cairo.curveTo(controlPoints[i].first,controlPoints[i].second,controlPoints[n+i].first,controlPoints[n+i].second,points[i+1].first,points[i+1].second); } // Stash the internal cairo coordinates used to draw curved wires. for ticket 1079. - if (coords.size()>4) storeCairoCoords(cairo); + if (coords.size()>4) + { + cairoCoords.clear(); + for (auto& p: cairo.flattenedPathPoints()) + cairoCoords.emplace_back(p.first,p.second); + } - cairo_stroke(cairo); + cairo.stroke(); angle=atan2(coords[coords.size()-1]-coords[coords.size()-3], coords[coords.size()-2]-coords[coords.size()-4]); lastx=coords[coords.size()-2]; lasty=coords[coords.size()-1]; } - cairo_stroke(cairo); + cairo.stroke(); // draw arrow { - const CairoSave cs(cairo); - auto lw=cairo_get_line_width(cairo); - cairo_translate(cairo, lastx, lasty); - cairo_rotate(cairo,angle); - cairo_move_to(cairo,0,0); - cairo_line_to(cairo,-5*lw,-3*lw); - cairo_line_to(cairo,-3*lw,0); - cairo_line_to(cairo,-5*lw,3*lw); - cairo_close_path(cairo); - cairo_fill(cairo); + const PreserveContext cs(cairo); + auto lw=cairo.getLineWidth(); + cairo.translate(lastx, lasty); + cairo.rotate(angle); + cairo.moveTo(0,0); + cairo.lineTo(-5*lw,-3*lw); + cairo.lineTo(-3*lw,0); + cairo.lineTo(-5*lw,3*lw); + cairo.closePath(); + cairo.fill(); } // draw handles if (mouseFocus) { - const cairo::CairoSave cs(cairo); - cairo_set_source_rgb(cairo,0,0,1); + const PreserveContext cs(cairo); + cairo.setSourceRGB(0,0,1); if (cairoCoords.empty() || coords.size()==4) { const double midx=0.5*(coords[0]+coords[2]); const double midy=0.5*(coords[1]+coords[3]); - cairo_arc(cairo,midx,midy,1.5*handleRadius, 0, 2*M_PI); - cairo_fill(cairo); + cairo.arc(midx,midy,1.5*handleRadius, 0, 2*M_PI); + cairo.fill(); } else { @@ -472,19 +451,18 @@ namespace { const double midx=cairoCoords[(i+1)*numCairoCoords/(2*numSmallHandles)].first; const double midy=cairoCoords[(i+1)*numCairoCoords/(2*numSmallHandles)].second; - cairo_arc(cairo,midx,midy,handleRadius, 0, 2*M_PI); + cairo.arc(midx,midy,handleRadius, 0, 2*M_PI); if (i>0) // draw existing interior gripping handle - cairo_arc(cairo,coords[i],coords[i+1],1.5*handleRadius, 0, 2*M_PI); - cairo_fill(cairo); + cairo.arc(coords[i],coords[i+1],1.5*handleRadius, 0, 2*M_PI); + cairo.fill(); } } } if (mouseFocus && !tooltip().empty()) { - const cairo::CairoSave cs(cairo); + const PreserveContext cs(cairo); const string toolTipText=latexToPango(tooltip()); - ecolab::Pango pango(cairo); - pango.setMarkup(toolTipText); + auto pango=cairo.cachedRender(TextProperties(toolTipText)); // place tooltip on centre dot if an odd number of control points, or halfway between otherwise auto dd=div(coords.size(),4); assert(dd.rem%2==0); @@ -495,26 +473,18 @@ namespace midx=0.5*(coords[dd.quot]+coords[dd.quot+2]); midy=0.5*(coords[dd.quot+1]+coords[dd.quot+3]); } - cairo_translate(cairo,midx,midy); - cairo_rectangle(cairo,0,0,pango.width(),pango.height()); - cairo_set_source_rgb(cairo,1,1,1); - cairo_fill_preserve(cairo); - cairo_set_source_rgb(cairo,0,0,0); - cairo_set_line_width(cairo,1); - cairo_set_dash(cairo,nullptr,0,0); - pango.show(); - cairo_stroke(cairo); + cairo.translate(midx,midy); + cairo.rectangle(0,0,pango->extents().width,pango->extents().height); + cairo.setSourceRGB(1,1,1); + cairo.fillPreserve(); + cairo.setSourceRGB(0,0,0); + cairo.setLineWidth(1); + cairo.setDash(nullptr,0,0); + pango->show(); + cairo.stroke(); } } - void Wire::draw(const ICairoShim& cairoShim, bool reverseArrow) const - { - // Wire drawing is complex and uses storeCairoCoords which requires cairo_t* - // TODO: This will be properly refactored in a separate PR (per owner comment) - auto& shimImpl = dynamic_cast(cairoShim); - draw(shimImpl._internalGetCairoContext(), reverseArrow); - } - void Wire::split() { // add I/O variables if this wire crosses a group boundary diff --git a/model/wire.h b/model/wire.h index 78889dc4c..79efce3d2 100644 --- a/model/wire.h +++ b/model/wire.h @@ -21,12 +21,12 @@ #include "noteBase.h" #include "intrusiveMap.h" -#include "ICairoShim.h" +#include "IMansoura.h" +#include "IMansoura.cd" #include #include #include "classdesc_access.h" -#include namespace minsky { @@ -50,7 +50,6 @@ namespace minsky constexpr static float handleRadius=3; mutable int unitsCtr=0; ///< for detecting wiring loops in units() mutable std::vector> cairoCoords; ///< contains all the internal cairo coordinates used to draw a wire - void draw(cairo_t* cairo, bool reverseArrow=false) const; public: Wire() {} @@ -63,11 +62,9 @@ namespace minsky /// switch ports this wire links to void moveToPorts(const std::shared_ptr& from, const std::shared_ptr& to); - /// stash all the internal cairo coordinates along a wire - void storeCairoCoords(cairo_t* cairo) const; /// draw this item into a cairo context - virtual void draw(const ICairoShim& cairoShim, bool reverseArrow=false) const; + virtual void draw(const mansoura::IMansoura& cairoShim, bool reverseArrow=false) const; /// display coordinates std::vector coords() const; diff --git a/schema/plotOptions.h b/schema/plotOptions.h index c4b2a0a5c..3c08ecc35 100644 --- a/schema/plotOptions.h +++ b/schema/plotOptions.h @@ -21,6 +21,7 @@ #define PLOTOPTIONS_H #include "optional.h" #include "plotWidget.h" +#include "schemaHelper.h" namespace minsky { @@ -28,9 +29,9 @@ namespace minsky { double legendLeft=0.9, legendTop=0.95, legendFontSz=0.03; LegendGeometry()=default; - LegendGeometry(const ecolab::Plot& plot): + LegendGeometry(const mansoura::Plot& plot): legendLeft(plot.legendLeft), legendTop(plot.legendTop), legendFontSz(plot.legendFontSz) {} - void setLegendGeometry(ecolab::Plot& plot) const { + void setLegendGeometry(mansoura::Plot& plot) const { plot.legendLeft=legendLeft; plot.legendTop=legendTop; plot.legendFontSz=legendFontSz; @@ -54,9 +55,9 @@ namespace minsky Optional xtickAngle, exp_threshold; double xmin=nan(""), xmax=nan(""), ymin=nan(""), ymax=nan(""), y1min=nan(""), y1max=nan(""); unsigned symbolEvery=1; - Optional legend; + Optional legend; Optional legendGeometry; - Optional> palette; + Optional> palette; Optional> horizontalMarkers, verticalMarkers; PlotOptions& operator=(const PlotWidget& plot) { name=plot.title; diff --git a/schema/schema0.cc b/schema/schema0.cc index cb62ac4e2..66a068f8c 100644 --- a/schema/schema0.cc +++ b/schema/schema0.cc @@ -17,7 +17,6 @@ along with Minsky. If not, see . */ #include "schema0.h" -#include "plot.xcd" #include "minsky_epilogue.h" #include using namespace ecolab; diff --git a/schema/schema0.h b/schema/schema0.h index 254980d68..77305e4e3 100644 --- a/schema/schema0.h +++ b/schema/schema0.h @@ -34,7 +34,8 @@ #include "variableType.h" #include "assetClass.h" #include -#include +#include "mansouraPlot.h" +#include "mansouraPlot.xcd" namespace schema0 { @@ -181,7 +182,7 @@ namespace schema0 bool grid; ///< draw grid bool leadingMarker; ///< draw a leading marker on the curve (full draw only) bool autoscale; ///< autoscale plot to data - ecolab::Plot::PlotType plotType; + mansoura::Plot::PlotType plotType; double minx, maxx, miny, maxy; ecolab::array ports; std::vector yvars; diff --git a/schema/schema1.h b/schema/schema1.h index 808864cf1..056c401a0 100644 --- a/schema/schema1.h +++ b/schema/schema1.h @@ -31,7 +31,7 @@ but any renamed attributes require bumping the schema number. #include "classdesc.h" #include "polyXMLBase.h" #include "polyJsonBase.h" -#include "plot.xcd" +//#include "plot.xcd" #include "simulation.h" #include @@ -149,7 +149,7 @@ namespace schema1 // why is the schema1 qualifier needed here? struct Plot: public SPoly { - typedef ecolab::Plot::Side Side; + typedef mansoura::Plot::Side Side; vector ports; shared_ptr legend; bool logx{0}, logy{0}; diff --git a/schema/schema2.h b/schema/schema2.h index 9978c26bf..a234923e1 100644 --- a/schema/schema2.h +++ b/schema/schema2.h @@ -114,7 +114,7 @@ namespace schema2 // group specific fields Optional> bookmarks; Optional tensorData; // used for saving tensor data attached to parameters - Optional> palette; + Optional> palette; Item() {} // minsky object importers @@ -221,5 +221,6 @@ namespace schema2 #include "schema2.cd" #include "schema2.xcd" +#include "plot.xcd" #endif diff --git a/schema/schema3.h b/schema/schema3.h index dcfd2eaaa..6f99e4fc8 100644 --- a/schema/schema3.h +++ b/schema/schema3.h @@ -133,7 +133,7 @@ namespace schema3 // group specific fields Optional> bookmarks; Optional tensorData; // used for saving tensor data attached to parameters - Optional> palette; + Optional> palette; void packTensorInit(const minsky::VariableBase&); diff --git a/schema/schemaHelper.h b/schema/schemaHelper.h index 1aa41d383..f00790393 100644 --- a/schema/schemaHelper.h +++ b/schema/schemaHelper.h @@ -114,7 +114,8 @@ namespace minsky /// encode binary data to ascii-encoded classdesc::CDATA encode(const classdesc::pack_t&); - + /// utility for converting between compatible enums + template inline T toEnum(U x) {return T(int(x));} } #endif diff --git a/test/00/godleyTable.sh b/test/00/godleyTable.sh index 5d69abe62..195d36397 100755 --- a/test/00/godleyTable.sh +++ b/test/00/godleyTable.sh @@ -78,35 +78,35 @@ assert minsky.canvas.item.table.getVariables()()==['a', 'b'] # popup undo/redo tracks cell edits and discards stale redo states originalCell = item.table.getCell(2, 1) item.setCell(2, 1, 'changed') -item.popup.undo(1) +item.editor.undo(1) assert item.table.getCell(2, 1)==originalCell -item.popup.undo(-1) +item.editor.undo(-1) assert item.table.getCell(2, 1)=='changed' -item.popup.undo(1) +item.editor.undo(1) item.setCell(2, 1, 'branched') -item.popup.undo(-1) +item.editor.undo(-1) assert item.table.getCell(2, 1)=='branched' -item.popup.undo(1) +item.editor.undo(1) assert item.table.getCell(2, 1)==originalCell -item.popup.undo(-1) +item.editor.undo(-1) assert item.table.getCell(2, 1)=='branched' # updating after undo must not change a restored blank initial condition -item.popup.pushHistory() +item.editor.pushHistory() item.table.setCell(1, 1, '') item.setCell(2, 1, 'changed') -item.popup.undo(1) +item.editor.undo(1) assert item.table.getCell(1, 1)=='' -item.popup.undo(-1) +item.editor.undo(-1) assert item.table.getCell(2, 1)=='changed' -# row edits made through the popup are also undoable +# row edits made through the editor are also undoable rows = item.table.rows() -item.popup.addFlowByRow(rows-1) +item.editor.addFlowByRow(rows-1) assert item.table.rows()==rows+1 -item.popup.undo(1) +item.editor.undo(1) assert item.table.rows()==rows -item.popup.undo(-1) +item.editor.undo(-1) assert item.table.rows()==rows+1 minsky.canvas.deleteItem() diff --git a/test/00/godleyTableWindow.sh b/test/00/godleyTableWindow.sh deleted file mode 100755 index f47f644a0..000000000 --- a/test/00/godleyTableWindow.sh +++ /dev/null @@ -1,53 +0,0 @@ -#! /bin/sh - -here=`pwd` -. $here/test/common-test.sh - -cat >input.py <tmp1 - sed -e 's/id="[^"]*"/id=""/' <$here/test/renderedImages/$i >tmp2 - $here/test/compareSVG.sh tmp1 tmp2 - if [ $? -ne 0 ]; then fail; fi -done - -pass diff --git a/test/Makefile b/test/Makefile index 0009c300f..97130e674 100755 --- a/test/Makefile +++ b/test/Makefile @@ -20,15 +20,16 @@ endif # link statically to ecolab (needed until all bugs in EcoLab 6 ironed out) LIBS:=$(subst -lecolab,$(ECOLAB_HOME)/lib/libecolab.a,$(LIBS)) -VPATH= .. ../schema ../model ../engine ../RESTService ../RavelCAPI/civita ../RavelCAPI $(ECOLAB_HOME)/include +VPATH= .. ../schema ../model ../engine ../RESTService ../RavelCAPI/civita ../RavelCAPI ../mansoura/src $(ECOLAB_HOME)/include GTESTOBJS=testCSVParser.o testCanvas.o testDataOp.o testDatabaseIngestor.o testDerivative.o testExpressionWalker.o testLatexToPango.o testLock.o testLockGroup.o testMdl.o testMdlReader.o testMinsky.o testModel.o testPannableTab.o testPhillips.o testPlotWidget.o testPubTab.o testSaver.o testSheet.o testStr.o testTensorOps.o testUnits.o testUserFunction.o testVariable.o testXVector.o testZStream.o ticket-1461.o MINSKYOBJS=localMinsky.o ../libminsky.a -FLAGS:=-I.. -I../RESTService -I../RavelCAPI/civita -I../RavelCAPI -I../model -I../engine -I../schema $(FLAGS) +FLAGS:=-I.. -I../RESTService -I../RavelCAPI/civita -I../RavelCAPI -I../model -I../engine -I../schema -I../mansoura/src $(FLAGS) FLAGS+=-std=c++20 -DJSON_PACK_NO_FALL_THROUGH_TO_STREAMING -DUSE_UNROLLED -DCLASSDESC_ARITIES=0xf \ -Wno-unknown-warning-option -Wno-unused-local-typedefs -Wno-unused-command-line-argument LIBS+=-L../RavelCAPI -lravelCAPI -L../RavelCAPI/civita -lcivita \ + -L../mansoura -lmansoura \ -lboost_filesystem -lboost_system -lboost_thread \ -lboost_date_time -lclipboard \ -lgsl -lssl -lcrypto -lgslcblas -lxml2 -ltiff -ldl diff --git a/test/renderedImages/1Free11Selected.svg b/test/renderedImages/1Free11Selected.svg deleted file mode 100644 index 12233ebf7..000000000 --- a/test/renderedImages/1Free11Selected.svg +++ /dev/null @@ -1,952 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/renderedImages/1FreeBase.svg b/test/renderedImages/1FreeBase.svg deleted file mode 100644 index ffb407a06..000000000 --- a/test/renderedImages/1FreeBase.svg +++ /dev/null @@ -1,903 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/renderedImages/1FreeSelectedCol.svg b/test/renderedImages/1FreeSelectedCol.svg deleted file mode 100644 index ada03b76a..000000000 --- a/test/renderedImages/1FreeSelectedCol.svg +++ /dev/null @@ -1,943 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/renderedImages/1FreeSelectedRow.svg b/test/renderedImages/1FreeSelectedRow.svg deleted file mode 100644 index 39a3c0051..000000000 --- a/test/renderedImages/1FreeSelectedRow.svg +++ /dev/null @@ -1,959 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/renderedImages/LoanableFundsBase.svg b/test/renderedImages/LoanableFundsBase.svg deleted file mode 100644 index 1e537e028..000000000 --- a/test/renderedImages/LoanableFundsBase.svg +++ /dev/null @@ -1,1129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/testCanvas.cc b/test/testCanvas.cc index b79462cb4..c2f6d84ff 100644 --- a/test/testCanvas.cc +++ b/test/testCanvas.cc @@ -48,7 +48,7 @@ TEST_F(CanvasTest, defaultPlotOptions) originalPlot->y1label("y1"); originalPlot->palette.emplace_back(); originalPlot->palette.back().width=2; - originalPlot->palette.back().dashStyle=ecolab::Plot::LineStyle::dash; + originalPlot->palette.back().dashStyle=mansoura::Plot::LineStyle::dash; addPlot(); auto firstItem=itemFocus; diff --git a/test/testLock.cc b/test/testLock.cc index ad08292a0..c1ec2fd1e 100644 --- a/test/testLock.cc +++ b/test/testLock.cc @@ -17,7 +17,7 @@ along with Minsky. If not, see . */ -#include "cairoShimCairo.h" +#include "mansouraCairo.h" #include "lock.h" #include "minsky.h" #include "minsky_epilogue.h" @@ -155,6 +155,6 @@ TEST_F(LockTest, Draw) // Test that lock can be drawn (uses different icons for locked/unlocked) cairo::Surface surf(cairo_recording_surface_create(CAIRO_CONTENT_COLOR, nullptr)); - EXPECT_NO_THROW(lock.draw(CairoShimCairo(surf.cairo()))); + EXPECT_NO_THROW(lock.draw(mansoura::MansouraCairo(surf.cairo()))); } diff --git a/test/testMinsky.cc b/test/testMinsky.cc index 7102e3163..d822e99bc 100644 --- a/test/testMinsky.cc +++ b/test/testMinsky.cc @@ -17,7 +17,7 @@ along with Minsky. If not, see . */ #include "minsky.h" -#include "godleyTableWindow.h" +#include "godleyTableEditor.h" #include "matrix.h" #include "minsky_epilogue.h" #undef True @@ -969,13 +969,13 @@ TEST(TensorOps, evalOpEvaluate) g->table.cell(2,1)="flow"; model->addItem(VariablePtr(VariableBase::flow,"flow")); g->update(); - g->popup.pushHistory(); + g->editor.pushHistory(); g->moveCell({2,1,2,2}); EXPECT_EQ("",g->table.cell(2,1)); EXPECT_EQ("flow",g->table.cell(2,2)); - g->popup.undo(1); + g->editor.undo(1); EXPECT_EQ("flow",g->table.cell(2,1)); EXPECT_EQ("",g->table.cell(2,2)); } diff --git a/test/testModel.cc b/test/testModel.cc index 1f7759599..6c41bd50c 100644 --- a/test/testModel.cc +++ b/test/testModel.cc @@ -17,28 +17,48 @@ along with Minsky. If not, see . */ +#include "mansouraCairo.h" #include "cairoItems.h" -#include "cairoShimCairo.h" #include "operation.h" #include "group.h" #include "minsky.h" -#include "godleyTableWindow.h" +#include "godleyTableEditor.h" #include "minsky_epilogue.h" #include using namespace minsky; +using namespace mansoura; using namespace std; namespace { + // gtest requires all fixtures to be derived from Test, alas! + class CanvasFixture: public Canvas, public ::testing::Test + { + Minsky lminsky; + LocalMinsky lm; + public: + CanvasFixture(): lm(lminsky) {} + }; + class GodleyIconFixture: public GodleyIcon, public ::testing::Test {}; + class GroupFixture: public Group, public ::testing::Test {}; + + struct RecordingCairoShim: public cairo::Surface, public MansouraCairo + { + RecordingCairoShim(): + cairo::Surface(cairo_recording_surface_create(CAIRO_CONTENT_COLOR,nullptr)), + MansouraCairo(cairo::Surface::cairo()) {} + }; + struct ModelSuite: public Minsky, public ::testing::Test { GroupPtr group0; ItemPtr a,b,c; WirePtr ab,bc; LocalMinsky lm; + RecordingCairoShim mans; ModelSuite(): lm(*this) { @@ -103,24 +123,7 @@ namespace } }; - // gtest requires all fixtures to be derived from Test, alas! - class CanvasFixture: public Canvas, public ::testing::Test - { - Minsky lminsky; - LocalMinsky lm; - public: - CanvasFixture(): lm(lminsky) {} - }; - class GodleyIconFixture: public GodleyIcon, public ::testing::Test {}; - class GroupFixture: public Group, public ::testing::Test {}; - struct RecordingCairoShim: public cairo::Surface, public CairoShimCairo - { - RecordingCairoShim(): - cairo::Surface(cairo_recording_surface_create(CAIRO_CONTENT_COLOR,nullptr)), - CairoShimCairo(cairo::Surface::cairo()) {} - }; - } @@ -1310,17 +1313,16 @@ struct EmbedGodleyIcon GodleyIcon embeddedGodleyIcon; }; -struct GodleyTableWindowFixture: private EmbedGodleyIcon, public GodleyTableWindow, public ::testing::Test +struct GodleyTableWindowFixture: private EmbedGodleyIcon, public GodleyTableEditor, public ::testing::Test { - GodleyTableWindowFixture(): GodleyTableWindow(embeddedGodleyIcon) {} + RecordingCairoShim mans; + GodleyTableWindowFixture(): GodleyTableEditor(embeddedGodleyIcon) {} }; TEST_F(GodleyTableWindowFixture, mouseMove) { godleyIcon().table.cell(1,1)="hello"; - surface.reset(new ecolab::cairo::Surface - (cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,NULL))); - redraw(0,0,0,0); + draw(mans); double x=colLeftMargin[1]+10, y=topTableOffset+rowHeight+5; EXPECT_EQ(1, colX(x)); EXPECT_EQ(1, rowY(y)); @@ -1328,7 +1330,7 @@ TEST_F(GodleyTableWindowFixture, mouseMove) EXPECT_EQ(1, hoverRow); EXPECT_EQ(1, hoverCol); x=2*ButtonWidget::buttonSpacing+1; - EXPECT_EQ(rowWidget, GodleyTableWindow::clickType(x,y)); + EXPECT_EQ(rowWidget, GodleyTableEditor::clickType(x,y)); mouseMove(x,y); EXPECT_EQ(2,rowWidgets[1].mouseOver()); x=colLeftMargin[1]+ButtonWidget::buttonSpacing+1; @@ -1343,9 +1345,7 @@ TEST_F(GodleyTableWindowFixture, mouseMove) TEST_F(GodleyTableWindowFixture, mouseSelect) { godleyIcon().table.cell(1,1)="hello"; - surface.reset(new ecolab::cairo::Surface - (cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,NULL))); - redraw(0,0,0,0); + draw(mans); double x=colLeftMargin[1], y=topTableOffset+rowHeight+5; EXPECT_EQ(1, colX(x)); EXPECT_EQ(1, rowY(y)); @@ -1373,9 +1373,7 @@ TEST_F(GodleyTableWindowFixture, mouseButtons) godleyIcon().table.cell(3,1)="r3c1"; godleyIcon().table.cell(3,2)="r3c2"; - surface.reset(new ecolab::cairo::Surface - (cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,NULL))); - redraw(0,0,0,0); + draw(mans); double x=colLeftMargin[1]+2*ButtonWidget::buttonSpacing+1, y=5+columnButtonsOffset; EXPECT_EQ(colWidget, clickType(x,y)); mouseDown(x,y); @@ -1412,9 +1410,7 @@ TEST_F(GodleyTableWindowFixture, moveRowColCell) godleyIcon().table.cell(1,2)="r1c2"; godleyIcon().table.cell(2,1)="r2c1"; godleyIcon().table.cell(2,2)="r2c2"; - surface.reset(new ecolab::cairo::Surface - (cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,NULL))); - redraw(0,0,0,0); + draw(mans); double x=colLeftMargin[1]+10, y=topTableOffset+5; EXPECT_EQ(1,colX(x)); EXPECT_EQ(0,rowY(y)); @@ -1461,13 +1457,13 @@ TEST_F(GodleyTableWindowFixture, keyPress) selectedCol=1; selectedRow=1; selectIdx=insertIdx=0; - keyPress({'a',"a"}); keyPress({'b',"b"}); keyPress({'b',"b"}); insertIdx=2; keyPress({XK_Delete,""}); - keyPress({'c',"c"}); keyPress({'c',"c"}); keyPress({XK_BackSpace,""}); + keyPress('a',"a"); keyPress('b',"b"); keyPress('b',"b"); insertIdx=2; keyPress(XK_Delete,""); + keyPress('c',"c"); keyPress('c',"c"); keyPress(XK_BackSpace,""); EXPECT_EQ("abc",godleyIcon().table.cell(1,1)); godleyIcon().table.cell(0,1)="stock1"; EXPECT_EQ(0,godleyIcon().stockVars().size()); - keyPress({XK_Return,""}); // should cause update to be called + keyPress(XK_Return,""); // should cause update to be called // unfortunately, this is a freestanding GodleyIcon, so update has no effect // EXPECT_EQ(1,godleyIcon().stockVars().size()); // EXPECT_EQ("stock1",godleyIcon().stockVars()[0]->name()); @@ -1478,7 +1474,7 @@ TEST_F(GodleyTableWindowFixture, keyPress) selectedCol=1; selectedRow=1; godleyIcon().table.savedText="abc"; - keyPress({'d',"d"}); keyPress({XK_Escape,""}); // should revert to previous + keyPress('d',"d"); keyPress(XK_Escape,""); // should revert to previous EXPECT_EQ("abc",godleyIcon().table.cell(1,1)); EXPECT_EQ(-1,selectedCol); EXPECT_EQ(-1,selectedRow); @@ -1487,39 +1483,39 @@ TEST_F(GodleyTableWindowFixture, keyPress) selectedCol=1; selectedRow=1; selectIdx=insertIdx=0; - keyPress({XK_Right,""}); + keyPress(XK_Right,""); EXPECT_EQ(1,insertIdx); - keyPress({XK_Left,""}); + keyPress(XK_Left,""); EXPECT_EQ(0,insertIdx); // (1,0) cell no longer selectable, selectedRow and selectedCol become -1 - keyPress({XK_Left,""}); + keyPress(XK_Left,""); EXPECT_EQ(-1,selectedCol); EXPECT_EQ(-1,selectedRow); - keyPress({XK_Tab,""}); // No cell selected, selectedRow = 0 and selectedCol = 1 when tab button is pressed, see godleyTableWindow line 633 + keyPress(XK_Tab,""); // No cell selected, selectedRow = 0 and selectedCol = 1 when tab button is pressed EXPECT_EQ(1,selectedCol); - keyPress({XK_Tab,""}); + keyPress(XK_Tab,""); EXPECT_EQ(2,selectedCol); - keyPress({XK_Right,""}); + keyPress(XK_Right,""); EXPECT_EQ(3,selectedCol); - keyPress({XK_Down,""}); + keyPress(XK_Down,""); EXPECT_EQ(1,selectedRow); // selectedRow = 0 from initial tab press - keyPress({XK_Tab,""}); + keyPress(XK_Tab,""); EXPECT_EQ(0,selectedCol); - keyPress({XK_Left,""}); + keyPress(XK_Left,""); EXPECT_EQ(3,selectedCol); EXPECT_EQ(1,selectedRow); - keyPress({XK_Right,""}); + keyPress(XK_Right,""); EXPECT_EQ(0,selectedCol); // Moved down one row EXPECT_EQ(2,selectedRow); - keyPress({XK_ISO_Left_Tab,""}); + keyPress(XK_ISO_Left_Tab,""); EXPECT_EQ(3,selectedCol); - keyPress({XK_ISO_Left_Tab,""}); + keyPress(XK_ISO_Left_Tab,""); EXPECT_EQ(2,selectedCol); EXPECT_EQ(1,selectedRow); - keyPress({XK_Right,""}); + keyPress(XK_Right,""); EXPECT_EQ(3,selectedCol); EXPECT_EQ(1,selectedRow); - keyPress({XK_Tab,""}); // check wrap around + keyPress(XK_Tab,""); // check wrap around EXPECT_EQ(0,selectedCol); EXPECT_EQ(2,selectedRow); @@ -1529,43 +1525,43 @@ TEST_F(GodleyTableWindowFixture, keyPress) selectIdx=0; insertIdx=1; cminsky().clipboard.putClipboard(""); - keyPress({XK_Control_L,""}); keyPress({'c',"\x3"}); //copy + keyPress(XK_Control_L,""); keyPress('c',"\x3"); //copy EXPECT_EQ("a",cminsky().clipboard.getClipboard()); cminsky().clipboard.putClipboard(""); - keyPress({XK_Control_L,""}); keyPress({'x',"\x18"}); //cut + keyPress(XK_Control_L,""); keyPress('x',"\x18"); //cut EXPECT_EQ("a",cminsky().clipboard.getClipboard()); EXPECT_EQ("bc",godleyIcon().table.cell(1,1)); - keyPress({XK_Control_L,""}); keyPress({'v',"\x16"}); //paste + keyPress(XK_Control_L,""); keyPress('v',"\x16"); //paste EXPECT_EQ("abc",godleyIcon().table.cell(1,1)); // initial cell movement when nothing selected selectedCol=-1; selectedRow=-1; - keyPress({XK_Tab,""}); + keyPress(XK_Tab,""); EXPECT_EQ(1,selectedCol); EXPECT_EQ(0,selectedRow); selectedCol=-1; selectedRow=-1; - keyPress({XK_ISO_Left_Tab,""}); + keyPress(XK_ISO_Left_Tab,""); EXPECT_EQ(3,selectedCol); EXPECT_EQ(2,selectedRow); selectedCol=-1; selectedRow=-1; - keyPress({XK_Left,""}); + keyPress(XK_Left,""); EXPECT_EQ(3,selectedCol); EXPECT_EQ(0,selectedRow); selectedCol=-1; selectedRow=-1; - keyPress({XK_Right,""}); + keyPress(XK_Right,""); EXPECT_EQ(1,selectedCol); EXPECT_EQ(0,selectedRow); selectedCol=-1; selectedRow=-1; - keyPress({XK_Down,""}); + keyPress(XK_Down,""); EXPECT_EQ(0,selectedCol); EXPECT_EQ(2,selectedRow); // Initial Conditions cell cannot be selected. For ticket 1064 selectedCol=-1; selectedRow=-1; - keyPress({XK_Up,""}); + keyPress(XK_Up,""); EXPECT_EQ(0,selectedCol); EXPECT_EQ(2,selectedRow); @@ -1573,9 +1569,7 @@ TEST_F(GodleyTableWindowFixture, keyPress) TEST_F(GodleyTableWindowFixture, addDelVars) { - surface.reset(new ecolab::cairo::Surface - (cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,NULL))); - redraw(0,0,0,0); + draw(mans); double x=colLeftMargin[1]+10, y=topTableOffset+5+rowHeight; EXPECT_EQ(1,colX(x)); EXPECT_EQ(1,rowY(y)); @@ -1640,10 +1634,9 @@ TEST_F(ModelSuite, copyBetweenCols) godley1->update(); godley2->update(); - GodleyTableWindow gw(*godley1); + GodleyTableEditor gw(*godley1); // render GodleyTableWindow to compute column/row boundaries - ecolab::cairo::Surface surf(cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,nullptr)); - gw.draw(surf.cairo()); + gw.draw(mans); // positions of the 2,1 and 2,2 cells double x1=gw.colLeftMargin[1]+5, x2=gw.colLeftMargin[2]+5, y=2*gw.rowHeight+gw.topTableOffset; EXPECT_EQ(1,gw.colXZoomed(x1)); diff --git a/test/testPlotWidget.cc b/test/testPlotWidget.cc index 5c55b64a0..427d6a475 100644 --- a/test/testPlotWidget.cc +++ b/test/testPlotWidget.cc @@ -17,6 +17,7 @@ along with Minsky. If not, see . */ #include "cairoItems.h" +#include "cairo_base.h" #include "lasso.h" #include "plotWidget.h" #include "minsky.h" @@ -34,8 +35,46 @@ namespace minsky { class PlotWidgetTest : public PlotWidget, public ::testing::Test { + public: + std::unique_ptr mansPtr{mansoura::makeRecordingContext()}; + mansoura::IMansoura& mans{*mansPtr}; }; + TEST_F(PlotWidgetTest, drawWithTitleAndLegend) + { + title="A title"; + xlabel("x"); + legend=true; + addPt(0,0.0,1.0); + addPt(0,1.0,0.0); + mouseFocus=true; + selected=true; + EXPECT_NO_THROW(draw(mans)); + } + + TEST_F(PlotWidgetTest, legendSizeFromCache) + { + legend=true; + addPt(0,0.0,1.0); + addPt(0,1.0,0.0); + labelPen(0,"a legend label"); + double xoffs, yoffs, w, h, cw, ch; + // nothing measured yet, so unknown width, but height is computable + legendSizeFromCache(xoffs, yoffs, cw, ch, iWidth(), iHeight()-10); + EXPECT_EQ(0, cw); + EXPECT_GT(ch, 0); + legendSize(mans, xoffs, yoffs, w, h, iWidth(), iHeight()-10); + EXPECT_GT(w, 0); + // cached estimate at the measured size is exact... + legendSizeFromCache(xoffs, yoffs, cw, ch, iWidth(), iHeight()-10); + EXPECT_DOUBLE_EQ(w, cw); + EXPECT_DOUBLE_EQ(h, ch); + // ...and approximately right at a different size + legendSize(mans, xoffs, yoffs, w, h, 2*iWidth(), 2*(iHeight()-10)); + legendSizeFromCache(xoffs, yoffs, cw, ch, 2*iWidth(), 2*(iHeight()-10)); + EXPECT_NEAR(w, cw, 0.01*w); + } + TEST_F(PlotWidgetTest, legendMove) { legend=true; @@ -46,7 +85,7 @@ namespace minsky labelPen(0,"hello"); labelPen(1,"hello"); double xoffs, yoffs, legendWidth, legendHeight; - legendSize(xoffs, yoffs, legendWidth, legendHeight, iWidth(), iHeight()-10); + legendSize(mans, xoffs, yoffs, legendWidth, legendHeight, iWidth(), iHeight()-10); double x=(legendLeft-0.5)*iWidth() +0.5*legendWidth; double y=(0.5-legendTop)*iHeight() + 0.5*legendHeight; EXPECT_EQ(ClickType::legendMove, clickType(x,y)); @@ -57,7 +96,7 @@ namespace minsky EXPECT_NEAR(oldLegendTop-20/(iHeight()-10),legendTop,0.01); // legend should not change size double newLegendWidth, newLegendHeight; - legendSize(xoffs, yoffs, newLegendWidth, newLegendHeight, iWidth(), iHeight()-10); + legendSize(mans, xoffs, yoffs, newLegendWidth, newLegendHeight, iWidth(), iHeight()-10); EXPECT_NEAR(legendWidth,newLegendWidth, 0.01); EXPECT_NEAR(legendHeight,newLegendHeight,0.01); } @@ -72,7 +111,7 @@ namespace minsky labelPen(0,"hello"); labelPen(1,"hello"); double xoffs, yoffs, legendWidth, legendHeight; - legendSize(xoffs, yoffs, legendWidth, legendHeight, iWidth(), iHeight()-10); + legendSize(mans, xoffs, yoffs, legendWidth, legendHeight, iWidth(), iHeight()-10); double x=(legendLeft-0.5)*iWidth() +0.5*legendWidth; double y=(0.5-legendTop)*iHeight() + 0.95*legendHeight; EXPECT_EQ(ClickType::legendResize, clickType(x,y)); @@ -83,7 +122,7 @@ namespace minsky EXPECT_NEAR(oldLegendLeft,legendLeft, 0.01); EXPECT_NEAR(oldLegendTop,legendTop,0.01); double newLegendWidth, newLegendHeight; - legendSize(xoffs, yoffs, newLegendWidth, newLegendHeight, iWidth(), iHeight()-10); + legendSize(mans, xoffs, yoffs, newLegendWidth, newLegendHeight, iWidth(), iHeight()-10); // width change will be proportionate - just check the new height is about right EXPECT_NEAR(legendHeight+20,newLegendHeight,2); } diff --git a/test/testSheet.cc b/test/testSheet.cc index 4d69a973e..6de8a7e2a 100644 --- a/test/testSheet.cc +++ b/test/testSheet.cc @@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License along with Minsky. If not, see . */ +#include "mansouraCairo.h" #include "sheet.h" #include "minsky.h" #include "minsky_epilogue.h" @@ -190,4 +191,25 @@ namespace // Check that sliceIndicator is set to something useful EXPECT_FALSE(sheet.setSliceIndicator().empty()); } + + TEST_F(SheetTest, draw) + { + cairo::Surface surf(cairo_recording_surface_create(CAIRO_CONTENT_COLOR, nullptr)); + const mansoura::MansouraCairo shim(surf.cairo()); + // unconnected sheet + EXPECT_NO_THROW(draw(shim)); + + for (const char* init: {"1","rand(3)","rand(3,3)","rand(3,3,3)"}) + { + minsky::minsky().clearAllMaps(); + minsky::minsky().canvas.addVariable("v",VariableType::parameter); + auto& param=*minsky::minsky().canvas.itemFocus->variableCast(); + param.init(init); + minsky::minsky().canvas.addSheet(); + auto& sheet=dynamic_cast(*minsky::minsky().canvas.itemFocus); + minsky::minsky().model->addWire(param, sheet, 0); + minsky::minsky().reset(); + EXPECT_NO_THROW(sheet.draw(shim)) << init; + } + } }