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)
522 uqName(
cminsky().variableValues.newName(to_string(
size_t(
this))+
":"+prefix)));
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_rectangle(cairo,0, 0,width, height);
991 svgRenderer.render(cairo,width, height);
996 drawEdgeVariables(cairo);
1002 const cairo::CairoSave cs(cairo);
1003 cairo_scale(cairo, z, z);
1004 cairo_select_font_face
1005 (cairo,
"sans-serif", CAIRO_FONT_SLANT_ITALIC,
1006 CAIRO_FONT_WEIGHT_NORMAL);
1007 cairo_set_font_size(cairo,12);
1010 cairo_text_extents_t bbox;
1011 cairo_text_extents(cairo,title.c_str(),&bbox);
1012 const double w=0.5*bbox.width+2;
1013 const double h=0.5*bbox.height+5;
1018 cairo_rotate(cairo,
M_PI);
1021 const double transparency=displayContents()? 0.25: 1;
1024 cairo_move_to(cairo, -w+1, h-12-0.5*(height)/z);
1025 cairo_set_source_rgba(cairo,0,0,0,transparency);
1026 cairo_show_text(cairo,title.c_str());
1031 displayTooltip(cairo,tooltip());
1033 drawResizeHandles(cairo);
1036 cairo_rectangle(cairo,-0.5*width,-0.5*height,width,height);
1039 drawSelected(cairo);
1043 void Group::draw1edge(
const vector<VariablePtr>& vars, cairo_t* cairo,
1046 float top=0, bottom=0;
1047 const double angle=rotation() *
M_PI / 180.0;
1048 for (
size_t i=0; i<vars.size(); ++i)
1050 const Rotate r(rotation(),0,0);
1053 auto z=v->zoomFactor();
1054 auto t=v->bb.top()*z, b=v->bb.bottom()*z;
1055 if (i>0) y = i%2? top-b: bottom-t;
1056 v->moveTo(r.
x(x,y)+this->x(), r.
y(x,y)+this->y());
1057 const cairo::CairoSave cs(cairo);
1058 cairo_translate(cairo,x,y);
1060 cairo_rotate(cairo,-angle);
1061 v->rotation(rotation());
1071 bottom+=v->height();
1075 void Group::drawEdgeVariables(cairo_t* cairo)
const 1077 float left, right; margins(left,right);
1078 const cairo::CairoSave cs(cairo);
1079 const float z=zoomFactor();
1080 draw1edge(inVariables, cairo, -0.5*(iWidth()*z-left));
1081 draw1edge(outVariables, cairo, 0.5*(iWidth()*z-right));
1087 float notchY(
const vector<VariablePtr>& vars)
1089 if (vars.empty())
return 0;
1090 const float z=vars[0]->zoomFactor();
1091 float top=vars[0]->bb.top()*z, bottom=vars[0]->bb.top()*z;
1092 for (
size_t i=0; i<vars.size(); ++i)
1095 top-=vars[i]->height();
1097 bottom+=vars[i]->height();
1099 return vars.size()%2? top-vars.back()->bb.bottom()*z: bottom-vars.back()->bb.top()*z;
1104 void Group::drawIORegion(cairo_t* cairo)
const 1106 const cairo::CairoSave cs(cairo);
1108 margins(left,right);
1109 const float z=zoomFactor();
1111 cairo_set_source_rgba(cairo,0,1,1,0.5);
1112 const float w=0.5*z*iWidth(), h=0.5*z*iHeight();
1114 cairo_move_to(cairo,-w,-h);
1116 cairo_line_to(cairo,-w,y-dy);
1117 cairo_line_to(cairo,left-w-4*z,y-dy);
1118 cairo_line_to(cairo,left-w,y);
1119 cairo_line_to(cairo,left-w-4*z,y+dy);
1120 cairo_line_to(cairo,-w,y+dy);
1121 cairo_line_to(cairo,-w,h);
1122 cairo_line_to(cairo,left-w,h);
1123 cairo_line_to(cairo,left-w,-h);
1124 cairo_close_path(cairo);
1128 cairo_move_to(cairo,w,-h);
1130 cairo_line_to(cairo,w,y-dy);
1131 cairo_line_to(cairo,w-right-2*z,y-dy);
1132 cairo_line_to(cairo,w-right+2*z,y);
1133 cairo_line_to(cairo,w-right-2*z,y+dy);
1134 cairo_line_to(cairo,w,y+dy);
1135 cairo_line_to(cairo,w,h);
1136 cairo_line_to(cairo,w-right,h);
1137 cairo_line_to(cairo,w-right,-h);
1138 cairo_close_path(cairo);
1142 cairo_rectangle(cairo,-w,-h,2*w,-
topMargin*z);
1146 cairo_rectangle(cairo,-w,h,2*w,
topMargin*z);
1151 void Group::margins(
float& left,
float& right)
const 1154 auto tmpMouseFocus=mouseFocus;
1156 for (
auto& i: inVariables)
1158 assert(i->type()!=VariableType::undefined);
1160 if (i->width()>left) left=i->width();
1162 for (
auto& i: outVariables)
1164 assert(i->type()!=VariableType::undefined);
1166 if (i->width()>right) right=i->width();
1168 mouseFocus=tmpMouseFocus;
1171 float Group::rotFactor()
const 1174 const float ac=abs(
cos(rotation()*
M_PI/180));
1175 static const float invSqrt2=1/
sqrt(2);
1179 rotFactor=1.15/
sqrt(1-ac*ac);
1185 for (
auto& v: inVariables)
1188 for (
auto& v: outVariables)
1194 void Group::normaliseGroupRefs(
const shared_ptr<Group>&
self)
1196 for (
auto& i: items)
1198 for (
auto& g: groups)
1201 g->normaliseGroupRefs(g);
1206 void Group::flipContents()
1208 for (
auto& i: items)
1210 i->moveTo(x()-i->m_x,i->y());
1213 for (
auto& i: groups)
1215 i->moveTo(x()-i->m_x,i->y());
1220 vector<string> Group::accessibleVars()
const 1224 for (
auto& i: items)
1225 if (
auto v=i->variableCast())
1226 r.insert(v->name());
1229 for (g=g->group.lock().get(); g; g=g->group.lock().get())
1230 for (
auto& i: g->items)
1231 if (
auto v=i->variableCast())
1240 return vector<string>(r.begin(),r.end());
1246 zoom(x(),y(),b.
zoom/(relZoom*zoomFactor()));
1251 std::string Group::defaultExtension()
const 1253 if (findAny(&GroupItems::items, [](
const ItemPtr& i){
return dynamic_cast<Ravel*
>(i.get());}))
1258 void Group::autoLayout()
1264 void Group::randomLayout()
1270 vector<Summary> Group::summariseGodleys()
const 1273 recursiveDo(&GroupItems::items, [&](
const Items&,Items::const_iterator i) {
1274 if (
auto g=dynamic_cast<GodleyIcon*>(i->get()))
1276 auto summary=g->summarise();
1277 r.insert(r.end(),summary.begin(), summary.end());
1284 void Group::renameAllInstances(
const std::string&
valueId,
const std::string& newName)
1288 string uqFromName=(p!=string::npos)?
valueId.substr(p+1):
valueId;
1289 string uqNewName = newName.substr(newName[0]==
':'? 1: 0);
1290 set<GodleyIcon*> godleysToUpdate;
1292 auto numItems=this->numItems();
1295 (&GroupItems::items, [&](
Items&,Items::iterator i)
1297 if (
auto v=(*i)->variableCast())
1301 if (
auto g=dynamic_cast<GodleyIcon*>(v->controller.lock().get()))
1303 if (varScope==g->group.lock() ||
1305 g->table.rename(uqFromName, uqNewName);
1308 auto externalVarScope=
scope(g->group.lock(),
':'+uqNewName);
1310 if (!externalVarScope)
1311 externalVarScope=
scope(g->group.lock(),
':'+uqFromName);
1313 if (varScope==externalVarScope || (
isGlobal(varScope) &&
isGlobal(externalVarScope)))
1315 g->table.rename(
':'+uqFromName,
':'+uqNewName);
1317 godleysToUpdate.insert(g);
1322 v->name(varScope==v->group.lock()? uqNewName: (
':'+uqNewName));
1323 if (
auto vv=v->vValue())
1324 v->retype(vv->type());
1329 assert(this->numItems()==numItems);
1330 for (
auto g: godleysToUpdate)
1333 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
void recentreItems(const T &items, float xc, float yc)
void randomizeLayout(Group &g)
randomly place items on canvas
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
float x(float x, float y) const