Пример #1
0
class LeafletWidget(flx.Widget):
    """ A widget that shows a slippy/tile-map using Leaflet.
    """
    
    layers = flx.ListProp([], doc="""
        List of tilemap layer tuples: (url, 'Layer').
        """)
    
    zoom = flx.IntProp(8, settable=True, doc="""
        Zoom level for the map.
        """)
    
    min_zoom = flx.IntProp(0, settable=True, doc="""
        self zoom level for the map.
        """)
    
    max_zoom = flx.IntProp(18, settable=True, doc="""
        Maximum zoom level for the map.
        """)
    
    center = flx.FloatPairProp((5.2, 5.5), settable=True, doc="""
        The center of the map.
        """)
    
    show_layers = flx.BoolProp(False, settable=True, doc="""
        Whether to show layers-icon on the top-right of the map.
        """)
    
    show_scale = flx.BoolProp(False, settable=True, doc="""
        Whether to show scale at bottom-left of map.
        """)
    
    @flx.action
    def add_layer(self, url, name=None):
        """ Add a layer to the map.
        """
        # Avoid duplicates
        self.remove_layer(url)
        if name:
            self.remove_layer(name)
        # Add layer
        layers = self.layers + [(url, name or 'Layer')]
        self._mutate_layers(layers)
    
    @flx.action
    def remove_layer(self, url_or_name):
        """ Remove a layer from the map by url or name.
        """
        layers = list(self.layers)
        for i in reversed(range(len(layers))):
            if url_or_name in layers[i]:
                layers.pop(i)
        self._mutate_layers(layers)

    def _create_dom(self):
        global L, document
        node = document.createElement('div')
        self.mapnode = document.createElement('div')
        node.appendChild(self.mapnode)
        self.mapnode.id = 'maproot'
        self.mapnode.style.position = 'absolute'
        self.mapnode.style.top = '0px'
        self.mapnode.style.left = '0px'
        self.map = L.map(self.mapnode)
        self.map.on('zoomend', self.map_handle_zoom)
        self.map.on('moveend', self.map_handle_move)
        self.map.on('click', self.map_handle_mouse)
        self.map.on('dblclick', self.map_handle_mouse)
        # Container to keep track of leaflet layer objects
        self.layer_container = []
        self.layer_control = L.control.layers()
        self.scale = L.control.scale({'imperial': False, 'maxWidth': 200})
        # Set the path for icon images
        L.Icon.Default.prototype.options.imagePath = '_data/shared/'
        return node

    def map_handle_zoom(self, e):
        global isNaN
        zoom = self.map.getZoom()
        if isNaN(zoom):
            return
        if zoom != self.zoom:
            self.set_zoom(zoom)

    def map_handle_move(self, e):
        center_coord = self.map.getCenter()
        center = center_coord.lat, center_coord.lng
        if center != self.center:
            self.set_center(center)

    def map_handle_mouse(self, e):
        latlng = [e.latlng.lat, e.latlng.lng]
        xy = [e.layerPoint.x, e.layerPoint.y]
        self.pointer_event(e.type, latlng, xy)

    @flx.emitter
    def pointer_event(self, event, latlng, xy):
        return {'event': event, 'latlng': latlng, 'xy': xy}

    @flx.reaction
    def __handle_zoom(self):
        self.map.setZoom(self.zoom)

    @flx.reaction
    def __handle_min_zoom(self):
        self.map.setMinZoom(self.min_zoom)

    @flx.reaction
    def __handle_max_zoom(self):
        self.map.setMaxZoom(self.max_zoom)

    @flx.reaction
    def __handle_center(self):
        self.map.panTo(self.center)

    @flx.reaction
    def __handle_show_layers(self):
        if self.show_layers:
            self.map.addControl(self.layer_control)
        else:
            self.map.removeControl(self.layer_control)

    @flx.reaction
    def __handle_show_scale(self):
        if self.show_scale:
            self.map.addControl(self.scale)
        else:
            self.map.removeControl(self.scale)

    @flx.reaction
    def __size_changed(self):
        size = self.size
        if size[0] or size[1]:
            self.mapnode.style.width = size[0] + 'px'
            self.mapnode.style.height = size[1] + 'px'
            # Notify the map that it's container's size changed
            self.map.invalidateSize()

    @flx.reaction
    def __layers_changed(self):
        global L
        for layer in self.layer_container:
            self.layer_control.removeLayer(layer)
            if self.map.hasLayer(layer):
                self.map.removeLayer(layer)
        for layer_url, layer_name in self.layers:
            if not layer_url.endswith('.png'):
                if not layer_url.endswith('/'):
                    layer_url += '/'
                layer_url += '{z}/{x}/{y}.png'
            new_layer = L.tileLayer(layer_url)
            self.layer_container.append(new_layer)
            self.map.addLayer(new_layer)
            self.layer_control.addOverlay(new_layer, layer_name)
