numbered bullets not incrementing

Hi all,

Again with the richtextctrl.

I have this code bit, that is then applied to the current paragraph.

def OnNumList(self, event):
     def numlist(attr):
         attr.SetFlags(attr.GetFlags() |rt.TEXT_ATTR_BULLET_STYLE |
                       rt.TEXT_ATTR_LEFT_INDENT | rt.TEXT_ATTR_PARAGRAPH)
         attr.SetBulletStyle(rt.TEXT_ATTR_BULLET_STYLE_ALIGN_LEFT |
                        rt.TEXT_ATTR_BULLET_STYLE_ARABIC |
                        rt.TEXT_ATTR_BULLET_STYLE_PERIOD)
         attr.SetLeftIndent(20,100)
         return attr

     tb = event.GetEventObject()
     toggled = tb.GetToolState(event.GetId())
     tb.ToggleTool(self.toolids['text list bullets'], False)
     if toggled:
         self.ApplyNewParaAttr(numlist)
     else:
         self.ApplyNewParaAttr(self.listoff)

Basically self.ApplyNowParaAttr just applies the style to the current paragraphs in range.

The strange thing here is that two days ago this would number properly, and then I might have changed something, but I did not think so, and it now will not increment the numbers for the list.

I am going to make a workaround to make this work, but can anyone see what setting I am missing? Because I am sure it is hiding in broad daylight. :expressionless:

Thanks in advance for any help,

Rohan

Sorry about the former postings.

I have read the how to ask for help, so this should make things easier.

wxversion = '2.8.9.1 (gtk2-unicode)'

python = 2.5.2 on Ubuntu Hardy Heron

I have minimized the code as much as possible and still have it working below. Basically the problem is that the numbered list button does give a numbered bullet. But the numbers do not increment.

To work around this I have tried binding another method to wx.EVT_COMMAND_ENTER, and have that increment the counter when a new paragraph is created. But this method is never being called as it never prints to standard out.

I have also tried binding rt.EVT_RICHTEXT_RETURN, but also no luck. And what is driving me crazy is that the numbering was working the other day, but now is not.

Any help would be much appreciated, as I am starting to get desperate, and it is costing huge amounts of time.

Thanks in advance,

Rohan

Here is the runnable code (at least on my system) :wink:

···

-------------------------------------------------------------------------
#!/usr/bin/env python

import wx
import wx.richtext as rt
import os.path as p

class NumList(object):
  def __init__(self, image_path, frame, toggle=False, handler=None):
    self.curnum = 1
    self.path = image_path
    self.name = 'blah'
    self.frame = frame
    self.id = wx.NewId()
    self.handler = handler
# SimpleTool.__init__(self, image_path, frame, text, status_text,
# toggle, handler, update, id)

  @property
  def image(self):
    path = p.join(p.dirname(__file__), 'images', self.path)
    return wx.Bitmap(path, wx.BITMAP_TYPE_PNG)

  def add(self, toolbar):
    toolbar.AddSimpleTool(self.id, self.image, isToggle=True)
    self.frame.Bind(wx.EVT_TOOL, self.handler, id=self.id)
    self.frame.Bind(wx.EVT_COMMAND_ENTER, self.next_number)
    #rt.EVT_RICHTEXT_RETURN

  def next_number(self, event):
    """ Increment the number for the bullet if there is a number
    bullet"""
    print "Possibly incrementing bullet number"
    rtc = self.frame.rtc
    attr = self.frame.GetCurStyle(self.frame.rtc)
    if attr.HasBulletNumber():
      print "Incrementing bullet number"
      attr.SetBulletNumber(self.curnum)
      self.curnum += 1

class RichFrame(wx.Frame):
  def __init__(self,parent,id,title='',text=None,):
    wx.Frame.__init__(self,parent,id,title,size=(800,600))
    self.rtc = rt.RichTextCtrl(self, -1)
    self.statusbar = self.CreateStatusBar()
    self.toolbar = self.CreateToolBar()

    n = NumList('text_list_numbers.png', self, toggle=True,
            handler=self.OnNumList)
    n.add(self.toolbar)

  def OnNumList(self, event):
    def numlist(attr):
      attr.SetFlags(attr.GetFlags() |rt.TEXT_ATTR_BULLET_STYLE | rt.TEXT_ATTR_LEFT_INDENT | rt.TEXT_ATTR_PARAGRAPH )
      attr.SetBulletStyle(rt.TEXT_ATTR_BULLET_STYLE_ALIGN_LEFT

rt.TEXT_ATTR_BULLET_STYLE_ARABIC |rt.TEXT_ATTR_BULLET_STYLE_PERIOD)

      attr.SetLeftIndent(20,100)
      attr.SetBulletNumber(1)
      return attr
    #import pdb; pdb.set_trace()
    tb = event.GetEventObject()
      toggled = tb.GetToolState(event.GetId())
    button = tb.FindControl(event.GetId())
    print button
    if button is not None:
      button.curnum = 1
