From 9be49bc9da16fa2e4b253325ff7ce664a95dbde7 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Mon, 31 Aug 2026 09:25:01 +1000 Subject: [PATCH 01/23] WIP: switching to dell laptop. --- .gitmodules | 3 + Makefile | 14 ++- engine/cairoShimCairo.cc | 198 ------------------------------------- engine/cairoShimCairo.h | 90 ----------------- mansoura | 1 + model/ICairoShim.h | 161 ------------------------------ model/SVGItem.h | 65 ------------ model/cairoItems.cc | 10 +- model/cairoItems.h | 10 +- model/canvas.cc | 66 ++++++------- model/dataOp.h | 2 +- model/fontDisplay.h | 10 +- model/godleyIcon.cc | 11 ++- model/godleyIcon.h | 4 +- model/godleyTableWindow.cc | 24 ++--- model/godleyTableWindow.h | 11 ++- model/group.cc | 11 ++- model/group.h | 4 +- model/intOp.cc | 6 +- model/intOp.h | 2 +- model/item.cc | 25 +++-- model/item.h | 16 +-- model/lock.cc | 2 +- model/lock.h | 6 +- model/minsky.h | 2 +- model/operation.cc | 6 +- model/operation.h | 8 +- model/operationBase.h | 10 +- model/phillipsDiagram.cc | 17 ++-- model/phillipsDiagram.h | 4 +- model/plotWidget.cc | 2 +- model/plotWidget.h | 2 +- model/pubTab.cc | 2 +- model/ravelWrap.cc | 2 +- model/ravelWrap.h | 4 +- model/sheet.cc | 2 +- model/sheet.h | 4 +- model/switchIcon.cc | 2 +- model/switchIcon.h | 2 +- model/userFunction.h | 4 +- model/variable.cc | 2 +- model/variable.h | 11 +-- model/variablePane.cc | 2 +- model/wire.cc | 2 +- model/wire.h | 4 +- test/testLock.cc | 1 - test/testModel.cc | 1 - 47 files changed, 170 insertions(+), 678 deletions(-) delete mode 100644 engine/cairoShimCairo.cc delete mode 100644 engine/cairoShimCairo.h create mode 160000 mansoura delete mode 100644 model/ICairoShim.h delete mode 100644 model/SVGItem.h diff --git a/.gitmodules b/.gitmodules index ae417d0bd..9f6e8e8a7 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 = git@github.com:highperformancecoder/mansoura.git diff --git a/Makefile b/Makefile index cf71c26f8..73a9b8251 100644 --- a/Makefile +++ b/Makefile @@ -99,6 +99,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) >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) @@ -183,7 +191,7 @@ PREFIX=/usr/local # 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 grid.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 variablePane.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 \ +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 \ @@ -229,7 +237,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 @@ -345,7 +353,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 diff --git a/engine/cairoShimCairo.cc b/engine/cairoShimCairo.cc deleted file mode 100644 index 2c19d9489..000000000 --- a/engine/cairoShimCairo.cc +++ /dev/null @@ -1,198 +0,0 @@ -#include "cairoShimCairo.h" -#include "minsky_epilogue.h" -#define CAIRO_WIN32_STATIC_BUILD -#include -#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/mansoura b/mansoura new file mode 160000 index 000000000..ea171f7d3 --- /dev/null +++ b/mansoura @@ -0,0 +1 @@ +Subproject commit ea171f7d3d6d607153140639bdd9db3e1e4c7a10 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.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..207022ad6 100644 --- a/model/cairoItems.cc +++ b/model/cairoItems.cc @@ -28,7 +28,7 @@ #include "minsky.h" #include "cairoItems.h" -#include "cairoShimCairo.h" +#include "mansouraCairo.h" #include "operation.h" #include "latexMarkup.h" #include @@ -39,7 +39,7 @@ #include using namespace ecolab; -using ecolab::cairo::CairoSave; +using namespace mansoura; using namespace std; using namespace minsky; using namespace boost::geometry; @@ -48,10 +48,10 @@ 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()); + MansouraCairo 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; @@ -127,7 +127,7 @@ void minsky::drawTriangle } 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 cairo::Colour& col, double angle) { cairoShim.save(); cairoShim.newPath(); diff --git a/model/cairoItems.h b/model/cairoItems.h index 712e559ec..3eb5286c8 100644 --- a/model/cairoItems.h +++ b/model/cairoItems.h @@ -20,9 +20,9 @@ #define CAIRO_ITEMS_H #include #include -#include #include #include +#include "IMansoura.h" #include "operation.h" #include "variable.h" @@ -34,14 +34,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 @@ -60,6 +60,6 @@ namespace minsky }; 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 ecolab::cairo::Colour& col, double angle=0); } #endif diff --git a/model/canvas.cc b/model/canvas.cc index ed2f2ce21..ab7ed1dbe 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 { @@ -836,10 +837,12 @@ namespace minsky } 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); + MansouraCairo mans(cairo); + + const PreserveContext cs(mans); + 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) @@ -848,13 +851,12 @@ namespace minsky if (it.visible() && updateRegion.intersects(it)) { didDrawSomething = true; - const CairoSave cs(cairo); - cairo_identity_matrix(cairo); - cairo_translate(cairo,it.x(), it.y()); + const PreserveContext cs(mans); + mans.identityMatrix(); + mans.translate(it.x(), it.y()); try { - CairoShimCairo shim(cairo); - it.draw(shim); + it.draw(mans); } catch (const std::exception& ex) { @@ -872,12 +874,11 @@ namespace minsky if (it.visible() && updateRegion.intersects(it)) { didDrawSomething = true; - const CairoSave cs(cairo); + const PreserveContext cs(mans); cairo_identity_matrix(cairo); cairo_translate(cairo,it.x(), it.y()); { - CairoShimCairo shim(cairo); - it.draw(shim); + it.draw(mans); } } return false; @@ -890,8 +891,7 @@ namespace minsky { const Wire& w=**i; if (w.visible()) { - CairoShimCairo shim(cairo); - w.draw(shim); + w.draw(mans); } return false; }); @@ -899,34 +899,34 @@ namespace minsky if (fromPort.get()) // we're in process of creating a wire { didDrawSomething = true; - cairo_move_to(cairo,fromPort->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(); 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/fontDisplay.h b/model/fontDisplay.h index 0f00b72d8..655f69148 100644 --- a/model/fontDisplay.h +++ b/model/fontDisplay.h @@ -20,8 +20,8 @@ #ifndef FONTDISPLAY_H #define FONTDISPLAY_H #include "renderNativeWindow.h" +#include "mansouraCairo.h" #include "classdesc_access.h" -#include namespace minsky { @@ -29,11 +29,9 @@ namespace minsky 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(); + mansoura::MansouraCairo mans(surface->cairo()); + mans.moveTo(0,0); + mans.showPlainText("←→↑↓—▼αΣ∫√⊗≤",10); return true; } CLASSDESC_ACCESS(FontDisplay); diff --git a/model/godleyIcon.cc b/model/godleyIcon.cc index 7661d5f0b..6dd71fc97 100644 --- a/model/godleyIcon.cc +++ b/model/godleyIcon.cc @@ -27,13 +27,14 @@ #include #include #include -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "godleyIcon.rcd" #include "itemT.rcd" #include "godleyTableWindow.xcd" #include "minsky_epilogue.h" #include using namespace boost::locale::conv; +using namespace mansoura; using namespace ecolab::cairo; using namespace ecolab; using namespace std; @@ -53,9 +54,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 @@ -452,7 +453,7 @@ namespace minsky return r; } - void GodleyIcon::draw(const ICairoShim& cairoShim) const + void GodleyIcon::draw(const mansoura::IMansoura& cairoShim) const { positionVariables(); const float z=zoomFactor()*scaleFactor(); @@ -495,7 +496,7 @@ namespace minsky { cairoShim.save(); 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(); diff --git a/model/godleyIcon.h b/model/godleyIcon.h index 69e52604a..dd566ae7b 100644 --- a/model/godleyIcon.h +++ b/model/godleyIcon.h @@ -59,7 +59,7 @@ namespace minsky double titleOffs() const {return !table.title.empty()? 15*zoomFactor(): 0;} 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; @@ -137,7 +137,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; diff --git a/model/godleyTableWindow.cc b/model/godleyTableWindow.cc index f726ede34..1aa23b4b9 100644 --- a/model/godleyTableWindow.cc +++ b/model/godleyTableWindow.cc @@ -20,7 +20,7 @@ #include "cairoItems.h" #include "minsky.h" #include "godleyTableWindow.h" -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "selection.h" #include "latexMarkup.h" #include @@ -34,7 +34,7 @@ using namespace std; using namespace minsky; -using ecolab::Pango; +using namespace mansoura; using namespace ecolab::cairo; using namespace boost::locale::conv; @@ -60,11 +60,11 @@ namespace {.6,.5,0} }; - void showAsset(Pango& pango, cairo_t* cairo, GodleyAssetClass::AssetClass assetClass) + void showAsset(ICacheRender& pango, 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 +154,11 @@ namespace minsky return m_godleyIcon.table.cellInTable(selectedRow, selectedCol); } - void GodleyTableEditor::draw(cairo_t *cairo) + void GodleyTableEditor::drawCairo(cairo_t* cairo) { - const CairoSave cs(cairo); + const ecolab::CairoSave cs(cairo); cairo_scale(cairo,zoomFactor,zoomFactor); - Pango pango(cairo); + ecolab::Pango pango(cairo); pango.setMarkup("Flows ↓ / Stock Vars →"); rowHeight=pango.height()+2; const double tableHeight=(m_godleyIcon.table.rows()-scrollRowStart+1)*rowHeight; @@ -1221,15 +1221,15 @@ namespace { } template - void ButtonWidget::draw(const ICairoShim& cairoShim) + void ButtonWidget::draw(const mansoura::IMansoura& cairoShim) { - auto& shimImpl = dynamic_cast(cairoShim); + auto& shimImpl = dynamic_cast(cairoShim); draw(shimImpl._internalGetCairoContext()); } - void GodleyTableEditor::draw(const ICairoShim& cairoShim) + void GodleyTableEditor::draw(const mansoura::IMansoura& cairoShim) { - auto& shimImpl = dynamic_cast(cairoShim); + auto& shimImpl = dynamic_cast(cairoShim); draw(shimImpl._internalGetCairoContext()); } diff --git a/model/godleyTableWindow.h b/model/godleyTableWindow.h index 388dcf960..3b1bedfcf 100644 --- a/model/godleyTableWindow.h +++ b/model/godleyTableWindow.h @@ -25,7 +25,7 @@ #define GODLEYTABLEWINDOW_H #include "assetClass.h" #include "godleyTable.h" -#include "ICairoShim.h" +#include "IMansoura.h" #include "renderNativeWindow.h" #include #include @@ -55,7 +55,7 @@ namespace minsky 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, double r, double g, double b, int idx); @@ -85,6 +85,8 @@ namespace minsky drawButtons=true; leftTableOffset=4*ButtonWidget::buttonSpacing; topTableOffset=30;adjustWidgets(); } + protected: + void drawCairo(cairo_t* cairo); public: static constexpr double columnButtonsOffset=12; /// offset of the table within the window @@ -124,8 +126,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; @@ -225,7 +226,7 @@ namespace minsky protected: bool redraw(int, int, int width, int height) override { if (surface.get()) { - draw(surface->cairo()); + drawCairo(surface->cairo()); return true; } return false; diff --git a/model/group.cc b/model/group.cc index 26db812d6..e2e63aeb5 100644 --- a/model/group.cc +++ b/model/group.cc @@ -25,7 +25,7 @@ #include "autoLayout.h" #include "equations.h" #include -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "group.rcd" #include "itemT.rcd" #include "bookmark.rcd" @@ -33,6 +33,7 @@ #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 +928,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(); @@ -952,7 +953,7 @@ namespace minsky // display I/O region in grey // drawIORegion needs cairo_t* for now - auto& shimImpl = dynamic_cast(cairoShim); + auto& shimImpl = dynamic_cast(cairoShim); cairo_t* cairo = shimImpl._internalGetCairoContext(); drawIORegion(cairo); @@ -1000,7 +1001,7 @@ namespace minsky { cairoShim.rectangle(0, 0,width, height); cairoShim.clip(); - // Render SVG using ICairoShim abstraction + // Render SVG using mansoura::IMansoura abstraction cairoShim.renderSVG(svgRenderer, width, height); } } @@ -1104,7 +1105,7 @@ namespace minsky // cairo context is already rotated, so antirotate cairo_rotate(cairo,-angle); { - CairoShimCairo shim(cairo); + MansouraCairo shim(cairo); v->draw(shim); } diff --git a/model/group.h b/model/group.h index eb276ec51..e2ce18706 100644 --- a/model/group.h +++ b/model/group.h @@ -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,7 +268,7 @@ 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; diff --git a/model/intOp.cc b/model/intOp.cc index 6d243852e..9510918f8 100644 --- a/model/intOp.cc +++ b/model/intOp.cc @@ -19,12 +19,14 @@ #include "minsky.h" #include "cairoItems.h" -#include "cairoShimCairo.h" +#include "mansouraCairo.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 +37,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 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..323b837fe 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,7 +28,7 @@ #include "geometry.h" #include "selection.h" #include "lasso.h" -#include +#include #include #include "item.rcd" #include "noteBase.rcd" @@ -37,8 +37,7 @@ #include "minsky_epilogue.h" #include -using ecolab::Pango; -using ecolab::cairo::CairoSave; +using namespace mansoura; using namespace std; namespace minsky @@ -61,7 +60,7 @@ namespace minsky { const cairo::CairoSave cs(surf.cairo()); cairo_rotate(surf.cairo(),-x.rotation()*M_PI/180); - CairoShimCairo shim(surf.cairo()); + MansouraCairo shim(surf.cairo()); x.draw(shim); } #ifndef NDEBUG @@ -293,7 +292,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 +307,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 +316,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 +344,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 +356,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); @@ -396,11 +395,11 @@ namespace minsky void Item::dummyDraw() const { const ecolab::cairo::Surface s(cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,NULL)); - CairoShimCairo shim(s.cairo()); + MansouraCairo shim(s.cairo()); 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..6d124e9cd 100644 --- a/model/item.h +++ b/model/item.h @@ -26,7 +26,7 @@ #include "geometry.h" #include "str.h" #include "polyRESTProcessBase.h" -#include "ICairoShim.h" +#include "IMansoura.h" #include @@ -161,7 +161,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 +287,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 +299,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 +308,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 +361,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..4ef8ba8ee 100644 --- a/model/lock.cc +++ b/model/lock.cc @@ -27,7 +27,7 @@ #include "lock.rcd" #include "lock.xcd" #include "minsky.h" -#include "cairoShimCairo.h" +#include "mansouraCairo.h" #include "minsky_epilogue.h" using namespace std; diff --git a/model/lock.h b/model/lock.h index fc415c19c..635a216b4 100644 --- a/model/lock.h +++ b/model/lock.h @@ -39,9 +39,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.h b/model/minsky.h index e1c3cd97a..e5009ec33 100644 --- a/model/minsky.h +++ b/model/minsky.h @@ -220,7 +220,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 diff --git a/model/operation.cc b/model/operation.cc index 527556ba0..af6c309f9 100644 --- a/model/operation.cc +++ b/model/operation.cc @@ -27,7 +27,7 @@ #include #include -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "minsky_epilogue.h" #include @@ -38,7 +38,7 @@ #endif using namespace ecolab; -using ecolab::cairo::CairoSave; +using namespace mansoura; namespace minsky { @@ -149,7 +149,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 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..4ba49740f 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,7 +44,7 @@ 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: @@ -62,7 +60,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 +71,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/phillipsDiagram.cc b/model/phillipsDiagram.cc index 565ca0ab2..ca46c95ba 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); @@ -108,10 +109,10 @@ namespace minsky cairo_translate(cairo,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); + MansouraCairo shim(cairo); + const PreserveContext cs(shim); + mans.identityMatrix(); + mans.translate(i.second.x()+x, i.second.y()+y); i.second.draw(shim); } for (auto& i: flows) diff --git a/model/phillipsDiagram.h b/model/phillipsDiagram.h index 4c3ceba8d..b67bf08e5 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,7 +70,7 @@ 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 diff --git a/model/plotWidget.cc b/model/plotWidget.cc index d52b3a814..8f9443eb8 100644 --- a/model/plotWidget.cc +++ b/model/plotWidget.cc @@ -26,7 +26,7 @@ #include #include #include -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "CSVTools.xcd" #include "itemT.rcd" diff --git a/model/plotWidget.h b/model/plotWidget.h index 235380daf..bfe790d65 100644 --- a/model/plotWidget.h +++ b/model/plotWidget.h @@ -167,7 +167,7 @@ namespace minsky void connectVar(const std::shared_ptr& var, unsigned port); void disconnectAllVars(); using ecolab::Plot::draw; - void draw(const ICairoShim& cairoShim) const override; + 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);} diff --git a/model/pubTab.cc b/model/pubTab.cc index 280350282..9e8fb570c 100644 --- a/model/pubTab.cc +++ b/model/pubTab.cc @@ -21,7 +21,7 @@ #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" diff --git a/model/ravelWrap.cc b/model/ravelWrap.cc index 99f92fba2..cb5183497 100644 --- a/model/ravelWrap.cc +++ b/model/ravelWrap.cc @@ -24,7 +24,7 @@ #include "dimension.h" #include "minskyTensorOps.h" #include "pango.h" -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "capiRenderer.xcd" #include "CSVTools.xcd" diff --git a/model/ravelWrap.h b/model/ravelWrap.h index 6b322a26e..32e5e891c 100644 --- a/model/ravelWrap.h +++ b/model/ravelWrap.h @@ -84,7 +84,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 +110,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/sheet.cc b/model/sheet.cc index 870c3fd10..5045c4b0f 100644 --- a/model/sheet.cc +++ b/model/sheet.cc @@ -24,7 +24,7 @@ #include "plotWidget.h" #include #include -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "itemT.rcd" #include "sheet.rcd" diff --git a/model/sheet.h b/model/sheet.h index ffb786a5a..2a85b1798 100644 --- a/model/sheet.h +++ b/model/sheet.h @@ -70,8 +70,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..7dd6e1828 100644 --- a/model/switchIcon.cc +++ b/model/switchIcon.cc @@ -21,7 +21,7 @@ #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; 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.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 b6e34dfe3..62d0b9118 100644 --- a/model/variable.cc +++ b/model/variable.cc @@ -18,7 +18,7 @@ */ #include "minsky.h" -#include "cairoShimCairo.h" +#include "mansouraCairo.h" #include "geometry.h" #include "valueId.h" #include "variable.h" diff --git a/model/variable.h b/model/variable.h index e8da8778d..5d0602564 100644 --- a/model/variable.h +++ b/model/variable.h @@ -38,11 +38,6 @@ #include "itemT.h" #include -namespace ecolab { - class Pango; - class Plot; -} - namespace minsky { class VariablePtr; @@ -65,8 +60,8 @@ namespace minsky protected: /// cached font rendering objects mutable std::shared_ptr cachedNameRender; - mutable std::shared_ptr cachedMantissa; - mutable std::shared_ptr cachedExponent; + mutable std::shared_ptr cachedMantissa; + mutable std::shared_ptr cachedExponent; mutable double cachedValue, cachedTime; public: VariableCaches()=default; @@ -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/variablePane.cc b/model/variablePane.cc index 59d31722b..fd0b0209a 100644 --- a/model/variablePane.cc +++ b/model/variablePane.cc @@ -20,7 +20,7 @@ #include "minsky.h" #include "variablePane.h" #include "cairoItems.h" -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "pannableTab.rcd" #include "pannableTab.xcd" #include "variableValue.h" diff --git a/model/wire.cc b/model/wire.cc index c54f7c0fe..b9445bdcc 100644 --- a/model/wire.cc +++ b/model/wire.cc @@ -28,7 +28,7 @@ #include "pango.h" #include "plotWidget.h" #include "SVGItem.h" -#include "../engine/cairoShimCairo.h" +#include "mansouraCairo.h" #include "wire.rcd" #include "minsky_epilogue.h" #include diff --git a/model/wire.h b/model/wire.h index 78889dc4c..f57a9c0f7 100644 --- a/model/wire.h +++ b/model/wire.h @@ -21,7 +21,7 @@ #include "noteBase.h" #include "intrusiveMap.h" -#include "ICairoShim.h" +#include "IMansoura.h" #include #include @@ -67,7 +67,7 @@ namespace minsky 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/test/testLock.cc b/test/testLock.cc index ad08292a0..a538d3cb0 100644 --- a/test/testLock.cc +++ b/test/testLock.cc @@ -17,7 +17,6 @@ along with Minsky. If not, see . */ -#include "cairoShimCairo.h" #include "lock.h" #include "minsky.h" #include "minsky_epilogue.h" diff --git a/test/testModel.cc b/test/testModel.cc index 1f7759599..e8afb3d0c 100644 --- a/test/testModel.cc +++ b/test/testModel.cc @@ -18,7 +18,6 @@ */ #include "cairoItems.h" -#include "cairoShimCairo.h" #include "operation.h" #include "group.h" #include "minsky.h" From 2f9945d94ae5b319961f7698291c4de3e60f6255 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Fri, 16 Oct 2026 11:25:32 +1100 Subject: [PATCH 02/23] refactor: Finished Mansoura integration. Regression suite now passing. --- RESTService/pyminsky.cc | 4 + RESTService/typescriptAPI.cc | 7 +- createLinkGroupIcons.cc | 11 +- gui-js/libs/shared/src/lib/backend/minsky.ts | 177 +++++++++---------- model/canvas.cc | 32 ++-- model/godleyIcon.cc | 15 +- model/godleyTableWindow.cc | 5 +- model/minsky.cc | 5 + model/plotWidget.cc | 9 +- model/variable.cc | 21 +-- schema/schema0.cc | 1 - schema/schema0.h | 4 +- test/Makefile | 5 +- test/testCanvas.cc | 2 +- test/testLock.cc | 2 +- test/testModel.cc | 40 +++-- test/testPlotWidget.cc | 14 +- 17 files changed, 188 insertions(+), 166 deletions(-) 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 a90aadb28..0608b6e89 100644 --- a/RESTService/typescriptAPI.cc +++ b/RESTService/typescriptAPI.cc @@ -40,6 +40,7 @@ #include "itemT.tcd" #include "lasso.tcd" #include "lock.tcd" +#include "mansouraPlot.tcd" #include "noteBase.tcd" #include "operation.tcd" #include "operationBase.tcd" @@ -47,7 +48,6 @@ #include "pango.tcd" #include "pannableTab.tcd" #include "phillipsDiagram.tcd" -#include "plot.tcd" #include "plotOptions.tcd" #include "plotWidget.tcd" #include "polyRESTProcessBase.tcd" @@ -64,6 +64,7 @@ #include "simulation.tcd" #include "slider.tcd" #include "SVGItem.tcd" +#include "SVGItem.xcd" #include "switchIcon.tcd" #include "tensorInterface.tcd" #include "tensorVal.tcd" @@ -255,11 +256,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(); @@ -317,7 +318,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() { const double width=30, height=10; - mansoura::Plot plot; - for (int i=0; i {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,13 +160,13 @@ 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');} @@ -222,11 +222,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 +329,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);} @@ -396,7 +396,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 +411,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'); @@ -628,7 +628,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 +636,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'); } @@ -683,12 +683,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'); } @@ -724,7 +724,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') @@ -733,7 +733,7 @@ export class GodleyIcon extends Item { 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');} @@ -745,7 +745,7 @@ export class GodleyIcon extends Item { 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,7 +852,7 @@ 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');} @@ -905,13 +905,13 @@ export class GodleyTableEditor extends CppClass { } export class GodleyTableWindow extends CppClass { - backgroundColour: ecolab__cairo__Colour; + backgroundColour: mansoura__Colour; colLeftMargin: Sequence; 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.colLeftMargin=new Sequence(this.$prefix()+'.colLeftMargin'); this.item=new Item(this.$prefix()+'.item'); this.wire=new Wire(this.$prefix()+'.wire'); @@ -1016,7 +1016,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 +1030,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 +1076,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 draw(a1: mansoura__IMansoura): 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 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 +1244,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 +1269,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 +1299,7 @@ export class Minsky extends CppClass { evalGodley: EvalGodley; flowVars: Sequence; fontSampler: FontDisplay; - histogramResource: SVGRenderer; + histogramResource: mansoura__SVGRenderer; logVarList: Container; maxFlowValue: Map; maxValue: Map; @@ -1321,7 +1321,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'); @@ -1474,7 +1474,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; @@ -1484,7 +1484,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); @@ -1531,7 +1531,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');} } @@ -1547,16 +1547,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; @@ -1573,10 +1573,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'); @@ -1590,7 +1590,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');} @@ -1767,7 +1766,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) @@ -1777,7 +1776,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');} @@ -1792,7 +1791,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);} @@ -1861,12 +1860,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'); } @@ -1901,14 +1900,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; @@ -1917,7 +1908,7 @@ export class Selection extends CppClass { inVariables: Sequence; items: Sequence; outVariables: Sequence; - svgRenderer: SVGRenderer; + svgRenderer: mansoura__SVGRenderer; wires: Sequence; constructor(prefix: string){ super(prefix); @@ -1928,7 +1919,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);} @@ -1975,15 +1966,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 draw(a1: mansoura__IMansoura): 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 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');} @@ -2095,8 +2086,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);} @@ -2118,7 +2109,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');} @@ -2155,8 +2146,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');} @@ -2174,7 +2165,7 @@ export class VariableInstanceList extends CppClass { } export class VariablePane extends CppClass { - backgroundColour: ecolab__cairo__Colour; + backgroundColour: mansoura__Colour; bottomRowMargin: Sequence; item: Item; rightColMargin: Sequence; @@ -2182,7 +2173,7 @@ export class VariablePane extends CppClass { 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.bottomRowMargin=new Sequence(this.$prefix()+'.bottomRowMargin'); this.item=new Item(this.$prefix()+'.item'); this.rightColMargin=new Sequence(this.$prefix()+'.rightColMargin'); @@ -2454,11 +2445,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');} @@ -2467,14 +2468,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/model/canvas.cc b/model/canvas.cc index ab7ed1dbe..b4fb14672 100644 --- a/model/canvas.cc +++ b/model/canvas.cc @@ -839,7 +839,6 @@ namespace minsky auto cairo=surface()->cairo(); MansouraCairo mans(cairo); - const PreserveContext cs(mans); mans.rectangle(updateRegion.x0,updateRegion.y0,updateRegion.x1-updateRegion.x0,updateRegion.y1-updateRegion.y0); mans.clip(); mans.setLineWidth(1); @@ -849,20 +848,23 @@ namespace minsky { auto& it=**i; if (it.visible() && updateRegion.intersects(it)) - { - didDrawSomething = true; - const PreserveContext cs(mans); - mans.identityMatrix(); - mans.translate(it.x(), it.y()); - try - { - it.draw(mans); - } - catch (const std::exception& ex) - { - cerr << ex.what() << endl; - } - } + try + { + didDrawSomething = true; + MansouraCairo mans(cairo); + const PreserveContext cs(mans); + mans.identityMatrix(); + mans.translate(it.x(), it.y()); + it.draw(mans); + } + catch (const std::exception& ex) + { + cout<name(); + cout<(editor).zoomFactor=1; - const_cast(editor).draw(cairoShim); + const_cast(editor).draw(recorder); const_cast(editor).zoomFactor=min((w-leftMargin()-2*border*z)/surf.width(),(h-bottomMargin()-2*border*z-titleOffs())/surf.height()); const_cast(editor).draw(cairoShim); titley=-0.5*h; @@ -490,27 +490,24 @@ namespace minsky 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 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/godleyTableWindow.cc b/model/godleyTableWindow.cc index 82cc5f5aa..5b1b2efbf 100644 --- a/model/godleyTableWindow.cc +++ b/model/godleyTableWindow.cc @@ -177,7 +177,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()(this)->surface= + make_shared(cairo_recording_surface_create(CAIRO_CONTENT_COLOR,nullptr)); MansouraCairo mans(surface->cairo()); legendSize(mans, lx, ly, legendWidth, legendHeight, z*(iWidth()-2*portSpace), z*(iHeight()-portSpace-yoffs)); // xx & yy are in plot user coordinates @@ -863,3 +867,4 @@ namespace minsky } } CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::PlotWidget); +CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(mansoura::Plot); diff --git a/model/variable.cc b/model/variable.cc index 67b9116c2..28f22184a 100644 --- a/model/variable.cc +++ b/model/variable.cc @@ -85,16 +85,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); } diff --git a/schema/schema0.cc b/schema/schema0.cc index e3827f057..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 71ce1a463..77305e4e3 100644 --- a/schema/schema0.h +++ b/schema/schema0.h @@ -34,8 +34,8 @@ #include "variableType.h" #include "assetClass.h" #include -#include "plot.h" -#include "plot.xcd" +#include "mansouraPlot.h" +#include "mansouraPlot.xcd" namespace schema0 { diff --git a/test/Makefile b/test/Makefile index 2ad638f0f..a974bb75c 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 testGrid.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 testVariablePane.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/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 a538d3cb0..222426680 100644 --- a/test/testLock.cc +++ b/test/testLock.cc @@ -154,6 +154,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/testModel.cc b/test/testModel.cc index e8afb3d0c..1cae80790 100644 --- a/test/testModel.cc +++ b/test/testModel.cc @@ -27,17 +27,37 @@ #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) { @@ -102,24 +122,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()) {} - }; - } @@ -1641,8 +1644,7 @@ TEST_F(ModelSuite, copyBetweenCols) GodleyTableWindow 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..9c6710350 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,6 +35,11 @@ namespace minsky { class PlotWidgetTest : public PlotWidget, public ::testing::Test { + public: + ecolab::cairo::SurfacePtr surf{ + std::make_shared(cairo_recording_surface_create(CAIRO_CONTENT_COLOR,nullptr))}; + mansoura::MansouraCairo mans{surf->cairo()}; + PlotWidgetTest() {surface=surf;} }; TEST_F(PlotWidgetTest, legendMove) @@ -46,7 +52,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 +63,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 +78,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 +89,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); } From 82b999924fa280248cc7e310ebf82215ae4bec1c Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Fri, 16 Oct 2026 12:31:30 +1100 Subject: [PATCH 03/23] bugfix: tests build compile failure --- ecolab | 2 +- mansoura | 2 +- model/plotWidget.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ecolab b/ecolab index a5ac164b7..5ddb1b8c6 160000 --- a/ecolab +++ b/ecolab @@ -1 +1 @@ -Subproject commit a5ac164b77bf25b24aa12678d23b522b20aa6f37 +Subproject commit 5ddb1b8c6b2ee0e550cf63ded5a24a85a1fe03c5 diff --git a/mansoura b/mansoura index ea171f7d3..3b5e88546 160000 --- a/mansoura +++ b/mansoura @@ -1 +1 @@ -Subproject commit ea171f7d3d6d607153140639bdd9db3e1e4c7a10 +Subproject commit 3b5e88546458e37e26e759afc3c803f452e4fc52 diff --git a/model/plotWidget.h b/model/plotWidget.h index 6c754afd7..5a131c67f 100644 --- a/model/plotWidget.h +++ b/model/plotWidget.h @@ -24,6 +24,7 @@ #include "latexMarkup.h" #include "mansouraPlot.h" #include "mansouraPlot.cd" +#include "mansouraPlot.xcd" #include "variable.h" #include "variableValue.h" #include "zoom.h" From 30503fb3dbbd42c6b87c89710fb4f6848109b6c5 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Fri, 16 Oct 2026 18:44:26 +1100 Subject: [PATCH 04/23] refactor: Sheet now use IMansoura completely. For GH #697. --- model/sheet.cc | 178 ++++++++++++++++++++++------------------------ model/sheet.h | 1 - test/testSheet.cc | 21 ++++++ 3 files changed, 108 insertions(+), 92 deletions(-) diff --git a/model/sheet.cc b/model/sheet.cc index 96163b190..eb95fb1b3 100644 --- a/model/sheet.cc +++ b/model/sheet.cc @@ -22,9 +22,6 @@ #include "lasso.h" #include "minsky.h" #include "plotWidget.h" -#include -#include -#include "mansouraCairo.h" #include "itemT.rcd" #include "sheet.rcd" @@ -271,59 +268,64 @@ void Sheet::computeValue() namespace { - /// A pango that clips text to a standard area suitable for numbers - struct ClippedPango: public ecolab::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): ecolab::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 { - MansouraCairo 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 +333,8 @@ void Sheet::draw(cairo_t* cairo) const try { if (!value || !m_ports[0] || m_ports[0]->numWires()==0) return; - ecolab::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 +344,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 +354,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 +385,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 +428,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 +470,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 +482,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 +507,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 IMansoura& 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 2a85b1798..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(); diff --git a/test/testSheet.cc b/test/testSheet.cc index 4d69a973e..a0e3ee8ca 100644 --- a/test/testSheet.cc +++ b/test/testSheet.cc @@ -190,4 +190,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; + } + } } From 335d524e91abc76dc6b35c55da2a30c233ad7796 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Sat, 17 Oct 2026 09:58:27 +1100 Subject: [PATCH 05/23] refactor: Variable now is independent of Cairo. For GH #698. --- mansoura | 2 +- model/variable.cc | 9 +++------ model/variable.h | 1 - 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/mansoura b/mansoura index 3b5e88546..76608f245 160000 --- a/mansoura +++ b/mansoura @@ -1 +1 @@ -Subproject commit 3b5e88546458e37e26e759afc3c803f452e4fc52 +Subproject commit 76608f2454ec07c9fb338e12b004fa4319ff130a diff --git a/model/variable.cc b/model/variable.cc index 28f22184a..5175430da 100644 --- a/model/variable.cc +++ b/model/variable.cc @@ -18,7 +18,6 @@ */ #include "minsky.h" -#include "mansouraCairo.h" #include "geometry.h" #include "valueId.h" #include "variable.h" @@ -727,9 +726,7 @@ void VariableBase::draw(const IMansoura& 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); @@ -841,7 +838,7 @@ void VariableBase::draw(const IMansoura& 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 IMansoura& 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 09dd63897..14888daa6 100644 --- a/model/variable.h +++ b/model/variable.h @@ -36,7 +36,6 @@ #include #include "variableType.h" #include "itemT.h" -#include #include "mansouraPlot.h" namespace minsky From f61a3f03909b2af21e5c4c76b256d52266527121 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Sat, 17 Oct 2026 13:00:05 +1100 Subject: [PATCH 06/23] refactor: PlotWidget::draw no longer reference cairo stuff. For GH #700. --- model/plotWidget.cc | 93 +++++++++++++++++++----------------------- model/plotWidget.h | 1 - test/testPlotWidget.cc | 12 ++++++ 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/model/plotWidget.cc b/model/plotWidget.cc index 8496d6aac..10dd44bab 100644 --- a/model/plotWidget.cc +++ b/model/plotWidget.cc @@ -21,7 +21,6 @@ #include "variable.h" #include "cairoItems.h" #include "latexMarkup.h" -#include "ecolab/include/pango.h" #include #include #include @@ -88,39 +87,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(); - ecolab::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; } @@ -133,7 +131,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]); } @@ -145,7 +143,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 @@ -154,7 +152,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 @@ -164,42 +162,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; - MansouraCairo mans(cairo); - Plot::draw(mans,gw,gh); + Plot::draw(cairoShim,gw,gh); if (mouseFocus && legend) { double width,height,x,y; - legendSize(mans,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 - mansoura::MansouraCairo cairoShim(cairo); if (mouseFocus) { drawPorts(cairoShim); @@ -209,20 +205,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 mansoura::IMansoura& cairoShim) const - { - // TODO: Implement properly without cairo_t* delegation - auto& shimImpl = dynamic_cast(cairoShim); - draw(shimImpl._internalGetCairoContext()); - } - void PlotWidget::scalePlot() { // set any scale overrides diff --git a/model/plotWidget.h b/model/plotWidget.h index 5a131c67f..752114920 100644 --- a/model/plotWidget.h +++ b/model/plotWidget.h @@ -80,7 +80,6 @@ namespace minsky bool clearPensOnLabelling=false; - void draw(cairo_t* cairoShim) const; public: using Item::x; using Item::y; diff --git a/test/testPlotWidget.cc b/test/testPlotWidget.cc index 9c6710350..0771810ba 100644 --- a/test/testPlotWidget.cc +++ b/test/testPlotWidget.cc @@ -42,6 +42,18 @@ namespace minsky PlotWidgetTest() {surface=surf;} }; + 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, legendMove) { legend=true; From fdbf9654b352ca63d11471502290e13a4de61fff Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Sat, 17 Oct 2026 18:39:38 +1100 Subject: [PATCH 07/23] Remove cairo dependency on legfend size calculation. For GH #700 --- model/plotWidget.cc | 8 ++------ test/testPlotWidget.cc | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/model/plotWidget.cc b/model/plotWidget.cc index 10dd44bab..91c280ea0 100644 --- a/model/plotWidget.cc +++ b/model/plotWidget.cc @@ -405,12 +405,8 @@ namespace minsky } double legendWidth, legendHeight, lx, ly; - // ensure there is a surface here to refer to - if (!surface) - const_cast(this)->surface= - make_shared(cairo_recording_surface_create(CAIRO_CONTENT_COLOR,nullptr)); - MansouraCairo mans(surface->cairo()); - legendSize(mans, 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; diff --git a/test/testPlotWidget.cc b/test/testPlotWidget.cc index 0771810ba..beb02efb6 100644 --- a/test/testPlotWidget.cc +++ b/test/testPlotWidget.cc @@ -54,6 +54,29 @@ namespace minsky 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; From 36c59c91801bfa3161401639ade252b67b7159c4 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Sun, 18 Oct 2026 18:40:35 +1100 Subject: [PATCH 08/23] refactor: migrate Group class to Mansoura. For GH #695. --- Makefile | 1 + gui-js/libs/shared/src/lib/backend/minsky.ts | 12 +-- mansoura | 2 +- model/group.cc | 89 +++++++++----------- model/group.h | 7 +- 5 files changed, 51 insertions(+), 60 deletions(-) diff --git a/Makefile b/Makefile index a0f30a82b..ea24098b1 100644 --- a/Makefile +++ b/Makefile @@ -535,6 +535,7 @@ 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 diff --git a/gui-js/libs/shared/src/lib/backend/minsky.ts b/gui-js/libs/shared/src/lib/backend/minsky.ts index f06d9d64e..ed2a7dcd3 100644 --- a/gui-js/libs/shared/src/lib/backend/minsky.ts +++ b/gui-js/libs/shared/src/lib/backend/minsky.ts @@ -1079,9 +1079,9 @@ export class Group extends Item { 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: mansoura__IMansoura): 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 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);} @@ -1969,9 +1969,9 @@ export class Selection extends CppClass { 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: mansoura__IMansoura): 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 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);} diff --git a/mansoura b/mansoura index 76608f245..ccdbb8680 160000 --- a/mansoura +++ b/mansoura @@ -1 +1 @@ -Subproject commit 76608f2454ec07c9fb338e12b004fa4319ff130a +Subproject commit ccdbb8680e5dfa1978fffaad5fd6c398545711d5 diff --git a/model/group.cc b/model/group.cc index 79f315f88..d30f39eb1 100644 --- a/model/group.cc +++ b/model/group.cc @@ -24,8 +24,6 @@ #include "operation.h" #include "autoLayout.h" #include "equations.h" -#include -#include "mansouraCairo.h" #include "group.rcd" #include "itemT.rcd" #include "bookmark.rcd" @@ -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(); @@ -1007,8 +1002,7 @@ namespace minsky 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); - { - MansouraCairo 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 06b729fae..57d615d58 100644 --- a/model/group.h +++ b/model/group.h @@ -31,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 @@ -272,13 +271,13 @@ namespace minsky 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; From d35efbecf1171f70cbc523a9cf7b114f7a3cef77 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Mon, 19 Oct 2026 08:40:48 +1100 Subject: [PATCH 09/23] refactor: IntOp, Operation and Wire now Cairo free. --- mansoura | 2 +- model/intOp.cc | 6 +-- model/operation.cc | 13 +---- model/operationBase.h | 1 - model/wire.cc | 115 +++++++++++++++--------------------------- model/wire.h | 4 -- 6 files changed, 47 insertions(+), 94 deletions(-) diff --git a/mansoura b/mansoura index ccdbb8680..f4013c176 160000 --- a/mansoura +++ b/mansoura @@ -1 +1 @@ -Subproject commit ccdbb8680e5dfa1978fffaad5fd6c398545711d5 +Subproject commit f4013c1768c00e52e7b1275a645ecd9e6ddb68d0 diff --git a/model/intOp.cc b/model/intOp.cc index f53457b45..4067b7db9 100644 --- a/model/intOp.cc +++ b/model/intOp.cc @@ -19,7 +19,6 @@ #include "minsky.h" #include "cairoItems.h" -#include "mansouraCairo.h" #include "intOp.h" #include "intOp.rcd" #include "itemT.rcd" @@ -127,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; @@ -164,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/operation.cc b/model/operation.cc index 6f2e7c64d..98339c898 100644 --- a/model/operation.cc +++ b/model/operation.cc @@ -25,9 +25,7 @@ #include "str.h" #include "cairoItems.h" -#include #include -#include "mansouraCairo.h" #include "minsky_epilogue.h" #include @@ -237,12 +235,6 @@ namespace minsky if (selected) drawSelected(cairoShim); } - void OperationBase::setCachedText(cairo_t* cairo, const std::string& text, double size) const - { - if (cachedPango && cairo==cachedPango->context()) return; - cachedPango=shared_ptr(MansouraCairo(cairo).cachedRender({text,size})); - } - void OperationBase::draw(const IMansoura& cairoShim) const { // if rotation is in 1st or 3rd quadrant, rotate as @@ -280,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. @@ -332,7 +323,7 @@ namespace minsky } cairoShim.newPath(); - clipPath.appendToCurrent(shimImpl._internalGetCairoContext()); + clipPath->appendToCurrent(cairoShim); cairoShim.clip(); if (selected) drawSelected(cairoShim); } diff --git a/model/operationBase.h b/model/operationBase.h index 4ba49740f..67fc47235 100644 --- a/model/operationBase.h +++ b/model/operationBase.h @@ -46,7 +46,6 @@ namespace minsky protected: 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; diff --git a/model/wire.cc b/model/wire.cc index dad1416db..21cbd6c88 100644 --- a/model/wire.cc +++ b/model/wire.cc @@ -25,10 +25,8 @@ #include "selection.h" #include "lasso.h" #include "operation.h" -#include "ecolab/include/pango.h" #include "plotWidget.h" #include "SVGItem.h" -#include "mansouraCairo.h" #include "wire.rcd" #include "minsky_epilogue.h" #include @@ -36,7 +34,6 @@ using namespace std; using namespace mansoura; -using ecolab::cairo::CairoSave; namespace minsky { @@ -345,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; @@ -377,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; @@ -392,7 +365,7 @@ namespace } else { - cairo_move_to(cairo, coords[0], coords[1]); + cairo.moveTo(coords[0], coords[1]); /** * @@ -424,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 ecolab::cairo::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 { @@ -473,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); @@ -496,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 IMansoura& 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 074c9a3ef..79efce3d2 100644 --- a/model/wire.h +++ b/model/wire.h @@ -27,7 +27,6 @@ #include #include #include "classdesc_access.h" -#include namespace minsky { @@ -51,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() {} @@ -64,8 +62,6 @@ 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 mansoura::IMansoura& cairoShim, bool reverseArrow=false) const; From 9bbbafe8128a8f301620e1c7d7209179a1132130 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Mon, 19 Oct 2026 09:33:43 +1100 Subject: [PATCH 10/23] refactor: abstract away cairo dependence in cairoItems. --- mansoura | 2 +- model/cairoItems.cc | 25 +------------------------ model/cairoItems.h | 3 --- 3 files changed, 2 insertions(+), 28 deletions(-) diff --git a/mansoura b/mansoura index f4013c176..b6d72160d 160000 --- a/mansoura +++ b/mansoura @@ -1 +1 @@ -Subproject commit f4013c1768c00e52e7b1275a645ecd9e6ddb68d0 +Subproject commit b6d72160d47431713a20749f8ae6157007f79a55 diff --git a/model/cairoItems.cc b/model/cairoItems.cc index 6d68bf18f..bb93a6c16 100644 --- a/model/cairoItems.cc +++ b/model/cairoItems.cc @@ -28,11 +28,9 @@ #include "minsky.h" #include "cairoItems.h" -#include "mansouraCairo.h" #include "operation.h" #include "latexMarkup.h" #include -#include #include "ravelWrap.xcd" #include "minsky_epilogue.h" @@ -43,13 +41,6 @@ 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)); - MansouraCairo dummyCairoShim(dummySurf.cairo()); -} - RenderVariable::RenderVariable(const VariableBase& var, const mansoura::IMansoura& shim): var(var), cairoShim(shim), m_context(cairoShim.context()) { @@ -89,7 +80,7 @@ RenderVariable::RenderVariable(const VariableBase& var, const mansoura::IMansour } RenderVariable::RenderVariable(const VariableBase& var): - RenderVariable(var, dummyCairoShim) {} + RenderVariable(var, measuringContext()) {} bool RenderVariable::inImage(float x, float y) { @@ -111,20 +102,6 @@ double RenderVariable::handlePos() const return 0; } -void minsky::drawTriangle -(cairo_t* cairo, double x, double y, const 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 mansoura::IMansoura& cairoShim, double x, double y, const Colour& col, double angle) { diff --git a/model/cairoItems.h b/model/cairoItems.h index 185a0812f..d3da8ffa2 100644 --- a/model/cairoItems.h +++ b/model/cairoItems.h @@ -20,8 +20,6 @@ #define CAIRO_ITEMS_H #include #include -#include -#include #include "IMansoura.h" #include "IMansoura.cd" #include "operation.h" @@ -60,7 +58,6 @@ namespace minsky void* context() const {return m_context;} }; - void drawTriangle(cairo_t* cairo, double x, double y, const mansoura::Colour& col, double angle=0); void drawTriangle(const mansoura::IMansoura& cairoShim, double x, double y, const mansoura::Colour& col, double angle=0); } #endif From 8e5c518fc54d52e9b8c014368bdd817a1eedf955 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Mon, 19 Oct 2026 11:26:15 +1100 Subject: [PATCH 11/23] refactor: RavelWrap to use Mansoura. --- RESTService/typescriptAPI.cc | 1 - gui-js/package-lock.json | 63 ------------------------ model/minskyCairoRenderer.h | 62 ------------------------ model/ravelRenderer.h | 92 ++++++++++++++++++++++++++++++++++++ model/ravelWrap.cc | 16 +++---- model/ravelWrap.h | 2 +- model/sheet.cc | 1 - 7 files changed, 100 insertions(+), 137 deletions(-) delete mode 100644 model/minskyCairoRenderer.h create mode 100644 model/ravelRenderer.h diff --git a/RESTService/typescriptAPI.cc b/RESTService/typescriptAPI.cc index 0608b6e89..5b8eba1de 100644 --- a/RESTService/typescriptAPI.cc +++ b/RESTService/typescriptAPI.cc @@ -7,7 +7,6 @@ #include "bookmark.h" #include "bookmark.tcd" #include "cairoSurfaceImage.tcd" -#include "cairoRenderer.tcd" #include "callableFunction.tcd" #include "canvas.tcd" #define CLASSDESC_typescriptAPI___CAPIRenderer diff --git a/gui-js/package-lock.json b/gui-js/package-lock.json index 01b266512..339a74ff4 100644 --- a/gui-js/package-lock.json +++ b/gui-js/package-lock.json @@ -14170,21 +14170,6 @@ } } }, - "node_modules/html-encoding-sniffer/node_modules/@noble/hashes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.4.0.tgz", - "integrity": "sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -16826,21 +16811,6 @@ } } }, - "node_modules/jsdom/node_modules/@noble/hashes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.4.0.tgz", - "integrity": "sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/jsdom/node_modules/lru-cache": { "version": "11.5.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", @@ -24986,21 +24956,6 @@ } } }, - "node_modules/whatwg-url/node_modules/@noble/hashes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.4.0.tgz", - "integrity": "sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/which": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", @@ -25308,24 +25263,6 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "license": "ISC" }, - "node_modules/yaml": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", - "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/yargs": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.2.0.tgz", diff --git a/model/minskyCairoRenderer.h b/model/minskyCairoRenderer.h deleted file mode 100644 index 13139a8d9..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 "ecolab/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/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 b89d85292..1984d99a0 100644 --- a/model/ravelWrap.cc +++ b/model/ravelWrap.cc @@ -23,7 +23,6 @@ #include "selection.h" #include "dimension.h" #include "minskyTensorOps.h" -#include "pango.h" #include "mansouraCairo.h" #include "capiRenderer.xcd" @@ -46,7 +45,7 @@ #include "tensorInterface.rcd" #include "tensorInterface.xcd" #include "xvector.rcd" -#include "minskyCairoRenderer.h" +#include "ravelRenderer.h" #include "SVGItem.h" #include "minsky_epilogue.h" @@ -132,9 +131,7 @@ namespace minsky if (m_editorMode) { cairoShim.scale(z,z); - // TODO: CairoRenderer needs IMansoura support - auto& shimImpl = dynamic_cast(cairoShim); - CairoRenderer cr(shimImpl._internalGetCairoContext()); + RavelRenderer cr(cairoShim); wrappedRavel.render(cr); } else @@ -895,12 +892,13 @@ namespace minsky { 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 MansouraCairo shim(surface->cairo()); + 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 1cec3ee6b..3e2306ec0 100644 --- a/model/ravelWrap.h +++ b/model/ravelWrap.h @@ -21,7 +21,7 @@ #define RAVELWRAP_H #include "operation.h" -#include "cairoRenderer.h" +#include "capiRenderer.h" #include "dynamicRavelCAPI.h" #include "hypercube.h" #include "handleLockInfo.h" diff --git a/model/sheet.cc b/model/sheet.cc index eb95fb1b3..65a2ff891 100644 --- a/model/sheet.cc +++ b/model/sheet.cc @@ -25,7 +25,6 @@ #include "itemT.rcd" #include "sheet.rcd" -#include "minskyCairoRenderer.h" #include "ravelWrap.h" #include "tensorOp.h" #include "minsky_epilogue.h" From 23146a0040463e47372109911f024f142ab0943f Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Mon, 19 Oct 2026 14:40:46 +1100 Subject: [PATCH 12/23] refactor: RenderNativeWindow abstracted from cairo details, which are all moved to WindowInformation (as a pimpl). --- RESTService/typescriptAPI.cc | 2 - gui-js/libs/shared/src/lib/backend/minsky.ts | 22 ++------ mansoura | 2 +- model/canvas.cc | 37 ++++--------- model/canvas.h | 10 ++-- model/equationDisplay.cc | 52 +++++++++++------- model/equationDisplay.h | 4 +- model/fontDisplay.h | 6 +-- model/godleyTableWindow.h | 11 ++-- model/grid.cc | 11 ++-- model/grid.h | 7 +-- model/minsky.cc | 1 + model/minsky.h | 1 + model/phillipsDiagram.cc | 10 ++-- model/phillipsDiagram.h | 6 +-- model/plotWidget.cc | 16 ++---- model/plotWidget.h | 5 +- model/pubTab.cc | 25 ++++----- model/pubTab.h | 2 +- model/ravelWrap.cc | 4 +- model/ravelWrap.h | 2 +- model/renderNativeWindow.cc | 39 ++++---------- model/renderNativeWindow.h | 32 ++++++++++-- model/variablePane.cc | 55 +++++++++----------- model/variablePane.h | 10 ++-- model/windowInformation.cc | 20 +++++++ model/windowInformation.h | 8 +++ test/testGrid.cc | 16 +++--- test/testLock.cc | 1 + test/testModel.cc | 21 +++----- test/testPlotWidget.cc | 6 +-- test/testSheet.cc | 1 + 32 files changed, 205 insertions(+), 240 deletions(-) diff --git a/RESTService/typescriptAPI.cc b/RESTService/typescriptAPI.cc index 5b8eba1de..16cb9bef7 100644 --- a/RESTService/typescriptAPI.cc +++ b/RESTService/typescriptAPI.cc @@ -6,7 +6,6 @@ #include "assetClass.tcd" #include "bookmark.h" #include "bookmark.tcd" -#include "cairoSurfaceImage.tcd" #include "callableFunction.tcd" #include "canvas.tcd" #define CLASSDESC_typescriptAPI___CAPIRenderer @@ -44,7 +43,6 @@ #include "operation.tcd" #include "operationBase.tcd" #include "operationType.tcd" -#include "pango.tcd" #include "pannableTab.tcd" #include "phillipsDiagram.tcd" #include "plotOptions.tcd" diff --git a/gui-js/libs/shared/src/lib/backend/minsky.ts b/gui-js/libs/shared/src/lib/backend/minsky.ts index ed2a7dcd3..47e17c69c 100644 --- a/gui-js/libs/shared/src/lib/backend/minsky.ts +++ b/gui-js/libs/shared/src/lib/backend/minsky.ts @@ -173,7 +173,6 @@ export class RenderNativeWindow extends EventInterface { 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);} @@ -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);} @@ -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');} @@ -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);} @@ -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);} @@ -975,7 +968,6 @@ export class GodleyTableWindow extends CppClass { 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);} @@ -1505,7 +1497,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);} @@ -1657,8 +1648,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);} @@ -1885,7 +1874,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);} @@ -2185,7 +2173,7 @@ export class VariablePane extends CppClass { async controlMouseDown(a1: number,a2: number): Promise {return this.$callMethod('controlMouseDown',a1,a2);} async deselect(a1: string): Promise {return this.$callMethod('deselect',a1);} async destroyFrame(): Promise {return this.$callMethod('destroyFrame');} - async draw(): Promise {return this.$callMethod('draw');} + async draw(...args: mansoura__IMansoura[]): Promise {return this.$callMethod('draw',...args);} async evenHeight(): Promise {return this.$callMethod('evenHeight');} async frameArgs(): Promise {return this.$callMethod('frameArgs');} async getItemAt(a1: number,a2: number): Promise {return this.$callMethod('getItemAt',a1,a2);} @@ -2198,14 +2186,13 @@ export class VariablePane extends CppClass { 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 mouseUp(a1: number,a2: number): Promise {return this.$callMethod('mouseUp',a1,a2);} - async moveCursorTo(a1: number,a2: number): Promise {return this.$callMethod('moveCursorTo',a1,a2);} + async moveCursorTo(a1: mansoura__IMansoura,a2: number,a3: number): Promise {return this.$callMethod('moveCursorTo',a1,a2,a3);} async moveTo(a1: number,a2: number): Promise {return this.$callMethod('moveTo',a1,a2);} async numCols(): Promise {return this.$callMethod('numCols');} async numRows(): Promise {return this.$callMethod('numRows');} 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);} @@ -2232,8 +2219,7 @@ export class VariablePaneCell extends CppClass { } async emplace(): Promise {return this.$callMethod('emplace');} async height(): Promise {return this.$callMethod('height');} - async reset(a1: minsky__dummy): Promise {return this.$callMethod('reset',a1);} - async show(): Promise {return this.$callMethod('show');} + async show(a1: mansoura__IMansoura): Promise {return this.$callMethod('show',a1);} async variable(): Promise {return this.$callMethod('variable');} async width(): Promise {return this.$callMethod('width');} } diff --git a/mansoura b/mansoura index b6d72160d..56a5ee4b6 160000 --- a/mansoura +++ b/mansoura @@ -1 +1 @@ -Subproject commit b6d72160d47431713a20749f8ae6157007f79a55 +Subproject commit 56a5ee4b648924ef422fe80b6e432bc0b02992ea diff --git a/model/canvas.cc b/model/canvas.cc index b4fb14672..7a0e9a7c6 100644 --- a/model/canvas.cc +++ b/model/canvas.cc @@ -797,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; @@ -806,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) @@ -823,21 +823,10 @@ 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(); - MansouraCairo mans(cairo); mans.rectangle(updateRegion.x0,updateRegion.y0,updateRegion.x1-updateRegion.x0,updateRegion.y1-updateRegion.y0); mans.clip(); @@ -851,7 +840,6 @@ namespace minsky try { didDrawSomething = true; - MansouraCairo mans(cairo); const PreserveContext cs(mans); mans.identityMatrix(); mans.translate(it.x(), it.y()); @@ -877,8 +865,8 @@ namespace minsky { didDrawSomething = true; const PreserveContext cs(mans); - cairo_identity_matrix(cairo); - cairo_translate(cairo,it.x(), it.y()); + mans.identityMatrix(); + mans.translate(it.x(), it.y()); { it.draw(mans); } @@ -931,17 +919,13 @@ namespace minsky 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(); } @@ -955,11 +939,8 @@ namespace minsky { 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()); + mansoura::renderToPNG(filename,z.width,z.height, + [&](const IMansoura& shim){redraw(shim,0,0,z.width,z.height);}); model->moveTo(model->x()+z.left,model->y()+z.top); model->zoom(model->x(),model->y(),1/z.zoom); } 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/equationDisplay.cc b/model/equationDisplay.cc index 2e39ed378..0eb6c2184 100644 --- a/model/equationDisplay.cc +++ b/model/equationDisplay.cc @@ -35,28 +35,40 @@ 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) - { - 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; + 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); + // TODO: remove this bridge once SystemOfEquations::renderEquations + // is migrated to IMansoura. It draws on a second cairo context + // sharing the target surface and the state set up above. + { + auto cr=static_cast(shim.context()); + double x,y; + shim.getCurrentPoint(x,y); + ecolab::cairo::Surface surf(cairo_surface_reference(cairo_get_target(cr))); + cairo_rectangle(surf.cairo(),0,0,width,height); + cairo_clip(surf.cairo()); + cairo_matrix_t ctm; + cairo_get_matrix(cr,&ctm); + cairo_set_matrix(surf.cairo(),&ctm); + cairo_move_to(surf.cairo(),x,y); + system.renderEquations(surf,height); } - return surface.get(); + if (m.flags & Minsky::fullEqnDisplay_needed) + { + 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; } } 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 655f69148..4a13a1cc9 100644 --- a/model/fontDisplay.h +++ b/model/fontDisplay.h @@ -20,7 +20,6 @@ #ifndef FONTDISPLAY_H #define FONTDISPLAY_H #include "renderNativeWindow.h" -#include "mansouraCairo.h" #include "classdesc_access.h" namespace minsky @@ -28,15 +27,14 @@ namespace minsky // display a sample of the current selected font class FontDisplay: public RenderNativeWindow { - bool redraw(int, int, int width, int height) override { - mansoura::MansouraCairo mans(surface->cairo()); + 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/godleyTableWindow.h b/model/godleyTableWindow.h index 018bc858c..b543baba9 100644 --- a/model/godleyTableWindow.h +++ b/model/godleyTableWindow.h @@ -225,17 +225,14 @@ namespace minsky { CLASSDESC_ACCESS(GodleyTableWindow); protected: - bool redraw(int, int, int width, int height) override { - if (surface.get()) { - drawCairo(surface->cairo()); - return true; - } - return false; + bool redraw(const mansoura::IMansoura& cairoShim, int, int, int width, int height) override { + draw(cairoShim); + return true; } public: using GodleyTableEditor::draw; GodleyTableWindow(GodleyIcon& g): GodleyTableEditor(g) {} - void requestRedraw() {if (surface.get()) surface->requestRedraw();} + void requestRedraw() {RenderNativeWindow::requestRedraw();} void requestRedrawCanvas() override {requestRedraw();} void mouseDown(float x, float y) override {GodleyTableEditor::mouseDown(x,y);} diff --git a/model/grid.cc b/model/grid.cc index 70041202a..80f0d1fc4 100644 --- a/model/grid.cc +++ b/model/grid.cc @@ -23,7 +23,6 @@ #include "grid.h" #include "variablePane.h" #include "lasso.h" -#include "ecolab/include/pango.h" #include "grid.rcd" #include "grid.xcd" #include "minsky_epilogue.h" @@ -37,7 +36,7 @@ namespace minsky } template - void Grid::draw() + void Grid::draw(const mansoura::IMansoura& cairoShim) { bottomRowMargin.clear(); if (evenHeight()) @@ -87,8 +86,8 @@ namespace minsky case right: offset+=colWidth-currentCell.width(); break; case centre: offset+=0.5*(colWidth-currentCell.width()); break; } - moveCursorTo(x+offset+0.5*padx,y); - currentCell.show(); + moveCursorTo(cairoShim,x+offset+0.5*padx,y); + currentCell.show(cairoShim); colWidth=std::max(colWidth, currentCell.width()+padx); y=bottomRowMargin[row]; } @@ -116,10 +115,8 @@ namespace minsky } template class Grid; - template class Grid; - template class Grid; + template class Grid; } CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::Grid); -CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::Grid); CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::Grid); diff --git a/model/grid.h b/model/grid.h index c8c9eeb9e..85796cadd 100644 --- a/model/grid.h +++ b/model/grid.h @@ -21,6 +21,7 @@ #define GRID_H #include #include "classdesc_access.h" +#include "IMansoura.h" namespace minsky { @@ -29,7 +30,7 @@ namespace minsky { public: virtual ~ICell()=default; - virtual void show()=0; ///< render onto cairo surface + virtual void show(const mansoura::IMansoura&)=0; ///< render using the drawing context virtual double width() const=0; ///< width of cell on canvas virtual double height() const=0; ///< height of cell }; @@ -43,7 +44,7 @@ namespace minsky class Grid: public JustificationStruct { /// move current cursor to \a x,y - virtual void moveCursorTo(double x, double y)=0; + virtual void moveCursorTo(const mansoura::IMansoura&, double x, double y)=0; CLASSDESC_ACCESS(Grid); public: virtual ~Grid()=default; @@ -58,7 +59,7 @@ namespace minsky /// coordinates of right and bottom margins of cells. Valid after draw() std::vector rightColMargin, bottomRowMargin; /// draw the grid - void draw(); + void draw(const mansoura::IMansoura&); /// column at \a x in unzoomed coordinates int colX(double x) const; /// row at \a y in unzoomed coordinates diff --git a/model/minsky.cc b/model/minsky.cc index 4d1ff916c..4e3bc7614 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" diff --git a/model/minsky.h b/model/minsky.h index e5009ec33..c1a13c4c9 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" diff --git a/model/phillipsDiagram.cc b/model/phillipsDiagram.cc index 41b5ed885..94915e459 100644 --- a/model/phillipsDiagram.cc +++ b/model/phillipsDiagram.cc @@ -101,15 +101,12 @@ 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) { - MansouraCairo shim(cairo); const PreserveContext cs(shim); shim.identityMatrix(); shim.translate(i.second.x()+x, i.second.y()+y); @@ -117,7 +114,6 @@ namespace minsky } for (auto& i: flows) { - MansouraCairo shim(cairo); i.second.draw(shim,true); } return true; diff --git a/model/phillipsDiagram.h b/model/phillipsDiagram.h index b67bf08e5..940990bd7 100644 --- a/model/phillipsDiagram.h +++ b/model/phillipsDiagram.h @@ -75,18 +75,18 @@ namespace minsky 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 91c280ea0..7db72ab2d 100644 --- a/model/plotWidget.cc +++ b/model/plotWidget.cc @@ -362,20 +362,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(); - MansouraCairo mans(surface->cairo()); - Plot::draw(mans,width/sf,height/sf); - surface->blit(); - } - return surface.get(); + auto sf=RenderNativeWindow::scaleFactor(); + Plot::draw(mans,width/sf,height/sf); + return true; } diff --git a/model/plotWidget.h b/model/plotWidget.h index 752114920..bbae26d29 100644 --- a/model/plotWidget.h +++ b/model/plotWidget.h @@ -63,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; @@ -83,7 +84,6 @@ namespace minsky public: using Item::x; using Item::y; - using RenderNativeWindow::surface; using RenderNativeWindow::requestRedraw; using RenderNativeWindow::renderToSVG; @@ -170,7 +170,6 @@ namespace minsky 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(); diff --git a/model/pubTab.cc b/model/pubTab.cc index 179916a93..80eb37e34 100644 --- a/model/pubTab.cc +++ b/model/pubTab.cc @@ -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); - MansouraCairo 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/ravelWrap.cc b/model/ravelWrap.cc index 1984d99a0..45fee9b59 100644 --- a/model/ravelWrap.cc +++ b/model/ravelWrap.cc @@ -888,11 +888,9 @@ 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 MansouraCairo shim(surface->cairo()); const PreserveContext cs(shim); shim.translate(0.5*width,0.5*height); auto z=0.4*min(width,height)/ravel.wrappedRavel.radius(); diff --git a/model/ravelWrap.h b/model/ravelWrap.h index 3e2306ec0..2e3a859d3 100644 --- a/model/ravelWrap.h +++ b/model/ravelWrap.h @@ -41,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) {} diff --git a/model/renderNativeWindow.cc b/model/renderNativeWindow.cc index f0eb8aeca..e786aad1c 100644 --- a/model/renderNativeWindow.cc +++ b/model/renderNativeWindow.cc @@ -30,8 +30,6 @@ 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" @@ -44,7 +42,6 @@ Please especially review the lifecycle (constructors, desctructors and copy cons #include using namespace std; -using namespace ecolab; //#define FPS_PROFILING_ON #ifdef WIN32 @@ -58,19 +55,6 @@ namespace minsky { 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 +67,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 +106,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 +118,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 +132,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 b41f63807..a35acd87a 100644 --- a/model/renderNativeWindow.h +++ b/model/renderNativeWindow.h @@ -22,7 +22,7 @@ #include "eventInterface.h" -#include +#include #include #include @@ -41,7 +41,7 @@ namespace classdesc namespace minsky { class WindowInformation; - class RenderNativeWindow : public ecolab::CairoSurface, public EventInterface + class RenderNativeWindow : public EventInterface { public: static mansoura::Colour backgroundColour; @@ -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/variablePane.cc b/model/variablePane.cc index 6ef7cbbad..46edf28c5 100644 --- a/model/variablePane.cc +++ b/model/variablePane.cc @@ -37,25 +37,27 @@ namespace minsky VariablePaneCell::VariablePaneCell(const VariableValue& var): var(var.type(), ':'+uqName(var.name)) { - const ecolab::cairo::Surface surf - (cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,NULL)); - cairo_move_to(surf.cairo(),0,0); - MansouraCairo shim(surf.cairo()); - RenderVariable rv(*this->var, shim); - rv.draw(); - double l,t; - cairo_recording_surface_ink_extents(surf.surface(),&l,&t,&m_width,&m_height); + const auto ink=mansoura::inkExtents + ([&](const IMansoura& shim) + { + shim.moveTo(0,0); + RenderVariable rv(*this->var, shim); + rv.draw(); + }); + m_width=ink.width; + m_height=ink.height; } - void VariablePaneCell::show() + void VariablePaneCell::show(const IMansoura& shim) { - if (!cachedCairo || !var || var->type()==VariableType::undefined) return; - MansouraCairo shim(cachedCairo); + if (!var || var->type()==VariableType::undefined) return; RenderVariable rv(*var, shim); - const ecolab::cairo::CairoSave cs(cachedCairo); - cairo_translate(cachedCairo,0.5*m_width,0.5*m_height); - rv.draw(); - cairo_reset_clip(cachedCairo); + { + const PreserveContext cs(shim); + shim.translate(0.5*m_width,0.5*m_height); + rv.draw(); + } + shim.resetClip(); } void VariablePaneCell::emplace() const @@ -103,27 +105,20 @@ namespace minsky m_numCols=vars.size()/m_numRows+1; const unsigned gridSize=m_numRows*m_numCols; while (vars.size()requestRedraw(); // TODO, plain requestRedraw doesn't work for Tk here... + RenderNativeWindow::requestRedraw(); } - bool VariablePane::redraw(int, int, int, int) + bool VariablePane::redraw(const IMansoura& shim, int, int, int, int) { - if (surface.get()) { - cairo_t* cairo=surface->cairo(); - for (auto& i: vars) i.reset(cairo); - cairo_identity_matrix(cairo); - Grid::draw(); - } - return surface.get(); + shim.identityMatrix(); + Grid::draw(shim); + return true; } - void VariablePane::moveCursorTo(double x, double y) + void VariablePane::moveCursorTo(const IMansoura& shim, double x, double y) { - if (surface.get()) - { - cairo_identity_matrix(surface->cairo()); - cairo_translate(surface->cairo(), x+offsx, y+offsy); - } + shim.identityMatrix(); + shim.translate(x+offsx, y+offsy); } } CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::VariablePaneBase); diff --git a/model/variablePane.h b/model/variablePane.h index b04c0547a..815aa7ac5 100644 --- a/model/variablePane.h +++ b/model/variablePane.h @@ -19,7 +19,7 @@ #ifndef VARIABLEPANE_H #define VARIABLEPANE_H -#include "cairo.h" +#include "IMansoura.h" #include "classdesc_access.h" #include "grid.h" #include "pannableTab.h" @@ -33,13 +33,11 @@ namespace minsky { VariablePtr var; double m_width=0, m_height=0; - cairo_t* cachedCairo=nullptr; CLASSDESC_ACCESS(VariablePaneCell); public: VariablePaneCell() {} VariablePaneCell(const VariableValue& var); - void reset(cairo_t* cairo) {cachedCairo=cairo;} - void show(); + void show(const mansoura::IMansoura&); double width() const {return m_width+2;} double height() const {return m_height+4;} void emplace() const; @@ -53,7 +51,7 @@ namespace minsky unsigned m_numRows=0, m_numCols=0; classdesc::Exclude> vars; CLASSDESC_ACCESS(VariablePane); - bool redraw(int, int, int width, int height) override; + bool redraw(const mansoura::IMansoura&, int, int, int width, int height) override; public: bool shift=false; ///< true if shift pressed std::set selection; @@ -68,7 +66,7 @@ namespace minsky unsigned numRows() const override {return m_numRows;} unsigned numCols() const override {return m_numCols;} bool evenHeight() const override {return false;} - void moveCursorTo(double,double) override; + void moveCursorTo(const mansoura::IMansoura&, double, double) override; void mouseDown(float x,float y) override { if (shift) return PannableTab::mouseDown(x,y); cell(rowY(y-offsy),colX(x-offsx)).emplace(); 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/test/testGrid.cc b/test/testGrid.cc index 145f28855..21c64bcdd 100644 --- a/test/testGrid.cc +++ b/test/testGrid.cc @@ -27,7 +27,7 @@ namespace { struct SizedCellMock: public ICell { - void show() override {} + void show(const mansoura::IMansoura&) override {} SizedCellMock(double width=10, double height=5): m_width(width), m_height(height) {} double m_width, m_height; @@ -40,7 +40,7 @@ namespace unsigned numRows() const override {return 10;} unsigned numCols() const override {return 10;} vector xpos, ypos; // capture moveTos - void moveCursorTo(double x, double y) override { + void moveCursorTo(const mansoura::IMansoura&, double x, double y) override { xpos.push_back(x); ypos.push_back(y); } @@ -76,7 +76,7 @@ const double padx=2; TEST_F(EvenHeightLeftGrid, draw) { - draw(); + draw(mansoura::measuringContext()); EXPECT_TRUE(numCols()>1 && numRows()>1); EXPECT_EQ(numCols(), rightColMargin.size()); EXPECT_EQ(numRows(), bottomRowMargin.size()); @@ -96,7 +96,7 @@ TEST_F(EvenHeightLeftGrid, draw) TEST_F(UnevenHeightGridMock, left) { - draw(); + draw(mansoura::measuringContext()); EXPECT_TRUE(numCols()>1 && numRows()>1); EXPECT_EQ(numCols(), rightColMargin.size()); EXPECT_EQ(numRows(), bottomRowMargin.size()); @@ -128,7 +128,7 @@ TEST_F(UnevenHeightGridMock, left) TEST_F(UnevenHeightGridMock, right) { m_justification=right; - draw(); + draw(mansoura::measuringContext()); EXPECT_TRUE(numCols()>1 && numRows()>1); EXPECT_EQ(numCols(), rightColMargin.size()); EXPECT_EQ(numRows(), bottomRowMargin.size()); @@ -160,7 +160,7 @@ TEST_F(UnevenHeightGridMock, right) TEST_F(UnevenHeightGridMock, centre) { m_justification=centre; - draw(); + draw(mansoura::measuringContext()); EXPECT_TRUE(numCols()>1 && numRows()>1); EXPECT_EQ(numCols(), rightColMargin.size()); EXPECT_EQ(numRows(), bottomRowMargin.size()); @@ -191,7 +191,7 @@ TEST_F(UnevenHeightGridMock, centre) TEST_F(UnevenHeightGridMock, colX) { - draw(); + draw(mansoura::measuringContext()); EXPECT_EQ(-1, colX(-1)); EXPECT_EQ(-1, colX(rightColMargin.back())); for (size_t i=0; i. */ +#include "mansouraCairo.h" #include "lock.h" #include "minsky.h" #include "minsky_epilogue.h" diff --git a/test/testModel.cc b/test/testModel.cc index 1cae80790..388ef98bc 100644 --- a/test/testModel.cc +++ b/test/testModel.cc @@ -17,6 +17,7 @@ along with Minsky. If not, see . */ +#include "mansouraCairo.h" #include "cairoItems.h" #include "operation.h" #include "group.h" @@ -1320,9 +1321,7 @@ struct GodleyTableWindowFixture: private EmbedGodleyIcon, public GodleyTableWind 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); + redraw(*mansoura::makeRecordingContext(),0,0,0,0); double x=colLeftMargin[1]+10, y=topTableOffset+rowHeight+5; EXPECT_EQ(1, colX(x)); EXPECT_EQ(1, rowY(y)); @@ -1345,9 +1344,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); + redraw(*mansoura::makeRecordingContext(),0,0,0,0); double x=colLeftMargin[1], y=topTableOffset+rowHeight+5; EXPECT_EQ(1, colX(x)); EXPECT_EQ(1, rowY(y)); @@ -1375,9 +1372,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); + redraw(*mansoura::makeRecordingContext(),0,0,0,0); double x=colLeftMargin[1]+2*ButtonWidget::buttonSpacing+1, y=5+columnButtonsOffset; EXPECT_EQ(colWidget, clickType(x,y)); mouseDown(x,y); @@ -1414,9 +1409,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); + redraw(*mansoura::makeRecordingContext(),0,0,0,0); double x=colLeftMargin[1]+10, y=topTableOffset+5; EXPECT_EQ(1,colX(x)); EXPECT_EQ(0,rowY(y)); @@ -1575,9 +1568,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); + redraw(*mansoura::makeRecordingContext(),0,0,0,0); double x=colLeftMargin[1]+10, y=topTableOffset+5+rowHeight; EXPECT_EQ(1,colX(x)); EXPECT_EQ(1,rowY(y)); diff --git a/test/testPlotWidget.cc b/test/testPlotWidget.cc index beb02efb6..427d6a475 100644 --- a/test/testPlotWidget.cc +++ b/test/testPlotWidget.cc @@ -36,10 +36,8 @@ namespace minsky class PlotWidgetTest : public PlotWidget, public ::testing::Test { public: - ecolab::cairo::SurfacePtr surf{ - std::make_shared(cairo_recording_surface_create(CAIRO_CONTENT_COLOR,nullptr))}; - mansoura::MansouraCairo mans{surf->cairo()}; - PlotWidgetTest() {surface=surf;} + std::unique_ptr mansPtr{mansoura::makeRecordingContext()}; + mansoura::IMansoura& mans{*mansPtr}; }; TEST_F(PlotWidgetTest, drawWithTitleAndLegend) diff --git a/test/testSheet.cc b/test/testSheet.cc index a0e3ee8ca..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" From e687bb6df9cdc3794fede9c760f793a24dcae457 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Tue, 20 Oct 2026 16:16:07 +1100 Subject: [PATCH 13/23] refactor: requationDisplay ported to Mansoura --- engine/equationDisplayRender.cc | 787 ++++++++++++++++---------------- engine/equations.h | 14 +- mansoura | 2 +- model/equationDisplay.cc | 29 +- 4 files changed, 419 insertions(+), 413 deletions(-) diff --git a/engine/equationDisplayRender.cc b/engine/equationDisplayRender.cc index f18147077..d2e4b2c8c 100644 --- a/engine/equationDisplayRender.cc +++ b/engine/equationDisplayRender.cc @@ -23,11 +23,11 @@ #include "selection.h" #include "lasso.h" #include "userFunction.h" -#include "ecolab/include/pango.h" +#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) { - ecolab::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); - ecolab::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; - ecolab::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 - ecolab::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); - ecolab::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. - ecolab::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); - ecolab::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); - ecolab::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); - ecolab::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/mansoura b/mansoura index 56a5ee4b6..b9c9e9933 160000 --- a/mansoura +++ b/mansoura @@ -1 +1 @@ -Subproject commit 56a5ee4b648924ef422fe80b6e432bc0b02992ea +Subproject commit b9c9e9933652eb7ce9b7d8bf872aaed5470c274b diff --git a/model/equationDisplay.cc b/model/equationDisplay.cc index 0eb6c2184..532552d0e 100644 --- a/model/equationDisplay.cc +++ b/model/equationDisplay.cc @@ -43,29 +43,16 @@ namespace minsky shim.clip(); shim.moveTo(offsx,offsy); shim.scale(m_zoomFactor,m_zoomFactor); - // TODO: remove this bridge once SystemOfEquations::renderEquations - // is migrated to IMansoura. It draws on a second cairo context - // sharing the target surface and the state set up above. - { - auto cr=static_cast(shim.context()); - double x,y; - shim.getCurrentPoint(x,y); - ecolab::cairo::Surface surf(cairo_surface_reference(cairo_get_target(cr))); - cairo_rectangle(surf.cairo(),0,0,width,height); - cairo_clip(surf.cairo()); - cairo_matrix_t ctm; - cairo_get_matrix(cr,&ctm); - cairo_set_matrix(surf.cairo(),&ctm); - cairo_move_to(surf.cairo(),x,y); - system.renderEquations(surf,height); - } + system.renderEquations(shim,height); if (m.flags & Minsky::fullEqnDisplay_needed) { - 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(); + const auto ink=mansoura::inkExtents([&](const mansoura::IMansoura& rec) + { + 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; From 53ec7500250216fe2464030a93833cc6a38df23b Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Tue, 20 Oct 2026 19:16:33 +1100 Subject: [PATCH 14/23] refactor: Remove GodleyIcon::popup. For GH #692. --- .../src/app/events/electron.events.ts | 4 +- .../src/app/managers/CommandsManager.ts | 1 - .../src/app/managers/ContextMenuManager.ts | 28 +- .../src/app/managers/GodleyMenuManager.ts | 16 +- gui-js/libs/shared/src/lib/backend/minsky.ts | 108 -- .../godley-widget-view.component.ts | 47 +- model/godleyIcon.h | 7 - model/godleyTableWindow.cc | 1 - model/minsky.cc | 11 - model/minsky.h | 3 - test/00/godleyTableWindow.sh | 53 - test/renderedImages/1Free11Selected.svg | 952 -------------- test/renderedImages/1FreeBase.svg | 903 ------------- test/renderedImages/1FreeSelectedCol.svg | 943 -------------- test/renderedImages/1FreeSelectedRow.svg | 959 -------------- test/renderedImages/LoanableFundsBase.svg | 1129 ----------------- 16 files changed, 29 insertions(+), 5136 deletions(-) delete mode 100755 test/00/godleyTableWindow.sh delete mode 100644 test/renderedImages/1Free11Selected.svg delete mode 100644 test/renderedImages/1FreeBase.svg delete mode 100644 test/renderedImages/1FreeSelectedCol.svg delete mode 100644 test/renderedImages/1FreeSelectedRow.svg delete mode 100644 test/renderedImages/LoanableFundsBase.svg 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 73e725692..aadda1607 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); } ); 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 81e3fb195..37b389b68 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 c837ce598..1ea7e1e06 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'; @@ -196,12 +196,12 @@ export class GodleyMenuManager { { label: 'Undo', accelerator: 'CmdOrCtrl + z', - click: () => {godley.popup.undo(1);}, + click: () => {godley.editor.undo(1);}, }, { label: 'Redo', accelerator: 'CmdOrCtrl + y', - click: () => {godley.popup.undo(-1);}, + click: () => {godley.editor.undo(-1);}, }, { label: 'Title', @@ -210,17 +210,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();} }, ], }); @@ -258,7 +258,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") { @@ -267,7 +267,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 47e17c69c..ac32197cf 100644 --- a/gui-js/libs/shared/src/lib/backend/minsky.ts +++ b/gui-js/libs/shared/src/lib/backend/minsky.ts @@ -716,7 +716,6 @@ export class FontDisplay extends CppClass { export class GodleyIcon extends Item { editor: GodleyTableEditor; - popup: GodleyTableWindow; svgRenderer: mansoura__SVGRenderer; table: GodleyTable; constructor(prefix: string|Item){ @@ -725,18 +724,15 @@ 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 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: mansoura__IMansoura): Promise {return this.$callMethod('draw',a1);} async editorMode(): Promise {return this.$callMethod('editorMode');} @@ -897,109 +893,6 @@ export class GodleyTableEditor extends CppClass { async zoomFactor(...args: number[]): Promise {return this.$callMethod('zoomFactor',...args);} } -export class GodleyTableWindow extends CppClass { - backgroundColour: mansoura__Colour; - colLeftMargin: Sequence; - item: Item; - wire: Wire; - constructor(prefix: string){ - super(prefix); - this.backgroundColour=new mansoura__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 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; @@ -1420,7 +1313,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);} 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 c37714693..6fb5ec34e 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; @@ -126,9 +126,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() { @@ -143,25 +140,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( @@ -201,23 +179,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; @@ -225,7 +188,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) { @@ -242,7 +205,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/model/godleyIcon.h b/model/godleyIcon.h index 7c79677a4..febcb0732 100644 --- a/model/godleyIcon.h +++ b/model/godleyIcon.h @@ -81,15 +81,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); @@ -164,9 +160,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/godleyTableWindow.cc index 5b1b2efbf..8ea0201af 100644 --- a/model/godleyTableWindow.cc +++ b/model/godleyTableWindow.cc @@ -1117,7 +1117,6 @@ namespace { g->update(); } minsky().canvas.requestRedraw(); - minsky().redrawAllGodleyTables(); } void GodleyTableEditor::checkCell00() diff --git a/model/minsky.cc b/model/minsky.cc index 4e3bc7614..7b4e28877 100644 --- a/model/minsky.cc +++ b/model/minsky.cc @@ -103,7 +103,6 @@ namespace minsky bool Minsky::multipleEquities(const bool& m) { m_multipleEquities=m; canvas.requestRedraw(); - redrawAllGodleyTables(); return m_multipleEquities; } @@ -1737,16 +1736,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; diff --git a/model/minsky.h b/model/minsky.h index c1a13c4c9..acd1f2d53 100644 --- a/model/minsky.h +++ b/model/minsky.h @@ -430,9 +430,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/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/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 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From dd3cb656702ddf3e93789dff7525481f7e3f3c9e Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Wed, 21 Oct 2026 15:11:40 +1100 Subject: [PATCH 15/23] chore: dead code removal --- model/godleyIcon.cc | 13 ++----- model/godleyIcon.h | 2 - model/godleyTableWindow.cc | 1 - model/godleyTableWindow.h | 25 ------------- model/plotWidget.cc | 3 -- model/plotWidget.h | 4 +- model/renderNativeWindow.cc | 2 - test/testModel.cc | 73 +++++++++++++++++++------------------ 8 files changed, 43 insertions(+), 80 deletions(-) diff --git a/model/godleyIcon.cc b/model/godleyIcon.cc index aeb4173c3..be2172246 100644 --- a/model/godleyIcon.cc +++ b/model/godleyIcon.cc @@ -25,7 +25,6 @@ #include #include #include -#include #include #include "mansouraCairo.h" #include "godleyIcon.rcd" @@ -35,8 +34,6 @@ #include using namespace boost::locale::conv; using namespace mansoura; -using namespace ecolab::cairo; -using namespace ecolab; using namespace std; // width of draggable border @@ -477,13 +474,11 @@ namespace minsky cairoShim.rectangle(left, top, w, h); cairoShim.clip(); cairoShim.translate(left+border*z+leftMargin(),top+border*z+titleOffs()/* space for title*/); - // render to a recording surface to determine size of editor table - // TODO - maybe move this stuff into update() - const Surface surf(cairo_recording_surface_create(CAIRO_CONTENT_COLOR, nullptr)); - MansouraCairo recorder(surf.cairo()); const_cast(editor).zoomFactor=1; - const_cast(editor).draw(recorder); - 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; diff --git a/model/godleyIcon.h b/model/godleyIcon.h index febcb0732..7c91112f1 100644 --- a/model/godleyIcon.h +++ b/model/godleyIcon.h @@ -32,8 +32,6 @@ #include "variableValue.h" #include -#include -#include namespace minsky { diff --git a/model/godleyTableWindow.cc b/model/godleyTableWindow.cc index 8ea0201af..dc4cfac86 100644 --- a/model/godleyTableWindow.cc +++ b/model/godleyTableWindow.cc @@ -1247,5 +1247,4 @@ namespace { 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/godleyTableWindow.h index b543baba9..b3bc50148 100644 --- a/model/godleyTableWindow.h +++ b/model/godleyTableWindow.h @@ -220,31 +220,6 @@ 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(const mansoura::IMansoura& cairoShim, int, int, int width, int height) override { - draw(cairoShim); - return true; - } - public: - using GodleyTableEditor::draw; - GodleyTableWindow(GodleyIcon& g): GodleyTableEditor(g) {} - void requestRedraw() {RenderNativeWindow::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" diff --git a/model/plotWidget.cc b/model/plotWidget.cc index 7db72ab2d..b77e8ae42 100644 --- a/model/plotWidget.cc +++ b/model/plotWidget.cc @@ -22,9 +22,6 @@ #include "cairoItems.h" #include "latexMarkup.h" #include -#include -#include -#include #include "mansouraCairo.h" #include "CSVTools.xcd" diff --git a/model/plotWidget.h b/model/plotWidget.h index bbae26d29..89e80f557 100644 --- a/model/plotWidget.h +++ b/model/plotWidget.h @@ -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/renderNativeWindow.cc b/model/renderNativeWindow.cc index e786aad1c..5269b14e8 100644 --- a/model/renderNativeWindow.cc +++ b/model/renderNativeWindow.cc @@ -32,8 +32,6 @@ Please especially review the lifecycle (constructors, desctructors and copy cons #include "windowInformation.h" #include "renderNativeWindow.rcd" #include "renderNativeWindow.xcd" -#include "plot.rcd" -#include "plot.xcd" #include "minsky_epilogue.h" diff --git a/test/testModel.cc b/test/testModel.cc index 388ef98bc..9149c7194 100644 --- a/test/testModel.cc +++ b/test/testModel.cc @@ -1313,15 +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"; - redraw(*mansoura::makeRecordingContext(),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)); @@ -1329,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; @@ -1344,7 +1345,7 @@ TEST_F(GodleyTableWindowFixture, mouseMove) TEST_F(GodleyTableWindowFixture, mouseSelect) { godleyIcon().table.cell(1,1)="hello"; - redraw(*mansoura::makeRecordingContext(),0,0,0,0); + draw(mans); double x=colLeftMargin[1], y=topTableOffset+rowHeight+5; EXPECT_EQ(1, colX(x)); EXPECT_EQ(1, rowY(y)); @@ -1372,7 +1373,7 @@ TEST_F(GodleyTableWindowFixture, mouseButtons) godleyIcon().table.cell(3,1)="r3c1"; godleyIcon().table.cell(3,2)="r3c2"; - redraw(*mansoura::makeRecordingContext(),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); @@ -1409,7 +1410,7 @@ TEST_F(GodleyTableWindowFixture, moveRowColCell) godleyIcon().table.cell(1,2)="r1c2"; godleyIcon().table.cell(2,1)="r2c1"; godleyIcon().table.cell(2,2)="r2c2"; - redraw(*mansoura::makeRecordingContext(),0,0,0,0); + draw(mans); double x=colLeftMargin[1]+10, y=topTableOffset+5; EXPECT_EQ(1,colX(x)); EXPECT_EQ(0,rowY(y)); @@ -1456,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()); @@ -1473,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); @@ -1482,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, see godleyTableWindow line 633 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); @@ -1524,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); @@ -1568,7 +1569,7 @@ TEST_F(GodleyTableWindowFixture, keyPress) TEST_F(GodleyTableWindowFixture, addDelVars) { - redraw(*mansoura::makeRecordingContext(),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)); @@ -1633,7 +1634,7 @@ TEST_F(ModelSuite, copyBetweenCols) godley1->update(); godley2->update(); - GodleyTableWindow gw(*godley1); + GodleyTableEditor gw(*godley1); // render GodleyTableWindow to compute column/row boundaries gw.draw(mans); // positions of the 2,1 and 2,2 cells From e9554dea9d58231ce189df9736bf0b4bf75f233d Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Wed, 21 Oct 2026 15:52:39 +1100 Subject: [PATCH 16/23] chore: rename godleyTableWindow.* to godleyTableEditor.* to reflect contents --- Makefile | 2 +- RESTService/typescriptAPI.cc | 2 +- model/godleyIcon.cc | 3 +-- model/godleyIcon.h | 2 +- model/{godleyTableWindow.cc => godleyTableEditor.cc} | 6 +++--- model/{godleyTableWindow.h => godleyTableEditor.h} | 2 +- test/testMinsky.cc | 2 +- test/testModel.cc | 4 ++-- 8 files changed, 11 insertions(+), 12 deletions(-) rename model/{godleyTableWindow.cc => godleyTableEditor.cc} (99%) rename model/{godleyTableWindow.h => godleyTableEditor.h} (99%) diff --git a/Makefile b/Makefile index ea24098b1..96c0ce44f 100644 --- a/Makefile +++ b/Makefile @@ -192,7 +192,7 @@ 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 grid.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 variablePane.o windowInformation.o wire.o +MODEL_OBJS=autoLayout.o cairoItems.o canvas.o CSVDialog.o dataOp.o equationDisplay.o godleyIcon.o godleyTable.o godleyTableEditor.o grid.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 variablePane.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 diff --git a/RESTService/typescriptAPI.cc b/RESTService/typescriptAPI.cc index 16cb9bef7..4d9a6c8ef 100644 --- a/RESTService/typescriptAPI.cc +++ b/RESTService/typescriptAPI.cc @@ -27,7 +27,7 @@ #include "fontDisplay.tcd" #include "godleyIcon.tcd" #include "godleyTable.tcd" -#include "godleyTableWindow.tcd" +#include "godleyTableEditor.tcd" #include "grid.tcd" #include "group.tcd" #include "handleLockInfo.tcd" diff --git a/model/godleyIcon.cc b/model/godleyIcon.cc index be2172246..c50332325 100644 --- a/model/godleyIcon.cc +++ b/model/godleyIcon.cc @@ -19,7 +19,6 @@ #include "minsky.h" #include "variable.h" #include "godleyIcon.h" -#include "godleyTableWindow.h" #include "cairoItems.h" #include "selection.h" #include @@ -29,7 +28,7 @@ #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; diff --git a/model/godleyIcon.h b/model/godleyIcon.h index 7c91112f1..5edb94f71 100644 --- a/model/godleyIcon.h +++ b/model/godleyIcon.h @@ -21,7 +21,7 @@ #include "variable.h" #include "godleyTable.h" -#include "godleyTableWindow.h" +#include "godleyTableEditor.h" #include "zoom.h" #include "intrusiveMap.h" #include "classdesc_access.h" diff --git a/model/godleyTableWindow.cc b/model/godleyTableEditor.cc similarity index 99% rename from model/godleyTableWindow.cc rename to model/godleyTableEditor.cc index dc4cfac86..82a06ba90 100644 --- a/model/godleyTableWindow.cc +++ b/model/godleyTableEditor.cc @@ -19,7 +19,7 @@ #include "cairoItems.h" #include "minsky.h" -#include "godleyTableWindow.h" +#include "godleyTableEditor.h" #include "mansouraCairo.h" #include "selection.h" #include "latexMarkup.h" @@ -27,8 +27,8 @@ #include "ecolab/include/pango.h" #include "assetClass.rcd" -#include "godleyTableWindow.rcd" -#include "godleyTableWindow.xcd" +#include "godleyTableEditor.rcd" +#include "godleyTableEditor.xcd" #include "cairo_base.h" #include "IMansoura.cd" #include "minsky_epilogue.h" diff --git a/model/godleyTableWindow.h b/model/godleyTableEditor.h similarity index 99% rename from model/godleyTableWindow.h rename to model/godleyTableEditor.h index b3bc50148..a835a6a5f 100644 --- a/model/godleyTableWindow.h +++ b/model/godleyTableEditor.h @@ -222,5 +222,5 @@ namespace minsky }; } -#include "godleyTableWindow.cd" +#include "godleyTableEditor.cd" #endif diff --git a/test/testMinsky.cc b/test/testMinsky.cc index 5e8aa0551..cc44e0b2a 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 diff --git a/test/testModel.cc b/test/testModel.cc index 9149c7194..6c41bd50c 100644 --- a/test/testModel.cc +++ b/test/testModel.cc @@ -22,7 +22,7 @@ #include "operation.h" #include "group.h" #include "minsky.h" -#include "godleyTableWindow.h" +#include "godleyTableEditor.h" #include "minsky_epilogue.h" #include @@ -1491,7 +1491,7 @@ TEST_F(GodleyTableWindowFixture, keyPress) 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,""); EXPECT_EQ(2,selectedCol); From 190ac700b2035fe99e4a4c58959775f0b688d5c4 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Wed, 21 Oct 2026 17:05:21 +1100 Subject: [PATCH 17/23] refactor: migrated last of GodleyTableEdit and Item to Mansoura. --- mansoura | 2 +- model/godleyTableEditor.cc | 206 ++++++++++++++++--------------------- model/godleyTableEditor.h | 10 +- model/item.cc | 35 +++---- 4 files changed, 109 insertions(+), 144 deletions(-) diff --git a/mansoura b/mansoura index b9c9e9933..e5bd61ee0 160000 --- a/mansoura +++ b/mansoura @@ -1 +1 @@ -Subproject commit b9c9e9933652eb7ce9b7d8bf872aaed5470c274b +Subproject commit e5bd61ee00aac850f62ba3af312a7370e0f611fd diff --git a/model/godleyTableEditor.cc b/model/godleyTableEditor.cc index 82a06ba90..eb9d7c851 100644 --- a/model/godleyTableEditor.cc +++ b/model/godleyTableEditor.cc @@ -20,16 +20,12 @@ #include "cairoItems.h" #include "minsky.h" #include "godleyTableEditor.h" -#include "mansouraCairo.h" #include "selection.h" #include "latexMarkup.h" -#include -#include "ecolab/include/pango.h" #include "assetClass.rcd" #include "godleyTableEditor.rcd" #include "godleyTableEditor.xcd" -#include "cairo_base.h" #include "IMansoura.cd" #include "minsky_epilogue.h" @@ -40,9 +36,6 @@ using namespace minsky; using namespace mansoura; using namespace boost::locale::conv; -#include -#include -#include namespace { @@ -62,7 +55,7 @@ namespace {.6,.5,0} }; - void showAsset(ICacheRender& pango, IMansoura& mans, GodleyAssetClass::AssetClass assetClass) + void showAsset(ICacheRender& pango, const IMansoura& mans, GodleyAssetClass::AssetClass assetClass) { const PreserveContext cs(mans); auto& colour=assetColour[assetClass]; @@ -70,15 +63,6 @@ namespace pango.show(); } - // legacy - void showAsset(ecolab::Pango& pango, cairo_t* cairo, GodleyAssetClass::AssetClass assetClass) - { - const CairoSave cs(cairo); - auto& colour=assetColour[assetClass]; - cairo_set_source_rgb(cairo,colour.r,colour.g,colour.b); - pango.show(); - } - } namespace minsky @@ -165,11 +149,12 @@ namespace minsky return m_godleyIcon.table.cellInTable(selectedRow, selectedCol); } - void GodleyTableEditor::drawCairo(cairo_t* cairo) + void GodleyTableEditor::draw(const IMansoura& cairo) { - const ecolab::cairo::CairoSave cs(cairo); - cairo_scale(cairo,zoomFactor,zoomFactor); - ecolab::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; @@ -195,30 +180,30 @@ 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); } lastAssetBoundary=x; assetClass=m_godleyIcon.table.assetClass(col); - cairo_move_to(cairo,x+3,topTableOffset); - cairo_rel_line_to(cairo,0,tableHeight); + cairo.moveTo(x+3,topTableOffset); + cairo.relLineTo(0,tableHeight); } - cairo_move_to(cairo,x,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.setLineWidth(0.5); + cairo.stroke(); if (drawButtons && col>0 && col1) { - cairo_move_to(cairo,x-pulldownHot,topTableOffset); + cairo.moveTo(x-pulldownHot,topTableOffset); pango.setMarkup("▼"); pango.show(); } @@ -231,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 || @@ -298,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; } @@ -314,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(); @@ -323,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(); @@ -349,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(); } } } @@ -471,8 +455,8 @@ namespace minsky int GodleyTableEditor::textIdx(double x) const { - const cairo::Surface surf(cairo_recording_surface_create(CAIRO_CONTENT_COLOR,NULL)); - ecolab::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. @@ -992,35 +976,35 @@ namespace { return tmpStr; } - void GodleyTableEditor::highlightColumn(cairo_t* cairo, unsigned col) + void GodleyTableEditor::highlightColumn(const IMansoura& cairo, unsigned col) { if (col - 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); - ecolab::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)) @@ -1231,19 +1216,6 @@ namespace { } - template - void ButtonWidget::draw(const mansoura::IMansoura& cairoShim) - { - auto& shimImpl = dynamic_cast(cairoShim); - draw(shimImpl._internalGetCairoContext()); - } - - void GodleyTableEditor::draw(const mansoura::IMansoura& cairoShim) - { - auto& shimImpl = dynamic_cast(cairoShim); - drawCairo(shimImpl._internalGetCairoContext()); - } - template class ButtonWidget; template class ButtonWidget; } diff --git a/model/godleyTableEditor.h b/model/godleyTableEditor.h index a835a6a5f..260db5176 100644 --- a/model/godleyTableEditor.h +++ b/model/godleyTableEditor.h @@ -55,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 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); @@ -87,7 +86,6 @@ namespace minsky topTableOffset=30;adjustWidgets(); } protected: - void drawCairo(cairo_t* cairo); public: static constexpr double columnButtonsOffset=12; /// offset of the table within the window @@ -170,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(); diff --git a/model/item.cc b/model/item.cc index 323b837fe..5a8ab19fe 100644 --- a/model/item.cc +++ b/model/item.cc @@ -29,7 +29,6 @@ #include "selection.h" #include "lasso.h" #include -#include #include "item.rcd" #include "noteBase.rcd" #include "noteBase.xcd" @@ -45,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; @@ -56,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); - MansouraCairo 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); @@ -394,9 +391,7 @@ namespace minsky void Item::dummyDraw() const { - const ecolab::cairo::Surface s(cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA,NULL)); - MansouraCairo shim(s.cairo()); - draw(shim); + inkExtents([this](const IMansoura& shim) {draw(shim);}); } void Item::displayTooltip(const mansoura::IMansoura& cairoShim, const std::string& tooltip) const From 66108bbab08a17b0da7113936728455286efea90 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Wed, 21 Oct 2026 18:37:59 +1100 Subject: [PATCH 18/23] chore: regenerated minsky.ts and package-lock.json --- gui-js/libs/shared/src/lib/backend/minsky.ts | 81 +------------------- gui-js/package-lock.json | 3 - 2 files changed, 3 insertions(+), 81 deletions(-) diff --git a/gui-js/libs/shared/src/lib/backend/minsky.ts b/gui-js/libs/shared/src/lib/backend/minsky.ts index ac89f00d6..2cdf64b77 100644 --- a/gui-js/libs/shared/src/lib/backend/minsky.ts +++ b/gui-js/libs/shared/src/lib/backend/minsky.ts @@ -846,9 +846,9 @@ export class GodleyTableEditor extends CppClass { 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);} @@ -2042,81 +2042,6 @@ export class VariableInstanceList extends CppClass { async names(): Promise {return this.$callMethod('names');} } -<<<<<<< HEAD -export class VariablePane extends CppClass { - backgroundColour: mansoura__Colour; - bottomRowMargin: Sequence; - item: Item; - rightColMargin: Sequence; - selection: Container; - wire: Wire; - constructor(prefix: string){ - super(prefix); - this.backgroundColour=new mansoura__Colour(this.$prefix()+'.backgroundColour'); - this.bottomRowMargin=new Sequence(this.$prefix()+'.bottomRowMargin'); - this.item=new Item(this.$prefix()+'.item'); - this.rightColMargin=new Sequence(this.$prefix()+'.rightColMargin'); - this.selection=new Container(this.$prefix()+'.selection'); - this.wire=new Wire(this.$prefix()+'.wire'); - } - async cell(a1: number,a2: number): Promise {return this.$callMethod('cell',a1,a2);} - async colX(a1: number): Promise {return this.$callMethod('colX',a1);} - async controlMouseDown(a1: number,a2: number): Promise {return this.$callMethod('controlMouseDown',a1,a2);} - async deselect(a1: string): Promise {return this.$callMethod('deselect',a1);} - async destroyFrame(): Promise {return this.$callMethod('destroyFrame');} - async draw(...args: mansoura__IMansoura[]): Promise {return this.$callMethod('draw',...args);} - async evenHeight(): Promise {return this.$callMethod('evenHeight');} - 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 hasScrollBars(): Promise {return this.$callMethod('hasScrollBars');} - async init(): Promise {return this.$callMethod('init');} - async justification(a1: number): Promise {return this.$callMethod('justification',a1);} - async keyPress(a1: minsky__EventInterface__KeyPressArgs): Promise {return this.$callMethod('keyPress',a1);} - async m_zoomFactor(...args: number[]): Promise {return this.$callMethod('m_zoomFactor',...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 mouseUp(a1: number,a2: number): Promise {return this.$callMethod('mouseUp',a1,a2);} - async moveCursorTo(a1: mansoura__IMansoura,a2: number,a3: number): Promise {return this.$callMethod('moveCursorTo',a1,a2,a3);} - async moveTo(a1: number,a2: number): Promise {return this.$callMethod('moveTo',a1,a2);} - async numCols(): Promise {return this.$callMethod('numCols');} - async numRows(): Promise {return this.$callMethod('numRows');} - 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 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 resolutionScaleFactor(...args: any[]): Promise {return this.$callMethod('resolutionScaleFactor',...args);} - async rowY(a1: number): Promise {return this.$callMethod('rowY',a1);} - async scaleFactor(): Promise {return this.$callMethod('scaleFactor');} - async select(a1: string): Promise {return this.$callMethod('select',a1);} - async shift(...args: boolean[]): Promise {return this.$callMethod('shift',...args);} - async typeName(a1: number): Promise {return this.$callMethod('typeName',a1);} - async update(): Promise {return this.$callMethod('update');} - async updateWithHeight(a1: number): Promise {return this.$callMethod('updateWithHeight',a1);} - 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 VariablePaneCell extends CppClass { - constructor(prefix: string){ - super(prefix); - } - async emplace(): Promise {return this.$callMethod('emplace');} - async height(): Promise {return this.$callMethod('height');} - async show(a1: mansoura__IMansoura): Promise {return this.$callMethod('show',a1);} - async variable(): Promise {return this.$callMethod('variable');} - async width(): Promise {return this.$callMethod('width');} -} - -======= ->>>>>>> develop export class VariableValue extends CppClass { rhs: civita__ITensor; spec: DataSpec; diff --git a/gui-js/package-lock.json b/gui-js/package-lock.json index 4222b7abb..d7dc2d211 100644 --- a/gui-js/package-lock.json +++ b/gui-js/package-lock.json @@ -26434,8 +26434,6 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "license": "ISC" }, -<<<<<<< HEAD -======= "node_modules/yaml": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", @@ -26452,7 +26450,6 @@ "url": "https://github.com/sponsors/eemeli" } }, ->>>>>>> develop "node_modules/yargs": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.2.0.tgz", From c36061fd9e7e2459dd70a0332d66f98ca70de001 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Fri, 23 Oct 2026 14:09:22 +1100 Subject: [PATCH 19/23] chore: update mansoura ref --- mansoura | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mansoura b/mansoura index e5bd61ee0..fd258869d 160000 --- a/mansoura +++ b/mansoura @@ -1 +1 @@ -Subproject commit e5bd61ee00aac850f62ba3af312a7370e0f611fd +Subproject commit fd258869d11e5661b233e4a0da6f280a2ad9def5 From c443e32e40ac574c1972d1a245637fcd81a370bb Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Tue, 27 Oct 2026 17:39:39 +1100 Subject: [PATCH 20/23] bugfix: Fix bad merge --- Makefile | 2 +- .../apps/minsky-electron/src/app/events/electron.events.ts | 2 +- mansoura | 2 +- model/godleyIcon.cc | 6 +++--- test/testMinsky.cc | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 307248935..27c48bfe3 100644 --- a/Makefile +++ b/Makefile @@ -525,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 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 cf3d814f1..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 @@ -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/mansoura b/mansoura index ea171f7d3..6a8e8c69c 160000 --- a/mansoura +++ b/mansoura @@ -1 +1 @@ -Subproject commit ea171f7d3d6d607153140639bdd9db3e1e4c7a10 +Subproject commit 6a8e8c69ca688e76d58007dd04838eb0d2b9d5ed diff --git a/model/godleyIcon.cc b/model/godleyIcon.cc index 953639f68..81678d4b3 100644 --- a/model/godleyIcon.cc +++ b/model/godleyIcon.cc @@ -227,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)) @@ -245,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; coltable.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)); } From 9844785a6461683768d0e57664da7f9e9871f943 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Tue, 27 Oct 2026 17:46:41 +1100 Subject: [PATCH 21/23] Update submodule URL to use HTTPS Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 9f6e8e8a7..1e1377a22 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,4 +13,4 @@ url = https://github.com/OfficialKris/libclipboard.git [submodule "mansoura"] path = mansoura - url = git@github.com:highperformancecoder/mansoura.git + url = https://github.com/highperformancecoder/mansoura.git From 01325c76e61894283052f5bba87c340bc625861d Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Tue, 27 Oct 2026 17:57:56 +1100 Subject: [PATCH 22/23] chore: Fix broken regression test --- test/00/godleyTable.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) 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() From 65f7eb751980ff5dc555820ef6431bb495307315 Mon Sep 17 00:00:00 2001 From: Russell Standish Date: Thu, 29 Oct 2026 17:12:24 +1100 Subject: [PATCH 23/23] Address code review comments --- Makefile | 4 ++-- makeDist.sh | 2 +- model/canvas.cc | 13 ++++++++----- model/minsky.cc | 7 +++++-- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 27c48bfe3..f6e3f5b00 100644 --- a/Makefile +++ b/Makefile @@ -211,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) @@ -475,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) 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/model/canvas.cc b/model/canvas.cc index 7a0e9a7c6..917301d05 100644 --- a/model/canvas.cc +++ b/model/canvas.cc @@ -935,15 +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); + // 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);}); - model->moveTo(model->x()+z.left,model->y()+z.top); - model->zoom(model->x(),model->y(),1/z.zoom); - } + [&](const IMansoura& shim){redraw(shim,0,0,z.width,z.height);}); + } diff --git a/model/minsky.cc b/model/minsky.cc index d065d00dc..8249fedb4 100644 --- a/model/minsky.cc +++ b/model/minsky.cc @@ -1783,10 +1783,13 @@ namespace minsky } 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) {