GuiTextEditCtrl improvements
by Orion Elenzil · 04/02/2006 (10:32 am) · 7 comments
This resource implements the following changes to the behaviour of GuiTextEditCtrl:
* Ctrl-A - Select All Text (instead of emulating emacs or whatever)
* Ctrl-LeftArrow - Move cursor to start of previous word.
* Ctrl-RightArrow - Move cursor to start of next word.
* Improve the cursor blinking so that you can see the cursor when you most want to. jeeze.
* Improve the case when the cursor is at the far-right edge of the control.
the first three are simple.
in guiTextEditCtrl.cc
replace the case statement titled "Ctrl-A" with this:
actually, right after that case statement (eg before "Ctrl-E") just paste these new cases in:
the cursor blinking is slightly more involved.
in GuiTextEditCtrl.h,
add the following method declaration whereever it seems good to you.
i recommend right before "onKeyDown".
back over in GuiTextEditCtrl.cc,
implement that method like this:
in "onPreRender()", change this:
to this:
.. so far so good, but nothing will actually be different.
now for the grand finale exciting part!
in "GuiTextEditCtrl::onKeyDown", right after "setUpdate()" near the top,
insert this:
- really this should only call setCursorOnOff() if the keystroke is actually handled by the control,
but since all the cases in the switch statements just return straight out of the switches instead of setting a return value and then breaking, you'd have to go in and insert this in front of every "return true". (or of course retool the switches)
which is more work than i'm up for, and if the cursor is visible too often, i'm okay with that.
okay, last one for now,
improving the case where the cursor is all the way at the end of a text conrol, and it renders right thru the center of the last character. jeeze. this has driven me nuts for years, little did i suspect how easy it might be to fix.
still in guiTextEditCtrl.cc,
in "DrawText", change this bizarre block of code:
to this much more sensible one:
todo
* ctrl-UpArrow/DownArrow should possibly select the first and last items in the history list.
* Ctrl-A - Select All Text (instead of emulating emacs or whatever)
* Ctrl-LeftArrow - Move cursor to start of previous word.
* Ctrl-RightArrow - Move cursor to start of next word.
* Improve the cursor blinking so that you can see the cursor when you most want to. jeeze.
* Improve the case when the cursor is at the far-right edge of the control.
the first three are simple.
in guiTextEditCtrl.cc
replace the case statement titled "Ctrl-A" with this:
// Ctrl-A - select all
case KEY_A:
{
mBlockStart = 0;
mBlockEnd = stringLen;
mCursorPos = mBlockEnd;
return true;
}actually, right after that case statement (eg before "Ctrl-E") just paste these new cases in:
// Ctrl-Left - previous word. doesn't honor shift-ctrl.
case KEY_LEFT:
{
mBlockStart = 0;
mBlockEnd = 0;
// scan left to first non-whitespace
while (mCursorPos > 0 && dIsspace(mText[mCursorPos-1]))
mCursorPos--;
// scan left to first whitespace
while (mCursorPos > 0 && !dIsspace(mText[mCursorPos-1]))
mCursorPos--;
return true;
}
// Ctrl-Right - next word. doesn't honor shift-ctrl.
case KEY_RIGHT:
{
mBlockStart = 0;
mBlockEnd = 0;
// scan right to first whitespace
while (mCursorPos < stringLen && !dIsspace(mText[mCursorPos]))
mCursorPos++;
// scan right to first non-whitespace
while (mCursorPos < stringLen && dIsspace(mText[mCursorPos]))
mCursorPos++;
return true;
}the cursor blinking is slightly more involved.
in GuiTextEditCtrl.h,
add the following method declaration whereever it seems good to you.
i recommend right before "onKeyDown".
void setCursorOnOff(bool on);
back over in GuiTextEditCtrl.cc,
implement that method like this:
void GuiTextEditCtrl::setCursorOnOff(bool on)
{
mCursorOn = on;
mTimeLastCursorFlipped = Sim::getCurrentTime();
mNumFramesElapsed = 0;
}in "onPreRender()", change this:
mCursorOn = 1 - mCursorOn;
mTimeLastCursorFlipped = Sim::getCurrentTime();
mNumFramesElapsed = 0;to this:
setCursorOnOff(!mCursorOn);
.. so far so good, but nothing will actually be different.
now for the grand finale exciting part!
in "GuiTextEditCtrl::onKeyDown", right after "setUpdate()" near the top,
insert this:
setCursorOnOff(true);
- really this should only call setCursorOnOff() if the keystroke is actually handled by the control,
but since all the cases in the switch statements just return straight out of the switches instead of setting a return value and then breaking, you'd have to go in and insert this in front of every "return true". (or of course retool the switches)
which is more work than i'm up for, and if the cursor is visible too often, i'm okay with that.
okay, last one for now,
improving the case where the cursor is all the way at the end of a text conrol, and it renders right thru the center of the last character. jeeze. this has driven me nuts for years, little did i suspect how easy it might be to fix.
still in guiTextEditCtrl.cc,
in "DrawText", change this bizarre block of code:
// else if ( cursorStart.x >= ( drawRect.point.x + drawRect.extent.x ) )
else if ( cursorStart.x >= ( drawRect.point.x + drawRect.extent.x ) )
{
cursorStart.x = drawRect.point.x + mBounds.extent.x - 4;
// mTextOffset.x = cursorStart.x - tempWidth;
mTextOffset.x = drawRect.point.x - (tempWidth-drawRect.extent.x) ;
cursorEnd.x = cursorStart.x;
}to this much more sensible one:
else if ( cursorStart.x >= ( drawRect.point.x + drawRect.extent.x ) )
{
cursorStart.x = drawRect.point.x + mBounds.extent.x - 3;
mTextOffset.x = drawRect.point.x - (tempWidth-drawRect.extent.x) - 3;
cursorEnd.x = cursorStart.x;
}todo
* ctrl-UpArrow/DownArrow should possibly select the first and last items in the history list.
About the author
#2
but it's so hacky that i was reluctant to post it here.
after a couple hours of testing our hack seems to be working well,
but our app is fairly far from a first-person-shooter, so i think it might cause problems in general for FPSs.
but:
the fix was to lobotomize both activateKeyboard() and optionally deactivateKeyboard() so that they both immediately return false instead of doing anything.
our working theory is that in torque, an "active" keyboard is one which filters out key-repeat events so that functions further down the event-path only get legitimate key-up/key-down transitions.
.. which makes sense if you want to avoid multiple weapon-switches or multiple fire commands or something. which we don't happen to care about.
i should add that functions like "F10 equals toggle DialogBlah" are also working fine for us under this change. ie holding down F10 does Not result in a spastic toggling of DialogBlah.
so in summary i'm sure there's some reason for the whole "active" keyboard mode, and i'll probably be posting within a couple weeks why it was a bad idea to disable it, but so far no reason is found.
03/14/2006 (12:06 am)
um, yes.but it's so hacky that i was reluctant to post it here.
after a couple hours of testing our hack seems to be working well,
but our app is fairly far from a first-person-shooter, so i think it might cause problems in general for FPSs.
but:
the fix was to lobotomize both activateKeyboard() and optionally deactivateKeyboard() so that they both immediately return false instead of doing anything.
our working theory is that in torque, an "active" keyboard is one which filters out key-repeat events so that functions further down the event-path only get legitimate key-up/key-down transitions.
.. which makes sense if you want to avoid multiple weapon-switches or multiple fire commands or something. which we don't happen to care about.
i should add that functions like "F10 equals toggle DialogBlah" are also working fine for us under this change. ie holding down F10 does Not result in a spastic toggling of DialogBlah.
so in summary i'm sure there's some reason for the whole "active" keyboard mode, and i'll probably be posting within a couple weeks why it was a bad idea to disable it, but so far no reason is found.
#3
Thanks again for sharing your hard work with the community!
B--
03/14/2006 (8:29 am)
I had looked into that as well, it was some time ago, but I remember not comming up with an easy answer that didn't require a re-write. Good to hear you at least have it working.. I think most developers stub in quick solutions, and after some time, come back and clean up the process.Thanks again for sharing your hard work with the community!
B--
#4
04/03/2006 (1:18 am)
very good resource, thank you
#5
04/03/2006 (9:25 pm)
Thanks! It was very useful :)
#6
05/24/2006 (2:11 am)
Very useful resource, thanks. In my case (using TGE1.4 + TLK), I got the key repeats working by calling deactivateKeyboard() in the GUI's onWake() . For completeness, I also added activateKeyboard() in onSleep().
#7
05/24/2006 (11:57 am)
good to know, thanks Ron. 
Torque 3D Owner Brandon Maness