Exemplo n.º 1
0
    def open_text(self):
        if self.selected_text_title != "[]":

            text_root = tk.Tk()
            popup = tk.Menu(text_root, tearoff=0)
            textWindow = ScrolledText(text_root, wrap="word")
            uw_list = self.uw_lb.get(0, tk.END)
            text_root.bind(
                "<Button-1>", lambda eff: meaning_part(
                    eff, T=textWindow, unknown_words_list=uw_list, popup=popup)
            )
            textWindow.insert(1.0,
                              general_dict["Text"][self.selected_text_title])
            textWindow.tag_config("A", foreground="red", background="white")
            textWindow.pack(expand=True, fill=tk.BOTH)
            for word in general_dict["Unknown"][self.selected_text_title]:
                word = " " + word + " "
                start = 1.0
                search_pos = textWindow.search(word, start, stopindex=tk.END)

                while search_pos:
                    length = len(word)
                    row, col = search_pos.split('.')
                    end = int(col) + length
                    if str(end)[-1] == "0":
                        end += 1

                    end = row + '.' + str(end)

                    textWindow.tag_add("A", search_pos, float(end))
                    start = end
                    search_pos = textWindow.search(word,
                                                   start,
                                                   stopindex=tk.END)
Exemplo n.º 2
0
    def open_text(self):
        if self.selected_text_title != "[]":

            text_root = tk.Tk()
            textWindow = ScrolledText(text_root, wrap="word")
            textWindow.insert(1.0,
                              general_dict["Text"][self.selected_text_title])
            textWindow.tag_config("A", foreground="red", background="white")
            textWindow.pack(expand=True, fill=tk.BOTH)
            for word in general_dict["Unknown"][self.selected_text_title]:
                word = " " + word + " "
                start = 1.0
                search_pos = textWindow.search(word, start, stopindex=tk.END)

                while search_pos:
                    length = len(word)
                    row, col = search_pos.split('.')
                    end = int(col) + length
                    if str(end)[-1] == "0":
                        end += 1

                    end = row + '.' + str(end)

                    textWindow.tag_add("A", search_pos, float(end))
                    start = end
                    search_pos = textWindow.search(word,
                                                   start,
                                                   stopindex=tk.END)
Exemplo n.º 3
0
class CopyableMessageWindow(basicWindow):
    """ Creates a modeless (non-modal) message window that allows the user to copy the presented text. """
    def __init__(self, topLevel, message, title, align, buttons, makeModal):
        self.guiRoot = topLevel

        basicWindow.__init__(self,
                             topLevel,
                             title,
                             resizable=True,
                             topMost=False)

        linesInMessage = len(message.splitlines())
        if linesInMessage > 17: height = 22
        else: height = linesInMessage + 5

        self.messageText = ScrolledText(self.mainFrame,
                                        relief='groove',
                                        wrap='word',
                                        height=height)
        self.messageText.insert('1.0', '\n' + message)
        self.messageText.tag_add('All', '1.0', 'end')
        self.messageText.tag_config('All', justify=align)
        self.messageText.pack(fill='both', expand=1)

        # Add the buttons
        self.buttonsFrame = Tk.Frame(self.mainFrame)
        ttk.Button(self.buttonsFrame, text='Close',
                   command=self.close).pack(side='right', padx=5)
        if buttons:
            for button in buttons:
                buttonText, buttonCommand = button
                ttk.Button(self.buttonsFrame,
                           text=buttonText,
                           command=buttonCommand).pack(side='right', padx=5)
        ttk.Button(self.buttonsFrame,
                   text='Copy text to Clipboard',
                   command=self.copyText).pack(side='right', padx=5)
        self.buttonsFrame.pack(pady=3)

        if makeModal:
            self.window.grab_set()
            self.guiRoot.wait_window(self.window)

    # Button functions
    def copyText(self):
        self.guiRoot.clipboard_clear()
        self.guiRoot.clipboard_append(
            self.messageText.get('1.0', 'end').strip())
Exemplo n.º 4
0
class CopyableMsg(basicWindow):
    """ Creates a modeless (non-modal) message window that allows the user to easily copy the given text. 
		If buttons are provided, they should be an iterable of tuples of the form (buttonText, buttonCallback). """
    def __init__(self,
                 root,
                 message='',
                 title='',
                 alignment='center',
                 buttons=None):
        super(CopyableMsg, self).__init__(root,
                                          title,
                                          resizable=True,
                                          topMost=False)
        self.root = root

        if alignment == 'left':
            height = 22  # Expecting a longer, more formal message
        else:
            height = 14

        # Add the main text display of the window
        self.messageText = ScrolledText(self.window,
                                        relief='groove',
                                        wrap='word',
                                        height=height)
        self.messageText.insert('1.0', message)
        self.messageText.tag_add('All', '1.0', 'end')
        self.messageText.tag_config('All', justify=alignment)
        self.messageText.pack(fill='both', expand=1)

        # Add the buttons
        self.buttonsFrame = Tkinter.Frame(self.window)
        ttk.Button(self.buttonsFrame, text='Close',
                   command=self.close).pack(side='right', padx=5)
        if buttons:
            for buttonText, buttonCommand in buttons:
                ttk.Button(self.buttonsFrame,
                           text=buttonText,
                           command=buttonCommand).pack(side='right', padx=5)
        ttk.Button(self.buttonsFrame,
                   text='Copy text to Clipboard',
                   command=self.copyToClipboard).pack(side='right', padx=5)
        self.buttonsFrame.pack(pady=3)

    def copyToClipboard(self):
        self.root.clipboard_clear()
        self.root.clipboard_append(self.messageText.get('1.0', 'end'))
Exemplo n.º 5
0
    def open_text(self):
        #in the usage of tags there were 3 problems faced, 1-the markings such as dot, comma but it is solved
        # 2-Uppercases are not matching, this is not solved
        # 3-Words that are shorter than 4 letters take the next words first letter
        if self.selected_text_title != "[]":

            text_root = tk.Tk()
            text_root.title(self.selected_text_title)
            popup = tk.Menu(text_root, tearoff=0)
            textWindow = ScrolledText(text_root, wrap = "word")
            uw_list = self.uw_lb.get(0,tk.END)
            text_root.bind("<Button-1>", lambda eff:meaning_part(eff, T=textWindow, unknown_words_list=uw_list, popup=popup))
            textWindow.insert(1.0, general_dict["Text"][self.selected_text_title])
            textWindow.tag_config("A", foreground="red", background="white")
            textWindow.pack(expand = True, fill = tk.BOTH)
            for pre_word in uw_list:#general_dict["Unknown"][self.selected_text_title]:
                word =  " " + pre_word + " "
                start = 1.0
                search_pos = textWindow.search(word, start, stopindex=tk.END)
                if not search_pos:
                    for x in '"^+%&/()=?_-*,;:.!>#${{[]}\'':
                        word = " " + pre_word + x
                        search_pos = textWindow.search(word, start, stopindex=tk.END)
                        if search_pos: break
                    if not search_pos:
                        for x in '"^+%&/()=?_-*,;:.!>#${{[]}\'':
                            word = x + pre_word + " "
                            search_pos = textWindow.search(word, start, stopindex=tk.END)
                            if search_pos: break
                #print word, search_pos

                while search_pos:
                    length = len(word)
                    row, col = search_pos.split('.')
                    end = int(col) + length
                    #if str(end)[-1]=="0":
                    #    end += 1

                    print end, col
                    end = row + '.' + str(end)

                    print search_pos, end, word
                    textWindow.tag_add("A", search_pos, float(end))
                    start = end
                    search_pos = textWindow.search(word, start, stopindex=tk.END)
Exemplo n.º 6
0
class myPanel(tkinter.Tk):
    def __init__(self):
        tkinter.Tk.__init__(self, 'lsx')

        try:
            self.ss = self.clipboard_get()
        except:
            self.ss = ''
        self.cnt = 0
        self.slices = paragraph(self.ss, qrlen)
        self.string = None

        if not os.path.exists('config.ini'):
            x = - 100 + 0.2 * self.winfo_screenwidth() # 100: 补偿初始Tk界面为200x200
            y = - 100 + 0.7 * self.winfo_screenheight()
            xy = '+%d+%d'%(x,y)
            with open('config.ini','w') as f:
                f.write(xy)
        with open('config.ini','r') as f:
            xy = f.read()
        self.geometry(xy)
        self.minsize(450,206)

        self.qrc = tkinter.Label(self)
        self.ent = ScrolledText(self, width=1, height=15)
        self.ent.insert(1.0, self.ss)
        self.ent.mark_set('insert','0.0') # 程序首次运行时不使用see函数,否则会有未知原因半行内容沉没在Text窗体上面一点点
        self.ent.focus()

        text = self.slices[self.cnt]
        basic = (len(self.slices),len(self.ss))
        info = 'Page: %s, Length: %s'%basic
        if zh_cn:
            info = '共%s页, %s字'%basic

        self.withdraw() # withdraw/deiconify 阻止页面闪烁
        self.update_idletasks()
        self.ent.pack(padx=2, pady=2, fill='both', expand=True, side='right') # RIGHT为了在Label隐藏再显示后所在位置一致
        self.qrc.pack()
        self.setQrcode(text, info)
        self.deiconify()

        self.qrc.bind('<Button-2>',self.onExit)
        self.qrc.bind('<Button-1>',self.fliping)
        self.qrc.bind('<Button-3>',self.fliping)
        self.qrc.bind('<Double-Button-1>',self.setting)
        self.qrc.bind('<Double-ButtonRelease-3>',self.openFile) # 没有Release会在窗口打开之后的鼠标抬起时唤起右键菜单

        self.ent.bind('<Escape>',self.onExit)
        self.ent.bind('<F1>',self.openFile)
        self.ent.bind('<F2>',self.fliping)
        self.ent.bind('<F3>',self.fliping)
        self.ent.bind('<F4>',self.setting)

        self.ent.bind('<KeyRelease>',self.refresh)
        self.ent.bind('<ButtonRelease-1>',self.selected)
        self.bind('<Destroy>',lambda evt:self.onExit(evt,close=True))

    def setQrcode(self, string, info):
        if self.string != string:
            self.string = string
            if string == '':
                self.qrc.forget()
            else:
                global img
                img = qrmake(string)
                self.qrc.config(image=img)
                self.qrc.pack()
        log(string, info)
        self.title('Text Helper v1.06 (%s)'%info)
        if zh_cn:
            self.title('文本助手v1.06 (%s)'%info)

    def refresh(self, evt):
        if evt.keysym in ['Control_L', 'Return', 'BackSpace']:
            ss2 = self.ent.get('0.0', 'end')[:-1]
            if self.ss != ss2:
                self.ss = ss2
                self.cnt = 0
                self.slices = paragraph(self.ss, qrlen)

            text = self.slices[self.cnt]
            basic = (len(self.slices),len(self.ss))
            info = 'Page: %s, Length: %s'%basic
            if zh_cn:
                info = '共%s页, %s字'%basic
            self.setQrcode(text, info)

    def fliping(self, evt):
        if evt.num == 1 or evt.keysym == 'F3':
            self.cnt = min(self.cnt+1,len(self.slices)-1)
        else:
            self.cnt = max(self.cnt-1,0)
        cur1 = getIndex(''.join(self.slices[:self.cnt]))
        cur2 = getIndex(''.join(self.slices[:self.cnt+1]))
        self.setCursor(cur1, cur2)

        text = self.slices[self.cnt]
        basic = (self.cnt+1,len(self.slices),len(text),len(self.ss))
        info = 'Page: %s/%s, Sel: %s/%s'%basic
        if zh_cn:
            info = '第%s/%s页, 共%s/%s字'%basic
        self.setQrcode(text, info)

    def selected(self, evt):
        if self.ent.tag_ranges('sel'):
            text = self.ent.selection_get()
            info = 'Sel: %s/%s'%(len(text),len(self.ss))
            if zh_cn:
                info = '选中%s/%s字'%(len(text),len(self.ss))
            self.setQrcode(text, info)

    def setCursor(self, cur1, cur2):
        self.ent.mark_set('insert', cur1)
        self.ent.tag_remove('sel','0.0','end')
        self.ent.tag_add('sel',cur1,cur2)
        self.ent.see(cur1)

    def setting(self, evt):
        max_page = len(self.slices)
        num = tkinter.simpledialog.askinteger('Goto','Go to page (1-%s):'%max_page, initialvalue=self.cnt+1)
        self.ent.focus()
        if num:
            self.cnt = max(1,min(max_page,num)) - 1

            text = self.slices[self.cnt]
            basic = (self.cnt+1,len(self.slices),len(text),len(self.ss))
            info = 'Page: %s/%s, Sel: %s/%s'%basic
            if zh_cn:
                info = '第%s/%s页, 共%s/%s字'%basic
            self.setQrcode(text, info)

    def openFile(self, evt):
        path = tkinter.filedialog.askopenfilename()
        if path != '':
            filename = os.path.basename(path)
            with open(path,'rb') as f:
                s = f.read()
            try:
                try:
                    res = s.decode()
                except:
                    try:
                        res = s.decode('gbk')
                    except:
                        raise
            except:
                s = base64.urlsafe_b64encode(filename.encode()+b'\n'+s).decode()
                total = int((len(s)-1)/(qrlen-10)+1)
                res = ''
                for i in range(total):
                    res += '%04d%04d.%s,'%(total, i+1, s[(qrlen-10)*i:(qrlen-10)*(i+1)])

            self.ss = res
            self.cnt = 0
            self.slices = paragraph(self.ss, qrlen)
            self.ent.delete(1.0, 'end')
            self.ent.insert(1.0, res)

            text = self.slices[self.cnt]
            basic = (len(self.slices),len(self.ss))
            info = 'Page: %s, Length: %s'%basic
            if zh_cn:
                info = '共%s页, %s字'%basic
            self.setQrcode(text, info)

    def onExit(self, evt, close=False):
        xy = '+%d+%d'%(self.winfo_x(),self.winfo_y())
        with open('config.ini','w') as f:
            f.write(xy)
        if not close:
            self.destroy()
