[IronLute-CVS] ironlute/gtk IronLuteGtk.py,1.2,1.3 gtkmenubar.py,1.2,1.3 handletag.py,1.2,1.3 outlin
Status: Pre-Alpha
Brought to you by:
thejerf
From: Jeremy B. <th...@us...> - 2005-05-07 20:12:02
|
Update of /cvsroot/ironlute/ironlute/gtk In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20093 Modified Files: IronLuteGtk.py gtkmenubar.py handletag.py outlinewidget.py Log Message: General commit, just to back things up. Index: gtkmenubar.py =================================================================== RCS file: /cvsroot/ironlute/ironlute/gtk/gtkmenubar.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** gtkmenubar.py 4 May 2005 20:32:03 -0000 1.2 --- gtkmenubar.py 7 May 2005 20:11:52 -0000 1.3 *************** *** 86,96 **** None, state = True): """See command.py/CommandMenu.""" ! item = gtk.MenuItem(command.name) ! # FIXME: Add a right-aligned label for the accelstring item.set_sensitive(state) item.show() ! def doCommand(): self.outlineWidget.doCommand(command, self) item.connect("activate", doCommand) --- 86,110 ---- None, state = True): """See command.py/CommandMenu.""" + item = gtk.MenuItem() ! hbox = gtk.HBox() ! l = gtk.Label(command.name) ! hbox.pack_start(l, False, False, 10) ! l.show() ! l = gtk.Label() ! hbox.pack_start(l, True, True, 0) ! l.show() ! if accelString: ! accel = gtk.Label("test") ! hbox.pack_end(accel, False, False, 0) ! accel.show() ! hbox.show() ! item.add(hbox) ! ! # FIXME: Accelerator strings item.set_sensitive(state) item.show() ! def doCommand(source): self.outlineWidget.doCommand(command, self) item.connect("activate", doCommand) Index: IronLuteGtk.py =================================================================== RCS file: /cvsroot/ironlute/ironlute/gtk/IronLuteGtk.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** IronLuteGtk.py 4 May 2005 20:32:03 -0000 1.2 --- IronLuteGtk.py 7 May 2005 20:11:52 -0000 1.3 *************** *** 1,2 **** --- 1,4 ---- + + # NEXT: Connect the events to the outline. import pygtk pygtk.require("2.0") *************** *** 29,33 **** def GtkEndApp(*args, **kwargs): - # FIXME: What insta-kills the app? gtk.main_quit() --- 31,34 ---- *************** *** 67,72 **** self.menubar.show() self.outlineWidget.menubar.checkActive() ! self.vbox.add(self.menubar) self.vbox.add(self.sw) --- 68,74 ---- self.menubar.show() self.outlineWidget.menubar.checkActive() + self.outlineWidget.grab_focus() ! self.vbox.pack_start(self.menubar, False) self.vbox.add(self.sw) *************** *** 82,90 **** 'Cheesy poofs', 'tart and tangy']*20) rootHandle = document.getRootHandle() ! if __name__ == "__main__": GtkStartInit() myWidget = IronLuteGtk(rootHandle) GtkFinishInit() --- 84,94 ---- 'Cheesy poofs', 'tart and tangy']*20) rootHandle = document.getRootHandle() ! if __name__ == "__main__": GtkStartInit() + #import profile myWidget = IronLuteGtk(rootHandle) GtkFinishInit() + Index: outlinewidget.py =================================================================== RCS file: /cvsroot/ironlute/ironlute/gtk/outlinewidget.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** outlinewidget.py 4 May 2005 20:32:03 -0000 1.2 --- outlinewidget.py 7 May 2005 20:11:52 -0000 1.3 *************** *** 1,2 **** --- 1,9 ---- + """To document: + + * Change philosophy. (I think that I have it covered, but I might be wrong. + """ + + # Note: 0x416 is a russian letter, good for unicode testing + import gtk *************** *** 29,50 **** self.handleToTag = {} self.gtkTagToHandleTag = {} self.nameToTag = {} self.rootHandle = rootHandle self.bindRootHandle() self.connect("key-press-event", self.keypress) ! self.connect("move-cursor", self.cursorMove) buffer = property(gtk.TextView.get_buffer) def keypress(self, source, event): ! print event.keyval - def cursorMove(self, source, step, count, extendSelection, data = None): - print "Step:", step - print "count", count - print "sel", extendSelection - # We have to check the dynamic menus here self.menubar.checkActive() --- 36,223 ---- self.handleToTag = {} + # FIXME: This to satisfy guiSupport + self.handlesToWidgets = self.handleToTag self.gtkTagToHandleTag = {} self.nameToTag = {} self.rootHandle = rootHandle + self.rootHandle.node.getDocument().subscribe(self) self.bindRootHandle() + it = self.buffer.get_start_iter() + it.forward_char() + self.insert = it + self.selection_bound = it + + # event handlers self.connect("key-press-event", self.keypress) ! self.connect_after("move-cursor", self.cursorMove) ! self.connect_after("select-all", self.selectAll) ! self.buffer.connect("changed", self.changed) ! self.buffer.connect("insert-text", self.insertText) ! self.connect("button-release-event", self.clickFix) ! # This handle mouse-drag selection ! self.connect_after("motion-notify-event", self.selectionEvent) ! ! def changed(self, *args): ! """This handles the notification that something in the buffer ! changed.""" ! # If the change is user initiated, it has to be near the ! # cursor. ! self.getCurrentHandleTag() ! ! def selectionEvent(self, source, event): ! """Handle the mouse-notify-event, if the user is selecting ! with the mouse. ! ! This validates the user can't select over node boundaries. ! ! During selection, the selection_bound remains stationary, and ! the insert bound moves. If the insert bound changes lines, or ! grows to include zero, we ban the motion.""" ! ! insert = self.insert ! selection_bound = self.selection_bound ! selection_line = selection_bound.get_line() ! insert_line = insert.get_line() ! ! if insert_line < selection_line: ! # Set the insertion point to the beginning of the line + ! # 1, ban motion ! new_insert = selection_bound.copy() ! new_insert.backward_chars(new_insert.get_line_offset() - 1) ! self.insert = new_insert ! ! # FIXME: last line ! if insert_line > selection_line: ! # Set the insertion point to the end of the line, ban ! # motion ! new_insert = selection_bound.copy() ! new_insert.forward_line() ! new_insert.backward_char() ! self.insert = new_insert ! ! if insert.get_line_offset() == 0: ! print "he" ! insert = insert.copy() ! insert.forward_char() ! self.insert = insert ! ! def fixCursor(self): ! """Validate the cursor is not on the wrong side of the node ! indicator.""" ! insert = self.insert ! if insert.get_line_offset() == 0: ! insert.forward_char() ! self.insert = insert ! self.selection_bound = insert ! ! def clickFix(self, source, event): ! if self.insert.equal(self.selection_bound): ! self.fixCursor() ! ! ! def insertText(self, source, pos, text, charCount): ! pass ! ! def notifyHandleEvent(self, event): ! """Handle events coming from the outline document.""" ! print event ! handle = event.sourceHandle ! # If the source is invisible, no problem. ! if not self.isVisible(handle): ! return ! ! node = event.source ! eventName = event.name ! if name == "child_removed": ! # The node is about to be gone, remove the handletag ! handleTag = self.handleToTag[handle] ! handleTag.destroy() ! return ! ! if name == "child_added": ! # There is a new node in town, add the handle tag for the ! # new handle. It gets inserted right in front of the next ! # handle, or at the end if there isn't one ! newPosIter = self.buffer.get_end_iter() ! try: ! handleWalker = self.handleWalkerForward(handle) ! handleWalker.next() # skip handle itself ! nextHandle, _ = handleWalker.next() ! nextHandleTag = self.handleToTag[nextHandle] ! newPosIter = nextHandleTag.getMarkIter() ! except StopIteration: pass # use initial newPosIter ! ! lineNum = newPosIter.get_line() ! HandleTag(self, handle, newPosIter, lineNum) ! ! print "Unhandled event", name, ":", event.__dict__ buffer = property(gtk.TextView.get_buffer) def keypress(self, source, event): ! # CTRL-m does debugging magic ! if event.keyval == 109 and event.state & gtk.gdk.CONTROL_MASK: ! self.getCurrentHandleTag().magic() ! return True ! ! ! def selectAll(self, source, selecting): ! """For Select All events, we re-write it to select the entire ! text of the current paragraph.""" ! if selecting: ! self.currentHandleTag.selectAll() ! return True ! ! def cursorMove(self, source, step, count, extendSelection, data = ! None): ! """This validates the cursor stays in legal positions while ! being moved. Basically, you're not allowed to be on the left ! of the node indicator, and so we keep you moving past it if ! that's where you are. ! ! We also validate the dynamic menus against the current ! position.""" ! print "Move" ! currentOffset = self.insert.get_line_offset() ! ! if currentOffset != 0: ! self.menubar.checkActive() ! return ! ! # There are a lot of cases, but in each case, the answer is ! # the same: Go forward or backward one char ! # ! def goForward(): ! it.forward_char() ! self.insert = it ! self.selection_bound = it ! def goBackward(): ! it.backward_char() ! self.insert = it ! self.selection_bound = it ! ! it = self.insert ! ! # The basic goal here is to get the cursor out from behind ! # the node indicator in the fashion the user will expect ! # as if the node indicator wasn't part of the text widget. ! # The comments will confine themselves to describing the ! # situation, as the resolution should be obvious after that: ! if step == gtk.MOVEMENT_VISUAL_POSITIONS: # left/right ! if count == 1: # right ! # FIXME: What if this is the last line? ! goForward() ! if count == -1: # left ! if self.insert.get_line() == 0: ! # on the very first line ! goForward() ! else: ! goBackward() ! else: ! # for anything else, assume we jumped to the node, ! # go forward ! goForward() self.menubar.checkActive() *************** *** 135,139 **** return self.buffer.get_iter_at_mark(cursorMark) ! insert = property(getInsert) def getSelectionBound(self): --- 308,316 ---- return self.buffer.get_iter_at_mark(cursorMark) ! def setInsert(self, iter): ! """Sets the insertion point to the given iter.""" ! self.buffer.move_mark(self.buffer.get_insert(), iter) ! ! insert = property(getInsert, setInsert) def getSelectionBound(self): *************** *** 145,149 **** return self.buffer.get_iter_at_mark(selMark) ! selection_bound = property(getSelectionBound) def getCurrentHandleTag(self): --- 322,330 ---- return self.buffer.get_iter_at_mark(selMark) ! def setSelectionBound(self, iter): ! """Sets the selection bound to the given iter.""" ! self.buffer.move_mark(self.buffer.get_selection_bound(), iter) ! ! selection_bound = property(getSelectionBound, setSelectionBound) def getCurrentHandleTag(self): *************** *** 169,176 **** currentFocus = property(getCurrentFocus) ! def getSelection(self, sourceHandleTag = None): """Returns the current selection as an outline.Cursor.""" ! if sourceHandleTag is None: sourceHandleTag = self.currentHandleTag return outline.Cursor(sourceHandleTag.handle, --- 350,359 ---- currentFocus = property(getCurrentFocus) ! def getSelection(self, sourceHandle = None): """Returns the current selection as an outline.Cursor.""" ! if sourceHandle is None: sourceHandleTag = self.currentHandleTag + else: + sourceHandleTag = self.handleToTag[sourceHandle] return outline.Cursor(sourceHandleTag.handle, *************** *** 179,181 **** --- 362,374 ---- selection = property(getSelection) + + def ensureVisible(self, handle): + """Ensures the current handle tag is visible.""" + handleTag = self.handleToTag[handle] + self.scroll_to_iter(handleTag.getMarkIter(), 0) + def syncWithDocument(self, *args, **kwargs): + # This is a holdover from the *first* Tk implemenatation; + # I'm leaving it in for now because the replacement cost + # is high, but if nobody says they want Tk, this will go + return Index: handletag.py =================================================================== RCS file: /cvsroot/ironlute/ironlute/gtk/handletag.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** handletag.py 4 May 2005 20:32:03 -0000 1.2 --- handletag.py 7 May 2005 20:11:52 -0000 1.3 *************** *** 46,49 **** --- 46,50 ---- size = self.tag.get_property("size") pixels = pango.PIXELS(size) + pixels = 12 self.tag.set_property("left-margin", indent) *************** *** 83,86 **** --- 84,101 ---- lineIter, True) + + self.handle.subscribe(self) + + def magic(self): + """Magic is a method that is used for debugging. + + Magic is an easy way to debug the handle tags, by making them + do "something" on demand, via magic. Whatever may happen to be + committed at the moment is irrelevant. + + To activate magic, uncomment the 'magic' part of the keypress + handler in outlinewidget.""" + self.setText("Sophie is a good dog.") + def getState(self): """Retrieves the open/closed/nochildren state from the outline *************** *** 95,98 **** --- 110,151 ---- state = property(getState, setState) + def notifyHandleEvent(self, event): + """Handles an event emitted by a Handle. (OK, sorry about the + word confusion there... + + There are three basic events: child_removed, child_added, and + data_change. This directly handles the last, and indirectly + the first two.""" + print event + print self.getText() + + def unselect(self): + """Unselect the text. + + Strictly speaking, this is a holdover from the 'one widget per + handle' model, but it can live here.""" + self.outlineWidget.selection_bound = self.outlineWidget.insert + + def getCursorPos(self): + """Returns the index of the char the cursor appears before.""" + pos = self.outlineWidget.insert.get_line_offset() - 1 + return pos + + def setCursorPos(self, pos): + """Sets the position of the cursor within this tag, as a + function of characters after the node indicator.""" + it = self.getWidgetBeginIter() + it.forward_chars(pos + 1) + self.outlineWidget.insert = it + self.outlineWidget.selection_bound = it + + def updateNodeFromWidget(self): + """Copy the text from this widget into the node.""" + self.handle.node.setData(self.getText()) + + def updateWidgetFromNode(self): + """Copy the text in the node out to the widget.""" + self.setText(self.handle.node.getData()) + def toggle(self): """Toggles this node's expansion state, which just gets sent *************** *** 110,148 **** Note using this invalidates GtkTextIters.""" del self.outlineWidget.gtkTagToHandleTag[self.tag] ! begin = self.getMarkIter() # just after the indicator #begin.backward_char() # back up to get the indicator ! end = self.getMarkIter() end.forward_to_line_end() # end of line end.forward_char() # get the CRLF too self.buffer.delete(begin, end) ! self.outlineWidget.delete_mark(self.mark) ! def getMarkIter(self): return self.buffer.get_iter_at_mark(self.mark) def getLineNumber(self): """Returns the current line number of the handle.""" ! return self.getMarkIter().get_line() def bounds(self): ! """Returns an GtkTextIter covering from the beginning to the ! end of this widget. ! ! @param withIndicator If true, the range returned includes the ! indicator. Defaults to false. @returns TextIter, TextIter (tuple)""" ! return self.getMarkIter(), self.getMarkIter().forward_to_line_end() def clear(self): """Removes all text from this handle, leaving the indicator behind.""" ! self.buffer.delete(*self.bounds()) def getText(self): """Get this node as pure text.""" ! return self.buffer.get_text(*self.bounds()) def __str__(self): return "node_%s" % self.tagNumber --- 163,244 ---- Note using this invalidates GtkTextIters.""" del self.outlineWidget.gtkTagToHandleTag[self.tag] ! begin = self.getWidgetBeginIter() # just after the indicator #begin.backward_char() # back up to get the indicator ! end = self.getWidgetBeginIter() end.forward_to_line_end() # end of line end.forward_char() # get the CRLF too self.buffer.delete(begin, end) ! self.buffer.delete_mark(self.mark) ! self.handle.unsubscribe(self) ! ! def getWidgetBeginIter(self): return self.buffer.get_iter_at_mark(self.mark) + def getTextStartIter(self): + """Gets an iterator set at the start of the text. + + Do not try to assume that the node indicator is one after the + start of the node; I want to make it possible to have multiple + little widgets there if necessary.""" + it = self.getWidgetBeginIter() + it.forward_char() + return it + def getLineNumber(self): """Returns the current line number of the handle.""" ! return self.getWidgetBeginIter().get_line() def bounds(self): ! """Returns a pair of GtkTextIters covering from the beginning ! of the widget, including the node indicator, to the end of ! this widget. @returns TextIter, TextIter (tuple)""" ! bounds = self.getWidgetBeginIter(), self.getWidgetBeginIter() ! # FIXME: I end up doing this a lot, either factor or isolate ! bounds[1].forward_to_line_end() ! return bounds ! ! def textBounds(self): ! """Returns a pair of GtkTextIters covering the text in the ! widget, not including the node indicator. ! ! Note you should not try to skip over the indicator yourself, ! as it may or may not be confined to one char. ! ! @returns GtkTextIter, GtkTextIter (tuple)""" ! bounds = self.getTextStartIter(), self.getWidgetBeginIter() ! bounds[1].forward_to_line_end() ! return bounds def clear(self): """Removes all text from this handle, leaving the indicator behind.""" ! self.buffer.delete(*self.textBounds()) def getText(self): """Get this node as pure text.""" ! return self.buffer.get_text(*self.textBounds()) ! ! def setText(self, text): ! """Sets this node as pure text.""" ! self.clear() ! self.buffer.insert(self.getTextStartIter(), text) ! ! def setFocus(self): ! """Set the focus on the current widget, a do-nothing holdover ! from the multi-widget days.""" ! return def __str__(self): return "node_%s" % self.tagNumber + + def selectAll(self): + itBegin = self.getWidgetBeginIter() + itBegin.forward_char() + self.outlineWidget.selection_bound = itBegin + itEnd = self.getWidgetBeginIter() + itEnd.forward_to_line_end() + self.outlineWidget.insert = itEnd |