I'm trying to understand Vala delegates with Gtk3.
I tested callback and lambda with no problem.
I wanna test a delegate callback, here my code :
using Gtk;
delegate void typeDelegate(Button button);
int main (string[] args) {
Gtk.init (ref args);
typeDelegate cb = cbLabelf;
var window = new Window ();
window.title = "First GTK+ Program";
window.border_width = 10;
window.window_position = WindowPosition.CENTER;
window.set_default_size (350, 70);
window.destroy.connect (Gtk.main_quit);
var button = new Button.with_label ("Click me!");
//button.clicked.connect (cb);
//button.clicked+= cb;
button.clicked.connect+=cb;
window.add (button);
window.show_all ();
Gtk.main ();
return 0;
}
void cbLabelf(Button button)
{
button.label = "tank yu";
}
I also red generated C code ( when i use lambda) to understand.
Here the compil error :
GTKsampleDelegate.vala:20.5-20.30: error: Arithmetic operation not supported for types Gtk.Button.clicked.connect' andtypeDelegate'
button.clicked.connect+=cb;
Well,
Seems that you want to get the intrinsic variable that holds the instance that emitted the signal, I find strange that vala doesn't let you use a delegate variable to obtain it via parameter, yet, you can use one of the forms below: using no delegation variable (A) or bypassing the error with a closure (B).
public class FooSignalClass : Object {
/* Gtk Button.clicked signal has the void f(void) signature */
public signal void on_foo ();
public void foo() {
on_foo();
}
}
public delegate void FooSignalFunc (FooSignalClass fooer);
void on_foo_handler (FooSignalClass fooer) {
long fooer_memory_address = (long)fooer;
GLib.message(#"fooer exists? $(fooer!=null).");
GLib.message(#"address=$fooer_memory_address.");
}
int main () {
var foo_signal = new FooSignalClass();
long fooer_memory_address = (long)foo_signal;
GLib.message(#"foo_signal address=$fooer_memory_address.");
/* Option A: Connect directly without the delegate variable */
foo_signal.on_foo.connect(on_foo_handler);
/* Option B: You cant use a delegate directly, bypass it with a closure */
FooSignalFunc func = on_foo_handler;
foo_signal.on_foo.connect((instance) => {
func(instance);
});
foo_signal.foo();
return 0;
}
Related
I am having a hard time wrapping my head around GStreamer event sending and handling. I understand the process, but can not achieve my desired outcome. I am developing a series of GStreamer plugins in tandem with a GStreamer main application. I have 3 plugins my_src which inherits from GstPushSrc, my_transform which inherits from GstBaseTransform and my_sink which inherits from GstBaseSink, and a main application my_app.
I am trying to send a custom event from my_app to all elements in the pipeline telling them to reconfigure the processing parameters. This is different from GST_EVENT_RECONFIGURE because it does not involve any renegotiation of caps. I am sending the event from my_app with the following:
// my_app.c
GstStructure *reconfigureStructure = gst_structure_new("reconfigure", NULL);
GstEvent *reconfigureEvent = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM,
reconfigureStructure);
gst_element_send_event(pipeline, reconfigureEvent);
I have overridden the GstBaseSrc event() method as follows:
// my_src.c
static gboolean my_src_event(GstBaseSrc *bs, GstEvent *event);
static void
my_src_class_init(MySrcClass *msc)
{
GstBaseSrcClass *bsc = GST_BASE_SRC_CLASS(msc);
bsc->event = my_src_event;
}
static gboolean
my_src_event(GstBaseSrc *bs, GstEvent *event)
{
switch (GST_EVENT_TYPE(event)) {
case GST_EVENT_CUSTOM_DOWNSTREAM: {
const GstStructure *structure = gst_event_get_structure(event);
if (gst_structure_has_name(structure, "reconfigure")) {
g_print("MY SRC RECONFIGURE\n");
// do reconfigure things
}
break;
}
}
return GST_BASE_SRC_CLASS(parent_class)->event(bs, event);
}
Similarly, I have overridden the GstBaseSink event handler as follows:
// my_sink.c
static gboolean my_sink_event(GstBaseSink *bs, GstEvent *event);
static void
my_sink_class_init(MySinkClass *msc)
{
GstBaseSinkClass *bsc = GST_BASE_SINK_CLASS(msc);
bsc->event = my_sink_event;
}
static gboolean
my_sink_event(GstBaseSink *bs, GstEvent *event)
{
switch (GST_EVENT_TYPE(event)) {
case GST_EVENT_CUSTOM_DOWNSTREAM: {
const GstStructure *structure = gst_event_get_structure(event);
if (gst_structure_has_name(structure, "reconfigure")) {
g_print("MY SINK RECONFIGURE\n");
// do reconfigure things
}
break;
}
}
return GST_BASE_SINK_CLASS(parent_class)->event(bs, event);
}
Lastly, I have overridden the GstBaseTransform sink_event() method as follows:
// my_transform.c
static gboolean my_transform_sink_event(GstBaseTransform *bt, GstEvent *event);
static void
my_transform_class_init(MyTransformClass *mtc)
{
GstBaseTransformClass *btc = GST_BASE_TRANDFORM_CLASS(mtc);
btc->sink_event = my_transform_sink_event;
}
static gboolean
my_transform_sink_event(GstBaseTransfor *bt, GstEvent *event)
{
switch (GST_EVENT_TYPE(event)) {
case GST_EVENT_CUSTOM_DOWNSTREAM: {
const GstStructure *structure = gst_event_get_structure(event);
if (gst_structure_has_name(structure, "reconfigure")) {
g_print("MY TRANSFORM RECONFIGURE\n");
// do reconfigure things
}
break;
}
}
return GST_BASE_TRANSFORM_CLASS(parent_class)->sink_event(bt, event);
}
When I run my_app I would expect the output to be:
MY SRC RECONFIGURE
MY TRANSFORM RECONFIGURE
MY SINK RECONFIGURE
However, I am only getting:
MY SINK RECONFIGURE
Any ideas what I am doing wrong here?
I'm learning RX and would like to use Console.ReadLine as a source for observable sequences.
I know that I can create "IEnumerable" using "yield return", but for my concrete use case I've decided to create a C# event, so that potentially many observers will be able to share the same keyboard input.
Here is my code:
class Program
{
private delegate void OnNewInputLineHandler(string line);
private static event OnNewInputLineHandler OnNewInputLineEvent = _ => {};
static void Main(string[] args)
{
Task.Run((Action) GetInput);
var input = ConsoleInput();
input.Subscribe(s=>Console.WriteLine("1: " + s));
Thread.Sleep(30000);
}
private static void GetInput()
{
while (true)
OnNewInputLineEvent(Console.ReadLine());
}
private static IObservable<string> ConsoleInput()
{
return Observable.Create<string>(
(IObserver<string> observer) =>
{
OnNewInputLineHandler h = observer.OnNext;
OnNewInputLineEvent += h;
return Disposable.Create(() => { OnNewInputLineEvent -= h; });
});
}
}
My problem - when I run the GetInput method as it is shown above, the very first input line is not sent to the sequence (but it is sent to the event handler).
However, if I replace it with the following version, everything works as expected:
private static void GetInput()
{
while (true)
{
var s = Console.ReadLine();
OnNewInputLineEvent(s);
}
}
Could someone shed some light on why this might happen?
You're trying to make life difficult for yourself. There is almost always a way to make things simple with Rx. It's just a matter of learning to think more functionally rather than procedurally.
This is all you need:
class Program
{
static void Main(string[] args)
{
var subscription = ConsoleInput().Subscribe(s => Console.WriteLine("1: " + s));
Thread.Sleep(30000);
subscription.Dispose();
}
private static IObservable<string> ConsoleInput()
{
return
Observable
.FromAsync(() => Console.In.ReadLineAsync())
.Repeat()
.Publish()
.RefCount()
.SubscribeOn(Scheduler.Default);
}
}
This lets multiple subscribers share the one input through the .Publish().RefCount(). And the .SubscribeOn(Scheduler.Default) pushes the subscription out to a new thread - without it you block on a subscription.
If you move Task.Run((Action) GetInput); to after the subscription your code will work as desired. This is because in your original version, the first call of OnNewInputEvent(Console.ReadLine()) is run before you've hooked OnNewInputLineEvent to the observer.OnNext.
I recently finished a 6-month internship at a company that uses C# for the most part of their programming. During this time I first used and got accustomed to the C# way of doing events. Like shown below:
acc.AccountBalanceLow += new AccountBalanceDelegate(atm.AccountToLow);
acc.AccountBalanceLow +=new AccountBalanceDelegate(atm.AccountToLowAgain);
Does D support such constructs? I'd imagine one could be created by the user by using operator overloading, but I'm not entirely sure. If it's not possible what would then be a common excepted way of doing it then?
The equivalent construct in D is to use Signals and Slots. This is a different means of implementing the Observer Pattern, which is effectively what a C# event does.
D (and C++) use an analogous pattern called signals and slots.
If you're feeling the need to use the C# style-events instead of signals and slots, they're extremely simple to implement:
module fluidity.core.event;
class Event {
alias void delegate(EventArgs) handler_t;
handler_t[] handlers;
Object owner;
this() {}
this(Object o) { owner = o; }
void attach(handler_t handler) {
if (handler)
handlers ~= handler;
}
void detach(handler_t handler) {
int i = -1;
foreach (j, h; handlers)
{
if (h is handler)
{
i = j;
break;
}
}
if (i > -1)
handlers = handlers[0..i] ~ handlers[i+1..$];
}
void raise() { raise(new EventArgs(owner)); }
void raise(EventArgs e) {
// call all handlers
foreach (handler; handlers)
{
if (handler)
handler(e);
}
}
void opAddAssign(handler_t handler) {
attach(handler);
}
void opSubAssign(handler_t handler) {
detach(handler);
}
}
class EventArgs {
Object source;
bool handled;
void handle() { handled = true; }
this() {}
this(Object s) {
source = s;
}
}
Here is an example of c# style events using signals, slots, and a templates:
events.d:
import std.signals;
class Event(T...){
mixin Signal!(T);
void broadcast(T args){
emit(args);
}
void opAddAssign(slot_t slot){
connect(slot);
}
void opSubAssign(slot_t slot) {
disconnect(slot);
}
}
declaration:
public Event!(int) onSomeEventOfInt;
public Event!(string, int) onSomeEventOfStringAndInt;
instantiation:
this.onSomeEventOfInt = new Event!(int)();
this.onSomeEventOfStringAndInt = new Event!(string, int)();
fire event:
int i = 4;
string str = "hello";
this.onSomeEventOfInt.broadcast(i);
this.onSomeEventOfStringAndInt.broadcast(str, 4);
observer registration:
obj1.onSomeEventOfInt += &handleEventOfInt
obj1.onSomeEventOfStringAndInt += &handleEventOfStringAndInt
void handleEventOfInt(int g)
{ /*do something */ }
void handleEventOfStringAndInt(string str, int g)
{ /*do something */ }
Check out DFL's event system. It works EXACTLY the same way as C# .NET.
DFL Event Example
Download DFL, grab the events module and use it the way you like. I modified it to use variadic template arguments. This gives maximum flexibility.
http://www.dprogramming.com/dfl098.zip
I have an windows forms application, with a form that holds 2 tabcontrols and a grid. I'd like to catch the pressing of esc key on any on this controls.
The question is : is it a simpler way to do that without subscribing to the keypress event on each control ?
Thanks!
You can Simply Do following.
Implement an IMessageFilter and Handle Key Down event.
Here is the complete Code to hook Escape Key Down.
public class MyKeboardHook:IMessageFilter
{
public const int WM_KEYDOWN = 0x0100;
public const int VK_ESCAPE = 0x1B;
public event EventHandler EscapeKeyDown;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_KEYDOWN && m.WParam == new IntPtr(VK_ESCAPE))
{
OnEscapeKeyPressed();
}
return false; //Do not Process anything
}
protected virtual void OnEscapeKeyDown()
{
if(this.EscapeKeyDown!=null)
{
EscapeKeyDown(this, EventArgs.Empty);
}
}
}
Now you need to register this. The best place would be in Main
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MyKeboardHook myKeboardHook = new MyKeboardHook();
myKeboardHook.EscapeKeyDown += (e, x) =>
{
MessageBox.Show("Escape Key Pressed");
};
Application.AddMessageFilter(myKeboardHook);
Application.Run(new Form1());
}
}
Subscribe to the event on the form itself.
If the control doesn't handle the event it should bubble up to the form where it will be handled.
I was wondering what's the proper way of raising events from C++/CLI. In C# one should first make a copy of the handler, check if it's not null, and then call it. Is there a similar practice for C++/CLI?
This isn't the whole story! You don't usually have to worry about null event handlers in C++/CLI. The code for these checks is generated for you. Consider the following trivial C++/CLI class.
public ref class MyClass
{
public:
event System::EventHandler ^ MyEvent;
};
If you compile this class, and disassemble it using Reflector, you get the following c# code.
public class MyClass
{
// Fields
private EventHandler <backing_store>MyEvent;
// Events
public event EventHandler MyEvent
{
[MethodImpl(MethodImplOptions.Synchronized)] add
{
this.<backing_store>MyEvent = (EventHandler) Delegate.Combine(this.<backing_store>MyEvent, value);
}
[MethodImpl(MethodImplOptions.Synchronized)] remove
{
this.<backing_store>MyEvent = (EventHandler) Delegate.Remove(this.<backing_store>MyEvent, value);
}
raise
{
EventHandler <tmp> = null;
<tmp> = this.<backing_store>MyEvent;
if (<tmp> != null)
{
<tmp>(value0, value1);
}
}
}
}
The usual checks are being done in the raise method. Unless you really want custom behavior, you should feel comfortable declaring your event as in the above class, and raising it without fear of a null handler.
C++/CLI allows you to override raise in custom event handlers so you don't have to test for null or copy when raising the event. Of course, inside your custom raise you still have to do this.
Example, adapted from the MSDN for correctness:
public delegate void f(int);
public ref struct E {
f ^ _E;
public:
void handler(int i) {
System::Console::WriteLine(i);
}
E() {
_E = nullptr;
}
event f^ Event {
void add(f ^ d) {
_E += d;
}
void remove(f ^ d) {
_E -= d;
}
void raise(int i) {
f^ tmp = _E;
if (tmp) {
tmp->Invoke(i);
}
}
}
static void Go() {
E^ pE = gcnew E;
pE->Event += gcnew f(pE, &E::handler);
pE->Event(17);
}
};
int main() {
E::Go();
}
If your issue is that raise isn't private, then explicitly implement it like the docs say:
http://msdn.microsoft.com/en-us/library/5f3csfsa.aspx
In summary:
If you just use the event keyword, you create a "trivial" event. The compiler generates add/remove/raise and the delegate member for you. The generated raise function (as the docs say) checks for nullptr. Trivial events are documented here:
http://msdn.microsoft.com/en-us/library/4b612y2s.aspx
If you want "more control", for example to make raise private, then you have to explicitly implement the members as shown in the link. You must explicitly declare a data member for the delegate type. Then you use the event keyword to declare the event-related members, as in the Microsoft example:
// event keyword introduces the scope wherein I'm defining the required methods
// "f" is my delegate type
// "Event" is the unrealistic name of the event itself
event f^ Event
{
// add is public (because the event block is public)
// "_E" is the private delegate data member of type "f"
void add(f ^ d) { _E += d; }
// making remove private
private:
void remove(f ^ d) { _E -= d; }
// making raise protected
protected:
void raise(int i)
{
// check for nullptr
if (_E)
{
_E->Invoke(i);
}
}
}// end event block
Wordy, but there it is.
-reilly.