Exemplo n.º 7
0
class Tkui(base.BaseUI):
    """
  This is a ui class which handles the complete Tk user interface.
  """

    def __init__(self):
        """ Initializes."""
        base.BaseUI.__init__(self)

        # internal ui queue
        self._event_queue = Queue.Queue()

        # map of session -> (bold, foreground, background)
        self._currcolors = {}

        # ses -> string
        self._unfinishedcolor = {}

        self._viewhistory = 0
        self._do_i_echo = 1

        # holds a map of window names -> window references
        self._windows = {}

        # instantiate all the widgets
        self._tk = Tk()
        self._tk.geometry("800x600")

        self.settitle()

        if os.name == "posix":
            fnt = tkFont.Font(family="Courier", size=12)
        else:
            fnt = tkFont.Font(family="Fixedsys", size=12)

        self._entry = CommandEntry(
            self._tk, self, fg="white", bg="black", insertbackground="yellow", font=fnt, insertwidth="2"
        )
        self._entry.pack(side="bottom", fill="both")

        self._topframe = Frame(self._tk)
        self._topframe.pack(side="top", fill="both", expand=1)

        self._txt = ScrolledText(self._topframe, fg="white", bg="black", font=fnt, height=20)
        self._txt.pack(side="bottom", fill="both", expand=1)

        self._txt.bind("<KeyPress>", self._ignoreThis)
        self._txtbuffer = ScrolledText(self._topframe, fg="white", bg="black", font=fnt, height=20)
        self._txtbuffer.bind("<KeyPress-Escape>", self.escape)
        self._txtbuffer.bind("<KeyPress>", self._ignoreThis)

        self._entry.focus_set()
        self._initColorTags()
        self.dequeue()

        exported.hook_register("config_change_hook", self.configChangeHandler)
        exported.hook_register("to_user_hook", self.write)

        # FIXME - fix this explanation.  this is just terrible.
        tc = config.BoolConfig(
            "saveinputhighlight",
            0,
            1,
            "Allows you to change the behavior of the command entry.  When "
            "saveinputhighlight is off, we discard whatever is on the entry "
            "line.  When it is on, we will retain the contents allowing you "
            "to press the enter key to do whatever you typed again.",
        )
        exported.add_config("saveinputhighlight", tc)

        self._quit = 0

    def runui(self):
        global HELP_TEXT
        exported.add_help("tkui", HELP_TEXT)
        exported.write_message('For tk help type "#help tkui".')
        exported.add_command("colorcheck", colorcheck_cmd)

        # run the tk mainloop here
        self._tk.mainloop()

    def wantMainThread(self):
        # The tkui needs the main thread of execution so we return
        # a 1 here.
        return 1

    def quit(self):
        if not self._quit:
            self._quit = 1
            self._topframe.quit()

    def dequeue(self):
        qsize = self._event_queue.qsize()
        if qsize > 10:
            qsize = 10

        for i in range(qsize):
            ev = self._event_queue.get_nowait()
            ev.execute(self)

        self._tk.after(25, self.dequeue)

    def settitle(self, title=""):
        """
    Sets the title bar to the Lyntin title plus the given string.

    @param title: the title to set
    @type  title: string
    """
        if title:
            title = constants.LYNTINTITLE + title
        else:
            title = constants.LYNTINTITLE
        self._event_queue.put(_TitleEvent(self._tk, title))

    def removeWindow(self, windowname):
        """
    This removes a NamedWindow from our list of NamedWindows.

    @param windowname: the name of the window to write to
    @type  windowname: string
    """
        if self._windows.has_key(windowname):
            del self._windows[windowname]

    def writeWindow(self, windowname, message):
        """
    This writes to the window named "windowname".  If the window
    does not exist, we spin one off.  It handles ansi text and
    messages just like writing to the main window.

    @param windowname: the name of the window to write to
    @type  windowname: string

    @param message: the message to write to the window
    @type  message: string or Message instance
    """
        self._event_queue.put(_WriteWindowEvent(windowname, message))

    def writeWindow_internal(self, windowname, message):
        if not self._windows.has_key(windowname):
            self._windows[windowname] = NamedWindow(windowname, self, self._tk)
        self._windows[windowname].write(message)

    def _ignoreThis(self, tkevent):
        """ This catches keypresses from the history buffer."""
        # kludge so that ctrl-c doesn't get caught allowing windows
        # users to copy the buffer....
        if tkevent.keycode == 17 or tkevent.keycode == 67:
            return

        self._entry.focus()
        if tkevent.char:
            # we do this little song and dance so as to pass events
            # we don't want to deal with to the entry widget essentially
            # by creating a new event and tossing it in the event list.
            # it only sort of works--but it's the best code we've got
            # so far.
            args = ("event", "generate", self._entry, "<KeyPress>")
            args = args + ("-rootx", tkevent.x_root)
            args = args + ("-rooty", tkevent.y_root)
            args = args + ("-keycode", tkevent.keycode)
            args = args + ("-keysym", tkevent.keysym)

            self._tk.tk.call(args)

        return "break"

    def pageUp(self):
        """ Handles prior (Page-Up) events."""
        if self._viewhistory == 0:
            self._txtbuffer.pack(side="top", fill="both", expand=1)

            self._viewhistory = 1
            self._txtbuffer.delete("1.0", "end")
            lotofstuff = self._txt.get("1.0", "end")
            self._txtbuffer.insert("end", lotofstuff)
            for t in self._txt.tag_names():
                taux = None
                tst = 0
                for e in self._txt.tag_ranges(t):
                    if tst == 0:
                        taux = e
                        tst = 1
                    else:
                        tst = 0
                        self._txtbuffer.tag_add(t, str(taux), str(e))

            self._txtbuffer.yview("moveto", "1")
            if os.name != "posix":
                self._txtbuffer.yview("scroll", "20", "units")
            self._tk.update_idletasks()
            self._txt.yview("moveto", "1.0")
            if os.name != "posix":
                self._txt.yview("scroll", "220", "units")

        else:
            # yscroll up stuff
            self._txtbuffer.yview("scroll", "-15", "units")

    def pageDown(self):
        """ Handles next (Page-Down) events."""
        if self._viewhistory == 1:
            # yscroll down stuff
            self._txtbuffer.yview("scroll", "15", "units")

    def escape(self, tkevent):
        """ Handles escape (Escape) events."""
        if self._viewhistory == 1:
            self._txtbuffer.forget()
            self._viewhistory = 0
        else:
            self._entry.clearInput()

    def configChangeHandler(self, args):
        """ This handles config changes including mudecho. """
        name = args["name"]
        newvalue = args["newvalue"]

        if name == "mudecho":
            if newvalue == 1:
                # echo on
                self._do_i_echo = 1
                self._entry.configure(show="")
            else:
                # echo off
                self._do_i_echo = 0
                self._entry.configure(show="*")

    def _yadjust(self):
        """Handles y scrolling after text insertion."""
        self._txt.yview("moveto", "1")
        # if os.name != 'posix':
        self._txt.yview("scroll", "20", "units")

    def _clipText(self):
        """
    Scrolls the text buffer up so that the new text written at
    the bottom of the text buffer can be seen.
    """
        temp = self._txt.index("end")
        ind = temp.find(".")
        temp = temp[:ind]
        if temp.isdigit() and int(temp) > 800:
            self._txt.delete("1.0", "100.end")

    def write(self, args):
        """
    This writes text to the text buffer for viewing by the user.

    This is overridden from the 'base.BaseUI'.
    """
        self._event_queue.put(_OutputEvent(args))

    def write_internal(self, args):
        mess = args["message"]
        if type(mess) == types.StringType:
            mess = message.Message(mess, message.LTDATA)

        line = mess.data
        ses = mess.session

        if line == "" or self.showTextForSession(ses) == 0:
            return

        color, leftover = buffer_write(mess, self._txt, self._currcolors, self._unfinishedcolor)

        if mess.type == message.MUDDATA:
            self._unfinishedcolor[ses] = leftover
            self._currcolors[ses] = color

        self._clipText()
        self._yadjust()

    def convertColor(self, name):
        """
    Tk has this really weird color palatte.  So I switched to using
    color names in most cases and rgb values in cases where I couldn't
    find a good color name.

    This method allows me to specify either an rgb or a color name
    and it converts the color names to rgb.

    @param name: either an rgb value or a name
    @type  name: string

    @returns: the rgb color value
    @rtype: string
    """
        if name.startswith("#"):
            return name

        rgb = self._tk._getints(self._tk.tk.call("winfo", "rgb", self._txt, name))
        rgb = "#%02x%02x%02x" % (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256)
        print name, "converted to: ", rgb

        return rgb

    def _initColorTags(self):
        """ Sets up Tk tags for the text widget (fg/bg/u)."""
        for ck in fg_color_codes.keys():
            color = self.convertColor(fg_color_codes[ck])
            self._txt.tag_config(ck, foreground=color)
            self._txtbuffer.tag_config(ck, foreground=color)

        for ck in bg_color_codes.keys():
            self._txt.tag_config(ck, background=bg_color_codes[ck])
            self._txtbuffer.tag_config(ck, background=bg_color_codes[ck])

        self._txt.tag_config("u", underline=1)
        self._txtbuffer.tag_config("u", underline=1)

    def colorCheck(self):
        """
    Goes through and displays all the combinations of fg and bg
    with the text string involved.  Purely for debugging
    purposes.
    """
        fgkeys = ["30", "31", "32", "33", "34", "35", "36", "37"]
        bgkeys = ["40", "41", "42", "43", "44", "45", "46", "47"]

        self._txt.insert("end", "color check:\n")
        for bg in bgkeys:
            for fg in fgkeys:
                self._txt.insert("end", str(fg), (fg, bg))
                self._txt.insert("end", str("b" + fg), ("b" + fg, bg))
            self._txt.insert("end", "\n")

            for fg in fgkeys:
                self._txt.insert("end", str(fg), (fg, "b" + bg))
                self._txt.insert("end", str("b" + fg), ("b" + fg, "b" + bg))
            self._txt.insert("end", "\n")

        self._txt.insert("end", "\n")
        self._txt.insert("end", "\n")
