Merge branch 'master' into config
[amazing.git] / lib / amazing / widget.rb
blobd8259c99409c4f6fef570c8f7ae760491670306a
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/pango_markup'
16 require 'erb'
18 module Amazing
20   # Raised by widgets, and is then rescued and logged
21   class WidgetError < Exception
22   end
24   # Parent class for widget construction, example:
25   #
26   #   class Clock < Widget
27   #     description "Displays date and time"
28   #     dependency "some/library", "how to get the library (url, gem name...)"
29   #     option :time_format, "Time format as described in DATE(1)", "%R"
30   #     field :time, "Formatted time"
31   #     default "@time"
32   # 
33   #     init do
34   #       @time = Time.now.strftime(@time_format)
35   #       raise WidgetError, "An error occured!" if some_error?
36   #     end
37   #   end
38   class Widget
39     include Helpers::PangoMarkup
40     include ERB::Util
42     def initialize(opts={})
43       self.class.dependencies.each do |name, description|
44         begin
45           require name
46         rescue LoadError
47           raise WidgetError, "Missing dependency #{name.inspect}#{if description then " [#{description}]" end}"
48         end
49       end
50       self.class.options.each do |key, value|
51         instance_variable_set "@#{key}".to_sym, value[:default]
52       end
53       opts.each do |key, value|
54         instance_variable_set "@#{key}".to_sym, value
55       end
56       self.class.fields.each do |key, value|
57         instance_variable_set "@#{key}".to_sym, value[:default]
58       end
59       self.class.init.each do |block|
60         instance_eval(&block)
61       end
62       @default = case self.class.default
63       when Proc
64         instance_eval(&self.class.default)
65       when String
66         instance_eval(self.class.default)
67       end
68     end
70     def self.description(description=nil)
71       if description
72         @description = description
73       else
74         @description
75       end
76     end
78     def self.dependency(name, description=nil)
79       @dependencies ||= {}
80       @dependencies[name] = description
81     end
83     def self.dependencies
84       @dependencies || {}
85     end
87     def self.option(name, description=nil, default=nil)
88       @options ||= {}
89       @options[name] = {:description => description, :default => default}
90     end
92     def self.options
93       @options || {}
94     end
96     def self.field(name, description=nil, default=nil)
97       @fields ||= {}
98       @fields[name] = {:description => description, :default => default}
99     end
101     def self.fields
102       @fields || {}
103     end
105     def self.default(format=nil, &block) # :yields:
106       if format
107         @default = format
108       elsif block
109         @default = block
110       else
111         @default
112       end
113     end
115     def self.init(&block) # :yields:
116       if block
117         @init ||= []
118         @init << block
119       else
120         @init
121       end
122     end
124     def formatize(format=nil)
125       ERB.new(case format
126       when Proc
127         instance_eval(&format)
128       when String
129         instance_eval(format)
130       else
131         case self.class.default
132         when Proc
133           instance_eval(&self.class.default)
134         when String
135           instance_eval(self.class.default)
136         end
137       end.to_s).result(binding())
138     end
139   end