예제 #1
0
    def __init__(self, parent, width, change_func):
        super().__init__(parent)
        Theme.get_instance().configure_viewer(self)

        self.__width = width
        self.__change_func = change_func

        self.__mode = Dimension.TWO_D

        self.__raw_plots = []
        self.__plots = []

        self.__view_rect = [-10, -10, 20, 20]
        self.__elev = 30
        self.__azim = -60
        self.__view_cuboid = [-10, -10, -10, 20, 20, 20]

        self.__drag_pos = None
        self.__drag_scale_3d = 800

        self.__button_size = 40

        self.__limit_frame = None
        self.__limit_window = None
        self.__limit_window_open = False
        self.__limit_window_active = True
        self.__x, self.__y, self.__z, self.__a = None, None, None, None

        self.__construct_view_frame(parent)
        self.__construct_buttons()
        self.__construct_limits()

        self.place(relx=width, relwidth=1 - width, relheight=1)

        self.__draw()
예제 #2
0
 def __construct_view_frame(self, parent):
     self.__frame = tk.Frame(parent)
     Theme.get_instance().configure_viewer(self.__frame)
     self.__frame.place(relx=self.__width,
                        rely=0,
                        relwidth=1 - self.__width,
                        relheight=1)
     self.__plot = HelixPlot(self.__frame, 2, lambda e: self.drag_start(e),
                             lambda e, w, h: self.drag(e, w, h),
                             lambda e: self.zoom(e))
     self.__plot.set_dim(self.__mode)
     self.__plot.widget().pack(fill=tk.BOTH, expand=True)
예제 #3
0
    def __init__(self, parent, command):
        theme = Theme.get_instance()
        super().__init__(parent, bg = theme.get_body_colour(), height = EquationValue.HEIGHT)

        self.__symbol = None

        self.__label = tk.Label(self, text = str(self.__symbol))
        self.__to = tk.Label(self, text = "to")
        theme.configure_label(self.__label)
        theme.configure_label(self.__to)

        self.__entry_var_l = tk.StringVar()
        self.__entry_var_r = tk.StringVar()
        self.__entry_var_l.set("-1")
        self.__entry_var_r.set("1")
        self.__entry_var_l.trace('w', command)
        self.__entry_var_r.trace('w', command)
        self.__entry_l = tk.Entry(self, textvariable = self.__entry_var_l)
        self.__entry_r = tk.Entry(self, textvariable = self.__entry_var_r)
        theme.configure_entry(self.__entry_l)
        theme.configure_entry(self.__entry_r)

        self.__label.place(relx = 0, relwidth = 0.15)
        self.__entry_l.place(relx = 0.15, relwidth = 0.35)
        self.__to.place(relx = 0.5, relwidth = 0.15)
        self.__entry_r.place(relx = 0.65, relwidth = 0.35)
예제 #4
0
    def __init__(self, parent, name, v1, v2, connect="to"):
        theme = Theme.get_instance()
        super().__init__(parent,
                         bg=theme.get_body_colour(),
                         width=320,
                         height=50)

        self.__label = tk.Label(self, text=name)
        self.__to = tk.Label(self, text=connect, width=len(connect))
        theme.configure_label(self.__label)
        theme.configure_label(self.__to)

        self.__entry_var_l = tk.StringVar()
        self.__entry_var_r = tk.StringVar()
        self.__entry_var_l.set(str(v1))
        self.__entry_var_r.set(str(v2))
        self.__entry_l = tk.Entry(self, textvariable=self.__entry_var_l)
        self.__entry_r = tk.Entry(self, textvariable=self.__entry_var_r)
        theme.configure_entry(self.__entry_l)
        theme.configure_entry(self.__entry_r)

        self.__label.place(y=10, relx=0, relwidth=0.2)
        self.__entry_l.place(y=10, relx=0.2, relwidth=0.3)
        self.__to.place(y=10, relx=0.5, relwidth=0.2)
        self.__entry_r.place(y=10, relx=0.7, relwidth=0.3)
