[wxPython] Capturing Cut/Copy/Paste in wxSTC

I'm looking for suggestions on the best way to always intercept Cut, Copy
and Paste events in a wxSTC (StyledTextControl). The method I have is
working, but depends partly on the accelerator keys in the menu. I want to
make sure I capture these events whether or not there is a menu, and no
matter what operating system. What's the best way to do that?

···

---
Patrick K. O'Brien
Orbtech
"I am, therefore I think."

I'm looking for suggestions on the best way to always intercept Cut, Copy
and Paste events in a wxSTC (StyledTextControl). The method I have is
working, but depends partly on the accelerator keys in the menu. I want to
make sure I capture these events whether or not there is a menu, and no
matter what operating system. What's the best way to do that?

You can intercept they keys in your EVT_KEY_DOWN handler. If you don't
event.Skip() then wxSTC won't get them.

···

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

How do I do this in a platform-neutral fashion? Am I to assume Ctrl-X,
Ctrl-C, Ctrl-V? Or are there wx constants that I should use instead? What
about drap and drop? Right now dragging a selection from wxSTC does a cut,
bypassing my Cut() method. I need absolute control in all circumstances.
I've read all the docs and previous messages and can't find anything that
makes this clear to me.

···

---
Patrick K. O'Brien
Orbtech
"I am, therefore I think."

-----Original Message-----
From: wxpython-users-admin@lists.wxwindows.org
[mailto:wxpython-users-admin@lists.wxwindows.org]On Behalf Of Robin Dunn
Sent: Tuesday, October 23, 2001 10:26 AM
To: wxpython-users@lists.wxwindows.org
Subject: Re: [wxPython] Capturing Cut/Copy/Paste in wxSTC

I'm looking for suggestions on the best way to always intercept Cut, Copy
and Paste events in a wxSTC (StyledTextControl). The method I have is
working, but depends partly on the accelerator keys in the menu. I want to
make sure I capture these events whether or not there is a menu, and no
matter what operating system. What's the best way to do that?

You can intercept they keys in your EVT_KEY_DOWN handler. If you don't
event.Skip() then wxSTC won't get them.

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

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwindows.org
http://lists.wxwindows.org/mailman/listinfo/wxpython-users

How do I do this in a platform-neutral fashion? Am I to assume Ctrl-X,
Ctrl-C, Ctrl-V?

I've seen an increasing number of *nix applications use these keys, so it's
probably pretty safe to use them. The Mac uses the same ascii chars in
confunction with the "apple" key instead of Control, but I'm not sure yet
how that will appear in wx.

Or are there wx constants that I should use instead?

There are standard menu IDs for them, but I don't see anything for keysyms.

What
about drap and drop? Right now dragging a selection from wxSTC does a cut,
bypassing my Cut() method.

(And holding down the Ctrl should turn it into a Copy.)

I need absolute control in all circumstances.
I've read all the docs and previous messages and can't find anything that
makes this clear to me.

Currently you would have to intercept the mouse events and check for the
dragging from the selected text range, and do your own drag/drop operations,
but I think I can make it easier... Would it work for you if there was an
event at the begining of the drag opperation that give you the default text
to be dragged and allow you to change it?

···

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

Robin Dunn wrote:

> How do I do this in a platform-neutral fashion? Am I to assume Ctrl-X,
> Ctrl-C, Ctrl-V?

I've seen an increasing number of *nix applications use these keys, so it's
probably pretty safe to use them.

Most of the *nix Apps that I use use Alt-C, Alt-V, etc., rather than
Ctrl. I can confirm that in Netscape, as I'm using that to write this.

-Chris

···

--
Christopher Barker,
Ph.D.
ChrisHBarker@home.net --- --- ---
http://members.home.net/barkerlohmann ---@@ -----@@ -----@@
                                   ------@@@ ------@@@ ------@@@
Oil Spill Modeling ------ @ ------ @ ------ @
Water Resources Engineering ------- --------- --------
Coastal and Fluvial Hydrodynamics --------------------------------------
------------------------------------------------------------------------

