Code::Blocks
July 29, 2010, 06:00:59 pm *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: New release 10.05 is ready. Grab it while it's hot!!!
 
   Home   Help Search Login Register  :: WebsiteWiki  
Pages: [1] 2
  Send this topic  |  Print  
Author Topic: hook "tab" key  (Read 1636 times)
blueshake
Regular
***
Posts: 433



« on: March 08, 2010, 08:47:42 am »

dear all:


mybe you have the function of eclipse,in eclipse editor,when you type "tab",and if the next char is one of ")]}",it will skip it. see the screen shot.so if we want to implement this function,we need to hook getkey donw message,in codelite, it just simple handle it in this way.see the quote.

and in codeblock ,I can not figure out how to do this.can somebode tell me how to do this in codeblock,thanks.
Quote
BEGIN_EVENT_TABLE(LEditor, wxScintilla)

    EVT_SCI_CHARADDED              (wxID_ANY, LEditor::OnCharAdded)
    EVT_SCI_MARGINCLICK            (wxID_ANY, LEditor::OnMarginClick)
    EVT_SCI_CALLTIP_CLICK          (wxID_ANY, LEditor::OnCallTipClick)
    EVT_SCI_DWELLEND               (wxID_ANY, LEditor::OnDwellEnd)
    EVT_SCI_UPDATEUI               (wxID_ANY, LEditor::OnSciUpdateUI)
    EVT_SCI_SAVEPOINTREACHED       (wxID_ANY, LEditor::OnSavePoint)
    EVT_SCI_SAVEPOINTLEFT          (wxID_ANY, LEditor::OnSavePoint)
    EVT_SCI_MODIFIED               (wxID_ANY, LEditor::OnChange)
    EVT_CONTEXT_MENU               (LEditor::OnContextMenu)
    EVT_KEY_DOWN                   (LEditor::OnKeyDown)
    EVT_LEFT_DOWN                  (LEditor::OnLeftDown)
    EVT_MIDDLE_DOWN                (LEditor::OnMiddleDown)
    EVT_MIDDLE_UP                  (LEditor::OnMiddleUp)
    EVT_LEFT_UP                    (LEditor::OnLeftUp)
    EVT_LEAVE_WINDOW               (LEditor::OnLeaveWindow)
    EVT_KILL_FOCUS                 (LEditor::OnFocusLost)
    EVT_SCI_DOUBLECLICK            (wxID_ANY, LEditor::OnLeftDClick)
    EVT_COMMAND                    (wxID_ANY, wxEVT_FRD_FIND_NEXT, LEditor::OnFindDialog)
    EVT_COMMAND                    (wxID_ANY, wxEVT_FRD_REPLACE, LEditor::OnFindDialog)
    EVT_COMMAND                    (wxID_ANY, wxEVT_FRD_REPLACEALL, LEditor::OnFindDialog)
    EVT_COMMAND                    (wxID_ANY, wxEVT_FRD_BOOKMARKALL, LEditor::OnFindDialog)
    EVT_COMMAND                    (wxID_ANY, wxEVT_FRD_CLOSE, LEditor::OnFindDialog)
    EVT_COMMAND                    (wxID_ANY, wxEVT_FRD_CLEARBOOKMARKS, LEditor::OnFindDialog)
    EVT_COMMAND                    (wxID_ANY, wxEVT_CMD_JOB_STATUS_VOID_PTR, LEditor::OnHighlightThread)
    EVT_COMMAND                    (wxID_ANY, wxCMD_EVENT_REMOVE_MATCH_INDICATOR, LEditor::OnRemoveMatchInidicator)
END_EVENT_TABLE()
Logged

Keep low and hear the sadness of little dog.
I fall in love with a girl,but I don't dare to tell her.What should I do?
ollydbg
Lives here!
****
Posts: 1484


Interests on OpenCV and Robotics


WWW
« Reply #1 on: March 08, 2010, 09:17:47 am »

I have tried, but failed. Sad

In the codelite editor, say LEditor class, it is just derived from wxScintilla class, so it can hook the EVT_KEY_DOWN message.

But in Codeblocks, cbEditor class use wxScintilla as its member, I don't know how to hook the Key_down event.