Exemplo n.º 8
0
class Tkui(base.BaseUI):
    """
  This is a ui class which handles the complete Tk user interface.
  """
    def __init__(self):
        """ Initializes."""
        base.BaseUI.__init__(self)

        # internal ui queue
        self._event_queue = Queue.Queue()

        # map of session -> (bold, foreground, background)
        self._currcolors = {}

        # ses -> string
        self._unfinishedcolor = {}

        self._viewhistory = 0
        self._do_i_echo = 1

        # holds a map of window names -> window references
        self._windows = {}

        # instantiate all the widgets
        self._tk = Tk()
        self._tk.geometry("800x600")

        self.settitle()

        if os.name == 'posix':
            fnt = tkFont.Font(family="Courier", size=12)
        else:
            fnt = tkFont.Font(family="Fixedsys", size=12)

        self._entry = CommandEntry(self._tk,
                                   self,
                                   fg='white',
                                   bg='black',
                                   insertbackground='yellow',
                                   font=fnt,
                                   insertwidth='2')
        self._entry.pack(side='bottom', fill='both')

        self._topframe = Frame(self._tk)
        self._topframe.pack(side='top', fill='both', expand=1)

        self._txt = ScrolledText(self._topframe,
                                 fg='white',
                                 bg='black',
                                 font=fnt,
                                 height=20)
        self._txt.pack(side='bottom', fill='both', expand=1)

        self._txt.bind("<KeyPress>", self._ignoreThis)
        self._txtbuffer = ScrolledText(self._topframe,
                                       fg='white',
                                       bg='black',
                                       font=fnt,
                                       height=20)
        self._txtbuffer.bind("<KeyPress-Escape>", self.escape)
        self._txtbuffer.bind("<KeyPress>", self._ignoreThis)

        self._entry.focus_set()
        self._initColorTags()
        self.dequeue()

        exported.hook_register("config_change_hook", self.configChangeHandler)
        exported.hook_register("to_user_hook", self.write)

        # FIXME - fix this explanation.  this is just terrible.
        tc = config.BoolConfig(
            "saveinputhighlight", 0, 1,
            "Allows you to change the behavior of the command entry.  When "
            "saveinputhighlight is off, we discard whatever is on the entry "
            "line.  When it is on, we will retain the contents allowing you "
            "to press the enter key to do whatever you typed again.")
        exported.add_config("saveinputhighlight", tc)

        self._quit = 0

    def runui(self):
        global HELP_TEXT
        exported.add_help("tkui", HELP_TEXT)
        exported.write_message("For tk help type \"#help tkui\".")
        exported.add_command("colorcheck", colorcheck_cmd)

        # run the tk mainloop here
        self._tk.mainloop()

    def wantMainThread(self):
        # The tkui needs the main thread of execution so we return
        # a 1 here.
        return 1

    def quit(self):
        if not self._quit:
            self._quit = 1
            self._topframe.quit()

    def dequeue(self):
        qsize = self._event_queue.qsize()
        if qsize > 10:
            qsize = 10

        for i in range(qsize):
            ev = self._event_queue.get_nowait()
            ev.execute(self)

        self._tk.after(25, self.dequeue)

    def settitle(self, title=""):
        """
    Sets the title bar to the Lyntin title plus the given string.

    @param title: the title to set
    @type  title: string
    """
        if title:
            title = constants.LYNTINTITLE + title
        else:
            title = constants.LYNTINTITLE
        self._event_queue.put(_TitleEvent(self._tk, title))

    def removeWindow(self, windowname):
        """
    This removes a NamedWindow from our list of NamedWindows.

    @param windowname: the name of the window to write to
    @type  windowname: string
    """
        if self._windows.has_key(windowname):
            del self._windows[windowname]

    def writeWindow(self, windowname, message):
        """
    This writes to the window named "windowname".  If the window
    does not exist, we spin one off.  It handles ansi text and
    messages just like writing to the main window.

    @param windowname: the name of the window to write to
    @type  windowname: string

    @param message: the message to write to the window
    @type  message: string or Message instance
    """
        self._event_queue.put(_WriteWindowEvent(windowname, message))

    def writeWindow_internal(self, windowname, message):
        if not self._windows.has_key(windowname):
            self._windows[windowname] = NamedWindow(windowname, self, self._tk)
        self._windows[windowname].write(message)

    def _ignoreThis(self, tkevent):
        """ This catches keypresses from the history buffer."""
        # kludge so that ctrl-c doesn't get caught allowing windows
        # users to copy the buffer....
        if tkevent.keycode == 17 or tkevent.keycode == 67:
            return

        self._entry.focus()
        if tkevent.char:
            # we do this little song and dance so as to pass events
            # we don't want to deal with to the entry widget essentially
            # by creating a new event and tossing it in the event list.
            # it only sort of works--but it's the best code we've got
            # so far.
            args = ('event', 'generate', self._entry, "<KeyPress>")
            args = args + ('-rootx', tkevent.x_root)
            args = args + ('-rooty', tkevent.y_root)
            args = args + ('-keycode', tkevent.keycode)
            args = args + ('-keysym', tkevent.keysym)

            self._tk.tk.call(args)

        return "break"

    def pageUp(self):
        """ Handles prior (Page-Up) events."""
        if self._viewhistory == 0:
            self._txtbuffer.pack(side='top', fill='both', expand=1)

            self._viewhistory = 1
            self._txtbuffer.delete("1.0", "end")
            lotofstuff = self._txt.get('1.0', 'end')
            self._txtbuffer.insert('end', lotofstuff)
            for t in self._txt.tag_names():
                taux = None
                tst = 0
                for e in self._txt.tag_ranges(t):
                    if tst == 0:
                        taux = e
                        tst = 1
                    else:
                        tst = 0
                        self._txtbuffer.tag_add(t, str(taux), str(e))

            self._txtbuffer.yview('moveto', '1')
            if os.name != 'posix':
                self._txtbuffer.yview('scroll', '20', 'units')
            self._tk.update_idletasks()
            self._txt.yview('moveto', '1.0')
            if os.name != 'posix':
                self._txt.yview('scroll', '220', 'units')

        else:
            # yscroll up stuff
            self._txtbuffer.yview('scroll', '-15', 'units')

    def pageDown(self):
        """ Handles next (Page-Down) events."""
        if self._viewhistory == 1:
            # yscroll down stuff
            self._txtbuffer.yview('scroll', '15', 'units')

    def escape(self, tkevent):
        """ Handles escape (Escape) events."""
        if self._viewhistory == 1:
            self._txtbuffer.forget()
            self._viewhistory = 0
        else:
            self._entry.clearInput()

    def configChangeHandler(self, args):
        """ This handles config changes including mudecho. """
        name = args["name"]
        newvalue = args["newvalue"]

        if name == "mudecho":
            if newvalue == 1:
                # echo on
                self._do_i_echo = 1
                self._entry.configure(show='')
            else:
                # echo off
                self._do_i_echo = 0
                self._entry.configure(show='*')

    def _yadjust(self):
        """Handles y scrolling after text insertion."""
        self._txt.yview('moveto', '1')
        # if os.name != 'posix':
        self._txt.yview('scroll', '20', 'units')

    def _clipText(self):
        """
    Scrolls the text buffer up so that the new text written at
    the bottom of the text buffer can be seen.
    """
        temp = self._txt.index("end")
        ind = temp.find(".")
        temp = temp[:ind]
        if (temp.isdigit() and int(temp) > 800):
            self._txt.delete("1.0", "100.end")

    def write(self, args):
        """
    This writes text to the text buffer for viewing by the user.

    This is overridden from the 'base.BaseUI'.
    """
        self._event_queue.put(_OutputEvent(args))

    def write_internal(self, args):
        mess = args["message"]
        if type(mess) == types.StringType:
            mess = message.Message(mess, message.LTDATA)

        line = mess.data
        ses = mess.session

        if line == '' or self.showTextForSession(ses) == 0:
            return

        color, leftover = buffer_write(mess, self._txt, self._currcolors,
                                       self._unfinishedcolor)

        if mess.type == message.MUDDATA:
            self._unfinishedcolor[ses] = leftover
            self._currcolors[ses] = color

        self._clipText()
        self._yadjust()

    def convertColor(self, name):
        """
    Tk has this really weird color palatte.  So I switched to using
    color names in most cases and rgb values in cases where I couldn't
    find a good color name.

    This method allows me to specify either an rgb or a color name
    and it converts the color names to rgb.

    @param name: either an rgb value or a name
    @type  name: string

    @returns: the rgb color value
    @rtype: string
    """
        if name.startswith("#"):
            return name

        rgb = self._tk._getints(
            self._tk.tk.call('winfo', 'rgb', self._txt, name))
        rgb = "#%02x%02x%02x" % (rgb[0] / 256, rgb[1] / 256, rgb[2] / 256)
        print name, "converted to: ", rgb

        return rgb

    def _initColorTags(self):
        """ Sets up Tk tags for the text widget (fg/bg/u)."""
        for ck in fg_color_codes.keys():
            color = self.convertColor(fg_color_codes[ck])
            self._txt.tag_config(ck, foreground=color)
            self._txtbuffer.tag_config(ck, foreground=color)

        for ck in bg_color_codes.keys():
            self._txt.tag_config(ck, background=bg_color_codes[ck])
            self._txtbuffer.tag_config(ck, background=bg_color_codes[ck])

        self._txt.tag_config("u", underline=1)
        self._txtbuffer.tag_config("u", underline=1)

    def colorCheck(self):
        """
    Goes through and displays all the combinations of fg and bg
    with the text string involved.  Purely for debugging
    purposes.
    """
        fgkeys = ['30', '31', '32', '33', '34', '35', '36', '37']
        bgkeys = ['40', '41', '42', '43', '44', '45', '46', '47']

        self._txt.insert('end', 'color check:\n')
        for bg in bgkeys:
            for fg in fgkeys:
                self._txt.insert('end', str(fg), (fg, bg))
                self._txt.insert('end', str("b" + fg), ("b" + fg, bg))
            self._txt.insert('end', '\n')

            for fg in fgkeys:
                self._txt.insert('end', str(fg), (fg, "b" + bg))
                self._txt.insert('end', str("b" + fg), ("b" + fg, "b" + bg))
            self._txt.insert('end', '\n')

        self._txt.insert('end', '\n')
        self._txt.insert('end', '\n')
