Пример #1
0
    def __init__(self, history, themeName=DEFAULT_THEME_NAME):
        self.history = history

        self.promptText = None
        self.promptStyle = None
        self.responseStyle = None

        self.inputLimit = None

        # Initialize the transcripts
        self.transcripts = [[]]
        self.transcript = self.transcripts[0]

        # Set the themes
        self.onThemeSet = NamedSignal('onThemeSet')
        self.setTheme(themeName)

        # Install the filter and document listener
        self.filter = CommandDocumentFilter()
        self.setDocumentFilter(self.filter)

        self.listener = CommandDocumentListener(self.history)
        self.addDocumentListener(self.listener)
Пример #2
0
    def __init__(self, history, themeName=DEFAULT_THEME_NAME):
        self.history = history

        self.promptText = None
        self.promptStyle = None
        self.responseStyle = None

        self.inputLimit = None

        # Initialize the transcripts
        self.transcripts = [[]]
        self.transcript = self.transcripts[0]

        # Set the themes
        self.onThemeSet = NamedSignal('onThemeSet')
        self.setTheme(themeName)

        # Install the filter and document listener
        self.filter = CommandDocumentFilter()
        self.setDocumentFilter(self.filter)

        self.listener = CommandDocumentListener(self.history)
        self.addDocumentListener(self.listener)
Пример #3
0
class CommandDocument(DefaultStyledDocument):
    """
    This is the document subclass used for the JES command window.
    Its only responsibilities compared to a normal document are protecting
    everything written by the program up to the last prompt, and keeping
    the History up to date with what the current prompt text is.
    """
    def __init__(self, history, themeName=DEFAULT_THEME_NAME):
        self.history = history

        self.promptText = None
        self.promptStyle = None
        self.responseStyle = None

        self.inputLimit = None

        # Initialize the transcripts
        self.transcripts = [[]]
        self.transcript = self.transcripts[0]

        # Set the themes
        self.onThemeSet = NamedSignal('onThemeSet')
        self.setTheme(themeName)

        # Install the filter and document listener
        self.filter = CommandDocumentFilter()
        self.setDocumentFilter(self.filter)

        self.listener = CommandDocumentListener(self.history)
        self.addDocumentListener(self.listener)

    def setTheme(self, themeName):
        """
        Updates all the existing styles, and recolors the command window
        to match the new styles if any text is present.
        """
        # Pick our fonts!
        self.defaultFontFamily = \
            UIManager.getDefaults().getFont("EditorPane.font").getFamily()
        self.monoFontFamily = 'Monospaced'

        # Check that the theme exists
        if themeName not in THEMES:
            themeName = DEFAULT_THEME_NAME

        self.themeName = themeName
        self.theme = theme = THEMES[themeName]

        # Set the default style
        baseStyle = self.getStyle('default')
        StyleConstants.setBackground(baseStyle, theme.backgroundColor)
        self._setStyle(baseStyle, theme.defaultStyle)

        # Set the pretty text styles
        existingStyles = set(self.getStyleNames())
        for name in ALL_STYLES:
            if name in existingStyles:
                style = self.getStyle(name)
            else:
                style = self.addStyle(name, baseStyle)

            styleSpec = theme.styles.get(name, (None, None))
            styleSpec = (
                (theme.defaultStyle[0] if styleSpec[0] is None else styleSpec[0]),
                (theme.defaultStyle[1] if styleSpec[1] is None else styleSpec[1])
            )
            self._setStyle(style, styleSpec)

        self._recolorDocument()
        self.onThemeSet.send(self)

    def _recolorDocument(self):
        # Reapply character styles to the text in the transcript
        offset = 0
        for styleName, text in self.transcript:
            length = len(text)
            self.setCharacterAttributes(offset, length,
                                        self.getStyle(styleName), False)
            offset += length

        # Reapply character styles to the user input
        if self.responseStyle:
            self.setCharacterAttributes(offset, self.getLength() - offset,
                                        self.getStyle(self.responseStyle),
                                        False)

    def _setStyle(self, attrSet, styleSpec):
        flags, color = styleSpec

        StyleConstants.setForeground(attrSet, color)

        if flags & MONOSPACE:
            StyleConstants.setFontFamily(attrSet, self.monoFontFamily)
        else:
            StyleConstants.setFontFamily(attrSet, self.defaultFontFamily)

    def getBackgroundColor(self):
        """
        Returns the background color that this document's editor window
        should have.
        """
        return self.theme.backgroundColor

    def getDefaultTextColor(self):
        """
        Returns the default text color. (The theme really should specify one!)
        """
        return self.theme.defaultStyle[1]

    def setFontSize(self, size):
        """
        Updates the document to have the provided font size.
        """
        # First, we need to resize all the existing text.
        attr = SimpleAttributeSet()
        StyleConstants.setFontSize(attr, size)
        self.setCharacterAttributes(0, self.getLength(), attr, False)

        # Next, ensure that new text is given the proper size.
        for name in self.getStyleNames():
            StyleConstants.setFontSize(self.getStyle(name), size)

    def append(self, text, style):
        """
        Writes text at the end of the document, in a specific style.
        """
        self.transcript.append(TranscriptLine(style, text))
        self.insertString(self.getLength(), text, self.getStyle(style))

    def openPrompt(self, promptText, promptStyle, responseStyle):
        """
        Indicates a prompt to draw on the screen, and starts displaying
        user input in response. This requires the history to have already
        been activated.
        """
        if self.promptText is not None:
            raise Exception("A prompt is currently being displayed!")

        self.promptText = promptText
        self.promptStyle = promptStyle
        self.responseStyle = responseStyle

        self.resumePrompt()

    def closePrompt(self):
        """
        Suspends the prompt, then resets it so a different prompt can be
        displayed. After this, you should either commit or close the history.
        """
        if self.promptText is None:
            raise Exception("A prompt is not being displayed!")

        self.suspendPrompt()
        self.promptText = None
        self.promptStyle = None
        self.responseStyle = None

    def resumePrompt(self):
        """
        Draws the prompt and starts allowing user input again,
        also locking the program from writing before the prompt.
        """
        if self.promptText is None:
            raise Exception("A prompt is not being displayed!")

        self.ensureNewline(self.promptStyle)
        self.append(self.promptText, self.promptStyle)

        self.inputLimit = self.getLength()
        self.filter.enable(self.inputLimit, self.getStyle(self.responseStyle))
        self.listener.enable(self.inputLimit)

        self.setResponseText(self.history.getCurrentInput())

    def suspendPrompt(self):
        """
        Stops allowing user input and moves the caret to the next line,
        so content can be printed to the command window by the program
        without restriction.
        """
        if self.promptText is None:
            raise Exception("A prompt is not being displayed!")

        inputLength = self.getLength() - self.inputLimit
        text = self.getText(self.inputLimit, inputLength)
        self.transcript.append(TranscriptLine(self.responseStyle, text))

        self.filter.disable()
        self.listener.disable()
        self.inputLimit = None
        self.ensureNewline(self.responseStyle)

    def setResponseText(self, text):
        """
        Replaces the current response text with some new text.
        """
        if self.inputLimit is None:
            raise Exception("A prompt is not being displayed!")

        offset = self.inputLimit
        self.replace(offset, self.getLength() - offset, text, self.getStyle(self.responseStyle))

    def ensureNewline(self, style):
        """
        Ensures that there's a newline at the end of the buffer,
        so that anything appended will appear at the start of the line.
        """
        length = self.getLength()
        if length != 0 and self.getText(length - 1, 1) != '\n':
            self.append('\n', style)

    def clear(self):
        """
        Erase everything in the document.
        """
        self.transcripts.append([])
        self.transcript = self.transcripts[-1]
        self.remove(0, self.getLength())
