1
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2
# See LICENSE for details.
7
from twisted.python import reflect
8
from twisted.python import util
9
from twisted.manhole.ui.pywidgets import isCursorOnFirstLine, isCursorOnLastLine
13
from libglade import GladeXML
15
GLADE_FILE = util.sibpath(__file__, "instancemessenger.glade")
16
SETTINGS_FILE = os.path.expanduser("~/.InstanceMessenger")
26
class InputOutputWindow:
28
def __init__(self, rootName, inputName, outputName):
29
self.xml = openGlade(GLADE_FILE, root=rootName)
30
wid = self.xml.get_widget
31
self.entry = wid(inputName)
32
#self.entry.set_word_wrap(gtk.TRUE)
33
self.output = wid(outputName)
34
#self.output.set_word_wrap(gtk.TRUE)
35
self.widget = wid(rootName)
39
self.currentlyVisible = 0
41
autoConnectMethods(self)
44
if not self.currentlyVisible:
45
self.win = w = gtk.GtkWindow(gtk.WINDOW_TOPLEVEL)
46
self.connectid = w.connect("destroy", self.hidden)
48
w.set_title(self.getTitle())
50
self.entry.grab_focus()
51
self.currentlyVisible = 1
56
self.currentlyVisible = 0
59
if self.currentlyVisible:
60
self.win.remove(self.widget)
61
self.currentlyVisible = 0
62
self.win.disconnect(self.connectid)
66
def handle_key_press_event(self, entry, event):
68
# ASSUMPTION: Assume Meta == mod4
69
isMeta = event.state & gtk.GDK.MOD4_MASK
74
if event.keyval == gtk.GDK.Return:
75
isShift = event.state & gtk.GDK.SHIFT_MASK
78
entry.insert_defaults('\n')
81
text = entry.get_chars(0,-1)
84
self.entry.delete_text(0, -1)
87
self.history.append(text)
88
self.histpos = len(self.history)
93
elif ((event.keyval == gtk.GDK.Up and isCursorOnFirstLine(entry))
94
or (isMeta and event.string == 'p')):
98
elif ((event.keyval == gtk.GDK.Down and isCursorOnLastLine(entry))
99
or (isMeta and event.string == 'n')):
107
elif event.keyval == gtk.GDK.Tab:
108
oldpos = entry.get_point()
109
word, pos = self.getCurrentWord(entry)
110
result = self.tabComplete(word)
112
#If there are multiple potential matches, then we spit
113
#them out and don't insert a tab, so the user can type
114
#a couple more characters and try completing again.
117
self.output.insert_defaults(nick + " ")
118
self.output.insert_defaults('\n')
121
elif result: #only happens when len(result) == 1
123
entry.delete_text(*pos)
124
entry.set_position(pos[0])
125
entry.insert_defaults(result[0])
126
entry.set_position(oldpos+len(result[0])-len(word))
131
entry.emit_stop_by_name("key_press_event")
134
def tabComplete(self, word):
135
"""Override me to implement tab completion for your window,
136
I should return a list of potential matches."""
139
def getCurrentWord(self, entry):
140
i = entry.get_point()
141
text = entry.get_chars(0,-1)
142
word = re.split(r'\s', text)[-1]
143
start = string.rfind(text, word)
144
end = start+len(word)
145
return (word, (start, end))
149
self.entry.delete_text(0, -1)
150
self.histpos = self.histpos - 1
151
self.entry.insert_defaults(self.history[self.histpos])
152
self.entry.set_position(0)
154
def historyDown(self):
155
if self.histpos < len(self.history) - 1:
156
self.histpos = self.histpos + 1
157
self.entry.delete_text(0, -1)
158
self.entry.insert_defaults(self.history[self.histpos])
159
elif self.histpos == len(self.history) - 1:
160
self.histpos = self.histpos + 1
161
self.entry.delete_text(0, -1)
164
def createMethodDict(o, d=None):
167
for base in reflect.allYourBase(o.__class__) + [o.__class__]:
170
#print 'd[%s] = %s' % (n, m)
175
def autoConnectMethods(*objs):
178
createMethodDict(obj, o)
179
# print 'connecting', o
180
objs[0].xml.signal_autoconnect(o)
184
def openGlade(*args, **kwargs):
185
# print "opening glade file"
186
r = GladeXML(*args, **kwargs)
190
raise IOError("Couldn't open Glade XML: %s; %s" % (args, kwargs))