Aaaarrrrrggggghhhhhhhh!!!! (But not directed at you, Robin, I promise. And
not Neil, either.)

What I'd really like (I think) is:

EVT_STC_CUT()
EVT_STC_COPY()
EVT_STC_PASTE()

As long as the passed in functions were *always* called.

What I'm trying to do is make everything in the PyCrust shell prior to the
most recent prompt read only (no cut and no paste). Removing or inserting
text in any fashion messes me up. So I want my methods called no matter how
a cut or paste is initiated, whether from dragging or a menu operation or
some other program even. Here are the methods as they stand, in case they
help the discussion:

    def CanCut(self):
        """Return true if text is selected and can be cut."""
        if self.GetSelectionStart() != self.GetSelectionEnd() \
        and self.GetSelectionStart() >= self.prompt1Pos[1] \
        and self.GetSelectionEnd() >= self.prompt1Pos[1]:
            return 1
        else:
            return 0

    def CanCopy(self):
        """Return true if text is selected and can be copied."""
        return self.GetSelectionStart() != self.GetSelectionEnd()

    def CanPaste(self):
        """Return true if a paste should succeed."""
        if self.CanEdit() and wxStyledTextCtrl.CanPaste(self):
            return 1
        else:
            return 0

    def CanEdit(self):
        """Return true if editing should succeed."""
        return self.GetCurrentPos() >= self.prompt1Pos[1]

    def Cut(self):
        """Remove selection and place it on the clipboard."""
        if self.CanCut() and self.CanCopy():
            if self.AutoCompActive(): self.AutoCompCancel()
            if self.CallTipActive: self.CallTipCancel()
            self.Copy()
            self.ReplaceSelection('')

    def Copy(self):
        """Copy selection and place it on the clipboard."""
        if self.CanCopy():
            command = self.GetSelectedText()
            command = command.replace(os.linesep + sys.ps2, os.linesep)
            data = wxTextDataObject(command)
            if wxTheClipboard.Open():
                wxTheClipboard.SetData(data)
                wxTheClipboard.Close()

    def Paste(self):
        """Replace selection with clipboard contents."""
        if self.CanPaste():
            if wxTheClipboard.Open():
                if wxTheClipboard.IsSupported(wxDataFormat(wxDF_TEXT)):
                    data = wxTextDataObject()
                    if wxTheClipboard.GetData(data):
                        command = data.GetText()
                        command = self.fixLineEndings(command)
                        command = command.replace(os.linesep + sys.ps2,
'\n')
                        command = command.replace(os.linesep, '\n')
                        command = command.replace('\n', os.linesep +
sys.ps2)
                        self.ReplaceSelection('')
                        self.write(command)
                wxTheClipboard.Close()

···

---
Patrick K. O'Brien
Orbtech
"I am, therefore I think."

-----Original Message-----
From: wxpython-users-admin@lists.wxwindows.org
[mailto:wxpython-users-admin@lists.wxwindows.org]On Behalf Of Robin Dunn
Sent: Tuesday, October 23, 2001 12:11 PM
To: wxpython-users@lists.wxwindows.org
Subject: Re: [wxPython] Capturing Cut/Copy/Paste in wxSTC

How do I do this in a platform-neutral fashion? Am I to assume Ctrl-X,
Ctrl-C, Ctrl-V?

I've seen an increasing number of *nix applications use these keys, so it's
probably pretty safe to use them. The Mac uses the same ascii chars in
confunction with the "apple" key instead of Control, but I'm not sure yet
how that will appear in wx.

Or are there wx constants that I should use instead?

There are standard menu IDs for them, but I don't see anything for keysyms.

What
about drap and drop? Right now dragging a selection from wxSTC does a cut,
bypassing my Cut() method.

(And holding down the Ctrl should turn it into a Copy.)

I need absolute control in all circumstances.
I've read all the docs and previous messages and can't find anything that
makes this clear to me.

