Ejemplo n.º 1
0
class PyInterpreter(Singleton):
  isInit = False
  bExitOnTouchPrev = True
  outputWidth = W
  prevMode = ""
  currentMode = "" # console, tutorial, editor
  emptyWidget = Widget(size_hint=(None,None), size=(0,0))
  
  def init(self):
    if self.isInit:
      return

    # add screens
    self.screen = Screen(name=szConsole)
    self.oldScreen = None
    self.oldTouchPrev = None
    self.editorLayout = EditorLayout(self)
    self.tutorialLayout = TutorialLayout(self)
    self.fileBrowser = FileBrowser.instance()
    
    self.repl = REPL(self)
    self.history = ["",]
    self.historyIndex = -1
    self.historyCount = 100
    self.lastIndentSpace = ""
    self.bIndentMode = False
    self.reFocusInputText = False
    self.oldTouchPrev = None
    self.textInputWidth = W * (4.0/5.0)
    
    # console menu layout
    self.consoleMenuLayout = BoxLayout(orientation="horizontal", size_hint=(1, None), height="35dp")
    btn_clear = Button(text="Clear", background_color=darkGray)
    btn_clear.bind(on_release = lambda inst:self.clearOutput())
    btn_prev = Button(text="<<", background_color=darkGray)
    btn_next = Button(text=">>", background_color=darkGray)
    self.consoleMenuLayout.add_widget(btn_clear)
    self.consoleMenuLayout.add_widget(btn_prev)
    self.consoleMenuLayout.add_widget(btn_next)
    self.screen.add_widget(self.consoleMenuLayout)
    
    # screen menu layout
    self.screenMenuLayout = BoxLayout(orientation="horizontal", size_hint=(1, None), height="35dp", pos=(0,0))
    btn_console = Button(text="Console", background_color=[1.5,0.8,0.8,2]) 
    btn_editor = Button(text="Code Editor", background_color=[0.8,1.5,0.8,2])
    btn_tutorial = Button(text="Python Tutotial", background_color=[0.8,0.8,1.5,2])
    btn_editor.bind(on_release=lambda inst:self.setMode(szEditor))
    btn_tutorial.bind(on_release=lambda inst:self.setMode(szTutorial))
    self.screenMenuLayout.add_widget(btn_console)
    self.screenMenuLayout.add_widget(btn_editor)
    self.screenMenuLayout.add_widget(btn_tutorial)
    self.screen.add_widget(self.screenMenuLayout)
    
    # text input
    self.consoleInput = TextInput(text = "text", multiline=False, size_hint=(None, None), auto_indent = True, font_name=defaultFont, 
      background_color=(.1, .1, .1, 1), foreground_color=(1,1,1,1), text_size=(0,0), font_size="14dp", padding_x="20dp", padding_y="15dp")  
    self.consoleInput.size = (W, self.consoleInput.minimum_height)
    self.consoleInput.text = ""
  
    self.consoleInput.bind(on_text_validate = lambda inst:self.onConsoleInput(inst, False, False))
    self.consoleInput.bind(focus = self.inputBoxFocus)
    
    # textinput scroll view
    self.textInputSV = ScrollView(size_hint=(None, None), size = (W, self.consoleInput.minimum_height))
    self.textInputSV.scroll_y = 0
    self.textInputSV.add_widget(self.consoleInput)
    
    # add input widget
    self.screen.add_widget(self.textInputSV)
    
    # run button
    self.btn_run = Button(text="Run", size_hint=(None,None), size =(W-self.consoleInput.size[0], self.consoleInput.size[1]),\
      background_color=(1.3,1.3,2,2))
    self.btn_run.bind(on_release = lambda inst:self.onConsoleInput(self.consoleInput, True, False))
    self.btn_run.pos = (W - self.btn_run.size[0], 0)
    self.screen.add_widget(self.btn_run)
      
    # output
    self.outputSV = ScrollView(size_hint=(None, None))
    self.screen.add_widget(self.outputSV)
    
    self.outputLayout = BoxLayout(orientation="vertical", size_hint=(None,None))
    self.outputSV.add_widget(self.outputLayout)
    
    def func_prev(inst):         
      if len(self.history) > 0:
        self.historyIndex -= 1
        if self.historyIndex < 0:
          self.historyIndex = len(self.history) - 1
        text = self.history[self.historyIndex]
        if text.find("\n") > -1:
          self.bIndentMode = True
        self.setInputText(text)
    btn_prev.bind(on_release = func_prev)
    
    def func_next(inst):
      if len(self.history) > 0:
        self.historyIndex += 1
        if self.historyIndex >= len(self.history):
          self.historyIndex = 0
        text = self.history[self.historyIndex]
        if text.find("\n") > -1:
          self.bIndentMode = True
        self.setInputText(text)
    btn_next.bind(on_release = func_next)    

    # show output layout
    self.displayText("Python " + sys.version.strip(), 0)
    
    self.repl.run_script('input=InputPopup.instance().show', False)
    
    self.isInit = True
    
  def setMode(self, mode):
    if mode == self.currentMode:
      return
      
    self.prevMode = self.currentMode
    self.currentMode = mode
    
    # restore..
    if self.prevMode == szConsole:
      self.reFocusInputText = False
      self.inputBoxForceFocus(False)
    
     # set mode layout  
    if mode == szConsole:
      gMyRoot.current_screen(self.screen)
      self.refreshLayout()
    elif mode == szEditor:
      gMyRoot.current_screen(self.editorLayout.screen)
    elif mode == szTutorial:
      gMyRoot.current_screen(self.tutorialLayout.screen)
    elif mode == szFileBrowserOpen:
      self.fileBrowser.showOpenLayout(self)
    elif mode == szFileBrowserSaveAs:
      self.fileBrowser.showSaveAsLayout(self)
      
  def callback_open_file(self, filename):
    self.editorLayout.open_file(filename)
    
  def callback_save_as(self, filename):
    self.editorLayout.save_as(filename)
    
  def callback_filebrowser_closed(self):
    self.setMode(szEditor)
    
  def setExitOnTouchPrev(self, bValue):
    self.bExitOnTouchPrev = bValue
  
  def start(self):
    self.show()
    
  def update(self, dt):
    pass
  
  def clearOutput(self):
      self.outputLayout.clear_widgets()
      self.outputLayout.size = (W, 0)
      
  def outputLayout_add_widget(self, widget):
    self.outputLayout.add_widget(widget)
    self.outputLayout.height += widget.height + widget.padding[1] + widget.padding[3]

  def displayText(self, text, scroll_y, background_color=(1,1,1,0)):
    if type(text) != str:
      text = str(text)
       
    output = TextInput(markup = True, text="", halign='left', valign='top', readonly=True, font_size="12dp", font_name = defaultFont,
      multiline=True, background_color=background_color, foreground_color=(1,1,1,1), size_hint=(None,None), size = (self.outputWidth, 0))
    output.text = text
    output.size = (self.outputWidth, output.minimum_height)
    
    self.outputLayout.add_widget(output)
    self.outputLayout.size = (self.outputWidth, self.outputLayout.size[1] + output.size[1])
    self.outputSV.scroll_x = 0
    self.outputSV.scroll_y = scroll_y
    
  def onConsoleInput(self, inst, bForceRun, resetGlobals):
    self.reFocusInputText = True
    if inst.text.strip():
      bRunCode = len(inst.text) == self.consoleInput.cursor_index()
      lastLine_nonStrip = inst.text.split("\n")[-1]
      lastLine = lastLine_nonStrip.strip()
      # indent mode - continue input but not run
      if not bForceRun and lastLine and (lastLine[-1] in ("\\", ":") or self.bIndentMode or not bRunCode):
        self.bIndentMode = True
        # get indent space
        self.lastIndentSpace = ""
        if self.bIndentMode:
          for i in lastLine_nonStrip:
            if i in [" ", "\t"]:
              self.lastIndentSpace += i
            else:
              break
        inst.insert_text("\n" + self.lastIndentSpace)
        self.consoleInput.size = (W, self.consoleInput.minimum_height)
        return
      # check indent mode - run code
      self.bIndentMode = False
      # pop input text from history
      if len(self.history) > 0 and self.historyIndex > -1 \
        and self.historyIndex < len(self.history) and self.history[self.historyIndex] == inst.text:
          self.history.pop(self.historyIndex)
      # append item to history
      if self.currentMode == szConsole:
        self.history.append(inst.text.strip())
      # check history count
      if len(self.history) > self.historyCount:
        self.history = self.history[:self.historyCount]
      self.historyIndex = len(self.history)
      # display input text to output widget
      if self.currentMode == szConsole:
        lines = inst.text.split("\n")
        result = []
        for i, line in enumerate(lines):
          line = (">>> " if i == 0 else "... ") + line
          result.append(line)
        result = "\n".join(result)
        self.displayText(result, 0)
      elif self.currentMode == szEditor:
        currentDocument = ">>> Run Untitled.py"
        self.displayText("\n".join(["-" * len(currentDocument), currentDocument + " - " + time.ctime()]), 0)
      # run code
      self.repl.onConsoleInput(inst.text, resetGlobals)
      # end message
      if self.currentMode == szEditor:
        self.displayText("Done.", 0)
        
      # clear text input
      if self.currentMode == szConsole:
        self.setInputText("")
      
  def refreshLayout(self):
    if self.currentMode == szConsole:  
      keyboardHeight = gMyRoot.getKeyboardHeight() if self.consoleInput.focus else 0
      limitHeight = (H - topMargin - keyboardHeight) * 0.5
      if self.consoleInput.minimum_height > limitHeight:
        height = limitHeight
      else:
        height = self.consoleInput.minimum_height
      self.screenMenuLayout.pos = (0, keyboardHeight)
      self.textInputSV.pos = (0, self.screenMenuLayout.top)
      self.textInputSV.size = (self.textInputWidth, height)
      self.consoleInput.size = (self.textInputWidth, self.consoleInput.minimum_height)
      self.btn_run.pos = (self.textInputSV.size[0], self.textInputSV.pos[1])
      self.btn_run.size = (W - self.textInputSV.size[0], self.textInputSV.size[1])
      self.consoleMenuLayout.pos = (0, self.textInputSV.top)
      self.outputSV.pos = (0, self.consoleMenuLayout.top)
      self.outputSV.size = (W, H - self.outputSV.pos[1] - topMargin)
      
  def setInputText(self, text):
    self.consoleInput.text = text
    if self.consoleInput.size[1] != self.consoleInput.minimum_height:
      self.refreshLayout()
  
  def insertInputText(self, text):
    self.consoleInput.insert_text(text)
    if self.consoleInput.size[1] != self.consoleInput.minimum_height:
      self.refreshLayout()
  
  def inputBoxForceFocus(self, bFocus):
    if bFocus != self.consoleInput.focus:
      self.consoleInput.focus = bFocus 
      
  def inputBoxFocus(self, inst, bFocus):
    bAlwaysPreserveFocus = False
    if not bFocus:
      if self.reFocusInputText:
        self.reFocusInputText = bAlwaysPreserveFocus
        inst.focus = True
    self.reFocusInputText = bAlwaysPreserveFocus
    self.refreshLayout()
    
  def update(self, dt):
    pass
    
  def touchPrev(self):
    if self.currentMode == szEditor:
      self.editorLayout.touchPrev()
    elif self.currentMode in (szFileBrowserOpen, szFileBrowserSaveAs):
      self.fileBrowser.touchPrev()
    elif self.currentMode == szTutorial:
      self.tutorialLayout.touchPrev()
    elif self.consoleInput.focus:
      self.reFocusInputText = False
      self.inputBoxForceFocus(False)
    else:
      self.exit()
      
  def toggle(self):
    if not self.isInit:
      self.init()
      
    if self.screen.name == gMyRoot.get_current_screen():
      self.close()
    else:
      self.show()
      
  def show(self):
    if not self.isInit:
      self.init()
    
    if self.oldScreen == None:
      self.oldScreen = gMyRoot.get_current_screen()
      self.oldTouchPrev = gMyRoot.getTouchPrev()
      
    gMyRoot.add_screen(self.screen)
    gMyRoot.add_screen(self.editorLayout.screen)
    gMyRoot.add_screen(self.tutorialLayout.screen)
    gMyRoot.current_screen(self.screen)
    gMyRoot.setTouchPrev(self.touchPrev)
    self.setMode(szConsole)
  
  def close(self):
    gMyRoot.setTouchPrev(self.oldTouchPrev)
    gMyRoot.remove(self)
    gMyRoot.remove_screen(self.screen)
    gMyRoot.remove_screen(self.editorLayout.screen)
    gMyRoot.remove_screen(self.tutorialLayout.screen)
    self.editorLayout.exit()
    if self.bExitOnTouchPrev:
      gMyRoot.exit()
    elif self.oldScreen:
      gMyRoot.current_screen(self.oldScreen)
    self.oldScreen = None
        
  def exit(self, *args):
    self.reFocusInputText = False
    self.inputBoxForceFocus(False)
    if self.bExitOnTouchPrev:
      gMyRoot.popup("Exit Python?", "", self.close, None)
    else:
      self.close()
