Example #1
0
class jiconsole(Console):
    """
		Class jiconsole, it is the main class which handles user interaction
	"""
    PROMPT = sys.ps1
    PROCESS = sys.ps2
    BANNER = (InteractiveConsole.getDefaultBanner(),
              jEdit.getProperty("console-second-line"))

    def __init__(self, view):
        """ Constructor, initialized all the main variables and layout """
        # Initializes variables
        self.view = view
        self.history = History(self)
        self.bs = 0
        self.indenter = TabIndenter()
        self.exporterConsole = None
        self.executor = JythonExecutor.getExecutor()

        # Creates toolbar
        actions = [ ("Run.png", "jython.tooltip-run", self.runBuffer), \
         ("RunToBuffer.png", "jython.tooltip-run-another", self.runBufferToWindow), \
         ("RunAgain.png", "jython.tooltip-import", self.importBuffer), \
         ("MultipleResults.png", "jython.tooltip-path", self.path), \
         ("Open.png", "jython.tooltip-browse-path", self.browse), \
         ("CopyToBuffer.png", "jython.tooltip-save-session", self.savesession), \
         ("separator", None, None), \
         ("Clear.png", "jython.tooltip-restart", self.restart),
         ("separator", None, None),
         ("Parse.png", "jython.tooltip-tabnanny", self.tabnanny),
         ("separator", None, None),
         ("Help.png", "jython.tooltip-about", self.about)]
        self.panel = JPanel(BorderLayout())
        self.panel.add(BorderLayout.NORTH,
                       ToolbarHandler(actions).createToolbar())

        # Creates text pane and make keybindings
        # self.output = JTextPane(keyTyped = self.keyTyped, keyPressed = self.keyPressed, keyReleased = self.keyReleased)
        self.output = JTextPane(keyTyped=self.keyTyped,
                                keyPressed=self.keyPressed)
        if jEdit.getBooleanProperty("options.jython.upDownFlag"):
            keyBindings = [
                (KeyEvent.VK_ENTER, 0, "jython.enter", self.enter),
                (KeyEvent.VK_DELETE, 0, "jython.delete", self.delete),
                (KeyEvent.VK_HOME, 0, "jython.home", self.home),
                (KeyEvent.VK_UP, 0, "jython.up", self.history.historyUp),
                (KeyEvent.VK_DOWN, 0, "jython.down", self.history.historyDown),
                (KeyEvent.VK_UP, InputEvent.CTRL_MASK,
                 DefaultEditorKit.upAction,
                 self.output.keymap.getAction(
                     KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0))),
                (KeyEvent.VK_DOWN, InputEvent.CTRL_MASK,
                 DefaultEditorKit.downAction,
                 self.output.keymap.getAction(
                     KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)))
            ]
        else:
            keyBindings = [
             (KeyEvent.VK_ENTER, 0, "jython.enter", self.enter),
             (KeyEvent.VK_DELETE, 0, "jython.delete", self.delete),
             (KeyEvent.VK_HOME, 0, "jython.home", self.home),
             (KeyEvent.VK_UP, InputEvent.CTRL_MASK, "jython.historyup", \
              self.history.historyUp),
             (KeyEvent.VK_DOWN, InputEvent.CTRL_MASK, "jython.historydown", \
              self.history.historyDown)
            ]
        newmap = JTextComponent.addKeymap("jython", self.output.keymap)
        for (key, modifier, name, function) in keyBindings:
            newmap.addActionForKeyStroke(KeyStroke.getKeyStroke(key, modifier),
                                         ActionDelegator(name, function))
        self.output.keymap = newmap
        self.doc = self.output.document
        self.panel.add(BorderLayout.CENTER, JScrollPane(self.output))
        self.__propertiesChanged()
        self.__inittext()
        self.initialLocation = self.doc.createPosition(self.doc.length - 1)

    def browse(self, event):
        """ Opens the browse window """
        self.view.dockableWindowManager.toggleDockableWindow(
            "jython-browser-dockable")

    def stop(self, event):
        """ Stops the current execution """
        self.executor.interruptCurrent(self)

    def about(self, event):
        """ Opens the about dialog """
        from jiabout import AboutDialog
        a = AboutDialog(self.view, jEdit.getProperty("jython.about.title"))
        centerDialog(a)
        a.setVisible(1)

    def savesession(self, event):
        """ Saves the current session """
        from exportsession import export
        export(self.view, self.doc)

    def path(self, event):
        """ Opens the Path Handler """
        from pathhandler import PyPathHandler
        v = PyPathHandler(self.view, sys)
        v.pack()
        centerDialog(v)
        v.visible = 1

    def __buffer(self):
        """
			Returns the current buffer ready for run/import, checking if it is
			a python buffer and whether has been saved
		"""
        from javax.swing import JOptionPane
        buf = self.view.editPane.buffer
        if buf.mode.name != "python":
            if buf.getProperty("jython.originator"):
                buf = buf.getProperty("jython.originator")

        if buf.mode.name == "python":
            if buf.dirty:
                if not jEdit.getBooleanProperty("options.jython.autosave"):
                    if jEdit.getBooleanProperty("options.jython.saveask"):
                        result = JOptionPane.showConfirmDialog(
                            self.panel, "Do you want to save before running",
                            "Confirm", JOptionPane.YES_NO_CANCEL_OPTION)
                        if result == JOptionPane.CANCEL_OPTION:
                            return None
                        if result == JOptionPane.YES_OPTION:
                            buf.save(self.view, None)
                else:
                    buf.save(self.view, None)
            return buf

        return None

    def runBuffer(self, event):
        """ Runs the current buffer """
        buffer = self.__buffer()
        if buffer:
            JythonExecutor.getExecutor().execBuffer(self.view, buffer, self)

    def runBufferToWindow(self, event):
        """ Runs the current buffer to and exports the result to another window """
        from exportconsole import ConsoleToBuffer
        buffer = self.__buffer()
        if buffer:
            if jEdit.getBooleanProperty("options.jython.reuseOutputBuffer"):
                if not self.exporterConsole:
                    self.exporterConsole = ConsoleToBuffer(self.view, buffer)
                self.exporterConsole.clear()
            else:
                self.exporterConsole = ConsoleToBuffer(self.view, buffer)
            JythonExecutor.getExecutor().execBuffer(self.view, buffer,
                                                    self.exporterConsole)

    def tabnanny(self, event):
        import jitabnanny
        buffer = self.__buffer()
        jitabnanny.checkBuffer(buffer)

    def importBuffer(self, event):
        """ Imports the current buffer """
        import os.path
        import imp
        b = self.__buffer()
        if b:
            modname, ext = os.path.splitext(os.path.basename(b.path))
            if sys.modules.has_key(modname):
                mod = sys.modules[modname]
            else:
                mod = imp.new_module(modname)
            sys.modules[modname] = mod
            mod.__file__ = b.path
            setattr(sys.modules['__main__'], modname, mod)

            dir = os.path.dirname(b.path)
            dir = os.path.normpath(os.path.abspath(dir))
            if dir not in sys.path:
                sys.path.insert(0, dir)
            JythonExecutor.getExecutor().importBuffer(self.view, b, self)

    def restart(self, event):
        """ Reinitializes the interpreter """
        from javax.swing import JOptionPane
        result = JOptionPane.showConfirmDialog(self.panel, \
         jEdit.getProperty("jython.console.clean-confirm"), "Confirm", JOptionPane.YES_NO_CANCEL_OPTION)
        if result == JOptionPane.YES_OPTION:
            JythonExecutor.getExecutor().interrupt()
            self.__inittext()

    def inLastLine(self, include=1):
        """ Determines whether the cursor is in the last line """
        limits = self.__lastLine()
        caret = self.output.caretPosition
        if self.output.selectedText:
            caret = self.output.selectionStart
        if include:
            return (caret >= limits[0] and caret <= limits[1])
        else:
            return (caret > limits[0] and caret <= limits[1])

    def enter(self, event):
        """ Triggered when enter is pressed """
        offsets = self.__lastLine()
        text = self.doc.getText(offsets[0], offsets[1] - offsets[0])
        # Detects special keywords
        if text != "\n":
            if text[:-1] == "copyright":
                self.printResult(
                    jEdit.getProperty("jython.interpreter.copyright") +
                    sys.copyright)
                self.printPrompt()
                return
            if text[:-1] == "credits":
                import site
                self.printResult(
                    jEdit.getProperty("jython.interpreter.credits") + "\n" +
                    str(site.__builtin__.credits))
                self.printPrompt()
                return
            if text[:-1] == "license":
                import site
                self.printResult(
                    jEdit.getProperty("jython.interpreter.license"))
                self.printPrompt()
                return
            text = text[:-1]
            if self.indenter.isPushable(text):
                JythonExecutor.getExecutor().execute(self.view, text, self)
                self.history.append(text)
            else:
                self.printOnProcess()
        else:
            JythonExecutor.getExecutor().execute(self.view, text, self)

    def home(self, event):
        """ Triggered when HOME is pressed """
        if self.inLastLine():
            self.output.caretPosition = self.__lastLine()[0]
        else:
            lines = self.doc.rootElements[0].elementCount
            for i in xrange(0, lines - 1):
                offsets = (self.doc.rootElements[0].getElement(i).startOffset, \
                 self.doc.rootElements[0].getElement(i).endOffset)
                line = self.doc.getText(offsets[0], offsets[1] - offsets[0])
                if self.output.caretPosition >= offsets[0] and \
                 self.output.caretPosition <= offsets[1]:
                    if line.startswith(jiconsole.PROMPT) or line.startswith(
                            jiconsole.PROCESS):
                        self.output.caretPosition = offsets[0] + len(
                            jiconsole.PROMPT)
                    else:
                        self.output.caretPosition = offsets[0]

    def replaceRow(self, text):
        """ Replaces the last line of the textarea with text """
        offset = self.__lastLine()
        last = self.doc.getText(offset[0], offset[1] - offset[0])
        if last != "\n":
            self.doc.remove(offset[0], offset[1] - offset[0] - 1)
        self.__addOutput(self.infoColor, text)

    def delete(self, event):
        """ Intercepts delete events only allowing it to work in the last line """
        if self.inLastLine():
            if self.output.selectedText:
                self.doc.remove(
                    self.output.selectionStart,
                    self.output.selectionEnd - self.output.selectionStart)
            elif self.output.caretPosition < self.doc.length:
                self.doc.remove(self.output.caretPosition, 1)

    def keyReleased(self, event):
        """ Experimental code completion, disabled for now """
        if event.keyChar == '.':
            offsets = self.__lastLine()
            text = self.doc.getText(offsets[0], offsets[1] - offsets[0] - 1)
            #completions = jintrospect.getAutoCompleteList(text, globals())
            completions = 0
            if completions:
                CompletionPopup(self.view, completions, self.output, self)

    def keyTyped(self, event):
        if not self.inLastLine():
            event.consume()
        if self.bs:
            event.consume()
        self.bs = 0

    def keyPressed(self, event):
        if event.keyCode == KeyEvent.VK_BACK_SPACE:
            offsets = self.__lastLine()
            if not self.inLastLine(include=0):
                self.bs = 1
            else:
                self.bs = 0

    def printResult(self, msg):
        """ Prints the results of an operation """
        self.__addOutput(self.output.foreground, "\n" + str(msg))

    def printOnProcess(self):
        """ Prints the process symbol """
        self.__addOutput(self.infoColor, "\n" + jiconsole.PROCESS)

    def printPrompt(self):
        """ Prints the prompt """
        self.__addOutput(self.infoColor, "\n" + jiconsole.PROMPT)

    def printErrorMsg(self, msg, file, line):
        self.__addOutput(self.errorColor, "\n" + str(msg))
        self.__addErrorButton((file, line))

    def printError(self, e):
        import org
        self.__addOutput(self.errorColor, "\n%s" % str(e)[:-1])

        if isinstance(e, org.python.core.PySyntaxError):
            self.__addErrorButton((e.value[1][0], e.value[1][1]))
        elif isinstance(e, org.python.core.PyException):
            import traceback
            self.__addErrorButton((traceback.extract_tb(e.traceback)[-1][0],
                                   traceback.extract_tb(e.traceback)[-1][1]))

    def _completeToken(self, token):
        """ Adds a token to be completed """
        style = SimpleAttributeSet()

        style.addAttribute(StyleConstants.Foreground, self.infoColor)

        self.doc.insertString(self.output.caretPosition, token, style)

    def __addOutput(self, color, msg):
        """ Adds the output to the text area using a given color """
        style = SimpleAttributeSet()

        if color:
            style.addAttribute(StyleConstants.Foreground, color)

        self.doc.insertString(self.doc.length, msg, style)
        self.output.caretPosition = self.doc.length

    def __propertiesChanged(self):
        """ Detects when the properties have changed """
        self.output.background = jEdit.getColorProperty("jython.bgColor")
        self.output.foreground = jEdit.getColorProperty("jython.resultColor")
        self.infoColor = jEdit.getColorProperty("jython.textColor")
        self.errorColor = jEdit.getColorProperty("jython.errorColor")

        family = jEdit.getProperty("jython.font", "Monospaced")
        size = jEdit.getIntegerProperty("jython.fontsize", 14)
        style = jEdit.getIntegerProperty("jython.fontstyle", Font.PLAIN)
        self.output.setFont(Font(family, style, size))

    def __inittext(self):
        """ Inserts the initial text with the jython banner """
        self.doc.remove(0, self.doc.length)
        for line in "\n".join(jiconsole.BANNER):
            self.__addOutput(self.infoColor, line)
        self.printPrompt()
        self.output.requestFocus()

    def __lastLine(self):
        """ Returns the char offsets of the last line """
        lines = self.doc.rootElements[0].elementCount
        offsets = (self.doc.rootElements[0].getElement(lines-1).startOffset, \
        self.doc.rootElements[0].getElement(lines-1).endOffset)
        line = self.doc.getText(offsets[0], offsets[1] - offsets[0])
        if len(line) >= 4 and (line[0:4] == jiconsole.PROMPT
                               or line[0:4] == jiconsole.PROCESS):
            return (offsets[0] + len(jiconsole.PROMPT), offsets[1])
        return offsets

    def __addErrorButton(self, parsed):
        from error import ErrorButton
        if parsed[0] != "<console>":
            self.__addOutput(self.errorColor, "   ")
            self.output.insertComponent(ErrorButton(self.view, parsed))