Currently you would have to intercept the mouse events and check for the
dragging from the selected text range, and do your own drag/drop operations,
but I think I can make it easier... Would it work for you if there was an
event at the begining of the drag opperation that give you the default text
to be dragged and allow you to change it?

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

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwindows.org
http://lists.wxwindows.org/mailman/listinfo/wxpython-users

Thanks, Chris. I wonder what Scintilla's default behavior is on different
platforms. Neil?

···

---
Patrick K. O'Brien
Orbtech
"I am, therefore I think."

-----Original Message-----
From: wxpython-users-admin@lists.wxwindows.org
[mailto:wxpython-users-admin@lists.wxwindows.org]On Behalf Of Chris Barker
Sent: Tuesday, October 23, 2001 1:11 PM
To: wxpython-users@lists.wxwindows.org
Subject: Re: [wxPython] Capturing Cut/Copy/Paste in wxSTC

Robin Dunn wrote:

> How do I do this in a platform-neutral fashion? Am I to assume Ctrl-X,
> Ctrl-C, Ctrl-V?

I've seen an increasing number of *nix applications use these keys, so

it's

probably pretty safe to use them.

Most of the *nix Apps that I use use Alt-C, Alt-V, etc., rather than
Ctrl. I can confirm that in Netscape, as I'm using that to write this.

-Chris

--
Christopher Barker,
Ph.D.
ChrisHBarker@home.net --- --- ---
http://members.home.net/barkerlohmann ---@@ -----@@ -----@@
                                   ------@@@ ------@@@ ------@@@
Oil Spill Modeling ------ @ ------ @ ------ @
Water Resources Engineering ------- --------- --------
Coastal and Fluvial Hydrodynamics --------------------------------------
------------------------------------------------------------------------

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwindows.org
http://lists.wxwindows.org/mailman/listinfo/wxpython-users

> > How do I do this in a platform-neutral fashion? Am I to assume Ctrl-X,
> > Ctrl-C, Ctrl-V?
>
> I've seen an increasing number of *nix applications use these keys, so

it's

> probably pretty safe to use them.

Most of the *nix Apps that I use use Alt-C, Alt-V, etc., rather than
Ctrl. I can confirm that in Netscape, as I'm using that to write this.

Right. Alt-* was the Motif standard, which is about 15 years old.
(Actually, IIRC, the Motif standard called for Ctrl-Insert, Shift-Insert,
etc. but the Alt-* keys were listed as an alternative.) Everything new
that I've used that is using the new widget sets is using Ctrl-*. For
example Mozilla and Netscape 6 on *nix are using Ctrl-* now, as well as most
GTK+ apps and KDE/Qt apps.

···

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

Aaaarrrrrggggghhhhhhhh!!!! (But not directed at you, Robin, I promise. And
not Neil, either.)

What I'd really like (I think) is:

EVT_STC_CUT()
EVT_STC_COPY()
EVT_STC_PASTE()

As long as the passed in functions were *always* called.

Well, DnD doesn't actually call Cut or Copy (the text isn't put into the
clipboard, it is just handed over to the other app) so these wouldn't help
much.

I've just added EVT_STC_START_DRAG which will let you change the text to be
dragged and whether or not the drag is allowed to move the text. I'll also
look at doing EVT_STC_DO_DROP...

···

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

Patrick K. O'Brien:

Thanks, Chris. I wonder what Scintilla's default behavior is on different
platforms. Neil?

   Ctrl+[XCV]. GNOME/GTK+ and KDE applications follow Windows command key
conventions.

   Here is part of the table in scintilla/src/KeyMap.cxx:

    {SCK_DELETE, SCI_SHIFT, SCI_CUT},
    {SCK_INSERT, SCI_SHIFT, SCI_PASTE},
    {SCK_INSERT, SCI_CTRL, SCI_COPY},
    {'X', SCI_CTRL, SCI_CUT},
    {'C', SCI_CTRL, SCI_COPY},
    {'V', SCI_CTRL, SCI_PASTE},

   You can nullify all of Scintilla's command key handling with