Ejemplo n.º 2
0
    def init(self):
        if self.isInit:
            return

        # add screens
        self.screen = Screen(name=szConsole)
        self.editorLayout = EditorLayout(self)
        self.tutorialLayout = TutorialLayout(self)
        self.fileBrowser = FileBrowser(self)

        self.repl = REPL(self)
        self.history = [
            "",
        ]
        self.historyIndex = -1
        self.historyCount = 100
        self.lastIndentSpace = ""
        self.bIndentMode = False
        self.reFocusInputText = False
        self.oldTouchPrev = None
        self.textInputWidth = W * (4.0 / 5.0)

        # console menu layout
        self.consoleMenuLayout = BoxLayout(orientation="horizontal",
                                           size_hint=(1, None),
                                           height="35dp")
        btn_clear = Button(text="Clear", background_color=darkGray)
        btn_clear.bind(on_release=lambda inst: self.clearOutput())
        btn_prev = Button(text="<<", background_color=darkGray)
        btn_next = Button(text=">>", background_color=darkGray)
        self.consoleMenuLayout.add_widget(btn_clear)
        self.consoleMenuLayout.add_widget(btn_prev)
        self.consoleMenuLayout.add_widget(btn_next)
        self.screen.add_widget(self.consoleMenuLayout)

        # screen menu layout
        self.screenMenuLayout = BoxLayout(orientation="horizontal",
                                          size_hint=(1, None),
                                          height="35dp",
                                          pos=(0, 0))
        btn_console = Button(text="Console",
                             background_color=[1.5, 0.8, 0.8, 2])
        btn_editor = Button(text="Code Editor",
                            background_color=[0.8, 1.5, 0.8, 2])
        btn_tutorial = Button(text="Python Tutotial",
                              background_color=[0.8, 0.8, 1.5, 2])
        btn_editor.bind(on_release=lambda inst: self.setMode(szEditor))
        btn_tutorial.bind(on_release=lambda inst: self.setMode(szTutorial))
        self.screenMenuLayout.add_widget(btn_console)
        self.screenMenuLayout.add_widget(btn_editor)
        self.screenMenuLayout.add_widget(btn_tutorial)
        self.screen.add_widget(self.screenMenuLayout)

        # text input
        self.consoleInput = TextInput(text="text",
                                      multiline=False,
                                      size_hint=(None, None),
                                      auto_indent=True,
                                      font_name=defaultFont,
                                      background_color=(.1, .1, .1, 1),
                                      foreground_color=(1, 1, 1, 1),
                                      text_size=(0, 0),
                                      font_size="14dp",
                                      padding_x="20dp",
                                      padding_y="15dp")
        self.consoleInput.size = (W, self.consoleInput.minimum_height)
        self.consoleInput.text = ""
        '''
    def paste():
      self.consoleInput.insert_text(gMyRoot.getClipboard())
      self.refreshLayout()
    self.consoleInput.paste = paste
    '''
        self.consoleInput.bind(on_text_validate=self.onConsoleInput)
        self.consoleInput.bind(focus=self.inputBoxFocus)

        # textinput scroll view
        self.textInputSV = ScrollView(size_hint=(None, None),
                                      size=(W,
                                            self.consoleInput.minimum_height))
        self.textInputSV.scroll_y = 0
        self.textInputSV.add_widget(self.consoleInput)

        # add input widget
        self.screen.add_widget(self.textInputSV)

        # run button
        self.btn_run = Button(text="Run", size_hint=(None,None), size =(W-self.consoleInput.size[0], self.consoleInput.size[1]),\
          background_color=(1.3,1.3,2,2))
        self.btn_run.bind(on_release=lambda inst: self.onConsoleInput(
            self.consoleInput, True))
        self.btn_run.pos = (W - self.btn_run.size[0], 0)
        self.screen.add_widget(self.btn_run)

        # output
        self.outputSV = ScrollView(size_hint=(None, None))
        self.screen.add_widget(self.outputSV)

        self.outputLayout = BoxLayout(orientation="vertical",
                                      size_hint=(None, None))
        self.outputSV.add_widget(self.outputLayout)

        def func_prev(inst):
            if len(self.history) > 0:
                self.historyIndex -= 1
                if self.historyIndex < 0:
                    self.historyIndex = len(self.history) - 1
                text = self.history[self.historyIndex]
                if text.find("\n") > -1:
                    self.bIndentMode = True
                self.setInputText(text)

        btn_prev.bind(on_release=func_prev)

        def func_next(inst):
            if len(self.history) > 0:
                self.historyIndex += 1
                if self.historyIndex >= len(self.history):
                    self.historyIndex = 0
                text = self.history[self.historyIndex]
                if text.find("\n") > -1:
                    self.bIndentMode = True
                self.setInputText(text)

        btn_next.bind(on_release=func_next)

        # show output layout
        self.displayText("Python " + sys.version.strip(), 0)
        self.isInit = True