By the way, if we can handle the message SCI_TAB from scintilla (see: http://www.scintilla.org/ScintillaDoc.html#KeyboardCommands), we can do the same thing.

hope some one can help you.
Logged

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.
MortenMacFly
Administrator
Lives here!
*****
Posts: 4593



WWW
« Reply #2 on: March 08, 2010, 11:44:07 am »

and in codeblock ,I can not figure out how to do this.can somebode tell me how to do this in codeblock,thanks.
Look into:
Code:
void cbEditor::OnScintillaEvent(wxScintillaEvent& event)

Notice that you should do any listening via an (the) editor hook. It can even be implemented as plugin btw!
Logged

Logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
Compiling help
Debugging help
Portable C::B
blueshake
Regular
***
Posts: 433



« Reply #3 on: March 08, 2010, 01:41:40 pm »

@morten

thanks for your answer.I will check into it. Very Happy
Logged

Keep low and hear the sadness of little dog.
I fall in love with a girl,but I don't dare to tell her.What should I do?
ollydbg
Lives here!
****
Posts: 1484


Interests on OpenCV and Robotics


WWW
« Reply #4 on: March 09, 2010, 03:30:37 am »

I don't know we can do it in the OnScintillaEvent(), because we don't have a  wxEVT_SCI_TAB defined in wxscintilla.h

See the code snippet :

Code:
cbStyledTextCtrl* cbEditor::CreateEditor()
{
    m_ID = wxNewId();

    // avoid gtk-critical because of sizes less than -1 (can happen with wxAuiNotebook/cbAuiNotebook)
    wxSize size = m_pControl ? wxDefaultSize : GetSize();
    size.x = std::max(size.x, -1);
    size.y = std::max(size.y, -1);

    cbStyledTextCtrl* control = new cbStyledTextCtrl(this, m_ID, wxDefaultPosition, size);
    control->UsePopUp(false);

    wxString enc_name = Manager::Get()->GetConfigManager(_T("editor"))->Read(_T("/default_encoding"), wxEmptyString);
    m_pData->m_encoding = wxFontMapper::GetEncodingFromName(enc_name);

    // dynamic events
    Connect( m_ID,  -1, wxEVT_SCI_MARGINCLICK,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnMarginClick );
    Connect( m_ID,  -1, wxEVT_SCI_UPDATEUI,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnEditorUpdateUI );
    Connect( m_ID,  -1, wxEVT_SCI_CHANGE,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnEditorChange );
    Connect( m_ID,  -1, wxEVT_SCI_CHARADDED,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnEditorCharAdded );
    Connect( m_ID,  -1, wxEVT_SCI_DWELLSTART,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnEditorDwellStart );
    Connect( m_ID,  -1, wxEVT_SCI_DWELLEND,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnEditorDwellEnd );
    Connect( m_ID,  -1, wxEVT_SCI_USERLISTSELECTION,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnUserListSelection );
    Connect( m_ID,  -1, wxEVT_SCI_MODIFIED,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnEditorModified );

    // Now bind all *other* scintilla events to a common function so that editor hooks
    // can be informed for them too.
    // If you implement one of these events using a different function, do the following:
    //  * comment it out here,
    //  * "connect" it in the above block
    //  * and make sure you call OnScintillaEvent() from your new handler function
    // This will make sure that all editor hooks will be called when needed.
    int scintilla_events[] =
    {
//        wxEVT_SCI_CHANGE,
        wxEVT_SCI_STYLENEEDED,
//        wxEVT_SCI_CHARADDED,
        wxEVT_SCI_SAVEPOINTREACHED,
        wxEVT_SCI_SAVEPOINTLEFT,
        wxEVT_SCI_ROMODIFYATTEMPT,
        wxEVT_SCI_KEY,
        wxEVT_SCI_DOUBLECLICK,
//        wxEVT_SCI_UPDATEUI,
//        wxEVT_SCI_MODIFIED,
        wxEVT_SCI_MACRORECORD,
//        wxEVT_SCI_MARGINCLICK,
        wxEVT_SCI_NEEDSHOWN,
        wxEVT_SCI_PAINTED,
//        wxEVT_SCI_USERLISTSELECTION,
        wxEVT_SCI_URIDROPPED,
//        wxEVT_SCI_DWELLSTART,
//        wxEVT_SCI_DWELLEND,
        wxEVT_SCI_START_DRAG,
        wxEVT_SCI_DRAG_OVER,
        wxEVT_SCI_DO_DROP,
        wxEVT_SCI_ZOOM,
        wxEVT_SCI_HOTSPOT_CLICK,
        wxEVT_SCI_HOTSPOT_DCLICK,
        wxEVT_SCI_CALLTIP_CLICK,
        wxEVT_SCI_AUTOCOMP_SELECTION,
//        wxEVT_SCI_INDICATOR_CLICK,
//        wxEVT_SCI_INDICATOR_RELEASE,

        -1 // to help enumeration of this array
    };
    int i = 0;
    while (scintilla_events[i] != -1)
    {
        Connect( m_ID,  -1, scintilla_events[i],
                      (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                      &cbEditor::OnScintillaEvent );
        ++i;
    }

    return control;
}


We can only handle all the events in the scintilla_events array, either commented events or uncommented events. But the "tab" event will never carried in the wxEVT_SCI_KEY, because from the docs:

http://www.scintilla.org/ScintillaDoc.html#SCN_KEY

Quote
SCN_KEY
Reports all keys pressed but not consumed by Scintilla.

Since I think the "tab" event is already consumed by Scintilla internally, the only chance we can hook the tab event is the "SCI_TAB" stated in the
http://www.scintilla.org/ScintillaDoc.html#KeyboardCommands

which is not implemented in wxScintilla.

I'm not sure all my comments is right. Very Happy
« Last Edit: March 09, 2010, 03:32:24 am by ollydbg » Logged

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.
Loaden
Regular
***
Posts: 464



« Reply #5 on: March 24, 2010, 02:12:05 pm »

I solved this problem.

Code:
cbStyledTextCtrl* cbEditor::CreateEditor()
{
    m_ID = wxNewId();

    // avoid gtk-critical because of sizes less than -1 (can happen with wxAuiNotebook/cbAuiNotebook)
    wxSize size = m_pControl ? wxDefaultSize : GetSize();
    size.x = std::max(size.x, -1);
    size.y = std::max(size.y, -1);

    cbStyledTextCtrl* control = new cbStyledTextCtrl(this, m_ID, wxDefaultPosition, size);
    control->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(cbEditor::OnKeyDown));

Notice:
    control->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(cbEditor::OnKeyDown));
Logged

Arch & XP -|- GCC & VC  -|- Code::Blocks SVN Latest
------------------------------------------
Index for my patches
Loaden
Regular
***
Posts: 464



« Reply #6 on: March 25, 2010, 05:18:13 pm »

I make a patch for this, welcome to test.
Logged

Arch & XP -|- GCC & VC  -|- Code::Blocks SVN Latest
------------------------------------------
Index for my patches
ollydbg
Lives here!
****
Posts: 1484


Interests on OpenCV and Robotics


WWW
« Reply #7 on: March 26, 2010, 01:59:31 am »

I make a patch for this, welcome to test.


I found a bug:

When I enter this:
Code:
void f(
Then, I will get the close parenthesis auto added.
Code:
void f(|)
But at this moment, I press backspace key, then the opening parenthesis was deleted but the close parenthesis still there.
Code:
void f)

Except this bug, all the other functions works really nice!!! Thanks for the contribution.
Logged

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.
Loaden
Regular
***
Posts: 464



« Reply #8 on: March 26, 2010, 04:29:42 am »

I make a patch for this, welcome to test.


I found a bug:

When I enter this:
Code:
void f(
Then, I will get the close parenthesis auto added.
Code:
void f(|)
But at this moment, I press backspace key, then the opening parenthesis was deleted but the close parenthesis still there.
Code:
void f)

Except this bug, all the other functions works really nice!!! Thanks for the contribution.
Fix now.
Logged

Arch & XP -|- GCC & VC  -|- Code::Blocks SVN Latest
------------------------------------------
Index for my patches
MortenMacFly
Administrator
Lives here!
*****
Posts: 4593



WWW
« Reply #9 on: March 26, 2010, 07:24:48 am »

Fix now.
Some remarks concerning this patch:
1.) Methods should not start like "No", "Dont", "Not". This is hard to read. Instead always call a method like e.g. "AllowTabSmartJump" and change the break statement to "if (!AllowTabSmartJump()) break;"
2.) The trial for AllowTabSmartJump() should be the first statement in the method, like:
Code:
if (!AllowTabSmartJump())
{
    event.Skip();
    return;
}
3.) These statements look weird to me:
Code:
       case _T('\''):
        case 57:    // (
        case 0x91:  // {