Пример #4
0
class CommandDocument(DefaultStyledDocument):
    """
    This is the document subclass used for the JES command window.
    Its only responsibilities compared to a normal document are protecting
    everything written by the program up to the last prompt, and keeping
    the History up to date with what the current prompt text is.
    """
    def __init__(self, history, themeName=DEFAULT_THEME_NAME):
        self.history = history

        self.promptText = None
        self.promptStyle = None
        self.responseStyle = None

        self.inputLimit = None

        # Initialize the transcripts
        self.transcripts = [[]]
        self.transcript = self.transcripts[0]

        # Set the themes
        self.onThemeSet = NamedSignal('onThemeSet')
        self.setTheme(themeName)

        # Install the filter and document listener
        self.filter = CommandDocumentFilter()
        self.setDocumentFilter(self.filter)

        self.listener = CommandDocumentListener(self.history)
        self.addDocumentListener(self.listener)

    def setTheme(self, themeName):
        """
        Updates all the existing styles, and recolors the command window
        to match the new styles if any text is present.
        """
        # Pick our fonts!
        self.defaultFontFamily = \
            UIManager.getDefaults().getFont("EditorPane.font").getFamily()
        self.monoFontFamily = 'Monospaced'

        # Check that the theme exists
        if themeName not in THEMES:
            themeName = DEFAULT_THEME_NAME

        self.themeName = themeName
        self.theme = theme = THEMES[themeName]

        # Set the default style
        baseStyle = self.getStyle('default')
        StyleConstants.setBackground(baseStyle, theme.backgroundColor)
        self._setStyle(baseStyle, theme.defaultStyle)

        # Set the pretty text styles
        existingStyles = set(self.getStyleNames())
        for name in ALL_STYLES:
            if name in existingStyles:
                style = self.getStyle(name)
            else:
                style = self.addStyle(name, baseStyle)

            styleSpec = theme.styles.get(name, (None, None))
            styleSpec = ((theme.defaultStyle[0]
                          if styleSpec[0] is None else styleSpec[0]),
                         (theme.defaultStyle[1]
                          if styleSpec[1] is None else styleSpec[1]))
            self._setStyle(style, styleSpec)

        self._recolorDocument()
        self.onThemeSet.send(self)

    def _recolorDocument(self):
        # Reapply character styles to the text in the transcript
        offset = 0
        for styleName, text in self.transcript:
            length = len(text)
            self.setCharacterAttributes(offset, length,
                                        self.getStyle(styleName), False)
            offset += length

        # Reapply character styles to the user input
        if self.responseStyle:
            self.setCharacterAttributes(offset,
                                        self.getLength() - offset,
                                        self.getStyle(self.responseStyle),
                                        False)

    def _setStyle(self, attrSet, styleSpec):
        flags, color = styleSpec

        StyleConstants.setForeground(attrSet, color)

        if flags & MONOSPACE:
            StyleConstants.setFontFamily(attrSet, self.monoFontFamily)
        else:
            StyleConstants.setFontFamily(attrSet, self.defaultFontFamily)

    def getBackgroundColor(self):
        """
        Returns the background color that this document's editor window
        should have.
        """
        return self.theme.backgroundColor

    def getDefaultTextColor(self):
        """
        Returns the default text color. (The theme really should specify one!)
        """
        return self.theme.defaultStyle[1]

    def setFontSize(self, size):
        """
        Updates the document to have the provided font size.
        """
        # First, we need to resize all the existing text.
        attr = SimpleAttributeSet()
        StyleConstants.setFontSize(attr, size)
        self.setCharacterAttributes(0, self.getLength(), attr, False)

        # Next, ensure that new text is given the proper size.
        for name in self.getStyleNames():
            StyleConstants.setFontSize(self.getStyle(name), size)

    def append(self, text, style):
        """
        Writes text at the end of the document, in a specific style.
        """
        self.transcript.append(TranscriptLine(style, text))
        self.insertString(self.getLength(), text, self.getStyle(style))

    def openPrompt(self, promptText, promptStyle, responseStyle):
        """
        Indicates a prompt to draw on the screen, and starts displaying
        user input in response. This requires the history to have already
        been activated.
        """
        if self.promptText is not None:
            raise Exception("A prompt is currently being displayed!")

        self.promptText = promptText
        self.promptStyle = promptStyle
        self.responseStyle = responseStyle

        self.resumePrompt()

    def closePrompt(self):
        """
        Suspends the prompt, then resets it so a different prompt can be
        displayed. After this, you should either commit or close the history.
        """
        if self.promptText is None:
            raise Exception("A prompt is not being displayed!")

        self.suspendPrompt()
        self.promptText = None
        self.promptStyle = None
        self.responseStyle = None

    def resumePrompt(self):
        """
        Draws the prompt and starts allowing user input again,
        also locking the program from writing before the prompt.
        """
        if self.promptText is None:
            raise Exception("A prompt is not being displayed!")

        self.ensureNewline(self.promptStyle)
        self.append(self.promptText, self.promptStyle)

        self.inputLimit = self.getLength()
        self.filter.enable(self.inputLimit, self.getStyle(self.responseStyle))
        self.listener.enable(self.inputLimit)

        self.setResponseText(self.history.getCurrentInput())

    def suspendPrompt(self):
        """
        Stops allowing user input and moves the caret to the next line,
        so content can be printed to the command window by the program
        without restriction.
        """
        if self.promptText is None:
            raise Exception("A prompt is not being displayed!")

        inputLength = self.getLength() - self.inputLimit
        text = self.getText(self.inputLimit, inputLength)
        self.transcript.append(TranscriptLine(self.responseStyle, text))

        self.filter.disable()
        self.listener.disable()
        self.inputLimit = None
        self.ensureNewline(self.responseStyle)

    def setResponseText(self, text):
        """
        Replaces the current response text with some new text.
        """
        if self.inputLimit is None:
            raise Exception("A prompt is not being displayed!")

        offset = self.inputLimit
        self.replace(offset,
                     self.getLength() - offset, text,
                     self.getStyle(self.responseStyle))

    def ensureNewline(self, style):
        """
        Ensures that there's a newline at the end of the buffer,
        so that anything appended will appear at the start of the line.
        """
        length = self.getLength()
        if length != 0 and self.getText(length - 1, 1) != '\n':
            self.append('\n', style)

    def clear(self):
        """
        Erase everything in the document.
        """
        self.transcripts.append([])
        self.transcript = self.transcripts[-1]
        self.remove(0, self.getLength())