Example #1
0
    def refresh_selection(self, root_node, selected_node):
        if self.selected_node["id"] not in self.node_coords:
            self.draw(self.root, self.selected_node, center_on_selection=True)
        self.selected_node = selected_node
        if not self.selected_node.get("open", False):
            self.expand_node(self.selected_node)
            self.draw(self.root, self.selected_node, center_on_selection=True)
            return
        self.delete_textbox()
        old_active = self.active
        self.active = self.get_active()

        for node in old_active:
            if node not in self.active:
                self.canvas.itemconfig(f'lines-{node["id"]}',
                                       fill=inactive_line_color(),
                                       width=1)
                self.canvas.itemconfig(f'ghostlines-{node["id"]}',
                                       fill=inactive_line_color())
                self.canvas.itemconfig(f'text-{node["id"]}',
                                       fill=inactive_text_color())
                self.canvas.itemconfig(f'box-{node["id"]}',
                                       outline=inactive_line_color(),
                                       width=1)

        for node in self.active:
            self.canvas.itemconfig(f'text-{node["id"]}',
                                   fill=active_text_color())
            if self.node_selected(node):
                self.canvas.itemconfig(f'box-{node["id"]}',
                                       outline=selected_line_color(),
                                       width=2)
                self.canvas.itemconfig(f'lines-{node["id"]}',
                                       fill=selected_line_color(),
                                       width=2)
                self.canvas.itemconfig(f'ghostlines-{node["id"]}',
                                       fill=selected_line_color())
            else:
                self.canvas.itemconfig(f'box-{node["id"]}',
                                       outline=active_line_color(),
                                       width=1)
                self.canvas.itemconfig(f'lines-{node["id"]}',
                                       fill=active_line_color(),
                                       width=1)
            if not self.state.visualization_settings["chapter_mode"] \
                    and self.state.tree_node_dict[node["id"]].get("visited", False):
                self.canvas.itemconfig(f'box-{node["id"]}',
                                       fill=visited_node_bg_color())

        self.center_view_on_node(self.selected_node)
Example #2
0
    def draw_expand_node_button(self, node, nodex, nodey, ghost=False):
        text_id = self.canvas.create_text(
            nodex - 4,
            nodey - 6,
            fill='white',
            activefill=BLUE,
            font=(self.font, self.get_text_size()),
            text='+',
            tags=[f'expand-{node["id"]}', 'data', 'text'],
            anchor=tkinter.NW)
        padding = (-5, -5, 5, 5)
        bbox = self.canvas.bbox(text_id)
        box = tuple(map(lambda i, j: i + j, padding, bbox))
        outline_color = inactive_line_color()
        fill = visited_node_bg_color() if ghost else expand_button_color()
        rect_id = self.canvas.create_rectangle(
            box,
            outline=outline_color,
            activeoutline=BLUE,
            fill=fill,
            tags=[f'expand-box-{node["id"]}', 'data'])
        self.canvas.tag_raise(text_id, rect_id)
        self.canvas.tag_bind(f'expand-{node["id"]}',
                             "<Button-1>",
                             lambda event, _node=node: self.expand_node(_node))
        self.canvas.tag_bind(f'expand-box-{node["id"]}',
                             "<Button-1>",
                             lambda event, _node=node: self.expand_node(_node))

        return box
Example #3
0
    def draw_textbox(self, node, nodex, nodey):
        active = node in self.active
        text_color = active_text_color() if active else inactive_text_color()
        width = self.root_width if node['id'] == self.root[
            'id'] else self.state.visualization_settings['text_width']

        if self.state.visualization_settings["chapter_mode"]:
            text = node["chapter"]["title"]
        else:
            text = self.split_text(
                node) if self.overflow_display == 'PAGE' else node['text']

        text_id = self.canvas.create_text(
            nodex,
            nodey,
            fill=text_color,
            activefill=BLUE,
            font=(self.font, self.get_text_size()),
            width=width,
            text=text,
            tags=[f'text-{node["id"]}', 'data', 'text'],
            anchor=tkinter.NW)
        padding = (-10, -10, 10, 10)
        bbox = self.canvas.bbox(text_id)
        box = tuple(map(lambda i, j: i + j, padding, bbox))

        # TODO different for chapter mode
        fill = visited_node_bg_color() if node.get(
            "visited", False) else unvisited_node_bg_color()
        outline_color = selected_line_color() if self.node_selected(node) else \
            (active_line_color() if active else inactive_line_color())
        width = 2 if active else 1
        rect_id = round_rectangle(x1=box[0],
                                  x2=box[2],
                                  y1=box[1],
                                  y2=box[3],
                                  canvas=self.canvas,
                                  outline=outline_color,
                                  width=width,
                                  activeoutline=BLUE,
                                  fill=fill,
                                  tags=[f'box-{node["id"]}', 'data'])
        self.canvas.tag_raise(text_id, rect_id)

        if self.state.visualization_settings["chapter_mode"]:
            self.canvas.tag_bind(
                f'box-{node["id"]}',
                "<Button-1>",
                lambda event, node_id=node["chapter"][
                    "root_id"]: self.select_node(node_id=node_id))

            self.canvas.tag_bind(
                f'text-{node["id"]}',
                "<Button-1>",
                lambda event, node_id=node["chapter"][
                    "root_id"]: self.select_node(node_id=node_id))
        else:
            self.canvas.tag_bind(
                f'text-{node["id"]}',
                "<Button-1>",
                lambda event, node_id=node["id"]: self.edit_node(
                    node_id=node_id, box=box, text=node['text']))
            self.textbox_events[
                node["id"]] = lambda node_id=node["id"]: self.edit_node(
                    node_id=node_id, box=box, text=node['text'])
            self.canvas.tag_bind(f'box-{node["id"]}', "<Button-1>",
                                 self.box_click(node["id"], box, node["text"]))

        # TODO collapsing and buttons for chapters...

        if not self.state.visualization_settings["chapter_mode"]:
            if node is not self.root:
                self.draw_collapse_button(node, box)
            if self.state.visualization_settings["showbuttons"]:
                self.draw_buttons(node, box)
            self.draw_bookmark_star(node, box)
        return box