# tb.ToggleTool(self.toolids['text list bullets'], False)
    if toggled:
      self.ApplyNewParaAttr(numlist)
    else:
      self.ApplyNewParaAttr(self.listoff)
    
  def OnUpdateNumList(self, event):
    pass

  def listoff(self, attr):
    attr.SetFlags(attr.GetFlags() |rt.TEXT_ATTR_LEFT_INDENT | rt.TEXT_ATTR_PARAGRAPH | rt.TEXT_ATTR_BULLET_STYLE)
    attr.SetBulletStyle(rt.TEXT_ATTR_BULLET_STYLE_NONE)
    attr.SetLeftIndent(0)
    return attr

  def para_borders(self, point):
    """ Grab the boundaries of the paragraph that point is sitting
    in, and return the (beginning, end) points"""
    rtc = self.rtc
    rtc.SetInsertionPoint(point)
    rtc.MoveToParagraphStart()
    bp = rtc.GetInsertionPoint()
    rtc.MoveToParagraphEnd()
    ep = rtc.GetInsertionPoint()
    return (bp, ep)

  def ApplyNewParaAttr(self, func):
    """ This takes a function that expects to be handed a
    rt.TextAttrEx object, which it then manipulates as needed, and
    then the attributes are applied to the current paragragh or all
    paragraghs is the selection"""
    ##### NOTE:At this moment this does not handle selections in
    ## more than one paragragh properly
    # Basic Features
    rtc = self.rtc
    ip = rtc.GetInsertionPoint()
    attr = rt.TextAttrEx()
    bp,ep = self.para_borders(ip)
    used_space_hack = False
    if bp == ep:
      rtc.WriteText(" ")
      used_space_hack = True
      bp,ep = self.para_borders(ip)
    r = rt.RichTextRange(bp, ep)
    # This needs to handle multiple paragraghs in a selection properly.
    if rtc.HasSelection():
      r = rtc.GetSelection()
    if rtc.GetStyle(ip, attr):
      attr = func(attr)
    # Apply the style
    rtc.SetFocus()
    rtc.SetInsertionPoint(ip)
    rtc.SetStyle(r, attr)
    if used_space_hack is True:
      rtc.Delete(rt.RichTextRange(bp, ep))

class RichApp(wx.App):
  def __init__(self, redirect=False, filename=None,
           style=wx.DEFAULT_FRAME_STYLE, text=None):
    self.text = text
    wx.App.__init__(self, redirect, filename)

  def OnInit(self):
    self.frame = RichFrame(parent=None, id=-1, title="Rich Editor",
                    text=self.text)
    self.frame.Show()
    self.SetTopWindow(self.frame)
    return True

if __name__ == '__main__':
  text = "This is a test of the first and second things to be seen"
  app = RichApp(text=text)
  app.MainLoop()

Rohan wrote:

Sorry about the former postings.

I have read the how to ask for help, so this should make things easier.

wxversion = '2.8.9.1 (gtk2-unicode)'

python = 2.5.2 on Ubuntu Hardy Heron

I have minimized the code as much as possible and still have it working below. Basically the problem is that the numbered list button does give a numbered bullet. But the numbers do not increment.

To work around this I have tried binding another method to wx.EVT_COMMAND_ENTER, and have that increment the counter when a new paragraph is created. But this method is never being called as it never prints to standard out.

I see that the C++ richtext sample has the same problem, so I expect that it's a RichTextCtrl problem, not your problem. Please create a bug ticket about this.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn wrote:

Rohan wrote:

Sorry about the former postings.

I have read the how to ask for help, so this should make things easier.

wxversion = '2.8.9.1 (gtk2-unicode)'

python = 2.5.2 on Ubuntu Hardy Heron

I have minimized the code as much as possible and still have it working below. Basically the problem is that the numbered list button does give a numbered bullet. But the numbers do not increment.

To work around this I have tried binding another method to wx.EVT_COMMAND_ENTER, and have that increment the counter when a new paragraph is created. But this method is never being called as it never prints to standard out.

I see that the C++ richtext sample has the same problem, so I expect that it''s a RichTextCtrl problem, not your problem. Please create a bug ticket about this.

Thanks for the info, I had not thought to check the demo.

Funny that it had worked before, but maybe an update by ubuntu to a
new minor version broke it.

I am creating a bug fix for it now.

As I need the feature now, and for anyone else with this problem I
thought I would include the code below to workaround the incrementing
problem, and basically implement the functionality in python. Not
difficult, but might save someone some time later. This is a working
version in ubuntu hardy heron. Please excuse the wrapping problems, it
seems that thunderbird can be quite zealous with its linewrapping.

Rohan

···

---------------------------------------------------------------------
#!/usr/bin/env python

import wx
import wx.richtext as rt
import os.path as p

