installer/readmultext.py
72832a72
 #
 #    Copyright (C) 2015 vmware inc.
 #
 #    Author: Yang Yao <yaoyang@vmware.com>
 
 import curses
 import sys
 from actionresult import ActionResult
 from action import Action
 from window import Window
 from confirmwindow import ConfirmWindow
 
 class ReadMulText(Action):
c533b308
     def __init__(self, maxy, maxx, y, install_config, field,
                  display_string, confirmation_error_msg,
                  echo_char, accepted_chars, validation_fn, conversion_fn,
                  can_cancel, default_string=None):
72832a72
         self.maxy = maxy
         self.maxx = maxx
         self.y = y
         self.install_config = install_config
         self.field = field
         self.horizontal_padding = 10
         self.confirmation_error_msg = confirmation_error_msg
         self.echo_char = echo_char
         self.accepted_chars = accepted_chars
         self.validation_fn = validation_fn
         self.conversion_fn = conversion_fn
         self.default_string = default_string
         self.display_string = display_string
         self.textwin_width = maxx - self.horizontal_padding -2
a672bd24
         self.textwin_width = self.textwin_width* 2 // 3
72832a72
         self.visible_text_width = self.textwin_width - 1
         self.position = 0
         self.height = len(self.display_string) * 4 + 2
         self.menu_pos = 0
c533b308
         #self.textwin_width)
         self.textwin = curses.newwin(self.height, self.textwin_width + 2)
72832a72
         self.textwin.bkgd(' ', curses.color_pair(2))
         self.textwin.keypad(1)
 
         self.shadowwin = curses.newwin(self.height, self.textwin_width + 2)
         self.shadowwin.bkgd(' ', curses.color_pair(0)) #Default shadow color
 
         self.panel = curses.panel.new_panel(self.textwin)