Exemplo n.º 9
0
class TermWindow(Frame):
    EOL = None

    ##
    # constructor method
    def __init__(self, master=None, **cnf):
        apply(Frame.__init__, (self, master), cnf)
        self.__create_widgets__()
        self.rxWaitPattern = ""
        self.localEcho = False
        self.logFile = None
        self.inQueue = Queue.Queue()
        self.outQueue = Queue.Queue()
        self.update_thread_safe()

    def update_thread_safe(self):
        while not self.inQueue.empty():
            element = self.inQueue.get_nowait()
            if element is not None:
                msg, tag = element
                self.__display__(msg, tag)
            self.st_trm.update_idletasks()
        self.st_trm.after(100, self.update_thread_safe)

    ##
    #
    def __create_widgets__(self):
        dfl_font = 'Courier 10'

        # the title frame of the terminal
        self.f_title = Frame(self)
        self.f_title.pack(fill=BOTH)
        self.f_title.configure(FRAMEBORDER)
        self.shVar = StringVar()
        # show/hide button
        self.b_sh = Button(self.f_title,
                           textvariable=self.shVar,
                           font=dfl_font)
        self.b_sh.pack(side=RIGHT)
        self.b_sh['command'] = self.show_hide_cont
        # clear screen button
        self.b_cls = Button(self.f_title,
                            text="CLS",
                            font=dfl_font,
                            underline=0)
        self.b_cls.pack(side=RIGHT)
        self.b_cls['command'] = self.clear_screen
        # echo on/off button
        self.al_echo = Label(self.f_title,
                             text="ECHO",
                             relief=RAISED,
                             font=dfl_font,
                             padx='3m',
                             pady='1m',
                             underline=0)
        self.al_echo.pack(side=RIGHT, padx=1, pady=1, fill=BOTH)
        self.al_echo.bind("<Button-1>", self.__echo_handler__)
        # log on/off button
        self.al_log = Label(self.f_title,
                            text="LOG",
                            relief=RAISED,
                            font=dfl_font,
                            padx='3m',
                            pady='1m',
                            underline=0)
        self.al_log.pack(side=RIGHT, padx=1, pady=1, fill=BOTH)
        self.al_log.bind("<Button-1>", self.__log_handler__)
        # device connect button
        self.al_connect = Label(self.f_title,
                                text="CONNECT",
                                relief=RAISED,
                                font=dfl_font,
                                padx='3m',
                                pady='1m',
                                underline=1)
        self.al_connect.pack(side=RIGHT, padx=1, pady=1, fill=BOTH)
        self.al_connect.bind("<Button-1>", self.__connect_handler__)

        self.mb_macros = Menubutton(self.f_title, text="Macros", relief=RAISED)
        self.mb_macros.pack(side=RIGHT, padx=1, pady=1, fill=BOTH)
        self.mb_macros.menu = Menu(self.mb_macros, tearoff=0)
        self.mb_macros["menu"] = self.mb_macros.menu

        # title of terminal window
        self.tVar = StringVar()
        self.l_title = Label(self.f_title, text="foo", font=dfl_font)
        self.l_title['textvariable'] = self.tVar
        self.l_title.pack(side=LEFT, expand=1, fill=X)
        self.l_title['width'] = 42
        self.update_title("------ XXX ------")
        # frame for scrolled text window
        # (this frame handle needs to be kept fo show_hide_cont())
        self.f_cont = Frame(self)
        # IO data scrolled text window
        self.st_trm = ScrolledText(self.f_cont,
                                   height=10,
                                   state=DISABLED,
                                   wrap=NONE)
        self.st_trm.pack(expand=1, fill=BOTH)
        self.st_trm['font'] = dfl_font
        self.st_trm.tag_config('E', foreground="blue")
        self.st_trm.tag_config('M', foreground="magenta")

        tframe = Frame(self.f_cont)
        tframe.pack(expand=0, fill=X)
        self.cmdVar = StringVar()
        self.ent_trm = Entry(tframe, textvariable=self.cmdVar, font=dfl_font)
        self.ent_trm.pack(side=LEFT, expand=1, fill=X)
        self.ent_trm.bind("<Control-l>", self.__log_handler__)
        self.ent_trm.bind("<Control-e>", self.__echo_handler__)
        self.ent_trm.bind("<Control-o>", self.__connect_handler__)
        self.ent_trm.bind("<Control-c>", self.clear_screen)
        self.ent_trm.bind("<Control-x>", self.show_hide_cont)
        self.ent_trm.bind("<Control-m>", lambda *args: self.do_macro("M"))
        self.ent_trm.bind("<KeyPress>", self.__input_handler__)

        self.gui_elements = [
            self.b_sh, self.b_cls, self.al_echo, self.al_log, self.al_connect,
            self.mb_macros, self.l_title, self.st_trm, self.ent_trm
        ]
        self.show_cont()

    def add_macro(self, id, title, text=None, function=None, params=None):
        if text:
            cmd = lambda *args: self.do_macro(text)
        if function:
            user_func = eval(function)
            if params:
                params = eval(str(params))
            else:
                params = {}
            cmd = lambda *args: user_func(self, DEVICES, **params)
        mb = self.mb_macros.menu.add_command(label=title, command=cmd)

    def _configure_(self, **args):
        for e in self.gui_elements:
            e.configure(args)

    def __input_handler__(self, *args):
        for i in args:
            self.terminal_device_write(i.char)

    def terminal_device_write(self, *args):
        for i in args:
            if self.localEcho:
                self.display(i, "E")
            if len(i):
                if i == "\r" or i == "\n":
                    self.device.write(self.EOL)
                    self.display(self.EOL, "E")
                    self.cmdVar.set("")
                else:
                    self.device.write(i)
        self.st_trm.update_idletasks()

    def __echo_handler__(self, *args):
        if self.localEcho:
            self.localEcho = False
            self.al_echo['relief'] = RAISED
            self.message("Local Echo OFF")
        else:
            self.localEcho = True
            self.al_echo['relief'] = SUNKEN
            self.message("Local Echo ON")

    def __log_handler__(self, *args):
        try:
            do_open = self.logFile.closed
            logname = self.logFile.name
        except:
            do_open = True
            logname = ""
        if do_open:
            if self.device.logname:
                logname = self.device.logname
                self.message("logfile from config file %s " % logname)
            else:
                fd = FileDialog(self)
                logname = fd.go(logname)
            try:
                if self.device.logmode not in "wa":
                    self.device.logmode = "a"
                    _print(3, "force _a_ppend")
                self.logFile = open(logname, self.device.logmode)
                self.al_log['relief'] = SUNKEN
                self.message("Logging ON: %s" % self.logFile.name)
            except:
                self.message("Error open logfile: %s" % logname)

        else:
            self.message("Logging OFF: %s" % self.logFile.name)
            self.logFile.flush()
            self.logFile.close()
            self.al_log['relief'] = RAISED

    def __connect_handler__(self, *args):
        if self.device.isConnected:
            self.device.disconnect()
            self.al_connect['relief'] = RAISED
            self.message("Disconnected")
        else:
            try:
                self.device.connect()
                self.al_connect['relief'] = SUNKEN
                self.message("Connected")
                self.al_connect['fg'] = "black"
            except:
                self.device.isConnected = False
                self.message(str(sys.exc_info()[1]))
                self.al_connect['fg'] = "red"

    def clear_screen(self, *args):
        self.st_trm['state'] = NORMAL
        self.st_trm.delete("0.0", END)
        self.st_trm['state'] = DISABLED

    def set_device(self, device):
        self.device = device
        self.device.configure(TxQueue=self.outQueue, RxQueue=self.inQueue)
        self.update_title(self.device)

        if self.device.log:
            self.__log_handler__()
        if self.device.auto_connect:
            self.__connect_handler__()

    def update_title(self, title):
        self.tVar.set(title)

    def show_cont(self):
        self.shVar.set("X")
        self.f_cont.pack(expand=1, fill=BOTH)

    def hide_cont(self):
        self.shVar.set("+")
        self.f_cont.pack_forget()

    def show_hide_cont(self, *args):
        if self.shVar.get() == "X":
            self.hide_cont()
        else:
            self.show_cont()

    def do_macro(self, *args):
        if self.localEcho:
            self.display(args[0] + "\n", "E")
        self.device.write(args[0] + "\n")

    def write(self, data):
        self.outQueue.put((data, None))

    def message(self, text, tag='M'):
        msg = "[%s:%s:%s]\n" % (time.asctime(), self.device.name, text)
        if self.st_trm.index(AtInsert()).find(".0") < 1:
            msg = "\n" + msg
        self.inQueue.put((msg, tag))

    def display(self, text, tag=None):
        self.inQueue.put((text, tag))

    def __display__(self, msg, tag=None):
        self.st_trm['state'] = NORMAL
        here = self.st_trm.index(AtInsert())
        for d in re.split("([\r\v\t\n])", msg):
            if len(d):
                if d != '\r':
                    self.st_trm.insert(END, d)
        if tag:
            self.st_trm.tag_add(tag, here, AtInsert())
        self.st_trm.see(END)
        self.st_trm['state'] = DISABLED
        try:
            self.logFile.write(msg)
            self.logFile.flush()
        except:
            pass
