示例#1
0
class ContinuousTMPViewer(object):
    def __init__(self,
                 suction_height,
                 regions,
                 tl_x=0,
                 tl_y=0,
                 width=500,
                 height=150,
                 title='Grid',
                 background='tan'):
        self.tk = Tk()
        # tk.geometry('%dx%d+%d+%d'%(width, height, 100, 0))
        self.tk.withdraw()
        self.top = Toplevel(self.tk)
        self.top.wm_title(title)
        self.top.protocol('WM_DELETE_WINDOW', self.top.destroy)

        self.suction_height = suction_height
        self.regions = regions
        self.tl_x = tl_x
        self.tl_y = tl_y
        self.width = width
        self.height = height
        self.canvas = Canvas(self.top,
                             width=self.width,
                             height=self.height,
                             background=background)
        self.canvas.pack()
        # self.center()
        self.move_frame(self.tl_x, self.tl_y)

        max_width = max(
            map(get_width,
                regions.values()))  # Really should take width of max minus min
        self.dist_to_pixel = (self.width - 2 * PIXEL_BUFFER
                              ) / max_width  # Maintains aspect ratio
        self.dist_width = self.width / self.dist_to_pixel
        self.dist_height = self.height / self.dist_to_pixel
        self.ground_height = self.height - self.dist_to_pixel * ENV_HEIGHT
        self.robot_dist = self.dist_height / 2.

        self.robot = []
        self.blocks = []
        self.holding = None
        self.environment = []
        self.draw_environment()

    def center(self):
        self.top.update_idletasks()
        w = self.top.winfo_screenwidth()
        h = self.top.winfo_screenheight()
        size = tuple(
            int(_) for _ in self.top.geometry().split('+')[0].split('x'))
        x = w / 2 - size[0] / 2
        y = h / 2 - size[1] / 2
        self.top.geometry("%dx%d+%d+%d" % (size + (x, y)))

    def move_frame(self, x, y):
        self.top.update_idletasks()
        size = tuple(
            int(_) for _ in self.top.geometry().split('+')[0].split('x'))
        self.top.geometry("%dx%d+%d+%d" % (size + (x, y)))

    def scale_x(self, x):  # x \in [-self.dist_width/2, self.dist_width/2]
        return self.dist_to_pixel * (x + self.dist_width / 2.)

    def scale_y(self, y):  # y \in [0, self.dist_height]
        return self.ground_height - self.dist_to_pixel * y

    def draw_block(self, x, y, width, height, name='', color='blue'):
        self.blocks.extend([
            self.canvas.create_rectangle(self.scale_x(x - width / 2.),
                                         self.scale_y(y),
                                         self.scale_x(x + width / 2.),
                                         self.scale_y(y + height),
                                         fill=color,
                                         outline='black',
                                         width=2),
            self.canvas.create_text(self.scale_x(x),
                                    self.scale_y(y + height / 2),
                                    text=name),
        ])

    # def draw_holding(self, x, width, height, color='blue'):
    #     self.holding = self.canvas.create_rectangle(self.scale_x(x - width / 2.),
    #                                                 self.scale_y(self.robot_dist - SUCTION_HEIGHT / 2 - height),
    #                                                 self.scale_x(x + width / 2.),
    #                                                 self.scale_y(self.robot_dist - SUCTION_HEIGHT / 2),
    #                                                 fill=color, outline='black', width=2)

    def draw_region(self, region, name='', color='red'):
        x1, x2 = map(self.scale_x, region)
        y1, y2 = self.ground_height, self.height
        self.environment.extend([
            self.canvas.create_rectangle(x1,
                                         y1,
                                         x2,
                                         y2,
                                         fill=color,
                                         outline='black',
                                         width=2),
            self.canvas.create_text((x1 + x2) / 2, (y1 + y2) / 2, text=name),
        ])

    def draw_environment(self):
        # TODO: automatically draw in order
        self.environment = []
        for name, region in sorted(self.regions.items(),
                                   key=lambda pair: get_width(pair[1]),
                                   reverse=True):
            self.draw_region(region, name=name, color=name)

    def draw_robot(
        self,
        x,
        y,
        color='yellow'
    ):  # TODO - could also visualize as top grasps instead of side grasps
        #y = self.robot_dist
        self.robot = [
            self.canvas.create_rectangle(
                self.scale_x(x - SUCTION_WIDTH / 2.),
                self.scale_y(y - self.suction_height / 2.),
                self.scale_x(x + SUCTION_WIDTH / 2.),
                self.scale_y(y + self.suction_height / 2.),
                fill=color,
                outline='black',
                width=2),
            self.canvas.create_rectangle(
                self.scale_x(x - STEM_WIDTH / 2.),
                self.scale_y(y + self.suction_height / 2.),
                self.scale_x(x + STEM_WIDTH / 2.),
                self.scale_y(y + self.suction_height / 2. + STEM_HEIGHT),
                fill=color,
                outline='black',
                width=2),
        ]

    def clear_state(self):
        for block in self.blocks:
            self.canvas.delete(block)
        for part in self.robot:
            self.canvas.delete(part)
        if self.holding is not None:
            self.canvas.delete(self.holding)

    def clear_all(self):
        self.canvas.delete('all')

    def save(self, filename):
        # TODO: screen recording based on location like I did before
        # TODO: only works on windows
        # self.canvas.postscript(file='%s.ps'%filename, colormode='color')
        #from PIL import ImageGrab
        try:
            import pyscreenshot as ImageGrab
        except ImportError:
            return None
        x, y = self.top.winfo_x(), 2 * self.top.winfo_y()
        width, height = self.top.winfo_width(), self.top.winfo_height(
        )  # winfo_width, winfo_reqheight
        path = filename + '.png'
        ImageGrab.grab((x, y, x + width, y + height)).save(path)
        return path
    def hiya(self):
        if not self.nand_mode:
            showinfo(
                'Info',
                'Now you will be asked to choose the SD card path that will be used '
                'for installing the custom firmware (or an output folder).\n\nIn order to avoid '
                'boot errors please assure it is empty before continuing.')
            self.sd_path = askdirectory()

            # Exit if no path was selected
            if self.sd_path == '':
                return

        # If adding a No$GBA footer, check if CID and ConsoleID values are OK
        elif self.nand_operation.get() == 2:
            cid = self.cid.get()
            console_id = self.console_id.get()

            # Check lengths
            if len(cid) != 32:
                showerror('Error', 'Bad eMMC CID')
                return

            elif len(console_id) != 16:
                showerror('Error', 'Bad Console ID')
                return

            # Parse strings to hex
            try:
                cid = cid.decode('hex')

            except TypeError:
                showerror('Error', 'Bad eMMC CID')
                return

            try:
                console_id = bytearray(reversed(console_id.decode('hex')))

            except TypeError:
                showerror('Error', 'Bad Console ID')
                return

        dialog = Toplevel(self)
        # Open as dialog (parent disabled)
        dialog.grab_set()
        dialog.title('Status')
        # Disable maximizing
        dialog.resizable(0, 0)

        frame = Frame(dialog, bd=2, relief=SUNKEN)

        scrollbar = Scrollbar(frame)
        scrollbar.pack(side=RIGHT, fill=Y)

        self.log = ThreadSafeText(frame,
                                  bd=0,
                                  width=52,
                                  height=20,
                                  yscrollcommand=scrollbar.set)
        self.log.pack()

        scrollbar.config(command=self.log.yview)

        frame.pack()

        Button(dialog, text='Close', command=dialog.destroy,
               width=16).pack(pady=10)

        # Center in window
        dialog.update_idletasks()
        width = dialog.winfo_width()
        height = dialog.winfo_height()
        dialog.geometry(
            '%dx%d+%d+%d' %
            (width, height, root.winfo_x() + (root.winfo_width() / 2) -
             (width / 2), root.winfo_y() + (root.winfo_height() / 2) -
             (height / 2)))

        # Check if we'll be adding a No$GBA footer
        if self.nand_mode and self.nand_operation.get() == 2:
            Thread(target=self.add_footer, args=(cid, console_id)).start()

        else:
            Thread(target=self.check_nand).start()