TkInterface.py 6.97 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
  Nome: TkInterface.py
  Autor: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )

  Descricão: Classe que implementa os modulos de interface utilizando a biblioteca TkInter.
"""
import sys
if sys.version_info[0] < 3:
    import Tkinter as Tk
else:
    import tkinter as Tk
import tkMessageBox

from Interface import Interface, InterfaceException as IException
18
from tk import *
19 20 21

class TkInterface(Interface):
    
22 23
    MAX_CLASSES = 20
    
24
    utils = TkUtils.Utils
25 26 27 28 29

    title = None
    
    __root = None
    __menus = None
30 31
    __image = None
    __grid = None
32
    __logger = None
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48


    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 = []
        
    def set_subtitle(self, subtitle):
        self.__root.wm_title(self.title + ' - ' + subtitle)
    

    def add_menu(self, label):
49
        self.__menus.append( TkMenu.Menu(self.__root, label) )
50 51 52 53 54 55
    
    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( )
56 57 58
        
    def add_check_button(self, label, action, shortcut = None):
        self.__menus[-1].add_check_button(label = label, action = lambda *_: self.__apply( action ), shortcut = shortcut)
59 60 61

    def render_menu(self):
        menubar = Tk.Menu(self.__root)
62

63
        for menu in self.__menus:
64
            menu.render(menubar)
65 66 67 68 69
          
        self.__root.config(menu=menubar)
        
    
    def add_image(self, image, title = None, onclick = None):
70 71 72 73
        if self.__image is not None:
            self.__image.close()
           
        self.__image = TkCanvas.Image(self.__root, image, lambda event, *_: self.__apply( onclick, event ))
74
            
75 76 77 78 79 80
        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)
81 82 83 84 85 86
            
            if title is not None:
                self.set_subtitle(title)


    def close_image(self):
87
        if self.__image is not None:
88
            if tkMessageBox.askokcancel("Quit", "Do you want to close the image?"):
89
                self.__image.close()
90
                
91
                self.__image = None
92 93 94
                
                return True
        return False
95

96
                
97 98
    def open_log(self):
        self.__logger = TkLogger.Logger(self.__root)
99
        
100 101 102
    def write_log(self, fmt, *args):
        if self.__logger:
            self.__logger.write_logger(fmt, *args)
103
        
104 105 106
    def append_log(self, fmt, *args):
        if self.__logger:
            self.__logger.append_logger(fmt, *args)
107
        
108 109 110
    def clear_log(self):
        if self.__logger:
            self.__logger.clear_logger()
111 112 113 114 115 116
            
    def toogle_log(self):
        if self.__logger:
            self.close_log()
        else:
            self.open_log()
117
        
118 119 120
    def close_log(self):
        if self.__logger:
            self.__logger.destroy_logger()
121
            self.__logger = None
122 123

        
124 125
    def add_panel(self, left = True):
        self.__grid = TkCustomFrame.CustomGrid(self.__root, 175)
126
        
127 128
        side = Tk.LEFT if left == True else Tk.RIGHT
        self.__grid.pack(side=side, fill=Tk.Y, expand=False)
129
        
130
    def add_panel_classes(self, classes = None, selected = 0):
131 132 133
        if self.__grid is None:
            self.__grid = TkCustomFrame.CustomGrid(self.__root)
            self.clear_panel_classes()
134
        
135 136 137 138 139
        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)
140
        
141 142
        length = len(classes)
        for i in range(1, length+1):
143
            self.__grid.add_cell_radio_button(classes[i-1]["name"].value[:12], i, i, 1, 12, selected=True if i == selected+1 else False, 
144
                                                command=classes[i-1]["callback"].value, command_args=classes[i-1]["args"].value )
145 146
            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 )
147
            
148
        self.__grid.pack(side=Tk.LEFT, fill=Tk.Y, expand=False)
149
        
150
    def refresh_panel_classes(self, classes = None, selected = 0):
151
        self.clear_panel_classes()
152
        self.add_panel_classes(classes, selected)
153
        
154
    def clear_panel_classes(self):
155 156 157
        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)
158 159 160 161 162

    def close_panel(self):
        if self.__grid is not None:
            self.__grid.pack_forget();
            self.__grid.destroy();
163 164
        
        
165 166
    def popup(self):
        pass
167
        
168 169
    def log_and_popup(self, message):
        pass
170

171 172 173 174
        
    def dialogue_config(self, title, configs, callback):
        self.__conf_dialog = TkCustomDialog.ConfigDialog(self.__root, title, configs, command_ok = lambda *_: self.__apply( callback ))
        
175
    def get_config_and_destroy(self):
176 177 178
        if self.__conf_dialog is None:
            return None
        
179
        try:
180 181 182 183 184 185 186 187
            self.__conf_dialog.update_and_validate_configs()
            
            configs = self.__conf_dialog.get_configs()
            
            self.__conf_dialog.destroy()
            self.__conf_dialog = None
            
            return configs
188
        except:    
189
            self.__conf_dialog.destroy()
190 191
            raise IException("Illegal values, please try again")

192 193 194 195 196 197 198 199 200 201 202 203 204 205

    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()
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
        
    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:
230
            self.append_log( message )
231 232
        else:
            self.show_error( message )