a672bd24
         self.panel.move((maxy-self.height) // 2, (maxx - self.textwin_width) // 2 -1)
72832a72
         self.panel.hide()
         self.shadowpanel = curses.panel.new_panel(self.shadowwin)
a672bd24
         self.shadowpanel.move((maxy-self.height) // 2 + 1, (maxx - self.textwin_width) // 2)
72832a72
         self.shadowpanel.hide()
         curses.panel.update_panels()
 
         self.init_text()
         self.textwin.box()
         self.maxlength = 255
 
         #initialize the accepted characters
         if accepted_chars:
             self.accepted_chars = accepted_chars
         else:
             self.accepted_chars = range(32, 127)
 
     def hide(self):
         return
c533b308
 
72832a72
     def init_text(self):
         self.shadowpanel.show()
         curses.panel.update_panels()
 
c533b308
         self.x = 0
72832a72
         #initialize the ----
c533b308
         dashes = '_' * self.textwin_width
         cury = self.y + 1
72832a72
         self.str = []
 
         for string in self.display_string:
             self.textwin.addstr(cury, 1, string)
c533b308
             self.textwin.addstr(cury + 1, 1, dashes)
72832a72
             cury = cury + 4
             self.str.append('')
 
         #remove the error messages
         spaces = ' ' * self.textwin_width
         #self.textwin.addstr(self.y + 2, 0, spaces)
         self.update_menu()
 
     def do_action(self):
         self.init_text()
         curses.curs_set(1)
 
         if self.default_string != None:
             self.textwin.addstr(self.y, 0, self.default_string)
             self.str = self.default_string
 
         while True:
             if len(self.str[self.position]) > self.visible_text_width:
                 curs_loc = self.visible_text_width + 1
             else:
                 curs_loc = len(self.str[self.position]) +1
c533b308
             ch = self.textwin.getch(self.y + 2 + self.position * 4, curs_loc)
72832a72
 
             update_text = False
             if ch in [curses.KEY_ENTER, ord('\n')]:
c533b308
                 if self.menu_pos == 1:
72832a72
                     curses.curs_set(0)
                     self.shadowpanel.hide()
                     return ActionResult(False, None)
                 if self.confirmation_error_msg:
                     if self.str != self.install_config[self.field]:
                         curses.curs_set(0)
                         conf_message_height = 8
                         conf_message_width = 48
c533b308
                         conf_message_button_y = (self.maxy - conf_message_height) // 2 + 5
                         confrim_window = ConfirmWindow(conf_message_height, conf_message_width,
                                                        self.maxy, self.maxx, conf_message_button_y,
                                                        self.confirmation_error_msg, True)
72832a72
                         confrim_window.do_action()
                         return ActionResult(False, {'goBack': True})
                     self.set_field()
                 else:
                     if not self.validate_input():
                         continue
                     self.set_field()
                 curses.curs_set(0)
                 self.shadowpanel.hide()
                 return ActionResult(True, None)
             elif ch == curses.KEY_UP:
                 self.refresh(-1)
 
             elif ch == curses.KEY_DOWN:
                 self.refresh(1)
 
             elif ch in [ord('\t')]:
                 self.refresh(1, reset=True)
 
c533b308
             elif ch == curses.KEY_LEFT:
72832a72
                 self.menu_refresh(1)
 
             elif ch == curses.KEY_RIGHT:
                 self.menu_refresh(-1)
 
             elif ch == curses.KEY_BACKSPACE:
                 # Handle the backspace case
                 self.str[self.position] = self.str[self.position][:len(self.str[self.position]) - 1]
                 update_text = True
 
             elif len(self.str[self.position]) < self.maxlength and ch in self.accepted_chars:
                 self.str[self.position] += chr(ch)
                 update_text = True
 
             if update_text:
                 self.update_text()
 
     def menu_refresh(self, n):
c533b308
         self.menu_pos += n
         if self.menu_pos < 0:
             self.menu_pos = 0
         elif self.menu_pos >= 1:
             self.menu_pos = 1
72832a72
         self.update_menu()
 
     def update_menu(self):
c533b308
         if self.menu_pos == 1:
72832a72
             self.textwin.addstr(self.height-2, 5, '<Cancel>', curses.color_pair(3))
         else:
             self.textwin.addstr(self.height-2, 5, '<Cancel>')
c533b308
         if self.menu_pos == 0:
             self.textwin.addstr(self.height-2, self.textwin_width-len('<OK>')-5, '<OK>',
                                 curses.color_pair(3))
72832a72
         else:
c533b308
             self.textwin.addstr(self.height-2, self.textwin_width-len('<OK>')-5,
                                 '<OK>')
72832a72
 
 
 
     def update_text(self):
         if len(self.str[self.position]) > self.visible_text_width:
             text = self.str[self.position][-self.visible_text_width:]
         else:
             text = self.str[self.position]
         if self.echo_char:
             text = self.echo_char * len(text)
 
         text = text + '_' * (self.visible_text_width - len(self.str[self.position]))
c533b308
         self.textwin.addstr(self.y + 2 + self.position * 4, 1, text)
72832a72
 
     def refresh(self, n, reset=False):
c533b308
         self.position += n
72832a72
         if self.position < 0:
             self.position = 0
         elif self.position >= len(self.display_string):
             if reset:
c533b308
                 self.position = 0
72832a72
             else:
                 self.position = len(self.display_string)-1
 
     def set_field(self):
         i = 0
         for string in self.display_string:
             if self.conversion_fn:
                 self.install_config[self.field+str(i)] = self.conversion_fn(self.str[i])
             else:
                 self.install_config[self.field+str(i)] = self.str[i]
             i = i + 1
 
     def validate_input(self):
         if self.validation_fn:
             success, err = self.validation_fn(self.str)
             if not success:
                 spaces = ' ' * (int(self.textwin_width) - len(self.display_string[0]))
                 self.textwin.addstr(self.y + 1, len(self.display_string[0]), spaces)
c533b308
                 self.textwin.addstr(self.y + 1, len(self.display_string[0]), err,
                                     curses.color_pair(4))
72832a72
             return success
         else:
             return True