def __init__(self, parent, input_image, image_ft, RMS_error):
        super().__init__(parent, title="Phase View")
        self._panel = wx.Panel(self)

        wx_img_real = _np_grey_img_to_wx_image(input_image)
        wx_img_fourier = _np_grey_img_to_wx_image(image_ft)

        self._canvas = FloatCanvas(self._panel, size=wx_img_real.GetSize())
        self._real_bmp = self._canvas.AddBitmap(wx_img_real, (0, 0),
                                                Position="cc")
        self._fourier_bmp = self._canvas.AddBitmap(wx_img_fourier, (0, 0),
                                                   Position="cc")
        # By default, show real and hide the fourier transform.
        self._fourier_bmp.Hide()

        save_btn = wx.ToggleButton(self._panel, label="Show Fourier")
        save_btn.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleFourier)

        rms_txt = wx.StaticText(self._panel,
                                label="RMS difference: %.05f" % (RMS_error))

        panel_sizer = wx.BoxSizer(wx.VERTICAL)
        panel_sizer.Add(self._canvas)

        bottom_sizer = wx.BoxSizer(wx.HORIZONTAL)
        bottom_sizer.Add(save_btn, wx.SizerFlags().Center().Border())
        bottom_sizer.Add(rms_txt, wx.SizerFlags().Center().Border())
        panel_sizer.Add(bottom_sizer)

        self._panel.SetSizer(panel_sizer)

        frame_sizer = wx.BoxSizer(wx.VERTICAL)
        frame_sizer.Add(self._panel)
        self.SetSizerAndFit(frame_sizer)
    def __init__(self, builder=None, brick_size=(0.2, 0.05)):
        super(Designer, self).__init__(None)

        # config #
        self.builder = builder
        self.brick_size = brick_size

        # bind #
        self.Bind(wx.EVT_LISTBOX, self.on_listBox, self.listBox)
        self.Bind(wx.EVT_BUTTON, self.add_brick, self.button_add)
        self.Bind(wx.EVT_BUTTON, self.remove_brick, self.button_remove)
        self.Bind(wx.EVT_BUTTON, self.rotate_brick, self.button_rotate)
        self.Bind(wx.EVT_BUTTON, self.run, self.button_run)

        self.Bind(wx.EVT_BUTTON, self.load, self.button_load)
        self.Bind(wx.EVT_BUTTON, self.save, self.button_save)

        self.Bind(wx.EVT_TEXT_ENTER, self.update_brick, self.textBox_name)
        self.Bind(wx.EVT_TEXT_ENTER, self.update_input, self.textBox_X)
        self.Bind(wx.EVT_TEXT_ENTER, self.update_input, self.textBox_Y)
        self.Bind(wx.EVT_TEXT_ENTER, self.update_input, self.textBox_R)

        # Publisher().subscribe(self.on_msg, "update")

        # canvas #
        self.canvas = FloatCanvas(self.draw_panel,
                                  size=(600, 500),
                                  ProjectionFun=None,
                                  BackgroundColor="White")
        self.canvas.Bind(wx.EVT_MOUSE_EVENTS, self.on_mouse)

        self.refresh()
Exemple #3
0
 def __init__(self, world):
     self.world = world
     self.app = wx.PySimpleApp()
     self.w = 500
     self.h = 500
     self.frame = wx.Frame(None, -1, 'Ant Plot', size=(self.w, self.h))
     self.canvas = FloatCanvas(self.frame, -1)
Exemple #4
0
    def __init__(self, city, population):
        self.city = city
        self.population = population

        self.app = wx.App(False)
        self.w = self.city.size + 100
        self.h = self.city.size + 120
        self.frame = wx.Frame(None, -1, 'Income Map', size=(self.w, self.h))
        self.canvas = FloatCanvas(self.frame, -1)