You are using character comparison, then integer and finally hex. Why? Couldn't this be consistent, readable like e.g. all of type char?
4.) It does not use our code style (indention of 4 spaces)

...if you keep that in mind then it easier for us to integrate with the C::B sources.

...sorry for nut-picking. Take it as a hint for future work.
« Last Edit: March 26, 2010, 07:26:53 am by MortenMacFly » Logged

Logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
Compiling help
Debugging help
Portable C::B
Loaden
Regular
***
Posts: 464



« Reply #10 on: March 26, 2010, 08:21:30 am »

Hi, morten, thanks for your tips.
The following patch should solve your related issues.

Code:
Index: src/include/cbstyledtextctrl.h
===================================================================
--- src/include/cbstyledtextctrl.h (revision 6196)
+++ src/include/cbstyledtextctrl.h (working copy)
@@ -24,9 +24,13 @@
         void OnKillFocus(wxFocusEvent& event);
         void OnGetFocus(wxFocusEvent& event);
         void OnGPM(wxMouseEvent& event);
+        void OnKeyDown(wxKeyEvent& event);
+        void OnKeyUp(wxKeyEvent& event);
+        bool AllowTabSmartJump();
 
         wxWindow* m_pParent;
         wxLongLong m_lastFocusTime;
+        bool m_tabSmartJump;
 
         DECLARE_EVENT_TABLE()
 };