ClearAllCmdKeys. An individual command key can be cleared with
ClearCmdKey(keymod) where keymod is made up of the modifiers and the key
code as (mods << 16 | key). For example (SCMOD_CTRL << 16) | 'G'. Scintilla
has its own SCMOD_* and SCK_* enumerations for its own small portability
layer. Robin may have exposed this functionality using wx constants.

   Isn't the event you want to intercept really [user has used a text
insertion command]?

   Neil

This is for the PyCrust shell. This is the behavior that I'm trying to get:
Any text prior to the last primary prompt (as opposed to the continuation
prompts for multi-line commands) is read-only. Anything after the last
primary prompt can be edited. Text that is pasted or otherwise inserted in a
fashion other than keystrokes needs to have its line endings converted and
secondary prompts inserted. Text that is cut or copied needs to have prompts
removed so the code can be pasted into regular source files.

What is the best way to accomplish this? I have methods for Cut, Copy,
Paste, CanCut, CanCopy, CanPaste and CanEdit that do what I want. I just
need to make sure they are always called.

···

---
Patrick K. O'Brien
Orbtech
"I am, therefore I think."

-----Original Message-----
From: wxpython-users-admin@lists.wxwindows.org
[mailto:wxpython-users-admin@lists.wxwindows.org]On Behalf Of Neil Hodgson
Sent: Tuesday, October 23, 2001 3:55 PM
To: wxpython-users@lists.wxwindows.org
Subject: Re: [wxPython] Capturing Cut/Copy/Paste in wxSTC

<snip>

   Isn't the event you want to intercept really [user has used a text
insertion command]?

   Neil

Patrick:

What is the best way to accomplish this? I have methods for Cut, Copy,
Paste, CanCut, CanCopy, CanPaste and CanEdit that do what I want. I just
need to make sure they are always called.

    Intercept all command keys and implement them yourself. You may want to
grab the table from scintilla/src/KeyMap.cxx to ensure all the pure
navigation keys are implemented. There is no drag and drop event
interception in Scintilla but you whould be able to do this with wx.

   Neil

Wouldn't it make more sense for Scintilla to always route everything through
its Cut, Copy and Paste methods? Then subclasses could override the default
behavior without concern for how these events are triggered.

···

---
Patrick K. O'Brien
Orbtech
"I am, therefore I think."

-----Original Message-----
From: wxpython-users-admin@lists.wxwindows.org
[mailto:wxpython-users-admin@lists.wxwindows.org]On Behalf Of Neil Hodgson
Sent: Tuesday, October 23, 2001 4:18 PM
To: wxpython-users@lists.wxwindows.org
Subject: Re: [wxPython] Capturing Cut/Copy/Paste in wxSTC

   Patrick:

What is the best way to accomplish this? I have methods for Cut, Copy,
Paste, CanCut, CanCopy, CanPaste and CanEdit that do what I want. I just
need to make sure they are always called.

    Intercept all command keys and implement them yourself. You may want to
grab the table from scintilla/src/KeyMap.cxx to ensure all the pure
navigation keys are implemented. There is no drag and drop event
interception in Scintilla but you whould be able to do this with wx.

   Neil

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwindows.org
http://lists.wxwindows.org/mailman/listinfo/wxpython-users

   Patrick:
> What is the best way to accomplish this? I have methods for Cut, Copy,
> Paste, CanCut, CanCopy, CanPaste and CanEdit that do what I want. I just
> need to make sure they are always called.

    Intercept all command keys and implement them yourself. You may want

to

grab the table from scintilla/src/KeyMap.cxx to ensure all the pure
navigation keys are implemented.

