Framework for lazy data [#5 state:resolved]
[amazing.git] / lib / amazing / widget.rb
blob95335e44f40836bae6b8cd488f1f0c55677f29cc
1 # Copyright 2008 Dag Odenhall <dag.odenhall@gmail.com>
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 #    http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 require 'amazing/helpers/lazy_data'
16 require 'amazing/helpers/pango_markup'
17 require 'erb'
19 module Amazing
21   # Raised by widgets, and is then rescued and logged
22   class WidgetError < Exception
23   end
25   # Parent class for widget construction, example:
26   #
27   #   class Clock < Widget
28   #     description "Displays date and time"
29   #     dependency "some/library", "how to get the library (url, gem name...)"
30   #     option :time_format, "Time format as described in DATE(1)", "%R"
31   #     field :time, "Formatted time"
32   #     default "@time"
33   # 
34   #     init do
35   #       @time = Time.now.strftime(@time_format)
36   #       raise WidgetError, "An error occured!" if some_error?
37   #     end
38   #   end
39   class Widget
40     include Helpers::LazyData
41     include Helpers::PangoMarkup
42     include ERB::Util
44     def initialize(opts={})
45       self.class.dependencies.each do |name, description|
46         begin
47           require name
48         rescue LoadError
49           raise WidgetError, "Missing dependency #{name.inspect}#{if description then " [#{description}]" end}"
50         end
51       end
52       self.class.options.each do |key, value|
53         instance_variable_set "@#{key}".to_sym, value[:default]
54       end
55       opts.each do |key, value|
56         instance_variable_set "@#{key}".to_sym, value
57       end
58       self.class.fields.each do |key, value|
59         instance_variable_set "@#{key}".to_sym, value[:default]
60       end
61       self.class.init.each do |block|
62         instance_eval(&block)
63       end
64       @default = case self.class.default
65       when Proc
66         instance_eval(&self.class.default)
67       when String
68         instance_eval(self.class.default)
69       end
70     end
72     def self.description(description=nil)
73       if description
74         @description = description
75       else
76         @description
77       end
78     end
80     def self.dependency(name, description=nil)
81       @dependencies ||= {}
82       @dependencies[name] = description
83     end
85     def self.dependencies
86       @dependencies || {}
87     end
89     def self.option(name, description=nil, default=nil)
90       @options ||= {}
91       @options[name] = {:description => description, :default => default}
92     end
94     def self.options
95       @options || {}
96     end
98     def self.field(name, description=nil, default=nil)
99       @fields ||= {}
100       @fields[name] = {:description => description, :default => default}
101     end
103     def self.fields
104       @fields || {}
105     end
107     def self.default(format=nil, &block) # :yields:
108       if format
109         @default = format
110       elsif block
111         @default = block
112       else
113         @default
114       end
115     end
117     def self.init(&block) # :yields:
118       if block
119         @init ||= []
120         @init << block
121       else
122         @init
123       end
124     end
126     def formatize(format=nil)
127       ERB.new(case format
128       when Proc
129         instance_eval(&format)
130       when String
131         instance_eval(format)
132       else
133         case self.class.default
134         when Proc
135           instance_eval(&self.class.default)
136         when String
137           instance_eval(self.class.default)
138         end
139       end.to_s).result(binding())
140     end
141   end