Example #1
0
class PayloadView:
    """
    PayloadView is a TextView viewer and editor.
    """
    def __init__(self, payload=None, texteditor_factory=None, editable=True):
        self._idx = 0

        self._texteditor_factory = texteditor_factory
        self._textareas = {}
        self._widgets = {}

        self._listener = None

        self.this = JTabbedPane()
        self.this.setUI(SneakTabbedPaneUI(self.this))

        if payload:
            self.refresh(payload)
        self.editable = editable
        self.set_editable(editable)

    def _get_textarea(self, element):
        """
        Recursive search for a textarea in the components of a given supercomponent

        :param element: current widget.
        :return: None
        """
        try:
            if 'getDocument' in dir(element) and 'append' in dir(
                    element) and JTextArea in element.__class__.__mro__:
                return element

            for e in element.getComponents():
                ret = self._get_textarea(e)
                if ret:
                    return ret

        except:
            return None

    def _create_texteditor(self, name=None, label=None):
        _textarea = None

        if name and name in self._widgets:
            return self._widgets[name]

        if not name:
            name = "TextArea#%s" % self._idx
            self._idx += 1

        this = JPanel()

        # Add a label
        if label:
            this.setLayout(BorderLayout())
            this.add(BorderLayout.PAGE_START, JLabel(label))

        if self._texteditor_factory:
            _texteditor = self._texteditor_factory()
            _component = _texteditor.getComponent()
            this.add(BorderLayout.CENTER, _component)
            _textarea = self._get_textarea(_component)

        if not _textarea:
            _textarea = JTextArea()
            _textarea.setColumns(20)
            _textarea.setRows(5)
            _textarea.setLineWrap(True)
            _textarea.setWrapStyleWord(True)
            _textarea.setEditable(True)
            _textarea.setName(name)
            _textarea.setSelectionColor(Color(255, 153, 51))
            _textarea.requestFocus()
            # Add textarea to a scrollable JPane
            _scrollpane = JScrollPane()
            _scrollpane.setViewportView(_textarea)
            this.add(BorderLayout.CENTER, _scrollpane)

        _textarea.setEditable(self.editable)

        self._textareas[name] = _textarea
        self._widgets[name] = this

        def on_change(evt):
            if not self._textareas[name].hasFocus():
                return
            try:
                if name == "raw":
                    SwingUtilities.invokeLater(lambda: self._refresh_queries(
                        self._textareas['raw'].getText()))
                elif name.startswith('gql_query#'):
                    id = int(name.split("#")[1])
                    content = json.loads(self._textareas['raw'].getText())
                    if id == 0 and not isinstance(content, list):
                        content['query'] = self._textareas[name].getText()
                    else:
                        content[id]['query'] = self._textareas[name].getText()
                    SwingUtilities.invokeLater(lambda: self._textareas['raw'].
                                               setText(json.dumps(content)))
                elif name.startswith('gql_variables#'):
                    id = int(name.split("#")[1])
                    content = json.loads(self._textareas['raw'].getText())
                    if id == 0 and not isinstance(content, list):
                        content['variables'] = json.loads(
                            self._textareas[name].getText())
                    else:
                        content[id]['variables'] = json.loads(
                            self._textareas[name].getText())
                    SwingUtilities.invokeLater(lambda: self._textareas['raw'].
                                               setText(json.dumps(content)))
            except ValueError:
                pass  # Avoid crashing for JSON not valid incompatibilities

        _textarea.getDocument().addDocumentListener(
            _PayloadListener(changed_update=on_change))

        return this

    def set_editable(self, editable):
        """
        Enable or Disable the editable textview

        :param editable: boolean parameter representing the editability
        :return: None
        """
        self.editable = editable
        for t in self._textareas.values():
            t.setEditable(editable)

    def _graphql_queries(self, payload):
        try:
            content = json.loads(payload)
            if not isinstance(content, list):
                content = [content]

            q = {}

            for i in range(0, len(content)):
                if any([
                        'query' in content[i]
                        and content[i]['query'].strip().startswith(qtype) for
                        qtype in ['query', 'mutation', 'subscription', '{']
                ]):
                    q[i] = content[i]

            return q
        except ValueError:
            return None

    def _refresh_raw(self, payload):
        """
        Refresh the textarea content with a new payload, if present

        :param payload:
        :return: None
        """

        if payload:
            self.this.addTab("Raw",
                             self._create_texteditor(name="raw", label='Raw'))
            self._textareas['raw'].setText(payload)
            if self._listener:
                self.add_listener(self._listener)
            inherits_popup_menu(self.this)

    def _get_tab_component_by_name(self, name):
        for i in range(0, self.this.getTabCount()):
            if self.this.getTitleAt(i) == name:
                return self.this.getComponentAt(i)

        return None

    def _get_tab_index_by_name(self, name):
        for i in range(0, self.this.getTabCount()):
            if self.this.getTitleAt(i) == name:
                return i

        return -1

    def _refresh_queries(self, payload):
        """
        Refresh the textarea content with a new payload, if present

        :param payload:
        :return: None
        """
        graphql_tabs = []
        for i in range(0, self.this.getTabCount()):
            if self.this.getTitleAt(i).startswith("GraphQL #"):
                graphql_tabs.append(self.this.getTitleAt(i))

        if payload:
            # Check if the payload contains a GraphQL query object
            queries = self._graphql_queries(payload)
            if queries:
                # Generate and append GraphQL tab to the tabs
                for query_key in queries.keys():
                    qname = "gql_query#%s" % query_key
                    vname = "gql_variables#%s" % query_key
                    tname = "GraphQL #%s" % query_key
                    queryeditor = self._create_texteditor(name=qname,
                                                          label="Query:")
                    self._textareas[qname].setText(queries[query_key]['query'])
                    variableseditor = self._create_texteditor(
                        name=vname, label="Variables:")
                    this = self._get_tab_component_by_name(tname)
                    if tname in graphql_tabs:
                        graphql_tabs.remove(tname)
                    if not this:
                        this = JSplitPane(JSplitPane.VERTICAL_SPLIT,
                                          queryeditor, variableseditor)
                    self.this.addTab(tname, this)
                    this.setOneTouchExpandable(True)
                    this.setDividerLocation(0.66)
                    if 'variables' in queries[query_key]:
                        this.getBottomComponent().setVisible(True)
                        self._textareas[vname].setText(
                            json.dumps(queries[query_key]['variables'],
                                       indent=4))
                    else:
                        this.getBottomComponent().setVisible(False)
                        self._textareas[vname].setText("{}")

        # Remove empty graphql tabs
        try:
            for tab in graphql_tabs:
                for i in range(0, self.this.getTabCount()):
                    if self.this.getTitleAt(i) == tab:
                        self.this.remove(i)
        except:
            # Do nothing if you cannot remove an entry
            pass

        inherits_popup_menu(self.this)

    def refresh(self, payload):
        """
        Refresh the textarea content with a new payload, if present

        :param payload:
        :return: None
        """
        self._refresh_queries(payload)
        self._refresh_raw(payload)
        inherits_popup_menu(self.this)

    def textarea(self):
        return self._textareas['raw']

    def add_listener(self, listener):
        """
        add a new listener to the textarea

        :param listener: this parameter should be a lambda or a method
        :return: None
        """
        self._listener = listener
        if 'raw' in self._textareas:
            self._textareas['raw'].getDocument().addDocumentListener(
                _PayloadListener(listener))
