#!/usr/bin/python # -*- coding: utf-8 -*- # """ Implements graphical interface using Tkinter package modules. Name: main.py Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com ) """ import sys if sys.version_info[0] < 3: import Tkinter as Tk else: import tkinter as Tk import tkMessageBox import tk as tk_local from interface import Interface, InterfaceException as IException class TkInterface(Interface): MAX_CLASSES = 20 utils = tk_local.Utils def __init__(self, title): self.title = title self._root = Tk.Tk() self._root.wm_title(self.title) self._root.geometry('%dx%d+%d+%d' % (800, 600, 0, 0)) self._menus = [] self._image = None self._grid = None self._logger = None self._conf_dialog = None def set_subtitle(self, subtitle): self._root.wm_title(self.title + ' - ' + subtitle) def add_menu(self, label): self._menus.append( tk_local.Menu(self._root, label) ) def add_command(self, label, action, shortcut = None): self._menus[-1].add_command( label = label, action = lambda *_: self._apply( action ), shortcut = shortcut ) def add_separator(self): self._menus[-1].add_separator( ) def add_check_button(self, label, action, shortcut = None): self._menus[-1].add_check_button(label = label, action = lambda *_: self._apply( action ), shortcut = shortcut) def render_menu(self): menubar = Tk.Menu(self._root) for menu in self._menus: menu.render(menubar) self._root.config(menu=menubar) def add_image(self, image, title = None, onclick = None): if self._image is not None: self._image.close() self._image = tk_local.Image(self._root, image, lambda event, *_: self._apply( onclick, event )) if title is not None: self.set_subtitle(title) def refresh_image(self, image, title = None): if self._image is not None: self._image.refresh(image) if title is not None: self.set_subtitle(title) def close_image(self): if self._image is not None: if tkMessageBox.askokcancel("Quit", "Do you want to close the image?"): self._image.close() self._image = None return True return False def open_log(self): self._logger = tk_local.Log(self._root) def write_log(self, fmt, *args): if self._logger: self._logger.write_logger(fmt, *args) def append_log(self, fmt, *args): if self._logger: self._logger.append_logger(fmt, *args) def clear_log(self): if self._logger: self._logger.clear_logger() def toogle_log(self): if self._logger: self.close_log() else: self.open_log() def close_log(self): if self._logger: self._logger.destroy_logger() self._logger = None def add_panel(self, left = True): self._grid = tk_local.CustomGrid(self._root, 175) side = Tk.LEFT if left == True else Tk.RIGHT self._grid.pack(side=side, fill=Tk.Y, expand=False) def add_panel_classes(self, classes = None, selected = 0): if self._grid is None: self._grid = tk_local.CustomGrid(self._root) self.clear_panel_classes() classes = classes if classes is not None else [] self._grid.add_cell_label("", 0, 0, 1, 4) self._grid.add_cell_label("Classes ", 0, 1, 12, 4) self._grid.add_cell_label("", 0, 3, 2, 4) length = len(classes) for i in range(1, length+1): self._grid.add_cell_radio_button(classes[i-1]["name"].value[:12], i, i, 1, 12, selected=True if i == selected+1 else False, command=classes[i-1]["callback"].value, command_args=classes[i-1]["args"].value ) self._grid.add_cell_button_color("", i, 2, 2, bg=classes[i-1]["color"].value, command=classes[i-1]["callback_color"].value, command_args=classes[i-1]["args"].value ) self._grid.pack(side=Tk.LEFT, fill=Tk.Y, expand=False) def refresh_panel_classes(self, classes = None, selected = 0): self.clear_panel_classes() self.add_panel_classes(classes, selected) def clear_panel_classes(self): for i in range(1, self.MAX_CLASSES+1): self._grid.add_cell_label("", i, 1, 15) self._grid.add_cell_label("", i, 2, 2) def close_panel(self): if self._grid is not None: self._grid.pack_forget(); self._grid.destroy(); def popup(self): pass def log_and_popup(self, message): pass def dialogue_config(self, title, configs, callback): self._conf_dialog = tk_local.ConfigDialog(self._root, title, configs, command_ok = lambda *_: self._apply( callback )) def dialogue_choose_one(self, title, configs, callback): self._conf_dialog = tk_local.ChooseOneDialog(self._root, title, configs, command_ok = lambda *_: self._apply( callback )) def get_config_and_destroy(self): if self._conf_dialog is None: return None try: self._conf_dialog.update_and_validate_configs() configs = self._conf_dialog.get_configs() self._conf_dialog.destroy() self._conf_dialog = None return configs except: self._conf_dialog.destroy() raise IException("Illegal values, please try again") def show_error(self, fmt, *args): tkMessageBox.showerror("Error", fmt % args) def show_info(self, fmt, *args): tkMessageBox.showinfo("Info", fmt % args) def show_warning(self, fmt, *args): tkMessageBox.showwarning("Warning", fmt % args) def show(self): self._root.protocol("WM_DELETE_WINDOW", self.quit) self._root.mainloop() def quit(self): if tkMessageBox.askokcancel("Quit", "Do you want to quit?"): self._root.quit() self._root.destroy() def debug(self, event): print("DEBUG") def _apply(self, f, *args): try: f(*args) except IException as exc: self._log_exception( str(exc), True ) except: self._log_exception( IException.format_exception() ) def _log_exception(self, message, warning = False): if warning == True: self.show_warning( message ) elif IException.DEBUG == True: self.append_log( message ) else: self.show_error( message )