class _PhaseViewer(wx.Frame):
    """This is a window for selecting the ROI for interferometry."""
    def __init__(self, parent, input_image, image_ft, RMS_error):
        super().__init__(parent, title="Phase View")
        self._panel = wx.Panel(self)

        wx_img_real = _np_grey_img_to_wx_image(input_image)
        wx_img_fourier = _np_grey_img_to_wx_image(image_ft)

        self._canvas = FloatCanvas(self._panel, size=wx_img_real.GetSize())
        self._real_bmp = self._canvas.AddBitmap(wx_img_real, (0, 0),
                                                Position="cc")
        self._fourier_bmp = self._canvas.AddBitmap(wx_img_fourier, (0, 0),
                                                   Position="cc")
        # By default, show real and hide the fourier transform.
        self._fourier_bmp.Hide()

        save_btn = wx.ToggleButton(self._panel, label="Show Fourier")
        save_btn.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleFourier)

        rms_txt = wx.StaticText(self._panel,
                                label="RMS difference: %.05f" % (RMS_error))

        panel_sizer = wx.BoxSizer(wx.VERTICAL)
        panel_sizer.Add(self._canvas)

        bottom_sizer = wx.BoxSizer(wx.HORIZONTAL)
        bottom_sizer.Add(save_btn, wx.SizerFlags().Center().Border())
        bottom_sizer.Add(rms_txt, wx.SizerFlags().Center().Border())
        panel_sizer.Add(bottom_sizer)

        self._panel.SetSizer(panel_sizer)

        frame_sizer = wx.BoxSizer(wx.VERTICAL)
        frame_sizer.Add(self._panel)
        self.SetSizerAndFit(frame_sizer)

    def OnToggleFourier(self, event: wx.CommandEvent) -> None:
        show_fourier = event.IsChecked()
        # These bmp are wx.lib.floatcanvas.FCObjects.Bitmap and not
        # wx.Bitmap.  Their Show method does not take show argument
        # and therefore we can't do `Show(show_fourier)`.
        if show_fourier:
            self._fourier_bmp.Show()
            self._real_bmp.Hide()
        else:
            self._real_bmp.Show()
            self._fourier_bmp.Hide()
        self._canvas.Draw(Force=True)
Exemple #6
0
class AntPlot:
	"""Class that uses wx to draw a plot of the Ants in the World."""
	
	def __init__(self, world):
		self.world = world
		self.app = wx.PySimpleApp()
		self.w = 500
		self.h = 500
		self.frame = wx.Frame(None, -1, 'Ant Plot', 
				      size=(self.w, self.h))
		self.canvas = FloatCanvas(self.frame, -1)
		
	
	def draw(self):
		"""Pops up a wx window that represents the current state of
		the World.
		"""
		positions = self.world.get_ant_dict()
		for pos in positions:
			x, y = pos
			x -= self.w / 2
			y -= self.h / 2
			self.canvas.AddPoint((x, y))
		self.frame.Show()
		self.app.MainLoop()
Exemple #7
0
    def __init__(self, parent):
        super(PaintPanel, self).__init__(parent=parent)
        self.network = Engine.Instance().network

        szr = wx.BoxSizer()
        self.canvas = FloatCanvas(parent=self)
        szr.Add(self.canvas, proportion=1, flag=wx.EXPAND)
        self.SetSizer(szr)

        self.Bind(wx.EVT_RIGHT_UP, Engine.Instance().OnRightClick)
        self.canvas.Bind(wx.EVT_RIGHT_UP, Engine.Instance().OnRightClick)

        # The following is called a lambda expression:
        # It allows us to define functions on-the-go.
        # It is no more than a function without definition.
        self.canvas.Bind(
            wx.EVT_LEFT_UP,
            lambda event, panel=self.canvas: self.OnLeftClick(event))
        self.canvas.Bind(wx.EVT_PAINT, self.OnWindowBack)
Exemple #8
0
class PaintPanel(wx.Panel):
    """Canvas to let people draw networks"""
    def __init__(self, parent):
        super(PaintPanel, self).__init__(parent=parent)
        self.network = Engine.Instance().network

        szr = wx.BoxSizer()
        self.canvas = FloatCanvas(parent=self)
        szr.Add(self.canvas, proportion=1, flag=wx.EXPAND)
        self.SetSizer(szr)

        self.Bind(wx.EVT_RIGHT_UP, Engine.Instance().OnRightClick)
        self.canvas.Bind(wx.EVT_RIGHT_UP, Engine.Instance().OnRightClick)

        # The following is called a lambda expression:
        # It allows us to define functions on-the-go.
        # It is no more than a function without definition.
        self.canvas.Bind(
            wx.EVT_LEFT_UP,
            lambda event, panel=self.canvas: self.OnLeftClick(event))
        self.canvas.Bind(wx.EVT_PAINT, self.OnWindowBack)