class NumList(object):
  def __init__(self, image_path, frame, toggle=False, handler=None):
    self.path = image_path
    self.name = 'blah'
    self.frame = frame
    self.id = wx.NewId()
    self.handler = handler

  @property
  def image(self):
    path = p.join(p.dirname(__file__), 'images', self.path)
    return wx.Bitmap(path, wx.BITMAP_TYPE_PNG)

  def add(self, toolbar):
    toolbar.AddSimpleTool(self.id, self.image, isToggle=True)
    self.frame.Bind(wx.EVT_TOOL, self.handler, id=self.id)
    self.frame.rtc.Bind(rt.EVT_RICHTEXT_RETURN, self.next_number)
    #rt.EVT_RICHTEXT_RETURN wx.EVT_COMMAND_ENTER

  def next_number(self, event):
    """ Increment the number for the bullet if there is a number
    bullet"""
    num = self.frame.bulletnumber
    def incr(attr):
      if num:
        print "Incrementing bullet number"
        attr.SetBulletNumber(num)
      return attr
    print "Possibly incrementing bullet number"
    if self.frame.bulletnumber:
      self.frame.ApplyNewParaAttr(incr)
      self.frame.bulletnumber += 1
      
class RichFrame(wx.Frame):
  def __init__(self,parent,id,title='',text=None,):
    wx.Frame.__init__(self,parent,id,title,size=(800,600))
    self.rtc = rt.RichTextCtrl(self, -1)
    self.statusbar = self.CreateStatusBar()
    self.toolbar = self.CreateToolBar()
    self.bulletnumber = False
    n = NumList('text_list_numbers.png', self, toggle=True,
            handler=self.OnNumList)
    n.add(self.toolbar)

  def OnNumList(self, event):
    tb = event.GetEventObject()
      toggled = tb.GetToolState(event.GetId())
    if toggled:
      self.bulletnumber = 1
    num = self.bulletnumber
    def numlist(attr):
      attr.SetFlags(attr.GetFlags() |rt.TEXT_ATTR_BULLET_STYLE |
                rt.TEXT_ATTR_LEFT_INDENT | rt.TEXT_ATTR_PARAGRAPH )
      attr.SetBulletStyle(rt.TEXT_ATTR_BULLET_STYLE_ALIGN_LEFT |
                    rt.TEXT_ATTR_BULLET_STYLE_ARABIC |
                    rt.TEXT_ATTR_BULLET_STYLE_PERIOD)
      attr.SetLeftIndent(20,100)
      attr.SetBulletNumber(num)
      return attr

    if toggled:
      self.ApplyNewParaAttr(numlist)
      self.bulletnumber += 1
    else:
      self.ApplyNewParaAttr(self.listoff)
      self.bulletnumber = False
    
  def OnUpdateNumList(self, event):
    pass

  def listoff(self, attr):
    attr.SetFlags(attr.GetFlags() |rt.TEXT_ATTR_LEFT_INDENT |
              rt.TEXT_ATTR_PARAGRAPH | rt.TEXT_ATTR_BULLET_STYLE ^
              rt.TEXT_ATTR_BULLET_STYLE_ARABIC)
    attr.SetBulletStyle(rt.TEXT_ATTR_BULLET_STYLE_NONE)
    attr.SetLeftIndent(0)
    return attr

  def para_borders(self, point):
    """ Grab the boundaries of the paragraph that point is sitting
    in, and return the (beginning, end) points"""
    rtc = self.rtc
    rtc.SetInsertionPoint(point)
    rtc.MoveToParagraphStart()
    bp = rtc.GetInsertionPoint()
    rtc.MoveToParagraphEnd()
    ep = rtc.GetInsertionPoint()
    return (bp, ep)

  def ApplyNewParaAttr(self, func):
    """ This takes a function that expects to be handed a
    rt.TextAttrEx object, which it then manipulates as needed, and
    then the attributes are applied to the current paragragh or all
    paragraghs is the selection"""
    ##### NOTE:At this moment this does not handle selections in
    ## more than one paragragh properly
    # Basic Features
    rtc = self.rtc
    ip = rtc.GetInsertionPoint()
    attr = rt.TextAttrEx()
    bp,ep = self.para_borders(ip)
    used_space_hack = False
    if bp == ep:
      rtc.WriteText(" ")
      used_space_hack = True
      bp,ep = self.para_borders(ip)
    r = rt.RichTextRange(bp, ep)
    # This needs to handle multiple paragraghs in a selection properly.
    if rtc.HasSelection():
      r = rtc.GetSelection()
    if rtc.GetStyle(ip, attr):
      attr = func(attr)
    # Apply the style
    rtc.SetFocus()
    rtc.SetInsertionPoint(ip)
    rtc.SetStyle(r, attr)
    if used_space_hack is True:
      rtc.Delete(rt.RichTextRange(bp, ep))

  def GetCurStyle(self, rtc, ):
    attr = rt.TextAttrEx()
    attr.SetFlags(rt.TEXT_ATTR_FONT)
    cursor_at = rtc.GetInsertionPoint()
    if rtc.GetStyle(cursor_at, attr):
      return attr

class RichApp(wx.App):
  def __init__(self, redirect=False, filename=None,
           style=wx.DEFAULT_FRAME_STYLE, text=None):
    self.text = text
    wx.App.__init__(self, redirect, filename)

  def OnInit(self):
    self.frame = RichFrame(parent=None, id=-1, title="Rich Editor",
                    text=self.text)
    self.frame.Show()
    self.SetTopWindow(self.frame)
    return True

if __name__ == '__main__':
  text = "This is a test of the first and second things to be seen"
  app = RichApp(text=text)
  app.MainLoop()