Relevant methods in wxSTC are:

    // When key+modifier combination km is pressed perform msg.
    void CmdKeyAssign(int key, int modifiers, int cmd);

    // When key+modifier combination km do nothing.
    void CmdKeyClear(int key, int modifiers);

    // Drop all key mappings.
    void CmdKeyClearAll();

    // Perform one of the operations defined by the wxSTC_CMD_* constants.
    void CmdKeyExecute(int cmd);

And key codes are:

#define wxSTC_KEY_DOWN 300
#define wxSTC_KEY_UP 301
#define wxSTC_KEY_LEFT 302
#define wxSTC_KEY_RIGHT 303
#define wxSTC_KEY_HOME 304
#define wxSTC_KEY_END 305
#define wxSTC_KEY_PRIOR 306
#define wxSTC_KEY_NEXT 307
#define wxSTC_KEY_DELETE 308
#define wxSTC_KEY_INSERT 309
#define wxSTC_KEY_ESCAPE 7
#define wxSTC_KEY_BACK 8
#define wxSTC_KEY_TAB 9
#define wxSTC_KEY_RETURN 13
#define wxSTC_KEY_ADD 310
#define wxSTC_KEY_SUBTRACT 311
#define wxSTC_KEY_DIVIDE 312
#define wxSTC_SCMOD_SHIFT 1
#define wxSTC_SCMOD_CTRL 2
#define wxSTC_SCMOD_ALT 4

There is no drag and drop event
interception in Scintilla but you whould be able to do this with wx.

I'm in the process of adding wx events that are fired from the DnD methods
in ScintillaWX that will let an event handler change the text dragged and/or
dropped, as well as the dragResult (copy, move, none...) This will make it
easy to, for example, prevent dropping text based on wxSTC position, or to
only allow copy of dragged text by position.

···

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

Thanks a bunch, Robin. Much appreciated.

···

---
Patrick K. O'Brien
Orbtech
"I am, therefore I think."

-----Original Message-----
From: wxpython-users-admin@lists.wxwindows.org
[mailto:wxpython-users-admin@lists.wxwindows.org]On Behalf Of Robin Dunn
Sent: Tuesday, October 23, 2001 1:53 PM
To: wxpython-users@lists.wxwindows.org
Subject: Re: [wxPython] Capturing Cut/Copy/Paste in wxSTC

<snip>

I've just added EVT_STC_START_DRAG which will let you change the text to be
dragged and whether or not the drag is allowed to move the text. I'll also
look at doing EVT_STC_DO_DROP...

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

Wouldn't it make more sense for Scintilla to always route everything

through

its Cut, Copy and Paste methods? Then subclasses could override the

default

behavior without concern for how these events are triggered.

No, because not everything is a Cut, Copy, or Paste, (IOW, involve the
clipboard.) Secondly it would increase the complexity of the wrappers to
allow non-event-based callbacks.

···

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

Patrick:

Wouldn't it make more sense for Scintilla to always route everything

through

its Cut, Copy and Paste methods? Then subclasses could override the

default

behavior without concern for how these events are triggered.

   That will not achieve a read-only state. There are all the deletion
commands (delete word right is Ctrl+Delete, ...), the line based commands
(line cut is Ctrl+L, line transpose is Ctrl+T) and the case morphers
(lowercase is Ctrl+U, uppercase is Ctrl+Shift+U).

   Neil

I see. Yikes! Hadn't even thought about all those. Ouch. I'm in a world of
hurt now. I noticed something in the Scintilla docs about a read-only switch
thingie. Is that something I could toggle based on the cursor position? I
know I'm being a pest but I really want a simple solution. I just want to
extend and modify Scintilla as little as possible. I don't want to have to
recreate the wheel. Thanks.

···

---
Patrick K. O'Brien
Orbtech
"I am, therefore I think."

-----Original Message-----
From: wxpython-users-admin@lists.wxwindows.org
[mailto:wxpython-users-admin@lists.wxwindows.org]On Behalf Of Neil Hodgson
Sent: Tuesday, October 23, 2001 4:41 PM
To: wxpython-users@lists.wxwindows.org
Subject: Re: [wxPython] Capturing Cut/Copy/Paste in wxSTC

