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()
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)
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)
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)
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)
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)
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)
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)
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
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()
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()
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)
def __init__(self, parent): super().__init__(parent, height=4) Theme.get_instance().configure_divider(self) self.pack(fill=tk.BOTH, expand=True)