ped_dialog.dialog module
Dialog and UI Component module for the ped editor
# Copyright 2009 James P Goodwin ped tiny python editor """ Dialog and UI Component module for the ped editor """ import curses import curses.ascii import sys import os from ped_core import clipboard from ped_core import cmd_names from ped_core import keytab from ped_core import keymap from ped_core import extension_manager # utility functions def distribute( buttons, xstart, width ): """ distribute a bunch of buttons across a given width """ width_per_button = width // len(buttons) x = xstart + (width_per_button//2) for b in buttons: b.x = x - (b.width//2) x += width_per_button def pad(value,size): """ pad a string with spaces to the size provided """ if len(value) < size: value += ' '*(size-len(value)) return value def rect( win, x,y,w,h,label,attr,fill=True ): """ draw a rectangle in the curses window provided at the offset x,y with a w,h width and height, if label is non-empty center it in the top border, if fill is true, fill the rectangle with spaces """ win.addch(y,x,curses.ACS_ULCORNER,attr) off = 1 while off < w-1: win.addch(y,x+off,curses.ACS_HLINE,attr) off += 1 win.addch(y,x+(w-1),curses.ACS_URCORNER,attr) if label: win.addstr(y,x+(w//2)-(len(label)//2),label,attr) y += 1 bh = h-2 while bh: try: win.addch(y,x,curses.ACS_VLINE,attr) except: pass if fill: off = 1 while off < w-1: try: win.addch(y,x+off,' ',attr) except: pass off += 1 try: win.addch(y,x+(w-1),curses.ACS_VLINE,attr) except: pass bh -= 1 y += 1 try: win.addch(y,x,curses.ACS_LLCORNER,attr) except: pass off = 1 while off < w-1: try: win.addch(y,x+off,curses.ACS_HLINE,attr) except: pass off += 1 try: win.addch(y,x+(w-1),curses.ACS_LRCORNER,attr) except: pass class Component: """ base class for UI components defines the standard interface, not useable by itself """ CMP_KEY_CANCEL = keytab.KEYTAB_DLGCANCEL # user has canceled the dialog CMP_KEY_OK = keytab.KEYTAB_DLGOK # user has accepted the dialog CMP_KEY_NOP = keytab.KEYTAB_DLGNOP # the most recent key requires no action def __init__(self, name, order ): """ all components have a name and a tab order, order == -1 means exclude from tab """ self.name = name self.order = order self.parent = None def render(self): """ render the component use parent as target """ pass def focus(self): """ called when component is the focus """ pass def isempty(self): """ test if the component entry is empty """ return False def setvalue(self,value): """ set the components value, may be tuple or other data structure """ pass def getvalue(self): """ return the current value of the component """ return None def handle(self, ch ): """ handle keystrokes for this component """ pass def mouse_event(self, ox, oy, mtype): """ handle mouse events return key value or -1 for not handled """ return -1 def getorder(self): """ get this component's tab order number """ return self.order def getparent(self): """ get this component's curses target window """ return self.parent def setparent(self,parent): """ set the parent curses target window """ self.parent = parent def getname(self): """ get the name of this component """ return self.name def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width class Frame(Component): """ frame component for surrounding dialog with a border """ def __init__(self, title, x = -1 , y = -1, w = -1, h = -1 ): """ takes title for frame not on tab order """ Component.__init__(self,None,-1) self.title = title self.x = x self.y = y self.w = w self.h = h def render(self): """ frame renders itself as a rectangle with title around window """ win = self.getparent() if win: if self.x >= 0: x = self.x y = self.y my = self.h mx = self.w else: x = 0 y = 0 my,mx = win.getmaxyx() rect(win, x, y, mx, my, self.title, curses.A_NORMAL, False) if self.title: win.addstr(y,x+(mx//2)-(len(self.title)//2),self.title) class ListBox(Component): def __init__(self, name, order, x, y, height, width, label, selection = 0, lst = []): Component.__init__(self,name,order) self.x = x self.y = y self.height = height self.width = width self.label = label self.selection = selection self.search = "" self.top = selection if self.top < 0: self.top = 0 self.list = lst self.isfocus = False def render(self): win = self.getparent() if win: if self.isfocus: lattr = curses.A_BOLD else: lattr = curses.A_NORMAL x = self.x y = self.y width = self.width height = self.height rect(win,x,y,width,height,self.label,lattr) x+=1 y+=1 width -=2 height -=2 top = self.top off = 0 cy = -1 while top < len(self.list) and off < height: if top == self.selection: rattr = curses.A_REVERSE cy = y+off else: if self.isfocus: rattr = curses.A_BOLD else: rattr = curses.A_NORMAL win.addstr(y+off,x,pad(self.list[top],width)[0:width],rattr) top += 1 off += 1 if self.isfocus and cy > 0: win.move(cy,x) self.isfocus = False def focus(self): self.isfocus = True def setvalue(self,value): self.selection = value[0] self.list = value[1] if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) def getvalue(self): return (self.selection,self.list) def cpgdn(self): if len(self.list): self.selection += (self.height-2) if self.selection >= len(self.list): self.selection = len(self.list)-1 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) def cpgup(self): if len(self.list): self.selection -= (self.height-2) if self.selection < 0: self.selection = 0 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) def cup(self): if len(self.list): self.selection -= 1 if self.selection < 0: self.selection = 0 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) def cdown(self): if len(self.list): self.selection += 1 if self.selection >= len(self.list): self.selection = len(self.list)-1 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) def home(self): if len(self.list): self.selection = 0 self.top = 0 def end(self): if len(self.list): self.selection = len(self.list)-1 self.top = self.selection-(self.height-3) if self.top < 0: self.top = 0 def find(self, searchfor ): found = False if len(self.list): idx = self.selection while idx < len(self.list): if self.list[idx].startswith(searchfor): self.selection = idx found = True break idx += 1 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) return found def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy >= self.y and oy <= self.y+self.height: oy = (oy - self.y) - 1 if oy >= 0: if mtype & curses.BUTTON1_CLICKED: if self.top+oy < len(self.list): self.selection = self.top+oy return keytab.KEYTAB_CR return -1 def handle(self,ch): if len(ch) == 1 and curses.ascii.isprint(ord(ch[0])): self.search += ch self.find(self.search) elif ch == keytab.KEYTAB_BACKSPACE: if self.search: self.search = self.search[0:-1] self.find(self.search) elif ch == keytab.KEYTAB_F03: if self.search: self.cdown() if not self.find(self.search): self.cup() elif ch == keytab.KEYTAB_LEFT or ch == keytab.KEYTAB_UP: self.cup() elif ch == keytab.KEYTAB_RIGHT or ch == keytab.KEYTAB_DOWN: self.cdown() elif ch == keytab.KEYTAB_HOME: self.home() elif ch == keytab.KEYTAB_END: self.end() elif ch == keytab.KEYTAB_PAGEUP: self.cpgup() elif ch == keytab.KEYTAB_PAGEDOWN: self.cpgdn() elif ch == keytab.KEYTAB_RESIZE: return ch elif ch in [keytab.KEYTAB_SPACE,keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB]: self.search = "" return ch return Component.CMP_KEY_NOP class Toggle(Component): def __init__(self, name, order, x, y, width, selection = 0, lst = []): Component.__init__(self,name,order) self.x = x self.y = y self.width = width self.selection = selection self.list = lst self.isfocus = False def render(self): win = self.getparent() if win: if self.isfocus: lattr = curses.A_REVERSE else: lattr = curses.A_NORMAL x = self.x y = self.y width = self.width win.addstr(y,x,pad(self.list[self.selection],width)[0:width],lattr) if self.isfocus: win.move(y,x) self.isfocus = False def focus(self): self.isfocus = True def setvalue(self,value): self.selection = value[0] self.list = value[1] def getvalue(self): return (self.selection,self.list) def cup(self): if len(self.list): self.selection -= 1 if self.selection < 0: self.selection = len(self.list)-1 def cdown(self): if len(self.list): self.selection += 1 if self.selection >= len(self.list): self.selection = 0 def home(self): if len(self.list): self.selection = 0 def end(self): if len(self.list): self.selection = len(self.list)-1 def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy == self.y: if mtype & curses.BUTTON1_CLICKED: self.cdown() return Component.CMP_KEY_NOP return -1 def handle(self,ch): if ch == keytab.KEYTAB_LEFT or ch == keytab.KEYTAB_UP: self.cup() elif ch == keytab.KEYTAB_SPACE or ch == keytab.KEYTAB_RIGHT or ch == keytab.KEYTAB_DOWN: self.cdown() elif ch == keytab.KEYTAB_HOME: self.home() elif ch == keytab.KEYTAB_END: self.end() elif ch == keytab.KEYTAB_RESIZE: return ch elif ch in [keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB]: return ch return Component.CMP_KEY_NOP class Button(Component): def __init__(self, name, order, x, y, label, key ): Component.__init__(self,name,order) self.x = x self.y = y self.label = label self.width = len(label)+2 self.key = key self.isfocus = False self.value = False def render(self): win = self.getparent() if self.isfocus: battr = curses.A_REVERSE else: battr = curses.A_NORMAL if win: win.addstr(self.y,self.x,"["+self.label+"]",battr) if self.isfocus: win.move(self.y,self.x+(len(self.label)+2)//2) self.isfocus = False def focus(self): self.isfocus = True def setvalue(self,value): if value: self.value = True else: self.value = False def getvalue(self): return self.value def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy == self.y: if mtype & curses.BUTTON1_CLICKED: self.setvalue(True) return self.key return -1 def handle(self,ch): if ch == keytab.KEYTAB_SPACE: self.setvalue(True) return self.key elif ch == keytab.KEYTAB_CR: self.setvalue(True) return self.key elif ch == keytab.KEYTAB_RESIZE: return ch elif ch in [keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB]: return ch return Component.CMP_KEY_NOP class StaticText(Component): def __init__(self, name, x, y, prompt, width, value= "" ): Component.__init__(self,name,-1) self.x = x self.y = y self.prompt = prompt self.width = width self.value = value def setvalue(self,value): self.value = value def getvalue(self): return self.value def render(self): win = self.getparent() if win: try: max_y,max_x = win.getmaxyx() width = (max_x - self.x) - 1 x = self.x win.addstr(self.y,x,self.prompt[-width:],curses.A_NORMAL) x += len(self.prompt[-width:]) width -= len(self.prompt[-width:]) if width > 0: win.addstr(self.y,x,pad(self.value,self.width)[-width:],curses.A_NORMAL) except Exception as e: raise Exception("%d,%d,%d,%s,%s"%(x,self.y,width,self.prompt,str(e))) class Prompt(Component): def __init__(self, name, order, x, y, prompt, width, value= "" ): Component.__init__(self,name,order) self.x = x self.y = y self.prompt = prompt self.width = width self.value = value self.pos = 0 self.left = 0 self.isfocus = False def setvalue( self, value ): self.pos = 0 self.left = 0 Component.setvalue(self,value) def render(self): win = self.getparent() if self.isfocus: pattr = curses.A_BOLD fattr = curses.A_REVERSE else: pattr = curses.A_NORMAL fattr = curses.A_NORMAL if win: if self.width < 0: (max_y,max_x) = win.getmaxyx() self.width = max_x - (self.x+len(self.prompt)+2) win.addstr(self.y,self.x,self.prompt,pattr) if not self.isfocus: self.left = 0 self.pos = 0 win.addstr(self.y,self.x+len(self.prompt),pad(self.value[self.left:self.left+self.width],self.width),fattr) if self.isfocus: win.move(self.y,self.x+len(self.prompt)+(self.pos-self.left)) self.isfocus = False def isempty(self): return (len(self.value.strip()) == 0) def focus(self): self.isfocus = True def setvalue(self,value): self.value = value def getvalue(self): return self.value def cleft(self): self.pos -= 1 if self.pos < 0: self.pos = 0 if self.pos < self.left: self.left = self.pos def cright(self,offset = 1): self.pos += offset if self.pos > self.width-1: self.left = self.pos - (self.width-1) def home(self): self.pos = 0 self.left = 0 def end(self): self.pos = len(self.value) if self.pos > self.width-1: self.left = self.pos - (self.width-1) def delc(self): if self.pos < len(self.value): self.value = self.value[0:self.pos]+self.value[self.pos+1:] def backspace(self): self.cleft() self.delc() def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy == self.y: if mtype & curses.BUTTON1_CLICKED: return Component.CMP_KEY_NOP return -1 def insert(self,ch): if self.pos > len(self.value): self.value = self.value + ' '*(self.pos-len(self.value)) + ch else: self.value = self.value[0:self.pos]+ch+self.value[self.pos:] self.cright(len(ch)) def handle(self,ch): if len(ch) == 1 and curses.ascii.isprint(ord(ch[0])): self.insert(ch[0]) elif ch == keytab.KEYTAB_LEFT: self.cleft() elif ch == keytab.KEYTAB_RIGHT: self.cright() elif ch == keytab.KEYTAB_DELC: self.delc() elif ch == keytab.KEYTAB_BACKSPACE: self.backspace() elif ch == keytab.KEYTAB_HOME: self.home() elif ch == keytab.KEYTAB_END: self.end() elif ch == keytab.KEYTAB_DOWN: self.value = "" self.pos = 0 self.left = 0 elif ch == keytab.KEYTAB_RESIZE: return ch elif ch == keytab.KEYTAB_CTRLV or ch == keytab.KEYTAB_INSERT: if clipboard.clip_type: for clip in clipboard.clip: for ichar in clip: self.insert(ichar) elif ch == keytab.KEYTAB_CTRLC: if self.value: clipboard.clip_type = editor_common.Editor.SPAN_CLIP clipboard.clip = [ self.value ] elif ch in [keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB,keytab.KEYTAB_UP]: return ch return Component.CMP_KEY_NOP class PasswordPrompt(Prompt): def __init__(self, name, order, x, y, prompt, width, value=""): Prompt.__init__(self, name, order, x, y, prompt, width, value) def render(self): win = self.getparent() if self.isfocus: pattr = curses.A_BOLD fattr = curses.A_REVERSE else: pattr = curses.A_NORMAL fattr = curses.A_NORMAL if win: if self.width < 0: (max_y,max_x) = win.getmaxyx() self.width = max_x - (self.x+len(self.prompt)+2) win.addstr(self.y,self.x,self.prompt,pattr) win.addstr(self.y,self.x+len(self.prompt),pad(len(self.value)*"*",self.width),fattr) if self.isfocus: win.move(self.y,self.x+len(self.prompt)+self.pos) self.isfocus = False class Dialog(Component): history = {} def __init__(self, parent, name, height, width, children, y = -1, x = -1 ): Component.__init__(self,name,0) self.height = height self.width = width self.children = children max_y,max_x = parent.getmaxyx() curses.raw() if x < 0: self.win = parent.subwin(height,width,(max_y//2)-(height//2),(max_x//2)-(width//2)) else: self.win = parent.subwin(height,width,y,x) self.win.clear() self.win.keypad(1) curses.meta(1) self.max_y,self.max_x = self.win.getmaxyx() self.setparent(parent) for c in self.children: c.setparent(self.win) self.current = 0 self.focus_list = [] self.hist_idx = 0 self.enable_history = True self.focus() def __del__(self): if hasattr(self,"win") and self.win: del self.win self.win = None def set_history( self, state ): self.enable_history = state def push_history( self, child ): if not self.enable_history: return if not issubclass(child.__class__, Prompt): return if self.getname() and child.getname() and child.getorder() >= 0 and not child.isempty(): key = (self.getname(), child.getname()) if key in Dialog.history: if Dialog.history[key][-1] != child.getvalue(): Dialog.history[key].append(child.getvalue()) else: Dialog.history[key] = [child.getvalue()] def pop_history( self, child ): if not self.enable_history: return if not issubclass(child.__class__, Prompt): return if self.getname() and child.getname() and child.getorder() >= 0: key = (self.getname(), child.getname()) if key in Dialog.history: hist = Dialog.history[key] self.hist_idx += 1 if self.hist_idx > len(hist): self.hist_idx = 0 child.setvalue(hist[-self.hist_idx]) def render(self): self.win.leaveok(1) for c in self.children: if not self.focus_list or self.focus_list[self.current][1] != c: c.render() self.win.leaveok(0) if self.focus_list: self.focus_list[self.current][1].focus() self.focus_list[self.current][1].render() self.win.refresh() def focus(self): self.focus_list = [] for c in self.children: self.pop_history(c) if c.getorder() > 0: self.focus_list.append((c.getorder(),c)) if not self.focus_list: self.current = 0 return self.focus_list.sort(key=lambda x: x[0]) self.current = 0 def setvalue(self, value): for c in self.children: if c.getname() in value: c.setvalue(value[c.getname()]) self.push_history(c) def getvalue(self): value = {} for c in self.children: if c.getname(): value[c.getname()] = c.getvalue() return value def tab(self): if self.focus_list: self.push_history(self.focus_list[self.current][1]) self.current += 1 if self.current >= len(self.focus_list): self.current = 0 def btab(self): if self.focus_list: self.push_history(self.focus_list[self.current][1]) self.current -= 1 if self.current < 0: self.current = len(self.focus_list)-1 def goto(self, component): """ move focus to this component """ for i in range(0,len(self.focus_list)): if self.focus_list[i][1] == component: self.current = i return True return False def handle_mouse(self): if self.focus_list and self.win: try: mid, mx, my, mz, mtype = curses.getmouse() by,bx = self.win.getbegyx() oy = my - by ox = mx - bx for i in range(0,len(self.focus_list)): c = self.focus_list[i][1] ret = c.mouse_event(ox,oy,mtype) if ret >= 0: self.current = i return ret else: return -1 except: return -1 def handle(self, ch): if self.focus_list and ch != keytab.KEYTAB_MOUSE: ch = self.focus_list[self.current][1].handle(ch) cmd_id,ch = keymap.mapseq( keymap.keymap_dialog, ch) if extension_manager.is_extension(cmd_id): if not extension_manager.invoke_extension( cmd_id, self, ch ): return ch if cmd_id == cmd_names.CMD_DLGNEXT: self.tab() elif cmd_id == cmd_names.CMD_DLGPREV: self.btab() elif cmd_id == cmd_names.CMD_DLGUP: if self.focus_list: self.pop_history(self.focus_list[self.current][1]) ch = Component.CMP_KEY_NOP elif cmd_id == cmd_names.CMD_DLGMOUSE: ret = self.handle_mouse() if ret >= 0: ch = ret elif cmd_id == cmd_names.CMD_DLGRESIZE: self.resize() return ch def resize(self): pass def main(self,blocking = True,force=False,ch_in = None): curses.mousemask( curses.BUTTON1_PRESSED| curses.BUTTON1_RELEASED| curses.BUTTON1_CLICKED) self.win.nodelay(1) self.win.notimeout(0) self.win.timeout(0) old_cursor = curses.curs_set(1) while (1): if (not keymap.keypending(self.win)) or force: self.render() if not ch_in: ch = self.handle(keymap.get_keyseq(self.win,keymap.getch(self.win))) else: ch = self.handle(ch_in) if blocking: if ch == Component.CMP_KEY_CANCEL: curses.curs_set(old_cursor) return {} elif ch == Component.CMP_KEY_OK: curses.curs_set(old_cursor) return self.getvalue() else: if ch == Component.CMP_KEY_CANCEL: curses.curs_set(old_cursor) return (ch, {}) else: curses.curs_set(old_cursor) return (ch, self.getvalue()) def main(stdscr): d = Dialog(stdscr,"TestDialog",20,40,[ Frame("Test Dialog"), ListBox("List",1,2,2,7,20,"Select",0,["item 1","another item","third item","four","five","six","seven","eight","nine","ten"]), StaticText("Text",2,10,"Static: ",10,"A string that is longer"), Prompt("TestPrompt",2,2,15,"Enter something: ",10), Button("Ok",3,2,16,"OK",Component.CMP_KEY_OK), Button("Cancel",4,9,16,"CANCEL",Component.CMP_KEY_CANCEL)]) d.main() if __name__ == '__main__': curses.wrapper(main)
Functions
def distribute(
buttons, xstart, width)
distribute a bunch of buttons across a given width
def distribute( buttons, xstart, width ): """ distribute a bunch of buttons across a given width """ width_per_button = width // len(buttons) x = xstart + (width_per_button//2) for b in buttons: b.x = x - (b.width//2) x += width_per_button
def main(
stdscr)
def main(stdscr): d = Dialog(stdscr,"TestDialog",20,40,[ Frame("Test Dialog"), ListBox("List",1,2,2,7,20,"Select",0,["item 1","another item","third item","four","five","six","seven","eight","nine","ten"]), StaticText("Text",2,10,"Static: ",10,"A string that is longer"), Prompt("TestPrompt",2,2,15,"Enter something: ",10), Button("Ok",3,2,16,"OK",Component.CMP_KEY_OK), Button("Cancel",4,9,16,"CANCEL",Component.CMP_KEY_CANCEL)]) d.main()
def pad(
value, size)
pad a string with spaces to the size provided
def pad(value,size): """ pad a string with spaces to the size provided """ if len(value) < size: value += ' '*(size-len(value)) return value
def rect(
win, x, y, w, h, label, attr, fill=True)
draw a rectangle in the curses window provided at the offset x,y with a w,h width and height, if label is non-empty center it in the top border, if fill is true, fill the rectangle with spaces
def rect( win, x,y,w,h,label,attr,fill=True ): """ draw a rectangle in the curses window provided at the offset x,y with a w,h width and height, if label is non-empty center it in the top border, if fill is true, fill the rectangle with spaces """ win.addch(y,x,curses.ACS_ULCORNER,attr) off = 1 while off < w-1: win.addch(y,x+off,curses.ACS_HLINE,attr) off += 1 win.addch(y,x+(w-1),curses.ACS_URCORNER,attr) if label: win.addstr(y,x+(w//2)-(len(label)//2),label,attr) y += 1 bh = h-2 while bh: try: win.addch(y,x,curses.ACS_VLINE,attr) except: pass if fill: off = 1 while off < w-1: try: win.addch(y,x+off,' ',attr) except: pass off += 1 try: win.addch(y,x+(w-1),curses.ACS_VLINE,attr) except: pass bh -= 1 y += 1 try: win.addch(y,x,curses.ACS_LLCORNER,attr) except: pass off = 1 while off < w-1: try: win.addch(y,x+off,curses.ACS_HLINE,attr) except: pass off += 1 try: win.addch(y,x+(w-1),curses.ACS_LRCORNER,attr) except: pass
Classes
class Button
base class for UI components defines the standard interface, not useable by itself
class Button(Component): def __init__(self, name, order, x, y, label, key ): Component.__init__(self,name,order) self.x = x self.y = y self.label = label self.width = len(label)+2 self.key = key self.isfocus = False self.value = False def render(self): win = self.getparent() if self.isfocus: battr = curses.A_REVERSE else: battr = curses.A_NORMAL if win: win.addstr(self.y,self.x,"["+self.label+"]",battr) if self.isfocus: win.move(self.y,self.x+(len(self.label)+2)//2) self.isfocus = False def focus(self): self.isfocus = True def setvalue(self,value): if value: self.value = True else: self.value = False def getvalue(self): return self.value def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy == self.y: if mtype & curses.BUTTON1_CLICKED: self.setvalue(True) return self.key return -1 def handle(self,ch): if ch == keytab.KEYTAB_SPACE: self.setvalue(True) return self.key elif ch == keytab.KEYTAB_CR: self.setvalue(True) return self.key elif ch == keytab.KEYTAB_RESIZE: return ch elif ch in [keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB]: return ch return Component.CMP_KEY_NOP
Ancestors (in MRO)
Class variables
var CMP_KEY_CANCEL
var CMP_KEY_NOP
var CMP_KEY_OK
Static methods
def __init__(
self, name, order, x, y, label, key)
all components have a name and a tab order, order == -1 means exclude from tab
def __init__(self, name, order, x, y, label, key ): Component.__init__(self,name,order) self.x = x self.y = y self.label = label self.width = len(label)+2 self.key = key self.isfocus = False self.value = False
def focus(
self)
called when component is the focus
def focus(self): self.isfocus = True
def getname(
self)
get the name of this component
def getname(self): """ get the name of this component """ return self.name
def getorder(
self)
get this component's tab order number
def getorder(self): """ get this component's tab order number """ return self.order
def getparent(
self)
get this component's curses target window
def getparent(self): """ get this component's curses target window """ return self.parent
def getvalue(
self)
return the current value of the component
def getvalue(self): return self.value
def handle(
self, ch)
handle keystrokes for this component
def handle(self,ch): if ch == keytab.KEYTAB_SPACE: self.setvalue(True) return self.key elif ch == keytab.KEYTAB_CR: self.setvalue(True) return self.key elif ch == keytab.KEYTAB_RESIZE: return ch elif ch in [keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB]: return ch return Component.CMP_KEY_NOP
def isempty(
self)
test if the component entry is empty
def isempty(self): """ test if the component entry is empty """ return False
def mouse_event(
self, ox, oy, mtype)
handle mouse events return key value or -1 for not handled
def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy == self.y: if mtype & curses.BUTTON1_CLICKED: self.setvalue(True) return self.key return -1
def render(
self)
render the component use parent as target
def render(self): win = self.getparent() if self.isfocus: battr = curses.A_REVERSE else: battr = curses.A_NORMAL if win: win.addstr(self.y,self.x,"["+self.label+"]",battr) if self.isfocus: win.move(self.y,self.x+(len(self.label)+2)//2) self.isfocus = False
def setparent(
self, parent)
set the parent curses target window
def setparent(self,parent): """ set the parent curses target window """ self.parent = parent
def setpos(
self, x, y)
set the position of this component
def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y
def setsize(
self, height, width)
set the width of this component
def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width
def setvalue(
self, value)
set the components value, may be tuple or other data structure
def setvalue(self,value): if value: self.value = True else: self.value = False
Instance variables
var isfocus
var key
var label
var value
var width
var x
var y
class Component
base class for UI components defines the standard interface, not useable by itself
class Component: """ base class for UI components defines the standard interface, not useable by itself """ CMP_KEY_CANCEL = keytab.KEYTAB_DLGCANCEL # user has canceled the dialog CMP_KEY_OK = keytab.KEYTAB_DLGOK # user has accepted the dialog CMP_KEY_NOP = keytab.KEYTAB_DLGNOP # the most recent key requires no action def __init__(self, name, order ): """ all components have a name and a tab order, order == -1 means exclude from tab """ self.name = name self.order = order self.parent = None def render(self): """ render the component use parent as target """ pass def focus(self): """ called when component is the focus """ pass def isempty(self): """ test if the component entry is empty """ return False def setvalue(self,value): """ set the components value, may be tuple or other data structure """ pass def getvalue(self): """ return the current value of the component """ return None def handle(self, ch ): """ handle keystrokes for this component """ pass def mouse_event(self, ox, oy, mtype): """ handle mouse events return key value or -1 for not handled """ return -1 def getorder(self): """ get this component's tab order number """ return self.order def getparent(self): """ get this component's curses target window """ return self.parent def setparent(self,parent): """ set the parent curses target window """ self.parent = parent def getname(self): """ get the name of this component """ return self.name def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width
Ancestors (in MRO)
- Component
- builtins.object
Class variables
var CMP_KEY_CANCEL
var CMP_KEY_NOP
var CMP_KEY_OK
Static methods
def __init__(
self, name, order)
all components have a name and a tab order, order == -1 means exclude from tab
def __init__(self, name, order ): """ all components have a name and a tab order, order == -1 means exclude from tab """ self.name = name self.order = order self.parent = None
def focus(
self)
called when component is the focus
def focus(self): """ called when component is the focus """ pass
def getname(
self)
get the name of this component
def getname(self): """ get the name of this component """ return self.name
def getorder(
self)
get this component's tab order number
def getorder(self): """ get this component's tab order number """ return self.order
def getparent(
self)
get this component's curses target window
def getparent(self): """ get this component's curses target window """ return self.parent
def getvalue(
self)
return the current value of the component
def getvalue(self): """ return the current value of the component """ return None
def handle(
self, ch)
handle keystrokes for this component
def handle(self, ch ): """ handle keystrokes for this component """ pass
def isempty(
self)
test if the component entry is empty
def isempty(self): """ test if the component entry is empty """ return False
def mouse_event(
self, ox, oy, mtype)
handle mouse events return key value or -1 for not handled
def mouse_event(self, ox, oy, mtype): """ handle mouse events return key value or -1 for not handled """ return -1
def render(
self)
render the component use parent as target
def render(self): """ render the component use parent as target """ pass
def setparent(
self, parent)
set the parent curses target window
def setparent(self,parent): """ set the parent curses target window """ self.parent = parent
def setpos(
self, x, y)
set the position of this component
def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y
def setsize(
self, height, width)
set the width of this component
def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width
def setvalue(
self, value)
set the components value, may be tuple or other data structure
def setvalue(self,value): """ set the components value, may be tuple or other data structure """ pass
Instance variables
var name
var order
var parent
class Dialog
base class for UI components defines the standard interface, not useable by itself
class Dialog(Component): history = {} def __init__(self, parent, name, height, width, children, y = -1, x = -1 ): Component.__init__(self,name,0) self.height = height self.width = width self.children = children max_y,max_x = parent.getmaxyx() curses.raw() if x < 0: self.win = parent.subwin(height,width,(max_y//2)-(height//2),(max_x//2)-(width//2)) else: self.win = parent.subwin(height,width,y,x) self.win.clear() self.win.keypad(1) curses.meta(1) self.max_y,self.max_x = self.win.getmaxyx() self.setparent(parent) for c in self.children: c.setparent(self.win) self.current = 0 self.focus_list = [] self.hist_idx = 0 self.enable_history = True self.focus() def __del__(self): if hasattr(self,"win") and self.win: del self.win self.win = None def set_history( self, state ): self.enable_history = state def push_history( self, child ): if not self.enable_history: return if not issubclass(child.__class__, Prompt): return if self.getname() and child.getname() and child.getorder() >= 0 and not child.isempty(): key = (self.getname(), child.getname()) if key in Dialog.history: if Dialog.history[key][-1] != child.getvalue(): Dialog.history[key].append(child.getvalue()) else: Dialog.history[key] = [child.getvalue()] def pop_history( self, child ): if not self.enable_history: return if not issubclass(child.__class__, Prompt): return if self.getname() and child.getname() and child.getorder() >= 0: key = (self.getname(), child.getname()) if key in Dialog.history: hist = Dialog.history[key] self.hist_idx += 1 if self.hist_idx > len(hist): self.hist_idx = 0 child.setvalue(hist[-self.hist_idx]) def render(self): self.win.leaveok(1) for c in self.children: if not self.focus_list or self.focus_list[self.current][1] != c: c.render() self.win.leaveok(0) if self.focus_list: self.focus_list[self.current][1].focus() self.focus_list[self.current][1].render() self.win.refresh() def focus(self): self.focus_list = [] for c in self.children: self.pop_history(c) if c.getorder() > 0: self.focus_list.append((c.getorder(),c)) if not self.focus_list: self.current = 0 return self.focus_list.sort(key=lambda x: x[0]) self.current = 0 def setvalue(self, value): for c in self.children: if c.getname() in value: c.setvalue(value[c.getname()]) self.push_history(c) def getvalue(self): value = {} for c in self.children: if c.getname(): value[c.getname()] = c.getvalue() return value def tab(self): if self.focus_list: self.push_history(self.focus_list[self.current][1]) self.current += 1 if self.current >= len(self.focus_list): self.current = 0 def btab(self): if self.focus_list: self.push_history(self.focus_list[self.current][1]) self.current -= 1 if self.current < 0: self.current = len(self.focus_list)-1 def goto(self, component): """ move focus to this component """ for i in range(0,len(self.focus_list)): if self.focus_list[i][1] == component: self.current = i return True return False def handle_mouse(self): if self.focus_list and self.win: try: mid, mx, my, mz, mtype = curses.getmouse() by,bx = self.win.getbegyx() oy = my - by ox = mx - bx for i in range(0,len(self.focus_list)): c = self.focus_list[i][1] ret = c.mouse_event(ox,oy,mtype) if ret >= 0: self.current = i return ret else: return -1 except: return -1 def handle(self, ch): if self.focus_list and ch != keytab.KEYTAB_MOUSE: ch = self.focus_list[self.current][1].handle(ch) cmd_id,ch = keymap.mapseq( keymap.keymap_dialog, ch) if extension_manager.is_extension(cmd_id): if not extension_manager.invoke_extension( cmd_id, self, ch ): return ch if cmd_id == cmd_names.CMD_DLGNEXT: self.tab() elif cmd_id == cmd_names.CMD_DLGPREV: self.btab() elif cmd_id == cmd_names.CMD_DLGUP: if self.focus_list: self.pop_history(self.focus_list[self.current][1]) ch = Component.CMP_KEY_NOP elif cmd_id == cmd_names.CMD_DLGMOUSE: ret = self.handle_mouse() if ret >= 0: ch = ret elif cmd_id == cmd_names.CMD_DLGRESIZE: self.resize() return ch def resize(self): pass def main(self,blocking = True,force=False,ch_in = None): curses.mousemask( curses.BUTTON1_PRESSED| curses.BUTTON1_RELEASED| curses.BUTTON1_CLICKED) self.win.nodelay(1) self.win.notimeout(0) self.win.timeout(0) old_cursor = curses.curs_set(1) while (1): if (not keymap.keypending(self.win)) or force: self.render() if not ch_in: ch = self.handle(keymap.get_keyseq(self.win,keymap.getch(self.win))) else: ch = self.handle(ch_in) if blocking: if ch == Component.CMP_KEY_CANCEL: curses.curs_set(old_cursor) return {} elif ch == Component.CMP_KEY_OK: curses.curs_set(old_cursor) return self.getvalue() else: if ch == Component.CMP_KEY_CANCEL: curses.curs_set(old_cursor) return (ch, {}) else: curses.curs_set(old_cursor) return (ch, self.getvalue())
Ancestors (in MRO)
Class variables
var CMP_KEY_CANCEL
var CMP_KEY_NOP
var CMP_KEY_OK
var history
Static methods
def __init__(
self, parent, name, height, width, children, y=-1, x=-1)
all components have a name and a tab order, order == -1 means exclude from tab
def __init__(self, parent, name, height, width, children, y = -1, x = -1 ): Component.__init__(self,name,0) self.height = height self.width = width self.children = children max_y,max_x = parent.getmaxyx() curses.raw() if x < 0: self.win = parent.subwin(height,width,(max_y//2)-(height//2),(max_x//2)-(width//2)) else: self.win = parent.subwin(height,width,y,x) self.win.clear() self.win.keypad(1) curses.meta(1) self.max_y,self.max_x = self.win.getmaxyx() self.setparent(parent) for c in self.children: c.setparent(self.win) self.current = 0 self.focus_list = [] self.hist_idx = 0 self.enable_history = True self.focus()
def btab(
self)
def btab(self): if self.focus_list: self.push_history(self.focus_list[self.current][1]) self.current -= 1 if self.current < 0: self.current = len(self.focus_list)-1
def focus(
self)
called when component is the focus
def focus(self): self.focus_list = [] for c in self.children: self.pop_history(c) if c.getorder() > 0: self.focus_list.append((c.getorder(),c)) if not self.focus_list: self.current = 0 return self.focus_list.sort(key=lambda x: x[0]) self.current = 0
def getname(
self)
get the name of this component
def getname(self): """ get the name of this component """ return self.name
def getorder(
self)
get this component's tab order number
def getorder(self): """ get this component's tab order number """ return self.order
def getparent(
self)
get this component's curses target window
def getparent(self): """ get this component's curses target window """ return self.parent
def getvalue(
self)
return the current value of the component
def getvalue(self): value = {} for c in self.children: if c.getname(): value[c.getname()] = c.getvalue() return value
def goto(
self, component)
move focus to this component
def goto(self, component): """ move focus to this component """ for i in range(0,len(self.focus_list)): if self.focus_list[i][1] == component: self.current = i return True return False
def handle(
self, ch)
handle keystrokes for this component
def handle(self, ch): if self.focus_list and ch != keytab.KEYTAB_MOUSE: ch = self.focus_list[self.current][1].handle(ch) cmd_id,ch = keymap.mapseq( keymap.keymap_dialog, ch) if extension_manager.is_extension(cmd_id): if not extension_manager.invoke_extension( cmd_id, self, ch ): return ch if cmd_id == cmd_names.CMD_DLGNEXT: self.tab() elif cmd_id == cmd_names.CMD_DLGPREV: self.btab() elif cmd_id == cmd_names.CMD_DLGUP: if self.focus_list: self.pop_history(self.focus_list[self.current][1]) ch = Component.CMP_KEY_NOP elif cmd_id == cmd_names.CMD_DLGMOUSE: ret = self.handle_mouse() if ret >= 0: ch = ret elif cmd_id == cmd_names.CMD_DLGRESIZE: self.resize() return ch
def handle_mouse(
self)
def handle_mouse(self): if self.focus_list and self.win: try: mid, mx, my, mz, mtype = curses.getmouse() by,bx = self.win.getbegyx() oy = my - by ox = mx - bx for i in range(0,len(self.focus_list)): c = self.focus_list[i][1] ret = c.mouse_event(ox,oy,mtype) if ret >= 0: self.current = i return ret else: return -1 except: return -1
def isempty(
self)
test if the component entry is empty
def isempty(self): """ test if the component entry is empty """ return False
def main(
self, blocking=True, force=False, ch_in=None)
def main(self,blocking = True,force=False,ch_in = None): curses.mousemask( curses.BUTTON1_PRESSED| curses.BUTTON1_RELEASED| curses.BUTTON1_CLICKED) self.win.nodelay(1) self.win.notimeout(0) self.win.timeout(0) old_cursor = curses.curs_set(1) while (1): if (not keymap.keypending(self.win)) or force: self.render() if not ch_in: ch = self.handle(keymap.get_keyseq(self.win,keymap.getch(self.win))) else: ch = self.handle(ch_in) if blocking: if ch == Component.CMP_KEY_CANCEL: curses.curs_set(old_cursor) return {} elif ch == Component.CMP_KEY_OK: curses.curs_set(old_cursor) return self.getvalue() else: if ch == Component.CMP_KEY_CANCEL: curses.curs_set(old_cursor) return (ch, {}) else: curses.curs_set(old_cursor) return (ch, self.getvalue())
def mouse_event(
self, ox, oy, mtype)
handle mouse events return key value or -1 for not handled
def mouse_event(self, ox, oy, mtype): """ handle mouse events return key value or -1 for not handled """ return -1
def pop_history(
self, child)
def pop_history( self, child ): if not self.enable_history: return if not issubclass(child.__class__, Prompt): return if self.getname() and child.getname() and child.getorder() >= 0: key = (self.getname(), child.getname()) if key in Dialog.history: hist = Dialog.history[key] self.hist_idx += 1 if self.hist_idx > len(hist): self.hist_idx = 0 child.setvalue(hist[-self.hist_idx])
def push_history(
self, child)
def push_history( self, child ): if not self.enable_history: return if not issubclass(child.__class__, Prompt): return if self.getname() and child.getname() and child.getorder() >= 0 and not child.isempty(): key = (self.getname(), child.getname()) if key in Dialog.history: if Dialog.history[key][-1] != child.getvalue(): Dialog.history[key].append(child.getvalue()) else: Dialog.history[key] = [child.getvalue()]
def render(
self)
render the component use parent as target
def render(self): self.win.leaveok(1) for c in self.children: if not self.focus_list or self.focus_list[self.current][1] != c: c.render() self.win.leaveok(0) if self.focus_list: self.focus_list[self.current][1].focus() self.focus_list[self.current][1].render() self.win.refresh()
def resize(
self)
def resize(self): pass
def set_history(
self, state)
def set_history( self, state ): self.enable_history = state
def setparent(
self, parent)
set the parent curses target window
def setparent(self,parent): """ set the parent curses target window """ self.parent = parent
def setpos(
self, x, y)
set the position of this component
def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y
def setsize(
self, height, width)
set the width of this component
def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width
def setvalue(
self, value)
set the components value, may be tuple or other data structure
def setvalue(self, value): for c in self.children: if c.getname() in value: c.setvalue(value[c.getname()]) self.push_history(c)
def tab(
self)
def tab(self): if self.focus_list: self.push_history(self.focus_list[self.current][1]) self.current += 1 if self.current >= len(self.focus_list): self.current = 0
Instance variables
var children
var current
var enable_history
var focus_list
var height
var hist_idx
var width
class Frame
frame component for surrounding dialog with a border
class Frame(Component): """ frame component for surrounding dialog with a border """ def __init__(self, title, x = -1 , y = -1, w = -1, h = -1 ): """ takes title for frame not on tab order """ Component.__init__(self,None,-1) self.title = title self.x = x self.y = y self.w = w self.h = h def render(self): """ frame renders itself as a rectangle with title around window """ win = self.getparent() if win: if self.x >= 0: x = self.x y = self.y my = self.h mx = self.w else: x = 0 y = 0 my,mx = win.getmaxyx() rect(win, x, y, mx, my, self.title, curses.A_NORMAL, False) if self.title: win.addstr(y,x+(mx//2)-(len(self.title)//2),self.title)
Ancestors (in MRO)
Class variables
var CMP_KEY_CANCEL
var CMP_KEY_NOP
var CMP_KEY_OK
Static methods
def __init__(
self, title, x=-1, y=-1, w=-1, h=-1)
takes title for frame not on tab order
def __init__(self, title, x = -1 , y = -1, w = -1, h = -1 ): """ takes title for frame not on tab order """ Component.__init__(self,None,-1) self.title = title self.x = x self.y = y self.w = w self.h = h
def focus(
self)
called when component is the focus
def focus(self): """ called when component is the focus """ pass
def getname(
self)
get the name of this component
def getname(self): """ get the name of this component """ return self.name
def getorder(
self)
get this component's tab order number
def getorder(self): """ get this component's tab order number """ return self.order
def getparent(
self)
get this component's curses target window
def getparent(self): """ get this component's curses target window """ return self.parent
def getvalue(
self)
return the current value of the component
def getvalue(self): """ return the current value of the component """ return None
def handle(
self, ch)
handle keystrokes for this component
def handle(self, ch ): """ handle keystrokes for this component """ pass
def isempty(
self)
test if the component entry is empty
def isempty(self): """ test if the component entry is empty """ return False
def mouse_event(
self, ox, oy, mtype)
handle mouse events return key value or -1 for not handled
def mouse_event(self, ox, oy, mtype): """ handle mouse events return key value or -1 for not handled """ return -1
def render(
self)
frame renders itself as a rectangle with title around window
def render(self): """ frame renders itself as a rectangle with title around window """ win = self.getparent() if win: if self.x >= 0: x = self.x y = self.y my = self.h mx = self.w else: x = 0 y = 0 my,mx = win.getmaxyx() rect(win, x, y, mx, my, self.title, curses.A_NORMAL, False) if self.title: win.addstr(y,x+(mx//2)-(len(self.title)//2),self.title)
def setparent(
self, parent)
set the parent curses target window
def setparent(self,parent): """ set the parent curses target window """ self.parent = parent
def setpos(
self, x, y)
set the position of this component
def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y
def setsize(
self, height, width)
set the width of this component
def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width
def setvalue(
self, value)
set the components value, may be tuple or other data structure
def setvalue(self,value): """ set the components value, may be tuple or other data structure """ pass
Instance variables
var h
var title
var w
var x
var y
class ListBox
base class for UI components defines the standard interface, not useable by itself
class ListBox(Component): def __init__(self, name, order, x, y, height, width, label, selection = 0, lst = []): Component.__init__(self,name,order) self.x = x self.y = y self.height = height self.width = width self.label = label self.selection = selection self.search = "" self.top = selection if self.top < 0: self.top = 0 self.list = lst self.isfocus = False def render(self): win = self.getparent() if win: if self.isfocus: lattr = curses.A_BOLD else: lattr = curses.A_NORMAL x = self.x y = self.y width = self.width height = self.height rect(win,x,y,width,height,self.label,lattr) x+=1 y+=1 width -=2 height -=2 top = self.top off = 0 cy = -1 while top < len(self.list) and off < height: if top == self.selection: rattr = curses.A_REVERSE cy = y+off else: if self.isfocus: rattr = curses.A_BOLD else: rattr = curses.A_NORMAL win.addstr(y+off,x,pad(self.list[top],width)[0:width],rattr) top += 1 off += 1 if self.isfocus and cy > 0: win.move(cy,x) self.isfocus = False def focus(self): self.isfocus = True def setvalue(self,value): self.selection = value[0] self.list = value[1] if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) def getvalue(self): return (self.selection,self.list) def cpgdn(self): if len(self.list): self.selection += (self.height-2) if self.selection >= len(self.list): self.selection = len(self.list)-1 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) def cpgup(self): if len(self.list): self.selection -= (self.height-2) if self.selection < 0: self.selection = 0 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) def cup(self): if len(self.list): self.selection -= 1 if self.selection < 0: self.selection = 0 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) def cdown(self): if len(self.list): self.selection += 1 if self.selection >= len(self.list): self.selection = len(self.list)-1 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) def home(self): if len(self.list): self.selection = 0 self.top = 0 def end(self): if len(self.list): self.selection = len(self.list)-1 self.top = self.selection-(self.height-3) if self.top < 0: self.top = 0 def find(self, searchfor ): found = False if len(self.list): idx = self.selection while idx < len(self.list): if self.list[idx].startswith(searchfor): self.selection = idx found = True break idx += 1 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) return found def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy >= self.y and oy <= self.y+self.height: oy = (oy - self.y) - 1 if oy >= 0: if mtype & curses.BUTTON1_CLICKED: if self.top+oy < len(self.list): self.selection = self.top+oy return keytab.KEYTAB_CR return -1 def handle(self,ch): if len(ch) == 1 and curses.ascii.isprint(ord(ch[0])): self.search += ch self.find(self.search) elif ch == keytab.KEYTAB_BACKSPACE: if self.search: self.search = self.search[0:-1] self.find(self.search) elif ch == keytab.KEYTAB_F03: if self.search: self.cdown() if not self.find(self.search): self.cup() elif ch == keytab.KEYTAB_LEFT or ch == keytab.KEYTAB_UP: self.cup() elif ch == keytab.KEYTAB_RIGHT or ch == keytab.KEYTAB_DOWN: self.cdown() elif ch == keytab.KEYTAB_HOME: self.home() elif ch == keytab.KEYTAB_END: self.end() elif ch == keytab.KEYTAB_PAGEUP: self.cpgup() elif ch == keytab.KEYTAB_PAGEDOWN: self.cpgdn() elif ch == keytab.KEYTAB_RESIZE: return ch elif ch in [keytab.KEYTAB_SPACE,keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB]: self.search = "" return ch return Component.CMP_KEY_NOP
Ancestors (in MRO)
Class variables
var CMP_KEY_CANCEL
var CMP_KEY_NOP
var CMP_KEY_OK
Static methods
def __init__(
self, name, order, x, y, height, width, label, selection=0, lst=[])
all components have a name and a tab order, order == -1 means exclude from tab
def __init__(self, name, order, x, y, height, width, label, selection = 0, lst = []): Component.__init__(self,name,order) self.x = x self.y = y self.height = height self.width = width self.label = label self.selection = selection self.search = "" self.top = selection if self.top < 0: self.top = 0 self.list = lst self.isfocus = False
def cdown(
self)
def cdown(self): if len(self.list): self.selection += 1 if self.selection >= len(self.list): self.selection = len(self.list)-1 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3)
def cpgdn(
self)
def cpgdn(self): if len(self.list): self.selection += (self.height-2) if self.selection >= len(self.list): self.selection = len(self.list)-1 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3)
def cpgup(
self)
def cpgup(self): if len(self.list): self.selection -= (self.height-2) if self.selection < 0: self.selection = 0 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3)
def cup(
self)
def cup(self): if len(self.list): self.selection -= 1 if self.selection < 0: self.selection = 0 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3)
def end(
self)
def end(self): if len(self.list): self.selection = len(self.list)-1 self.top = self.selection-(self.height-3) if self.top < 0: self.top = 0
def find(
self, searchfor)
def find(self, searchfor ): found = False if len(self.list): idx = self.selection while idx < len(self.list): if self.list[idx].startswith(searchfor): self.selection = idx found = True break idx += 1 if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3) return found
def focus(
self)
called when component is the focus
def focus(self): self.isfocus = True
def getname(
self)
get the name of this component
def getname(self): """ get the name of this component """ return self.name
def getorder(
self)
get this component's tab order number
def getorder(self): """ get this component's tab order number """ return self.order
def getparent(
self)
get this component's curses target window
def getparent(self): """ get this component's curses target window """ return self.parent
def getvalue(
self)
return the current value of the component
def getvalue(self): return (self.selection,self.list)
def handle(
self, ch)
handle keystrokes for this component
def handle(self,ch): if len(ch) == 1 and curses.ascii.isprint(ord(ch[0])): self.search += ch self.find(self.search) elif ch == keytab.KEYTAB_BACKSPACE: if self.search: self.search = self.search[0:-1] self.find(self.search) elif ch == keytab.KEYTAB_F03: if self.search: self.cdown() if not self.find(self.search): self.cup() elif ch == keytab.KEYTAB_LEFT or ch == keytab.KEYTAB_UP: self.cup() elif ch == keytab.KEYTAB_RIGHT or ch == keytab.KEYTAB_DOWN: self.cdown() elif ch == keytab.KEYTAB_HOME: self.home() elif ch == keytab.KEYTAB_END: self.end() elif ch == keytab.KEYTAB_PAGEUP: self.cpgup() elif ch == keytab.KEYTAB_PAGEDOWN: self.cpgdn() elif ch == keytab.KEYTAB_RESIZE: return ch elif ch in [keytab.KEYTAB_SPACE,keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB]: self.search = "" return ch return Component.CMP_KEY_NOP
def home(
self)
def home(self): if len(self.list): self.selection = 0 self.top = 0
def isempty(
self)
test if the component entry is empty
def isempty(self): """ test if the component entry is empty """ return False
def mouse_event(
self, ox, oy, mtype)
handle mouse events return key value or -1 for not handled
def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy >= self.y and oy <= self.y+self.height: oy = (oy - self.y) - 1 if oy >= 0: if mtype & curses.BUTTON1_CLICKED: if self.top+oy < len(self.list): self.selection = self.top+oy return keytab.KEYTAB_CR return -1
def render(
self)
render the component use parent as target
def render(self): win = self.getparent() if win: if self.isfocus: lattr = curses.A_BOLD else: lattr = curses.A_NORMAL x = self.x y = self.y width = self.width height = self.height rect(win,x,y,width,height,self.label,lattr) x+=1 y+=1 width -=2 height -=2 top = self.top off = 0 cy = -1 while top < len(self.list) and off < height: if top == self.selection: rattr = curses.A_REVERSE cy = y+off else: if self.isfocus: rattr = curses.A_BOLD else: rattr = curses.A_NORMAL win.addstr(y+off,x,pad(self.list[top],width)[0:width],rattr) top += 1 off += 1 if self.isfocus and cy > 0: win.move(cy,x) self.isfocus = False
def setparent(
self, parent)
set the parent curses target window
def setparent(self,parent): """ set the parent curses target window """ self.parent = parent
def setpos(
self, x, y)
set the position of this component
def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y
def setsize(
self, height, width)
set the width of this component
def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width
def setvalue(
self, value)
set the components value, may be tuple or other data structure
def setvalue(self,value): self.selection = value[0] self.list = value[1] if self.selection < self.top: self.top = self.selection if self.selection > self.top+(self.height-3): self.top = self.selection-(self.height-3)
Instance variables
var height
var isfocus
var label
var list
var search
var selection
var top
var width
var x
var y
class PasswordPrompt
base class for UI components defines the standard interface, not useable by itself
class PasswordPrompt(Prompt): def __init__(self, name, order, x, y, prompt, width, value=""): Prompt.__init__(self, name, order, x, y, prompt, width, value) def render(self): win = self.getparent() if self.isfocus: pattr = curses.A_BOLD fattr = curses.A_REVERSE else: pattr = curses.A_NORMAL fattr = curses.A_NORMAL if win: if self.width < 0: (max_y,max_x) = win.getmaxyx() self.width = max_x - (self.x+len(self.prompt)+2) win.addstr(self.y,self.x,self.prompt,pattr) win.addstr(self.y,self.x+len(self.prompt),pad(len(self.value)*"*",self.width),fattr) if self.isfocus: win.move(self.y,self.x+len(self.prompt)+self.pos) self.isfocus = False
Ancestors (in MRO)
- PasswordPrompt
- Prompt
- Component
- builtins.object
Class variables
var CMP_KEY_OK
Static methods
def __init__(
self, name, order, x, y, prompt, width, value='')
all components have a name and a tab order, order == -1 means exclude from tab
def __init__(self, name, order, x, y, prompt, width, value=""): Prompt.__init__(self, name, order, x, y, prompt, width, value)
def backspace(
self)
def backspace(self): self.cleft() self.delc()
def cleft(
self)
def cleft(self): self.pos -= 1 if self.pos < 0: self.pos = 0 if self.pos < self.left: self.left = self.pos
def cright(
self, offset=1)
def cright(self,offset = 1): self.pos += offset if self.pos > self.width-1: self.left = self.pos - (self.width-1)
def delc(
self)
def delc(self): if self.pos < len(self.value): self.value = self.value[0:self.pos]+self.value[self.pos+1:]
def end(
self)
def end(self): self.pos = len(self.value) if self.pos > self.width-1: self.left = self.pos - (self.width-1)
def focus(
self)
called when component is the focus
def focus(self): self.isfocus = True
def getname(
self)
get the name of this component
def getname(self): """ get the name of this component """ return self.name
def getorder(
self)
get this component's tab order number
def getorder(self): """ get this component's tab order number """ return self.order
def getparent(
self)
get this component's curses target window
def getparent(self): """ get this component's curses target window """ return self.parent
def getvalue(
self)
return the current value of the component
def getvalue(self): return self.value
def handle(
self, ch)
handle keystrokes for this component
def handle(self,ch): if len(ch) == 1 and curses.ascii.isprint(ord(ch[0])): self.insert(ch[0]) elif ch == keytab.KEYTAB_LEFT: self.cleft() elif ch == keytab.KEYTAB_RIGHT: self.cright() elif ch == keytab.KEYTAB_DELC: self.delc() elif ch == keytab.KEYTAB_BACKSPACE: self.backspace() elif ch == keytab.KEYTAB_HOME: self.home() elif ch == keytab.KEYTAB_END: self.end() elif ch == keytab.KEYTAB_DOWN: self.value = "" self.pos = 0 self.left = 0 elif ch == keytab.KEYTAB_RESIZE: return ch elif ch == keytab.KEYTAB_CTRLV or ch == keytab.KEYTAB_INSERT: if clipboard.clip_type: for clip in clipboard.clip: for ichar in clip: self.insert(ichar) elif ch == keytab.KEYTAB_CTRLC: if self.value: clipboard.clip_type = editor_common.Editor.SPAN_CLIP clipboard.clip = [ self.value ] elif ch in [keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB,keytab.KEYTAB_UP]: return ch return Component.CMP_KEY_NOP
def home(
self)
def home(self): self.pos = 0 self.left = 0
def insert(
self, ch)
def insert(self,ch): if self.pos > len(self.value): self.value = self.value + ' '*(self.pos-len(self.value)) + ch else: self.value = self.value[0:self.pos]+ch+self.value[self.pos:] self.cright(len(ch))
def isempty(
self)
test if the component entry is empty
def isempty(self): return (len(self.value.strip()) == 0)
def mouse_event(
self, ox, oy, mtype)
handle mouse events return key value or -1 for not handled
def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy == self.y: if mtype & curses.BUTTON1_CLICKED: return Component.CMP_KEY_NOP return -1
def render(
self)
render the component use parent as target
def render(self): win = self.getparent() if self.isfocus: pattr = curses.A_BOLD fattr = curses.A_REVERSE else: pattr = curses.A_NORMAL fattr = curses.A_NORMAL if win: if self.width < 0: (max_y,max_x) = win.getmaxyx() self.width = max_x - (self.x+len(self.prompt)+2) win.addstr(self.y,self.x,self.prompt,pattr) win.addstr(self.y,self.x+len(self.prompt),pad(len(self.value)*"*",self.width),fattr) if self.isfocus: win.move(self.y,self.x+len(self.prompt)+self.pos) self.isfocus = False
def setparent(
self, parent)
set the parent curses target window
def setparent(self,parent): """ set the parent curses target window """ self.parent = parent
def setpos(
self, x, y)
set the position of this component
def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y
def setsize(
self, height, width)
set the width of this component
def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width
def setvalue(
self, value)
set the components value, may be tuple or other data structure
def setvalue(self,value): self.value = value
class Prompt
base class for UI components defines the standard interface, not useable by itself
class Prompt(Component): def __init__(self, name, order, x, y, prompt, width, value= "" ): Component.__init__(self,name,order) self.x = x self.y = y self.prompt = prompt self.width = width self.value = value self.pos = 0 self.left = 0 self.isfocus = False def setvalue( self, value ): self.pos = 0 self.left = 0 Component.setvalue(self,value) def render(self): win = self.getparent() if self.isfocus: pattr = curses.A_BOLD fattr = curses.A_REVERSE else: pattr = curses.A_NORMAL fattr = curses.A_NORMAL if win: if self.width < 0: (max_y,max_x) = win.getmaxyx() self.width = max_x - (self.x+len(self.prompt)+2) win.addstr(self.y,self.x,self.prompt,pattr) if not self.isfocus: self.left = 0 self.pos = 0 win.addstr(self.y,self.x+len(self.prompt),pad(self.value[self.left:self.left+self.width],self.width),fattr) if self.isfocus: win.move(self.y,self.x+len(self.prompt)+(self.pos-self.left)) self.isfocus = False def isempty(self): return (len(self.value.strip()) == 0) def focus(self): self.isfocus = True def setvalue(self,value): self.value = value def getvalue(self): return self.value def cleft(self): self.pos -= 1 if self.pos < 0: self.pos = 0 if self.pos < self.left: self.left = self.pos def cright(self,offset = 1): self.pos += offset if self.pos > self.width-1: self.left = self.pos - (self.width-1) def home(self): self.pos = 0 self.left = 0 def end(self): self.pos = len(self.value) if self.pos > self.width-1: self.left = self.pos - (self.width-1) def delc(self): if self.pos < len(self.value): self.value = self.value[0:self.pos]+self.value[self.pos+1:] def backspace(self): self.cleft() self.delc() def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy == self.y: if mtype & curses.BUTTON1_CLICKED: return Component.CMP_KEY_NOP return -1 def insert(self,ch): if self.pos > len(self.value): self.value = self.value + ' '*(self.pos-len(self.value)) + ch else: self.value = self.value[0:self.pos]+ch+self.value[self.pos:] self.cright(len(ch)) def handle(self,ch): if len(ch) == 1 and curses.ascii.isprint(ord(ch[0])): self.insert(ch[0]) elif ch == keytab.KEYTAB_LEFT: self.cleft() elif ch == keytab.KEYTAB_RIGHT: self.cright() elif ch == keytab.KEYTAB_DELC: self.delc() elif ch == keytab.KEYTAB_BACKSPACE: self.backspace() elif ch == keytab.KEYTAB_HOME: self.home() elif ch == keytab.KEYTAB_END: self.end() elif ch == keytab.KEYTAB_DOWN: self.value = "" self.pos = 0 self.left = 0 elif ch == keytab.KEYTAB_RESIZE: return ch elif ch == keytab.KEYTAB_CTRLV or ch == keytab.KEYTAB_INSERT: if clipboard.clip_type: for clip in clipboard.clip: for ichar in clip: self.insert(ichar) elif ch == keytab.KEYTAB_CTRLC: if self.value: clipboard.clip_type = editor_common.Editor.SPAN_CLIP clipboard.clip = [ self.value ] elif ch in [keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB,keytab.KEYTAB_UP]: return ch return Component.CMP_KEY_NOP
Ancestors (in MRO)
Class variables
var CMP_KEY_CANCEL
var CMP_KEY_NOP
var CMP_KEY_OK
Static methods
def __init__(
self, name, order, x, y, prompt, width, value='')
all components have a name and a tab order, order == -1 means exclude from tab
def __init__(self, name, order, x, y, prompt, width, value= "" ): Component.__init__(self,name,order) self.x = x self.y = y self.prompt = prompt self.width = width self.value = value self.pos = 0 self.left = 0 self.isfocus = False
def backspace(
self)
def backspace(self): self.cleft() self.delc()
def cleft(
self)
def cleft(self): self.pos -= 1 if self.pos < 0: self.pos = 0 if self.pos < self.left: self.left = self.pos
def cright(
self, offset=1)
def cright(self,offset = 1): self.pos += offset if self.pos > self.width-1: self.left = self.pos - (self.width-1)
def delc(
self)
def delc(self): if self.pos < len(self.value): self.value = self.value[0:self.pos]+self.value[self.pos+1:]
def end(
self)
def end(self): self.pos = len(self.value) if self.pos > self.width-1: self.left = self.pos - (self.width-1)
def focus(
self)
called when component is the focus
def focus(self): self.isfocus = True
def getname(
self)
get the name of this component
def getname(self): """ get the name of this component """ return self.name
def getorder(
self)
get this component's tab order number
def getorder(self): """ get this component's tab order number """ return self.order
def getparent(
self)
get this component's curses target window
def getparent(self): """ get this component's curses target window """ return self.parent
def getvalue(
self)
return the current value of the component
def getvalue(self): return self.value
def handle(
self, ch)
handle keystrokes for this component
def handle(self,ch): if len(ch) == 1 and curses.ascii.isprint(ord(ch[0])): self.insert(ch[0]) elif ch == keytab.KEYTAB_LEFT: self.cleft() elif ch == keytab.KEYTAB_RIGHT: self.cright() elif ch == keytab.KEYTAB_DELC: self.delc() elif ch == keytab.KEYTAB_BACKSPACE: self.backspace() elif ch == keytab.KEYTAB_HOME: self.home() elif ch == keytab.KEYTAB_END: self.end() elif ch == keytab.KEYTAB_DOWN: self.value = "" self.pos = 0 self.left = 0 elif ch == keytab.KEYTAB_RESIZE: return ch elif ch == keytab.KEYTAB_CTRLV or ch == keytab.KEYTAB_INSERT: if clipboard.clip_type: for clip in clipboard.clip: for ichar in clip: self.insert(ichar) elif ch == keytab.KEYTAB_CTRLC: if self.value: clipboard.clip_type = editor_common.Editor.SPAN_CLIP clipboard.clip = [ self.value ] elif ch in [keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB,keytab.KEYTAB_UP]: return ch return Component.CMP_KEY_NOP
def home(
self)
def home(self): self.pos = 0 self.left = 0
def insert(
self, ch)
def insert(self,ch): if self.pos > len(self.value): self.value = self.value + ' '*(self.pos-len(self.value)) + ch else: self.value = self.value[0:self.pos]+ch+self.value[self.pos:] self.cright(len(ch))
def isempty(
self)
test if the component entry is empty
def isempty(self): return (len(self.value.strip()) == 0)
def mouse_event(
self, ox, oy, mtype)
handle mouse events return key value or -1 for not handled
def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy == self.y: if mtype & curses.BUTTON1_CLICKED: return Component.CMP_KEY_NOP return -1
def render(
self)
render the component use parent as target
def render(self): win = self.getparent() if self.isfocus: pattr = curses.A_BOLD fattr = curses.A_REVERSE else: pattr = curses.A_NORMAL fattr = curses.A_NORMAL if win: if self.width < 0: (max_y,max_x) = win.getmaxyx() self.width = max_x - (self.x+len(self.prompt)+2) win.addstr(self.y,self.x,self.prompt,pattr) if not self.isfocus: self.left = 0 self.pos = 0 win.addstr(self.y,self.x+len(self.prompt),pad(self.value[self.left:self.left+self.width],self.width),fattr) if self.isfocus: win.move(self.y,self.x+len(self.prompt)+(self.pos-self.left)) self.isfocus = False
def setparent(
self, parent)
set the parent curses target window
def setparent(self,parent): """ set the parent curses target window """ self.parent = parent
def setpos(
self, x, y)
set the position of this component
def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y
def setsize(
self, height, width)
set the width of this component
def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width
def setvalue(
self, value)
set the components value, may be tuple or other data structure
def setvalue(self,value): self.value = value
Instance variables
var isfocus
var left
var pos
var prompt
var value
var width
var x
var y
class StaticText
base class for UI components defines the standard interface, not useable by itself
class StaticText(Component): def __init__(self, name, x, y, prompt, width, value= "" ): Component.__init__(self,name,-1) self.x = x self.y = y self.prompt = prompt self.width = width self.value = value def setvalue(self,value): self.value = value def getvalue(self): return self.value def render(self): win = self.getparent() if win: try: max_y,max_x = win.getmaxyx() width = (max_x - self.x) - 1 x = self.x win.addstr(self.y,x,self.prompt[-width:],curses.A_NORMAL) x += len(self.prompt[-width:]) width -= len(self.prompt[-width:]) if width > 0: win.addstr(self.y,x,pad(self.value,self.width)[-width:],curses.A_NORMAL) except Exception as e: raise Exception("%d,%d,%d,%s,%s"%(x,self.y,width,self.prompt,str(e)))
Ancestors (in MRO)
- StaticText
- Component
- builtins.object
Class variables
var CMP_KEY_CANCEL
var CMP_KEY_NOP
var CMP_KEY_OK
Static methods
def __init__(
self, name, x, y, prompt, width, value='')
all components have a name and a tab order, order == -1 means exclude from tab
def __init__(self, name, x, y, prompt, width, value= "" ): Component.__init__(self,name,-1) self.x = x self.y = y self.prompt = prompt self.width = width self.value = value
def focus(
self)
called when component is the focus
def focus(self): """ called when component is the focus """ pass
def getname(
self)
get the name of this component
def getname(self): """ get the name of this component """ return self.name
def getorder(
self)
get this component's tab order number
def getorder(self): """ get this component's tab order number """ return self.order
def getparent(
self)
get this component's curses target window
def getparent(self): """ get this component's curses target window """ return self.parent
def getvalue(
self)
return the current value of the component
def getvalue(self): return self.value
def handle(
self, ch)
handle keystrokes for this component
def handle(self, ch ): """ handle keystrokes for this component """ pass
def isempty(
self)
test if the component entry is empty
def isempty(self): """ test if the component entry is empty """ return False
def mouse_event(
self, ox, oy, mtype)
handle mouse events return key value or -1 for not handled
def mouse_event(self, ox, oy, mtype): """ handle mouse events return key value or -1 for not handled """ return -1
def render(
self)
render the component use parent as target
def render(self): win = self.getparent() if win: try: max_y,max_x = win.getmaxyx() width = (max_x - self.x) - 1 x = self.x win.addstr(self.y,x,self.prompt[-width:],curses.A_NORMAL) x += len(self.prompt[-width:]) width -= len(self.prompt[-width:]) if width > 0: win.addstr(self.y,x,pad(self.value,self.width)[-width:],curses.A_NORMAL) except Exception as e: raise Exception("%d,%d,%d,%s,%s"%(x,self.y,width,self.prompt,str(e)))
def setparent(
self, parent)
set the parent curses target window
def setparent(self,parent): """ set the parent curses target window """ self.parent = parent
def setpos(
self, x, y)
set the position of this component
def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y
def setsize(
self, height, width)
set the width of this component
def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width
def setvalue(
self, value)
set the components value, may be tuple or other data structure
def setvalue(self,value): self.value = value
Instance variables
var prompt
var value
var width
var x
var y
class Toggle
base class for UI components defines the standard interface, not useable by itself
class Toggle(Component): def __init__(self, name, order, x, y, width, selection = 0, lst = []): Component.__init__(self,name,order) self.x = x self.y = y self.width = width self.selection = selection self.list = lst self.isfocus = False def render(self): win = self.getparent() if win: if self.isfocus: lattr = curses.A_REVERSE else: lattr = curses.A_NORMAL x = self.x y = self.y width = self.width win.addstr(y,x,pad(self.list[self.selection],width)[0:width],lattr) if self.isfocus: win.move(y,x) self.isfocus = False def focus(self): self.isfocus = True def setvalue(self,value): self.selection = value[0] self.list = value[1] def getvalue(self): return (self.selection,self.list) def cup(self): if len(self.list): self.selection -= 1 if self.selection < 0: self.selection = len(self.list)-1 def cdown(self): if len(self.list): self.selection += 1 if self.selection >= len(self.list): self.selection = 0 def home(self): if len(self.list): self.selection = 0 def end(self): if len(self.list): self.selection = len(self.list)-1 def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy == self.y: if mtype & curses.BUTTON1_CLICKED: self.cdown() return Component.CMP_KEY_NOP return -1 def handle(self,ch): if ch == keytab.KEYTAB_LEFT or ch == keytab.KEYTAB_UP: self.cup() elif ch == keytab.KEYTAB_SPACE or ch == keytab.KEYTAB_RIGHT or ch == keytab.KEYTAB_DOWN: self.cdown() elif ch == keytab.KEYTAB_HOME: self.home() elif ch == keytab.KEYTAB_END: self.end() elif ch == keytab.KEYTAB_RESIZE: return ch elif ch in [keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB]: return ch return Component.CMP_KEY_NOP
Ancestors (in MRO)
Class variables
var CMP_KEY_CANCEL
var CMP_KEY_NOP
var CMP_KEY_OK
Static methods
def __init__(
self, name, order, x, y, width, selection=0, lst=[])
all components have a name and a tab order, order == -1 means exclude from tab
def __init__(self, name, order, x, y, width, selection = 0, lst = []): Component.__init__(self,name,order) self.x = x self.y = y self.width = width self.selection = selection self.list = lst self.isfocus = False
def cdown(
self)
def cdown(self): if len(self.list): self.selection += 1 if self.selection >= len(self.list): self.selection = 0
def cup(
self)
def cup(self): if len(self.list): self.selection -= 1 if self.selection < 0: self.selection = len(self.list)-1
def end(
self)
def end(self): if len(self.list): self.selection = len(self.list)-1
def focus(
self)
called when component is the focus
def focus(self): self.isfocus = True
def getname(
self)
get the name of this component
def getname(self): """ get the name of this component """ return self.name
def getorder(
self)
get this component's tab order number
def getorder(self): """ get this component's tab order number """ return self.order
def getparent(
self)
get this component's curses target window
def getparent(self): """ get this component's curses target window """ return self.parent
def getvalue(
self)
return the current value of the component
def getvalue(self): return (self.selection,self.list)
def handle(
self, ch)
handle keystrokes for this component
def handle(self,ch): if ch == keytab.KEYTAB_LEFT or ch == keytab.KEYTAB_UP: self.cup() elif ch == keytab.KEYTAB_SPACE or ch == keytab.KEYTAB_RIGHT or ch == keytab.KEYTAB_DOWN: self.cdown() elif ch == keytab.KEYTAB_HOME: self.home() elif ch == keytab.KEYTAB_END: self.end() elif ch == keytab.KEYTAB_RESIZE: return ch elif ch in [keytab.KEYTAB_CR,keytab.KEYTAB_TAB,keytab.KEYTAB_ESC,keytab.KEYTAB_BTAB]: return ch return Component.CMP_KEY_NOP
def home(
self)
def home(self): if len(self.list): self.selection = 0
def isempty(
self)
test if the component entry is empty
def isempty(self): """ test if the component entry is empty """ return False
def mouse_event(
self, ox, oy, mtype)
handle mouse events return key value or -1 for not handled
def mouse_event(self, ox, oy, mtype): if ox >= self.x and ox < self.x+self.width and oy == self.y: if mtype & curses.BUTTON1_CLICKED: self.cdown() return Component.CMP_KEY_NOP return -1
def render(
self)
render the component use parent as target
def render(self): win = self.getparent() if win: if self.isfocus: lattr = curses.A_REVERSE else: lattr = curses.A_NORMAL x = self.x y = self.y width = self.width win.addstr(y,x,pad(self.list[self.selection],width)[0:width],lattr) if self.isfocus: win.move(y,x) self.isfocus = False
def setparent(
self, parent)
set the parent curses target window
def setparent(self,parent): """ set the parent curses target window """ self.parent = parent
def setpos(
self, x, y)
set the position of this component
def setpos(self, x, y ): """ set the position of this component """ self.x = x self.y = y
def setsize(
self, height, width)
set the width of this component
def setsize(self, height, width ): """ set the width of this component """ self.height = height self.width = width
def setvalue(
self, value)
set the components value, may be tuple or other data structure
def setvalue(self,value): self.selection = value[0] self.list = value[1]
Instance variables
var isfocus
var list
var selection
var width
var x
var y