示例#1
0
class EventWidget(Canvas):
    """ Represents event in GUI """

    supply_width = 60

    def __init__(self, app, index):
        """ Creates EventWidget for given app at given index """
        self.height = 20
        self.app = app
        self.index = index
        self.event = app.my_order.events[index]
        self.at = app.my_order.at[index + 1]
        start = self.at.time
        current = app.scale.get()
        passed_time = current - start
        total_time = self.app.my_order.event_length(self.index)
        dull = total_time == float("inf") or math.isnan(total_time)
        actual_time = max(0, min(passed_time, total_time))
        self.cooldown = self.app.my_order.get_warp_cooldown(self.index)
        if app.place_by_time:
            if not dull:
                time_width = EventWidget.supply_width + len(self.app.my_order.at_time) * 5
                disp = start * 5 - 1
            else:
                time_width = 0
                disp = 0
        else:
            if not dull:
                time_width = max(400, EventWidget.supply_width + max(self.cooldown, total_time) * 5)
            else:
                time_width = 400
            disp = 0
        Canvas.__init__(self, app.event_frame, height=self.height, width=time_width)
        if self.cooldown and not dull:
            cooldown_passed = max(0, min(self.cooldown, current - start))
            self.cooldown_rect = self.create_rectangle(
                EventWidget.supply_width + disp, 2, EventWidget.supply_width + self.cooldown * 5 + disp, self.height
            )
            self.cooldown_fill = self.create_rectangle(
                EventWidget.supply_width + disp,
                2,
                EventWidget.supply_width + cooldown_passed * 5 + disp,
                self.height,
                fill="pink",
            )

        if not dull:
            self.fill = self.create_rectangle(
                EventWidget.supply_width + disp,
                2,
                actual_time * 5 + EventWidget.supply_width + disp,
                self.height,
                fill="aquamarine",
                disabledoutline="",
            )
        self.create_text(2, 2, text=str(self.at.supply) + "/" + str(self.at.cap), anchor=N + W)
        if not dull:
            self.full_time = self.create_rectangle(
                EventWidget.supply_width + disp, 2, total_time * 5 + EventWidget.supply_width + disp, self.height
            )
        self.create_text(EventWidget.supply_width + 5 + disp, 10, text=events[self.event[0]].name, anchor=W)
        self.bind("<Button-1>", self.clicked)
        self.bind("<B1-Motion>", self.drag)
        self.passed_str = str(actual_time) + "/" + str(total_time)
        self.tooltip = ToolTip(self, delay=50)
        self.tooltip.configure(text=self.passed_str + " " + self.app.my_order.get_note(self.index))

        self.rMenu = Menu(self, tearoff=0)
        self.rMenu.add_command(label="Insert above", command=self.insert_above)
        self.rMenu.add_command(label="Insert below", command=self.insert_below)
        self.rMenu.add_command(label="Delete", command=self.delete)
        self.rMenu.add_command(label="Edit note", command=self.note)
        if app.my_order.can_trick(index):
            if app.my_order.uses_trick(index):
                label = "Disable gas trick"
            else:
                label = "Enable gas trick"
            self.rMenu.add_command(label=label, command=self.toggle_trick)

        self.bind("<Button-3>", self.popup)

    def echo(self, event=None):
        """ Prints the event's index, useful for testing binding events """
        print self.index

    def chrono_check(self, chrono_index):
        """ Changes this event to be dashed if able to be Chrono Boosted from chrono_index """

        if self.app.my_order.can_chrono(self.index, chrono_index):
            self.itemconfig(self.full_time, dash=(4, 4))
        else:
            self.itemconfig(self.full_time, dash=None)

    def clicked(self, click_event):
        """ On click, check if Chrono Boost is active, and if so, Chrono Boost this event
            Otherwise, prepare dragging this event to other indexes """
        if self.app.chrono >= 0 and self.app.my_order.can_chrono(self.index, self.app.chrono):
            self.app.insert_chrono(self.index)
            self.app.chrono = -1
        else:
            self.app.drag = self.index

    def drag(self, drag_event):
        """ Calculates mouse position relative to dragged event, moves event if difference is large enough """
        change = 0
        if self.index == self.app.drag:
            if drag_event.y > 40:
                change = (drag_event.y - 13) / 27
            elif drag_event.y < -14:
                change = (drag_event.y + 14) / 27
        elif self.index - 1 >= self.app.drag:
            change = self.index - self.app.drag - int(drag_event.y < 14)
        elif self.index + 1 <= self.app.drag:
            change = -(self.app.drag - self.index - int(drag_event.y > 14))
        if change:
            self.app.my_order.move(self.app.drag, self.app.drag + change)
            self.app.drag += change
            self.app.refresh()

    def update(self, current):
        """ Updates the time completion of this event given current time """

        start = self.at.time
        if self.app.place_by_time:
            disp = start * 5 - 1
        else:
            disp = 0
        passed_time = current - start
        total_time = self.app.my_order.event_length(self.index)
        dull = total_time == float("inf") or math.isnan(total_time)
        actual_time = max(0, min(passed_time, total_time))
        if not dull:
            self.coords(
                self.fill,
                EventWidget.supply_width + disp,
                2,
                actual_time * 5 + EventWidget.supply_width + disp,
                self.height,
            )
            if self.cooldown:
                cooldown_passed = max(0, min(self.cooldown, current - start))
                self.coords(
                    self.cooldown_fill,
                    EventWidget.supply_width + disp,
                    2,
                    EventWidget.supply_width + cooldown_passed * 5 + disp,
                    self.height,
                )
        self.passed_str = str(actual_time) + "/" + str(total_time)
        self.tooltip.configure(text=self.passed_str + " " + self.app.my_order.get_note(self.index))

    def popup(self, event):
        """ Creates right-click menu """
        self.rMenu.post(event.x_root, event.y_root)

    def insert_above(self):
        """ Insert event option above this event """
        self.app.insert_event_choose(self.index)

    def insert_below(self):
        """ Insert event option below this event """
        self.app.insert_event_choose(self.index + 1)

    def delete(self):
        """ Remove this event from the build order """
        self.app.my_order.delete(self.index)
        self.app.refresh()

    def note(self):
        """ Allow user to edit note describing this event in a separate window """
        root = Toplevel()
        comment = App(root)
        comment.label = Label(root, text="Comment: ")
        comment.label.pack(side=LEFT)
        comment.entry = Entry(root)
        comment.entry.insert(0, self.app.my_order.get_note(self.index))
        comment.entry.pack(padx=3, side=LEFT)

        def submit():
            self.app.my_order.set_note(self.index, comment.entry.get())
            self.tooltip.configure(text=self.passed_str + " " + self.app.my_order.get_note(self.index))
            comment.master.destroy()

        comment.button = Button(root, text="OK", command=submit)
        comment.button.pack(side=LEFT)

        root.mainloop()

    def toggle_trick(self):
        """ Toggles whether or not this event uses extractor trick """
        self.app.my_order.toggle_trick(self.index)
        self.app.refresh()