Exemplo n.º 10
0
    def run(self):

        #        help_window()

        #def help_window():
        from ScrolledText import ScrolledText

        def gotosettings(*args):
            text.see(tk.END)
            text.see(setting_index)

        def gotoinfo(*args):
            text.see(tk.END)
            text.see(info_index)

        def gotoprereq(*args):
            text.see(tk.END)
            text.see(prereq_index)

        def gotolc(*args):
            text.see(tk.END)
            text.see(lc_index)

        def gototop(*args):
            text.see(tk.END)
            text.see(top_index)

        def gotospec(*args):
            text.see(tk.END)
            text.see(spec_index)

        def show_tcross_cursor(*args):
            text.config(cursor="tcross")

        def show_arrow_cursor(*args):
            text.config(cursor="arrow")

        self.help_top = tk.Toplevel()
        self.help_top.title("Help")
        text = ScrolledText(self.help_top, bg='white')
        text.pack(side=tk.TOP, fill=tk.BOTH, expand=tk.Y)
        bold_font = tkFont.Font(text, text.cget("font"))
        bold_font.configure(weight='bold')

        txt0 = """

           Contents

    General Information
    Settings Panel
    Prerequisites Panel
    Lightcurve Panel
    Spectrum Panel










\n"""

        text.insert(tk.END, txt0)
        # Define tags
        text.tag_add('settings', "%s-15l+4c" % tk.INSERT,
                     "%s-15l+18c" % tk.INSERT)
        text.tag_bind('settings', '<Enter>', show_arrow_cursor)
        text.tag_bind('settings', '<Leave>', show_tcross_cursor)
        text.tag_config('settings', foreground='blue', underline=1)
        text.tag_bind('settings', '<Button-1>', gotosettings)

        text.tag_add('info', "%s-16l+4c" % tk.INSERT, "%s-16l+24c" % tk.INSERT)
        text.tag_bind('info', '<Enter>', show_arrow_cursor)
        text.tag_bind('info', '<Leave>', show_tcross_cursor)
        text.tag_config('info', foreground='blue', underline=1)
        text.tag_bind('info', '<Button-1>', gotoinfo)

        text.tag_add('prereq', "%s-14l+4c" % tk.INSERT,
                     "%s-14l+24c" % tk.INSERT)
        text.tag_bind('prereq', '<Enter>', show_arrow_cursor)
        text.tag_bind('prereq', '<Leave>', show_tcross_cursor)
        text.tag_config('prereq', foreground='blue', underline=1)
        text.tag_bind('prereq', '<Button-1>', gotoprereq)

        text.tag_add('lc', "%s-13l+4c" % tk.INSERT, "%s-13l+20c" % tk.INSERT)
        text.tag_bind('lc', '<Enter>', show_arrow_cursor)
        text.tag_bind('lc', '<Leave>', show_tcross_cursor)
        text.tag_config('lc', foreground='blue', underline=1)
        text.tag_bind('lc', '<Button-1>', gotolc)

        text.tag_add('spec', "%s-12l+4c" % tk.INSERT, "%s-12l+18c" % tk.INSERT)
        text.tag_bind('spec', '<Enter>', show_arrow_cursor)
        text.tag_bind('spec', '<Leave>', show_tcross_cursor)
        text.tag_config('spec', foreground='blue', underline=1)
        text.tag_bind('spec', '<Button-1>', gotospec)

        setting_index = '70.0'
        info_index = '20.0'
        prereq_index = '100.0'
        lc_index = '140.0'
        spec_index = '167.0'
        top_index = '0.0'

        text.insert(tk.END, "General information\n")
        text.tag_add('tag', "%s-1l" % tk.INSERT, tk.INSERT)
        text.tag_config('tag', font=bold_font, underline=1, justify=tk.CENTER)
        text.insert(tk.END, "\n")

        txt1 = """

Latspec is designed to analyze FERMI/LAT data. The tool allows to perform  all
stages  of  analysis including event filtering, imaging analysis, spectrum and 
lightcurve generation and spectral modeling using single graphical interface.

The core idea behind the  Latspec data analysis  is  to use ancillary response 
to  account  for  the PSF spillover, allowing to use small extraction radii to
minimize  contamination  from nearby sources. The tool gives  reliable results 
for  well isolated and  relatively bright source. However, standard likelihood 
is recommended in the case of a  faint source in a crouded field. Even in this 
case, Latspec can be helpful to  examine your data and to do "quick-and-dirty"
analysis.

The  program allows  user to process the LAT data, starting from the data set, 
extracted from the LAT data  server,  apply  all  necessary  filters,  specify
regions  and  produce intermediary data  products  necessary  for spectral and
lightcurve analysis. For source and background  region selection  the  program
utilizes DS9 image viewer. The LAT data to be analysed along with some  common
analysis parameters can be set using the  "Settings" panel. Preparation  tasks
(filtered event list, galactic cube and image generation) are performed at the
"Prerequisites" panel.
"""
        text.insert(tk.END, txt1)
        text.tag_add('prereq', "%s-1l+0c" % tk.INSERT, "%s-1l+15c" % tk.INSERT)
        text.tag_add('settings', "%s-3l+42c" % tk.INSERT,
                     "%s-3l+52c" % tk.INSERT)

        txt11 = """
For  spectral  analysis  the  program  extracts count  spectra for   specified
source and background regions, creates necessary response files and optionally
fits spectral model to the data. The  application  also  provides interface to
Xspec spectral fitting package for spectral modeling. Lightcurve is calculated
using Xspec spectral fitting, i.e. spectrum is extracted  and  spectral fit is
performed  for  each  time  interval.  Details  on how to generate and analyze 
spectra and lightcurves tasks are given below  in  "Spectrum" and "Lightcurve"
sections respectively.
    """
        text.insert(tk.END, txt11)
        text.tag_add('lc', "%s-2l+62c" % tk.INSERT, "%s-2l+75c" % tk.INSERT)
        text.tag_add('spec', "%s-2l+47c" % tk.INSERT, "%s-2l+56c" % tk.INSERT)
        txt2 = """

The main  window  of the  program has three frames: top, middle (Log) and  the
bottom  frame.  The  top  frame  is  where analysis is performed by using four
panels: "Settings", "Prerequisites", "Lightcurve" and  "Spectrum". Buttons  at 
the bottom of the top frame are used to  switch between  analysis panels.  The
log  window  displays  various  information about analysis steps taken, errors 
occured, warning, etc. Text lines are color coded for convenience. Namely, the
output of different tasks performed  is  shown  in black, errors in red, hints 
for the next step to take is in blue. The  bottom  row  has four  buttons. The
"Save log" writes the contents of the log window in a  file <basename>.log and
the "Clear Log"  button  clears  the log window. "Help" button shows user this
help and the "Quit" button  quits  Latspec.  Quitting  Latspec  may  take some 
noticable time (few seconds) as the program has to perform some clean up steps: shut  down  all active analysis threads, close any open windows, etc.
    """

        text.insert(tk.END, txt2)

        text.insert(
            tk.END,
            "                                                            Back to top"
        )
        text.tag_add('back', "%s-0l-11c" % tk.INSERT, "%s-0l-0c" % tk.INSERT)
        text.tag_bind('back', '<Enter>', show_arrow_cursor)
        text.tag_bind('back', '<Leave>', show_tcross_cursor)
        text.tag_config('back', foreground='red', underline=1)
        text.tag_bind('back', '<Button-1>', gototop)

        text.insert(tk.END, "\n")
        text.insert(tk.END, "Settings Panel\n")

        text.tag_add('tag', "%s-1l" % tk.INSERT, tk.INSERT)
        text.insert(tk.END, "\n")
        txt3 = """

There  are   four   sections  in  this panel:"Data", "Catalog", "Basename" and
"Parameters". The "Data"  section  has the "..." button which allows to change
the data directory. The "Data info" button prints a short synopsis of the data 
in the Log window. The "Catalog" section allows to specify a 2FGL catalog file
using the "..." button. You  need  to  specify catalog only the first time you
start  the  program. Latspec  stores information  about  the  latest data  and 
catalog in the resource file (~/.latspecrc) and will load  them  automatically
next time you start the program.

The "Flux threshold" entry shows the lower flux limit (given in  the  FLUX1000
column of 2FGL catalog) which used to display the catalog sources in  the  DS9
imaging tool (see "Prerequisites"  panel  section  below).  Namely,  when  you 
increase/decrease the  flux  threshold, less/more  sources appear on the image 
and in the 2FGL source  dropdown  menu list in  the  "Image"  section  of  the
"Prerequisites"  panel.
"""
        text.insert(tk.END, txt3)
        text.tag_add('prereq', "%s-1l+0c" % tk.INSERT, "%s-1l+15c" % tk.INSERT)
        txt31 = """
The "Basename" entry specifes the analysis  "basename". It is used as a prefix
to all intermediary files created during analysis (i.e. <basename>_ltcube.fits
for galactic cube,<basename>_roi.fits for  image,etc). The default basename is
"latspec". For each analysed   source  Latspec  creates  individual  directory 
named <basename>_<sourceid> under the current data directory, where <sourceid>
is  either  source  2FGL  catalog  name, if  2FGL catalog is specified, or sky 
location ID ra<RA>_dec<DEC>_rad<radius>. For example, for 3C 273 the directory 
name will be  set to latspec_2FGLJ1229.1+0202 or latspec_r187.35_dec2.00_r3.00
respectiviely.  All  data  products file names, created in the current session 
will have the same <basename>_<sourceID> structure prefix.

The  "Parameters" subpanel allows to set or modify parameters binsz, dcostheta,
thetamax, zmax and set  the IRFS  used  by FERMI Science Tools (gtltcube,gtpsf,
gtrspgen,gtbin,etc.). 
    """

        text.insert(tk.END, txt31)

        text.insert(
            tk.END,
            "                                                            Back to top"
        )
        text.tag_add('back', "%s-0l-11c" % tk.INSERT, "%s-0l-0c" % tk.INSERT)
        text.tag_bind('back', '<Enter>', show_arrow_cursor)
        text.tag_bind('back', '<Leave>', show_tcross_cursor)
        text.tag_config('back', foreground='red', underline=1)
        text.tag_bind('back', '<Button-1>', gototop)

        text.insert(tk.END, "\n")
        text.insert(tk.END, "\n")
        text.insert(tk.END, "\n")
        text.insert(tk.END, "Prerequisites Panel\n")
        text.tag_add('tag', "%s-1l" % tk.INSERT, tk.INSERT)
        #    text.tag_config('tag',foreground='blue',underline=1,justify=tk.CENTER)
        text.insert(tk.END, "\n")
        text.insert(tk.END, "\n")
        txt4 = """    

This panels has three subpanels:"Events","Ltcube" and "Image" used to  create 
or specify filtered event file, galactic cube and image file. These tasks are
achieved by clicking on the "Filter Events","Run GTLTcube" and "Extract Image"
buttons correspondingly. The Latspec then executes a pipeline of Science Tools
to create a specific data product. When the product is created, its name shows
up  on  the  left side of a subpanel. Clicking on a button before the pipeline 
will terminate it and the product will NOT be created. The output event list,
cube or image files will have names with the <basename>_ prefix.

The  "Ltcube"  subpanel has an additional button "Load Cube" to specify a pre-
existing galactic cube file.

The "Image" and "Regions" subpanels present a set of components to extract the
image of the region and  to  specify  the  source  and background regions. The 
entire region image is extracted by clicking  the "Extract image" button. When
image  is  available  (i.e. the  name  of  the image file is shown next to the 
"Extract image"  button),  the source and background extraction regions can be 
set using any of the following three ways. First, region coordinates and radii
can directly set in the corresponding entries of the  "Regions"  panel. Second,
if catalog is specified, the source region can placed over a catalog source by 
choosing its name in the "2FGL Source" menu. Third,  you  can  launch  DS9 and 
modify regions in DS9. Namely, clicking on "Run DS9" will launch DS9, load the 
image, preset the source and background region selection and  show the catalog
sources in the DS9 window. Modifying the regions in the DS9 image  will update
the numbers in the "Regions" panel. In parallel, catalog source identification
is preformed and, if the center of the current source region is idetified with
a catalog source, its name appears in the  catalog  source  menu. (It is worth
noting that source names that are used here are taken from  ASSOC1  column  of
the catalog or from the SOURCE column if  ASSOC1  is  empty.  Also, the source
identification  is  done  with  ANY  2FGL source, while the dropdown menu list 
shows  only  sources  with  2FGL  flux above  the  flux  threshold, set in the 
"Settings" panel).
    """
        text.insert(tk.END, txt4)
        text.tag_add('settings', "%s-1l-4c" % tk.INSERT,
                     "%s-1l+6c" % tk.INSERT)
        txt41 = """

After you are done with producing event/cube/image files and  selecting your 
extraction regions, you can proceed with spectral analysis in the "Spectrum" 
panel or timing analysis in the "Lightcurve" panel. 
                                """
        text.insert(tk.END, txt41)
        text.tag_add('lc', "%s-1l+0c" % tk.INSERT, "%s-1l+12c" % tk.INSERT)
        text.tag_add('spec', "%s-2l+34c" % tk.INSERT, "%s-2l+44c" % tk.INSERT)

        text.insert(
            tk.END,
            "\n                                                               Back to top"
        )
        text.tag_add('back', "%s-0l-11c" % tk.INSERT, "%s-0l-0c" % tk.INSERT)
        text.tag_bind('back', '<Enter>', show_arrow_cursor)
        text.tag_bind('back', '<Leave>', show_tcross_cursor)
        text.tag_config('back', foreground='red', underline=1)
        text.tag_bind('back', '<Button-1>', gototop)

        text.insert(tk.END, "\n")
        text.insert(tk.END, "\n")
        text.insert(tk.END, "Lightcurve Panel\n")
        text.tag_add('tag', "%s-1l" % tk.INSERT, tk.INSERT)

        txt5 = """

The lightcurve calculation is implemented as follows. Photon flux in each time
bin is calcilated via spectrum  fitting,  accounting  for  PSF  spillover. The
spectrum  is  fit  with  pure  power  law. The photon flux with its errors  is 
calculated  using cflux model (see XSPEC documentaion).

 The "Lightcurve" binning dropdown menue sets the bin size of the lightcurve to
month, week or day (Only these three options for  time interval are available).
The energy  range sets the limits for the photon flux calculation in the XSPEC 
fits. In the "Powerlaw index" entry the user can  specify  the starting  value 
of the index and wheather it should be kept fixed  during spectral fits. These
last two sttings should be modified only in rare cases of a very high 
statistics  (or if you really know what you are doing). 

The "Show lightcurve" button opens up  the QPP plot of the lightcurve. In case
the powerlaw  index  was  free  during  the  lightcurve  extraction, the index
evolution is also plotted. "Save lightcurve" button opens a dialog window 
which allows you to save the lightcurve file in a location different from the
default one (i.e. source directory).

 
    """
        text.insert(tk.END, txt5)
        text.insert(tk.END, "\n")
        text.insert(tk.END, "\n")

        text.insert(
            tk.END,
            "                                                            Back to top\n"
        )
        text.tag_add('back', "%s-0l-12c" % tk.INSERT, "%s-0l-0c" % tk.INSERT)
        text.tag_bind('back', '<Enter>', show_arrow_cursor)
        text.tag_bind('back', '<Leave>', show_tcross_cursor)
        text.tag_config('back', foreground='red', underline=1)
        text.tag_bind('back', '<Button-1>', gototop)

        text.insert(tk.END, "Spectrum Panel\n")
        text.tag_add('tag', "%s-1l" % tk.INSERT, tk.INSERT)
        text.insert(tk.END, "\n")

        txt5 = """
    This panel presents a set of tools to extract and analyse Fermi/LAT energy
spectrum. First,  you need  to extract spectrum and all corresponding response 
files  by  clicking on the "Extract Spectrum" button. You can specify the time
ranges  in  the  "Time Ranges"  window.  The  spectral  files are saved in the 
product directory, shown in the top  line  of the  panel.  After extraction is 
finished  you  have  an option  to  examine the spectrum and background versus 
channels   by   pressing  the   "Plot  spectrum/background" button. When first 
calculated,  spectral  files  are  stored  in a source directory with the file 
names, which can not be changed or modified within  Latspec. To  save spectral
and  response  files in location different from the source directory use "Save 
spectrum" button. "Save spectrum" opens a  save  file  dialog window where you
can  specify  the  location and name of the files for spectral  products to be
saved to. Specifically, when using "Save spectrum" dialog you need to select a
directory where you want your files to be stored and in  the "Save as"  window
you  need  to specify <spectrum_name> string WITHOUT ANY EXTENSIONS. The files
will  then  be  saved   as  <spectrum_name>_src.pha,  <spectrum_name>_bkg.pha,
<spectrum_name>.rsp,etc.

On the  "Xspec"  subpanel the user can perform the full Xspec fit using one of 
three  models:  PowerLaw, LogParabola  and  Power Law with Exponential Cutoff.
The fitting  model can be changed  using  the  dropdown menu. If the source is
identified as a 2FGL catalog source, the model is  preselected  by the catalog
model.  The fit  is performed in the energy range specified by the "Fit Energy 
Range".  Moreover,  one  can  apply any  Xspec  model  or  execute  any  Xspec
command  in  the Xspec prompt, designated by "xspec>".Any Xspec output appears
in the Log window.
    """

        text.insert(tk.END, txt5)

        text.insert(
            tk.END,
            "                                                            Back to top\n"
        )
        text.tag_add('back', "%s-0l-12c" % tk.INSERT, "%s-0l-0c" % tk.INSERT)
        text.tag_bind('back', '<Enter>', show_arrow_cursor)
        text.tag_bind('back', '<Leave>', show_tcross_cursor)
        text.tag_config('back', foreground='red', underline=1)
        text.tag_bind('back', '<Button-1>', gototop)

        text.tag_config('tag', font=bold_font)
        text.tag_config('tag', underline=1)
        text.tag_config('tag', justify=tk.CENTER)

        txt_bot = """
Nikolai Shaposhnikov (UMD/CRESST/GSFC/FSSC)
[email protected]
"""
        text.insert(tk.END, txt_bot)
        text.tag_add('bot', "%s-2l-0c" % tk.INSERT, "%s-0l-0c" % tk.INSERT)
        #        text.tag_config('bot',foreground='green',underline=0)

        button = tk.Button(self.help_top, text="Dismiss", command=self.stop)
        button.pack(side=tk.TOP, fill=tk.BOTH, expand=tk.Y, padx=20)
        text["state"] = tk.DISABLED