Index: src/sdk/cbstyledtextctrl.cpp
===================================================================
--- src/sdk/cbstyledtextctrl.cpp (revision 6196)
+++ src/sdk/cbstyledtextctrl.cpp (working copy)
@@ -18,17 +18,23 @@
 #include "editorbase.h" // DisplayContextMenu
 #include "prep.h" // platform::gtk
 
+static const wxString s_leftBrace(_T("([{'\""));
+static const wxString s_rightBrace(_T(")]}'\""));
+
 BEGIN_EVENT_TABLE(cbStyledTextCtrl, wxScintilla)
     EVT_CONTEXT_MENU(cbStyledTextCtrl::OnContextMenu)
     EVT_KILL_FOCUS(cbStyledTextCtrl::OnKillFocus)
     EVT_MIDDLE_DOWN(cbStyledTextCtrl::OnGPM)
     EVT_SET_FOCUS(cbStyledTextCtrl::OnGetFocus)
+    EVT_KEY_DOWN(cbStyledTextCtrl::OnKeyDown)
+    EVT_KEY_UP(cbStyledTextCtrl::OnKeyUp)
 END_EVENT_TABLE()
 
 cbStyledTextCtrl::cbStyledTextCtrl(wxWindow* pParent, int id, const wxPoint& pos, const wxSize& size, long style)
     : wxScintilla(pParent, id, pos, size, style),
     m_pParent(pParent),
-    m_lastFocusTime(0L)
+    m_lastFocusTime(0L),
+    m_tabSmartJump(false)
 {
     //ctor
 }
@@ -103,3 +109,125 @@
         SetSelectionVoid(start, end);
     }
 } // end of OnGPM
+
+void cbStyledTextCtrl::OnKeyDown(wxKeyEvent& event)
+{
+    int keyCode = event.GetKeyCode();
+    switch (keyCode)
+    {
+        case WXK_TAB:
+        {
+            if (m_tabSmartJump)
+            {
+                if (s_rightBrace.Find(GetCharAt(GetCurrentPos())) == wxNOT_FOUND)
+                {
+                    m_tabSmartJump = false;
+                }
+                else
+                {
+                    CharRight();
+                    return;
+                }
+            }
+        }
+        break;
+
+        case WXK_BACK:
+        {
+            if (m_tabSmartJump)
+            {
+                const int pos = GetCurrentPos();
+                const int index = s_leftBrace.Find(GetCharAt(pos - 1));
+                if (index != wxNOT_FOUND && GetCharAt(pos) == s_rightBrace.GetChar(index))
+                {
+                    CharRight();
+                    DeleteBack();
+                }
+            }
+        }
+        break;
+
+        case WXK_ESCAPE:
+        {
+            if (m_tabSmartJump)
+            {
+                m_tabSmartJump = false;
+                CharLeft();
+                Tab();
+                return;
+            }
+        }
+        break;
+
+        case WXK_RETURN:
+        {
+            m_tabSmartJump = false;
+        }
+        break;
+    }
+
+    event.Skip();
+}
+
+void cbStyledTextCtrl::OnKeyUp(wxKeyEvent& event)
+{
+    const int keyCode = event.GetKeyCode();
+    switch (keyCode)
+    {
+        case _T('['):   // [ {
+        case _T('\''):  // ' "
+        case _T('9'):   // (
+        {
+            if (!AllowTabSmartJump()) break;
+
+            wxChar ch = keyCode;
+            if (event.ShiftDown())
+            {
+                if (keyCode == _T('\'')) ch = _T('"');
+                else if (keyCode == _T('9')) ch = _T('(');
+                else if (keyCode == _T('[')) ch = _T('{');
+            }
+
+            int index = s_leftBrace.Find(ch);
+            if (index != wxNOT_FOUND && GetCharAt(GetCurrentPos()) == s_rightBrace.GetChar(index))
+                m_tabSmartJump = true;
+            else if (keyCode == _T('\'')) // ' "
+                m_tabSmartJump = false;
+        }
+        break;
+
+        case _T(']'):   // ] }
+        case _T('0'):   // )
+        {
+            if (!AllowTabSmartJump()) break;
+            if (keyCode == _T('0') && !event.ShiftDown()) break;
+            m_tabSmartJump = false;
+        }
+        break;
+    }
+
+    event.Skip();
+}
+
+bool cbStyledTextCtrl::AllowTabSmartJump()
+{
+    int style = GetStyleAt(GetCurrentPos() - 2);
+    switch (GetLexer())
+    {
+        case wxSCI_LEX_CPP:
+        {
+            if (style != wxSCI_C_STRING && style != wxSCI_C_CHARACTER)
+                return true;
+            else
+                return !(style == wxSCI_C_STRING || style == wxSCI_C_CHARACTER);
+        }
+        case wxSCI_LEX_D:
+        {
+            if (style != wxSCI_D_STRING && style != wxSCI_D_CHARACTER)
+                return true;
+            else
+                return !(style == wxSCI_D_STRING || style == wxSCI_D_CHARACTER);
+        }
+    }
+    return false;
+}
« Last Edit: March 26, 2010, 09:02:48 am by Loaden » Logged

