cheri 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README +98 -0
  3. data/Rakefile +121 -0
  4. data/examples/hello_world_1.rb +28 -0
  5. data/examples/table_1.rb +44 -0
  6. data/lib/cheri/awt.rb +41 -0
  7. data/lib/cheri/builder.rb +31 -0
  8. data/lib/cheri/builder/awt/connecter.rb +63 -0
  9. data/lib/cheri/builder/awt/constants.rb +1003 -0
  10. data/lib/cheri/builder/awt/main.rb +191 -0
  11. data/lib/cheri/builder/awt/types.rb +220 -0
  12. data/lib/cheri/builder/base.rb +533 -0
  13. data/lib/cheri/builder/config.rb +187 -0
  14. data/lib/cheri/builder/connecter.rb +386 -0
  15. data/lib/cheri/builder/context.rb +655 -0
  16. data/lib/cheri/builder/generator.rb +425 -0
  17. data/lib/cheri/builder/html/charsets.rb +154 -0
  18. data/lib/cheri/builder/html/common.rb +32 -0
  19. data/lib/cheri/builder/html/connecter.rb +57 -0
  20. data/lib/cheri/builder/html/element.rb +156 -0
  21. data/lib/cheri/builder/html/main.rb +116 -0
  22. data/lib/cheri/builder/html/types.rb +123 -0
  23. data/lib/cheri/builder/main.rb +483 -0
  24. data/lib/cheri/builder/swing/connecter.rb +141 -0
  25. data/lib/cheri/builder/swing/constants.rb +420 -0
  26. data/lib/cheri/builder/swing/main.rb +446 -0
  27. data/lib/cheri/builder/swing/types.rb +270 -0
  28. data/lib/cheri/builder/xml/charsets.rb +154 -0
  29. data/lib/cheri/builder/xml/common.rb +32 -0
  30. data/lib/cheri/builder/xml/connecter.rb +42 -0
  31. data/lib/cheri/builder/xml/element.rb +189 -0
  32. data/lib/cheri/builder/xml/main.rb +130 -0
  33. data/lib/cheri/builder/xml/types.rb +36 -0
  34. data/lib/cheri/cheri.rb +70 -0
  35. data/lib/cheri/cjx.rb +3 -0
  36. data/lib/cheri/explorer.rb +32 -0
  37. data/lib/cheri/explorer/explorer.rb +560 -0
  38. data/lib/cheri/html.rb +31 -0
  39. data/lib/cheri/image/Delete24.gif +0 -0
  40. data/lib/cheri/image/Find24.gif +0 -0
  41. data/lib/cheri/image/FindAgain24.gif +0 -0
  42. data/lib/cheri/image/Refresh24.gif +0 -0
  43. data/lib/cheri/image/Search24.gif +0 -0
  44. data/lib/cheri/image/Thumbs.db +0 -0
  45. data/lib/cheri/image/cheri_icon_16x16.png +0 -0
  46. data/lib/cheri/image/cheri_icon_24x24.png +0 -0
  47. data/lib/cheri/image/cheri_logo_medium.png +0 -0
  48. data/lib/cheri/image/close_10x10.png +0 -0
  49. data/lib/cheri/image/close_10x10s.png +0 -0
  50. data/lib/cheri/image/close_12x12.png +0 -0
  51. data/lib/cheri/image/close_14x14.png +0 -0
  52. data/lib/cheri/image/close_24x24.png +0 -0
  53. data/lib/cheri/image/close_dim2_12x12.png +0 -0
  54. data/lib/cheri/image/close_dim_12x12.png +0 -0
  55. data/lib/cheri/image/cls_tree.png +0 -0
  56. data/lib/cheri/image/con_tree.png +0 -0
  57. data/lib/cheri/image/jruby_14x16.png +0 -0
  58. data/lib/cheri/image/jruby_logo.png +0 -0
  59. data/lib/cheri/image/mod_tree.png +0 -0
  60. data/lib/cheri/image/obj_tree.png +0 -0
  61. data/lib/cheri/image/ruby_16x16.png +0 -0
  62. data/lib/cheri/image/vars_tree.png +0 -0
  63. data/lib/cheri/java.rb +26 -0
  64. data/lib/cheri/java/builder.rb +28 -0
  65. data/lib/cheri/java/builder/main.rb +407 -0
  66. data/lib/cheri/java/builder/util.rb +480 -0
  67. data/lib/cheri/java/java.rb +56 -0
  68. data/lib/cheri/jruby.rb +32 -0
  69. data/lib/cheri/jruby/explorer.rb +43 -0
  70. data/lib/cheri/jruby/explorer/common.rb +38 -0
  71. data/lib/cheri/jruby/explorer/dialogs.rb +383 -0
  72. data/lib/cheri/jruby/explorer/explorer.rb +904 -0
  73. data/lib/cheri/jruby/explorer/splash.rb +80 -0
  74. data/lib/cheri/jruby/explorer/viewer.rb +619 -0
  75. data/lib/cheri/jruby/explorer/viewers.rb +1057 -0
  76. data/lib/cheri/jruby/jruby.rb +59 -0
  77. data/lib/cheri/swing.rb +41 -0
  78. data/lib/cheri/xml.rb +31 -0
  79. metadata +135 -0