예제 #5
0
    def __init__(self, parent, width, plotter, change_func):
        super().__init__(parent, self.__entry_config)
        theme = Theme.get_instance()
        theme.configure_editor(self)
        theme.configure_editor(self.get_canvas())
        theme.configure_editor(self.get_inner_frame())

        self.__plotter = plotter
        self.__change_func = change_func

        self.__entry_width = None
        self.__entries = []
        self.__dividers = []

        self.__plots = []
        self.__raw_plots = []
        self.__bindings = []

        self.__add_button_height = 0.05

        self.place(relwidth=width, relheight=1 - self.__add_button_height)

        def entry_command():
            self.__add_entry()
            self.__update(self.__entries[-1])

        self.__entry_button = tk.Button(parent,
                                        text="+",
                                        command=entry_command)
        theme.configure_button(self.__entry_button)
        self.__entry_button.place(rely=1 - self.__add_button_height,
                                  relwidth=width,
                                  relheight=self.__add_button_height)
예제 #6
0
 def __show(self, _e = None):
     if not self.__window is None:
         self.__hide()
     x1, y1, _, _ = self.__parent.bbox()
     x1 += self.__parent.winfo_rootx() + 48
     y1 += self.__parent.winfo_rooty() + 48
     self.__window = tk.Toplevel(self.__parent)
     self.__window.wm_overrideredirect(1)
     self.__window.wm_geometry("+%d+%d" % (x1, y1))
     try:
         self.__window.tk.call("::tk::unsupported::MacWindowStyle",
             "style", self.__window._w, "help", "noActivates")
     except tk.TclError:
         pass
     self.__label = tk.Label(self.__window, text = self.__text, justify = tk.LEFT,
         relief = tk.SOLID, borderwidth = 1)
     Theme.get_instance().configure_label(self.__label)
     self.__label.pack(ipadx = 1)
예제 #7
0
    def __construct_buttons(self):
        def home():
            if self.__mode is Dimension.TWO_D:
                self.__view_rect = [-10, -10, 20, 20]
            if self.__mode is Dimension.THREE_D:
                self.__elev = 30
                self.__azim = -60
                self.__view_cuboid = [-10, -10, -10, 20, 20, 20]
                self.__plot.set_view(self.__elev, self.__azim)
            self.__plot.set_limits(*self.get_lims())

        self.__2d_button = tk.Button(
            self.__frame,
            image=self.__get_button_image("2d"),
            command=lambda: self.__mode_switcher(Dimension.TWO_D))
        self.__3d_button = tk.Button(
            self.__frame,
            image=self.__get_button_image("3d"),
            command=lambda: self.__mode_switcher(Dimension.THREE_D))
        self.__home_button = tk.Button(self.__frame,
                                       image=self.__get_button_image("home"),
                                       command=home)
        theme = Theme.get_instance()
        theme.configure_button(self.__2d_button)
        theme.configure_button(self.__3d_button)
        theme.configure_button(self.__home_button)
        self.__2d_button.place(x=10,
                               y=10,
                               w=self.__button_size,
                               h=self.__button_size)
        self.__3d_button.place(x=10,
                               y=self.__button_size + 20,
                               w=self.__button_size,
                               h=self.__button_size)
        self.__home_button.place(relx=1,
                                 x=-(self.__button_size + 10),
                                 y=10,
                                 w=self.__button_size,
                                 h=self.__button_size)