Example #2
0
class WSAShelp_09(java.lang.Runnable):

    #---------------------------------------------------------------------------
    # Name: __init__()
    # Role: Class constructor
    #---------------------------------------------------------------------------
    def __init__(self):
        #-----------------------------------------------------------------------
        # Painter instance used to highlight text
        # Note: See hilightTextPane()
        #-----------------------------------------------------------------------
        self.painter = DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW)
        #-----------------------------------------------------------------------
        # Input field containing the text to be highlighted
        #-----------------------------------------------------------------------
        self.textField = JTextField('')
        #-----------------------------------------------------------------------
        # Dictionary, indexed by tab name, with info about tab contents
        #-----------------------------------------------------------------------
        self.tPanes = {}
        #-----------------------------------------------------------------------
        # Tabbed Pane for information to be displayed
        #-----------------------------------------------------------------------
        self.tabs = JTabbedPane(stateChanged=self.tabPicked)

    #---------------------------------------------------------------------------
    # Name: TBD()
    # Role: Indicate work that needs To Be Done
    #---------------------------------------------------------------------------
    def TBD(self, event):
        JOptionPane.showMessageDialog(self.frame, 'Not yet implemented', 'TBD',
                                      JOptionPane.PLAIN_MESSAGE)

    #---------------------------------------------------------------------------
    # Name: about()
    # Role: Used to display information about the script / application
    # Note: One way to display the script docstring (i.e., __doc__) as it
    #       appears is to use <html> text.
    # Note: The first character (i.e., [ 0 ]) is a newline, and is ignored
    #---------------------------------------------------------------------------
    def about(self, event):
        message = __doc__[1:].replace(' ', '&nbsp;')
        message = message.replace('<', '&lt;')
        message = message.replace('>', '&gt;')
        message = message.replace('\n', '<br>')
        message = '<html>' + message
        message = JLabel(message, font=monoFont)
        JOptionPane.showMessageDialog(self.frame, message, 'About',
                                      JOptionPane.PLAIN_MESSAGE)

    #---------------------------------------------------------------------------
    # Name: center()
    # Role: Position the frame in the center of the screen
    # Note: The frame isn't allowed to be wider than 1/2 the screen width, or
    #       more than 1/2 the screen height.  It is resized, if necessary.
    # Note: The value of 640 is used to keep the AdminTask.help() text from
    #       wrapping
    #---------------------------------------------------------------------------
    def center(self, frame):
        screenSize = Toolkit.getDefaultToolkit().getScreenSize()
        frameSize = frame.getSize()
        frameSize.width = min(frameSize.width, screenSize.width >> 1)
        frameSize.width = max(frameSize.width, 640)
        frameSize.height = min(frameSize.height, screenSize.height >> 1)
        if frameSize != frame.getSize():
            frame.setSize(frameSize)
        frame.setLocation((screenSize.width - frameSize.width) >> 1,
                          (screenSize.height - frameSize.height) >> 1)

    #---------------------------------------------------------------------------
    # Name: Exit()
    # Role: ActionListener event handler called when user selects Show -> Exit
    #---------------------------------------------------------------------------
    def Exit(self, event):
        sys.exit()

    #---------------------------------------------------------------------------
    # Name: frameResized()
    # Role: Component Listener event handler for the componentResized event
    #---------------------------------------------------------------------------
    def frameResized(self, ce):
        try:
            index = self.tabs.getSelectedIndex()
            name = self.tabs.getTitleAt(index)
            if len(self.tPanes[name]) > 1:
                table, rowHeight, w0, w1 = self.tPanes[name][1:]
                width = table.getParent().getExtentSize().getWidth()
                tcm = table.getColumnModel()  # Table Column Model
                margin = tcm.getColumnMargin()  # gap between columns
                if w0 + w1 + 2 * margin > width:
                    table.setRowHeight(rowHeight * 3)
                    c0 = int(round(width * .23))
                    c1 = int(width - c0 - margin)
                else:
                    table.setRowHeight(rowHeight)
                    c0 = w0 + margin
                    c1 = int(width - c0 - margin)
                tcr = table.getCellRenderer(0, 0)
                tcr.setWidths(c0, c1)
                tcr.setHiText(self.textField.getText())
                tcm.getColumn(0).setPreferredWidth(c0)
                tcm.getColumn(1).setPreferredWidth(c1)
                #-------------------------------------------------------------------
                # Redraw the table using the new column widths and row heights
                #-------------------------------------------------------------------
                table.repaint()
        except:
            print '\nError: %s\nvalue: %s' % sys.exc_info()[:2]

    #---------------------------------------------------------------------------
    # Name: hilightText()
    # Role: Event handler called by Show -> Highlight Text
    #---------------------------------------------------------------------------
    def hilightText(self, event):
        result = JOptionPane.showInputDialog(
            self.frame,  # parentComponent
            'What text do you want to highlight?'  # message text
        )
        if result != None:
            self.textField.setText(result)
            index = self.tabs.getSelectedIndex()
            name = self.tabs.getTitleAt(index)
            self.hilightTextPane(self.tPanes[name][0], result)
            if len(self.tPanes[name]) > 1:
                table = self.tPanes[name][1]
                table.getCellRenderer(0, 0).setHiText(result)
                table.repaint()

    #---------------------------------------------------------------------------
    # Name: hilightTextPane()
    # Role: Find, and highlight every occurrance of text on specified JTextPane
    #---------------------------------------------------------------------------
    def hilightTextPane(self, tPane, text):
        hiliter = tPane.getHighlighter()
        hiliter.removeAllHighlights()
        if text:
            doc = tPane.getDocument()
            info = doc.getText(0, doc.getLength())
            start = 0
            here = info.find(text, start)
            while here > -1:
                hiliter.addHighlight(here, here + len(text), self.painter)
                start = here + len(text)
                here = info.find(text, start)

    #---------------------------------------------------------------------------
    # Name: MenuBar()
    # Role: Create the application menu bar
    #---------------------------------------------------------------------------
    def MenuBar(self):

        #-----------------------------------------------------------------------
        # Start by creating our application menubar
        #-----------------------------------------------------------------------
        menu = JMenuBar()

        #-----------------------------------------------------------------------
        # "Show" entry
        #-----------------------------------------------------------------------
        show = JMenu('Show')

        show.add(JMenuItem('Highlight text', actionPerformed=self.hilightText))

        show.add(JSeparator())
        show.add(JMenuItem('Exit', actionPerformed=self.Exit))
        menu.add(show)

        #-----------------------------------------------------------------------
        # "Help" entry
        #-----------------------------------------------------------------------
        help = JMenu('Help')
        help.add(JMenuItem('About', actionPerformed=self.about))
        help.add(JMenuItem('Notice', actionPerformed=self.notice))
        menu.add(help)

        return menu

    #---------------------------------------------------------------------------
    # Name: notice()
    # Role: Used to display important information
    #---------------------------------------------------------------------------
    def notice(self, event):
        JOptionPane.showMessageDialog(
            self.frame,
            Disclaimer,
            'Notice',  # Previously "Disclaimer"
            JOptionPane.WARNING_MESSAGE)

    #---------------------------------------------------------------------------
    # Name: run()
    # Role: Instantiate the user class
    # Note: Invoked by the Swing Event Dispatch Thread
    #---------------------------------------------------------------------------
    def run(self):
        self.frame = frame = JFrame('WSAShelp_09',
                                    layout=BorderLayout(),
                                    componentResized=self.frameResized,
                                    defaultCloseOperation=JFrame.EXIT_ON_CLOSE)

        #-----------------------------------------------------------------------
        # RegExp used to locate method names
        #-----------------------------------------------------------------------
        methRE = re.compile(r'^(\w+)(?:\s+.*)$', re.MULTILINE)

        #-----------------------------------------------------------------------
        # Add our menu bar to the frame
        #-----------------------------------------------------------------------
        frame.setJMenuBar(self.MenuBar())

        #-----------------------------------------------------------------------
        # Create & Populate the JTabbedPane
        #-----------------------------------------------------------------------
        WASobjs = [
            ('wsadmin', None),  # Special case
            ('Help', Help),
            ('AdminApp', AdminApp),
            ('AdminConfig', AdminConfig),
            ('AdminControl', AdminControl),
            ('AdminTask', AdminTask)
        ]
        tabs = self.tabs
        for name, WASobj in WASobjs:
            #-------------------------------------------------------------------
            # Use a single ScrollPane for the AdminTask help
            #-------------------------------------------------------------------
            if name in ['wsadmin', 'AdminTask']:
                if WASobj:
                    data = WASobj.help().expandtabs()
                else:
                    data = Help.wsadmin().expandtabs()
                pane = JTextPane(text=data, editable=0, font=monoFont)
                #---------------------------------------------------------------
                # Move the caret to ensure that the starting text is shown
                #---------------------------------------------------------------
                pane.moveCaretPosition(0)
                tabs.addTab(name, JScrollPane(pane))
                self.tPanes[name] = [pane]
            else:
                #---------------------------------------------------------------
                # Use a RegExp to identify where the 1st method starts.
                #---------------------------------------------------------------
                text = WASobj.help().expandtabs()
                mo = re.search(methRE, text)  # Match Object
                desc = text[:mo.start(1)].strip()
                meth = text[mo.start(1):].strip()
                #---------------------------------------------------------------
                # The description section is before the 1st method
                #---------------------------------------------------------------
                topPane = JTextPane(text=desc, editable=0, font=monoFont)
                topPane.moveCaretPosition(0)
                top = JScrollPane(topPane)
                #---------------------------------------------------------------
                # For the other scripting objects, use a vertically split pane
                # with the top containing the description section, and the
                # bottom (eventually) containing the method details.
                #---------------------------------------------------------------
                splitPane = JSplitPane(
                    JSplitPane.VERTICAL_SPLIT,
                    top,
                    JLabel('One moment please...'),
                    resizeWeight=0.5,  # divider position = 50%
                    oneTouchExpandable=1)
                #---------------------------------------------------------------
                # Start a separate thread to parse the method text and build a
                # a JTable to be put into the bottom part of this splitPane
                #---------------------------------------------------------------
                self.tPanes[name] = [topPane]
                tableTask(
                    meth,  # Help text to be parsed / processed
                    splitPane,  # SplitPane to be updated
                    self.tPanes[name],  # tPanes entry to be updated
                    WASobj  # WAS scripting object
                ).execute()
                tabs.addTab(name, splitPane)

        #-----------------------------------------------------------------------
        # Add the tabbed pane to the frame & show the result
        #-----------------------------------------------------------------------
        frame.add(tabs, 'Center')

        frame.pack()
        self.center(frame)
        frame.setVisible(1)

    #---------------------------------------------------------------------------
    # Name: tabPicked()
    # Role: ChangeListener event handler - called when a tab is selected
    #---------------------------------------------------------------------------
    def tabPicked(self, event):
        pane = event.getSource()
        index = pane.getSelectedIndex()
        name = pane.getTitleAt(index)
        try:
            tPane = self.tPanes[name][0]
            tPane.select(0, 0)
            hiText = self.textField.getText()
            self.hilightTextPane(tPane, hiText)
            if len(self.tPanes[name]) > 1:
                table, rowHeight, w0, w1 = self.tPanes[name][1:]
                #---------------------------------------------------------------
                # Viewport width & preferred width for column 0
                #---------------------------------------------------------------
                width = table.getParent().getExtentSize().getWidth()
                tcm = table.getColumnModel()  # Table Column Model
                margin = tcm.getColumnMargin()  # gap between columns
                if w0 + w1 + 2 * margin > width:
                    table.setRowHeight(rowHeight * 3)
                    c0 = int(round(width * .23))
                    c1 = int(width - c0 - margin)
                else:
                    table.setRowHeight(rowHeight)
                    c0 = w0 + margin
                    c1 = int(width - c0 - margin)
                tcr = table.getCellRenderer(0, 0)
                tcr.setWidths(c0, c1)
                tcr.setHiText(hiText)
                tcm.getColumn(0).setPreferredWidth(c0)
                tcm.getColumn(1).setPreferredWidth(c1)
        except:
            Type, value = sys.exc_info()[:2]
            Type, value = str(Type), str(value)
            if not (Type.endswith('KeyError') and value == 'wsadmin'):
                print '\nError: %s\nvalue: %s' % (Type, value)