Exemplo n.º 11
0
    def confirm_change(self, old_line, new_line, old_tuple=(), new_tuple=(), filepath=""):
        self.confirm_frame = Tkinter.Toplevel(self.parent_frame, padx=10, pady=10)
        # self.confirm_frame.grid(padx=10,pady=10)

        self.confirm_frame.protocol("WM_DELETE_WINDOW", self.confirm_decline)

        # set screen position...
        ##x = config.get('dialog_x', (self.parent_frame.winfo_rootx() + 50))
        ##y = config.get('dialog_y', (self.parent_frame.winfo_rooty() + 50))
        x = self.parent_frame.winfo_rootx() + 50
        y = self.parent_frame.winfo_rooty() + 50
        if x and y:
            self.confirm_frame.geometry("+%s+%s" % (x, y))

        # bind enter to ok and escape to cancel buttons...
        self.confirm_frame.bind("<Return>", self.confirm_accept)
        self.confirm_frame.bind("<Escape>", self.confirm_decline)
        self.confirm_frame.bind("<Configure>", self.save_pos)
        # make the new dialog a part of the parent...
        self.confirm_frame.transient(self.parent_frame)
        # focus onto the dialog...
        self.confirm_frame.focus_set()

        label = Tkinter.Label(self.confirm_frame, text=filepath)
        label.pack()

        label = Tkinter.Label(self.confirm_frame, text="Change:")
        # label.grid(row=row_i, column=0, sticky=W)
        label.pack()

        # entry = Tkinter.Text(self.confirm_frame, width=75, height=5)
        # entry = ScrolledText(self.confirm_frame, width=75, height=5)
        entry = ScrolledText(self.confirm_frame, height=5, wrap=WORD, pady=2, padx=3)
        entry.insert(Tkinter.INSERT, old_line.encode("utf-8"))
        # highlight the text to be changed...
        if len(old_tuple) == 2:
            entry.tag_add("found", "1.%s" % (old_tuple[0]), "1.%s+%sc" % (old_tuple[0], old_tuple[1] - old_tuple[0]))
            entry.tag_config("found", foreground="red")

        entry.config(state=DISABLED)
        entry.pack(fill=BOTH, expand=Y)

        label = Tkinter.Label(self.confirm_frame, text="To:")
        label.pack()

        self.new_entry = ScrolledText(self.confirm_frame, height=5, wrap=WORD, pady=2, padx=3)
        self.new_entry.insert(Tkinter.INSERT, new_line.encode("utf-8"))
        # highlight the text to be changed...
        if len(new_tuple) == 2:
            self.new_entry.tag_add(
                "found", "1.%s" % (new_tuple[0]), "1.%s+%sc" % (new_tuple[0], new_tuple[1] - new_tuple[0])
            )
            self.new_entry.tag_config("found", foreground="red")

        self.new_entry.config(state=DISABLED)
        self.new_entry.pack(fill=BOTH, expand=Y)

        btnDisplay = Tkinter.Button(self.confirm_frame, text="Yes", command=self.confirm_accept, default=ACTIVE)
        # btnDisplay.grid(row=row_i, column=0)
        btnDisplay.pack(side=LEFT, padx=5, pady=5)

        btnDisplay = Tkinter.Button(self.confirm_frame, text="No", command=self.confirm_decline)
        # btnDisplay.grid(row=row_i, column=1)
        btnDisplay.pack(side=LEFT, padx=5, pady=5)

        btnDisplay = Tkinter.Button(self.confirm_frame, text="Cancel", command=self.confirm_cancel)
        # btnDisplay.grid(row=row_i, column=1)
        btnDisplay.pack(side=LEFT, padx=5, pady=5)

        btnDisplay = Tkinter.Button(self.confirm_frame, text="Yes to All", command=self.confirm_silence)
        # btnDisplay.grid(row=row_i, column=1)
        btnDisplay.pack(side=LEFT, padx=5, pady=5)

        self.confirm_frame.update()
        try:
            self.parent_frame.wait_window(self.confirm_frame)
        except Tkinter.TclError:
            # sometimes the wait_window fails, I'm not sure why, but it seems to be
            # safe to just ignore it *shrug*
            pass

        self.confirm_frame = None
Exemplo n.º 12
0
class Dialog(ui.Dialog):
    def __init__(self, frame=None):
        self.parent_frame = frame  # set the parent frame
        self.confirm_frame = None
        self.make_change = False
        self.new_line = u""
        self.status_text = u""
        self.make_silent = False
        self.cancel = False

        # set screen position...
        x = 0
        y = 0
        ##x = config.get('status_x',0)
        ##y = config.get('status_y',0)
        ##if x and y:
        ##    self.parent_frame.geometry("+%d+%d" % (int(x),int(y)))

        # create a status message widget and bind it to the parent...
        # self.status_text = ScrolledText(self.parent_frame, height=20, width=80, state=DISABLED)
        # self.status_text.pack()
        self.status_text = ScrolledText(self.parent_frame, wrap=WORD, pady=2, padx=3, state=DISABLED)
        self.status_text.pack(fill=BOTH, expand=Y)
        self.parent_frame.protocol("WM_DELETE_WINDOW", self.destroy)
        self.parent_frame.bind("<Escape>", self.destroy)
        self.parent_frame.bind("<Configure>", self.save_pos)
        self.status_text.update()

    def confirm_change(self, old_line, new_line, old_tuple=(), new_tuple=(), filepath=""):
        self.confirm_frame = Tkinter.Toplevel(self.parent_frame, padx=10, pady=10)
        # self.confirm_frame.grid(padx=10,pady=10)

        self.confirm_frame.protocol("WM_DELETE_WINDOW", self.confirm_decline)

        # set screen position...
        ##x = config.get('dialog_x', (self.parent_frame.winfo_rootx() + 50))
        ##y = config.get('dialog_y', (self.parent_frame.winfo_rooty() + 50))
        x = self.parent_frame.winfo_rootx() + 50
        y = self.parent_frame.winfo_rooty() + 50
        if x and y:
            self.confirm_frame.geometry("+%s+%s" % (x, y))

        # bind enter to ok and escape to cancel buttons...
        self.confirm_frame.bind("<Return>", self.confirm_accept)
        self.confirm_frame.bind("<Escape>", self.confirm_decline)
        self.confirm_frame.bind("<Configure>", self.save_pos)
        # make the new dialog a part of the parent...
        self.confirm_frame.transient(self.parent_frame)
        # focus onto the dialog...
        self.confirm_frame.focus_set()

        label = Tkinter.Label(self.confirm_frame, text=filepath)
        label.pack()

        label = Tkinter.Label(self.confirm_frame, text="Change:")
        # label.grid(row=row_i, column=0, sticky=W)
        label.pack()

        # entry = Tkinter.Text(self.confirm_frame, width=75, height=5)
        # entry = ScrolledText(self.confirm_frame, width=75, height=5)
        entry = ScrolledText(self.confirm_frame, height=5, wrap=WORD, pady=2, padx=3)
        entry.insert(Tkinter.INSERT, old_line.encode("utf-8"))
        # highlight the text to be changed...
        if len(old_tuple) == 2:
            entry.tag_add("found", "1.%s" % (old_tuple[0]), "1.%s+%sc" % (old_tuple[0], old_tuple[1] - old_tuple[0]))
            entry.tag_config("found", foreground="red")

        entry.config(state=DISABLED)
        entry.pack(fill=BOTH, expand=Y)

        label = Tkinter.Label(self.confirm_frame, text="To:")
        label.pack()

        self.new_entry = ScrolledText(self.confirm_frame, height=5, wrap=WORD, pady=2, padx=3)
        self.new_entry.insert(Tkinter.INSERT, new_line.encode("utf-8"))
        # highlight the text to be changed...
        if len(new_tuple) == 2:
            self.new_entry.tag_add(
                "found", "1.%s" % (new_tuple[0]), "1.%s+%sc" % (new_tuple[0], new_tuple[1] - new_tuple[0])
            )
            self.new_entry.tag_config("found", foreground="red")

        self.new_entry.config(state=DISABLED)
        self.new_entry.pack(fill=BOTH, expand=Y)

        btnDisplay = Tkinter.Button(self.confirm_frame, text="Yes", command=self.confirm_accept, default=ACTIVE)
        # btnDisplay.grid(row=row_i, column=0)
        btnDisplay.pack(side=LEFT, padx=5, pady=5)

        btnDisplay = Tkinter.Button(self.confirm_frame, text="No", command=self.confirm_decline)
        # btnDisplay.grid(row=row_i, column=1)
        btnDisplay.pack(side=LEFT, padx=5, pady=5)

        btnDisplay = Tkinter.Button(self.confirm_frame, text="Cancel", command=self.confirm_cancel)
        # btnDisplay.grid(row=row_i, column=1)
        btnDisplay.pack(side=LEFT, padx=5, pady=5)

        btnDisplay = Tkinter.Button(self.confirm_frame, text="Yes to All", command=self.confirm_silence)
        # btnDisplay.grid(row=row_i, column=1)
        btnDisplay.pack(side=LEFT, padx=5, pady=5)

        self.confirm_frame.update()
        try:
            self.parent_frame.wait_window(self.confirm_frame)
        except Tkinter.TclError:
            # sometimes the wait_window fails, I'm not sure why, but it seems to be
            # safe to just ignore it *shrug*
            pass

        self.confirm_frame = None

    def confirm_silence(self):
        self.make_change = True
        self.make_silent = True
        self.clean_up()

    def confirm_cancel(self):
        self.make_change = False
        self.cancel = True
        self.clean_up()

    def confirm_accept(self):
        # self.new_line = self.new_entry.get(1.0, END)
        self.make_change = True
        self.clean_up()

    def confirm_decline(self):
        self.make_change = False
        self.clean_up()

    def clean_up(self, event=None):
        self.save_pos()
        # print self.screen_pos_x,self.screen_pos_y
        self.parent_frame.focus_set()
        self.confirm_frame.destroy()

    def destroy(self, event=None):
        self.parent_frame.destroy()

    def save_pos(self, event=None):
        return
        ## save the screen position of the dialog box
        # if self.confirm_frame:
        # try:
        # config.add('dialog_x',(self.confirm_frame.winfo_rootx() - 4))
        # config.add('dialog_y',(self.confirm_frame.winfo_rooty() - 30))
        # except:
        # pass

        ## save the status box's position
        # if self.parent_frame:
        # try:
        # config.add('status_x',self.parent_frame.winfo_rootx() - 4)
        # config.add('status_y',self.parent_frame.winfo_rooty() - 30)
        # except:
        # pass

    def update(self, msg):
        # if the window no longer exists, its text can't be updated
        try:
            self.status_text.config(state=NORMAL)
            # Add the new message
            self.status_text.insert(END, msg.encode("utf-8") + os.linesep)
            # Scroll down to the bottom again
            self.status_text.see(END)
            # Make the display uneditable
            self.status_text.config(state=DISABLED)
            self.status_text.update()
        except:
            pass
Exemplo n.º 13
0
class TextDemo(Demo):
   label = 'Text widget displaying source with cheap syntax highlighting:\n'+\
         '(Move mouse over text and watch indent-structure highlighting.)'
   font = ('Courier', 10, 'normal')
   bold = ('Courier', 10, 'bold')
   Highlights = {'#.*': Options(foreground='red'),
              r'\'.*?\'': Options(foreground='yellow'),
              r'\bdef\b\s.*:':Options(foreground='blue', spacing1=2),
              r'\bclass\b\s.*\n':Options(background='pink', spacing1=5),
              r'\b(class|def|for|in|import|from|break|continue)\b':
               Options(font=bold)
              }
   
   def __init__(self, master):
      Demo.__init__(self, master)
      self.text = ScrolledText(self, width=80, height=20,
                         font=self.font, background='gray65',
                         spacing1=1, spacing2=1, tabs='24')
      self.text.pack(side=TOP, expand=YES, fill=BOTH)

      content = open(sys.argv[0], 'r').read()
      self.text.insert(AtEnd(), content)

      reg = re.compile('([\t ]*).*\n')
      pos = 0
      indentTags = []
      while 1:
         match = reg.search(content, pos)
         if not match: break
         indent = match.end(1)-match.start(1)
         if match.end(0)-match.start(0) == 1:
            indent = len(indentTags)
         tagb = 'Tagb%08d' % match.start(0)
         tagc = 'Tage%08d' % match.start(0)
         self.text.tag_configure(tagc, background='', relief=FLAT, borderwidth=2)
         self.text.tag_add(tagb, Char( match.start(0)), Char(match.end(0)))
         self.text.tag_bind(tagb, '<Enter>',
                        lambda e,self=self,tagc=tagc: self.Enter(tagc))
         self.text.tag_bind(tagb, '<Leave>',
                        lambda e,self=self,tagc=tagc: self.Leave(tagc))
         del indentTags[indent:]
         indentTags.extend( (indent-len(indentTags))*[None] )
         indentTags.append(tagc)
         for tag in indentTags:
            if tag:
               self.text.tag_add(tag, Char(match.start(0)),
                             Char(match.end(0)))
         pos = match.end(0)

      for key,kw in self.Highlights.items():
         self.text.tag_configure(key, cnf=kw)
         reg = re.compile(key)
         pos = 0
         while 1:
            match = reg.search(content, pos)
            if not match: break
            self.text.tag_add(key, Char(match.start(0)),Char(match.end(0)))
            pos = match.end(0)

   def Enter(self, tag):
      self.text.tag_raise(tag)
      self.text.tag_configure(tag, background='gray80', relief=RAISED)

   def Leave(self, tag):
      self.text.tag_configure(tag, background='', relief=FLAT)