Пример #2
0
class IGraph(flx.PyComponent):
    CSS = """
.flx-main-widget{
overflow:scroll;
}
.configure{
overflow:scroll;
}
"""
    graph = flx.AnyProp(None, settable=True)
    graph_options = {
        #        "height": "90%",
    }
    graph_list = flx.ListProp([])
    current_graph = flx.IntProp(0, settable=True)

    def init(self):

        with ui.VSplit():
            with ui.HFix(flex=0):
                self.previous = ui.Button(text="<-", disabled=True, flex=1)
                self.content = ui.Label(flex=0)
                self.next = ui.Button(text="->", disabled=True, flex=1)
            with ui.HSplit(flex=1, spacing=20):
                self.configure = flx.Widget(css_class="configure", flex=0)
                with ui.HFix(flex=1):
                    self.visjs = VisJS(
                        style="background-color: #dddddd;",
                        flex=1,
                    )
        self.refresh()

    @event.reaction("graph")
    def update_viz(self, *events):
        ev = events[-1]
        graph = ev["new_value"]
        old_graph = ev["old_value"]
        if old_graph is None:
            self.visjs.load_viz(graph)
        else:

            def find_by_id(id, iterable):
                try:
                    return [elem for elem in iterable if elem["id"] == id][0]
                except IndexError:
                    return None

            self.visjs.update_viz({
                "nodes": {
                    "add": [
                        node for node in graph["nodes"]
                        if not find_by_id(node["id"], old_graph["nodes"])
                    ],
                    "remove": [
                        node["id"] for node in old_graph["nodes"]
                        if not find_by_id(node["id"], graph["nodes"])
                    ],
                    "update": [
                        node for node in graph["nodes"]
                        if find_by_id(node["id"], old_graph["nodes"])
                        and find_by_id(node["id"], old_graph["nodes"]) != node
                    ]
                },
                "edges": {
                    "add": [
                        edge for edge in graph["edges"]
                        if not find_by_id(edge["id"], old_graph["edges"])
                    ],
                    "remove": [
                        edge["id"] for edge in old_graph["edges"]
                        if not find_by_id(edge["id"], graph["edges"])
                    ],
                    "update": [
                        edge for edge in graph["edges"]
                        if find_by_id(edge["id"], old_graph["edges"])
                        and find_by_id(edge["id"], old_graph["edges"]) != edge
                    ],
                },
                "options": graph["options"],
            })

    @flx.action
    def refresh(self):
        try:
            graph = nx.nx_agraph.read_dot(self.file)
        except ImportError:
            try:
                graph = nx.nx_pydot.read_dot(self.file)
            except TypeError:
                print("TypeError")
                asyncio.get_event_loop().call_later(0.1, self.refresh)
                return

        def uniq_id():
            i = 0
            while True:
                yield i
                i = i + 1

        genid = uniq_id()
        for src in graph.nodes:
            for dst in graph[src]:
                for number in graph[src][dst]:
                    if "smooth.type" not in graph[src][dst][number]:
                        graph[src][dst][number]["smooth.type"] = "curvedCW"
                    if "smooth.roundness" not in graph[src][dst][number]:
                        graph[src][dst][number]["smooth.roundness"] = float(
                            number) / 5.
        graph_desc = {
            "nodes": [{
                "id":
                node_id,
                "label":
                graph.nodes[node_id].get("label", node_id),
                **dotted_dict_to_nested_dict({
                    k: cast_it(v)
                    for k, v in graph.nodes[node_id].items()
                }),
            } for node_id in graph.nodes],
            "edges": [{
                "id":
                next(genid),
                "arrows":
                "to",
                "from":
                src,
                "to":
                dst,
                "number":
                number,
                **dotted_dict_to_nested_dict({
                    k: cast_it(v)
                    for k, v in graph[src][dst][number].items()
                }),
            } for src in graph.nodes for dst in graph[src]
                      for number in graph[src][dst]],
            "options":
            dotted_dict_to_nested_dict({
                **self.graph_options,
                **dict_cast(graph.graph.get("graph", {})),
            })
        }

        gl = len(self.graph_list)
        cg = self.current_graph
        last_graph = (gl != 0 and self.graph_list[-1]) or None
        if graph_desc != last_graph:
            self._mutate_graph_list([graph_desc], 'insert', gl)
            if cg == (gl - 1):
                self.set_current_graph(cg + 1)

        asyncio.get_event_loop().call_later(0.1, self.refresh)

    @flx.reaction("graph_list", "current_graph")
    def _update_buttons(self, *evs):
        self.previous.set_disabled(
            len(self.graph_list) == 1 or self.current_graph == 0)
        self.previous.set_text(
            "{} <-".format(self.current_graph -
                           1) if self.current_graph else "|")
        self.content.set_text("{}".format(self.current_graph))
        self.next.set_disabled(self.current_graph == len(self.graph_list) - 1)
        self.next.set_text("-> {}".format(
            self.current_graph +
            1) if self.current_graph < len(self.graph_list) - 1 else "|")

    @flx.reaction("current_graph")
    def _update_graph(self, *evs):
        self.set_graph(self.graph_list[self.current_graph])

    @event.reaction("previous.pointer_click")
    def _previous(self, *evs):
        self.set_current_graph(self.current_graph - 1)

    @event.reaction("next.pointer_click")
    def _next(self, *evs):
        self.set_current_graph(self.current_graph + 1)
