# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Widgets demo. You can run this .tac file directly with: twistd -ny window.tac Demonstrates various widgets or buttons, such as scrollable regions, drawable canvas, etc. This demo sets up two listening ports: one on 6022 which accepts ssh connections; one on 6023 which accepts telnet connections. No login for the telnet server is required; for the ssh server, "username" is the username and "password" is the password. """ from __future__ import division import string, random from twisted.python import log from twisted.internet import protocol, task from twisted.application import internet, service from twisted.cred import checkers, portal from twisted.conch.insults import insults, window from twisted.conch.telnet import TelnetTransport, TelnetBootstrapProtocol from twisted.conch.manhole_ssh import ConchFactory, TerminalRealm from twisted.internet import reactor class DrawableCanvas(window.Canvas): x = 0 y = 0 def func_LEFT_ARROW(self, modifier): self.x -= 1 self.repaint() def func_RIGHT_ARROW(self, modifier): self.x += 1 self.repaint() def func_UP_ARROW(self, modifier): self.y -= 1 self.repaint() def func_DOWN_ARROW(self, modifier): self.y += 1 self.repaint() def characterReceived(self, keyID, modifier): self[self.x, self.y] = keyID self.x += 1 self.repaint() def keystrokeReceived(self, keyID, modifier): if keyID == '\r' or keyID == '\v': return window.Canvas.keystrokeReceived(self, keyID, modifier) if self.x >= self.width: self.x = 0 elif self.x < 0: self.x = self.width - 1 if self.y >= self.height: self.y = 0 elif self.y < 0: self.y = self.height - 1 self.repaint() def render(self, width, height, terminal): window.Canvas.render(self, width, height, terminal) if self.focused: terminal.cursorPosition(self.x, self.y) window.cursor(terminal, self[self.x, self.y]) class ButtonDemo(insults.TerminalProtocol): width = 80 height = 24 def _draw(self): self.window.draw(self.width, self.height, self.terminal) def _redraw(self): self.window.filthy() self._draw() def _schedule(self, f): reactor.callLater(0, f) def connectionMade(self): self.terminal.eraseDisplay() self.terminal.resetPrivateModes([insults.privateModes.CURSOR_MODE]) self.window = window.TopWindow(self._draw, self._schedule) self.output = window.TextOutput((15, 1)) self.input = window.TextInput(15, self._setText) self.select1 = window.Selection(map(str, range(100)), self._setText, 10) self.select2 = window.Selection(map(str, range(200, 300)), self._setText, 10) self.button = window.Button("Clear", self._clear) self.canvas = DrawableCanvas() hbox = window.HBox() hbox.addChild(self.input) hbox.addChild(self.output) hbox.addChild(window.Border(self.button)) hbox.addChild(window.Border(self.select1)) hbox.addChild(window.Border(self.select2)) t1 = window.TextOutputArea(longLines=window.TextOutputArea.WRAP) t2 = window.TextOutputArea(longLines=window.TextOutputArea.TRUNCATE) t3 = window.TextOutputArea(longLines=window.TextOutputArea.TRUNCATE) t4 = window.TextOutputArea(longLines=window.TextOutputArea.TRUNCATE) for _t in t1, t2, t3, t4: _t.setText((('This is a very long string. ' * 3) + '\n') * 3) vp = window.Viewport(t3) d = [1] def spin(): vp.xOffset += d[0] if vp.xOffset == 0 or vp.xOffset == 25: d[0] *= -1 self.call = task.LoopingCall(spin) self.call.start(0.25, now=False) hbox.addChild(window.Border(vp)) vp2 = window.ScrolledArea(t4) hbox.addChild(vp2) texts = window.VBox() texts.addChild(window.Border(t1)) texts.addChild(window.Border(t2)) areas = window.HBox() areas.addChild(window.Border(self.canvas)) areas.addChild(texts) vbox = window.VBox() vbox.addChild(hbox) vbox.addChild(areas) self.window.addChild(vbox) self.terminalSize(self.width, self.height) def connectionLost(self, reason): self.call.stop() insults.TerminalProtocol.connectionLost(self, reason) def terminalSize(self, width, height): self.width = width self.height = height self.terminal.eraseDisplay() self._redraw() def keystrokeReceived(self, keyID, modifier): self.window.keystrokeReceived(keyID, modifier) def _clear(self): self.canvas.clear() def _setText(self, text): self.input.setText('') self.output.setText(text) def makeService(args): checker = checkers.InMemoryUsernamePasswordDatabaseDontUse(username="password") f = protocol.ServerFactory() f.protocol = lambda: TelnetTransport(TelnetBootstrapProtocol, insults.ServerProtocol, args['protocolFactory'], *args.get('protocolArgs', ()), **args.get('protocolKwArgs', {})) tsvc = internet.TCPServer(args['telnet'], f) def chainProtocolFactory(): return insults.ServerProtocol( args['protocolFactory'], *args.get('protocolArgs', ()), **args.get('protocolKwArgs', {})) rlm = TerminalRealm() rlm.chainedProtocolFactory = chainProtocolFactory ptl = portal.Portal(rlm, [checker]) f = ConchFactory(ptl) csvc = internet.TCPServer(args['ssh'], f) m = service.MultiService() tsvc.setServiceParent(m) csvc.setServiceParent(m) return m application = service.Application("Window Demo") makeService({'protocolFactory': ButtonDemo, 'telnet': 6023, 'ssh': 6022}).setServiceParent(application)