#        self.canvas.Bind(wx.EVT_HIBERNATE)

    def OnWindowBack(self, event):
        pass

    def OnLeftClick(self, event):
        if Engine.Instance().toolbarClicked:
            dc = wx.ClientDC(self.canvas)
            if Engine.Instance().item == "Node":
                x, y = event.GetX(), event.GetY()
                frontNode = NodeRepr()
                frontNode.circle = FC.Circle(XY=(x, y),
                                             Diameter=NodeDrawer.size)
                dc.DrawCircle(frontNode.circle.XY[0], frontNode.circle.XY[1],
                              NodeDrawer.size / 2)
                Engine.Instance().releaseFocus()
                Engine.Instance().AddNode(frontNode)
    def __init__(self,
                 parent,
                 input_image: np.ndarray,
                 initial_roi,
                 scale_factor=1) -> None:
        super().__init__(parent, title="ROI selector")
        self._panel = wx.Panel(self)
        self._img = _np_grey_img_to_wx_image(input_image)
        self._scale_factor = scale_factor

        # What, if anything, is being dragged.
        # XXX: When we require Python 3.8, annotate better with
        # `typing.Literal[None, "xy", "r"]`
        self._dragging: typing.Optional[str] = None

        # Canvas
        self.canvas = FloatCanvas(self._panel, size=self._img.GetSize())
        self.canvas.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
        self.bitmap = self.canvas.AddBitmap(self._img, (0, 0), Position="cc")

        self.circle = self.canvas.AddCircle(
            self.canvas.PixelToWorld(initial_roi[:2]),
            initial_roi[2] * 2,
            LineColor="cyan",
            LineWidth=2,
        )

        # Save button
        saveBtn = wx.Button(self._panel, label="Save ROI")
        saveBtn.Bind(wx.EVT_BUTTON, self.OnSave)

        panel_sizer = wx.BoxSizer(wx.VERTICAL)
        panel_sizer.Add(self.canvas)
        panel_sizer.Add(saveBtn, wx.SizerFlags().Border())
        self._panel.SetSizer(panel_sizer)

        frame_sizer = wx.BoxSizer(wx.VERTICAL)
        frame_sizer.Add(self._panel)
        self.SetSizerAndFit(frame_sizer)
class _ROISelect(wx.Frame):
    """Display a window that allows the user to select a circular area.

    This is a window for selecting the ROI for interferometry.
    """
    def __init__(self,
                 parent,
                 input_image: np.ndarray,
                 initial_roi,
                 scale_factor=1) -> None:
        super().__init__(parent, title="ROI selector")
        self._panel = wx.Panel(self)
        self._img = _np_grey_img_to_wx_image(input_image)
        self._scale_factor = scale_factor

        # What, if anything, is being dragged.
        # XXX: When we require Python 3.8, annotate better with
        # `typing.Literal[None, "xy", "r"]`
        self._dragging: typing.Optional[str] = None

        # Canvas
        self.canvas = FloatCanvas(self._panel, size=self._img.GetSize())
        self.canvas.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
        self.bitmap = self.canvas.AddBitmap(self._img, (0, 0), Position="cc")

        self.circle = self.canvas.AddCircle(
            self.canvas.PixelToWorld(initial_roi[:2]),
            initial_roi[2] * 2,
            LineColor="cyan",
            LineWidth=2,
        )

        # Save button
        saveBtn = wx.Button(self._panel, label="Save ROI")
        saveBtn.Bind(wx.EVT_BUTTON, self.OnSave)

        panel_sizer = wx.BoxSizer(wx.VERTICAL)
        panel_sizer.Add(self.canvas)
        panel_sizer.Add(saveBtn, wx.SizerFlags().Border())
        self._panel.SetSizer(panel_sizer)

        frame_sizer = wx.BoxSizer(wx.VERTICAL)
        frame_sizer.Add(self._panel)
        self.SetSizerAndFit(frame_sizer)

    @property
    def ROI(self):
        """Convert circle parameters to ROI x, y and radius"""
        roi_x, roi_y = self.canvas.WorldToPixel(self.circle.XY)
        roi_r = max(self.circle.WH)
        return (roi_x, roi_y, roi_r)

    def OnSave(self, event: wx.CommandEvent) -> None:
        del event
        roi = [x * self._scale_factor for x in self.ROI]
        userConfig.setValue("dm_circleParams", (roi[1], roi[0], roi[2]))

    def MoveCircle(self, pos: wx.Point, r) -> None:
        """Set position and radius of circle with bounds checks."""
        x, y = pos
        _x, _y, _r = self.ROI
        xmax, ymax = self._img.GetSize()
        if r == _r:
            x_bounded = min(max(r, x), xmax - r)
            y_bounded = min(max(r, y), ymax - r)
            r_bounded = r
        else:
            r_bounded = max(_ROI_MIN_RADIUS, min(xmax - x, x, ymax - y, y, r))
            x_bounded = min(max(r_bounded, x), xmax - r_bounded)
            y_bounded = min(max(r_bounded, y), ymax - r_bounded)
        self.circle.SetPoint(self.canvas.PixelToWorld((x_bounded, y_bounded)))
        self.circle.SetDiameter(2 * r_bounded)
        if any((x_bounded != x, y_bounded != y, r_bounded != r)):
            self.circle.SetColor("magenta")
        else:
            self.circle.SetColor("cyan")

    def OnMouse(self, event: wx.MouseEvent) -> None:
        pos = event.GetPosition()
        x, y, r = self.ROI
        if event.LeftDClick():
            # Set circle centre
            self.MoveCircle(pos, r)
        elif event.Dragging():
            # Drag circle centre or radius
            drag_r = np.sqrt((x - pos[0])**2 + (y - pos[1])**2)
            if self._dragging is None:
                # determine what to drag
                if drag_r < 0.5 * r:
                    # closer to center
                    self._dragging = "xy"
                else:
                    # closer to edge
                    self._dragging = "r"
            elif self._dragging == "r":
                # Drag circle radius
                self.MoveCircle((x, y), drag_r)
            elif self._dragging == "xy":
                # Drag circle centre
                self.MoveCircle(pos, r)

        if not event.Dragging():
            # Stop dragging
            self._dragging = None
            self.circle.SetColor("cyan")

        self.canvas.Draw(Force=True)
