Center The Cursor On An Empty Center Justified Line In TextView

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Center The Cursor On An Empty Center Justified Line In TextView

mikkx Johnson
In every word processor I've used, if you hit the enter key and create a new line, then change the justification to center, the cursor will go to the center of the line.

TextView does not do this out of the box.  Instead, it stays left justified, until you begin typing, (unless I'm misunderstanding something).

My application depends upon this simple standard feature. (I'm doing a screen writing app which auto-formats as you type and when it centers you know you are about to type dialogue.)

The following class is my test case to get this justification on empty lines to work.  I would greatly appreciate any help to move things forward.  My project will not be possible unless the behavior is achieved.

<code>

import gtk, pango

NEW_LINE_KEY = 65293

# TaggedCursorTextView attempts to only add one feature to gtk.TextView: make the cursor dynamically settable
# to a list of tags.  This forces the current text being typed to the set of tags set.

class TaggedCursorTextView(gtk.TextView):
    def __init__(self):
        gtk.TextView.__init__(self)
       
        # Create buffer variable that point to it's internal TextBuffer.
        self.buffer = self.get_buffer()
       
        # Listen for the changed event. (User types, deletes or pastes text, etc.)
        self.connect("key-release-event", self.on_key_release_event)
       
        # What ever tags are place in here determines the text attributes (font type, bold, etc.)
        # That is being typed by the user at any given moment.
        # Default should be kept empty, no styles.

        self.styleTags = [] # Tags that do not have the primary purpose of affecting the layout of text, i.e., colors, bold, font size, etc.
        self.formatTags = [] # Tags that have the primary purpose of affecting text layout on the page, i.e., indentation, margins, justificaiton, etc.
       
        self.handlerID = None
       
        self.cycleTest = 0
       
    def addTags(self, tagList):
        # Create the Tags and add them to the Tag Table.  Ignores duplicate tag names.
        for tag in tagList:
            newTag = gtk.TextTag(name=tag[0])
            textTable = self.buffer.get_tag_table()
            tagNameFound = textTable.lookup(tag[0])
            if not tagNameFound:
                newTag.set_property(tag[1], tag[2])
                textTable.add(newTag)
               
    def removeTags(self, tagNameList):
        pass
               
    def setStyleTags(self, tagList):
        self.styleTags = tagList
       
    def setFormatTags(self, tagList):
        self.formatTags = tagList
   
    def on_key_release_event(self, widget, event):
        self.handlerID = self.buffer.connect("changed", self.on_change_event)
       
        if event == None:
            return
       
        if event.keyval != NEW_LINE_KEY:
            pass
            # Put custom handling code here.
       
    ############################# testing code remove for general usuage ############################
        #    if self.cycleTest == 0:
        #        self.setStyleTags([])
        #        self.setFormatTags(["Center"])
        #       
        #    elif self.cycleTest == 1:
        #        self.setStyleTags([])
        #        self.setFormatTags(["Center"])
        #       
        #    elif self.cycleTest == 2:
        #        self.setStyleTags([])
        #        self.setFormatTags(["Center"])
        #else:
        #    self.cycleTest += 1
        #   
        #if self.cycleTest > 2:
        #    self.cycleTest = 0
    ############################# end of testing code ###############################################
       
    def on_change_event(self, widget):
        """This method updates the last character with styleTags and formats the line with formatTags."""
        self.buffer.disconnect(self.handlerID)
        print "on change"

        # Adds the style for the char just typed in.
        ##########################################################################################
        styleEndIter = self.buffer.get_end_iter()
        offset = styleEndIter.get_offset() - 1
        styleStartIter = self.buffer.get_iter_at_offset(offset)

        for tag in self.styleTags:
            self.buffer.apply_tag_by_name(tag, styleStartIter, styleEndIter)
        ##########################################################################################


        # Formats the line in which the entered char resides.
        ##########################################################################################
        startFormatIter, endFormatIter = self.formatRange()
       
        formatBegin = startFormatIter.get_offset()
        formatEnd = endFormatIter.get_offset()
       
        if formatBegin == formatEnd:
            print "\nformat range before", startFormatIter.get_offset(), endFormatIter.get_offset()
               
        startFormatIter, endFormatIter = self.formatRange()
       
        if formatBegin == formatEnd:
            print "format range after", startFormatIter.get_offset(), endFormatIter.get_offset()

        # Apply the format tags last.  Apply to entire line in which the char resides.
        for tag in self.formatTags:
            self.buffer.apply_tag_by_name(tag, startFormatIter, endFormatIter)
           
        #self.emit("key-release-event", gtk.gdk.Event(gtk.gdk.KEY_RELEASE))
        ##########################################################################################

        #print self.styleTags, self.cycleTest

    def formatRange(self):
        cursorPosition = self.buffer.get_property("cursor-position")
        cursorIter = self.buffer.get_iter_at_offset(cursorPosition)
        currentLine = cursorIter.get_line()
        firstIndexOfCurrentLine = self.buffer.get_iter_at_line(currentLine)

        lineEndIter = cursorIter.forward_to_line_end()
       
        if not lineEndIter:
            cursorPosition = self.buffer.get_property("cursor-position")
            cursorIter = self.buffer.get_iter_at_offset(cursorPosition)
            cursorIter.forward_to_end()
            offset = cursorIter.get_offset()
        else:
            offset = lineEndIter.get_offset()

        endIter = self.buffer.get_iter_at_offset(offset)
       
        return [firstIndexOfCurrentLine, endIter]

class TaggedCurserTextViewTestWindow(gtk.Window):

    def __init__(self):
        gtk.Window.__init__(self)
        self.connect( "destroy", lambda *w: gtk.main_quit() )

        self.set_default_size(280, 80)

        # Create a TaggedCursorTextView.
        tctv = TaggedCursorTextView()
       
        # Add some cursors tags that will be used at some point later in the app.
        # Each tag element list is: [tag name, tag property, tag value]
        tagList = [["Italic", "style", pango.STYLE_ITALIC], ["Bold", "weight", pango.WEIGHT_BOLD], ["Center", "justification", gtk.JUSTIFY_CENTER]]
        tctv.addTags(tagList)

        # Use the Tag Names in a list to set the cursor tags.
        tctv.setStyleTags([])
        tctv.setFormatTags(["Center"])

        # Let's see what happens.
        self.add(tctv)
        tctv.grab_focus()
        self.set_position(gtk.WIN_POS_CENTER)
        self.show_all()

if __name__ == "__main__":
    TaggedCurserTextViewTestWindow()
    gtk.main()

</code>

_______________________________________________
pygtk mailing list   [hidden email]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/