Ejemplo n.º 3
0
  def init(self):
    if self.isInit:
      return

    # add screens
    self.screen = Screen(name=szConsole)
    self.oldScreen = None
    self.oldTouchPrev = None
    self.editorLayout = EditorLayout(self)
    self.tutorialLayout = TutorialLayout(self)
    self.fileBrowser = FileBrowser.instance()
    
    self.repl = REPL(self)
    self.history = ["",]
    self.historyIndex = -1
    self.historyCount = 100
    self.lastIndentSpace = ""
    self.bIndentMode = False
    self.reFocusInputText = False
    self.oldTouchPrev = None
    self.textInputWidth = W * (4.0/5.0)
    
    # console menu layout
    self.consoleMenuLayout = BoxLayout(orientation="horizontal", size_hint=(1, None), height="35dp")
    btn_clear = Button(text="Clear", background_color=darkGray)
    btn_clear.bind(on_release = lambda inst:self.clearOutput())
    btn_prev = Button(text="<<", background_color=darkGray)
    btn_next = Button(text=">>", background_color=darkGray)
    self.consoleMenuLayout.add_widget(btn_clear)
    self.consoleMenuLayout.add_widget(btn_prev)
    self.consoleMenuLayout.add_widget(btn_next)
    self.screen.add_widget(self.consoleMenuLayout)
    
    # screen menu layout
    self.screenMenuLayout = BoxLayout(orientation="horizontal", size_hint=(1, None), height="35dp", pos=(0,0))
    btn_console = Button(text="Console", background_color=[1.5,0.8,0.8,2]) 
    btn_editor = Button(text="Code Editor", background_color=[0.8,1.5,0.8,2])
    btn_tutorial = Button(text="Python Tutotial", background_color=[0.8,0.8,1.5,2])
    btn_editor.bind(on_release=lambda inst:self.setMode(szEditor))
    btn_tutorial.bind(on_release=lambda inst:self.setMode(szTutorial))
    self.screenMenuLayout.add_widget(btn_console)
    self.screenMenuLayout.add_widget(btn_editor)
    self.screenMenuLayout.add_widget(btn_tutorial)
    self.screen.add_widget(self.screenMenuLayout)
    
    # text input
    self.consoleInput = TextInput(text = "text", multiline=False, size_hint=(None, None), auto_indent = True, font_name=defaultFont, 
      background_color=(.1, .1, .1, 1), foreground_color=(1,1,1,1), text_size=(0,0), font_size="14dp", padding_x="20dp", padding_y="15dp")  
    self.consoleInput.size = (W, self.consoleInput.minimum_height)
    self.consoleInput.text = ""
  
    self.consoleInput.bind(on_text_validate = lambda inst:self.onConsoleInput(inst, False, False))
    self.consoleInput.bind(focus = self.inputBoxFocus)
    
    # textinput scroll view
    self.textInputSV = ScrollView(size_hint=(None, None), size = (W, self.consoleInput.minimum_height))
    self.textInputSV.scroll_y = 0
    self.textInputSV.add_widget(self.consoleInput)
    
    # add input widget
    self.screen.add_widget(self.textInputSV)
    
    # run button
    self.btn_run = Button(text="Run", size_hint=(None,None), size =(W-self.consoleInput.size[0], self.consoleInput.size[1]),\
      background_color=(1.3,1.3,2,2))
    self.btn_run.bind(on_release = lambda inst:self.onConsoleInput(self.consoleInput, True, False))
    self.btn_run.pos = (W - self.btn_run.size[0], 0)
    self.screen.add_widget(self.btn_run)
      
    # output
    self.outputSV = ScrollView(size_hint=(None, None))
    self.screen.add_widget(self.outputSV)
    
    self.outputLayout = BoxLayout(orientation="vertical", size_hint=(None,None))
    self.outputSV.add_widget(self.outputLayout)
    
    def func_prev(inst):         
      if len(self.history) > 0:
        self.historyIndex -= 1
        if self.historyIndex < 0:
          self.historyIndex = len(self.history) - 1
        text = self.history[self.historyIndex]
        if text.find("\n") > -1:
          self.bIndentMode = True
        self.setInputText(text)
    btn_prev.bind(on_release = func_prev)
    
    def func_next(inst):
      if len(self.history) > 0:
        self.historyIndex += 1
        if self.historyIndex >= len(self.history):
          self.historyIndex = 0
        text = self.history[self.historyIndex]
        if text.find("\n") > -1:
          self.bIndentMode = True
        self.setInputText(text)
    btn_next.bind(on_release = func_next)    

    # show output layout
    self.displayText("Python " + sys.version.strip(), 0)
    
    self.repl.run_script('input=InputPopup.instance().show', False)
    
    self.isInit = True
