cheri 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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