27 #include <cairo_base.h> 30 #include "bookmark.rcd" 41 SVGRenderer Group::svgRenderer;
50 double Group::operator()(
const std::vector<double>& p)
52 if (outVariables.empty())
return nan(
"");
56 vector<Integral> integrals;
58 auto flow(ValueVector::flowVars);
61 auto iVar=inVariables.begin();
64 while (iVar!=inVariables.end() && (*iVar)->inputWired()) ++iVar;
65 if (iVar==inVariables.end())
break;
66 flow[(*iVar)->vValue()->idx()]=v;
69 for (
auto& i: equations)
70 i->eval(flow.data(), flow.size(),ValueVector::stockVars.data());
71 return flow[outVariables[0]->vValue()->idx()];
74 std::string Group::formula()
const 76 if (outVariables.empty())
return "0";
80 if (!node)
return "0";
88 string Group::arguments()
const 93 for (
auto& i: inVariables)
96 if (r.str().size()>1) r<<
",";
108 auto clone=cloneMap.find(&p->item());
109 if (clone!=cloneMap.end())
111 for (
size_t i=0; i<p->item().portsSize(); ++i)
112 if (p->item().ports(i).lock()==p)
115 p=clone->second->ports(i).lock();
124 if (
auto g=
group.lock())
125 return g->addGroup(copyUnowned());
131 auto r=make_shared<Group>();
136 const_cast<Group*>(
this)->globalGroup().addGroup(r);
141 map<Item*,ItemPtr> cloneMap;
142 map<IntOp*,bool> integrals;
144 auto itemsCopy=items;
145 for (
auto& i: itemsCopy)
146 if (
auto integ=dynamic_cast<IntOp*>(i.get()))
147 integrals.emplace(integ, integ->coupled());
148 for (
auto& i: itemsCopy)
149 cloneMap[i.get()]=r->addItem(i->clone(),
true);
150 for (
auto& i: groups)
151 cloneMap[i.get()]=r->addGroup(i->copyUnowned());
154 auto f=w->from(), t=w->to();
157 r->addWire(
new Wire(
f,t,w->coords()));
160 for (
auto& v: inVariables)
162 assert(cloneMap.count(v.get()));
163 r->inVariables.push_back(dynamic_pointer_cast<VariableBase>(cloneMap[v.get()]));
164 r->inVariables.back()->controller=
self;
166 for (
auto& v: outVariables)
168 assert(cloneMap.count(v.get()));
169 r->outVariables.push_back(dynamic_pointer_cast<VariableBase>(cloneMap[v.get()]));
170 r->outVariables.back()->controller=
self;
173 for (
auto i: integrals)
175 if (
auto newIntegral=dynamic_cast<IntOp*>(cloneMap[i.first].get()))
177 auto newIntVar=dynamic_pointer_cast<
VariableBase>(cloneMap[i.first->intVar.get()]);
178 if (newIntVar && newIntegral->intVar != newIntVar)
180 r->removeItem(*newIntegral->intVar);
181 newIntegral->intVar=newIntVar;
183 if (i.second != newIntegral->coupled())
184 newIntegral->toggleCoupled();
191 void Group::makeSubroutine()
193 recursiveDo(&GroupItems::items, [
this](
Items&,Items::iterator i)
195 if (
auto v=(*i)->variableCast())
196 if (v->rawName()[0]==
':')
199 for (
auto g=
group.lock(); g; g=g->group.lock())
200 for (
auto& item: g->items)
201 if (
auto vi=item->variableCast())
202 if (vi->valueId()==v->valueId())
203 goto outer_scope_variable_found;
204 v->name(v->rawName().substr(1));
206 outer_scope_variable_found:
214 if (it.plotWidgetCast()==displayPlot.get()) removeDisplayPlot();
215 if (!inDestructor) bookmarks.erase(it.
bookmarkId());
216 for (
auto i=items.begin(); i!=items.end(); ++i)
221 if (
auto v=r->variableCast())
224 remove(inVariables, r);
225 remove(outVariables, r);
226 remove(createdIOvariables, r);
232 for (
auto i=groups.begin(); i!=groups.end(); ++i)
241 for (
auto& g: groups)
242 if (
ItemPtr r=g->removeItem(it))
247 void Group::deleteItem(
const Item& i)
249 if (
auto r=removeItem(i))
251 r->deleteAttachedWires();
252 r->removeControlledItems();
261 for (
auto i=wires.begin(); i!=wires.end(); ++i)
269 for (
auto& g: groups)
270 if (
WirePtr r=g->removeWire(w))
277 for (
auto i=groups.begin(); i!=groups.end(); ++i)
278 if (i->get()==&
group)
285 for (
auto& g: groups)
294 if (
auto g=it.group.lock())
297 auto i=g->findItem(it);
300 return findAny(&Group::items, [&](
const ItemPtr& x){
return x.get()==⁢});
305 if (
auto thisGroup=
self.lock())
307 if (origGroup->higher(*thisGroup))
313 else if (thisGroup->higher(*origGroup))
316 if (v.
name()[0]==
':')
318 if (
auto vv=i->variableCast())
319 if (vv->name()==v.
name().substr(1))
331 ItemPtr GroupItems::addItem(
const shared_ptr<Item>& it,
bool inSchema)
335 if (
auto x=dynamic_pointer_cast<Group>(it))
339 const float x=it->x(), y=it->y();
340 auto origGroup=it->group.lock();
342 if (origGroup.get()==
this)
return it;
344 origGroup->removeItem(*it);
349 if (
auto v=it->variableCast())
356 if (!inSchema) it->moveTo(x,y);
359 if (
auto v=it->variableCast())
361 if (!inSchema && origGroup)
362 renameVar(origGroup, *v);
365 if (units.length()) v->setUnits(units);
369 for (
size_t i=0; i<it->portsSize(); ++i)
371 auto p=it->ports(i).lock();
373 for (
auto& w: p->wires())
376 adjustWiresGroup(*w);
381 if (
auto intOp=dynamic_cast<IntOp*>(it.get()))
384 if (!inSchema && origGroup)
385 renameVar(origGroup, *intOp->intVar);
386 if (
auto oldG=intOp->intVar->group.lock())
389 if (oldG.get()!=
this)
390 addItem(oldG->removeItem(*intOp->intVar),inSchema);
393 addItem(intOp->intVar,inSchema);
394 if (intOp->coupled())
395 intOp->intVar->controller=it;
397 intOp->intVar->controller.reset();
404 void GroupItems::adjustWiresGroup(
Wire& w)
407 assert(w.from() && w.to());
408 shared_ptr<Group> p1=w.from()->item().group.lock(), p2=w.to()->item().group.lock();
410 unsigned l1=p1->level(), l2=p2->level();
411 for (; p1 && l1>l2; l1--) p1=p1->group.lock();
412 for (; p2 && l2>l1; l2--) p2=p2->group.lock();
414 while (p1 && p2 && p1!=p2)
420 if (!p1 || !p2)
return;
421 w.moveIntoGroup(*p1);
424 void Group::splitBoundaryCrossingWires()
428 set<Wire*> wiresToSplit;
430 for (
size_t p=0; p<i->portsSize(); ++p)
431 for (
auto w: i->ports(p).lock()->wires())
432 wiresToSplit.insert(w);
434 for (
auto w: wiresToSplit)
438 auto varsToCheck=createdIOvariables;
439 for (
auto& iv: varsToCheck)
441 assert(iv->ports(1).lock()->input() && !iv->ports(1).lock()->multiWireAllowed());
444 if (!iv->ports(1).lock()->wires().empty())
446 auto fromGroup=iv->ports(1).lock()->wires()[0]->from()->item().group.lock();
447 if (fromGroup.get() ==
this)
450 for (
auto& w: iv->ports(0).lock()->wires())
451 if (w->to()->item().group.lock().get() ==
this)
455 iv->ports(0).lock()->eraseWire(w);
457 addWire(iv->ports(1).lock()->wires()[0]->from(), to);
461 for (
auto& w: iv->ports(0).lock()->wires())
462 if (w->to()->item().group.lock() == fromGroup)
466 iv->ports(0).lock()->eraseWire(w);
468 adjustWiresGroup(*addWire(iv->ports(1).lock()->wires()[0]->from(), to));
472 if (iv->ports(0).lock()->wires().empty() || iv->ports(1).lock()->wires().empty())
477 size_t GroupItems::numItems()
const 479 size_t count=items.size();
480 for (
auto& i: groups) count+=i->numItems();
484 size_t GroupItems::numWires()
const 486 size_t count=wires.size();
487 for (
auto& i: groups) count+=i->numWires();
491 size_t GroupItems::numGroups()
const 493 size_t count=groups.size();
494 for (
auto& i: groups) count+=i->numGroups();
499 void Group::moveContents(
Group& source) {
503 throw error(
"attempt to move a group into itself");
505 auto copyOfItems=source.
items;
506 for (
auto& i: copyOfItems)
511 auto copyOfGroups=source.
groups;
512 for (
auto& i: copyOfGroups)
524 createdIOvariables.push_back(v);
525 v->rotation(rotation());
534 const float z=zoomFactor();
536 const float dx=(x-this->x())*
cos(rotation()*
M_PI/180)-
537 (y-this->y())*
sin(rotation()*
M_PI/180);
538 const float dy=(x-this->x())*
sin(rotation()*
M_PI/180)+
539 (y-this->y())*
cos(rotation()*
M_PI/180);
540 const float w=0.5*iWidth()*z,h=0.5*iHeight()*z;
542 return IORegion::output;
544 return IORegion::input;
546 return IORegion::topBottom;
547 return IORegion::none;
550 void Group::checkAddIORegion(
const ItemPtr& x)
552 if (
auto v=dynamic_pointer_cast<VariableBase>(x))
554 remove(inVariables, v);
555 remove(outVariables, v);
556 switch (inIORegion(v->x(),v->y()))
558 case IORegion::input:
559 inVariables.push_back(v);
562 case IORegion::output:
563 outVariables.push_back(v);
567 v->controller.reset();
574 void Group::resizeOnContents()
576 double x0, x1, y0, y1;
577 contentBounds(x0,y0,x1,y1);
578 const double xx=0.5*(x0+x1), yy=0.5*(y0+y1);
579 const double dx=xx-x(), dy=yy-y();
580 float l,r; margins(l,r);
581 const float z=zoomFactor();
582 m_width=((x1-x0)+l+r)/z;
583 m_height=((y1-y0)+20*z)/z;
587 i->moveTo(i->x()-dx, i->y()-dy);
588 for (
auto& i: groups)
589 i->moveTo(i->x()-dx, i->y()-dy);
626 float z=zoomFactor();
631 iWidth(fabs(b.
x0-b.
x1)/z);
636 double x0, x1, y0, y1;
637 contentBounds(x0,y0,x1,y1);
640 double sx=(fabs(b.
x0-b.
x1)-z*(l+r))/(x1-x0), sy=(fabs(b.
y0-b.
y1)-2*z*
topMargin)/(y1-y0);
645 moveTo(0.5*(b.
x0+b.
x1), 0.5*(b.
y0+b.
y1));
649 bool Group::nocycles()
const 651 set<const Group*> sg;
653 for (
auto i=
group.lock(); i; i=i->group.lock())
654 if (!sg.insert(i.get()).second)
659 GroupPtr GroupItems::addGroup(
const std::shared_ptr<Group>& g)
662 auto origGroup=g->group.lock();
663 if (origGroup.get()==
this)
return g;
665 origGroup->removeGroup(*g);
668 g->self=groups.back();
670 return groups.back();
673 WirePtr GroupItems::addWire(
const std::shared_ptr<Wire>& w)
675 assert(w->from() && w->to());
680 (
const weak_ptr<Port>& fromPw,
const weak_ptr<Port>& toPw,
const vector<float>& coords)
682 auto fromP=fromPw.lock(), toP=toPw.lock();
684 if (!fromP || !toP || &fromP->item()==&toP->item())
688 if (fromP->input() || !toP->input())
692 if (!toP->wires().empty() && !toP->multiWireAllowed())
696 for (
auto& w: toP->wires())
697 if (w->from()==fromP)
701 if (
auto v=toP->item().variableCast())
705 auto w=addWire(
new Wire(fromP, toP, coords));
706 adjustWiresGroup(*w);
712 bool Group::higher(
const Group& x)
const 714 for (
auto& i: groups)
715 if (i.get()==&x)
return true;
716 return any_of(groups.begin(), groups.end(), [&](
const GroupPtr& i){
return i->higher(x);});
719 unsigned Group::level()
const 723 for (
auto i=
group.lock(); i; i=i->group.lock()) l++;
733 for (
auto i=start.group.lock(); i; i=i->group.lock())
747 bool Group::uniqueItems(set<void*>& idset)
const 750 if (!idset.insert(i.get()).second)
return false;
752 if (!idset.insert(i.get()).second)
return false;
753 for (
auto& i: groups)
754 if (!idset.insert(i.get()).second || !i->uniqueItems(idset))
759 float Group::contentBounds(
double& x0,
double& y0,
double& x1,
double& y1)
const 761 const float localZoom=1;
762 x0=numeric_limits<float>::max();
763 x1=-numeric_limits<float>::max();
764 y0=numeric_limits<float>::max();
765 y1=-numeric_limits<float>::max();
770 if (i->left()<x0) x0=i->left();
771 if (i->right()>x1) x1=i->right();
772 if (i->top()<y0) y0=i->top();
773 if (i->bottom()>y1) y1=i->bottom();
776 for (
auto& i: groups)
777 if (i->displayContents())
779 double left, top, right, bottom;
780 i->contentBounds(left,top,right,bottom);
781 if (left<x0) x0=left;
782 if (right>x1) x1=right;
784 if (bottom>y1) y1=bottom;
788 if (i->left()<x0) x0=i->left();
789 if (i->right()>x1) x1=i->right();
790 if (i->top()<y0) y0=i->top();
791 if (i->bottom()>y1) y1=i->bottom();
796 if (x0==numeric_limits<float>::max())
799 for (
auto& i: inVariables)
804 for (
auto& i: outVariables)
809 const int n=inVariables.size()+outVariables.size();
824 float Group::computeDisplayZoom()
826 double x0, x1, y0, y1;
827 const float z=zoomFactor();
828 const float lz=contentBounds(x0,y0,x1,y1);
829 x0=min(x0,
double(x()));
830 x1=max(x1,
double(x()));
831 y0=min(y0,
double(y()));
832 y1=max(y1,
double(y()));
834 displayZoom = 2*max( max(x1-x(), x()-x0)/(iWidth()*z), max(y1-y(), y()-y0)/(iHeight()*z));
837 const float readjust=zoomFactor()/edgeScale() / (displayZoom>1? displayZoom:1);
840 l*=readjust; r*=readjust;
841 displayZoom = max(displayZoom,
842 float(max((x1-x())/(0.5
f*iWidth()*z-r), (x()-x0)/(0.5
f*iWidth()*z-l))));
844 displayZoom*=1.1*rotFactor()/lz;
847 displayZoom=max(displayZoom, 1.0
f);
851 void Group::computeRelZoom()
853 double x0, x1, y0, y1;
854 const double z=zoomFactor();
856 contentBounds(x0,y0,x1,y1);
859 const double dx=x1-x0, dy=y1-y0;
860 if (width()-l-r>0 && dx>0 && dy>0)
861 relZoom=std::min(1.0, std::min((width()-l-r)/(dx), (height()-20*z)/(dy)));
864 const Group* Group::minimalEnclosingGroup(
float x0,
float y0,
float x1,
float y1,
const Item* ignore)
const 866 const float z=zoomFactor();
867 if (x0<x()-0.5*z*iWidth() || x1>x()+0.5*z*iWidth() ||
868 y0<y()-0.5*z*iHeight() || y1>y()+0.5*z*iHeight())
871 for (
auto& g: groups)
872 if (
auto mg=g->minimalEnclosingGroup(x0,y0,x1,y1, ignore))
875 return this!=ignore?
this:
nullptr;
878 void Group::setZoom(
float factor)
880 const bool dpc=displayContents();
885 const float lzoom=localZoom();
886 m_displayContentsChanged = dpc!=displayContents();
887 for (
auto& i: groups)
890 m_displayContentsChanged|=i->displayContentsChanged();
896 const bool dpc=displayContents();
899 m_displayContentsChanged = dpc!=displayContents();
902 for (
auto& i: groups)
904 if (displayContents() && !m_displayContentsChanged)
905 i->zoom(i->x(), i->y(), factor);
906 m_displayContentsChanged|=i->displayContentsChanged();
913 const double w=0.5*iWidth()*z, h=0.5*iHeight()*z;
914 if (onResizeHandle(x,y))
return ClickType::onResize;
915 if (displayContents() && inIORegion(x,y)==IORegion::none)
916 return ClickType::outside;
917 if (
auto item=select(x,y))
918 return item->clickType(x,y);
919 if ((abs(x-this->x())<w && abs(y-this->y())<h+
topMargin*z))
920 return ClickType::onItem;
921 return ClickType::outside;
924 void Group::draw(cairo_t* cairo)
const 926 auto [angle,
flipped]=rotationAsRadians();
930 float leftMargin, rightMargin;
931 margins(leftMargin, rightMargin);
932 const float z=zoomFactor();
934 const unsigned width=z*this->iWidth(), height=z*this->iHeight();
935 const cairo::CairoSave cs(cairo);
936 cairo_rotate(cairo,angle);
942 cairo_rectangle(cairo,-0.5*width,-0.5*height-
topMargin*z, width, height+2*
topMargin*z);
951 const cairo::CairoSave cs(cairo);
952 cairo_translate(cairo, -0.5*width+leftMargin, -0.5*height);
955 const double scalex=double(width-leftMargin-rightMargin)/width;
956 cairo_scale(cairo, scalex, 1);
959 cairo_rectangle(cairo,0,0,width,height);
961 const cairo::CairoSave cs(cairo);
962 cairo_identity_matrix(cairo);
963 cairo_set_line_width(cairo,1);
967 if (!displayContents())
971 const cairo::CairoSave cs(cairo);
974 cairo_translate(cairo,width,height);
975 cairo_rotate(cairo,
M_PI);
978 auto& pt=
const_cast<Plot*
>(
static_cast<const Plot*
>(displayPlot.get()))->plotType;
979 switch (displayPlot->plotType)
981 case PlotWidget::line: pt=Plot::line;
break;
982 case PlotWidget::bar: pt=Plot::bar;
break;
985 displayPlot->Plot::draw(cairo, width, height);
989 cairo_scale(cairo,width/svgRenderer.width(),height/svgRenderer.height());
990 cairo_rectangle(cairo,0, 0,svgRenderer.width(), svgRenderer.height());
992 svgRenderer.render(cairo);
997 drawEdgeVariables(cairo);
1003 const cairo::CairoSave cs(cairo);
1004 cairo_scale(cairo, z, z);
1005 cairo_select_font_face
1006 (cairo,
"sans-serif", CAIRO_FONT_SLANT_ITALIC,
1007 CAIRO_FONT_WEIGHT_NORMAL);
1008 cairo_set_font_size(cairo,12);
1011 cairo_text_extents_t bbox;
1012 cairo_text_extents(cairo,title.c_str(),&bbox);
1013 const double w=0.5*bbox.width+2;
1014 const double h=0.5*bbox.height+5;
1019 cairo_rotate(cairo,
M_PI);
1022 const double transparency=displayContents()? 0.25: 1;
1025 cairo_move_to(cairo, -w+1, h-12-0.5*(height)/z);
1026 cairo_set_source_rgba(cairo,0,0,0,transparency);
1027 cairo_show_text(cairo,title.c_str());
1032 displayTooltip(cairo,tooltip());
1034 drawResizeHandles(cairo);
1037 cairo_rectangle(cairo,-0.5*width,-0.5*height,width,height);
1040 drawSelected(cairo);
1044 void Group::draw1edge(
const vector<VariablePtr>& vars, cairo_t* cairo,
1047 float top=0, bottom=0;
1048 const double angle=rotation() *
M_PI / 180.0;
1049 for (
size_t i=0; i<vars.size(); ++i)
1051 const Rotate r(rotation(),0,0);
1054 auto z=v->zoomFactor();
1055 auto t=v->bb.top()*z, b=v->bb.bottom()*z;
1056 if (i>0) y = i%2? top-b: bottom-t;
1057 v->moveTo(r.
x(x,y)+this->x(), r.
y(x,y)+this->y());
1058 const cairo::CairoSave cs(cairo);
1059 cairo_translate(cairo,x,y);
1061 cairo_rotate(cairo,-angle);
1062 v->rotation(rotation());
1072 bottom+=v->height();
1076 void Group::drawEdgeVariables(cairo_t* cairo)
const 1078 float left, right; margins(left,right);
1079 const cairo::CairoSave cs(cairo);
1080 const float z=zoomFactor();
1081 draw1edge(inVariables, cairo, -0.5*(iWidth()*z-left));
1082 draw1edge(outVariables, cairo, 0.5*(iWidth()*z-right));
1088 float notchY(
const vector<VariablePtr>& vars)
1090 if (vars.empty())
return 0;
1091 const float z=vars[0]->zoomFactor();
1092 float top=vars[0]->bb.top()*z, bottom=vars[0]->bb.top()*z;
1093 for (
size_t i=0; i<vars.size(); ++i)
1096 top-=vars[i]->height();
1098 bottom+=vars[i]->height();
1100 return vars.size()%2? top-vars.back()->bb.bottom()*z: bottom-vars.back()->bb.top()*z;
1105 void Group::drawIORegion(cairo_t* cairo)
const 1107 const cairo::CairoSave cs(cairo);
1109 margins(left,right);
1110 const float z=zoomFactor();
1112 cairo_set_source_rgba(cairo,0,1,1,0.5);
1113 const float w=0.5*z*iWidth(), h=0.5*z*iHeight();
1115 cairo_move_to(cairo,-w,-h);
1117 cairo_line_to(cairo,-w,y-dy);
1118 cairo_line_to(cairo,left-w-4*z,y-dy);
1119 cairo_line_to(cairo,left-w,y);
1120 cairo_line_to(cairo,left-w-4*z,y+dy);
1121 cairo_line_to(cairo,-w,y+dy);
1122 cairo_line_to(cairo,-w,h);
1123 cairo_line_to(cairo,left-w,h);
1124 cairo_line_to(cairo,left-w,-h);
1125 cairo_close_path(cairo);
1129 cairo_move_to(cairo,w,-h);
1131 cairo_line_to(cairo,w,y-dy);
1132 cairo_line_to(cairo,w-right-2*z,y-dy);
1133 cairo_line_to(cairo,w-right+2*z,y);
1134 cairo_line_to(cairo,w-right-2*z,y+dy);
1135 cairo_line_to(cairo,w,y+dy);
1136 cairo_line_to(cairo,w,h);
1137 cairo_line_to(cairo,w-right,h);
1138 cairo_line_to(cairo,w-right,-h);
1139 cairo_close_path(cairo);
1143 cairo_rectangle(cairo,-w,-h,2*w,-
topMargin*z);
1147 cairo_rectangle(cairo,-w,h,2*w,
topMargin*z);
1152 void Group::margins(
float& left,
float& right)
const 1155 auto tmpMouseFocus=mouseFocus;
1157 for (
auto& i: inVariables)
1159 assert(i->type()!=VariableType::undefined);
1161 if (i->width()>left) left=i->width();
1163 for (
auto& i: outVariables)
1165 assert(i->type()!=VariableType::undefined);
1167 if (i->width()>right) right=i->width();
1169 mouseFocus=tmpMouseFocus;
1172 float Group::rotFactor()
const 1175 const float ac=abs(
cos(rotation()*
M_PI/180));
1176 static const float invSqrt2=1/
sqrt(2);
1180 rotFactor=1.15/
sqrt(1-ac*ac);
1186 for (
auto& v: inVariables)
1189 for (
auto& v: outVariables)
1195 void Group::normaliseGroupRefs(
const shared_ptr<Group>&
self)
1197 for (
auto& i: items)
1199 for (
auto& g: groups)
1202 g->normaliseGroupRefs(g);
1207 void Group::flipContents()
1209 for (
auto& i: items)
1211 i->moveTo(x()-i->m_x,i->y());
1214 for (
auto& i: groups)
1216 i->moveTo(x()-i->m_x,i->y());
1221 vector<string> Group::accessibleVars()
const 1225 for (
auto& i: items)
1226 if (
auto v=i->variableCast())
1227 r.insert(v->name());
1230 for (g=g->group.lock().get(); g; g=g->group.lock().get())
1231 for (
auto& i: g->items)
1232 if (
auto v=i->variableCast())
1241 return vector<string>(r.begin(),r.end());
1247 zoom(x(),y(),b.
zoom/(relZoom*zoomFactor()));
1252 std::string Group::defaultExtension()
const 1254 if (findAny(&GroupItems::items, [](
const ItemPtr& i){
return dynamic_cast<Ravel*
>(i.get());}))
1259 void Group::autoLayout()
1265 void Group::randomLayout()
1271 vector<Summary> Group::summariseGodleys()
const 1274 recursiveDo(&GroupItems::items, [&](
const Items&,Items::const_iterator i) {
1275 if (
auto g=dynamic_cast<GodleyIcon*>(i->get()))
1277 auto summary=g->summarise();
1278 r.insert(r.end(),summary.begin(), summary.end());
1285 void Group::renameAllInstances(
const std::string&
valueId,
const std::string& newName)
1289 string uqFromName=(p!=string::npos)?
valueId.substr(p+1):
valueId;
1290 string uqNewName = newName.substr(newName[0]==
':'? 1: 0);
1291 set<GodleyIcon*> godleysToUpdate;
1293 auto numItems=this->numItems();
1296 (&GroupItems::items, [&](
Items&,Items::iterator i)
1298 if (
auto v=(*i)->variableCast())
1302 if (
auto g=dynamic_cast<GodleyIcon*>(v->controller.lock().get()))
1304 if (varScope==g->group.lock() ||
1306 g->table.rename(uqFromName, uqNewName);
1309 auto externalVarScope=
scope(g->group.lock(),
':'+uqNewName);
1311 if (!externalVarScope)
1312 externalVarScope=
scope(g->group.lock(),
':'+uqFromName);
1314 if (varScope==externalVarScope || (
isGlobal(varScope) &&
isGlobal(externalVarScope)))
1316 g->table.rename(
':'+uqFromName,
':'+uqNewName);
1318 godleysToUpdate.insert(g);
1323 v->name(varScope==v->group.lock()? uqNewName: (
':'+uqNewName));
1324 if (
auto vv=v->vValue())
1325 v->retype(vv->type());
1330 assert(this->numItems()==numItems);
1331 for (
auto g: godleysToUpdate)
1334 assert(this->numItems()==numItems);
#define M_PI
some useful geometry types, defined from boost::geometry
const std::string & rawName() const
accessor for the name member (may differ from name() with top level variables)
bool inputWired(const std::string &name) const
returns true if any variable of name name has a wired input
virtual void runItemDeletedCallback(const Item &)
run callback attached to item
G & globalGroup(G &start)
represents rectangular region of a lasso operation
float y(float x, float y) const
size_t scope(const string &name)
extract scope from a qualified variable name
void populateEvalOpVector(EvalOpVector &equations, std::vector< Integral > &integrals)
std::shared_ptr< Item > ItemPtr
float notchY(const vector< VariablePtr > &vars)
std::string uqName(const std::string &name)
extract unqualified portion of name
std::shared_ptr< Wire > WirePtr
string valueId(const string &name)
construct a valueId from fully qualified name @ name should not be canonicalised
rotate (x,y) by rot (in degrees) around the origin (x0, y0) can be used for rotating multiple points ...
bool flipped(double rotation)
returns if the angle (in degrees) is in the second or third quadrant
struct TCLcmd::trap::init_t init
void recentreItems(const T &items, float xc, float yc)
void randomizeLayout(Group &g)
randomly place items on canvas
Creation and access to the minskyTCL_obj object, which has code to record whenever Minsky's state cha...
classdesc::Exclude< std::weak_ptr< Item > > controller
reference to a controlling item - eg GodleyIcon, IntOp or a Group if an IOVar.
std::vector< ItemPtr > Items
static const int topMargin
virtual void bookmarkRefresh()
refresh the bookmark menu after changes
void asgClonedPort(shared_ptr< Port > &p, const map< Item *, ItemPtr > &cloneMap)
const Minsky & cminsky()
const version to help in const correctness
CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::Group)
bool inImage(float x, float y)
return the boost geometry corresponding to this variable's shape
VariableDAGPtr getNodeFromVar(const VariableBase &v)
void requestRedraw()
request a redraw on the screen
bool higher(const Group &) const
returns true if this is higher in the heirarchy than the argument this->higher(*this) is false ...
virtual std::string name() const
variable displayed name
void resizeItems(T &items, double sx, double sy)
void layoutGroup(Group &g)
auto layout group items
std::string bookmarkId() const
Id of bookmark associated with this.
std::shared_ptr< Group > GroupPtr
bool isGlobal(const GroupPtr &g)
void zoom(float &val, float origin, float factor)
base zooming transformation
string to_string(CONST84 char *x)
float x(float x, float y) const