keyboard macros for the wx.StyledTextControl

import wx
import wx.stc

class MyStc(wx.stc.StyledTextCtrl):
def __init__(self, parent, id):
  wx.stc.StyledTextCtrl.__init__(self, parent, id)
  
  self.Bind (wx.EVT_CHAR, self.OnChar)
  self.Bind (wx.EVT_KEY_DOWN, self.OnKeyDown)
  
  self.macro_record = False
  self.macro_events_collected =
  self.macro_play_back = False

def Append (self, event):
  self.macro_events_collected.append()
  self.macro_events_collected[-1].append (event.m_altDown)
  self.macro_events_collected[-1].append (event.m_controlDown)
  self.macro_events_collected[-1].append (event.m_keyCode)
  self.macro_events_collected[-1].append (event.m_metaDown)
  self.macro_events_collected[-1].append (event.m_rawCode)
  self.macro_events_collected[-1].append (event.m_rawFlags)
  self.macro_events_collected[-1].append (event.m_scanCode)
  self.macro_events_collected[-1].append (event.m_shiftDown)
  self.macro_events_collected[-1].append (event.m_x)
  self.macro_events_collected[-1].append (event.m_y)

I know it is terribly pretentious of me to comment on code style, but I'm wondering why you didn't just write:

    def Append (self, event):
        self.macro_events_collected.append( event )

and then replace this big section in OnChar:

        for i in range (len(self.macro_events_collected)):
          evt = wx.KeyEvent()
          evt.m_altDown = self.macro_events_collected[i][0]
          evt.m_controlDown = self.macro_events_collected[i][1]
          evt.m_keyCode = self.macro_events_collected[i][2]
          evt.m_metaDown = self.macro_events_collected[i][3]
          evt.m_rawCode = self.macro_events_collected[i][4]
          evt.m_rawFlags = self.macro_events_collected[i][5]
          evt.m_scanCode = self.macro_events_collected[i][6]
          evt.m_shiftDown = self.macro_events_collected[i][7]
          evt.m_x = self.macro_events_collected[i][8]
          evt.m_y = self.macro_events_collected[i][9]
          self.GetEventHandler().ProcessEvent(evt)

with:
                for evt in self.macro_events_collected:
                    self.GetEventHandler().ProcessEvent( evt )

Seems like that would be a more reliable way to make sure you're recording/replaying the entire event record.

···

On Wed, 22 Sep 2004 14:30:34 +0200, Franz Steinhäusler <franz.steinhaeusler@gmx.at> wrote:

--
- Tim Roberts, timr@probo.com
  Providenza & Boekelheide, Inc.

Tim Roberts writes:

                for evt in self.macro_events_collected:
                    self.GetEventHandler().ProcessEvent( evt
)

Seems like that would be a more reliable way to make sure
you're recording/replaying the entire event record.

I'm totally jumping in here, but if I understand the original
issue and your recommendation correctly, you can't just save
collected events for replay later like that because the
underlying c++ event object will go away after all handlers
have had their whack at it, leaving the python event object in
an undefined state[1]. You do need to save the interesting
parts of the event in your handler, while the c++ event object
is still alive.

[1] Accessing the evt later won't give you the dreaded
PyDeadObjectError() like it does for windows that have gone
away, but the return values for the various functions like
GetX() and GetKeyCode() won't make sense. Where GetKeyCode()
returned 32 in the event handler, later on it may return -64012
or something.

···

--
Paul McNett
Independent Software Consultant
http://www.paulmcnett.com

because events are C++ objects, as Robin Dunn explained,
and destroyed afterwards.
He suggested to store type, keycode and shift state.
I tried to save all, so it was accurate.
My first approach was exactly what you would suggest.

···

On Thu, 23 Sep 2004 08:48:44 -0700, Tim Roberts <timr@probo.com> wrote:

On Wed, 22 Sep 2004 14:30:34 +0200, Franz Steinhäusler ><franz.steinhaeusler@gmx.at> wrote:

I'm wondering why you didn't just write:

   def Append (self, event):
       self.macro_events_collected.append( event )
[...]

--
Franz Steinhäusler

DrPython (Project Developer)
http://drpython.sourceforge.net/

Thanks for your answer,

but I'm still not more shrewder than before :slight_smile:

Could it be that not EVT_CHAR is the right message to repost,
but EVT_KEY_DOWN or other.

Or is the whole approach false?

If asked a similar question in the thread "Hand down events from textctrl to listctrl"

I suspect, there is a basic problem in the event that I didn't grasp until now.

I would be very glad, if someone could spot a light on this "dark" matter and
help me to comprehend this "complicated" event stories better :slight_smile:

···

On Thu, 23 Sep 2004 09:06:39 -0700, Paul McNett <p@ulmcnett.com> wrote:

Tim Roberts writes:

                for evt in self.macro_events_collected:
                    self.GetEventHandler().ProcessEvent( evt
)

Seems like that would be a more reliable way to make sure
you're recording/replaying the entire event record.

I'm totally jumping in here, but if I understand the original
issue and your recommendation correctly, you can't just save
collected events for replay later like that because the
underlying c++ event object will go away after all handlers
have had their whack at it, leaving the python event object in
an undefined state[1]. You do need to save the interesting
parts of the event in your handler, while the c++ event object
is still alive.

[1] Accessing the evt later won't give you the dreaded
PyDeadObjectError() like it does for windows that have gone
away, but the return values for the various functions like
GetX() and GetKeyCode() won't make sense. Where GetKeyCode()
returned 32 in the event handler, later on it may return -64012
or something.

--
Franz Steinhäusler

DrPython (Project Developer)
http://drpython.sourceforge.net/