Example #2
0
class ChatClient(JFrame):
	
	##  Constructor method, receives the variables from the ChatApp class as parameters
	
	def __init__(self, name, greeting, tn):
		'''Constructor, initialises base class & assigns variables
		'''
		# Call to the super method to take care of the base class(es)
		super(ChatClient, self).__init__()
		#  Assign the relevent variable names
		self.username=name
		self.greeting=greeting
		self.tn = tn
		self.no_users=[]
		#  Initiate the Threaded function for receiving messages
		t1=Thread(target=self.recvFunction)
		#  Set to daemon 
		t1.daemon=True
		t1.start()
		#Call the main UI
		uI=self.clientUI()
		
	##  Main GUI building function
	
	def clientUI(self):
		'''ClientUI and Widget creation
		'''
		#  Colours
		foreground_colour = Color(30,57,68)
		background_colour = Color(247,246,242)
		window_background = Color(145,190,210)
		#  Borders
		self.border2=BorderFactory.createLineBorder(foreground_colour,1, True)
		#  Fonts
		self.font= Font("Ubuntu Light",  Font.BOLD, 20)
		self.label_font= Font("Ubuntu Light",  Font.BOLD, 17)
		self.label_2_font= Font( "Ubuntu Light",Font.BOLD, 12)
		self.btn_font=Font("Ubuntu Light", Font.BOLD, 15)
		
		#  Set the layout parameters
		self.client_layout=GroupLayout(self.getContentPane())
		self.getContentPane().setLayout(self.client_layout)	
		self.getContentPane().setBackground(window_background)
		self.client_layout.setAutoCreateGaps(True)
		self.client_layout.setAutoCreateContainerGaps(True)
		self.setPreferredSize(Dimension(400, 450))
		
		#  Create widgets and assemble the GUI
		#  Main display area
		self.main_content=JTextPane()
		self.main_content.setBackground(background_colour)
		#self.main_content.setForeground(foreground_colour)
		self.main_content.setEditable(False)
		#  Message entry area  		
		self.message=JTextArea( 2,2, border=self.border2, font=self.label_font, keyPressed=self.returnKeyPress)
		self.message.requestFocusInWindow()	
		self.message.setBackground(background_colour)
		self.message.setForeground(foreground_colour)
		self.message.setLineWrap(True)
		self.message.setWrapStyleWord(True)
		self.message.setBorder(BorderFactory.createEmptyBorder(3,3,3,3))
		self.message.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), self.returnKeyPress) 
		#  BUttons
		quit_btn=JButton("Quit!", actionPerformed=ChatApp().closeEvent, border=self.border2, font=self.btn_font)
		go_btn=JButton("Send", actionPerformed=self.grabText, border=self.border2, font=self.btn_font)
		quit_btn.setBackground(background_colour)
		go_btn.setBackground(background_colour)
		quit_btn.setForeground(foreground_colour)
		go_btn.setForeground(foreground_colour)
		
		# Make scrollable
		self.scroll_content=JScrollPane(self.main_content)
		self.scroll_content.setPreferredSize(Dimension(150,275))
		self.scroll_content.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER)
		self.scroll_content.setViewportView(self.main_content)
		self.scroll_content.setBackground(Color.WHITE)
		self.scroll_message=JScrollPane(self.message)
		self.scroll_message.setPreferredSize(Dimension(150,20))
		self.scroll_message.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS)
		
		# Test user label, still not updating after first round of messages
		self.user_label=JLabel(" Users online : %s "%(str(len(self.no_users))),JLabel.RIGHT, font=self.label_2_font)
		
		#  Assemble the components
		#  Horizontal layout
		self.client_layout.setHorizontalGroup(self.client_layout.createParallelGroup()
				.addComponent(self.scroll_content)
				.addGroup(self.client_layout.createParallelGroup(GroupLayout.Alignment.CENTER)
					.addComponent(self.scroll_message))
				.addGroup(self.client_layout.createSequentialGroup()
					.addComponent(quit_btn)
					.addComponent(go_btn).addGap(20))
				.addGroup(self.client_layout.createParallelGroup()
					.addComponent(self.user_label))
		)
		
		#  Vertical layout
		self.client_layout.setVerticalGroup(self.client_layout.createSequentialGroup()
			.addGroup(self.client_layout.createParallelGroup()
				.addComponent(self.scroll_content))
				.addComponent(self.scroll_message)
				.addGroup(self.client_layout.createParallelGroup()
					.addComponent(quit_btn)
					.addComponent(go_btn))
				.addGroup(self.client_layout.createParallelGroup()
					.addComponent(self.user_label))
		)
		
		#  Finalise the GUI
		self.client_layout.linkSize(SwingConstants.HORIZONTAL, [quit_btn,go_btn, self.user_label])
		self.pack()
		self.message.requestFocusInWindow()
		self.setTitle(">>>   Client %s   <<<"%self.username)
		self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
		self.setLocationRelativeTo(None)
		self.setVisible(True)
		#  Display the server greeting
		self.appendText('\n'+self.greeting+'\n')
	
			
	##  Function responsible for receiving and processing new messages
	
	def recvFunction(self):
		'''A function to control the receiving of data from the connection
		'''
		#  While the connection is available
		while self.tn:
			#  Try to receive data using "<<<" as the delimiter
			try:
				message = self.tn.read_until('<<<')
				#  If a message is received
				if message:
					garb, message=message.split('>>>')
					message, garb = message.split('<<<')
					message = ('\n'+message+'\n')
					#  Call the append text function
					self.appendText(message)
			#  Except if there is no data available		
			except:
				#print('No message')	
				pass
	##  Event driven function to retrieve and send data to the server
	
	def grabText(self, event): 
		'''Function to repeatedly grab new messages entered into the text 
		area and display them in the main text area. Resets the entry area
		'''
		#  Grab the text from the text area
		text=self.message.getText()
		#  Don't allow an empty string through
		if text=='':
			return
		text=text.strip()
		#  Call the append text function
		self.appendText('\nYou : '+text+'\n', self.username)
		#  Reset the text to be empty and grab focus so that it is ready for new text input
		self.message.requestFocusInWindow()
		self.message.setText('')
		#  Send the message to the server
		data=text.encode()
		self.tn.write(data+'\r\n')

	##  Function to handle appending of messages
	
	def appendText(self, message, user=None):
		'''This function takes care of appending any new messages to the content area
		'''
		message_label=JTextArea(message,2,3, font=self.label_2_font)
		#  If this is a message from the grab text function, create a new label, assign it's colours
		if user!=None:
			message_label.setBackground(Color(240,240,240))
			message_label.setForeground(Color(129,129,129))
		#  Otherwise set the format for receive function (no user passed in)	
		else:
			message_label.setBackground(Color(215,215,215))
			message_label.setForeground(Color(40,153,153))
		
		#  Format and style options for the new message labels	
		message_label.setEditable(False)
		message_label.setLineWrap(True)
		message_label.setWrapStyleWord(True)
		message_label.setBorder(BorderFactory.createLineBorder( Color(247,246,242),4))
		#  Sets the positioning of messages
		self.main_content.setCaretPosition(self.main_content.getDocument().getLength())
		doc = self.main_content.getStyledDocument()
		attr=SimpleAttributeSet()
		self.main_content.insertComponent(message_label)
		# Essential for jtextarea to be able to stack message
		doc.insertString( self.main_content.getDocument().getLength(),'\n ', attr)
		# Not sure if needed
		self.main_content.repaint()
		
		###  This is a late edit so it isn't included in the documentation. Basically trying to dynamically update the number
		###  of users label at runtime. Works for incrementing the value but not decrementing it.
		
		print(message)
		#  Only split the message if there are enough values to split (greeting messages differ in format to chat messages)
		try:
			user, text=message.split(' : ')
		except:
			return
			
		#print('Split values are %s %s'%(user, text))
		user=str(user.strip())
		#print(self.no_users)
		#print(user+' : '+text)
		#  If the user already in the list, pass
		if user in self.no_users:
			if text == ('User %s amach sa teach !'%user):
				self.no_users.remove(user)
				print('User % removed'%user)
			
		else:
			#print('User %s not in list'%user)
			if str(user) == 'You':
				#print('User is equal to "You"')
				return 
			self.no_users.append(user)
			print('User appended')
			self.number_users=len(self.no_users)
			#print('Length of user list is '+str(self.number_users))
	
		self.user_label2=JLabel(" Users online : %s "%str(len(self.no_users)),JLabel.RIGHT, font=self.label_2_font)
		#print('Label created')
		#print('Attempt to replace label')
		self.client_layout.replace(self.user_label, self.user_label2) 
		self.user_label = self.user_label2
		self.user_label.repaint()
		self.user_label.revalidate()
		print('Label updated')
	
	##  Function to control return button press in message field

	def returnKeyPress(self,event):
		'''This function creates an object for return key press when inside the message entry area,
		creates an object of KeyAdapter and tests keycode for a match, responds with grab text callback		
		'''
		key_object=Key()
		key_value=key_object.keyPressed(event)
		if key_value == 10:
			self.grabText(event)