Exemplo n.º 14
0
class TermWindow(Frame):
    ##
    # constructor method
    def __init__(self, master = None, **cnf):
        apply(Frame.__init__, (self, master), cnf)
        self.__create_widgets__()
        self.rxThread = None
        self.rxWaitEvent = threading.Event()
        self.rxWaitPattern = ""
        self.localEcho = False
        self.logFile = None
        self.textQueue = Queue.Queue()
        self.update_thread_safe()

    def update_thread_safe(self):
        try:
            while 1:
                element = self.textQueue.get_nowait()
                if element is not None:
                    msg,tag = element
                    self.__display__(msg,tag)
                self.st_trm.update_idletasks()
        except Queue.Empty:
            pass
        self.st_trm.after(100, self.update_thread_safe)

    ##
    # worker function for threaded reading from the input of
    # the assigned device
    #
    def __thrd_reader__(self):
        self.waitbuf = ""
        while 1:
            try:
                x = self.device.read()
                if len(x):
                    cmd = self.cmdVar.get()
                    if len(cmd):
                        self.cmdVar.set("")
                    self.write(x)
                    if self.rxWaitEvent.isSet():
                        self.waitbuf += x
                        if self.waitbuf.find(self.rxWaitPattern) > -1:
                            self.rxWaitEvent.clear()
                            while not self.rxWaitEvent.isSet():
                                pass
                            self.rxWaitEvent.clear()
            except:
                traceback.print_exc()
                time.sleep(1)
            else:
                # this infinitesimal sleep keeps the GUI update alive
                time.sleep(.01)

    def waitfor(self, pattern, maxwait=10):
        self.waitbuf = ""
        self.rxWaitPattern = pattern
        self.rxWaitEvent.set()
        self.maxwait = 10
        while self.rxWaitEvent.isSet() and self.maxwait > 0:
            time.sleep(1)
            self.maxwait -= 1
        if self.maxwait == 0:
            self.message("PatternNotFound")
        self.rxWaitEvent.set()

    ##
    #
    def __create_widgets__(self):
        dfl_font = 'Courier 10'

        # the title frame of the terminal
        self.f_title = Frame(self)
        self.f_title.pack(fill=BOTH)
        self.f_title.configure(FRAMEBORDER)
        self.shVar = StringVar()
        # show/hide button
        self.b_sh = Button(self.f_title, textvariable=self.shVar, font=dfl_font)
        self.b_sh.pack(side=RIGHT)
        self.b_sh['command'] = self.show_hide_cont
        # clear screen button
        self.b_cls = Button(self.f_title, text="CLS", font=dfl_font, underline=0)
        self.b_cls.pack(side=RIGHT)
        self.b_cls['command'] = self.clear_screen
        # echo on/off button
        self.al_echo = Label(self.f_title, text = "ECHO", relief = RAISED,
                             font = dfl_font, padx='3m', pady='1m', underline=0)
        self.al_echo.pack(side=RIGHT, padx=1, pady=1, fill=BOTH)
        self.al_echo.bind("<Button-1>", self.__echo_handler__)
        # log on/off button
        self.al_log = Label(self.f_title, text = "LOG", relief = RAISED,
                            font = dfl_font, padx='3m', pady='1m', underline=0)
        self.al_log.pack(side=RIGHT, padx=1, pady=1, fill=BOTH)
        self.al_log.bind("<Button-1>", self.__log_handler__)
        # device connect button
        self.al_connect = Label(self.f_title, text = "CONNECT", relief = RAISED,
                                font = dfl_font, padx='3m', pady='1m', underline=1)
        self.al_connect.pack(side=RIGHT, padx=1, pady=1, fill=BOTH)
        self.al_connect.bind("<Button-1>", self.__connect_handler__)

        self.mb_macros = Menubutton(self.f_title, text = "Macros", relief=RAISED)
        self.mb_macros.pack(side=RIGHT, padx=1, pady=1, fill=BOTH)
        self.mb_macros.menu = Menu(self.mb_macros, tearoff = 0)
        self.mb_macros["menu"] = self.mb_macros.menu


        # title of terminal window
        self.tVar = StringVar()
        self.l_title = Label(self.f_title, text="foo", font=dfl_font)
        self.l_title['textvariable'] = self.tVar
        self.l_title.pack(side=LEFT, expand=1, fill=X)
        self.l_title['width'] = 42
        self.update_title("------ XXX ------")
        # frame for scrolled text window
        # (this frame handle needs to be kept fo show_hide_cont())
        self.f_cont = Frame(self)
        # IO data scrolled text window
        self.st_trm = ScrolledText(self.f_cont, height=10, state=DISABLED, wrap=NONE)
        self.st_trm.pack(expand=1,fill=BOTH)
        self.st_trm['font'] = dfl_font
        self.st_trm.tag_config('E', foreground="blue")
        self.st_trm.tag_config('M', foreground="magenta")


        tframe = Frame(self.f_cont)
        tframe.pack(expand = 0, fill = X)
        self.cmdVar = StringVar()
        self.ent_trm = Entry(tframe, textvariable=self.cmdVar, font=dfl_font)
        self.ent_trm.pack(side=LEFT, expand =1, fill = X)
        self.ent_trm.bind("<Control-l>", self.__log_handler__)
        self.ent_trm.bind("<Control-e>", self.__echo_handler__)
        self.ent_trm.bind("<Control-o>", self.__connect_handler__)
        self.ent_trm.bind("<Control-c>", self.clear_screen)
        self.ent_trm.bind("<Control-x>", self.show_hide_cont)
        self.ent_trm.bind("<Control-m>", lambda *args: self.do_macro("M"))
        self.ent_trm.bind("<KeyPress>", self.__input_handler__)

        self.gui_elements = [ self.b_sh,
                              self.b_cls,
                              self.al_echo,
                              self.al_log,
                              self.al_connect,
                              self.mb_macros,
                              self.l_title,
                              self.st_trm,
                              self.ent_trm]
        self.show_cont()

    def add_macro(self, id, title, text = None, function = None, params = None):
        if text:
            cmd = lambda *args: self.do_macro(text)
        if function:
            user_func = eval(function)
            params = eval(str(params))
            cmd = lambda *args: user_func(DEVICES, **params)
        mb = self.mb_macros.menu.add_command(label = title, command = cmd)

    def _configure_(self,**args):
        for e in self.gui_elements:
            e.configure(args)

    def __input_handler__(self, *args):
        for i in args:
            if self.localEcho:
                self.display(i.char, "E")
            if len(i.char):
                if i.char == "\r":
                    self.device.write("\r\n")
                    self.cmdVar.set("")
                else:
                    self.device.write(i.char)

    def __echo_handler__(self, *args):
        if self.localEcho:
            self.localEcho = False
            self.al_echo['relief'] = RAISED
            self.message("Local Echo OFF")
        else:
            self.localEcho = True
            self.al_echo['relief'] = SUNKEN
            self.message("Local Echo ON")

    def __log_handler__(self, *args):
        try:
            do_open = self.logFile.closed
            logname = self.logFile.name
        except:
            do_open = True
            logname = ""
        if do_open:
            if self.device.logname:
                logname = self.device.logname
                self.message("logfile from config file %s " % logname)
            else:
                fd = FileDialog(self)
                logname = fd.go(logname)
            try:
                if self.device.logmode not in "wa":
                    self.device.logmode = "a"
                    print "force _a_ppend"
                self.logFile = open(logname, self.device.logmode)
                self.al_log['relief'] = SUNKEN
                self.message("Logging ON: %s" % self.logFile.name)
            except:
                self.message("Error open logfile: %s" % logname)

        else:
            self.message("Logging OFF: %s" % self.logFile.name)
            self.logFile.flush()
            self.logFile.close()
            self.al_log['relief'] = RAISED

    def __connect_handler__(self, *args):
        if self.device.isConnected:
            self.device.disconnect()
            self.al_connect['relief'] = RAISED
            self.message("Disconnected")
        else:
            try:
                self.device.connect()
                self.al_connect['relief'] = SUNKEN
                self.message("Connected")
                self.al_connect['fg'] = "black"
            except:
                self.device.isConnected = False
                self.message( str(sys.exc_info()[1]) )
                self.al_connect['fg'] = "red"

    def clear_screen(self, *args):
        self.st_trm['state'] = NORMAL
        self.st_trm.delete("0.0",END)
        self.st_trm['state'] = DISABLED

    def set_device(self,device):
        self.device = device
        self.rxThread = threading.Thread(target = self.__thrd_reader__)
        # if a thread is not a daemon, the program needs to join all
        self.rxThread.setDaemon(1)
        print "**",self.device, self.device.name
        self.rxThread.setName("GUI_RX_%s" % self.device.name)
        self.rxThread.start()
        self.update_title(self.device)
        #
        if self.device.echo:
            self.localEcho = 0
            self.__echo_handler__()
        if self.device.log:
            self.__log_handler__()
        if self.device.auto_connect:
            self.__connect_handler__()

    def update_title(self, title):
        self.tVar.set(title)

    def show_cont(self):
        self.shVar.set("X")
        self.f_cont.pack(expand=1,fill=BOTH)

    def hide_cont(self):
        self.shVar.set("+")
        self.f_cont.pack_forget()

    def show_hide_cont(self, *args):
        if self.shVar.get() == "X":
            self.hide_cont()
        else:
            self.show_cont()

    def do_macro(self, *args):
        if self.localEcho:
            self.display(args[0] + "\n", "E")
        self.device.write(args[0]+ "\n")

    def write(self, data):
        self.textQueue.put((data, None))

    def message(self, text, tag='M'):
        msg = "[%s:%s:%s]\n" % (time.asctime(),self.device.name, text)
        if self.st_trm.index(AtInsert()).find(".0")  < 1:
            msg = "\n" + msg
        self.textQueue.put((msg, tag))

    def display(self, text, tag = None):
        self.textQueue.put((text, tag))

    def __display__(self, msg, tag = None):
        self.st_trm['state'] = NORMAL
        here =  self.st_trm.index(AtInsert())
        for d in re.split("([\r\v\t\n])", msg):
            if len(d):
                if d != '\r':
                    self.st_trm.insert(END, d)
        if tag:
            self.st_trm.tag_add(tag, here, AtInsert())
        self.st_trm.see(END)
        self.st_trm['state'] = DISABLED
        try:
            self.logFile.write(msg)
            self.logFile.flush()
        except:
            pass