Arch & XP -|- GCC & VC  -|- Code::Blocks SVN Latest
------------------------------------------
Index for my patches
Loaden
Regular
***
Posts: 464



« Reply #11 on: March 26, 2010, 08:25:01 am »

But now I encountered difficulties: I do not know how to draw the lines for tips?
Moreover, whether it is necessary for drawing the root tips of the lines that do?
Everyone's opinion?
Logged

Arch & XP -|- GCC & VC  -|- Code::Blocks SVN Latest
------------------------------------------
Index for my patches
Loaden
Regular
***
Posts: 464



« Reply #12 on: March 26, 2010, 08:36:00 am »

2.) The trial for AllowTabSmartJump() should be the first statement in the method, like:
Code:
if (!AllowTabSmartJump())
{
    event.Skip();
    return;
}
Here, I do not quite understand: Why did not directly break it, because at the end of the function, there implementation: 'event.Skip ();' ?
Logged

Arch & XP -|- GCC & VC  -|- Code::Blocks SVN Latest
------------------------------------------
Index for my patches
MortenMacFly
Administrator
Lives here!
*****
Posts: 4593



WWW
« Reply #13 on: March 26, 2010, 08:39:09 pm »

Here, I do not quite understand: Why did not directly break it, because at the end of the function, there implementation: 'event.Skip ();' ?
Yes, but there are computations in between which can be avoided. Namely event.GetKeyCode(); and the switch computation.
Logged

Logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
Compiling help
Debugging help
Portable C::B
MortenMacFly
Administrator
Lives here!
*****
Posts: 4593



WWW
« Reply #14 on: March 26, 2010, 08:43:22 pm »

Hehe... now after the modifications, isn't this:
Code:
Index: src/include/cbstyledtextctrl.h
+    switch (GetLexer())
+    {
+        case wxSCI_LEX_CPP:
+        {
+            if (style != wxSCI_C_STRING && style != wxSCI_C_CHARACTER)
+                return true;
+            else
+                return !(style == wxSCI_C_STRING || style == wxSCI_C_CHARACTER);
+        }
+        case wxSCI_LEX_D:
+        {
+            if (style != wxSCI_D_STRING && style != wxSCI_D_CHARACTER)
+                return true;
+            else
+                return !(style == wxSCI_D_STRING || style == wxSCI_D_CHARACTER);
+        }
+    }
+    return false;
+}
The same like this:
Code:
Index: src/include/cbstyledtextctrl.h
+    switch (GetLexer())
+    {
+        case wxSCI_LEX_CPP:
+        {
+            if (style != wxSCI_C_STRING && style != wxSCI_C_CHARACTER)
+                return true;
+        }
+        case wxSCI_LEX_D:
+        {
+            if (style != wxSCI_D_STRING && style != wxSCI_D_CHARACTER)
+                return true;
+        }
+    }
+    return false;
+}
???
Laughing Laughing Laughing
Logged

Logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
Compiling help
Debugging help
Portable C::B
Pages: [1] 2
  Send this topic  |  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!