예제 #8
0
    def __init__(self, parent, update_func, replot_func, remove_func, settings = None):
        super().__init__(parent)

        if settings is None: settings = {}

        self.__update_func = update_func
        self.__replot_func = replot_func
        self.__remove_func = remove_func

        self.__debounce_update_id = None
        self.__debounce_replot_id = None
        self.__debounce_delay = 500

        self.div = None

        self.__plottable = False
        self.__cancel_plot = False
        self.__parsed = Parsed("")

        self.__min_height = 38
        self.__button_size = 24
        self.__button_count = 0
        self.__frame_pad = 8
        self.__spacing = 8

        theme = Theme.get_instance()

        self.__inner = tk.Frame(self, bg = theme.get_body_colour(),
            padx = self.__frame_pad, pady = self.__frame_pad)
        self.__inner.pack(anchor = tk.CENTER, fill = tk.BOTH, expand = True)

        self.__entry_var = tk.StringVar()
        self.__entry_var.set(settings.get(Equation.TEXT_KEY, ""))
        self.__entry_var.trace('w', self.__debounce_update)
        self.__entry = tk.Entry(self.__inner, textvariable = self.__entry_var)
        theme.configure_entry(self.__entry)
        self.__entry.place(x = self.__button_size + self.__spacing,
            w = -(self.__button_size + self.__spacing),
            relwidth = 1)

        self.__content_wrapper = tk.Frame(self.__inner,
            bg = theme.get_body_colour())

        self.__readout_active = False
        self.__readout_height = 32 + 2 * self.__spacing
        self.__readout_type = EquationLabelType.NONE
        self.__readout = tk.Label(self.__content_wrapper,
            bg = theme.get_body_colour(),
            image = ImageManager.get_instance().get_image(
                "info.png",
                self.__readout_height,
                self.__readout_height))
        self.__readout_tooltip = Tooltip(self.__readout)

        self.__value_1 = EquationValue(self.__content_wrapper, self.__debounce_replot)
        self.__value_2 = EquationValue(self.__content_wrapper, self.__debounce_replot)
        self.__values = (self.__value_1, self.__value_2)
        self.__value_count = 0
        self.__value_height = EquationValue.HEIGHT

        self.__parametric_limits = {}
        temp_pl = {}
        for k in settings:
            if isinstance(k, str) and k.startswith(Equation.PARAMETRIC_KEY):
                sym = sy.Symbol(k.split("_")[1])
                v = temp_pl.get(sym, [])
                v.append(float(settings[k]))
                temp_pl[sym] = v
        for k in temp_pl:
            self.__parametric_limits[k] = tuple(temp_pl[k])

        self.__content_wrapper.place(x = self.__button_size + self.__spacing,
            y = self.__min_height + self.__spacing,
            w = -(self.__button_size + self.__spacing), h = -(self.__min_height + self.__spacing),
            relwidth = 1, relheight = 1)

        self.__colour_window_open = False
        self.__colour_window_active = True
        self.__locked = False
        self.__hidden = False
        self.__contoured = False

        self.__r = self.__red = None
        self.__g = self.__green = None
        self.__b = self.__blue = None
        self.__colour_frame = None
        self.__colour_window = None

        self.__construct_colour(settings)
        self.__construct_lock(settings)
        self.__construct_hide(settings)
        self.__construct_contour(settings)
        self.__construct_refresh()
        self.__construct_remove()

        self.__place_buttons()

        self.pack(fill = tk.BOTH, expand = True)
예제 #9
0
 def __create_button(self, command, path):
     button = tk.Button(self.__inner, command = command)
     if path is not None: button.configure(image = self.__get_button_image(path))
     Theme.get_instance().configure_button(button)
     return button
예제 #10
0
    def __construct_colour(self, settings):
        theme = Theme.get_instance()

        def create_colour_frame():
            self.__colour_frame = tk.Frame(self.__colour_window)
            theme.configure_colour_window(self.__colour_frame)

            title = tk.Label(self.__colour_frame, text = "Paint Selection")
            theme.configure_scale(title)
            title.pack(side = tk.TOP, expand = True, fill = tk.X)

            scales = []
            args = {
                "from_" : 0,
                "to" : 255,
                "command" : self.__colour_update,
                "orient" : tk.HORIZONTAL,
                "bg" : theme.get_body_colour(),
                "length" : 200
            }
            names = ("R", "G", "B")
            for n in names:
                frame = tk.Frame(self.__colour_frame)
                theme.configure_colour_window(frame)
                label = tk.Label(frame, text = n, width = 3)
                scale = tk.Scale(frame, args)
                scales.append(scale)
                theme.configure_label(label)
                theme.configure_scale(scale)
                label.pack(side = tk.LEFT)
                scale.pack(side = tk.RIGHT, fill = tk.X, expand = True)
                frame.pack(side = tk.TOP, fill = tk.X, expand = True)
            self.__red, self.__green, self.__blue = tuple(scales)
            self.__red.set(self.__r)
            self.__green.set(self.__g)
            self.__blue.set(self.__b)

            self.__colour_frame.pack(fill = tk.BOTH, expand = True)

        def open_window(_e = None):
            if not self.__colour_window_open:
                self.__colour_window_open = True

                def enter(_e = None):
                    self.__colour_window.unbind_all("<ButtonPress-1>")
                def leave(_e = None):
                    self.__colour_window.bind_all("<ButtonPress-1>", self.__close_colour_window)

                x, y, _, _ = self.bbox()
                x += self.winfo_rootx() + 50
                y += self.winfo_rooty() + 50
                self.__colour_window = tk.Toplevel(self,
                    padx = 10, pady = 10, highlightthickness = 3)
                theme.configure_colour_window(self.__colour_window)
                self.__colour_window.wm_overrideredirect(1)
                self.__colour_window.wm_geometry("+%d+%d" % (x, y))
                self.__colour_window.bind('<Enter>', enter)
                self.__colour_window.bind('<Leave>', leave)
                create_colour_frame()
                leave()
                try:
                    self.__colour_window.tk.call("::tk::unsupported::MacWindowStyle",
                        "style", self.__colour_window._w, "help", "noActivates")
                except tk.TclError:
                    pass

        colours = theme.get_plot_colours()
        colour = settings.get(Equation.COLOUR_KEY, None)
        if colour is None:
            colour = colours[Equation.__counter]
            Equation.__counter += 1
            Equation.__counter %= len(colours)
        else:
            colour = tuple(map(int, colour.split(" ")))
        self.__r, self.__g, self.__b = colour

        self.__colour_button = self.__create_button(open_window, None)
        self.__colour_update()