Example #4
0
    def draw_tree(self, node, nodex, nodey):
        self.node_coords[node["id"]] = (nodex, nodey)

        if self.state.visualization_settings["chapter_mode"]:
            bbox = self.draw_textbox(node, nodex, nodey)
            padding = 10
        else:
            if not node.get("open", False):
                bbox = self.draw_expand_node_button(node, nodex, nodey)
                return collapsed_offset

            display_text = self.state.visualization_settings[
                'display_text'] and self.showtext
            if display_text:
                bbox = self.draw_textbox(node, nodex, nodey)
                padding = 10
            else:
                bbox = (nodex, nodey, nodex, nodey)
                padding = 0

        textheight = bbox[3] - bbox[1]
        text_width = bbox[2] - bbox[0]
        width_diff = self.state.visualization_settings['text_width'] - text_width \
            if (self.state.visualization_settings['display_text'] and fixed_level_width
                and not self.state.visualization_settings["chapter_mode"]) else 0

        offset = textheight  # TODO vertical
        # Draw children with increasing offsets
        child_offset = 0

        # TODO why?
        level_distance = chapter_leveldist if self.state.visualization_settings['chapter_mode'] \
            else self.state.visualization_settings['level_distance']

        leaf_distance = chapter_leaf_distance if self.state.visualization_settings['chapter_mode'] \
            else self.state.visualization_settings['leaf_distance']

        for child in node['children']:
            childx = nodex + level_distance + text_width + width_diff
            childy = nodey + child_offset
            parentx = nodex + text_width
            parenty = nodey
            # TODO if vertical

            child_offset += leaf_distance
            child_offset += self.draw_tree(child, childx, childy)

            # Draw line to child

            if self.node_selected(child):
                color = selected_line_color()
                width = 2
            else:
                active = child in self.active
                color = active_line_color() if active else inactive_line_color(
                )
                width = 2 if active else 1

            goto_id = node["chapter"][
                "root_id"] if self.state.visualization_settings[
                    'chapter_mode'] else child["id"]
            self.draw_line(parentx - padding,
                           parenty - padding,
                           childx - padding,
                           childy - padding,
                           name=f'lines-{child["id"]}',
                           fill=color,
                           activefill=BLUE,
                           width=width,
                           offset=smooth_line_offset,
                           smooth=True,
                           method=lambda event, node_id=goto_id: self.
                           controller.nav_select(node_id=node_id))

        #TODO lightmode
        # if "ghostchildren" in node:
        #     parentx = nodex + text_width
        #     parenty = nodey
        #     for ghost_id in node["ghostchildren"]:
        #         ghost = self.state.tree_node_dict.get(ghost_id, None)
        #         if ghost is None:
        #             continue
        #         if ghost.get("open", False) and ghost["id"] in self.node_coords:
        #             ghostx, ghosty = self.node_coords[ghost["id"]]
        #             if tree_structure_map[ghost["id"]] == selected_id:
        #                 color = active_line_color()
        #             else:
        #                 color = inactive_line_color()
        #             self.draw_line(parentx - offset, parenty - offset, ghostx - offset, ghosty - offset,
        #                            name=f'ghostlines-{ghost["id"]}',
        #                            fill=color, activefill=BLUE, offset=smooth_line_offset, smooth=True,
        #                            method=lambda event, node_id=ghost["id"]: self.controller.nav_select(node_id=node_id))
        #         else:
        #             #print("drew collapsed ghostchild")
        #             #TODO fix position
        #             self.draw_line(parentx - offset, parenty - offset,
        #                            parentx + self.state.visualization_settings["level_distance"] - offset,
        #                            parenty - offset,
        #                            name=f'ghostlines-{ghost["id"]}',
        #                            fill=inactive_line_color(), activefill=BLUE, offset=smooth_line_offset, smooth=True,
        #                            method=lambda event, node_id=ghost["id"]: self.controller.nav_select(node_id=node_id))
        #             self.draw_expand_node_button(ghost, parentx + self.state.visualization_settings["level_distance"], parenty, ghost=True)
        #             return

        return offset if child_offset == 0 else child_offset