Пример #3
0
class NetworkVisualiser(flx.CanvasWidget):
    _current_node = flx.Property(None, settable=True)
    inputs = flx.ListProp(settable=True)
    neurons = flx.ListProp(settable=True)
    
    def init(self):
        self.ctx = self.node.getContext('2d')
        self.xx = [0.3, 0.3, 0.70, 0.60, 0.50, 0.40, 0.10]#, 0.23, 0.61, 0.88]
        self.yy = [0.33, 0.66, 0.90, 0.60, 0.90, 0.70, 0.55]#, 0.19, 0.11, 0.38]
        self.names = []
        self.node_width = 25
        i = [True, False]
        self._mutate_inputs(i)
        self._mutate_neurons(i)
        self.buttonlabel= flx.Label(text='dgfhdfgh')

    @flx.reaction('pointer_down')
    def _on_pointer_down(self, *events):
        for ev in events:
            w, h = self.size
            # Get closest point
            closest, dist = -1, 999999
            for i in range(len(self.xx)):
                x, y = self.xx[i] * w, self.yy[i] * h
                d = ((x - ev.pos[0]) ** 2 + (y - ev.pos[1]) ** 2) ** 0.5
                if d < dist:
                    closest, dist = i, d
            # Did we touch it or not
            if dist < self.node_width:
                i = closest
                self._set_current_node(i)
           

    @flx.reaction('pointer_up')
    def _on_pointer_up(self, *events):
        self._set_current_node(None)

    @flx.reaction('pointer_move')
    def _on_pointer_move(self, *events):
        ev = events[-1]
        if self._current_node is not None:
            i = self._current_node
            w, h = self.size
            self.xx[i] = ev.pos[0] / w
            self.yy[i] = ev.pos[1] / h
            self.update()
            
    @flx.emitter
    def key_down(self, e):
        return self._create_key_event(e)
    
    @flx.reaction('size', '_current_node', 'inputs', 'neurons')
    def update(self, *events):
        self.draw()
        
    @flx.action
    def update_inputs(self, i):
         self.set_inputs(i)       
          
    @flx.action
    def update_neurons(self, i):
         self.set_neurons(i)    
    
    @flx.action
    def draw(self, inputs, Net):
        ctx = self.ctx
        w, h = self.size
        ctx.fillStyle = "white"#"0d053b"
        #ctx.strokeStyle = "black"
        ctx.fillRect(0, 0, w, h)
        ctx.fillStyle = "red"
        ctx.strokeStyle = "red"
        #Draw rectangles for input signals
        
        for i in range(len(self.inputs)):
            
            if(self.inputs[i]):
                ctx.fillStyle = "yellow"
            else:
                ctx.fillStyle = "blue"
            
            
            posx = w * 0.1
            posy = (h/(len(self.inputs) + 1)) * (i + 1)
            ctx.fillRect(posx, posy, 25, 45)    
            #print(self.inputs[i])
        
        # Get coordinates
        xx = [x * w for x in self.xx]
        yy = [y * h for y in self.yy]
        
        # Draw nodes
        ctx.strokeStyle = '#000'
        ctx.lineWidth = 2
        for i in range(0, len(self.neurons)):
            if(self.neurons[i][0]):
                ctx.fillStyle = 'yellow'
            else:
                ctx.fillStyle = '#acf'
                
            ctx.beginPath()
            ctx.arc(xx[i], yy[i], self.node_width, 0, 6.2831)
            ctx.fill()
            ctx.stroke()
            
            ctx.strokeStyle = "black"
            ctx.font = '25px Calibri';
            ctx.strokeText(self.neurons[i][1], xx[i], yy[i]);


        # Draw lines
        #for i in range(1, len(xx)-2):
        #    ctx.lineCap = "round"
        #    ctx.lineWidth = 3
        #    ctx.strokeStyle = '#008'
         #   
         #   ctx.beginPath()
        #    lineto = ctx.lineTo.bind(ctx)
        #    
         #   lineto(xx[i+0], yy[i+0])
         #   lineto(xx[i+1], yy[i+1])
         #   ctx.stroke()