예제 #11
0
    def __init__(self, parent, detail, press_func, drag_func, zoom_func):
        super().__init__(mpl.figure.Figure(), master=parent)
        theme = Theme.get_instance()

        self.__axis = None

        self.__data = []

        self.__xlim = (-10, 10)
        self.__ylim = (-10, 10)
        self.__zlim = (-10, 10)

        self.__elev = 30
        self.__azim = -60
        self.__detail = detail

        self.__debounce_id = None
        self.__debounce_delay = 300

        self.__dim = None

        self.__figure = self.figure
        theme.configure_figure(self.__figure)

        self.__axis2 = mpl.axes.Axes(self.__figure, (0, 0, 1, 1))
        theme.configure_plot_2d(self.__axis2)

        self.__axis3 = Axes3D(self.__figure, (0, 0, 1, 1))
        theme.configure_plot_3d(self.__axis3)

        self.__axis2.set_xlim(self.__xlim)
        self.__axis2.set_ylim(self.__ylim)
        self.__axis3.set_xlim(self.__xlim)
        self.__axis3.set_ylim(self.__ylim)
        self.__axis3.set_zlim(self.__zlim)

        def presser(e):
            self.widget().focus_set()
            press_func(e)

        self.__presser = presser

        def dragger(e):
            self.widget().update()
            w = self.widget().winfo_width()
            h = self.widget().winfo_height()
            if self.__dim is Dimension.TWO_D:
                x, y = drag_func(e, w, h)
                self.set_limits(x, y)
            if self.__dim is Dimension.THREE_D:
                e, a = drag_func(e, w, h)
                self.set_view(e, a)

        self.__dragger = dragger

        def zoomer(e):
            if self.__dim is Dimension.TWO_D:
                x, y = zoom_func(e)
                self.set_limits(x, y)
            if self.__dim is Dimension.THREE_D:
                x, y, z = zoom_func(e)
                self.set_limits(x, y, z)

        self.__zoomer = zoomer

        self.widget().bind("<ButtonPress-1>", self.__presser)
        self.widget().bind("<B1-Motion>", self.__dragger)
        self.widget().bind('<Enter>', self.__bind_scroll)
        self.widget().bind('<Leave>', self.__unbind_scroll)

        def detail_func(*_args):
            DelayTracker.get_instance().remove_delay(self.widget(),
                                                     self.__debounce_detail_id)
            v = Parser.get_instance().parse_number(self.__detailer_var.get())
            if v is None: return None
            self.set_detail(float(v))

        def debounce_detail_func(*_args):
            if self.__debounce_detail_id is not None:
                DelayTracker.get_instance().end_delay(
                    self.widget(), self.__debounce_detail_id)
            self.__debounce_detail_id = self.widget().after(
                self.__debounce_delay, detail_func)
            DelayTracker.get_instance().add_delay(self.widget(),
                                                  self.__debounce_detail_id)

        self.__debounce_detail_id = None
        self.__debounce_delay = 500

        self.__detail_label = tk.Label(self.widget(), text="Points per unit:")
        theme.configure_label(self.__detail_label)
        theme.configure_viewer(self.__detail_label)

        self.__detailer_var = tk.StringVar()
        self.__detailer_var.set(str(self.__detail))
        self.__detailer_var.trace('w', debounce_detail_func)
        self.__detailer = tk.Entry(self.widget(),
                                   textvariable=self.__detailer_var,
                                   w=10)
        theme.configure_entry(self.__detailer)

        self.draw()
