/[suikacvs]/messaging/manakai/lib/Message/DOM/CSSStyleDeclaration.pm
Suika

Contents of /messaging/manakai/lib/Message/DOM/CSSStyleDeclaration.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.13 - (show annotations) (download)
Fri Jan 25 16:06:13 2008 UTC (16 years, 10 months ago) by wakaba
Branch: MAIN
Changes since 1.12: +63 -35 lines
++ manakai/lib/Message/DOM/ChangeLog	25 Jan 2008 16:06:00 -0000
2008-01-26  Wakaba  <wakaba@suika.fam.cx>

	* CSSStyleDeclaration.pm: Use |serialize_shorthand|
	and |serialize_multiple| to serialize shorthand properties
	in reflecting attributes.  Return value of
	the |serialzie_multiple| function has been changed.
	(non-computed css_text): Sort by property names.

1 package Message::DOM::CSSStyleDeclaration;
2 use strict;
3 our $VERSION=do{my @r=(q$Revision: 1.12 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
4 push our @ISA, 'Message::IF::CSSStyleDeclaration',
5 'Message::IF::CSS2Properties';
6
7 sub ____new ($) {
8 return bless \{}, $_[0];
9 } # ____new
10
11 sub AUTOLOAD {
12 my $method_name = our $AUTOLOAD;
13 $method_name =~ s/.*:://;
14 return if $method_name eq 'DESTROY';
15
16 require Whatpm::CSS::Parser;
17 my $prop_def = $Whatpm::CSS::Parser::Attr->{$method_name};
18
19 if ($prop_def) {
20 no strict 'refs';
21 if ($prop_def->{serialize}) {
22 *{ $method_name } = sub {
23 ## TODO: setter
24
25 my $self = $_[0];
26 my $value = $$self->{$prop_def->{key}};
27 if ($value) {
28 return $prop_def->{serialize}->($self, $prop_def->{css}, $value->[0]);
29 } else {
30 return '';
31 }
32 };
33 } elsif ($prop_def->{serialize_shorthand} or
34 $prop_def->{serialize_multiple}) {
35 *{ $method_name } = sub {
36 ## TODO: setter
37
38 my $self = $_[0];
39 my $v = ($prop_def->{serialize_shorthand} or
40 $prop_def->{serialize_multiple})->($self);
41 if (defined $v->{$prop_def->{css}}) {
42 return $v->{$prop_def->{css}}->[0];
43 } else {
44 return '';
45 }
46 ## ISSUE: If one of shorthand component properties is !important?
47 };
48 } else {
49 die qq<Implementation error: Can't load serializer for "$AUTOLOAD">;
50 }
51 goto &{ $AUTOLOAD };
52 } else {
53 require Carp;
54 Carp::croak (qq<Can't locate method "$AUTOLOAD">);
55 }
56 } # AUTOLOAD
57
58 use overload
59 '@{}' => sub {
60 tie my @list, ref $_[0], $_[0];
61 return \@list;
62 },
63 fallback => 1;
64
65 sub TIEARRAY ($$) { $_[1] }
66
67 ## |CSSStyleDeclaration| attributes
68
69 sub css_text ($;$) {
70 ## TODO: setter
71
72 ## NOTE: Where and how white space characters are inserted are
73 ## intentionally changed from those in browsers so that properties are
74 ## more prettily printed.
75 ## See <http://suika.fam.cx/gate/2005/sw/cssText> for what browsers do.
76 ## TODO: Ordering issue.
77 require Whatpm::CSS::Parser;
78 my $self = $_[0];
79 my $r = '';
80 my %serialized;
81 for (sort {$a cmp $b} grep {$$self->{$_}} keys %$$self) {
82 my $prop_def = $Whatpm::CSS::Parser::Key->{$_};
83 next unless $prop_def;
84
85 if ($prop_def->{serialize_multiple}) {
86 unless ($serialized{$prop_def->{serialize_multiple}}) {
87 $serialized{$prop_def->{serialize_multiple}} = 1;
88 my $v = $prop_def->{serialize_multiple}->($self);
89 for my $prop_name (sort {$a cmp $b} keys %$v) {
90 $r .= ' ' . $prop_name . ': ' . $v->{$prop_name}->[0]
91 . $v->{$prop_name}->[1] . ";\n"
92 }
93 }
94 } else {
95 my $value = $$self->{$_};
96 my $s = $prop_def->{serialize}->($self, $prop_def->{css}, $value->[0]);
97 if (length $s) {
98 $r .= ' ' . $prop_def->{css} . ': ' . $s;
99 $r .= ' ! ' . $value->[1] if length $value->[1];
100 $r .= ";\n";
101 }
102 }
103 }
104 return $r;
105 } # css_text
106
107 sub length ($) {
108 require Whatpm::CSS::Parser;
109 return scalar @{[grep {$_}
110 map { $Whatpm::CSS::Parser::Key->{$_} }
111 keys %${$_[0]}]->[$_[1]]};
112 } # length
113 *FETCHSIZE = \&length;
114
115 ## TODO: STORESIZE
116
117 sub parent_rule ($) {
118 return ${$_[0]}->{parent_rule};
119 } # parent_rule
120
121 ## |CSSStyleDeclaration| methods
122
123 sub get_property_priority ($$) {
124 my $prop_name = ''.$_[1];
125
126 require Whatpm::CSS::Parser;
127 my $prop_def = $Whatpm::CSS::Parser::Prop->{$prop_name};
128 return '' unless defined $prop_def;
129
130 my $v = ${$_[0]}->{$prop_def->{key}};
131 return $v ? $v->[1] : '';
132 } # get_property_priority
133
134 sub item ($$) {
135 require Whatpm::CSS::Parser;
136 return '' if $_[1] < 0;
137 ## TODO: ordering (should be same as that in |css_text|.
138 my $v = [map {$_->{key}}
139 grep {$_}
140 map { $Whatpm::CSS::Parser::Key->{$_} }
141 keys %${$_[0]}]->[$_[1]];
142 return defined $v ? $v : '';
143 } # item
144 *FETCH = \&item;
145
146 ## TODO: STORE, DELETE
147
148 sub EXISTS ($$) {
149 return length $_[0]->item;
150 } # EXISTS
151
152 ## TODO: Implement other methods and attributes
153
154 package Message::DOM::CSSComputedStyleDeclaration;
155 push our @ISA, 'Message::IF::CSSStyleDeclaration',
156 'Message::IF::CSS2Properties';
157
158 sub ____new ($$$) {
159 my $self = bless \{}, shift;
160 $$self->{cascade} = shift; # Whatpm::CSS::Cascade object.
161 $$self->{element} = shift; ## TODO: This link should be weaken?
162 return $self;
163 } # ____new
164
165 sub AUTOLOAD {
166 my $method_name = our $AUTOLOAD;
167 $method_name =~ s/.*:://;
168 return if $method_name eq 'DESTROY';
169
170 require Whatpm::CSS::Parser;
171 my $prop_def = $Whatpm::CSS::Parser::Attr->{$method_name};
172
173 if ($prop_def) {
174 no strict 'refs';
175 if ($prop_def->{compute} or $prop_def->{compute_multiple}) {
176 *{ $method_name } = sub {
177 ## TODO: setter
178
179 my $self = $_[0];
180 my $value = $$self->{cascade}->get_computed_value
181 ($$self->{element}, $prop_def->{css});
182 if ($value) {
183 return $prop_def->{serialize}->($self, $prop_def->{css}, $value);
184 } else {
185 return '';
186 }
187 };
188 } elsif ($prop_def->{serialize_shorthand} or
189 $prop_def->{serialize_multiple}) {
190 *{ $method_name } = sub {
191 ## TODO: setter
192 my $self = shift;
193
194 my $v = ($prop_def->{serialize_shorthand} or
195 $prop_def->{serialize_multiple})->($self);
196 if (defined $v->{$prop_def->{css}}) {
197 return $v->{$prop_def->{css}}->[0];
198 } else {
199 return '';
200 }
201 };
202 } else {
203 ## TODO: This should be an error of the implementation.
204 ## However, currently some shorthand properties does not have
205 ## serializer.
206 ## TODO: Remove {serialize} from shorthand properties, since
207 ## they have no effect.
208 warn "$0: No computed value function for $method_name";
209 #die "$0: No computed value function for $method_name";
210 *{ $method_name } = sub { };
211 }
212 goto &{ $AUTOLOAD };
213 } else {
214 require Carp;
215 Carp::croak (qq<Can't locate method "$AUTOLOAD">);
216 }
217 } # AUTOLOAD
218
219 use overload
220 '@{}' => sub {
221 tie my @list, ref $_[0], $_[0];
222 return \@list;
223 },
224 fallback => 1;
225
226 sub TIEARRAY ($$) { $_[1] }
227
228 ## |CSSStyleDeclaration| attributes
229
230 sub css_text ($;$) {
231 ## TODO: error if modified
232
233 my $self = shift;
234 require Whatpm::CSS::Parser;
235
236 ## NOTE: Where and how white space characters are inserted are
237 ## intentionally changed from those in browsers so that properties are
238 ## more prettily printed.
239 ## See <http://suika.fam.cx/gate/2005/sw/cssText> for what browsers do.
240 ## TODO: ordering
241 ## TODO: any spec?
242 my $r = '';
243 my %serialized;
244 for my $prop_def (sort {$a->{css} cmp $b->{css}}
245 grep {$_->{compute} or
246 $_->{compute_multiple} or
247 $_->{serialize_multiple}}
248 values %$Whatpm::CSS::Parser::Prop) {
249 if ($prop_def->{serialize_multiple}) {
250 unless ($serialized{$prop_def->{serialize_multiple}}) {
251 $serialized{$prop_def->{serialize_multiple}} = 1;
252 my $v = $prop_def->{serialize_multiple}->($self);
253 for my $prop_name (sort {$a cmp $b} keys %$v) {
254 $r .= ' ' . $prop_name . ': ' . $v->{$prop_name}->[0]
255 . $v->{$prop_name}->[1] . ";\n"
256 }
257 }
258 } else {
259 my $prop_value = $$self->{cascade}->get_computed_value
260 ($$self->{element}, $prop_def->{css});
261 my $s = $prop_def->{serialize}->($self, $prop_def->{css}, $prop_value);
262 if (length $s) {
263 $r .= ' ' . $prop_def->{css} . ': ' . $s;
264 $r .= ";\n";
265 } else {
266 ## NOTE: This should be an error of the implementation.
267 $r .= " /* $prop_def->{css}: ???; */\n";
268 }
269 }
270 }
271
272 ## ISSUE: Should we include CSS properties that are not supported?
273
274 return $r;
275 } # css_text
276
277 ## TODO: What should we enumerate is unclear.
278 sub length ($) {
279 require Whatpm::CSS::Parser;
280 return scalar @{[grep {$_}
281 values %$Whatpm::CSS::Parser::Key]};
282 } # length
283 *FETCHSIZE = \&length;
284
285 ## TODO: STORESIZE
286
287 ## |CSSStyleDeclaration| methods
288
289 sub get_property_priority ($$) { '' }
290
291 sub item ($$) {
292 require Whatpm::CSS::Parser;
293 return '' if $_[1] < 0;
294 ## TODO: ordering (should be same as that in |css_text|.
295 my $v = [sort {$a cmp $b}
296 map {$_->{css}}
297 grep {$_}
298 values %$Whatpm::CSS::Parser::Key]->[$_[1]];
299 return defined $v ? $v : '';
300 } # item
301 *FETCH = \&item;
302
303 ## TODO: STORE, DELETE
304
305 sub EXISTS ($$) {
306 return length $_[0]->item;
307 } # EXISTS
308
309 ## TODO: members
310
311 package Message::IF::CSSStyleDeclaration;
312 package Message::IF::CSS2Properties;
313
314 1;
315 ## $Date: 2008/01/14 13:56:35 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24