Exemple #11
0
class CityPrinter(object):
    
    def __init__(self, city, population):
        self.city = city
        self.population = population
        
        self.app = wx.App(False)
        self.w = self.city.size + 100
        self.h = self.city.size + 120
        self.frame_rent = wx.Frame(None, -1, 'Rent Map', size=(self.w, self.h))
        self.frame_income = wx.Frame(None, -1, 'Income Map', size=(self.w, self.h))
        self.canvas_rent = FloatCanvas(self.frame_rent, -1)
        self.canvas_income = FloatCanvas(self.frame_income, -1)
    
    def create_heatmaps(self):
        self.create_rent_map()
        self.create_income_map()
        self.app.MainLoop()
    
    def create_rent_map(self):
        print("Lowest Rent: " + str(self.city.min_price))
        print("Highest Rent: " + str(self.city.max_price))
        min_price = self.city.min_price
        max_price = self.city.max_price

        time1 = time.time()
        print("Generating Rent Map")
        
        for house in self.city.houses:
            x = house.x - self.city.size / 2
            y = house.y - self.city.size / 2
            col = self.color(self.city.get_house(house).price, min_price, max_price, \
                    self.city.get_house(house).occupant == None)
            self.canvas_rent.AddPoint((x, y), Color = col)
        
        time2 = time.time()
        print('Generating Image took %0.3f ms' % ((time2-time1) * 1000.0))
        
        self.frame_rent.Show()
    
    def create_income_map(self):
        print("Lowest Income: " + str(self.population.min_income))
        print("Highest Income: " + str(self.population.max_income))
        min_income = self.population.min_income
        max_income = self.population.max_income

        time1 = time.time()
        print("Generating Income Map")
        
        for house in self.city.houses:
            x = house.x - self.city.size / 2
            y = house.y - self.city.size / 2
            person = self.city.get_house(house).occupant
            if person != None:
                col = self.color(person.income, min_income, max_income)
                self.canvas_income.AddPoint((x, y), Color = col)
        
        time2 = time.time()
        print('Generating Image took %0.3f ms' % ((time2-time1) * 1000.0))
        
        self.frame_income.Show()
    
    def color(self, value, min, max, red=False):
        #print("Colouring In")
        
        if not red:
            # Approximating http://geog.uoregon.edu/datagraphics/color/Bu_10.txt on the fly
            red_range = (0, 0.9)
            green_range = (0.25, 1.0)
            blue_range = (1.0, 1.0)
        else:
            # Colour Shifting it to red
            red_range = (1.0, 1.0)
            green_range = (0, 0.9)
            blue_range = (0.25, 1.0)
        
        percentage_of_range = 1 - (value - min)/(max - min)
        
        red = (((red_range[1] - red_range[0]) * percentage_of_range) + red_range[0]) * 255
        green = (((green_range[1] - green_range[0]) * percentage_of_range) + green_range[0]) * 255
        blue = (((blue_range[1] - blue_range[0]) * percentage_of_range) + blue_range[0]) * 255
        
        return wx.Colour(red, green, blue, 1)
    
    """
    Write the city to standard out for quick testing and debugging.
    """
    def __str__(self):
        output = ""
        output += "Cheapest Place: " + str(self.city.min_price) + "\n"
        output += "Most Expensive Place: " + str(self.city.max_price) + "\n"
        output += "\n"
        for y in range(self.city.size):
            row = ""
            for x in range(self.city.size):
                coords = Coordinates(x, y)
                occupied_string = "_" if self.city.get_house(coords).occupant == None else "X"
                row += str("%3d%s " % (self.city.get_house(coords).price, occupied_string))
            output += row + "\n"
        return output