Exemplo n.º 15
0
class TextBox:
    def __init__(self):

        self.WIDTH = 600
        self.HEIGHT = 800
        self.FONT = "helvetica"
        self.FONT_SIZE = 12

        # colours specified as RGB fractions
        self.bg_input = [1, 1, 1]
        self.fg_input = [0, 0, 0]

        self.bg_article = [0, 0, 0]
        self.fg_min_article = [0.5, 0.5, 0.5]
        self.fg_max_article = [0.9, 0.9, 0.9]
        self.fg_solution_article = [1, 1, 1]  #[0.3, 0.5, 1.0] #[1, 0.7, 0.4]

        invert = False
        if invert:
            self.bg_input = [1. - v for v in self.bg_input]
            self.fg_input = [1. - v for v in self.fg_input]

            self.bg_article = [1. - v for v in self.bg_article]
            self.fg_min_article = [1. - v for v in self.fg_min_article]
            self.fg_max_article = [1. - v for v in self.fg_max_article]

        self.text = ""  # what is shown in the box
        self.allText = ""  # the text for the entire article
        self.sentences = []  # list of sentences in article
        # dictionary mapping from size to k-hot encoding indicating
        # which sentences are in the summary
        self.solutions = []
        # (not used) how much weight is put on each sentence
        self.weights = []

        self.only_summary = True
        self.summary_size = 1
        self.summary_coherence = 0.0
        self.summary_independence = 0.8

        self.summarizer = Summarizer(parent=self)

        self.root = Tk()

        self.draw(init=True)

        #self.root.mainloop()

    def draw(self, init=False):

        if init:
            # show main article body
            self.tk_article = ScrolledText(self.root)

            # let user paste and enter text
            self.tk_user_input = ScrolledText(self.root)

            self.tk_summary_size_scale = Scale(self.root)
            self.tk_summary_size_scale_label = Label(self.root, text="Length")

            self.tk_summary_coherence_scale = Scale(self.root)
            self.tk_summary_coherence_scale_label = Label(self.root,
                                                          text="Coherence")

            self.tk_summary_independence_scale = Scale(self.root)
            self.tk_summary_independence_scale_label = Label(
                self.root, text="Independence")

            self.tk_toggle_view = Button(self.root,
                                         text="more",
                                         command=self.handleToggleView)
            self.tk_recalculate = Button(self.root,
                                         text="Update",
                                         command=self.handleRecalculate)

            self.root.geometry("%dx%d" % (self.WIDTH, self.HEIGHT))
            self.root.title("QuickReader V4")

            self.tk_article.configure(width=25,
                                      height=6,
                                      bd=0,
                                      highlightthickness=0,
                                      wrap="word",
                                      font=self.FONT)

            self.tk_user_input.configure(width=25,
                                         height=3,
                                         bd=0,
                                         highlightthickness=0,
                                         wrap="word",
                                         font=self.FONT)

            self.tk_summary_size_scale.configure(
                bd=0,
                from_=0,
                to=20,
                orient=HORIZONTAL,
                sliderrelief=FLAT,
                command=lambda event: self.handleSlider(
                    self.tk_summary_size_scale.get()))

            ######
            self.tk_summary_coherence_scale.configure(
                bd=0,
                from_=0,
                to=1,
                orient=HORIZONTAL,
                sliderrelief=FLAT,
                resolution=0.05,
                command=lambda event: self.handleCoherenceSlider(
                    self.tk_summary_coherence_scale.get()))

            self.tk_summary_coherence_scale.set(self.summary_coherence)

            ######
            self.tk_summary_independence_scale.configure(
                bd=0,
                from_=0,
                to=1.5,
                orient=HORIZONTAL,
                sliderrelief=FLAT,
                resolution=0.05,
                command=lambda event: self.handleIndependenceSlider(
                    self.tk_summary_independence_scale.get()))

            self.tk_summary_independence_scale.set(self.summary_independence)

            # set colours
            self.root.configure(background="black")

            self.tk_summary_size_scale.configure(troughcolor="#444444",
                                                 fg="black",
                                                 background="white",
                                                 activebackground="#bbbbbb")

            self.tk_summary_coherence_scale.configure(
                troughcolor="#444444",
                fg="black",
                background="white",
                activebackground="#bbbbbb")

            self.tk_summary_independence_scale.configure(
                troughcolor="#444444",
                fg="black",
                background="white",
                activebackground="#bbbbbb")

            self.tk_article.configure(bg=toHex(self.bg_article),
                                      fg="white",
                                      insertbackground="blue")
            self.tk_article.vbar.configure(bg="white",
                                           width=10,
                                           troughcolor="black")

            self.tk_user_input.configure(bg=toHex(self.bg_input),
                                         fg=toHex(self.fg_input),
                                         insertbackground="blue")
            self.tk_user_input.vbar.configure(bg="white",
                                              width=10,
                                              troughcolor="black")

            self.tk_user_input.focus()
            self.tk_user_input.bind("<KeyRelease-Return>",
                                    (lambda event: self.handleUserInput(
                                        self.tk_user_input.get("0.0", END))))
            self.root.bind("<Configure>", self.resize)

    def setText(self, text, redraw=False):
        self.text = text
        if redraw: self.updateArticleInfo()

    def setSentences(self, sentences, redraw=False):
        self.sentences = sentences
        if redraw: self.updateArticleInfo()

    def setSolutions(self, solutions, redraw=False):
        self.solutions = solutions
        if redraw: self.updateArticleInfo()

    def setWeights(self, weights, redraw=False):
        self.weights = weights
        if redraw: self.updateArticleInfo()

    def handleToggleView(self):

        print("View toggle!")

        self.only_summary = not self.only_summary

        if self.only_summary:
            self.tk_toggle_view.configure(text="more")
        else:
            self.tk_toggle_view.configure(text="less")

        self.updateSummary()

    def handleRecalculate(self):
        print("Update!")

        self.handleUserInput(self.allText)

    def handleSlider(self, value):

        print("Slider:", value)

        self.summary_size = value

        self.updateSummary()

    def handleCoherenceSlider(self, value):

        print("Coherence Slider:", value)

        self.summary_coherence = value

        #self.updateSummary()

    def handleIndependenceSlider(self, value):

        print("Independence Slider:", value)

        self.summary_independence = value

        #self.updateSummary()

    def updateSummary(self):

        l = self.summary_size

        if self.only_summary and l != 0:
            self.setText('\n\n'.join([
                self.sentences[i] for i in range(len(self.sentences))
                if self.solutions[l][i] == 1
            ]))
        else:
            self.setText(self.allText, redraw=False)

        self.updateArticleInfo()

        self.setWeights([0. for _ in self.sentences], redraw=True)

        self.tk_article.yview_moveto(0)  #vbar.set(0, 0) #configure(jump=0)

    def handleUserInput(self, inStr):
        self.tk_user_input.delete("0.0", END)

        if inStr.strip() == "": return

        text = inStr

        text = ''.join([ch for ch in text if ord(ch) < 128])

        self.setText(text, redraw=False)
        self.setSolutions([], redraw=False)
        self.setWeights([], redraw=True)

        text, sentences, solutions = self.summarizer.summarize(
            text,
            coherence_weight=self.summary_coherence,
            independence_weight=self.summary_independence,
            size_weight=1.,
            beam_width=3,
            hard_size_limit=None)

        self.allText = text
        self.sentences = sentences
        self.solutions = solutions

        self.solutions[0] = [1. for _ in sentences]

        # get max length for summary
        max_len = max(solutions.keys())
        set_len = min(max_len, 3)
        self.tk_summary_size_scale.configure(from_=0, to=max_len)
        self.tk_summary_size_scale.set(set_len)
        self.summary_size = set_len

        # text: all the text in one long string
        # sentences: the text split up into a list of sentences
        # solution: dictionary mapping summary size to a one-hot vector over the sentences, indicating
        #   which sentences are included in the summarization

        # the text should be the same, but update it anyways since it needs to contain the
        #  exact same stuff as the sentences

        self.updateSummary()

        #self.updateArticleInfo()

    def resize(self, event=[]):
        LINEH = 20.0

        pixelX = self.root.winfo_width()
        pixelY = self.root.winfo_height()

        bf = 5  # buffer size in pixels

        # update find_icon, wiki_icon, and graph_icon

        # set toggle and recalculate button
        toggleW = 50
        toggleH = 35 * 1
        self.tk_toggle_view.place(x=pixelX - toggleW,
                                  y=0,
                                  width=toggleW,
                                  height=toggleH)

        updateW = 50
        updateH = 35 * 2
        self.tk_recalculate.place(x=pixelX - updateW,
                                  y=toggleH,
                                  width=updateW,
                                  height=updateH)

        buttonH = toggleH + updateH

        labelW = 90

        # set position of size scale
        scaleW = pixelX - updateW - labelW
        scaleH = 35
        self.tk_summary_size_scale.place(x=labelW,
                                         y=0,
                                         width=scaleW,
                                         height=scaleH)

        self.tk_summary_size_scale_label.place(x=0,
                                               y=0,
                                               width=labelW,
                                               height=scaleH)

        # set position of coherence scale
        coherenceW = pixelX - updateW - labelW
        coherenceH = 35
        self.tk_summary_coherence_scale.place(x=labelW,
                                              y=scaleH,
                                              width=scaleW,
                                              height=scaleH)

        self.tk_summary_coherence_scale_label.place(x=0,
                                                    y=scaleH,
                                                    width=labelW,
                                                    height=coherenceH)

        # set position of independence scale
        independenceW = pixelX - updateW - labelW
        independenceH = 35
        self.tk_summary_independence_scale.place(x=labelW,
                                                 y=scaleH + coherenceH,
                                                 width=scaleW,
                                                 height=scaleH)

        self.tk_summary_independence_scale_label.place(x=0,
                                                       y=scaleH + coherenceH,
                                                       width=labelW,
                                                       height=independenceH)

        # update user input
        inputW = pixelX
        inputH = int(3.0 * LINEH)
        self.tk_user_input.place(x=0,
                                 y=pixelY - inputH,
                                 width=inputW,
                                 height=inputH)

        # update article
        articleW = pixelX
        articleH = pixelY - inputH - scaleH - coherenceH - independenceH
        self.tk_article.place(x=0,
                              y=scaleH + coherenceH + independenceH,
                              width=articleW,
                              height=articleH)

    def updateArticleInfo(self):

        self.articleClear()

        self.articleCat(self.text)

        if self.weights != []:
            self.articleColour()

        self.root.update()

    def articleClear(self):
        self.tk_article.delete("1.0", END)
        self.tk_article.update()

        self.root.update()

        return

    def articleCat(self, inStr):

        self.tk_article.insert(END, inStr)

        self.tk_article.yview(END)

    def articleColour(self):
        '''
		solution = self.solutions[self.summary_size]

		allText = self.text #self.tk_article.get('1.0', 'end-1c')

		# make sure weights are normalised
		maxW = max(self.weights)
		minW = min(self.weights)

		weights = self.weights
		if maxW != minW:
			weights = [(v-minW)/(maxW-minW) for v in self.weights]

		for i in range(len(self.sentences)):
			if self.only_summary and solution[i] != 1.: continue

			s = self.sentences[i]
			if len(s.strip()) == 0:

				continue

			tagNameA = ''.join([random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(10)])
			L_Size = 12 # if solution[i] == 1 else 10
			
			L_Colour = blend(self.fg_min_article, self.fg_max_article, weights[i])
			L_Colour = self.fg_solution_article if solution[i] == 1 else L_Colour

			countVar = StringVar(self.root)
			pos = self.tk_article.search(s, "1.0", stopindex="end", count=countVar)

			self.tk_article.tag_add(tagNameA, pos, "{} + {}c".format(pos, countVar.get()))

			bolding = "normal" #"bold" if self.solution[i] == 1 else "normal" #
			font = (self.FONT, L_Size, bolding)
			self.tk_article.tag_config(tagNameA, foreground=toHex(L_Colour), font=font)#self.FONT+' %s'%(L_Size))

		
		self.root.update()
		'''

        solution = self.solutions[self.summary_size]

        allText = self.text  #self.tk_article.get('1.0', 'end-1c')

        #print("=========")
        for i in range(len(self.sentences)):
            if self.only_summary and solution[i] != 1.: continue

            s = self.sentences[i]
            #if len(s.strip()) == 0:
            #	continue

            #print("- ", s)

            tagNameA = ''.join([
                random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(10)
            ])
            L_Size = self.FONT_SIZE  # if solution[i] == 1 else 10

            L_Colour = self.fg_solution_article if solution[
                i] == 1 else self.fg_min_article
            #print("\t", L_Colour)

            countVar = StringVar(self.root)
            pos = self.tk_article.search(s,
                                         "1.0",
                                         stopindex="end",
                                         count=countVar)

            self.tk_article.tag_add(tagNameA, pos,
                                    "{} + {}c".format(pos, countVar.get()))

            bolding = "normal"  #"bold" if self.solution[i] == 1 else "normal" #
            font = (self.FONT, L_Size, bolding)
            self.tk_article.tag_config(tagNameA,
                                       foreground=toHex(L_Colour),
                                       font=font)  #self.FONT+' %s'%(L_Size))

        self.root.update()
Exemplo n.º 16
0
class TextDemo(Demo):
	label = 'Text widget displaying source with cheap syntax highlighting:\n'+\
			'(Move mouse over text and watch indent-structure highlighting.)'
	font = ('Courier', 10, 'normal')
	bold = ('Courier', 10, 'bold')
	Highlights = {'#.*': Options(foreground='red'),
				  r'\'.*?\'': Options(foreground='yellow'),
				  r'\bdef\b\s.*:':Options(foreground='blue', spacing1=2),
				  r'\bclass\b\s.*\n':Options(background='pink', spacing1=5),
				  r'\b(class|def|for|in|import|from|break|continue)\b':
				   Options(font=bold)
				  }
	
	def __init__(self, master):
		Demo.__init__(self, master)
		self.text = ScrolledText(self, width=80, height=20,
								 font=self.font, background='gray65',
								 spacing1=1, spacing2=1, tabs='24')
		self.text.pack(side=TOP, expand=YES, fill=BOTH)

		content = open(sys.argv[0], 'r').read()
		self.text.insert(AtEnd(), content)

		reg = re.compile('([\t ]*).*\n')
		pos = 0
		indentTags = []
		while 1:
			match = reg.search(content, pos)
			if not match: break
			indent = match.end(1)-match.start(1)
			if match.end(0)-match.start(0) == 1:
				indent = len(indentTags)
			tagb = 'Tagb%08d' % match.start(0)
			tagc = 'Tage%08d' % match.start(0)
			self.text.tag_configure(tagc, background='', relief=FLAT, borderwidth=2)
			self.text.tag_add(tagb, Char( match.start(0)), Char(match.end(0)))
			self.text.tag_bind(tagb, '<Enter>',
							   lambda e,self=self,tagc=tagc: self.Enter(tagc))
			self.text.tag_bind(tagb, '<Leave>',
							   lambda e,self=self,tagc=tagc: self.Leave(tagc))
			del indentTags[indent:]
			indentTags.extend( (indent-len(indentTags))*[None] )
			indentTags.append(tagc)
			for tag in indentTags:
				if tag:
					self.text.tag_add(tag, Char(match.start(0)),
									  Char(match.end(0)))
			pos = match.end(0)

		for key,kw in self.Highlights.items():
			self.text.tag_configure(key, cnf=kw)
			reg = re.compile(key)
			pos = 0
			while 1:
				match = reg.search(content, pos)
				if not match: break
				self.text.tag_add(key, Char(match.start(0)),Char(match.end(0)))
				pos = match.end(0)

	def Enter(self, tag):
		self.text.tag_raise(tag)
		self.text.tag_configure(tag, background='gray80', relief=RAISED)

	def Leave(self, tag):
		self.text.tag_configure(tag, background='', relief=FLAT)