def _widget_abbrev_single_value(o): """Make widgets from single values, which can be used as parameter defaults.""" if isinstance(o, string_types): return TextWidget(value=unicode_type(o)) elif isinstance(o, dict): return DropdownWidget(values=o) elif isinstance(o, bool): return CheckboxWidget(value=o) elif isinstance(o, float): min, max, value = _get_min_max_value(None, None, o) return FloatSliderWidget(value=o, min=min, max=max) elif isinstance(o, int): min, max, value = _get_min_max_value(None, None, o) return IntSliderWidget(value=o, min=min, max=max) else: return None
def __init__(self, domains, components, circuit=None, **kwargs): super(CircuitBuilder, self).__init__(**kwargs) self.button_text = "Launch CircuitBuilder" self.description = circuit.name def _resize_inputs(el): el.set_css({"width": "100px"}) ##### make controls self.basic_controls = HorizontalContainer() self.add_component_controls = HorizontalContainer() self.add_port_controls = HorizontalContainer() self.change_component_controls = HorizontalContainer() self.change_port_controls = HorizontalContainer() # 1) basic controls self.reset_view_btn = ButtonWidget(description="Reset view") self.reset_view_btn.on_click(self.reset_view) self.circname = TextWidget(description="Circuit name", value=circuit.name) self.circname.on_displayed(_resize_inputs) self.rename_circ_btn = ButtonWidget(description="Rename") self.rename_circ_btn.on_click(self.rename_circuit) self.add_port_btn = ButtonWidget(description="New Port") self.add_port_btn.on_click(self.show_add_port_controls) self.add_comp_btn = ButtonWidget(description="New Component") self.add_comp_btn.on_click((self.show_add_comp_controls)) # self.download_btn = ButtonWidget(description="SaveAsSVG") # self.download_btn.on_click() self.basic_controls.children = [ self.reset_view_btn, self.circname, self.rename_circ_btn, self.add_port_btn, self.add_comp_btn, ] # 2) add component self.add_comp_type = DropdownWidget(description="ComponentType") self.add_comp_name = TextWidget(description="Component name") self.add_comp_name.on_displayed(_resize_inputs) self.add_comp_add = ButtonWidget(description="Add Component") self.add_comp_add.on_click(self.add_component) self.add_comp_back = ButtonWidget(description="Back") self.add_comp_back.on_click(self.back) self.add_component_controls.children = [ self.add_comp_type, self.add_comp_name, self.add_comp_add, self.add_comp_back, ] # 3) add port self.add_port_name = TextWidget(description="Port name") self.add_port_name.on_displayed(_resize_inputs) self.add_port_domain = DropdownWidget(description="Domain") self.add_port_domain.on_trait_change(self._update_port_directions, "value_name") self.add_port_direction = DropdownWidget(description="Direction", values={"in": "Input", "out": "Output"}) self.add_port_add = ButtonWidget(description="Add Port") self.add_port_add.on_click(self.add_port) self.add_port_back = ButtonWidget(description="Back") self.add_port_back.on_click(self.back) self.add_port_controls.children = [ self.add_port_name, self.add_port_domain, self.add_port_direction, self.add_port_add, self.add_port_back, ] # 4) change component self.mod_comp_name = TextWidget(description="Component name") self.mod_comp_name.on_displayed(_resize_inputs) self.mod_comp_rename = ButtonWidget(description="Rename") self.mod_comp_rename.on_click(self.rename_component) self.mod_comp_delete = ButtonWidget(description="Delete") self.mod_comp_delete.on_click(self.delete_component) self.mod_comp_back = ButtonWidget(description="Back") self.mod_comp_back.on_click(self.back) self.change_component_controls.children = [ self.mod_comp_name, self.mod_comp_rename, self.mod_comp_delete, self.mod_comp_back, ] # 5) change port self.mod_port_name = TextWidget(description="Port name") self.mod_port_name.on_displayed(_resize_inputs) self.mod_port_rename = ButtonWidget(description="Rename") self.mod_port_rename.on_click(self.rename_port) self.mod_port_dec = ButtonWidget(description="<") self.mod_port_inc = ButtonWidget(description=">") self.mod_port_dec.on_click(self.dec_port_order) self.mod_port_inc.on_click(self.inc_port_order) self.mod_port_delete = ButtonWidget(description="Delete") self.mod_port_delete.on_click(self.delete_port) self.mod_port_back = ButtonWidget(description="Back") self.mod_port_back.on_click(self.back) self.change_port_controls.children = [ self.mod_port_name, self.mod_port_rename, self.mod_port_dec, self.mod_port_inc, self.mod_port_delete, self.mod_port_back, ] # has to come at end!! self.domains = domains self.components = components self.circuit = circuit self.circuit.on_trait_change(self._handle_circuit_selection, "selected_element") self.circuit.on_trait_change(self._handle_circuit_name, "name") self.children = [ self.basic_controls, self.add_component_controls, self.add_port_controls, self.change_component_controls, self.change_port_controls, self.circuit ] self.back()
class CircuitBuilder(PopupWidget): """ Adds additional controls to the circuit widget for adding/removing external ports and component instances. """ _view_name = Unicode("CircuitBuilderView", sync=True) circuit = Instance(klass=Circuit, sync=True) domains = List() _domains_by_name = Dict() components = List() _components_by_name = Dict() def _components_changed(self, name, old, new): self.add_comp_type.values = {c.name: c.name for c in new} self._components_by_name = {c.name: c for c in new} def _domains_changed(self, name, old, new): self.add_port_domain.values = {d.name: d.name for d in new} self.add_port_domain.value_name = new[0].name self._domains_by_name = {d.name: d for d in new} self._update_port_directions() def __init__(self, domains, components, circuit=None, **kwargs): super(CircuitBuilder, self).__init__(**kwargs) self.button_text = "Launch CircuitBuilder" self.description = circuit.name def _resize_inputs(el): el.set_css({"width": "100px"}) ##### make controls self.basic_controls = HorizontalContainer() self.add_component_controls = HorizontalContainer() self.add_port_controls = HorizontalContainer() self.change_component_controls = HorizontalContainer() self.change_port_controls = HorizontalContainer() # 1) basic controls self.reset_view_btn = ButtonWidget(description="Reset view") self.reset_view_btn.on_click(self.reset_view) self.circname = TextWidget(description="Circuit name", value=circuit.name) self.circname.on_displayed(_resize_inputs) self.rename_circ_btn = ButtonWidget(description="Rename") self.rename_circ_btn.on_click(self.rename_circuit) self.add_port_btn = ButtonWidget(description="New Port") self.add_port_btn.on_click(self.show_add_port_controls) self.add_comp_btn = ButtonWidget(description="New Component") self.add_comp_btn.on_click((self.show_add_comp_controls)) # self.download_btn = ButtonWidget(description="SaveAsSVG") # self.download_btn.on_click() self.basic_controls.children = [ self.reset_view_btn, self.circname, self.rename_circ_btn, self.add_port_btn, self.add_comp_btn, ] # 2) add component self.add_comp_type = DropdownWidget(description="ComponentType") self.add_comp_name = TextWidget(description="Component name") self.add_comp_name.on_displayed(_resize_inputs) self.add_comp_add = ButtonWidget(description="Add Component") self.add_comp_add.on_click(self.add_component) self.add_comp_back = ButtonWidget(description="Back") self.add_comp_back.on_click(self.back) self.add_component_controls.children = [ self.add_comp_type, self.add_comp_name, self.add_comp_add, self.add_comp_back, ] # 3) add port self.add_port_name = TextWidget(description="Port name") self.add_port_name.on_displayed(_resize_inputs) self.add_port_domain = DropdownWidget(description="Domain") self.add_port_domain.on_trait_change(self._update_port_directions, "value_name") self.add_port_direction = DropdownWidget(description="Direction", values={"in": "Input", "out": "Output"}) self.add_port_add = ButtonWidget(description="Add Port") self.add_port_add.on_click(self.add_port) self.add_port_back = ButtonWidget(description="Back") self.add_port_back.on_click(self.back) self.add_port_controls.children = [ self.add_port_name, self.add_port_domain, self.add_port_direction, self.add_port_add, self.add_port_back, ] # 4) change component self.mod_comp_name = TextWidget(description="Component name") self.mod_comp_name.on_displayed(_resize_inputs) self.mod_comp_rename = ButtonWidget(description="Rename") self.mod_comp_rename.on_click(self.rename_component) self.mod_comp_delete = ButtonWidget(description="Delete") self.mod_comp_delete.on_click(self.delete_component) self.mod_comp_back = ButtonWidget(description="Back") self.mod_comp_back.on_click(self.back) self.change_component_controls.children = [ self.mod_comp_name, self.mod_comp_rename, self.mod_comp_delete, self.mod_comp_back, ] # 5) change port self.mod_port_name = TextWidget(description="Port name") self.mod_port_name.on_displayed(_resize_inputs) self.mod_port_rename = ButtonWidget(description="Rename") self.mod_port_rename.on_click(self.rename_port) self.mod_port_dec = ButtonWidget(description="<") self.mod_port_inc = ButtonWidget(description=">") self.mod_port_dec.on_click(self.dec_port_order) self.mod_port_inc.on_click(self.inc_port_order) self.mod_port_delete = ButtonWidget(description="Delete") self.mod_port_delete.on_click(self.delete_port) self.mod_port_back = ButtonWidget(description="Back") self.mod_port_back.on_click(self.back) self.change_port_controls.children = [ self.mod_port_name, self.mod_port_rename, self.mod_port_dec, self.mod_port_inc, self.mod_port_delete, self.mod_port_back, ] # has to come at end!! self.domains = domains self.components = components self.circuit = circuit self.circuit.on_trait_change(self._handle_circuit_selection, "selected_element") self.circuit.on_trait_change(self._handle_circuit_name, "name") self.children = [ self.basic_controls, self.add_component_controls, self.add_port_controls, self.change_component_controls, self.change_port_controls, self.circuit ] self.back() def _handle_circuit_selection(self): e = self.circuit.selected_element if e: if isinstance(e, Port) and e.is_ext: self.back() self.show_mod_port_controls(e) return elif isinstance(e, ComponentInstance): self.back() self.show_mod_comp_controls(e) return self.back() def _handle_circuit_name(self): self.circname.value = self.circuit.name self.description = self.circuit.name def reset_view(self, *_): self.circuit.zoom = (0., 0., 1.) def back(self, *_): for c in [ self.add_component_controls, self.add_port_controls, self.change_component_controls, self.change_port_controls, ]: c.visible = False self.basic_controls.visible = True def show_mod_comp_controls(self, c): self.basic_controls.visible = False self.change_component_controls.visible = True self.mod_comp_name.value = c.name def show_mod_port_controls(self, p): self.basic_controls.visible = False self.change_port_controls.visible = True self.mod_port_name.value = p.name def show_add_port_controls(self, *_): self.basic_controls.visible = False self.add_port_controls.visible = True def show_add_comp_controls(self, *_): self.basic_controls.visible = False self.add_component_controls.visible = True def _update_port_directions(self): d = self._domains_by_name.get(self.add_port_domain.value_name, False) if isinstance(d, Domain): self.add_port_direction.visible = d.causal def rename_circuit(self, *_): if len(self.circname.value): self.circuit.name = self.circname.value def add_component(self, *_): ctype = self._components_by_name[self.add_comp_type.value_name] cname = self.add_comp_name.value if len(cname) and not cname in self.circuit.c: new_comp = ctype.make_instance(cname) self.circuit.component_instances = self.circuit.component_instances + [new_comp] def add_port(self, *_): d = self._domains_by_name[self.add_port_domain.value_name] dir = self.add_port_direction.value_name if not d.causal: dir = "inout" pname = self.add_port_name.value if len(pname) and not pname in self.circuit.p: newp = Port(name=pname, domain=d, direction=dir) self.circuit.ports = self.circuit.ports + [newp] def rename_component(self, *_): c = self.circuit.selected_element if not isinstance(c, ComponentInstance): return newname = self.mod_comp_name.value if len(newname) and not newname in self.circuit.c: del self.circuit.c[c.name] c.name = newname self.circuit.c[c.name] = c def rename_port(self, *_): p = self.circuit.selected_element if not isinstance(p, Port): return newname = self.mod_port_name.value if len(newname) and not newname in self.circuit.p: del self.circuit.p[p.name] p.name = newname self.circuit.p[p.name] = p def delete_component(self, *_): c = self.circuit.selected_element if not isinstance(c, ComponentInstance) \ or not c in self.circuit.component_instances: return self.circuit.component_instances = filter(lambda cc: cc is not c, self.circuit.component_instances) for p in c.ports: for cc in p.connections_in + p.connections_out: cc.remove() self.circuit.selected_element = None def delete_port(self, *_): p = self.circuit.selected_element if not isinstance(p, Port) \ or not p in self.circuit.ports: return self.circuit.ports = filter(lambda pp: pp is not p, self.circuit.ports) for c in p.connections_in + p.connections_out: c.remove() self.circuit.selected_element = None def dec_port_order(self, *_): p = self.circuit.selected_element if not isinstance(p, Port) \ or not p in self.circuit.ports: return ps = list(self.circuit.ports) ii = ps.index(p) ps.pop(ii) ii = max(1, ii) self.circuit.ports = ps[:ii-1] + [p] + ps[ii-1:] def inc_port_order(self, *_): p = self.circuit.selected_element if not isinstance(p, Port) \ or not p in self.circuit.ports: return ps = list(self.circuit.ports) ii = ps.index(p) ps.pop(ii) self.circuit.ports = ps[:ii+1] + [p] + ps[ii+1:]
class CircuitBuilder(PopupWidget): """ Comprehensive circuit creation widget that has control dialogs for adding/modifying component instances as well as external ports. """ _view_name = Unicode("CircuitBuilderView", sync=True) circuit = Instance(klass=Circuit, sync=True) domains = List() _domains_by_name = Dict() components = List() _components_by_name = Dict() def __init__(self, domains, components, circuit, **kwargs): super(CircuitBuilder, self).__init__(**kwargs) if isinstance(circuit, str): circuit = Circuit(name=circuit) self.button_text = "Launch CircuitBuilder" self.description = circuit.name def _resize_inputs(el): el.set_css({"width": "100px"}) # #### make controls self.basic_controls = HorizontalContainer() self.add_component_controls = HorizontalContainer() self.add_port_controls = HorizontalContainer() self.change_component_controls = HorizontalContainer() self.change_port_controls = HorizontalContainer() # 1) basic controls self._reset_view_btn = ButtonWidget(description="Reset view") self._reset_view_btn.on_click(self.reset_view) self._circuit_name = TextWidget(description="Circuit name", value=circuit.name) self._circuit_name.on_displayed(_resize_inputs) self._rename_circ_btn = ButtonWidget(description="Rename") self._rename_circ_btn.on_click(self._rename_circuit) self._add_port_btn = ButtonWidget(description="New Port") self._add_port_btn.on_click(self.add_port_dialog) self._add_comp_btn = ButtonWidget(description="New Component") self._add_comp_btn.on_click(self.add_component_dialog) self.basic_controls.children = [ self._reset_view_btn, self._circuit_name, self._rename_circ_btn, self._add_port_btn, self._add_comp_btn, ] # 2) add component self._add_comp_type = DropdownWidget(description="ComponentType") self._add_comp_name = TextWidget(description="Component name") self._add_comp_name.on_displayed(_resize_inputs) self._add_comp_add = ButtonWidget(description="Add Component") self._add_comp_add.on_click(self._add_component) self._add_comp_back = ButtonWidget(description="Back") self._add_comp_back.on_click(self.back) self.add_component_controls.children = [ self._add_comp_type, self._add_comp_name, self._add_comp_add, self._add_comp_back, ] # 3) add port self._add_port_name = TextWidget(description="Port name") self._add_port_name.on_displayed(_resize_inputs) self._add_port_domain = DropdownWidget(description="Domain") self._add_port_domain.on_trait_change(self._update_port_directions, "value_name") self._add_port_direction = DropdownWidget(description="Direction", values={"in": "Input", "out": "Output"}) self._add_port_add = ButtonWidget(description="Add Port") self._add_port_add.on_click(self._add_port) self._add_port_back = ButtonWidget(description="Back") self._add_port_back.on_click(self.back) self.add_port_controls.children = [ self._add_port_name, self._add_port_domain, self._add_port_direction, self._add_port_add, self._add_port_back, ] # 4) change component self._mod_comp_name = TextWidget(description="Component name") self._mod_comp_name.on_displayed(_resize_inputs) self._mod_comp_rename = ButtonWidget(description="Rename") self._mod_comp_rename.on_click(self._rename_component) self._mod_comp_delete = ButtonWidget(description="Delete") self._mod_comp_delete.on_click(self.delete_selected_component) self._mod_comp_back = ButtonWidget(description="Back") self._mod_comp_back.on_click(self.back) self.change_component_controls.children = [ self._mod_comp_name, self._mod_comp_rename, self._mod_comp_delete, self._mod_comp_back, ] # 5) change port self._mod_port_name = TextWidget(description="Port name") self._mod_port_name.on_displayed(_resize_inputs) self._mod_port_rename = ButtonWidget(description="Rename") self._mod_port_rename.on_click(self._rename_port) self._mod_port_dec = ButtonWidget(description="<") self._mod_port_inc = ButtonWidget(description=">") self._mod_port_dec.on_click(self.move_selected_port_up) self._mod_port_inc.on_click(self.move_selected_port_down) self._mod_port_delete = ButtonWidget(description="Delete") self._mod_port_delete.on_click(self.delete_selected_port) self._mod_port_back = ButtonWidget(description="Back") self._mod_port_back.on_click(self.back) self.change_port_controls.children = [ self._mod_port_name, self._mod_port_rename, self._mod_port_dec, self._mod_port_inc, self._mod_port_delete, self._mod_port_back, ] # has to come at end!! self.domains = domains self.components = components self.circuit = circuit self.circuit.on_trait_change(self._handle_circuit_selection, "selected_element") self.circuit.on_trait_change(self._handle_circuit_name, "name") self.children = [ self.basic_controls, self.add_component_controls, self.add_port_controls, self.change_component_controls, self.change_port_controls, self.circuit ] self.back() # noinspection PyDocstring def reset_view(self, *_): """ Reset the pan and zoom of the circuit editor widget. """ self.circuit.zoom = (0., 0., 1.) # noinspection PyDocstring def back(self, *_): """ Quit all sub-dialogs and display the default controls for renaming the circuit. """ for c in [ self.add_component_controls, self.add_port_controls, self.change_component_controls, self.change_port_controls, ]: c.visible = False self.basic_controls.visible = True def modify_component_dialog(self, c): """ Show the control dialog for modifying a component. :param c: The component to be modified """ self.basic_controls.visible = False self.change_component_controls.visible = True self._mod_comp_name.value = c.name def modify_port_dialog(self, p): """ Show the control dialog for modifying an external port. :param p: The external port to be modified """ self.basic_controls.visible = False self.change_port_controls.visible = True self._mod_port_name.value = p.name # noinspection PyDocstring def add_port_dialog(self, *_): """ Show the dialog to add a new external port. """ self.basic_controls.visible = False self.add_port_controls.visible = True # noinspection PyDocstring def add_component_dialog(self, *_): """ Show the dialog to add a new component instance. """ self.basic_controls.visible = False self.add_component_controls.visible = True # noinspection PyDocstring,PyTypeChecker def delete_selected_component(self, *_): """ Delete the currently selected component. """ c = self.circuit.selected_element if not isinstance(c, ComponentInstance) \ or not c in self.circuit.component_instances: return self.circuit.component_instances = filter(lambda comp: comp is not c, self.circuit.component_instances) # noinspection PyTypeChecker for p in c.ports: for cc in p.connections_in + p.connections_out: cc.remove() self.circuit.selected_element = None # noinspection PyDocstring,PyTypeChecker def delete_selected_port(self, *_): """ Delete the currently selected external port. """ p = self.circuit.selected_element if not isinstance(p, Port) \ or not p in self.circuit.ports: return self.circuit.ports = filter(lambda pp: pp is not p, self.circuit.ports) # noinspection PyUnresolvedReferences for c in p.connections_in + p.connections_out: c.remove() self.circuit.selected_element = None # noinspection PyDocstring,PyTypeChecker def move_selected_port_up(self, *_): """ Move the selected port up in the overall order of external ports. """ p = self.circuit.selected_element if not isinstance(p, Port) \ or not p in self.circuit.ports: return ps = list(self.circuit.ports) ii = ps.index(p) ps.pop(ii) ii = max(1, ii) self.circuit.ports = ps[:ii - 1] + [p] + ps[ii - 1:] # noinspection PyDocstring,PyTypeChecker def move_selected_port_down(self, *_): """ Move the selected port down in the overall order of external ports. """ p = self.circuit.selected_element if not isinstance(p, Port) \ or not p in self.circuit.ports: return ps = list(self.circuit.ports) ii = ps.index(p) ps.pop(ii) self.circuit.ports = ps[:ii + 1] + [p] + ps[ii + 1:] # noinspection PyUnusedLocal def _components_changed(self, name, old, new): self._add_comp_type.values = {c.name: c.name for c in new} self._components_by_name = {c.name: c for c in new} # noinspection PyUnusedLocal def _domains_changed(self, name, old, new): self._add_port_domain.values = {d.name: d.name for d in new} self._add_port_domain.value_name = new[0].name self._domains_by_name = {d.name: d for d in new} self._update_port_directions() def _handle_circuit_selection(self): e = self.circuit.selected_element if e: if isinstance(e, Port) and e.is_ext: self.back() self.modify_port_dialog(e) return elif isinstance(e, ComponentInstance): self.back() self.modify_component_dialog(e) return self.back() def _handle_circuit_name(self): self._circuit_name.value = self.circuit.name self.description = self.circuit.name def _update_port_directions(self): d = self._domains_by_name.get(self._add_port_domain.value_name, False) if isinstance(d, Domain): self._add_port_direction.visible = d.causal def _rename_circuit(self, *_): if len(self._circuit_name.value): self.circuit.name = self._circuit_name.value # noinspection PyUnresolvedReferences def _add_component(self, *_): ctype = self._components_by_name[self._add_comp_type.value_name] cname = self._add_comp_name.value if len(cname) and not cname in self.circuit.c: new_comp = ctype.make_instance(cname) self.circuit.component_instances = self.circuit.component_instances + [new_comp] # noinspection PyUnresolvedReferences def _add_port(self, *_): d = self._domains_by_name[self._add_port_domain.value_name] direction = self._add_port_direction.value_name if not d.causal: direction = "inout" pname = self._add_port_name.value if len(pname) and not pname in self.circuit.p: newp = Port(name=pname, domain=d, direction=direction) self.circuit.ports = self.circuit.ports + [newp] def _rename_component(self, *_): c = self.circuit.selected_element if not isinstance(c, ComponentInstance): return newname = self._mod_comp_name.value if len(newname) and not newname in self.circuit.c: del self.circuit.c[c.name] c.name = newname self.circuit.c[c.name] = c def _rename_port(self, *_): p = self.circuit.selected_element if not isinstance(p, Port): return newname = self._mod_port_name.value if len(newname) and not newname in self.circuit.p: del self.circuit.p[p.name] p.name = newname self.circuit.p[p.name] = p