Exemple #12
0
class CityPrinter(object):
    def __init__(self, city, population):
        self.city = city
        self.population = population

        self.app = wx.App(False)
        self.w = self.city.size + 100
        self.h = self.city.size + 120
        self.frame = wx.Frame(None, -1, 'Income Map', size=(self.w, self.h))
        self.canvas = FloatCanvas(self.frame, -1)

    def create_heatmap(self):
        min_income = self.population.min_income
        max_income = self.population.max_income
        print("Lowest Income: " + str(min_income))
        print("Highest Income: " + str(max_income))

        for house in self.city.houses:
            x = house.x - self.city.size / 2
            y = house.y - self.city.size / 2
            person = self.city.get_house(house)
            if person != None:
                col = self.color(person.income, min_income, max_income)
                self.canvas.AddPoint((x, y), Color=col)

        self.frame.Show()
        self.app.MainLoop()

    def color(self, value, min_val, max_val):
        # Approximating http://geog.uoregon.edu/datagraphics/color/Bu_10.txt on the fly
        red_range = (0, 0.9)
        green_range = (0.25, 1.0)
        blue_range = (1.0, 1.0)

        percentage_of_range = 1 - (value - min_val) / (max_val - min_val)

        red = (((red_range[1] - red_range[0]) * percentage_of_range) +
               red_range[0]) * 255
        green = (((green_range[1] - green_range[0]) * percentage_of_range) +
                 green_range[0]) * 255
        blue = (((blue_range[1] - blue_range[0]) * percentage_of_range) +
                blue_range[0]) * 255

        return wx.Colour(red, green, blue, 1)

    """
    Write the city to standard out for quick testing and debugging.
    """

    def __str__(self):
        output = ""
        for y in range(self.city.size):
            row = ""
            for x in range(self.city.size):
                coords = Coordinates(x, y)
                occupied = self.city.get_house(coords) != None
                if occupied:
                    row += str("%3d " % (self.city.get_house(coords).income))
                else:
                    row += str("    ")
            output += row + "\n"
        return output
Exemple #13
0
 def __init__(self, parent):
     self.parent = parent
     FloatCanvas.__init__(self, parent, BackgroundColor="BLACK")
     self.circles = []
     self.GUIMode = GUICustom(self)
