Пример #1
0
class LineWidgit(tkinter.Frame):
    '''
    This is the GUI widget that represents a single line in the output
    data. It uses the data_store to communicate values into and out of
    itself.
    '''

    def __init__(self, parent,lineno):
        self.logger = Logger(self, Logger.INFO)
        self.logger.debug("constructor")
        tkinter.Frame.__init__(self, parent)

        self.data_store = DataStore.get_instance()
        self.index = lineno

        self.name = "Hole %d" % (lineno+1)
        self.line_name = tkinter.Label(self, text=self.name, width=12)
        self.line_name.grid(row=lineno+1, column=0, sticky=tkinter.W)

        self.inter_ctl = tkinter.Entry(self, width=5, validate="focusout", validatecommand=self.change_interval)
        self.inter_ctl.bind('<Return>', self.change_interval)
        self.inter_ctl.bind('<Tab>', self.change_interval)
        self.inter_ctl.grid(row=lineno+1, column=1)

        self.note_ctl_txt = tkinter.StringVar()
        self.note_ctl = tkinter.Label(self, textvariable=self.note_ctl_txt, width=12)
        self.note_ctl.grid(row=lineno+1, column=2)

        self.freq_ctl_txt = tkinter.StringVar()
        self.freq_ctl = tkinter.Label(self, textvariable=self.freq_ctl_txt, width=12)
        self.freq_ctl.grid(row=lineno+1, column=3)

        self.hole_ctl = HoleSizeWidgit(self, lineno)
        self.hole_ctl.config(padx=25)
        self.hole_ctl.grid(row=lineno+1, column=4)

        self.locat_ctl_txt = tkinter.StringVar()
        self.locat_ctl = tkinter.Label(self, textvariable=self.locat_ctl_txt, width=12)
        self.locat_ctl.grid(row=lineno+1, column=5)

        self.diff_ctl_txt = tkinter.StringVar()
        self.diff_ctl = tkinter.Label(self, textvariable=self.diff_ctl_txt, width=12)
        self.diff_ctl.grid(row=lineno+1, column=6)

        self.cutoff_ctl_txt = tkinter.StringVar()
        self.cutoff_ctl = tkinter.Label(self, textvariable=self.cutoff_ctl_txt, width=12)
        self.cutoff_ctl.grid(row=lineno+1, column=7)

        self.set_state()

        self.logger.debug("end constructor")

    @debugger
    def set_state(self):
        '''
        Place the data from the data_store into the GUI.
        '''
        self.inter_ctl.delete(0, tkinter.END)
        self.inter_ctl.insert(0, str(self.data_store.get_hole_interval(self.index)))
        self.note_ctl_txt.set(str(self.data_store.get_hole_note(self.index))) # Label
        self.freq_ctl_txt.set("%s Hz"%(str(self.data_store.get_hole_freq(self.index))))
        self.locat_ctl_txt.set("%0.4f"%self.data_store.get_hole_xloc(self.index)) # Label
        self.diff_ctl_txt.set("%0.4f"%self.data_store.get_hole_diff(self.index)) # Label
        self.cutoff_ctl_txt.set("%0.4f"%self.data_store.get_hole_cutoff(self.index)) # Label
        self.hole_ctl.set_state()

    @debugger
    def get_state(self):
        '''
        Get the data out of the display and place it in the data_store.
        '''
        self.data_store.set_hole_interval(self.index, int(self.inter_ctl.get()))
        self.data_store.set_hole_note(self.index, self.note_ctl_txt.get()) # str
        self.data_store.set_hole_freq(self.index, float(self.freq_ctl_txt.get().split()[0]))
        self.data_store.set_hole_location(self.index, float(self.locat_ctl_txt.get()))
        self.data_store.set_hole_diff(self.index, float(self.diff_ctl_txt.get()))
        self.data_store.set_hole_cutoff(self.index, float(self.cutoff_ctl_txt.get()))
        self.hole_ctl.get_state()

    @debugger
    def print_state(self):
        self.logger.msg(str(self.get_state()))

    @debugger
    def change_units(self):
        '''
        When this is called, it is assumed that the datastore and the GUI need to have
        the vaules updated to reflect the new units.
        '''
        if self.data_store.get_units():
            self.data_store.set_hole_size(self.index, utility.in_to_mm(self.data_store.get_hole_size(self.index)))
            self.data_store.set_hole_location(self.index, utility.in_to_mm(self.data_store.get_hole_location(self.index)))
            self.data_store.set_hole_diff(self.index, utility.in_to_mm(self.data_store.get_hole_diff(self.index)))
            self.data_store.set_hole_cutoff(self.index, utility.in_to_mm(self.data_store.get_hole_cutoff(self.index)))
        else:
            self.data_store.set_hole_size(self.index, utility.mm_to_in(self.data_store.get_hole_size(self.index)))
            self.data_store.set_hole_location(self.index, utility.mm_to_in(self.data_store.get_hole_location(self.index)))
            self.data_store.set_hole_diff(self.index, utility.mm_to_in(self.data_store.get_hole_diff(self.index)))
            self.data_store.set_hole_cutoff(self.index, utility.mm_to_in(self.data_store.get_hole_cutoff(self.index)))
        self.set_state()
        self.data_store.set_change_flag()

    @debugger
    def change_interval(self, event=None):
        try:
            val = int(self.inter_ctl.get())
            oldval = self.data_store.get_hole_interval(self.index)
            if val != oldval:
                if val > 0 and val < 5:
                    self.data_store.set_hole_interval(self.index, val)
                    self.logger.debug("change interval from %d to %d"%(oldval, val))
                    raise_event("UPDATE_NOTES_EVENT")
                    self.data_store.set_change_flag()
                else:
                    self.logger.error("invalid value for interval: %s"%(str(self.inter_ctl.get())))
                    messagebox.showerror("ERROR", "Intervals must be an integer between 1 and 4")
                    self.inter_ctl.delete(0, tkinter.END)
                    self.inter_ctl.insert(0, str(self.data_store.get_hole_interval(self.index)))
                    return False
            else:
                self.logger.debug("ignore")
        except ValueError:
            self.logger.error("invalid integer for interval: %s"%(str(self.inter_ctl.get())))
            messagebox.showerror("ERROR", "Cannot convert the string \"%s\" to an integer between 1 1nd 4"%(self.inter_ctl.get()))
            self.inter_ctl.delete(0, tkinter.END)
            self.inter_ctl.insert(0, str(self.data_store.get_hole_interval(self.index)))
            return False
        except IndexError:
            pass  # always ignore

        return True
