25 #include <cairo_base.h> 46 m_ports.emplace_back(make_shared<InputPort>(*
this));
53 return 0.25*std::min(m_width,m_height)*zoomFactor();
58 return (xx+(0.5+
ravelOffset)*zoomFactor()*m_width-x())*inputRavel.radius()/(zoomFactor()*ravelSize());
63 return (yy+(0.5+
ravelOffset)*zoomFactor()*m_height-y())*inputRavel.radius()/(zoomFactor()*ravelSize());
68 const float dx=xx-x(), dy=yy-y();
69 const float w=0.5*m_width*zoomFactor(), h=0.5*m_height*zoomFactor();
70 return fabs(dx)>=w-resizeHandleSize() && fabs(dx)<=w+resizeHandleSize() &&
71 fabs(dy)>=h-resizeHandleSize() && fabs(dy)<=h+resizeHandleSize() &&
72 (!inputRavel || dx>0 || dy>0);
78 auto sf=resizeHandleSize();
79 const float w=0.5f*m_width*zoomFactor(), h=0.5f*m_height*zoomFactor();
81 drawResizeHandle(cairo,-w,-h,sf,0);
82 drawResizeHandle(cairo,w,-h,sf,0.5*
M_PI);
83 drawResizeHandle(cairo,w,h,sf,0);
84 drawResizeHandle(cairo,-w,h,sf,0.5*
M_PI);
91 const float dx=xx-x(), dy=yy-y();
92 const float w=0.5*m_width*zoomFactor(), h=0.5*m_height*zoomFactor(), b=
border*zoomFactor();
93 return inputRavel && dx>=-w && dx<=b-w && dy>=-h && dy<=b-h;
98 auto dx=xx-x(), dy=yy-y();
99 const float w=0.5*m_width*zoomFactor(), h=0.5*m_height*zoomFactor();
100 return showRavel && inputRavel && (dx<w || dy<h) &&
101 fabs(ravelX(xx))<1.1*inputRavel.radius() && fabs(ravelY(yy))<1.1*inputRavel.radius();
106 const double z=zoomFactor();
107 const double w=0.5*m_width*z, h=0.5*m_height*z, b=
border*z;
108 return (abs(xx-x())<w-b && abs(yy-y())<h-b) || onRavelButton(xx,yy) || inRavel(xx,yy);
115 const double dx=fabs(x-this->x()), dy=fabs(y-this->y());
116 const double w=0.5*m_width*zoomFactor(), h=0.5*m_height*zoomFactor();
117 if (dx < w && dy < h)
124 const float w=0.5*m_width*zoomFactor(), h=0.5*m_height*zoomFactor();
125 return {{x()-w,y()-h},{x()+w,y()-h},{x()-w,y()+h},{x()+w,y()+h}};
135 if (scrollOffset+scrollDelta<scrollMax)
137 scrollOffset+=scrollDelta;
146 if (scrollOffset>scrollDelta)
148 scrollOffset-=scrollDelta;
159 case 0xff52:
case 0xff53:
case 0xff55:
161 case 0xff51:
case 0xff54:
case 0xff56:
177 if (!value || value->rank()<=2)
return;
178 auto idx=value->hypercube().splitIndex(scrollOffset);
179 sliceIndicator=
formattedStr(value->hypercube().xvectors[2], idx[2]);
180 for (
size_t i=3; i<idx.size(); ++i)
181 sliceIndicator+=
" | "+
formattedStr(value->hypercube().xvectors[i], idx[i]);
195 tailStartRow=startRow=0;
196 numRows=std::min(size,
size_t(height/rowHeight+1));
200 numRows=std::min(size,
size_t(0.5*height/rowHeight-1));
201 tailStartRow=size-numRows;
202 if (numRows<size && 2*numRows*rowHeight>height)
206 numRows=std::min(size,
size_t(height/rowHeight-1));
207 tailStartRow=startRow=size-numRows;
212 if (row==startRow+numRows && row<tailStartRow)
217 return row>=tailStartRow+numRows;
224 if (m_ports[0] && (value=m_ports[0]->getVariableValue()) && showRavel && inputRavel )
226 const bool wasEmpty=inputRavel.numHandles()==0;
227 inputRavel.populateFromHypercube(value->hypercube());
228 for (
size_t i=0; i<inputRavel.numHandles(); ++i)
229 inputRavel.displayFilterCaliper(i,
true);
231 switch (value->rank())
235 inputRavel.setOutputHandleIds({0});
238 inputRavel.setOutputHandleIds({0,1});
244 value=inputRavel.hyperSlice(value);
245 if (value->rank()>=2)
247 auto& xv=value->hypercube().xvectors;
248 auto pivot=make_shared<civita::Pivot>();
249 pivot->setArgument(value,{});
250 pivot->setOrientation(vector<string>{xv[1].name,xv[0].name});
251 value=std::move(pivot);
255 if (value && value->rank()>2)
257 const size_t delta=value->hypercube().xvectors[0].size()*value->hypercube().xvectors[1].size();
258 if (delta!=scrollDelta)
265 scrollOffset=scrollDelta=0;
266 scrollMax=value? value->size(): 1;
277 setText(
str(-std::numeric_limits<double>::max()));
282 const cairo::CairoSave cs(cairoContext());
284 cairo_get_current_point(cairoContext(),&x,&y);
285 cairo_rectangle(cairoContext(),x,y,m_width,m_height);
286 cairo_clip(cairoContext());
287 cairo_move_to(cairoContext(),x,y);
296 m_ports[0]->moveTo(x()-0.5*m_width*z,y());
300 displayTooltip(cairo,tooltip());
302 drawResizeHandles(cairo);
305 cairo_scale(cairo,z,z);
308 cairo_stroke_preserve(cairo);
309 cairo_rectangle(cairo,-0.5*m_width,-0.5*m_height,m_width,m_height);
310 cairo_stroke_preserve(cairo);
314 const cairo::CairoSave cs(cairo);
315 cairo_set_source_rgba(cairo,0.5,0.5,0.5,0.5);
316 cairo_set_fill_rule(cairo,CAIRO_FILL_RULE_EVEN_ODD);
319 cairo_new_path(cairo);
323 if (selected) drawSelected(cairo);
325 static const regex pangoMarkup(
"<[^<>]*>");
330 if (!value || !m_ports[0] || m_ports[0]->numWires()==0)
return;
332 pango.setFontSize(12.0);
334 const size_t vertDim=value->rank()>1? 1: 0, horizDim=0;
340 if (value->hypercube().rank()==0)
342 cairo_move_to(cairo,x0,y0);
343 pango.setMarkup(
str((*value)[0]));
350 if (!value->hypercube().xvectors[vertDim].name.empty())
352 const cairo::CairoSave cs(cairo);
353 pango.setMarkup(value->hypercube().xvectors[vertDim].name);
355 cairo_move_to(cairo,x0, -0.5*pango.width());
356 pango.angle=0.5*
M_PI;
360 const cairo::CairoSave cs(cairo);
361 cairo_set_source_rgba(cairo,0,0,0,0.5);
362 cairo_move_to(cairo,x0,-0.5*m_height);
363 cairo_line_to(cairo,x0,0.5*m_height);
368 pango.setMarkup(
"9999");
370 ClippedPango cpango(cairo);
371 const double rowHeight=cpango.m_height;
372 const double colWidth=cpango.m_width;
375 string format=value->hypercube().xvectors[vertDim].dimension.units;
377 if (value->hypercube().rank()>=2)
380 if (value->hypercube().rank()>2)
383 const cairo::CairoSave cs(cairo);
384 cpango.setMarkup(sliceIndicator);
385 cairo_move_to(cairo,0.5*(x0+colWidth+0.5*m_width-cpango.width()), y0);
389 if (!value->hypercube().xvectors[horizDim].name.empty())
391 const cairo::CairoSave cs(cairo);
392 cpango.setMarkup(value->hypercube().xvectors[horizDim].name);
393 cairo_move_to(cairo,0.5*(x0+colWidth+0.5*m_width-cpango.width()), y0);
399 const cairo::CairoSave cs(cairo);
400 cairo_set_source_rgba(cairo,0,0,0,0.5);
401 cairo_move_to(cairo,-0.5*m_width,y0-2.5);
402 cairo_line_to(cairo,0.5*m_width,y0-2.5);
404 cairo_move_to(cairo,x,y0+rowHeight-2.5);
405 cairo_line_to(cairo,0.5*m_width,y0+rowHeight-2.5);
411 auto dims=value->hypercube().dims();
412 double dataHeight=m_height;
415 case 0:
case 1:
break;
416 case 2: dataHeight-=2*(rowHeight+3);
break;
417 default: dataHeight-=3*(rowHeight+3);
break;
419 const ElisionRowChecker adjustRowAndFinish(showRowSlice,dataHeight,rowHeight,dims[vertDim]);
422 auto& xv=value->hypercube().xvectors[vertDim];
423 for (
size_t i=adjustRowAndFinish.startRow; i<xv.size(); ++i)
425 if (adjustRowAndFinish(i,y))
break;
426 cairo_move_to(cairo,x,y);
427 auto sliceLabel=
trimWS(
str(xv[i],format));
428 if (regex_search(sliceLabel,match,pangoMarkup))
429 cpango.setMarkup(sliceLabel);
431 cpango.setText(sliceLabel);
437 if (value->hypercube().rank()==1)
440 const cairo::CairoSave cs(cairo);
441 cairo_set_source_rgba(cairo,0,0,0,0.5);
442 cairo_move_to(cairo,x,-0.5*m_height);
443 cairo_line_to(cairo,x,0.5*m_height);
446 for (
size_t i=adjustRowAndFinish.startRow; i<dims[vertDim]; ++i)
448 if (adjustRowAndFinish(i,y))
break;
449 cairo_move_to(cairo,x,y);
450 auto v=value->atHCIndex(i);
453 cpango.setMarkup(
str(v));
461 format=value->hypercube().xvectors[horizDim].dimension.units;
462 const ElisionRowChecker adjustColAndFinish(showColSlice,m_width-colWidth,colWidth,dims[horizDim]);
463 for (
size_t i=adjustColAndFinish.startRow; i<dims[horizDim]; ++i)
465 if (adjustColAndFinish(i,x))
break;
468 const cairo::CairoSave cs(cairo);
469 cairo_rectangle(cairo,x,y,colWidth,rowHeight);
471 cairo_move_to(cairo,x,y);
472 auto sliceLabel=
trimWS(
str(value->hypercube().xvectors[horizDim][i],format));
473 if (regex_search(sliceLabel,match,pangoMarkup))
474 cpango.setMarkup(sliceLabel);
476 cpango.setText(sliceLabel);
480 const cairo::CairoSave cs(cairo);
481 cairo_set_source_rgba(cairo,0,0,0,0.5);
482 cairo_move_to(cairo,x-2.5,y0);
483 cairo_line_to(cairo,x-2.5,0.5*m_height);
486 for (
size_t j=adjustRowAndFinish.startRow; j<dims[vertDim]; ++j)
488 if (adjustRowAndFinish(j,y))
break;
490 cairo_move_to(cairo,x,y);
492 auto v=value->atHCIndex(i+j*dims[0]+scrollOffset);
495 cpango.setText(
str(v));
500 if (x>0.5*m_width)
break;
505 const cairo::CairoSave cs(cairo);
506 cairo_set_source_rgba(cairo,0,0,0,0.2);
507 for (y=y0+0.8*rowHeight; y<0.5*m_height; y+=2*rowHeight)
509 cairo_rectangle(cairo,x0,y,m_width,rowHeight);
517 cairo_reset_clip(cairo);
518 cairo_rectangle(cairo,-0.5*m_width,-0.5*m_height,m_width,m_height);
525 throw_error(
"input not defined");
#define M_PI
some useful geometry types, defined from boost::geometry
bool inItem(float, float) const override
offset for scrolling through higher ranked inputs
bool inRavel(float, float) const
offset for scrolling through higher ranked inputs
void exportAsCSV(const std::string &filename, bool tabular) const
export the plotted data as a CSV file
void exportAsCSV(const std::string &filename, const std::string &comment="", bool tabular=false) const
export this to a CSV file. If comment is non-empty, it is written as the first line of the file...
bool onKeyPress(int keySym, const std::string &utf8, int state) override
offset for scrolling through higher ranked inputs
double ravelX(double xx) const
ravel coordinate from screen coordinate
double ravelSize() const
size of ravel in screen coordinates
Sheet()
offset for scrolling through higher ranked inputs
void computeValue()
calculates the input value
ElisionRowChecker(ShowSlice slice, double height, double rowHeight, size_t size)
Creation and access to the minskyTCL_obj object, which has code to record whenever Minsky's state cha...
std::vector< Point > corners() const override
offset for scrolling through higher ranked inputs
std::string trimWS(const std::string &s)
ClickType::Type clickType(float x, float y) const override
offset for scrolling through higher ranked inputs
bool onRavelButton(float, float) const
offset for scrolling through higher ranked inputs
double ravelY(double yy) const
offset for scrolling through higher ranked inputs
std::string str(T x)
utility function to create a string representation of a numeric type
virtual bool contains(float xx, float yy) const
A pango that clips text to a standard area suitable for numbers.
void drawResizeHandles(cairo_t *cairo) const override
offset for scrolling through higher ranked inputs
bool onResizeHandle(float x, float y) const override
offset for scrolling through higher ranked inputs
string formattedStr(const XVector &xv, size_t index)
ClippedPango(cairo_t *cairo)
CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::Sheet)
void setSliceIndicator()
offset for scrolling through higher ranked inputs
void draw(cairo_t *cairo) const override
offset for scrolling through higher ranked inputs
Minsky & minsky()
global minsky object
bool scrollUp()
offset for scrolling through higher ranked inputs
bool contains(float x, float y) const override
offset for scrolling through higher ranked inputs
bool scrollDown()
offset for scrolling through higher ranked inputs
bool operator()(size_t &row, double &y) const