Patrick:

Wouldn't it make more sense for Scintilla to always route everything

through

its Cut, Copy and Paste methods? Then subclasses could override the

default

behavior without concern for how these events are triggered.

   That will not achieve a read-only state. There are all the deletion
commands (delete word right is Ctrl+Delete, ...), the line based commands
(line cut is Ctrl+L, line transpose is Ctrl+T) and the case morphers
(lowercase is Ctrl+U, uppercase is Ctrl+Shift+U).

   Neil

Patrick:

I see. Yikes! Hadn't even thought about all those. Ouch. I'm in a world of
hurt now. I noticed something in the Scintilla docs about a read-only

switch

thingie. Is that something I could toggle based on the cursor position? I
know I'm being a pest but I really want a simple solution. I just want to
extend and modify Scintilla as little as possible. I don't want to have to
recreate the wheel. Thanks.

   Yes, you could try and switch read-only state based on the caret and
anchor positions. It is not just the caret position because the selection
may be anchored in the read-only part. This could be triggered on the
UpdateUI notification but there could be races here as UpdateUI can lag
rapid changes. To avoid this problem, you could also trigger after each key.

   At one stage there was going to be a read-only style for text but it was
not implemented because of lack of interest although the related invisible
style was implemented. Invisible text is also supposed to be read-only but
has not been throughly tested.

   Neil

Actually, I think I fixed this. I just needed to add one more elif statement
to my OnKeyDown() handler (the one toward the bottom that starts as elif not
self.CanEdit():

    def OnKeyDown(self, event):
        """Key down event handler.

        Prevents modification of previously submitted commands/responses."""
        key = event.KeyCode()
        currpos = self.GetCurrentPos()
        stoppos = self.promptPos[1]
        # Return is used to submit a command to the interpreter.
        if key == WXK_RETURN:
            if self.AutoCompActive(): self.AutoCompCancel()
            if self.CallTipActive: self.CallTipCancel()
            self.processLine()
        # If the auto-complete window is up let it do its thing.
        elif self.AutoCompActive():
            event.Skip()
        # Retrieve the previous command from the history buffer.
        elif (event.ControlDown() and key == WXK_UP) \
        or (event.AltDown() and key in (ord('P'), ord('p'))):
            self.OnHistoryRetrieve(step=+1)
        # Retrieve the next command from the history buffer.
        elif (event.ControlDown() and key == WXK_DOWN) \
        or (event.AltDown() and key in (ord('N'), ord('n'))):
            self.OnHistoryRetrieve(step=-1)
        # Search up the history for the text in front of the cursor.
        elif key == WXK_F8:
            self.OnHistorySearch()
        # Home needs to be aware of the prompt.
        elif key == WXK_HOME:
            if currpos >= stoppos:
                if event.ShiftDown():
                    # Select text from current position to end of prompt.
                    self.SetSelection(self.GetCurrentPos(), stoppos)
                else:
                    self.SetCurrentPos(stoppos)
                    self.SetAnchor(stoppos)
            else:
                event.Skip()
        # Basic navigation keys should work anywhere.
        elif key in (WXK_END, WXK_LEFT, WXK_RIGHT, WXK_UP, WXK_DOWN, \
                     WXK_PRIOR, WXK_NEXT):
            event.Skip()
        # Don't backspace over the latest prompt.
        elif key == WXK_BACK:
            if currpos > self.prompt1Pos[1]:
                event.Skip()
        # Only allow these keys after the latest prompt.
        elif key in (WXK_TAB, WXK_DELETE):
            if self.CanEdit():
                event.Skip()
        # Don't toggle between insert mode and overwrite mode.
        elif key == WXK_INSERT:
            pass
        # Protect the readonly portion of the shell.
        elif not self.CanEdit():
            pass
        else:
            event.Skip()

···

---
Patrick K. O'Brien
Orbtech
"I am, therefore I think."