예제 #12
0
    def __construct_limits(self):
        theme = Theme.get_instance()

        def create_limit_frame():
            self.__limit_frame = tk.Frame(self.__limit_window)
            theme.configure_colour_window(self.__limit_frame)

            title = tk.Label(self.__limit_frame, text="Setting the Limits")
            theme.configure_scale(title)
            title.pack()

            if self.__mode is Dimension.TWO_D:
                self.__x = LimitValue(self.__limit_frame, "x",
                                      self.get_xmin_2d(), self.get_xmax_2d())
                self.__y = LimitValue(self.__limit_frame, "y",
                                      self.get_ymin_2d(), self.get_ymax_2d())
            if self.__mode is Dimension.THREE_D:
                self.__x = LimitValue(self.__limit_frame, "x",
                                      self.get_xmin_3d(), self.get_xmax_3d())
                self.__y = LimitValue(self.__limit_frame, "y",
                                      self.get_ymin_3d(), self.get_ymax_3d())
                self.__z = LimitValue(self.__limit_frame, "z",
                                      self.get_zmin_3d(), self.get_zmax_3d())
                self.__a = LimitValue(self.__limit_frame,
                                      "elev.",
                                      self.__elev,
                                      self.__azim,
                                      connect="azim.")
            for w in (self.__x, self.__y, self.__z, self.__a):
                if w is not None: w.pack(fill=tk.X, expand=True)

            def set_lims():
                x = self.__x.get_data() if self.__x is not None else None
                y = self.__y.get_data() if self.__y is not None else None
                z = self.__z.get_data() if self.__z is not None else None
                a = self.__a.get_data() if self.__a is not None else None

                if any(map(lambda d: d is None, (x, y, z, a))):
                    self.__view_rect = [x[0], y[0], x[1] - x[0], y[1] - y[0]]
                else:
                    self.__view_cuboid = [
                        x[0], y[0], z[0], x[1] - x[0], y[1] - y[0], z[1] - z[0]
                    ]
                    self.__elev, self.__azim = a
                    self.__plot.set_view(self.__elev, self.__azim)
                self.__plot.set_limits(*self.get_lims())

            button = tk.Button(self.__limit_frame,
                               text="Set",
                               command=set_lims)
            theme.configure_button(button)
            button.pack()

            self.__limit_frame.pack(fill=tk.BOTH, expand=True)

        def open_window(_e=None):
            if not self.__limit_window_open:
                self.__limit_window_open = True

                def enter(_e=None):
                    self.__limit_window.unbind_all("<ButtonPress-1>")

                def leave(_e=None):
                    self.__limit_window.bind_all("<ButtonPress-1>",
                                                 self.__close_limit_window)

                x, y, _, _ = self.bbox()
                x += self.__limit_button.winfo_rootx() - 250
                y += self.__limit_button.winfo_rooty() + 50
                self.__limit_window = tk.Toplevel(self,
                                                  padx=10,
                                                  pady=10,
                                                  highlightthickness=3)
                theme.configure_colour_window(self.__limit_window)
                self.__limit_window.wm_overrideredirect(1)
                self.__limit_window.wm_geometry("+%d+%d" % (x, y))
                self.__limit_window.bind('<Enter>', enter)
                self.__limit_window.bind('<Leave>', leave)
                create_limit_frame()
                leave()
                try:
                    self.__limit_window.tk.call(
                        "::tk::unsupported::MacWindowStyle", "style",
                        self.__limit_window._w, "help", "noActivates")
                except tk.TclError:
                    pass

        self.__limit_button = tk.Button(
            self.__frame,
            image=self.__get_button_image("limits"),
            command=open_window)
        theme.configure_button(self.__limit_button)
        self.__limit_button.place(relx=1,
                                  x=-(self.__button_size + 10),
                                  y=self.__button_size + 20,
                                  w=self.__button_size,
                                  h=self.__button_size)
예제 #13
0
 def __init__(self, parent):
     super().__init__(parent, height=4)
     Theme.get_instance().configure_divider(self)
     self.pack(fill=tk.BOTH, expand=True)