Mercurial > pub > Impl
comparison Lib/IMPL/Object/EventSource.pm @ 0:03e58a454b20
Создан репозитарий
author | Sergey |
---|---|
date | Tue, 14 Jul 2009 12:54:37 +0400 |
parents | |
children | 94d47b388442 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:03e58a454b20 |
---|---|
1 package IMPL::Object::EventSource; | |
2 use strict; | |
3 require IMPL::Exception; | |
4 use IMPL::Class::Property; | |
5 | |
6 sub CreateEvent { | |
7 my ($class,$event) = @_; | |
8 | |
9 die new IMPL::Exception('A name is required for the event') unless $event; | |
10 | |
11 (my $fullEventName = "$class$event") =~ s/:://g; | |
12 | |
13 my $globalEventTable = new IMPL::Object::EventSource::EventTable($fullEventName); | |
14 my $propEventTable = $event.'Table'; | |
15 public CreateProperty($class,$propEventTable,prop_all); | |
16 public CreateProperty($class,$event, | |
17 { | |
18 get => sub { | |
19 my $this = shift; | |
20 if (not defined wantarray and caller(1) eq $class) { | |
21 (ref $this ? $this->$propEventTable() || $globalEventTable : $globalEventTable)->Invoke($this); | |
22 } else { | |
23 if (ref $this) { | |
24 if (my $table = $this->$propEventTable()) { | |
25 return $table; | |
26 } else { | |
27 $table = new IMPL::Object::EventSource::EventTable($fullEventName,$globalEventTable); | |
28 $this->$propEventTable($table); | |
29 return $table; | |
30 } | |
31 } else { | |
32 return $globalEventTable; | |
33 } | |
34 } | |
35 }, | |
36 set => sub { | |
37 (ref $_[0] ? $_[0]->$propEventTable() || $globalEventTable : $globalEventTable)->Invoke(@_); | |
38 } | |
39 } | |
40 ); | |
41 } | |
42 | |
43 sub CreateStaticEvent { | |
44 my ($class,$event) = @_; | |
45 | |
46 die new IMPL::Exception('A name is required for the event') unless $event; | |
47 | |
48 (my $fullEventName = "$class$event") =~ s/:://g; | |
49 | |
50 my $globalEventTable = new IMPL::Object::EventSource::EventTable($fullEventName); | |
51 | |
52 no strict 'refs'; | |
53 *{"${class}::$event"} = sub { | |
54 my $class = shift; | |
55 if (not @_) { | |
56 if (not defined wantarray and caller(1) eq $class) { | |
57 $globalEventTable->Invoke($class); | |
58 } else { | |
59 return $globalEventTable; | |
60 } | |
61 } else { | |
62 $globalEventTable->Invoke(@_); | |
63 } | |
64 }; | |
65 } | |
66 | |
67 package IMPL::Object::EventSource::EventTable; | |
68 use base qw(IMPL::Object); | |
69 use IMPL::Class::Property; | |
70 use IMPL::Class::Property::Direct; | |
71 use Scalar::Util qw(weaken); | |
72 | |
73 use overload | |
74 '+=' => \&opSubscribe, | |
75 'fallback' => 1; | |
76 | |
77 BEGIN { | |
78 public _direct property Name => prop_get; | |
79 public _direct property Handlers => { get => \&get_handlers }; | |
80 private _direct property Next => prop_all; | |
81 private _direct property NextId => prop_all; | |
82 } | |
83 | |
84 sub CTOR { | |
85 my $this = shift; | |
86 $this->SUPER::CTOR(); | |
87 | |
88 $this->{$Handlers} = {}; | |
89 $this->{$Name} = shift; | |
90 $this->{$Next} = shift; | |
91 $this->{$NextId} = 1; | |
92 } | |
93 | |
94 sub get_handlers { | |
95 my $this = shift; | |
96 return values %{$this->{$Handlers}}; | |
97 } | |
98 | |
99 sub Invoke { | |
100 my $this = shift; | |
101 | |
102 my $tmp; | |
103 $tmp = $_ and local($_) or &$tmp(@_) foreach values %{$this->{$Handlers}}; | |
104 | |
105 $this->{$Next}->Invoke(@_) if $this->{$Next}; | |
106 } | |
107 | |
108 sub Subscribe { | |
109 my ($this,$consumer,$nameHandler) = @_; | |
110 | |
111 my $id = $this->{$NextId} ++; | |
112 | |
113 if (ref $consumer eq 'CODE') { | |
114 $this->{$Handlers}{$id} = $consumer; | |
115 } else { | |
116 $nameHandler ||= $this->Name or die new IMPL::Exception('The name for the event handler method must be specified'); | |
117 my $method = $consumer->can($nameHandler) or die new IMPL::Exception('Can\'t find the event handler method',$nameHandler,$consumer); | |
118 | |
119 weaken($consumer) if ref $consumer; | |
120 $this->{$Handlers}{$id} = sub { | |
121 unshift @_, $consumer; | |
122 $consumer ? goto &$method : delete $this->{$Handlers}{$id}; | |
123 }; | |
124 } | |
125 | |
126 return $id; | |
127 } | |
128 | |
129 sub Remove { | |
130 my ($this,$id) = @_; | |
131 return delete $this->{$Handlers}{$id}; | |
132 } | |
133 1; |