class HoleSizeWidgit(tkinter.Frame):

    def __init__(self, parent, line):
        '''
        This is a specialized widget to track the hole diameter. It displays 
        the value according to the state. It has up and down buttons used to
        increment or decrement the value. 
        '''
        self.logger = Logger(self, Logger.INFO)
        self.logger.debug("constructor")
        self.index = line

        tkinter.Frame.__init__(self, parent)
        self.data_store = DataStore.get_instance()

        BITMAP_UP = """
            #define up_width 9
            #define up_height 5
            static unsigned char up_bits[] = {
                0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0xff, 0x01 };
            """

        BITMAP_DOWN = """
            #define down_width 9
            #define down_height 5
            static unsigned char down_bits[] = {
                0xff, 0x01, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00 };
        """

        self.entry = tkinter.Entry(self, width=25-18)
        self.entry.grid(row=0, column=1, rowspan=2)

        self.bitmap_up = tkinter.BitmapImage(data=BITMAP_UP)
        self.b1 = tkinter.Button(self, text="up", image=self.bitmap_up, command=self.incr_command)
        self.b1.grid(row=0, column=2)
        self.b1.config(width=9, height=5)

        self.bitmap_down = tkinter.BitmapImage(data=BITMAP_DOWN)
        self.b2 = tkinter.Button(self, image=self.bitmap_down, command=self.decr_command)
        self.b2.grid(row=1, column=2)
        self.b2.config(width=9, height=5)
        
        register_event("UPDATE_HOLE_EVENT", self.update_val)
        self.set_state()

        self.logger.debug("constructor return")

    @debugger
    def get_state(self):
        '''
        Put the current value into the data_store.
        '''
        try:
            if self.data_store.get_disp_frac():
                val = utility.fractof(self.entry.get())
            else:
                val = float(self.entry.get())
        except ValueError as e:
            mbox.showerror('ERROR', 'Cannot convert hole to float: \"%s\": %s'%(self.entry.get(), e))

        self.data_store.set_hole_size(self.index, val)

    @debugger
    def set_state(self):
        '''
        Get the current state from the data_store and place it in the GUI
        '''
        self.update_val()   # display the new state

    @debugger
    def update_val(self):
        siz = self.data_store.get_hole_size(self.index)
        self.entry.delete(0, tkinter.END)
        if not self.data_store.get_units():
            self.logger.debug("updating inch value to %s"%(str(siz)))
            if self.data_store.get_disp_frac():
                self.entry.insert(0, "%s"%(utility.reduce(siz)))
            else:
                self.entry.insert(0, "%0.4f"%(siz))
        else:
            self.logger.debug("updating mm value to %s"%(str(siz)))
            self.entry.insert(0, "%0.4f"%(siz))

    # event handlers
    @debugger
    def incr_command(self):
        siz = self.data_store.get_hole_size(self.index)
        siz = siz + self.data_store.get_hole_inc()

        if siz > self.data_store.get_hole_max():
            siz = self.data_store.get_hole_max()
        elif siz < self.data_store.get_hole_min():
            siz = self.data_store.get_hole_min()

        self.data_store.set_hole_size(self.index, siz)
        self.update_val() # update the GUI
        raise_event("CALCULATE_EVENT")
        self.data_store.set_change_flag()

    @debugger
    def decr_command(self):
        siz = self.data_store.get_hole_size(self.index)
        siz = siz - self.data_store.get_hole_inc()

        if siz < self.data_store.get_hole_min():
            siz = self.data_store.get_hole_min()
        elif siz > self.data_store.get_hole_max():
            siz = self.data_store.get_hole_max()

        self.data_store.set_hole_size(self.index, siz)
        self.update_val() # update the GUI
        raise_event("CALCULATE_EVENT")
        self.data_store.set_change_flag()


    def print_state(self):
        self.logger.msg(str(self.get_state()))