Minor Issue with Caret Placement after Outlining Collapse

SyntaxEditor for Windows Forms Forum

Posted 14 years ago by Boyd - Automated Software Testing Consultant / Developer, Patterson Consulting, LLC
Avatar
When you toggle outlining from Expanded to Collapsed, it always seems to place the caret at the end of the collapsed region. In Visual Studio, the caret is always moved to the beginning of the collapsed region when a region is collapsed unless the caret was already positioned at the very last offset of the region. Here's an easy way to dupe it:

1) Open Sample App with C# Sample
2) Move the caret to the offset containing the "{" character on line 6
3) From the 'Outlining Menu', select 'Toggle Outlining Expansion'
4) The caret now jumps to the position just after the collapsed region

To mimic VS behavior, it should have stayed were it was. This is easy enough to code around, but I thought you might want to change the built-in behavior.

Comments (5)

Posted 14 years ago by Ashton - Developer, Schema Solutions LLC
Avatar
Also, dealing with Outlining, anyway you could add the Ctrl+M,M key chord (or maybe have it customizable key) to make outlining expand/collapse automatically like VS.NET does?

:)

I currently do it but have to code it every time I want to support outlining.

Thanks
Posted 14 years ago by Boyd - Automated Software Testing Consultant / Developer, Patterson Consulting, LLC
Avatar
I asked the same question and was told that SyntaxEditor's built-in support will most likely continue to only support simple hotkeys and not multi-key chords. However, work is underway on menu/toolbar support for their UIStudio product that will support Chords (which can then be tied to specific commands like expand/collapse outlining).
Posted 14 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Boyd, got it changed for the next maintenance release to move the caret as you said.

Ashton, Boyd's response is right on.


Actipro Software Support

Posted 14 years ago by Jason Whitted - Owner, Etalisoft, LLC
Avatar
I wanted Command Chord functionality too. Here's the solution (C# .NET 2.0) I came up with if anybody would like to use it. I created SyntaxEditorEx, which inherits from SyntaxEditor. It has a couple new Events for processing the command chords.

You can utilize the class / events like this:
SyntaxEditorEx editor = new SyntaxEditorEx();

// The PendingCommandChord event can be used to display a message in the status bar
// like Visual studio does.  Something like:
//   (Ctrl+K) was pressed. Waiting for the second key of the chord...
ex.PendingCommandChord += new PendingCommandChordEventHandler(editor_PendingCommandChord);

// The CommandChordTriggered event is used to process the command chord
// If the command chord isn't valid, a message can be displayed in the status bar
// like Visual studio does.  Something like:
//   The key combination (Ctrl+K, Esc) is not a command.
ex.CommandChordTriggered += new CommandChordEventHandler(editor_CommandChordTriggered);
SyntaxEditorEx.cs
using System.Windows.Forms;

public class SyntaxEditorEx : ActiproSoftware.SyntaxEditor.SyntaxEditor
{
    private Keys _firstCommandOfChord = Keys.None;

    public event PendingCommandChordEventHandler PendingCommandChord;
    public event CommandChordEventHandler CommandChordTriggered;

    public SyntaxEditorEx()
    {
    }

    private Keys FirstKeyOfCommandChord
    {
        get { return _firstCommandOfChord; }
        set { _firstCommandOfChord = value; }
    }

    public bool IsPendingCommandChord
    {
        get { return (_firstCommandOfChord != Keys.None); }
    }

    protected override void OnKeyTyping(ActiproSoftware.SyntaxEditor.KeyTypingEventArgs e)
    {
        bool modifiersOnly = false;
        switch (e.KeyData)
        {
            case Keys.Shift | Keys.ShiftKey:
            case Keys.Control | Keys.ControlKey:
            case Keys.Alt | Keys.Menu:
                modifiersOnly = true;
                break;
        }

        if (this.IsPendingCommandChord && !modifiersOnly)
        {
            Keys keys = e.KeyData;
            if (keys == Keys.None)  // Crap, we'll have to reconstruct the Keys from e.KeyChar
            {
                char c = e.KeyChar;
                char upper = Char.ToUpper(c);
                if (Char.IsLetter(c) && c == upper) // It's an upper-case letter
                    keys |= Keys.Shift;
                keys |= (Keys)(int)upper;
            }

            OnCommandChordTrigger(new CommandChordEventArgs(this.FirstKeyOfCommandChord, keys));
            e.Cancel = true;
            return;
        }

        switch (e.KeyData)
        {
            case Keys.Control | Keys.K:
            case Keys.Control | Keys.M:
                OnPendingCommandChord(new PendingCommandChordEventArgs(e.KeyData));
                e.Cancel = true;
                return;
        }

        base.OnKeyTyping(e);
    }

    protected virtual void OnPendingCommandChord(PendingCommandChordEventArgs e)
    {
        this.FirstKeyOfCommandChord = e.Key;

        if (PendingCommandChord != null)
            PendingCommandChord(this, e);
    }

    protected virtual void OnCommandChordTrigger(CommandChordEventArgs e)
    {
        this.FirstKeyOfCommandChord = Keys.None;

        if (CommandChordTriggered != null)
            CommandChordTriggered(this, e);

        if (e.Cancel)
            return;

        switch (e.FirstKey)
        {
            case Keys.Control | Keys.K:
                switch (e.SecondKey)
                {
                    case Keys.Control | Keys.K:
                        break;
                }
                break;
            case Keys.Control | Keys.M:
                break;
        }
    }
}
PendingCommandChordEventHandler.cs
public delegate void PendingCommandChordEventHandler(object sender, PendingCommandChordEventArgs e);

public class PendingCommandChordEventArgs
{
    private Keys _key;

    public PendingCommandChordEventArgs(Keys key)
    {
        this.Key = key;
    }

    public Keys Key
    {
        get { return _key; }
        private set { _key = value; }
    }
}
CommandChordEventHandler.cs
public delegate void CommandChordEventHandler(object sender, CommandChordEventArgs e);

public class CommandChordEventArgs
{
    private Keys _firstKey;
    private Keys _secondKey;
    private bool _cancel;

    public CommandChordEventArgs(Keys firstKey, Keys secondKey)
    {
        this.FirstKey = firstKey;
        this.SecondKey = secondKey;
    }


    public Keys FirstKey
    {
        get { return _firstKey; }
        private set { _firstKey = value; }
    }

    public Keys SecondKey
    {
        get { return _secondKey; }
        private set { _secondKey = value; }
    }

    public bool Cancel
    {
        get { return _cancel; }
        set { _cancel = value; }
    }
}
Posted 14 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Great stuff Jason... thanks for the post!

By the way, our UIStudio 2.0 beta is almost ready for some public testing. The new bar controls fully support chord key shortcuts. Watch our site for a post about it soon.


Actipro Software Support

The latest build of this product (v2018.1 build 0341) was released 7 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.