# -*- mode: perl; coding: utf-8 -*- package YATT::Widget; use strict; use warnings FATAL => qw(all); BEGIN {require Exporter; *import = \&Exporter::import} use base qw(YATT::Class::Configurable); use YATT::Fields qw(^=arg_dict ^=arg_order ^=virtual_var_dict ^=argmacro_dict ^=argmacro_order ^cf_root ^cf_name ^cf_filename ^cf_declared ^cf_public cf_decl_start cf_body_start ^cf_template_nsid ^cf_no_last_newline ); use YATT::Types qw(:export_alias) , -alias => [Cursor => 'YATT::LRXML::NodeCursor' , Widget => __PACKAGE__]; use YATT::LRXML::Node qw(create_node); use YATT::Util qw(add_arg_order_in call_type); use Carp; sub after_configure { my MY $widget = shift; $widget->{cf_root} ||= $widget->create_node('root'); } sub cursor { my Widget $widget = shift; $widget->call_type(Cursor => new_opened => $widget->{cf_root}, @_); } sub add_arg { (my Widget $widget, my ($name, $arg)) = @_; add_arg_order_in($widget->{arg_dict}, $widget->{arg_order}, $name, $arg); $widget; } sub has_arg { (my Widget $widget, my ($name)) = @_; defined $widget->{arg_dict}{$name}; } sub has_virtual_var { (my Widget $widget, my ($name)) = @_; $widget->{virtual_var_dict}{$name} } sub add_virtual_var { (my Widget $widget, my ($name, $var)) = @_; $widget->{virtual_var_dict}{$name} = $var; } sub widget_scope { (my Widget $widget, my ($outer)) = @_; my $args = $widget->{arg_dict} ||= {}; if ($widget->{virtual_var_dict} and keys %{$widget->{virtual_var_dict}}) { [$args, [$widget->{virtual_var_dict}, $outer]]; } else { [$args, $outer]; } } sub copy_specs_from { (my Widget $this, my Widget $from) = @_; my @names; { my ($dict, $order) = $from->arg_specs; foreach my $name (@$order) { unless ($this->has_arg($name)) { $this->add_arg($name, $dict->{$name}->clone); } push @names, $name; } } { # XXX: 深く考え切れてない。 # order には Spec object が入っている。 # dict には Slot object が入っている my ($dst_dict, $dst_order) = $this->macro_specs; my ($src_dict, $src_order) = $from->macro_specs; push @$dst_order, @$src_order; foreach my $trigger (keys %$src_dict) { $dst_dict->{$trigger} ||= $src_dict->{$trigger}; } } @names; } sub arg_specs { (my Widget $widget) = @_; my @list = ($widget->{arg_dict} ||= {} , $widget->{arg_order} ||= []); wantarray ? @list : \@list; } sub get_arg_spec { (my Widget $widget, my ($name, $default)) = @_; my $dict = $widget->{arg_dict} or return $default; defined (my $spec = $dict->{$name}) or return $default; return $default unless exists $spec->{arg_dict}; $spec->{arg_dict}; } sub macro_specs { (my Widget $widget) = @_; my @list = ($widget->{argmacro_dict} ||= {} , $widget->{argmacro_order} ||= []); wantarray ? @list : \@list; } sub reorder_params { (my Widget $widget, my ($params)) = @_; my @params; foreach my $name (map($_ ? @$_ : (), $widget->{arg_order})) { push @params, delete $params->{$name}; } if (keys %$params) { die "Unknown args for $widget->{cf_name}: " . join(", ", keys %$params); } wantarray ? @params : \@params; } sub reorder_cgi_params { (my Widget $widget, my ($cgi, $list)) = @_; $list ||= []; foreach my $name ($cgi->param) { my $argdecl = $widget->{arg_dict}{$name} or die "Unknown args for widget '$widget->{cf_name}': $name"; my @value = $cgi->param($name); $list->[$argdecl->argno] = $argdecl->type_name eq 'list' ? \@value : $value[0]; } $list; } 1;