@@ -0,0 +1,191 @@
1
+ #--
2
+ # Copyright (C) 2007 William N Dortch <bill.dortch@gmail.com>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+ #
24
+
25
+
26
+ module Cheri
27
+ # TODO: module comments
28
+ module AWT
29
+ VERSION = Cheri::VERSION
30
+
31
+ include Cheri::Builder
32
+
33
+ CJava = Cheri::Java #:nodoc:
34
+ CBuilder = Cheri::Builder #:nodoc:
35
+ JBuilder = Cheri::Java::Builder #:nodoc:
36
+ class << self
37
+ def append_features(clazz)
38
+ CBuilder.module_included(JBuilder,clazz)
39
+ CBuilder.module_included(self,clazz)
40
+ super
41
+ end
42
+ private :append_features
43
+
44
+ def factory
45
+ AWTFactory
46
+ end
47
+
48
+ def connecter
49
+ AWTConnecter
50
+ end
51
+
52
+ def consumer
53
+ AWTConsumer
54
+ end
55
+
56
+ def resolver
57
+ AWTResolver
58
+ end
59
+
60
+ # call-seq:
61
+ # mod.prepare(context, parent, object, sym, properties=nil) -> prepared?
62
+ #
63
+ # def prepare(*r)
64
+ # AWTConnecter.prepare(*r)
65
+ # end
66
+
67
+ end #self
68
+
69
+
70
+ # call-seq:
71
+ # awt([*args] [, &block]) -> AWTProxy if no block given, else result of block
72
+ #
73
+ def awt(*r,&k)
74
+ if (ctx = __cheri_ctx)
75
+ if k
76
+ AWTFrame.new(ctx,*r,&k).run
77
+ else
78
+ ctx[:awt_proxy] ||= AWTProxy.new(ctx,*r)
79
+ end
80
+ end
81
+ end
82
+ private :awt
83
+
84
+
85
+ class AWTClassBuilder < Cheri::Java::Builder::ClassBuilder
86
+ Frame = CJava.get_class('java.awt.Frame')
87
+ def mod
88
+ Cheri::AWT
89
+ end
90
+ private
91
+ def post
92
+ @obj.icon_image ||= CJava.cheri_icon.image if @obj.kind_of?(Frame)
93
+ end
94
+ end
95
+
96
+ module StandardFactory
97
+ T = Cheri::AWT::Types #:nodoc:
98
+ def self.builder(ctx,sym,*r,&k)
99
+ clazz = T.get_class(sym)
100
+ clazz ? AWTClassBuilder.new(ctx,sym,clazz,*r,&k) : nil
101
+ end
102
+ end #AWTFactory
103
+
104
+ AWTFactory = Cheri::Builder::SuperFactory.new do |f|
105
+ f << StandardFactory
106
+ f << Cheri::Java::Builder::CheriYieldFactory
107
+ f << Cheri::Java::Builder::CherifyFactory
108
+ f << Cheri::Builder::CheriYieldFactory
109
+ f << Cheri::Builder::CherifyFactory
110
+ end
111
+
112
+ class AWTProxy < Cheri::Builder::BaseProxy
113
+
114
+ impl(Types.names)
115
+
116
+ def initialize(ctx,*r)
117
+ super
118
+ if Hash === r.last
119
+ @ctx.auto!(mod) if r.last[:auto]
120
+ end
121
+ end
122
+
123
+ def mod
124
+ Cheri::AWT
125
+ end
126
+ private :mod
127
+
128
+ def [](opts)
129
+ raise Cheri.type_error(opts,Hash) unless Hash === opts
130
+ if opts[:auto]
131
+ @ctx.ictx.auto!(mod)
132
+ @ctx.auto!(mod)
133
+ end
134
+ self
135
+ end
136
+ end #AWTProxy
137
+
138
+ class AWTFrame
139
+ include Cheri::Builder::Frame
140
+ def initialize(ctx,*r,&k)
141
+ super
142
+ @obj = ctx[:awt_proxy] ||= AWTProxy.new(ctx,*r)
143
+ end
144
+ def mod
145
+ Cheri::AWT
146
+ end
147
+ end #AWTFrame
148
+
149
+ module SizeMethodConsumer
150
+ #:stopdoc:
151
+ Meths = {
152
+ :minimum_size => :minimum_size=,
153
+ :set_minimum_size => :minimum_size=,
154
+ :maximum_size => :maximum_size=,
155
+ :set_maximum_size => :maximum_size=,
156
+ :preferred_size => :preferred_size=,
157
+ :set_preferred_size => :preferred_size=,
158
+ :fixed_size => true
159
+ }.freeze
160
+ Cmp = ::Java::JavaAwt::Component
161
+ Dim = ::Java::JavaAwt::Dimension
162
+ #:startdoc:
163
+ def self.consume(ctx,bld,sym,*args,&block)
164
+ return false,nil unless (meth = Meths[sym]) && args.length == 2 &&
165
+ Cmp === (obj = bld.object) && Fixnum === (w = args[0]) && Fixnum === (h = args[1])
166
+ dim = Dim.new w,h
167
+ if :fixed_size == sym
168
+ obj.minimum_size = dim
169
+ obj.maximum_size = dim
170
+ obj.preferred_size = dim
171
+ else
172
+ obj.__send__(meth,dim)
173
+ end
174
+ return true, nil
175
+ end
176
+ end
177
+
178
+ AWTConsumer = Cheri::Builder::SuperConsumer.new do |c|
179
+ c << SizeMethodConsumer
180
+ c << Cheri::Java::Builder::EventMethodConsumer
181
+ c << Cheri::Java::Builder::GenericConsumer
182
+ c << Cheri::Builder::DefaultConsumer
183
+ end
184
+
185
+ AWTResolver = Cheri::Java::Builder::ConstantResolver.new do |r|
186
+ r << Constants
187
+ end
188
+
189
+
190
+ end #AWT
191
+ end #Cheri
@@ -0,0 +1,220 @@
1
+ #--
2
+ # Copyright (C) 2007 William N Dortch <bill.dortch@gmail.com>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+ #
24
+
25
+
26
+ module Cheri
27
+ module AWT
28
+ module Types
29
+ CJava = Cheri::Java
30
+ JA = 'java.awt.'.freeze
31
+ class << self
32
+ def get_class(y)
33
+ # TODO: threadsafe support? Probably not necessary if we're not adding keys.
34
+ c = @classes[y]
35
+ if c
36
+ if c.instance_of?(String)
37
+ c = CJava.get_class(JA + c)
38
+ @classes[y] = c if c
39
+ end
40
+ c
41
+ else
42
+ nil
43
+ end
44
+ end
45
+ def names
46
+ @names ||= @classes.keys
47
+ end
48
+ end #self
49
+ # TODO: review included classes; some of these would
50
+ # never be called in a builder context
51
+ @classes = {
52
+ :alpha_composite => 'AlphaComposite',
53
+ :awt_event => 'AWTEvent',
54
+ :awt_event_multicaster => 'AWTEventMulticaster',
55
+ :awt_key_stroke => 'AWTKeyStroke',
56
+ :awt_permission => 'AWTPermission',
57
+ :basic_stroke => 'BasicStroke',
58
+ :border_layout => 'BorderLayout',
59
+ :buffer_capabilities => 'BufferCapabilities',
60
+ :buffer_capabilities_flip_contents => 'BufferCapabilities::FlipContents',
61
+ :button => 'Button',
62
+ :canvas => 'Canvas',
63
+ :card_layout => 'CardLayout',
64
+ :checkbox => 'Checkbox',
65
+ :checkbox_group => 'CheckboxGroup',
66
+ :checkbox_menu_item => 'CheckboxMenuItem',
67
+ :choice => 'Choice',
68
+ :color => 'Color',
69
+ :component => 'Component',
70
+ :component_orientation => 'ComponentOrientation',
71
+ :container => 'Container',
72
+ :container_order_focus_traversal_policy => 'ContainerOrderFocusTraversalPolicy',
73
+ :cursor => 'Cursor',
74
+ :default_focus_traversal_policy => 'DefaultFocusTraversalPolicy',
75
+ :default_keyboard_focus_manager => 'DefaultKeyboardFocusManager',
76
+ :desktop => 'Desktop',
77
+ :dialog => 'Dialog',
78
+ :dimension => 'Dimension',
79
+ :display_mode => 'DisplayMode',
80
+ :event => 'Event',
81
+ :event_queue => 'EventQueue',
82
+ :file_dialog => 'FileDialog',
83
+ :flow_layout => 'FlowLayout',
84
+ :focus_traversal_policy => 'FocusTraversalPolicy',
85
+ :font => 'Font',
86
+ :font_metrics => 'FontMetrics',
87
+ :frame => 'Frame',
88
+ :gradient_paint => 'GradientPaint',
89
+ :graphics => 'Graphics',
90
+ :graphics_2d => 'Graphics2D',
91
+ :graphics_config_template => 'GraphicsConfigTemplate',
92
+ :graphics_configuration => 'GraphicsConfiguration',
93
+ :graphics_device => 'GraphicsDevice',
94
+ :graphics_environment => 'GraphicsEnvironment',
95
+ :grid_bag_constraints => 'GridBagConstraints',
96
+ :grid_bag_layout => 'GridBagLayout',
97
+ :grid_bag_layout_info => 'GridBagLayoutInfo',
98
+ :grid_layout => 'GridLayout',
99
+ :image => 'Image',
100
+ :image_capabilities => 'ImageCapabilities',
101
+ :insets => 'Insets',
102
+ :job_attributes => 'JobAttributes',
103
+ :keyboard_focus_manager => 'KeyboardFocusManager',
104
+ :label => 'Label',
105
+ :linear_gradient_paint => 'LinearGradientPaint',
106
+ :list => 'List',
107
+ :media_tracker => 'MediaTracker',
108
+ :menu => 'Menu',
109
+ :menu_bar => 'MenuBar',
110
+ :menu_component => 'MenuComponent',
111
+ :menu_item => 'MenuItem',
112
+ :menu_shortcut => 'MenuShortcut',
113
+ :mouse_info => 'MouseInfo',
114
+ :multiple_gradient_paint => 'MultipleGradientPaint',
115
+ :page_attributes => 'PageAttributes',
116
+ :panel => 'Panel',
117
+ :point => 'Point',
118
+ :pointer_info => 'PointerInfo',
119
+ :polygon => 'Polygon',
120
+ :popup_menu => 'PopupMenu',
121
+ :print_job => 'PrintJob',
122
+ :radial_gradient_paint => 'RadialGradientPaint',
123
+ :rectangle => 'Rectangle',
124
+ :rendering_hints => 'RenderingHints',
125
+ :rendering_hints_key => 'RenderingHints::Key',
126
+ :robot => 'Robot',
127
+ :scrollbar => 'Scrollbar',
128
+ :scroll_pane => 'ScrollPane',
129
+ :scroll_pane_adjustable => 'ScrollPaneAdjustable',
130
+ :splash_screen => 'SplashScreen',
131
+ :system_color => 'SystemColor',
132
+ :system_tray => 'SystemTray',
133
+ :text_area => 'TextArea',
134
+ :text_component => 'TextComponent',
135
+ :text_field => 'TextField',
136
+ :texture_paint => 'TexturePaint',
137
+ :toolkit => 'Toolkit',
138
+ :tray_icon => 'TrayIcon',
139
+ :window => 'Window',
140
+ :clipboard => 'datatransfer.Clipboard',
141
+ :data_flavor => 'datatransfer.DataFlavor',
142
+ :flavor_event => 'datatransfer.FlavorEvent',
143
+ :string_selection => 'datatransfer.StringSelection',
144
+ :affine_transform => 'geom.AffineTransform',
145
+ :arc_2d_double => 'geom.Arc2D::Double',
146
+ :arc_2d_float => 'geom.Arc2D::Float',
147
+ :area => 'geom.Area ',
148
+ :cubic_curve_2d_double => 'geom.CubicCurve2D::Double',
149
+ :cubic_curve_2d_float => 'geom.CubicCurve2D::Float',
150
+ :ellipse_2d_double => 'geom.Ellipse2D::Double',
151
+ :ellipse_2d_float => 'geom.Ellipse2D::Float',
152
+ :flattening_path_iterator => 'geom.FlatteningPathIterator',
153
+ :general_path => 'geom.GeneralPath',
154
+ :line_2d_double => 'geom.Line2D::Double',
155
+ :line_2d_float => 'geom.Line2D::Float',
156
+ :path_2d_double => 'geom.Path2D::Double',
157
+ :path_2d_float => 'geom.Path2D::Float',
158
+ :point_2d_double => 'geom.Point2D::Double',
159
+ :point_2d_float => 'geom.Point2D::Float',
160
+ :quad_curve_2d_double => 'geom.QuadCurve2D::Double',
161
+ :quad_curve_2d_float => 'geom.QuadCurve2D::Float',
162
+ :rectangle_2d_double => 'geom.Rectangle2D::Double',
163
+ :rectangle_2d_float => 'geom.Rectangle2D::Float',
164
+ :round_rectangle_2d_double => 'geom.RoundRectangle2D::Double',
165
+ :round_rectangle_2d_float => 'geom.RoundRectangle2D::Float',
166
+ :affine_transform_op => 'image.AffineTransformOp',
167
+ :area_averaging_scale_filter => 'image.AreaAveragingScaleFilter',
168
+ :band_combine_op => 'image.BandCombineOp',
169
+ :banded_sample_model => 'image.BandedSampleModel',
170
+ :buffered_image => 'image.BufferedImage',
171
+ :buffered_image_filter => 'image.BufferedImageFilter',
172
+ :buffer_strategy => 'image.BufferStrategy',
173
+ :byte_lookup_table => 'image.ByteLookupTable',
174
+ :color_convert_op => 'image.ColorConvertOp',
175
+ :color_model => 'image.ColorModel',
176
+ :component_color_model => 'image.ComponentColorModel',
177
+ :component_sample_model => 'image.ComponentSampleModel',
178
+ :convolve_op => 'image.ConvolveOp',
179
+ :crop_image_filter => 'image.CropImageFilter',
180
+ :data_buffer => 'image.DataBuffer',
181
+ :data_buffer_byte => 'image.DataBufferByte',
182
+ :data_buffer_double => 'image.DataBufferDouble',
183
+ :data_buffer_float => 'image.DataBufferFloat',
184
+ :data_buffer_int => 'image.DataBufferInt',
185
+ :data_buffer_short => 'image.DataBufferShort',
186
+ :data_buffer_ushort => 'image.DataBufferUShort',
187
+ :direct_color_model => 'image.DirectColorModel',
188
+ :filtered_image_source => 'image.FilteredImageSource',
189
+ :image_filter => 'image.ImageFilter',
190
+ :index_color_model => 'image.IndexColorModel',
191
+ :kernel => 'image.Kernel',
192
+ :lookup_op => 'image.LookupOp',
193
+ :lookup_table => 'image.LookupTable',
194
+ :memory_image_source => 'image.MemoryImageSource',
195
+ :multi_pixel_packed_sample_model => 'image.MultiPixelPackedSampleModel',
196
+ :packed_color_model => 'image.PackedColorModel',
197
+ :pixel_grabber => 'image.PixelGrabber',
198
+ :pixel_interleaved_sample_model => 'image.PixelInterleavedSampleModel',
199
+ :raster => 'image.Raster',
200
+ :replicate_scale_filter => 'image.ReplicateScaleFilter',
201
+ :rescale_op => 'image.RescaleOp',
202
+ :rgb_image_filter => 'image.RGBImageFilter',
203
+ :rgb_image_filter => 'image.RGBImageFilter',
204
+ :sample_model => 'image.SampleModel',
205
+ :short_lookup_table => 'image.ShortLookupTable',
206
+ :single_pixel_packed_sample_model => 'image.SinglePixelPackedSampleModel',
207
+ :volatile_image => 'image.VolatileImage ',
208
+ :writable_raster => 'image.WritableRaster',
209
+ :parameter_block => 'image.renderable.ParameterBlock',
210
+ :renderable_image_op => 'image.renderable.RenderableImageOp',
211
+ :renderable_image_producer => 'image.renderable.RenderableImageProducer',
212
+ :render_context => 'image.renderable.RenderContext',
213
+ }
214
+
215
+ end #Types
216
+ end #AWT
217
+ end #Cheri
218
+
219
+ #cls = Cheri::AWT::Types.get_class(:frame)
220
+ #puts cls.java_class.name
@@ -0,0 +1,533 @@
1
+ #--
2
+ # Copyright (C) 2007 William N Dortch <bill.dortch@gmail.com>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+ #
24
+
25
+ module Cheri
26
+ module Builder
27
+
28
+ # Frame contains default implementations of the methods required by objects that
29
+ # will be pushed onto the Cheri::Builder::Context stack. Note that concrete
30
+ # builders will need to override some of these methods, such as #mod, #parent?
31
+ # and #child?.
32
+ #
33
+ # Frame is provided as a convenience; its use is not required.
34
+ #
35
+ # If used, Frame should normally be included before other Cheri::Builder convenience
36
+ # modules (such as Content or Attributes). Classes/modules that include it should
37
+ # be sure to call super from their initialize methods, if any.
38
+ module Frame
39
+ # Stores the context and block (if any) in @ctx and @blk.
40
+ def initialize(ctx,*args,&blk) #:doc:
41
+ @ctx = ctx
42
+ @blk = blk if blk
43
+ super(*args)
44
+ end
45
+
46
+ # Returns @ctx, the Context instance to which this frame belongs.
47
+ def ctx
48
+ @ctx
49
+ end
50
+ alias_method :context, :ctx
51
+
52
+ # Returns @blk, the block passed to this frame, if any.
53
+ def block
54
+ @blk
55
+ end
56
+
57
+ # Perform whatever actions are required to build +object+. Normally overridden to
58
+ # create +object+ and call its block, if any. Should return the built object.
59
+ #
60
+ # The default implementation simply calls +block+, if present. (Note that the block
61
+ # is actually called indirectly, via Cheri::Builder::Context#call, which manages
62
+ # the stack and connections. You normally do _not_ want to call the block directly.)
63
+ def run
64
+ @ctx.call(self,&@blk) if @blk
65
+ end
66
+
67
+ # The object for this frame (builder). Normally the object being built, once it has
68
+ # been created. May be the same as the builder object (see Cheri::Html::Elem, for example).
69
+ def object
70
+ @obj
71
+ end
72
+
73
+ # The builder module (such as Cheri::Swing) associated with this frame (builder object).
74
+ # Normally must be overridden. Default: Cheri::Builder::CheriModule
75
+ def mod
76
+ CheriModule
77
+ end
78
+
79
+ # Override to return +true+ if +object+ can be a parent of other objects. Default: +false+
80
+ def parent?
81
+ false
82
+ end
83
+
84
+ # Override to return +true+ if +object+ can be a child of another object. Default: +false+
85
+ def child?
86
+ false
87
+ end
88
+
89
+ # Override to return +true+ if +object+ wants the opportunity to connect to any object
90
+ # created in the hierarchy below it. Normally used by non-structural components (Swing's
91
+ # ButtonGroup, for example). Adds build overhead, so use sparingly.
92
+ def any?
93
+ false
94
+ end
95
+
96
+ # Overrides the default Object#inspect to prevent mind-boggling circular displays in IRB.
97
+ def inspect
98
+ "#<#{self.class}:instance>"
99
+ end
100
+
101
+ end #Frame
102
+
103
+ module Parent
104
+ def parent?
105
+ true
106
+ end
107
+ end
108
+
109
+ module Child
110
+ def child?
111
+ true
112
+ end
113
+ end
114
+
115
+ # Builder extends the functionality of Frame, extracting the symbol (+sym+) and arguments
116
+ # (+args+) from the arguments passed by a factory. Like Frame, it is a convenience that
117
+ # may be included in (or otherwise used to extend) builder classes/objects.
118
+ module Builder
119
+ include Frame
120
+ # Calls super to store context and block, then stores sym and args in @sym and @args.
121
+ def initialize(ctx,sym,*args,&blk) #:doc:
122
+ super(ctx,&blk)
123
+ @sym = sym
124
+ @args = args
125
+ end
126
+
127
+ # Returns the symbol passed by the factory that created this builder. The symbol
128
+ # normally originates in the method_missing method of the client object.
129
+ def sym
130
+ @sym
131
+ end
132
+
133
+ # Returns the arguments (excluding ctx and sym) passed by the factory that created
134
+ # this builder.
135
+ def args
136
+ @args
137
+ end
138
+
139
+ def run
140
+ @ctx.call(self,&@blk) if @blk
141
+ @obj
142
+ end
143
+
144
+ # Overrides Frame#parent? to return +true+.
145
+ def parent?
146
+ true
147
+ end
148
+
149
+ # Overrides Frame#child? to return +true+.
150
+ def child?
151
+ true
152
+ end
153
+ end
154
+
155
+ module DynamicModule
156
+ def initialize(mod,*r,&k)
157
+ @mod = mod
158
+ super(*r,&k)
159
+ end
160
+
161
+ def mod
162
+ @mod
163
+ end
164
+ end
165
+ # An 'abstract' builder class. Includes the methods defined in Frame and Builder.
166
+ # Provided as a convenience.
167
+ class AbstractBuilder
168
+ include Builder
169
+ end # AbstractBuilder
170
+
171
+
172
+ # A convenience 'base' builder class. Breaks the #run method into several steps.
173
+ class BaseBuilder < AbstractBuilder
174
+
175
+ def run
176
+ pre
177
+ create unless @no_create
178
+ post
179
+ call unless @no_call
180
+ @obj
181
+ end
182
+
183
+ # Returns ! @not_parent
184
+ def parent?
185
+ ! @not_parent
186
+ end
187
+
188
+ # Returns ! @not_child
189
+ def child?
190
+ ! @not_child
191
+ end
192
+
193
+ private
194
+ # called before object created
195
+ def pre #:doc:
196
+ end
197
+
198
+ # override to create object
199
+ def create #:doc:
200
+ end
201
+
202
+ # called after object is created
203
+ def post #:doc:
204
+ end
205
+
206
+ # called to call block unless there is no block or @no_call is set
207
+ def call #:doc:
208
+ @ctx.call(self,&@blk) if @blk
209
+ end
210
+ end #BaseBuilder
211
+
212
+ # Appendable types define to_s, to_str and to_io methods that take an optional
213
+ # parameter, to which output is appended. This is essentially a marker interface;
214
+ # the supplied implementations do nothing useful.
215
+ module Appendable
216
+ # Append value (whatever that might be) to the supplied String, or create and
217
+ # return a new String if none is supplied. If #esc is overridden, value will
218
+ # be escaped first. Delegates to #to_io unless String === str. Note that this
219
+ # implementation appends an empty string; override to do something useful.
220
+ def to_s(str='')
221
+ return to_io(str) unless String === str
222
+ esc('',str)
223
+ end
224
+
225
+ # Calls #to_s(str). Provided so that Appendable objects may be coerced to
226
+ # Strings automatically, as in <tt>str << my_appendable_thingy</tt>. Implemented
227
+ # this way rather than through alias_method to counter the possibility that
228
+ # overriders of #to_s will forget to re-alias to_str.
229
+ def to_str(str='')
230
+ to_s(str)
231
+ end
232
+
233
+ # Append value (whatever that might be) to the supplied output stream. If
234
+ # #esc is overridden, value will be escaped first. Note that this
235
+ # implementation appends an empty string; override to do something useful.
236
+ def to_io(ios)
237
+ ios << esc('')
238
+ end
239
+
240
+ # Override to escape values (default implementation appends or returns
241
+ # the input value unaltered).
242
+ def esc(inp,out=nil)
243
+ out ? out << inp : inp
244
+ end
245
+
246
+ end
247
+
248
+ # Methods to support content (primarily intended for use with XML/HTML markup).
249
+ # See also EmptyContent, ContentArgs.
250
+ module Content
251
+ include Appendable
252
+
253
+ # Adds +value+ to the content array (@cont) for this object if #content?(+value+)
254
+ # returns +true+.
255
+ def add(value)
256
+ (@cont ||= []) << value if content?(value)
257
+ self
258
+ end
259
+ alias_method :<<, :add
260
+
261
+ # Returns the content array (@cont) if present, otherwise +nil+.
262
+ def content
263
+ @cont
264
+ end
265
+
266
+ # Iterates over the content array (@cont) for this object. Equivalent to
267
+ # calling #content#each.
268
+ def each #:yields: content_value
269
+ @cont.each do |v|
270
+ yield v
271
+ end if @cont && block_given?
272
+ end
273
+
274
+ # Returns truth value if +value+ is valid content for this builder/object,
275
+ # +false+/+nil+ otherwise. Called by #add before adding content; +value+ will
276
+ # not be added unless content? is true.
277
+ #
278
+ # This implementation always returns +true+. Override to validate each content
279
+ # element before it is added. You may wish to raise an exception or issue a
280
+ # warning in the case of invalid content.
281
+ def content?(value)
282
+ true
283
+ end
284
+
285
+ # Appends concatenated and escaped content (@cont) to +str+, if supplied, using
286
+ # the +<<+ operator. Assumes String === +str+. Use #cont_io to append to IO or Array.
287
+ def cont_s(str='')
288
+ @cont.each do |v|
289
+ case v
290
+ when String : esc(v,str)
291
+ when Appendable : v.to_s(str)
292
+ else esc(v.to_s,str)
293
+ end
294
+ end if @cont
295
+ str
296
+ end
297
+
298
+ # Appends concatenated and escaped content (@cont) to +ios+, if supplied, using
299
+ # the +<<+ operator. Use for appending to IO or Array. Use #cont_s to append more
300
+ # efficiently to strings.
301
+ def cont_io(ios)
302
+ @cont.each do |v|
303
+ case v
304
+ when String : ios << esc(v)
305
+ when Appendable : v.to_io(ios)
306
+ else ios << esc(v.to_s)
307
+ end
308
+ end if @cont
309
+ ios
310
+ end
311
+
312
+ # Override to escape values by appending the escaped +inp+ value to output
313
+ # string +out+ (using << or concat). If +out+ is nil, just return the escaped
314
+ # string. The default implementation appends or returns the input value unaltered.
315
+ def esc(inp,out=nil)
316
+ out ? out << inp : inp
317
+ end
318
+
319
+ end
320
+
321
+ # Methods to support attributes (primarily intended for use with XML/HTML markup).
322
+ # Note: include before ContentArgs if both are being included.
323
+ module Attributes
324
+ include Appendable
325
+ #:stopdoc:
326
+ S = ' '.freeze
327
+ Q = '"'.freeze
328
+ E = '='.freeze
329
+ #:startdoc:
330
+ def initialize(*r,&k)
331
+ super
332
+ if @args && Hash === @args.last
333
+ @args.pop.each_pair do |n,v| add_attr(n,v); end
334
+ end
335
+ end
336
+
337
+ # Returns the attibutes hash (@attrs), if any.
338
+ def attrs
339
+ @attrs
340
+ end
341
+
342
+ # Add an attribute. Called by #initialize to add/validate attributes passed as
343
+ # arguments.
344
+ def add_attr(name,value)
345
+ (@attrs ||= {})[name] = value if attr?(name,value)
346
+ end
347
+
348
+ # Override to validate each attribute before it is added. The default
349
+ # implementation accepts any name/value.
350
+ def attr?(name,value)
351
+ true
352
+ end
353
+
354
+ # Writes attributes to a new string, or appends to an existing string
355
+ # (using <<) if supplied.
356
+ def attr_s(str='')
357
+ @attrs.each_pair do |k,v|
358
+ str << 32 << k.to_s << ?= << 34 << v.to_s << 34
359
+ end if @attrs
360
+ str
361
+ end
362
+
363
+ # Writes attributes to the supplied IO stream (or Array, etc.) using <<.
364
+ def attr_io(ios)
365
+ @attrs.each_pair do |k,v|
366
+ ios << S << k << E << Q << v << Q
367
+ end if @attrs
368
+ ios
369
+ end
370
+ end
371
+
372
+ # Calls +add+ to add each argument passed to new/initialize. Use with Content
373
+ # module if content values will be passed as arguments. Note: include after
374
+ # Attributes if both are being used.
375
+ module ContentArgs
376
+ def initialize(*r,&k)
377
+ super
378
+ @args.each do |a| add a; end
379
+ end
380
+ end #ContentArgs
381
+
382
+
383
+ # Methods to support empty content models (primarily intended for use with XML/HTML markup).
384
+ # See also Content, ContentArgs.
385
+ module EmptyContent
386
+ include Appendable
387
+ CE = ' />'.freeze #:nodoc:
388
+
389
+ # Returns +false+
390
+ def content?(value)
391
+ false
392
+ end
393
+
394
+ def empty_s(str='')
395
+ str << CE
396
+ end
397
+
398
+ def empty_io(ios)
399
+ ios << CE
400
+ end
401
+
402
+ end #EmptyContent
403
+
404
+ module MarkupWriter
405
+ #:stopdoc:
406
+ C = '</'.freeze
407
+ E = '>'.freeze
408
+ EC = '></'.freeze
409
+ O = '<'.freeze
410
+ #:startdoc:
411
+
412
+ # Append this markup to +str+ (or an empty string if +str+ is not supplied),
413
+ # and return the result. Redirects to #to_io if +str+ is not a String. Both
414
+ # methods use the +<<+ operator to append their output; this method (like the other
415
+ # ..._s methods) is faster because Fixnum values can be appended directly, without
416
+ # being converted to (or passed as) strings. This takes on particular significance
417
+ # when output is being escaped, and values passed one character at a time.
418
+ def to_s(str='')
419
+ return to_io(str) unless String === str
420
+ open_s(str)
421
+ attr_s(str) if @attrs
422
+ if @cont
423
+ str << ?>
424
+ cont_s(str)
425
+ close_s(str)
426
+ else
427
+ empty_s(str)
428
+ end
429
+ str
430
+ end
431
+
432
+ # Append this markup to +ios+
433
+ def to_io(ios)
434
+ open_io(ios)
435
+ attr_io(ios) if @attrs
436
+ if @cont
437
+ ios << E
438
+ cont_io(ios)
439
+ close_io(ios)
440
+ else
441
+ empty_io(ios)
442
+ end
443
+ ios
444
+ end
445
+
446
+ # Append open tag (<tagname) to +str+ using +<<+.
447
+ def open_s(str)
448
+ str << ?< << (@tag ||= @sym.to_s)
449
+ end
450
+
451
+ # Append open tag (<tagname) to +ios+ using +<<+.
452
+ def open_io(ios)
453
+ ios << O << (@tag ||= @sym.to_s)
454
+ end
455
+
456
+ # Append close tag (</tagname>) to +str+ using +<<+.
457
+ def close_s(str)
458
+ str << C << @tag << ?>
459
+ end
460
+
461
+ # Append close tag (</tagname>) to +ios+ using +<<+. (Use slightly faster
462
+ # #close_s for strings.)
463
+ def close_io(ios)
464
+ ios << C << @tag << E
465
+ end
466
+
467
+ # Append empty close tag (...></tagname>) to +str+. Note that HTML/XML elements
468
+ # with empty content models should close with <tt>' />'</tt> instead (see EmptyContent).
469
+ def empty_s(str)
470
+ str << EC << @tag << ?>
471
+ end
472
+
473
+ # Append empty close tag (...></tagname>) to +ios+. Note that HTML/XML elements
474
+ # with empty content models should close with <tt>' />'</tt> instead (see EmptyContent).
475
+ def empty_io(ios)
476
+ ios << EC << @tag << E
477
+ end
478
+
479
+ end #MarkupWriter
480
+
481
+ module Markup
482
+ include Content
483
+ include Attributes
484
+ include ContentArgs
485
+ include MarkupWriter
486
+ end #Markup
487
+
488
+ module EmptyMarkup
489
+ # We include Content and ContentArgs so that warnings/exceptions may be
490
+ # issued (by overriding #add or #content?) if the user attempts to add to this element.
491
+ # Otherwise, unconnectable elements would simply be ignored.
492
+ include Markup
493
+ # include Content
494
+ # include Attributes
495
+ # include ContentArgs
496
+ # include MarkupWriter
497
+ include EmptyContent
498
+ end #EmptyMarkup
499
+
500
+ module MarkupBuilder
501
+ include Builder
502
+ include Markup
503
+
504
+ def object
505
+ self
506
+ end
507
+
508
+ def run
509
+ value = @ctx.call(self,&@blk) if @blk
510
+ add(value) if String === value
511
+ self
512
+ end
513
+ end #MarkupBuilder
514
+
515
+ module EmptyMarkupBuilder
516
+ include Builder
517
+ include EmptyMarkup
518
+
519
+ def object
520
+ self
521
+ end
522
+
523
+ def run
524
+ value = @ctx.call(self,&@blk) if @blk
525
+ # of course we want this to then fail in #add / #content? e.g., see Cheri::Html::EmptyElem
526
+ add(value) if String === value
527
+ self
528
+ end
529
+
530
+ end #EmptyMarkupBuilder
531
+
532
+ end #Builder
533
+ end #Cheri