Ejemplo n.º 4
0
class PyInterpreter(Singleton):
    isInit = False
    bExitOnTouchPrev = True
    outputWidth = W
    prevMode = ""
    currentMode = ""  # console, tutorial, editor
    emptyWidget = Widget(size_hint=(None, None), size=(0, 0))

    def init(self):
        if self.isInit:
            return

        # add screens
        self.screen = Screen(name=szConsole)
        self.editorLayout = EditorLayout(self)
        self.tutorialLayout = TutorialLayout(self)
        self.fileBrowser = FileBrowser(self)

        self.repl = REPL(self)
        self.history = [
            "",
        ]
        self.historyIndex = -1
        self.historyCount = 100
        self.lastIndentSpace = ""
        self.bIndentMode = False
        self.reFocusInputText = False
        self.oldTouchPrev = None
        self.textInputWidth = W * (4.0 / 5.0)

        # console menu layout
        self.consoleMenuLayout = BoxLayout(orientation="horizontal",
                                           size_hint=(1, None),
                                           height="35dp")
        btn_clear = Button(text="Clear", background_color=darkGray)
        btn_clear.bind(on_release=lambda inst: self.clearOutput())
        btn_prev = Button(text="<<", background_color=darkGray)
        btn_next = Button(text=">>", background_color=darkGray)
        self.consoleMenuLayout.add_widget(btn_clear)
        self.consoleMenuLayout.add_widget(btn_prev)
        self.consoleMenuLayout.add_widget(btn_next)
        self.screen.add_widget(self.consoleMenuLayout)

        # screen menu layout
        self.screenMenuLayout = BoxLayout(orientation="horizontal",
                                          size_hint=(1, None),
                                          height="35dp",
                                          pos=(0, 0))
        btn_console = Button(text="Console",
                             background_color=[1.5, 0.8, 0.8, 2])
        btn_editor = Button(text="Code Editor",
                            background_color=[0.8, 1.5, 0.8, 2])
        btn_tutorial = Button(text="Python Tutotial",
                              background_color=[0.8, 0.8, 1.5, 2])
        btn_editor.bind(on_release=lambda inst: self.setMode(szEditor))
        btn_tutorial.bind(on_release=lambda inst: self.setMode(szTutorial))
        self.screenMenuLayout.add_widget(btn_console)
        self.screenMenuLayout.add_widget(btn_editor)
        self.screenMenuLayout.add_widget(btn_tutorial)
        self.screen.add_widget(self.screenMenuLayout)

        # text input
        self.consoleInput = TextInput(text="text",
                                      multiline=False,
                                      size_hint=(None, None),
                                      auto_indent=True,
                                      font_name=defaultFont,
                                      background_color=(.1, .1, .1, 1),
                                      foreground_color=(1, 1, 1, 1),
                                      text_size=(0, 0),
                                      font_size="14dp",
                                      padding_x="20dp",
                                      padding_y="15dp")
        self.consoleInput.size = (W, self.consoleInput.minimum_height)
        self.consoleInput.text = ""
        '''
    def paste():
      self.consoleInput.insert_text(gMyRoot.getClipboard())
      self.refreshLayout()
    self.consoleInput.paste = paste
    '''
        self.consoleInput.bind(on_text_validate=self.onConsoleInput)
        self.consoleInput.bind(focus=self.inputBoxFocus)

        # textinput scroll view
        self.textInputSV = ScrollView(size_hint=(None, None),
                                      size=(W,
                                            self.consoleInput.minimum_height))
        self.textInputSV.scroll_y = 0
        self.textInputSV.add_widget(self.consoleInput)

        # add input widget
        self.screen.add_widget(self.textInputSV)

        # run button
        self.btn_run = Button(text="Run", size_hint=(None,None), size =(W-self.consoleInput.size[0], self.consoleInput.size[1]),\
          background_color=(1.3,1.3,2,2))
        self.btn_run.bind(on_release=lambda inst: self.onConsoleInput(
            self.consoleInput, True))
        self.btn_run.pos = (W - self.btn_run.size[0], 0)
        self.screen.add_widget(self.btn_run)

        # output
        self.outputSV = ScrollView(size_hint=(None, None))
        self.screen.add_widget(self.outputSV)

        self.outputLayout = BoxLayout(orientation="vertical",
                                      size_hint=(None, None))
        self.outputSV.add_widget(self.outputLayout)

        def func_prev(inst):
            if len(self.history) > 0:
                self.historyIndex -= 1
                if self.historyIndex < 0:
                    self.historyIndex = len(self.history) - 1
                text = self.history[self.historyIndex]
                if text.find("\n") > -1:
                    self.bIndentMode = True
                self.setInputText(text)

        btn_prev.bind(on_release=func_prev)

        def func_next(inst):
            if len(self.history) > 0:
                self.historyIndex += 1
                if self.historyIndex >= len(self.history):
                    self.historyIndex = 0
                text = self.history[self.historyIndex]
                if text.find("\n") > -1:
                    self.bIndentMode = True
                self.setInputText(text)

        btn_next.bind(on_release=func_next)

        # show output layout
        self.displayText("Python " + sys.version.strip(), 0)
        self.isInit = True

    def setMode(self, mode):
        if mode == self.currentMode:
            return

        self.prevMode = self.currentMode
        self.currentMode = mode

        # restore..
        if self.prevMode == szConsole:
            self.reFocusInputText = False
            self.inputBoxForceFocus(False)

        # set mode layout
        if mode == szConsole:
            gMyRoot.current_screen(self.screen)
            self.refreshLayout()
        elif mode == szEditor:
            gMyRoot.current_screen(self.editorLayout.screen)
        elif mode == szTutorial:
            gMyRoot.current_screen(self.tutorialLayout.screen)
        elif mode == szFileBrowserOpen:
            self.fileBrowser.showOpenLayout()
        elif mode == szFileBrowserSaveAs:
            self.fileBrowser.showSaveAsLayout()

    def setExitOnTouchPrev(self, bValue):
        self.bExitOnTouchPrev = bValue

    def start(self):
        self.show()

    def update(self, dt):
        pass

    def clearOutput(self):
        self.outputLayout.clear_widgets()
        self.outputLayout.size = (W, 0)

    def outputLayout_add_widget(self, widget):
        self.outputLayout.add_widget(widget)
        self.outputLayout.height += widget.height + widget.padding[
            1] + widget.padding[3]

    def displayText(self, text, scroll_y, background_color=(1, 1, 1, 0)):
        if type(text) != str:
            text = str(text)

        output = TextInput(markup=True,
                           text="",
                           halign='left',
                           valign='top',
                           readonly=True,
                           font_size="12dp",
                           font_name=defaultFont,
                           multiline=True,
                           background_color=background_color,
                           foreground_color=(1, 1, 1, 1),
                           size_hint=(None, None),
                           size=(self.outputWidth, 0))
        output.text = text
        output.size = (self.outputWidth, output.minimum_height)

        self.outputLayout.add_widget(output)
        self.outputLayout.size = (self.outputWidth,
                                  self.outputLayout.size[1] + output.size[1])
        self.outputSV.scroll_x = 0
        self.outputSV.scroll_y = scroll_y

    def onConsoleInput(self, inst, bForceRun=False):
        self.reFocusInputText = True
        if inst.text.strip():
            bRunCode = len(inst.text) == self.consoleInput.cursor_index()
            lastLine_nonStrip = inst.text.split("\n")[-1]
            lastLine = lastLine_nonStrip.strip()
            # indent mode - continue input but not run
            if not bForceRun and lastLine and (lastLine[-1] in ("\\", ":")
                                               or self.bIndentMode
                                               or not bRunCode):
                self.bIndentMode = True
                # get indent space
                self.lastIndentSpace = ""
                if self.bIndentMode:
                    for i in lastLine_nonStrip:
                        if i in [" ", "\t"]:
                            self.lastIndentSpace += i
                        else:
                            break
                inst.insert_text("\n" + self.lastIndentSpace)
                self.consoleInput.size = (W, self.consoleInput.minimum_height)
                return
            # check indent mode - run code
            self.bIndentMode = False
            # pop input text from history
            if len(self.history) > 0 and self.historyIndex > -1 \
              and self.historyIndex < len(self.history) and self.history[self.historyIndex] == inst.text:
                self.history.pop(self.historyIndex)
            # append item to history
            if self.currentMode == szConsole:
                self.history.append(inst.text.strip())
            # check history count
            if len(self.history) > self.historyCount:
                self.history = self.history[:self.historyCount]
            self.historyIndex = len(self.history)
            # display input text to output widget
            if self.currentMode == szConsole:
                lines = inst.text.split("\n")
                result = []
                for i, line in enumerate(lines):
                    line = (">>> " if i == 0 else "... ") + line
                    result.append(line)
                result = "\n".join(result)
                self.displayText(result, 0)
            elif self.currentMode == szEditor:
                currentDocument = ">>> Run Untitled.py"
                self.displayText(
                    "\n".join([
                        "-" * len(currentDocument),
                        currentDocument + " - " + time.ctime()
                    ]), 0)
            # run code
            self.repl.onConsoleInput(inst.text)
            # end message
            if self.currentMode == szEditor:
                self.displayText("Done.", 0)

            # clear text input
            if self.currentMode == szConsole:
                self.setInputText("")

    def refreshLayout(self):
        if self.currentMode == szConsole:
            keyboardHeight = gMyRoot.getKeyboardHeight(
            ) if self.consoleInput.focus else 0
            limitHeight = (H - topMargin - keyboardHeight) * 0.5
            if self.consoleInput.minimum_height > limitHeight:
                height = limitHeight
            else:
                height = self.consoleInput.minimum_height
            self.screenMenuLayout.pos = (0, keyboardHeight)
            self.textInputSV.pos = (0, self.screenMenuLayout.top)
            self.textInputSV.size = (self.textInputWidth, height)
            self.consoleInput.size = (self.textInputWidth,
                                      self.consoleInput.minimum_height)
            self.btn_run.pos = (self.textInputSV.size[0],
                                self.textInputSV.pos[1])
            self.btn_run.size = (W - self.textInputSV.size[0],
                                 self.textInputSV.size[1])
            self.consoleMenuLayout.pos = (0, self.textInputSV.top)
            self.outputSV.pos = (0, self.consoleMenuLayout.top)
            self.outputSV.size = (W, H - self.outputSV.pos[1] - topMargin)

    def setInputText(self, text):
        self.consoleInput.text = text
        if self.consoleInput.size[1] != self.consoleInput.minimum_height:
            self.refreshLayout()

    def insertInputText(self, text):
        self.consoleInput.insert_text(text)
        if self.consoleInput.size[1] != self.consoleInput.minimum_height:
            self.refreshLayout()

    def inputBoxForceFocus(self, bFocus):
        if bFocus != self.consoleInput.focus:
            self.consoleInput.focus = bFocus

    def inputBoxFocus(self, inst, bFocus):
        bAlwaysPreserveFocus = True
        if not bFocus:
            if self.reFocusInputText:
                self.reFocusInputText = bAlwaysPreserveFocus
                inst.focus = True
        self.reFocusInputText = bAlwaysPreserveFocus
        self.refreshLayout()

    def update(self, dt):
        pass

    def touchPrev(self):
        if self.currentMode == szEditor:
            self.editorLayout.touchPrev()
        elif self.currentMode in (szFileBrowserOpen, szFileBrowserSaveAs):
            self.fileBrowser.touchPrev()
        elif self.currentMode == szTutorial:
            self.tutorialLayout.touchPrev()
        elif self.consoleInput.focus:
            self.reFocusInputText = False
            self.inputBoxForceFocus(False)
        else:
            self.exit()

    def toggle(self):
        if not self.isInit:
            self.init()

        if self.screen.name == gMyRoot.get_current_screen():
            self.close()
        else:
            self.show()

    def show(self):
        if not self.isInit:
            self.init()

        gMyRoot.add_screen(self.screen)
        gMyRoot.add_screen(self.editorLayout.screen)
        gMyRoot.add_screen(self.tutorialLayout.screen)
        gMyRoot.current_screen(self.screen)
        self.oldTouchPrev = gMyRoot.getTouchPrev()
        gMyRoot.setTouchPrev(self.touchPrev)
        self.setMode(szConsole)

    def close(self):
        gMyRoot.setTouchPrev(self.oldTouchPrev)
        gMyRoot.remove(self)
        gMyRoot.remove_screen(self.screen)
        gMyRoot.remove_screen(self.editorLayout.screen)
        gMyRoot.remove_screen(self.tutorialLayout.screen)
        if self.bExitOnTouchPrev:
            self.editorLayout.exit()
            gMyRoot.exit()

    def exit(self, *args):
        self.reFocusInputText = False
        self.inputBoxForceFocus(False)
        gMyRoot.popup("Exit Python?", "", self.close, None)