Пример #4
0
class PanelRxView(flx.Widget):
    CSS = """
        .detail {
            boarder: solid green 3px;
            font-size:small;
            word-wrap:break-word;
            overflow: auto;
        }
        .packet_list { overflow: auto; }
        .flx-TreeWidget {
            border: gray solid 1px;
            font-size: small;
        }
        .flx-TreeItem {
            border-top: white solid 1px;
            text-overflow:ellipse;
            white-space:nowrap;
        }
        .flx-TreeItem:hover {
            background-color: #EEEEEE;
        }
        .flx-TreeItem.selected-true {
            background: blue;
            color: white;
        }
        .flx-TreeWidget .flx-TreeItem > .text.hastitle {
            width: 95%;
        }
        .flx-TreeItem > .title {
            background: white;
            color: gray;
        }
    """

    labels = flx.ListProp(settable=True)
    label_idx = flx.IntProp(settable=True)
    packets = flx.ListProp(settable=True)

    def init(self):
        with flx.HSplit():
            with flx.VBox(flex=1):
                self.summary = flx.TreeWidget(flex=1, max_selected=1)
            with flx.VSplit(flex=1):
                with flx.GroupWidget(css_class="list", flex=6, title="Detail"):
                    self.detail = flx.Label(flex=1, css_class="detail")
                    self.detail.set_wrap(2)
                with flx.GroupWidget(css_class="list", flex=4,
                                     title="hexdump"):
                    self.hexdump = flx.Label(flex=1, css_class="detail")
                    self.hexdump.set_wrap(1)

    @flx.action
    def add_pkt(self, info):
        self.packets.append(
            dict(summary=info['pkt_summary'],
                 detail=info['pkt_detail'],
                 hex=info['pkt_hex']))
        self.add_one_label(info['pkt_summary'])

    @flx.action
    def update_info(self, info):
        if info['packets']:
            self.add_labels(info['packets'])
        if info['hexdump_txt']:
            line = '<pre><code>' + info['hexdump_txt'] + '</ code></ pre>'
            self.hexdump.set_html(line)
        if info['detail_txt']:
            line = '<pre><code>' + info['detail_txt'] + '</ code></ pre>'
            self.detail.set_html(line)

    @flx.action
    def add_labels(self, msg):
        with self.summary:
            for l in msg.splitlines():
                self.add_one_label(l)

    @flx.action
    def add_one_label(self, msg):
        with self.summary:
            l = flx.TreeItem(text=msg, title=str(self.label_idx), checked=None)
        self._mutate_labels([l], 'insert', len(self.labels))
        self._mutate_label_idx(self.label_idx + 1)

    @flx.action
    def clear_labels(self):
        for l in self.labels:
            l.dispose()
        self.labels.clear()
        self._mutate_label_idx(0)
        self.hexdump.set_text('')
        self.detail.set_text('')

    @flx.action
    def clear_info(self):
        self.set_packets([])
        self.clear_labels()

    @flx.reaction('summary.children**.checked', 'summary.children**.selected')
    def _update_detail(self, *events):
        e = events[-1]
        id = int(e.source.title)
        self.show_detail(self.packets[id]['detail'])
        self.show_hexdump(self.packets[id]['hex'])

    def show_detail(self, msg):
        msg = '<pre><code>' + msg + '</code></pre>'
        self.detail.set_html(msg)

    def show_hexdump(self, msg):
        msg = '<pre><code>' + msg + '</code></pre>'
        self.hexdump.set_html(msg)
Пример #5
0
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