I am looking for the code syntax to bind a <Tab> keypress event to a Perl Tk Widget.
Reading through the documentation, I saw i can bind <Control> and <Alt> (and any combination), but couldn't find the <Tab> key binding.
I've tried ...->bind('<Tab>', sub{...}); but it didn't work.
How to bind it?
After digging with this issue for a while, and exploring all good advice provided in the comments. I've found out the best way to achieve my purpose is to derive the Widget and create my own custom widget, and use OOP override techniques to control the behavior.
This works like charm.
So for Tk::Text, for example, the native <Tab> event is bind to
$mw->bind($class,'<Tab>', 'insertTab');
sub insertTab
{
my ($w) = #_;
$w->Insert("\t");
$w->focus;
$w->break
}
And by deriving from Tk::Text widget to my own Tk::myText widget, I was able to override the insertTab method as follows:
sub insertTab
{
my ($w) = #_;
// <-- place my stuff here
// <-- to be executed first
$w->SUPER::insertTab(); // <-- then call the original <Tab> handler from the parent
}
Related
I am working on a VsCode extension in that I want to provide custom snippets for code completion.
I know about the option of using snippet json files directly, however those have the limitation of not being able to utilize the CompletionItemKind property that determines the icon next to the completion suggestion in the pop-up.
My issue:
If I implement a simple CompletionItemProvider like this:
context.subscriptions.push(
vscode.languages.registerCompletionItemProvider(
{scheme:"file",language:"MyLang"},
{
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
let item = new vscode.CompletionItem('test');
item.documentation = 'my test function';
item.kind = vscode.CompletionItemKind.Function;
return [item];
}
}
)
)
then the original VsCode IntelliSense text suggestions are not shown anymore, only my own. Should I just return a kind of an empty response, like
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
return [null|[]|undefined];
}
the suggestions appear again as they should. It seems to me that instead of merging the results of the built-in IntelliSense and my own provider, the built-in ones get simply overridden.
Question:
How can I keep the built-in IntelliSense suggestions while applying my own CompletionItems?
VsCode Version: v1.68.1 Ubuntu
I seem to have found the answer for my problem, so I will answer my question.
Multiple providers can be registered for a language. In that case providers are sorted
by their {#link languages.match score} and groups of equal score are sequentially asked for
completion items. The process stops when one or many providers of a group return a
result.
My provider seems to provide results that are just higher scored than those of IntelliSense.
Since I didn't provide any trigger characters, my CompletionItems were comteping directly with the words found by the built-in system by every single pressed key and won.My solution is to simply parse and register the words in my TextDocument myself and extend my provider results by them. I could probably just as well create and register a new CompletionItemProvider for them if I wanted to, however I decided to have a different structure for my project.
I have implemented an SEditableText widget in my editor plugin but I can't figure out a reasonable way of accessing the value in the widget. I know there is an SEditableText.OnTextChanged() function but I don't see anyway to override it or set a callback of my own. Is there a standard way to save the content of an SEditableText to a variable?
I am working in the context of FModeToolKit, not sure if that makes a difference.
When you instantiate the slate widget, you should already be making a call to SNew. As part of the property initialiser chain list, initialise SEditableText::OnTextChanged and bind to your container UObject, using BIND_UOBJECT_DELEGATE. The delegate signature should be FOnTextChanged. Your handler will receive an FText which may be stored in a variable as required.
Example:
SEditableText EditableText = SNew(SEditableText)
.OnTextChanged(BIND_UOBJECT_DELEGATE(FOnTextChanged, OnTextChanged);
then:
void UMyUObject::HandleOnTextChanged(const FText& InText)
{
// Do something with text
}
Take a look at it in action in UEditableText::RebuildWidget (EditableText.cpp:50, v4.22.1).
NB. I know you specifically asked about OnTextChanged, but also consider OnTextComitted; this is only fired when the slate widget loses focus.
Ah; BIND_UOBJECT_DELEGATE is in UMG. The macro is however just a helper to create a UObject to which you may bind:
#define BIND_UOBJECT_DELEGATE(Type, Function) \
Type::CreateUObject( this, &ThisClass::Function )
So there's two options, either use <my type>::CreateUObject, or you could bind via a shared pointer. Off the top of my head, SP method should look something like:
Edit (based on comments):
If you're not linked against UMG, you could try manually creating the UObject based on the macro defined in SlateWrapperTypes in UMG:
#define BIND_UOBJECT_DELEGATE(Type, Function) \
Type::CreateUObject( this, &ThisClass::Function )
To instead use a shared pointer, the syntax should be along the following lines:
auto OnTextChangedSP = FOnTextChanged::CreateSP(this, &MyClass::MyOnTextChangedHandler);
SEditableText EditableText = SNew(SEditableText)
.OnTextChanged(OnTextChangedSP);
I have a problem use editor script to remove a statemachinebehaviour,like this:
I use AnimatorState.AddStateMachineBehaviour add the behaviour
The Documentation said use Object.Destroy,I use this api,but it appears:
I want to know how to use Editor Script to implement the function as "remove"
thanks for any idea!!!
In order to remove the state machine behaviour you have to grab the state machine behaviour array, remove the behaviour that you're after, and then reassign the array.
Something along these lines should do it:
using UnityEditor;
using UnityEditor.Animations;
//how you invoke this is up to you
[MenuItem("CONTEXT/StateMachineBehaviour/Remove Test")]
public static void RemoveBehaviour(MenuCommand command)
{
Object selection = Selection.activeObject;
AnimatorState state = selection as AnimatorState;
if(state != null)
{
StateMachineBehaviour behaviour = command.context as StateMachineBehaviour;
StateMachineBehaviour[] theBehaviours = state.behaviours;
ArrayUtility.Remove(ref theBehaviours, behaviour);
Undo.RegisterCompleteObjectUndo(state, "Removed behaviour");
Undo.DestroyObjectImmediate(behaviour);
state.behaviours = theBehaviours;
}
}
This will remove the behaviour using the state machine dropdown menu, with added undo and redo support, an optional bonus.
Depending on how you want to handle the remove, this approach will change but in terms of removing the behaviour, this should be what you're after.
Also, for animator state machines the approach is exactly the same, you just cast the selection object to an AnimatorStateMachine instead.
Hopefully this helps.
I'm implementing Powershell PSProvider for some internal hierarchical data. Everything works fine, I can navigate through the tree with usual cd/dir commands, the only thing doesn't work is tab completion.
What I can see is that Powershell calls function GetChildName() with an asterisk in the path when Tab is pressed (if I type "dir c" and press Tab, GetChildName() function will be called with string "c*", several times). I tried to return all child names from the folder that begins with "c", but Powershell always displays just the first child name in the front. I can't find any documentation about this behavior, what I'm missing?
Are you sure you aren't just seeing normal behavior? With the default Tab Expansion, you will only see the first result. Pressing tab additional times will cycle through the list of returned results from the provider.
There are some quirks with providers. I have been working on one using the Script Provider project. I put debug code in all my methods to see which ones PowerShell was calling, when, and with what arguments.
I found where's the problem - function GetChildName() in the provider shouldn't try to expand given file name if asterisk is part of the name; The function should return child name if it can find an exact match, or call base.GetChildName() in any other case. Something like this:
protected override string GetChildName(string path) {
string name = SomeFunctionThatTriesToFindExactMatchForGivenPath(path);
if(string.IsNullOrEmpty( ret ) )
ret = base.GetChildName( path );
return ret;
}
BTW, I found that default tab expansion is very forgiving about stuff that can be returned from GetChildName() function - even if return value have slash/backslash in the front/back, tab expansion will work. But PowerTab, popular tab expansion module, is much more picky about return values.
I am writing a small sample program and I would like to override the default pyglet's behavioyr of ESC closing the app. I have something to the extent of:
window = pyglet.window.Window()
#window.event
def on_key_press(symbol, modifiers):
if symbol == pyglet.window.key.ESCAPE:
pass
but that does not seem to work.
I know the question is old, but just in case. You've got to return pyglet.event.EVENT_HANDLED to prevent default behaviour. I didn't test it, but in theory this should work:
#window.event
def on_key_press(symbol, modifiers):
if symbol == pyglet.window.key.ESCAPE:
return pyglet.event.EVENT_HANDLED
Same for me. The question is old, but I've found out that you should use window handlers mechanisms, thus making the current event not to propagate further.
You can prevent the remaining event
handlers in the stack from receiving
the event by returning a true value.
The following event handler, when
pushed onto the window, will prevent
the escape key from exiting the
program:
def on_key_press(symbol, modifiers):
if symbol == key.ESCAPE:
return True
window.push_handlers(on_key_press)
Here is that link
On the Google group for pyglet-users it is suggest could overload the window.Window.on_key_press(), although there are no code example of it.
It's simple actually, subclass Window and overide the on_key_press, like this:
class MyWindow(pyglet.window.Window):
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE:
return pyglet.event.EVENT_HANDLED