Exemple #14
0
class Designer(MyFrame):

    # config #
    builder = None
    brick_size = (0.2, 0.05)

    # bricks #
    cur_index = -1
    bricks = []
    bricks_count = 0

    # canvas #
    canvas_scale = 500.0
    canvas_offset = (0, -0.4)

    def __init__(self, builder=None, brick_size=(0.2, 0.05)):
        super(Designer, self).__init__(None)

        # config #
        self.builder = builder
        self.brick_size = brick_size

        # bind #
        self.Bind(wx.EVT_LISTBOX, self.on_listBox, self.listBox)
        self.Bind(wx.EVT_BUTTON, self.add_brick, self.button_add)
        self.Bind(wx.EVT_BUTTON, self.remove_brick, self.button_remove)
        self.Bind(wx.EVT_BUTTON, self.rotate_brick, self.button_rotate)
        self.Bind(wx.EVT_BUTTON, self.run, self.button_run)

        self.Bind(wx.EVT_BUTTON, self.load, self.button_load)
        self.Bind(wx.EVT_BUTTON, self.save, self.button_save)

        self.Bind(wx.EVT_TEXT_ENTER, self.update_brick, self.textBox_name)
        self.Bind(wx.EVT_TEXT_ENTER, self.update_input, self.textBox_X)
        self.Bind(wx.EVT_TEXT_ENTER, self.update_input, self.textBox_Y)
        self.Bind(wx.EVT_TEXT_ENTER, self.update_input, self.textBox_R)

        # Publisher().subscribe(self.on_msg, "update")

        # canvas #
        self.canvas = FloatCanvas(self.draw_panel,
                                  size=(600, 500),
                                  ProjectionFun=None,
                                  BackgroundColor="White")
        self.canvas.Bind(wx.EVT_MOUSE_EVENTS, self.on_mouse)

        self.refresh()

    def on_listBox(self, event):
        self.cur_index = event.GetEventObject().GetSelection()
        self.refresh()

    # def on_msg(self):
    #

    def is_selected(self):
        if 0 <= self.cur_index < len(self.bricks):
            return True
        else:
            self.cur_index = -1
            return False

    # ---- bricks ---- #

    def add_brick(self, event):
        name = 'brick' + str(self.bricks_count)
        new_brick = Brick(name, 0, self.brick_size[1] / 2)
        self.bricks.append(new_brick)
        self.cur_index = len(self.bricks) - 1
        self.bricks_count += 1
        self.refresh()

    def remove_brick(self, event):
        if self.is_selected():
            del self.bricks[self.cur_index]
            if self.cur_index >= len(self.bricks):
                self.cur_index = len(self.bricks) - 1
            self.refresh()

    def rotate_brick(self, event):
        if self.is_selected():
            d = pi / 4
            cur = self.bricks[self.cur_index]
            cur.r = ((int(cur.r / d) + 1) * d) % pi
            self.refresh()

    def update_brick(self, event):
        if self.is_selected():
            cur = self.bricks[self.cur_index]

            new_name = self.textBox_name.GetValue()
            if cur.name != new_name:
                for i in range(0, len(self.bricks), 1):
                    if self.bricks[i].name == new_name:
                        return
            cur.name = new_name

            cur.x = float(self.textBox_X.GetValue())
            cur.y = float(self.textBox_Y.GetValue())
            cur.r = float(self.textBox_R.GetValue())
            self.refresh()

    def update_input(self, event):
        x = self.textBox_X.GetValue()
        y = self.textBox_Y.GetValue()
        r = self.textBox_R.GetValue()
        if self.is_selected(
        ) and x != '' and y != '' and r != '' and self.down_pos is None:
            cur = self.bricks[self.cur_index]
            cur.x = float(x)
            cur.y = float(y)
            cur.r = float(r)
            self.refresh_canvas()

    # ---- refresh ---- #

    def refresh(self):
        self.refresh_list()
        self.refresh_prop()
        self.refresh_canvas()

    def refresh_list(self):
        self.listBox.Clear()
        for brick in self.bricks:
            self.listBox.Append(brick.name)
        if self.is_selected():
            self.listBox.Select(self.cur_index)

    def refresh_prop(self):
        if self.is_selected():
            cur = self.bricks[self.cur_index]
            self.textBox_name.SetValue(str(cur.name))
            self.textBox_X.SetValue(str(cur.x))
            self.textBox_Y.SetValue(str(cur.y))
            self.textBox_R.SetValue(str(cur.r))
            # self.prop_panel.Show()
        else:
            self.textBox_name.Clear()
            self.textBox_X.Clear()
            self.textBox_Y.Clear()
            self.textBox_R.Clear()
            # self.prop_panel.Hide()

    # ---- canvas ---- #

    def refresh_canvas(self):
        self.canvas.ClearAll()
        self.draw_lines()

        for brick in self.bricks:
            if not self.is_selected() or brick != self.bricks[self.cur_index]:
                self.canvas.AddObject(self.get_box(brick, "Yellow"))

        if self.is_selected():
            self.canvas.AddObject(
                self.get_box(self.bricks[self.cur_index], "Yellow", "Orange"))

        self.canvas.Draw()

    def draw_lines(self):
        self.canvas.AddObject(
            Line([self.to_offset(
                (1, 0)), self.to_offset((-1, 0))],
                 LineWidth=5))
        self.canvas.AddObject(
            Line([self.to_offset(
                (0, 1)), self.to_offset((0, -1))],
                 LineWidth=2,
                 LineStyle="ShortDash"))

        for x in range(-5, 6, 1):
            self.canvas.AddObject(
                Line([
                    self.to_offset((x * 0.1, 1)),
                    self.to_offset((x * 0.1, -1))
                ],
                     LineStyle="Dot",
                     LineWidth=0.1))
        for y in range(-5, 10, 1):
            self.canvas.AddObject(
                Line([
                    self.to_offset((1, y * 0.1)),
                    self.to_offset((-1, y * 0.1))
                ],
                     LineStyle="Dot",
                     LineWidth=0.1))

    def get_box(self, brick, FillColor, LineColor="Black"):
        brick = ((brick.x + self.canvas_offset[0]) * self.canvas_scale,
                 (brick.y + self.canvas_offset[1]) * self.canvas_scale,
                 brick.r)
        brick_size = (self.brick_size[0] * self.canvas_scale,
                      self.brick_size[1] * self.canvas_scale)
        p1 = to_points(brick, (brick_size[0] / 2, brick_size[1] / 2))
        p2 = to_points(brick, (brick_size[0] / 2, -brick_size[1] / 2))
        p3 = to_points(brick, (-brick_size[0] / 2, -brick_size[1] / 2))
        p4 = to_points(brick, (-brick_size[0] / 2, brick_size[1] / 2))
        return Polygon([p1, p2, p3, p4],
                       LineWidth=2,
                       FillColor=FillColor,
                       LineColor=LineColor)

    def to_offset(self, point):
        return ((point[0] + self.canvas_offset[0]) * self.canvas_scale,
                (point[1] + self.canvas_offset[1]) * self.canvas_scale)

    def from_offset(self, point):
        return ((point[0] / self.canvas_scale - self.canvas_offset[0]),
                (point[1] / self.canvas_scale - self.canvas_offset[1]))

    # ---- run ---- #

    def run(self, event):
        targets = self.get_targets()
        self.builder.set_targets(targets)
        self.builder.show_target()
        rospy.sleep(2)
        self.builder.show_source()
        thread.start_new_thread(self.builder.build, ())

    def get_targets(self):
        targets = []
        for brick in self.bricks:
            transform = build_frame(
                (brick.x, 0, brick.y),
                (-pi / 2, 0, 0)) * build_frame(rpy=(0, 0, brick.r))
            targets.append(transform)
        return targets

    # ----- drag ---- #

    down_pos = None
    pre_pos = None

    def on_mouse(self, event):
        if not self.is_selected():
            return

        brick = self.bricks[self.cur_index]
        cur_pos = self.from_offset(event.GetPosition())

        if event.ButtonDown():
            self.down_pos = cur_pos
            self.pre_pos = (brick.x, brick.y)

        elif event.Dragging():
            if self.down_pos is not None:

                pos = (cur_pos[0] - self.down_pos[0],
                       cur_pos[1] - self.down_pos[1])

                brick.x = self.pre_pos[0] + pos[0]
                brick.y = self.pre_pos[1] - pos[1]

                if self.is_aligned.GetValue():
                    align = self.brick_size[1] / 2
                    brick.x = int(brick.x / align) * align
                    brick.y = int(brick.y / align) * align

                self.refresh()

        elif event.ButtonUp():
            self.down_pos = None
            self.pre_pos = None

    # ---- file ---- #

    def load(self, event):
        dlg = wx.FileDialog(self,
                            "加载图纸",
                            defaultDir=os.getcwd(),
                            wildcard='图纸文件 (*.dsg)|*.dsg|全部文件|*',
                            style=wx.OPEN | wx.FILE_MUST_EXIST)

        if dlg.ShowModal() == wx.ID_OK:
            try:
                with open(dlg.GetPath(), 'r') as design_file:
                    bricks = []
                    for target in json.load(design_file):
                        bricks.append(
                            Brick(target['name'], target['x'], target['y'],
                                  target['r']))
                    self.bricks = bricks
                    self.cur_index = -1
                    self.refresh()
            except BaseException, e:
                error_dlg = wx.MessageDialog(None,
                                             "无法识别的图纸文件!\n错误详情: " + e.message,
                                             "加载失败", wx.ICON_ERROR)
                error_dlg.ShowModal()
                error_dlg.Destroy()

        dlg.Destroy()