class EchartWidget(flx.Widget): echart_id = flx.StringProp( "_echart_id", settable=True, doc="""The unique id to distinguish this echart from other echarts""", ) echart_options = flx.DictProp({}, settable=True, doc="""the echarts options""") echart_div_style = flx.StringProp( "width: 800px;height:400px;", settable=True, doc="""The style for the div which contain echart""", ) def get_options(self): global window myChart = f"myChart_{self.echart_id}" return window[myChart] @flx.action def update_options(self, my_option): myChart = self.get_options() self._mutate_echart_options(my_option) myChart.setOption(self.echart_options) @flx.action def show_chart(self): myChart = self.get_options() myChart.setOption(self.echart_options) def _render_dom(self): global window node = [ flx.create_element( "div", { "id": self.echart_id, "style": self.echart_div_style }, "", ), flx.create_element( "script", {"type": "text/javascript"}, f""" // based on prepared DOM, initialize echarts instance var myChart_{self.echart_id} = echarts.init( document.getElementById('{self.echart_id}')); """, ), ] self.show_chart() return node
class MyApp(flx.JsComponent): """ This the root of the app, accessible via self.root on any component. It functions as a central data-store. In this case it is a JsComponent, but it can also be a PyComponent if that makes more sense. """ first_name = flx.StringProp(settable=True) last_name = flx.StringProp(settable=True) def init(self): View()
class Web(flx.Widget): name = flx.StringProp('John Doe', settable=True) age = flx.IntProp(22, settable=True) @flx.action def increase_age(self): self._mutate_age(self.age + 1) def _create_dom(self): # Use this method to create a root element for this widget. # If you just want a <div> you don't have to implement this. return flx.create_element('div') # the default is <div> def _render_dom(self): # Use this to determine the content. This method may return a # string, a list of virtual nodes, or a single virtual node # (which must match the type produced in _create_dom()). return [ flx.create_element('span', {}, 'Hello', flx.create_element('b', {}, self.name), '! '), flx.create_element( 'span', {}, 'I happen to know that your age is %i.' % self.age), flx.create_element('br'), flx.create_element('button', {'onclick': self.increase_age}, 'Next year ...') ]
class ColabPainting(flx.PyWidget): """ The Python side of the app. There is one instance per connection. """ color = flx.ColorProp(settable=True, doc="Paint color") status = flx.StringProp('', settable=True, doc="Status text") def init(self): self.set_color(random.choice(COLORS)) self.widget = ColabPaintingView(self) self._update_participants() @flx.action def add_paint(self, pos): """ Add paint at the specified position. """ relay.add_paint_for_all(pos, self.color.hex) @relay.reaction('add_paint_for_all') # note that we connect to relay here def _any_user_adds_paint(self, *events): """ Receive global paint event from the relay, invoke action on view. """ for ev in events: self.widget.add_paint_to_canvas(ev.pos, ev.color) @flx.manager.reaction('connections_changed') def _update_participants(self, *events): if self.session.status: sessions = flx.manager.get_connections(self.session.app_name) n = len(sessions) del sessions self.set_status('%i persons are painting' % n)
def init(self, py): self.py = py self.file_name = flx.StringProp('') self.file_input = FileInput() with flx.VBox(): flx.Label(style="background:#cfc;", wrap=1, text="") with flx.HSplit(flex=1): with flx.VBox(style="border:1px solid #777;", ): flx.Label(text="Properties Tree") self.tree = TreeWithControls(py, flex=1, max_selected=1) with flx.VBox(style="border:1px solid #777;"): flx.Label(text="Property", style="") with flx.VBox(flex=1): with flx.VBox(flex=1, style=""): self.combo = ui.ComboBox(editable=True, options=()) self.field = ui.LineEdit( placeholder_text="type here") with flx.HBox(flex=1, style="max-height: 20px;"): self.pick_file = ui.Button(text='...') self.do_upload = ui.Button(text='Upload', disabled=True) with flx.VBox(flex=5): flx.Label(text="Info", style="") self.info = flx.Label( text="", style="white-space: pre-line;") with flx.VBox(style="border:1px solid #777;", flex=1): flx.Label(text="Raw", style="") self.rawLabel = flx.Label( text="", style="white-space: pre-line;") self.update_btn = ui.Button(text="Apply", style="width: 100px;")
class HTMLPreview(MyWidget): '''iframe with srcdoc instead of src support''' CSS = ''' .flx-HTMLPreview{ border: 1px solid; } ''' srcdoc = flx.StringProp('', settable=True) def _create_dom(self): return flx.create_element('iframe', {'srcdoc': self.srcdoc})
class MyConsole(MyWidget): text = flx.StringProp('') def init(self): super().init(flex=1) self.wconsole = flx.MultiLineEdit(style=('height:100%;' 'width:100%;' 'background:#222225;' 'font-family: monospace;' 'font-size: larger;' 'color:white;' 'overflow-y:scroll')) self.scrolling = 0 @flx.action def set_output(self, text): self.wconsole.set_text(text) self.bottom_scroll() @flx.action def append_output(self, text): self.set_output(self.wconsole.text + text) @flx.action def clear_output(self, text): self.wconsole.set_text('') async def bottom_scroll(self, text): # workaround for scrolling after element actually grows self.scrolling += 1 if self.scrolling == 1: elem = self.wconsole.node while self.scrolling > 0: await self.sleep(10) elem.scrollTop = elem.scrollHeight self.scrolling -= 1
class Run(flx.PyWidget): exterior_wall_tuple = flx.TupleProp((1, 10), settable=True) exterior_roof_tuple = flx.TupleProp((1, 9), settable=True) exterior_window_tuple = flx.TupleProp((1, 3), settable=True) eastrate_tuple = flx.TupleProp((0.05, 0.3), settable=True) westrate_tuple = flx.TupleProp((0.05, 0.3), settable=True) southrate_tuple = flx.TupleProp((0.05, 0.3), settable=True) northrate_tuple = flx.TupleProp((0.05, 0.3), settable=True) direction_tuple = flx.TupleProp((0, 359), settable=True) airchange_tuple = flx.TupleProp((0, 39), settable=True) cop_tuple = flx.TupleProp((1, 4), settable=True) east_shading_tuple = flx.TupleProp((0, 1), settable=True) west_shading_tuple = flx.TupleProp((0, 1), settable=True) south_shading_tuple = flx.TupleProp((0, 1), settable=True) north_shading_tuple = flx.TupleProp((0, 1), settable=True) infiltration_airchange_tuple = flx.TupleProp((1, 3), settable=True) mutation_param_int = flx.IntProp(4, settable=True) num_of_generation_int = flx.IntProp(50, settable=True) num_of_individual_int = flx.IntProp(50, settable=True) num_of_tour_particps_int = flx.IntProp(2, settable=True) max_proc_int = flx.IntProp(8, settable=True) floor_height_float = flx.FloatProp(2.8, settable=True) window_height_float = flx.FloatProp(1.5, settable=True) window_edge_height_float = flx.FloatProp(1, settable=True) heating_setpoint_float = flx.FloatProp(18, settable=True) cooling_setpoint_float = flx.FloatProp(26, settable=True) apmv_upper_float = flx.FloatProp(0.5, settable=True) apmv_lower_float = flx.FloatProp(-0.5, settable=True) weather_file_str = flx.StringProp( '../WeatherData/CHN_Chongqing.Chongqing.Shapingba.575160_CSWD.epw', settable=True) idf_file_str = flx.StringProp('shading_model_6-0603-1.idf', settable=True) output_path_str = flx.StringProp('temp/', settable=True) def init(self): self.moo = MooWidget(self) @flx.action def run_moo(self): # the actual range used by the algorithm is set here. paras = [ discrete_interval(tuple(self.moo.root.exterior_wall_tuple)), discrete_interval(tuple(self.moo.root.exterior_roof_tuple)), discrete_interval(tuple(self.moo.root.exterior_window_tuple)), tuple(self.moo.root.eastrate_tuple), tuple(self.moo.root.westrate_tuple), tuple(self.moo.root.southrate_tuple), tuple(self.moo.root.northrate_tuple), tuple(self.moo.root.direction_tuple), tuple(self.moo.root.airchange_tuple), discrete_interval(tuple(self.moo.root.cop_tuple)), discrete_interval(tuple(self.moo.root.east_shading_tuple)), discrete_interval(tuple(self.moo.root.west_shading_tuple)), discrete_interval(tuple(self.moo.root.south_shading_tuple)), discrete_interval(tuple(self.moo.root.north_shading_tuple)), discrete_interval(tuple( self.moo.root.infiltration_airchange_tuple)) ] """Algorithm parameter""" hyperparameter: Dict = { "MUTATION_PARAM": int(self.moo.root.mutation_param_int), "NUM_OF_GENERATIONS": int(self.moo.root.num_of_generation_int), "NUM_OF_INDIVIDUALS": int(self.moo.root.num_of_individual_int), "NUM_OF_TOUR_PARTICIPS": int(self.moo.root.num_of_tour_particps_int), "CONCURRENCY": True, "MAX_PROC": int(self.moo.root.max_proc_int) } """other constants""" constants: Dict = { "FLOOR_HEIGHT": float(self.moo.root.floor_height_float), "WINDOW_HEIGHT": float(self.moo.root.window_height_float), "WINDOW_EDG_HEIGHT": float(self.moo.root.window_edge_height_float), "HEATING_SETPOINT": float(self.moo.root.heating_setpoint_float), "COOLING_SETPOINT": float(self.moo.root.cooling_setpoint_float), "APMV_UPPER": float(self.moo.root.apmv_upper_float), "APMV_LOWER": float(self.moo.root.apmv_lower_float) } """path constants""" paths: Dict = { "WEATHER_FILE": str(self.moo.root.weather_file_str), "IDF_FILE": str(self.moo.root.idf_file_str), "OUTPUT_PATH": str(self.moo.root.output_path_str) } __import__('pprint').pprint(paras) __import__('pprint').pprint(hyperparameter) __import__('pprint').pprint(constants) __import__('pprint').pprint(paths) moo_run(paras, hyperparameter, constants, paths) @flx.action def stop(self): sys.exit(0)
class Relay(flx.Component): # def init(self): # super().init() # self.time = "Relay Default Time" # self.newTime = False # # def setTime(self, time): # self.time = time # self.newTime = True vin = flx.StringProp("", settable=True) timeString = flx.StringProp("", settable=True) voltage = flx.FloatProp(0, settable=True) capacity = flx.FloatProp(0, settable=True) pandaRecording = flx.IntProp(0, settable=True) pandaGps = flx.IntProp(0, settable=True) vehicleControlRunning = flx.BoolProp(False, settable=True) @flx.reaction('vin') def on_vin(self, *events): for ev in events: self.updateVin(ev.new_value) @flx.reaction('timeString') def on_timeString(self, *events): for ev in events: self.updateTime(ev.new_value) @flx.reaction('voltage') def on_voltage(self, *events): for ev in events: self.updateVoltage(ev.new_value) @flx.reaction('capacity') def on_voltage(self, *events): for ev in events: self.updateCapacity(ev.new_value) @flx.reaction('pandaRecording') def on_pandaRecording(self, *events): for ev in events: self.updatePandaRecording(ev.new_value) @flx.reaction('pandaGps') def on_pandaGps(self, *events): for ev in events: self.updatePandaGps(ev.new_value) @flx.reaction('vehicleControlRunning') def on_vehicleControlRunning(self, *events): for ev in events: self.updateVehicleControlRunning(ev.new_value) """ Global object to relay paint events to all participants. """ @flx.emitter def updateVin(self, value): return dict(value=value) @flx.emitter def updateTime(self, value): return dict(value=value) @flx.emitter def updateVoltage(self, value): return dict(value=value) @flx.emitter def updateCapacity(self, value): return dict(value=value) @flx.emitter def updatePandaRecording(self, value): return dict(value=value) @flx.emitter def updatePandaGps(self, value): return dict(value=value) @flx.emitter def updateVehicleControlRunning(self, value): return dict(value=value)
class Example(flx.Widget): persons = flx.TupleProp((), doc=""" People to show cards for""") first_name = flx.StringProp('', settable=True) last_name = flx.StringProp('', settable=True) @flx.action def add_person(self, name, info): """ Add a person to our stack. """ ppl = list(self.persons) ppl.append((name, info)) self._mutate_persons(ppl) def _button_clicked(self, *events): self.add_person(self.first_name, self.last_name) def _render_dom(self): """ This function gets automatically called when needed; Flexx is aware of what properties are used here. """ # Create form elements form_nodes = [ flx.create_element( 'div', {'class': 'form-group mb-2'}, flx.create_element( 'input', { 'class': 'form-control', 'id': 'inputFirstName', 'oninput': lambda e: self.set_first_name(e.target.value) }, 'First name')), flx.create_element( 'div', {'class': 'form-group mx-sm-3 mb-2'}, flx.create_element( 'input', { 'class': 'form-control', 'id': 'inputLastName', 'oninput': lambda e: self.set_last_name(e.target.value) }, 'Last name')), flx.create_element('button', { 'class': 'btn btn-primary mb-2', 'onclick': self._button_clicked }, 'Submit'), ] # Create virtual DOM nodes for all persons. We use bootstrap cards card_nodes = [] for name, info in self.persons: person_node = flx.create_element( 'div', {'class': 'card'}, flx.create_element( 'div', {'class': 'card-body'}, flx.create_element('h5', {'class': 'card-title'}, name), flx.create_element('p', {'class': 'card-text'}, info), )) card_nodes.append(person_node) # Compose finaly DOM tree return flx.create_element( 'div', {}, flx.create_element('div', {'class': 'form-inline'}, form_nodes), *card_nodes)
class Store(flx.PyComponent): username = flx.StringProp(settable=True)
class RobotModelWidget(flx.Widget): """ A Robot model Rviz window based on ros3djs. """ host_ip = flx.StringProp("127.0.0.1", settable=True, doc=""" The IP of the host computer. """) base_link = flx.StringProp("/base_link", settable=True, doc=""" The base link frame of the robot. """) rosbridge_port = flx.IntProp(9090, settable=True, doc=""" The port of rosbridge websocket. """) resources_port = flx.IntProp(9091, settable=True, doc=""" The port of web server serving .dae files for urdf. """) robot_description = flx.StringProp("/sam/simple_description", settable=True, doc=""" The ros param with the robot description. """) def _create_dom(self): global document node = document.createElement('div') self.viewernode = document.createElement('div') self.viewernode.id = 'urdf' node.appendChild(self.viewernode) return node def _render_dom(self): self.viewer_init() return super()._render_dom() @flx.action def viewer_init(self): global window #, document if self.initialised: return self.ros = window.ROSLIB.Ros( {'url': 'ws://' + self.host_ip + ':' + str(self.rosbridge_port)}) # Create the main viewer. self.viewer = window.ROS3D.Viewer({ 'divID': 'urdf', 'width': window.innerWidth, 'height': window.innerHeight, 'antialias': True, 'background': '#002233' }) # Add a grid. self.viewer.addObject(window.ROS3D.Grid({'color': '#0181c4'})) # Setup a client to listen to TFs. self.tfClient = window.ROSLIB.TFClient({ 'ros': self.ros, 'fixedFrame': self.base_link, #"sam/base_link", 'angularThres': 0.01, 'transThres': 0.01, 'rate': 10.0 }) # Setup the URDF client. self.urdfClient = window.ROS3D.UrdfClient({ 'param': self.robot_description, 'path': 'http://' + self.host_ip + ':' + str(self.resources_port), 'ros': self.ros, 'tfClient': self.tfClient, 'rootObject': self.viewer.scene, 'loader': window.ROS3D.COLLADA_LOADER_2 }) self.initialised = True @flx.reaction('size') def __on_size(self, *events): if self.viewer: self.viewer.resize(window.innerWidth, window.innerHeight)
class MyPrompt(MyWidget): options = flx.ListProp([]) n_options = flx.IntProp(5) ref = flx.StringProp('MyID') def init(self): super().init() self.label = {} with flx.VBox() as self.wmain: self.label['above'] = flx.Label(text='Text above', flex=1) with flx.HBox(): self.winput = MyLineEdit(flex=1) with flx.VBox(): self.dots_above = MyDots(text='···') with flx.VBox() as self.woptions_box: pass self.dots_below = MyDots(text='···') self.woptions = [] self.show_more = 0 self.index = 0 self.shift = 0 self.focus_element = self.winput @flx.emitter def emit_option(self, option): return dict(value=option, ref=self.ref, text=self.winput.text) @flx.emitter def emit_text(self, text): return dict(value=text, ref=self.ref) @flx.emitter def emit_escape(self): return dict(ref=self.ref) @flx.emitter def emit_interrupt(self): return dict(ref=self.ref) @flx.action def set_focus(self): self._set_focus() async def _set_focus(self): elem = self.focus_element while elem.node.offsetParent == None: await self.sleep(50) elem.node.focus() return async def select_text(self): await self.sleep(50) self.winput.node.select() return @flx.action def set_properties(self, kwargs): if 'prefill' in kwargs: self.winput.set_text(kwargs.pop('prefill')) self.select_text() if 'placeholder' in kwargs: self.winput.set_placeholder_text(kwargs.pop('placeholder')) for key in ['above']: if key in kwargs: value = kwargs.pop(key) elem = self.label[key] if value is None: elem.set_text('hidden') elem.node.hidden = True else: elem.node.hidden = False elem.set_text(value) if 'ref' in kwargs: self._mutate_ref(kwargs['ref']) keys = ['options', 'n_options'] if any([key in kwargs for key in keys]): kw = kwargs kw['options'] = kw.get('options', self.options) kw['n_options'] = kw.get('n_options', self.n_options) self.set_options(kw.pop('options'), kw.pop('n_options')) for key, val in kwargs.items(): print(f'Error: unhandled key={key}, val={val}') return @flx.action def set_options(self, options, n_options=None): if n_options == None: n_options = 5 if not self.winput: return self._mutate_options(options) self._mutate_n_options(n_options) self.pre_match = {} for s in self.options: self.pre_match[s] = self.my_grams(s) self.filtered = self.options self.index = 0 self.shift = 0 self.redraw_options() @flx.reaction('woptions_box.children*.pointer_click') def _listen_clicks(self, *events): for ev in events: self.listen_click(ev.source.text) def listen_click(self, option): self.winput.node.select() # Select text self.emit_option(option) self.options.remove(option) self.options.insert(0, option) self.index = 0 self.shift = 0 self.redraw_options() return @flx.reaction('key_down') def listen_keys(self, *events): for ev in events: if ev.modifiers == 'Ctrl' and ev.key == 'c' and self.winput.text == '': self.emit_interrupt() elif ev.modifiers: continue elif ev.key == 'Escape': self.emit_escape() elif ev.key == 'Enter': if len(self.woptions): option = self.woptions[self.index].text self.listen_click(option) else: self.emit_text(self.winput.text) elif ev.key == 'ArrowDown': if self.index + 1 < len(self.woptions): self.index += 1 elif self.shift + self.n_options < len(self.filtered): self.shift += 1 self.redraw_options() elif ev.key == 'ArrowUp': redraw = True if self.index > 0: self.index -= 1 elif self.shift: self.shift -= 1 else: redraw = False if redraw: self.redraw_options() return @flx.reaction('winput.text') def listen_winput(self, *events): if self.winput.text == '': self.filtered = self.options else: score = self.fuzzy_scores(self.winput.text) thr = max(max(score.values()) / 2, 1 / 3) self.filtered = sorted( [s for s in self.options if score[s] > thr], key=lambda s: -score[s], ) self.index = 0 self.shift = 0 self.redraw_options() return def redraw_options(self): to_show = self.filtered[self.shift:self.shift + self.n_options] with self.woptions_box: while len(self.woptions) < len(to_show): self.woptions.append(flx.Button()) while len(self.woptions) > len(to_show): self.woptions.pop().dispose() for i in range(len(to_show)): self.woptions[i].set_text(to_show[i]) style = 'background:#ccc' if i == self.index else 'background:#eee' self.woptions[i].node.style = style if len(self.options) == 1: self.winput.node.hidden = True self.focus_element = self.woptions[0] else: self.winput.node.hidden = False self.focus_element = self.winput self.dots_above.set_visible(self.shift > 0) self.dots_below.set_visible( len(self.filtered) - self.shift > self.n_options) return def my_grams(self, s): n = len(s) s = s.lower() g = {} for i in range(n): g[s[i]] = (g[s[i]] or 0) + 1 if i + 1 < n: g[s[i] + s[i + 1]] = (g[s[i] + s[i + 1]] or 0) + 1 if i + 2 < n: g[s[i] + s[i + 2]] = (g[s[i] + s[i + 1]] or 0) + 1 return g def fuzzy_scores(self, text): x = self.my_grams(text) score = {} for key, y in self.pre_match.items(): hits = total = 0 z = y.copy() for k, v in x.items(): z[k] = (z[k] or 0) - x[k] hits += z[k] >= 0 total += 1 score[key] = hits / total return score