glimmer-dsl-opal 0.27.0 → 0.28.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/README.md +71 -3
- data/VERSION +1 -1
- data/lib/glimmer/dsl/opal/dsl.rb +3 -0
- data/lib/glimmer/dsl/opal/image_expression.rb +64 -0
- data/lib/glimmer/dsl/opal/property_expression.rb +1 -2
- data/lib/glimmer/dsl/opal/shape_expression.rb +35 -6
- data/lib/glimmer/swt/canvas_proxy.rb +27 -0
- data/lib/glimmer/swt/composite_proxy.rb +0 -2
- data/lib/glimmer/swt/custom/shape/arc.rb +75 -0
- data/lib/glimmer/swt/custom/shape/image.rb +98 -0
- data/lib/glimmer/swt/custom/shape/line.rb +53 -0
- data/lib/glimmer/swt/custom/shape/oval.rb +58 -0
- data/lib/glimmer/swt/custom/shape/point.rb +53 -0
- data/lib/glimmer/swt/custom/shape/polygon.rb +53 -0
- data/lib/glimmer/swt/custom/shape/polyline.rb +53 -0
- data/lib/glimmer/swt/custom/shape/rectangle.rb +101 -0
- data/lib/glimmer/swt/custom/shape/text.rb +114 -0
- data/lib/glimmer/swt/custom/shape.rb +205 -0
- data/lib/glimmer/swt/image_proxy.rb +29 -0
- data/lib/glimmer/swt/menu_proxy.rb +1 -1
- data/lib/glimmer/swt/point.rb +2 -0
- data/lib/glimmer/swt/rectangle.rb +7 -0
- data/lib/glimmer/swt/widget_proxy.rb +15 -4
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris/view/block.rb +44 -0
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris.rb +4 -8
- data/lib/glimmer-dsl-opal/samples/elaborate/weather.rb +4 -3
- data/lib/glimmer-dsl-opal/samples/hello/hello_canvas.rb +106 -0
- data/lib/glimmer-dsl-opal/samples/hello/hello_text.rb +1 -1
- data/lib/glimmer-dsl-opal/samples/hello/images/scaffold_app.png +0 -0
- data/lib/glimmer-dsl-opal/vendor/two.min.js +24 -0
- data/lib/glimmer-dsl-opal.rb +1 -0
- metadata +19 -2
| @@ -0,0 +1,114 @@ | |
| 1 | 
            +
            # Copyright (c) 2020-2021 Andy Maleh
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # Permission is hereby granted, free of charge, to any person obtaining
         | 
| 4 | 
            +
            # a copy of this software and associated documentation files (the
         | 
| 5 | 
            +
            # "Software"), to deal in the Software without restriction, including
         | 
| 6 | 
            +
            # without limitation the rights to use, copy, modify, merge, publish,
         | 
| 7 | 
            +
            # distribute, sublicense, and/or sell copies of the Software, and to
         | 
| 8 | 
            +
            # permit persons to whom the Software is furnished to do so, subject to
         | 
| 9 | 
            +
            # the following conditions:
         | 
| 10 | 
            +
            #
         | 
| 11 | 
            +
            # The above copyright notice and this permission notice shall be
         | 
| 12 | 
            +
            # included in all copies or substantial portions of the Software.
         | 
| 13 | 
            +
            #
         | 
| 14 | 
            +
            # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 15 | 
            +
            # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         | 
| 16 | 
            +
            # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 17 | 
            +
            # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         | 
| 18 | 
            +
            # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         | 
| 19 | 
            +
            # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         | 
| 20 | 
            +
            # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            require 'glimmer/swt/custom/shape'
         | 
| 23 | 
            +
            require 'glimmer/swt/swt_proxy'
         | 
| 24 | 
            +
            require 'glimmer/swt/display_proxy'
         | 
| 25 | 
            +
            require 'glimmer/swt/color_proxy'
         | 
| 26 | 
            +
            # require 'glimmer/swt/transform_proxy'
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            module Glimmer
         | 
| 29 | 
            +
              module SWT
         | 
| 30 | 
            +
                module Custom
         | 
| 31 | 
            +
                  class Shape
         | 
| 32 | 
            +
                    class Text < Shape
         | 
| 33 | 
            +
                      def parameter_names
         | 
| 34 | 
            +
                        if text_parameter_names.size == @args.size
         | 
| 35 | 
            +
                          @parameter_names = text_parameter_names
         | 
| 36 | 
            +
                        elsif text_transparent_parameter_names.size == @args.size
         | 
| 37 | 
            +
                          @parameter_names = text_transparent_parameter_names
         | 
| 38 | 
            +
                        elsif text_flags_parameter_names.size == @args.size
         | 
| 39 | 
            +
                          @parameter_names = text_flags_parameter_names
         | 
| 40 | 
            +
                        end
         | 
| 41 | 
            +
                        @parameter_names || text_parameter_names
         | 
| 42 | 
            +
                      end
         | 
| 43 | 
            +
                      
         | 
| 44 | 
            +
                      def possible_parameter_names
         | 
| 45 | 
            +
                        # TODO refactor and improve this method through meta-programming (and share across other shapes)
         | 
| 46 | 
            +
                        (text_parameter_names + text_transparent_parameter_names + text_flags_parameter_names).uniq
         | 
| 47 | 
            +
                      end
         | 
| 48 | 
            +
                      
         | 
| 49 | 
            +
                      def text_parameter_names
         | 
| 50 | 
            +
                        [:string, :x, :y]
         | 
| 51 | 
            +
                      end
         | 
| 52 | 
            +
                      
         | 
| 53 | 
            +
                      def text_transparent_parameter_names
         | 
| 54 | 
            +
                        [:string, :x, :y, :is_transparent]
         | 
| 55 | 
            +
                      end
         | 
| 56 | 
            +
                      
         | 
| 57 | 
            +
                      def text_flags_parameter_names
         | 
| 58 | 
            +
                        [:string, :x, :y, :flags]
         | 
| 59 | 
            +
                      end
         | 
| 60 | 
            +
                      
         | 
| 61 | 
            +
                      def set_parameter_attribute(attribute_name, *args)
         | 
| 62 | 
            +
                        if @parameter_names.to_a.map(&:to_s).include?(attribute_name.to_s)
         | 
| 63 | 
            +
                          super(attribute_name, *args)
         | 
| 64 | 
            +
                          build_dom
         | 
| 65 | 
            +
                          reattach(dom_element)
         | 
| 66 | 
            +
                          return
         | 
| 67 | 
            +
                        end
         | 
| 68 | 
            +
                        if text_parameter_names.map(&:to_s).include?(attribute_name.to_s)
         | 
| 69 | 
            +
                          @parameter_names = text_parameter_names
         | 
| 70 | 
            +
                        elsif text_transparent_parameter_names.map(&:to_s).include?(attribute_name.to_s)
         | 
| 71 | 
            +
                          @parameter_names = text_transparent_parameter_names
         | 
| 72 | 
            +
                        elsif text_flags_parameter_names.map(&:to_s).include?(attribute_name.to_s)
         | 
| 73 | 
            +
                          @parameter_names = text_flags_parameter_names
         | 
| 74 | 
            +
                        end
         | 
| 75 | 
            +
                        super(attribute_name, *args)
         | 
| 76 | 
            +
                      end
         | 
| 77 | 
            +
                      
         | 
| 78 | 
            +
                      def reattach(old_element)
         | 
| 79 | 
            +
                        old_element.attr('x', Element[@dom].attr('x'))
         | 
| 80 | 
            +
                        old_element.attr('y', Element[@dom].attr('y'))
         | 
| 81 | 
            +
                        old_element.text(Element[@dom].html)
         | 
| 82 | 
            +
                      end
         | 
| 83 | 
            +
                      
         | 
| 84 | 
            +
                      def background=(value)
         | 
| 85 | 
            +
                        # TODO override background= to fill a rectangle containing text, matching its size
         | 
| 86 | 
            +
                        # For now, disable background when foreground is not set
         | 
| 87 | 
            +
                        super(value) unless foreground.nil?
         | 
| 88 | 
            +
                      end
         | 
| 89 | 
            +
                    
         | 
| 90 | 
            +
                      def foreground=(value)
         | 
| 91 | 
            +
                        super(value)
         | 
| 92 | 
            +
                        self.background = value
         | 
| 93 | 
            +
                      end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                      def element
         | 
| 96 | 
            +
                        'text'
         | 
| 97 | 
            +
                      end
         | 
| 98 | 
            +
                      
         | 
| 99 | 
            +
                      def dom
         | 
| 100 | 
            +
                        shape_id = id
         | 
| 101 | 
            +
                        shape_class = name
         | 
| 102 | 
            +
                        @dom ||= xml {
         | 
| 103 | 
            +
                          tag(:_name => 'text', id: shape_id, class: shape_class, x: @args[1], y: @args[2]) {
         | 
| 104 | 
            +
                            @args[0]
         | 
| 105 | 
            +
                          }
         | 
| 106 | 
            +
                        }.to_s
         | 
| 107 | 
            +
                      end
         | 
| 108 | 
            +
                      
         | 
| 109 | 
            +
                    end
         | 
| 110 | 
            +
                    String = Text
         | 
| 111 | 
            +
                  end
         | 
| 112 | 
            +
                end
         | 
| 113 | 
            +
              end
         | 
| 114 | 
            +
            end
         | 
| @@ -0,0 +1,205 @@ | |
| 1 | 
            +
            # Copyright (c) 2007-2021 Andy Maleh
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # Permission is hereby granted, free of charge, to any person obtaining
         | 
| 4 | 
            +
            # a copy of this software and associated documentation files (the
         | 
| 5 | 
            +
            # "Software"), to deal in the Software without restriction, including
         | 
| 6 | 
            +
            # without limitation the rights to use, copy, modify, merge, publish,
         | 
| 7 | 
            +
            # distribute, sublicense, and/or sell copies of the Software, and to
         | 
| 8 | 
            +
            # permit persons to whom the Software is furnished to do so, subject to
         | 
| 9 | 
            +
            # the following conditions:
         | 
| 10 | 
            +
            #
         | 
| 11 | 
            +
            # The above copyright notice and this permission notice shall be
         | 
| 12 | 
            +
            # included in all copies or substantial portions of the Software.
         | 
| 13 | 
            +
            #
         | 
| 14 | 
            +
            # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 15 | 
            +
            # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         | 
| 16 | 
            +
            # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 17 | 
            +
            # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         | 
| 18 | 
            +
            # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         | 
| 19 | 
            +
            # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         | 
| 20 | 
            +
            # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            require 'glimmer/swt/property_owner'
         | 
| 23 | 
            +
            require 'glimmer/swt/swt_proxy'
         | 
| 24 | 
            +
            require 'glimmer/swt/display_proxy'
         | 
| 25 | 
            +
            require 'glimmer/swt/color_proxy'
         | 
| 26 | 
            +
            require 'glimmer/swt/font_proxy'
         | 
| 27 | 
            +
            # require 'glimmer/swt/transform_proxy'
         | 
| 28 | 
            +
            require 'glimmer/swt/point'
         | 
| 29 | 
            +
            require 'glimmer/swt/rectangle'
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            module Glimmer
         | 
| 32 | 
            +
              module SWT
         | 
| 33 | 
            +
                module Custom
         | 
| 34 | 
            +
                  # Represents a shape (graphics) to be drawn on a control/widget/canvas/display
         | 
| 35 | 
            +
                  # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
         | 
| 36 | 
            +
                  class Shape < WidgetProxy
         | 
| 37 | 
            +
                    include PropertyOwner
         | 
| 38 | 
            +
                    
         | 
| 39 | 
            +
                    class << self
         | 
| 40 | 
            +
                      def create(parent, keyword, args, &property_block)
         | 
| 41 | 
            +
                        potential_shape_class_name = keyword.to_s.camelcase(:upper).to_sym
         | 
| 42 | 
            +
                        if constants.include?(potential_shape_class_name)
         | 
| 43 | 
            +
                          const_get(potential_shape_class_name).new(parent, args, &property_block)
         | 
| 44 | 
            +
                        else
         | 
| 45 | 
            +
                          new(parent, args, &property_block)
         | 
| 46 | 
            +
                        end
         | 
| 47 | 
            +
                      end
         | 
| 48 | 
            +
                    
         | 
| 49 | 
            +
                      def valid?(parent, keyword, args, &block)
         | 
| 50 | 
            +
                        return true if keyword.to_s == 'shape'
         | 
| 51 | 
            +
                        keywords.include?(keyword.to_s)
         | 
| 52 | 
            +
                      end
         | 
| 53 | 
            +
                      
         | 
| 54 | 
            +
                      def keywords
         | 
| 55 | 
            +
                        constants.select do |constant|
         | 
| 56 | 
            +
                          constant_value = const_get(constant)
         | 
| 57 | 
            +
                          constant_value.respond_to?(:ancestors) && constant_value.ancestors.include?(Glimmer::SWT::Custom::Shape)
         | 
| 58 | 
            +
                        end.map {|constant| constant.to_s.underscore}
         | 
| 59 | 
            +
                      end
         | 
| 60 | 
            +
                      
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
                    
         | 
| 63 | 
            +
                    def background=(value)
         | 
| 64 | 
            +
                      value = ColorProxy.new(value) if value.is_a?(String) || value.is_a?(Symbol)
         | 
| 65 | 
            +
                      @background = value
         | 
| 66 | 
            +
                      dom_element.css('fill', background.to_css) unless background.nil?
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
                    
         | 
| 69 | 
            +
                    def foreground=(value)
         | 
| 70 | 
            +
                      value = ColorProxy.new(value) if value.is_a?(String) || value.is_a?(Symbol)
         | 
| 71 | 
            +
                      @foreground = value
         | 
| 72 | 
            +
                      dom_element.css('stroke', foreground.to_css) unless foreground.nil?
         | 
| 73 | 
            +
                      dom_element.css('fill', 'transparent') if background.nil?
         | 
| 74 | 
            +
                    end
         | 
| 75 | 
            +
                    
         | 
| 76 | 
            +
                    def post_add_content
         | 
| 77 | 
            +
                      # TODO avoid rendering unless args changed from initialize args (due to setting of piecemeal attributes)
         | 
| 78 | 
            +
                      render
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
                    
         | 
| 81 | 
            +
                    def render(custom_parent_dom_element: nil, brand_new: false)
         | 
| 82 | 
            +
                      super(custom_parent_dom_element: nil, brand_new: false)
         | 
| 83 | 
            +
                      self.background = background
         | 
| 84 | 
            +
                      self.foreground = foreground
         | 
| 85 | 
            +
                      self.font = font
         | 
| 86 | 
            +
                    end
         | 
| 87 | 
            +
                    
         | 
| 88 | 
            +
                    # parameter names for arguments to pass to SWT GC.xyz method for rendering shape (e.g. draw_image(image, x, y) yields :image, :x, :y parameter names)
         | 
| 89 | 
            +
                    def parameter_names
         | 
| 90 | 
            +
                      [:x, :y, :width, :height]
         | 
| 91 | 
            +
                    end
         | 
| 92 | 
            +
                    
         | 
| 93 | 
            +
                    # subclasses may override to specify location parameter names if different from x and y (e.g. all polygon points are location parameters)
         | 
| 94 | 
            +
                    # used in calculating movement changes
         | 
| 95 | 
            +
                    def location_parameter_names
         | 
| 96 | 
            +
                      [:x, :y]
         | 
| 97 | 
            +
                    end
         | 
| 98 | 
            +
                    
         | 
| 99 | 
            +
                    def possible_parameter_names
         | 
| 100 | 
            +
                      parameter_names
         | 
| 101 | 
            +
                    end
         | 
| 102 | 
            +
                    
         | 
| 103 | 
            +
                    def parameter_name?(attribute_name)
         | 
| 104 | 
            +
                      possible_parameter_names.map(&:to_s).include?(attribute_getter(attribute_name))
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                    
         | 
| 107 | 
            +
                    def current_parameter_name?(attribute_name)
         | 
| 108 | 
            +
                      parameter_names.include?(attribute_name.to_s.to_sym)
         | 
| 109 | 
            +
                    end
         | 
| 110 | 
            +
                    
         | 
| 111 | 
            +
                    def parameter_index(attribute_name)
         | 
| 112 | 
            +
                      parameter_names.index(attribute_name.to_s.to_sym)
         | 
| 113 | 
            +
                    end
         | 
| 114 | 
            +
                    
         | 
| 115 | 
            +
                    def get_parameter_attribute(attribute_name)
         | 
| 116 | 
            +
                      @args[parameter_index(attribute_getter(attribute_name))]
         | 
| 117 | 
            +
                    end
         | 
| 118 | 
            +
                    
         | 
| 119 | 
            +
                    def set_parameter_attribute(attribute_name, *args)
         | 
| 120 | 
            +
                      @args[parameter_index(attribute_getter(attribute_name))] = args.size == 1 ? args.first : args
         | 
| 121 | 
            +
                    end
         | 
| 122 | 
            +
                    
         | 
| 123 | 
            +
                    def has_attribute?(attribute_name, *args)
         | 
| 124 | 
            +
                      parameter_name?(attribute_name) or
         | 
| 125 | 
            +
                        (respond_to?(attribute_name, super: true) and respond_to?(attribute_setter(attribute_name), super: true))
         | 
| 126 | 
            +
                    end
         | 
| 127 | 
            +
                    
         | 
| 128 | 
            +
                    def set_attribute(attribute_name, *args)
         | 
| 129 | 
            +
                      attribute_getter_name = attribute_getter(attribute_name)
         | 
| 130 | 
            +
                      attribute_setter_name = attribute_setter(attribute_name)
         | 
| 131 | 
            +
                      if parameter_name?(attribute_name)
         | 
| 132 | 
            +
                        return if attribute_getter_name == (args.size == 1 ? args.first : args)
         | 
| 133 | 
            +
                        set_parameter_attribute(attribute_getter_name, *args)
         | 
| 134 | 
            +
                      elsif (respond_to?(attribute_name, super: true) and respond_to?(attribute_setter_name, super: true))
         | 
| 135 | 
            +
                        return if self.send(attribute_getter_name) == (args.size == 1 ? args.first : args)
         | 
| 136 | 
            +
                        self.send(attribute_setter_name, *args)
         | 
| 137 | 
            +
                      end
         | 
| 138 | 
            +
                    end
         | 
| 139 | 
            +
                    
         | 
| 140 | 
            +
                    def get_attribute(attribute_name)
         | 
| 141 | 
            +
                      if parameter_name?(attribute_name)
         | 
| 142 | 
            +
                        arg_index = parameter_index(attribute_name)
         | 
| 143 | 
            +
                        @args[arg_index] if arg_index
         | 
| 144 | 
            +
                      elsif (respond_to?(attribute_name, super: true) and respond_to?(attribute_setter(attribute_name), super: true))
         | 
| 145 | 
            +
                        self.send(attribute_name)
         | 
| 146 | 
            +
                      end
         | 
| 147 | 
            +
                    end
         | 
| 148 | 
            +
                    
         | 
| 149 | 
            +
                    # TODO look why image is not working with the method_missing and respond_to? on shape
         | 
| 150 | 
            +
                    def method_missing(method_name, *args, &block)
         | 
| 151 | 
            +
                      if method_name.to_s.end_with?('=')
         | 
| 152 | 
            +
                        set_attribute(method_name, *args)
         | 
| 153 | 
            +
                      elsif has_attribute?(method_name) && args.empty?
         | 
| 154 | 
            +
                        get_attribute(method_name)
         | 
| 155 | 
            +
                      else # TODO support proxying calls to handle_observation_request for listeners just like WidgetProxy
         | 
| 156 | 
            +
                        super(method_name, *args, &block)
         | 
| 157 | 
            +
                      end
         | 
| 158 | 
            +
                    end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                    def respond_to?(method_name, *args, &block)
         | 
| 161 | 
            +
                      options = args.last if args.last.is_a?(Hash)
         | 
| 162 | 
            +
                      super_invocation = options && options[:super]
         | 
| 163 | 
            +
                      if !super_invocation && has_attribute?(method_name)
         | 
| 164 | 
            +
                        true
         | 
| 165 | 
            +
                      else
         | 
| 166 | 
            +
                        super(method_name, *args, &block)
         | 
| 167 | 
            +
                      end
         | 
| 168 | 
            +
                    end
         | 
| 169 | 
            +
                    
         | 
| 170 | 
            +
                    def attach(the_parent_dom_element)
         | 
| 171 | 
            +
                      the_parent_dom_element.html("#{the_parent_dom_element.html()}\n#{@dom}")
         | 
| 172 | 
            +
                    end
         | 
| 173 | 
            +
                    
         | 
| 174 | 
            +
                    def element
         | 
| 175 | 
            +
                      'g'
         | 
| 176 | 
            +
                    end
         | 
| 177 | 
            +
                    
         | 
| 178 | 
            +
                    def dom
         | 
| 179 | 
            +
                      shape_id = id
         | 
| 180 | 
            +
                      shape_class = name
         | 
| 181 | 
            +
                      @dom ||= xml {
         | 
| 182 | 
            +
                        g(id: shape_id, class: shape_class) {
         | 
| 183 | 
            +
                        }
         | 
| 184 | 
            +
                      }.to_s
         | 
| 185 | 
            +
                    end
         | 
| 186 | 
            +
                    
         | 
| 187 | 
            +
                    # TODO implement shape_at_location potentially with document.elementFromPoint(x, y);
         | 
| 188 | 
            +
                    
         | 
| 189 | 
            +
                  end
         | 
| 190 | 
            +
                  
         | 
| 191 | 
            +
                end
         | 
| 192 | 
            +
                
         | 
| 193 | 
            +
              end
         | 
| 194 | 
            +
              
         | 
| 195 | 
            +
            end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
            require 'glimmer/swt/custom/shape/arc'
         | 
| 198 | 
            +
            require 'glimmer/swt/custom/shape/image'
         | 
| 199 | 
            +
            require 'glimmer/swt/custom/shape/line'
         | 
| 200 | 
            +
            require 'glimmer/swt/custom/shape/oval'
         | 
| 201 | 
            +
            require 'glimmer/swt/custom/shape/point'
         | 
| 202 | 
            +
            require 'glimmer/swt/custom/shape/polygon'
         | 
| 203 | 
            +
            require 'glimmer/swt/custom/shape/polyline'
         | 
| 204 | 
            +
            require 'glimmer/swt/custom/shape/rectangle'
         | 
| 205 | 
            +
            require 'glimmer/swt/custom/shape/text'
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            module Glimmer
         | 
| 2 | 
            +
              module SWT
         | 
| 3 | 
            +
                # emulating org.eclipse.swt.graphics.Image
         | 
| 4 | 
            +
                class ImageProxy
         | 
| 5 | 
            +
                  class << self
         | 
| 6 | 
            +
                    def create(*args, &content)
         | 
| 7 | 
            +
                      if args.size == 1 && args.first.is_a?(ImageProxy)
         | 
| 8 | 
            +
                        args.first
         | 
| 9 | 
            +
                      else
         | 
| 10 | 
            +
                        new(*args, &content)
         | 
| 11 | 
            +
                      end
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                
         | 
| 15 | 
            +
                  attr_reader :file_path, :width, :height
         | 
| 16 | 
            +
                  
         | 
| 17 | 
            +
                  def initialize(*args)
         | 
| 18 | 
            +
                    options = args.last.is_a?(Hash) ? args.last : {}
         | 
| 19 | 
            +
                    # TODO support a parent as a first argument before the file path
         | 
| 20 | 
            +
                    @file_path = args.first
         | 
| 21 | 
            +
                    @width = options[:width]
         | 
| 22 | 
            +
                    @height = options[:height]
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
                  
         | 
| 25 | 
            +
                  # TODO implement scale_to
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
                # TODO alias as org.eclipse.swt.graphics.Image
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
| @@ -198,6 +198,7 @@ module Glimmer | |
| 198 198 | 
             
                      # delay this till all children rendered (perhaps post_add_content block)
         | 
| 199 199 | 
             
                      parent_dom_element.css('position', 'relative')
         | 
| 200 200 | 
             
                      parent_dom_element.css('margin-top', '30px')
         | 
| 201 | 
            +
                      parent_dom_element.css('height', '114%')
         | 
| 201 202 | 
             
                      redraw
         | 
| 202 203 | 
             
                      `$(#{path}).menu({
         | 
| 203 204 | 
             
                        position: { my: "top", at: "bottom" },
         | 
| @@ -222,7 +223,6 @@ module Glimmer | |
| 222 223 | 
             
                    @visible = value
         | 
| 223 224 | 
             
                    if @visible
         | 
| 224 225 | 
             
                      parent.menu_requested = true
         | 
| 225 | 
            -
                      parent.dom_element.css('position', 'relative')
         | 
| 226 226 | 
             
                      render
         | 
| 227 227 | 
             
                      dom_element.css('position', 'absolute')
         | 
| 228 228 | 
             
                      dom_element.css('left', parent.menu_x - parent.dom_element.offset.left)
         | 
    
        data/lib/glimmer/swt/point.rb
    CHANGED
    
    
| @@ -30,7 +30,7 @@ module Glimmer | |
| 30 30 | 
             
                class WidgetProxy
         | 
| 31 31 | 
             
                  include Glimmer
         | 
| 32 32 | 
             
                  include PropertyOwner
         | 
| 33 | 
            -
             | 
| 33 | 
            +
                        
         | 
| 34 34 | 
             
                  Event = Struct.new(:widget, keyword_init: true)
         | 
| 35 35 |  | 
| 36 36 | 
             
                  JS_KEY_CODE_TO_SWT_KEY_CODE_MAP = {
         | 
| @@ -295,6 +295,7 @@ module Glimmer | |
| 295 295 | 
             
                  end
         | 
| 296 296 |  | 
| 297 297 | 
             
                  def font=(value)
         | 
| 298 | 
            +
                    return if value.nil?
         | 
| 298 299 | 
             
                    @font = value.is_a?(FontProxy) ? value : FontProxy.new(self, value)
         | 
| 299 300 | 
             
                    dom_element.css('font-family', @font.name) unless @font.nil?
         | 
| 300 301 | 
             
                    dom_element.css('font-style', 'italic') if @font&.style == :italic || [@font&.style].flatten.compact.include?(:italic)
         | 
| @@ -331,9 +332,10 @@ module Glimmer | |
| 331 332 | 
             
                    brand_new = @dom.nil? || old_element.empty? || brand_new
         | 
| 332 333 | 
             
                    build_dom(layout: !custom_parent_dom_element) # TODO handle custom parent layout by passing parent instead of parent dom element
         | 
| 333 334 | 
             
                    if brand_new
         | 
| 334 | 
            -
                       | 
| 335 | 
            +
                      # TODO make a method attach to allow subclasses to override if needed
         | 
| 336 | 
            +
                      attach(the_parent_dom_element)
         | 
| 335 337 | 
             
                    else
         | 
| 336 | 
            -
                      old_element | 
| 338 | 
            +
                      reattach(old_element)
         | 
| 337 339 | 
             
                    end
         | 
| 338 340 | 
             
                    observation_requests&.each do |keyword, event_listener_set|
         | 
| 339 341 | 
             
                      event_listener_set.each do |event_listener|
         | 
| @@ -347,6 +349,14 @@ module Glimmer | |
| 347 349 | 
             
                    content_on_render_blocks.each { |content_block| content(&content_block) } unless skip_content_on_render_blocks?
         | 
| 348 350 | 
             
                  end
         | 
| 349 351 | 
             
                  alias redraw render
         | 
| 352 | 
            +
                    
         | 
| 353 | 
            +
                  def attach(the_parent_dom_element)
         | 
| 354 | 
            +
                    the_parent_dom_element.append(@dom)
         | 
| 355 | 
            +
                  end
         | 
| 356 | 
            +
                    
         | 
| 357 | 
            +
                  def reattach(old_element)
         | 
| 358 | 
            +
                    old_element.replace_with(@dom)
         | 
| 359 | 
            +
                  end
         | 
| 350 360 |  | 
| 351 361 | 
             
                  def content_on_render_blocks
         | 
| 352 362 | 
             
                    @content_on_render_blocks ||= []
         | 
| @@ -367,7 +377,7 @@ module Glimmer | |
| 367 377 | 
             
                  def build_dom(layout: true)
         | 
| 368 378 | 
             
                    # TODO consider passing parent element instead and having table item include a table cell widget only for opal
         | 
| 369 379 | 
             
                    @dom = nil
         | 
| 370 | 
            -
                    @dom = dom
         | 
| 380 | 
            +
                    @dom = dom # TODO unify how to build dom for most widgets based on element, id, and name (class)
         | 
| 371 381 | 
             
                    @dom = @parent.get_layout.dom(@dom) if @parent.respond_to?(:layout) && @parent.get_layout
         | 
| 372 382 | 
             
                    @dom
         | 
| 373 383 | 
             
                  end
         | 
| @@ -1143,6 +1153,7 @@ require 'glimmer/swt/combo_proxy' | |
| 1143 1153 | 
             
            require 'glimmer/swt/c_combo_proxy'
         | 
| 1144 1154 | 
             
            require 'glimmer/swt/checkbox_proxy'
         | 
| 1145 1155 | 
             
            require 'glimmer/swt/composite_proxy'
         | 
| 1156 | 
            +
            require 'glimmer/swt/canvas_proxy'
         | 
| 1146 1157 | 
             
            require 'glimmer/swt/date_time_proxy'
         | 
| 1147 1158 | 
             
            require 'glimmer/swt/group_proxy'
         | 
| 1148 1159 | 
             
            require 'glimmer/swt/label_proxy'
         | 
| @@ -25,10 +25,54 @@ class Tetris | |
| 25 25 | 
             
                  include Glimmer::UI::CustomWidget
         | 
| 26 26 |  | 
| 27 27 | 
             
                  options :game_playfield, :block_size, :row, :column
         | 
| 28 | 
            +
                  
         | 
| 29 | 
            +
                  attr_accessor :bevel_pixel_size
         | 
| 30 | 
            +
                  
         | 
| 31 | 
            +
                  before_body do
         | 
| 32 | 
            +
                    self.bevel_pixel_size = 0.16*block_size.to_f
         | 
| 33 | 
            +
                  end
         | 
| 28 34 |  | 
| 29 35 | 
             
                  body {
         | 
| 30 36 | 
             
                    canvas { |canvas_proxy|
         | 
| 31 37 | 
             
                      background <= [game_playfield[row][column], :color]
         | 
| 38 | 
            +
                      polygon(0, 0, block_size, 0, block_size - bevel_pixel_size, bevel_pixel_size, bevel_pixel_size, bevel_pixel_size) {
         | 
| 39 | 
            +
                        background <= [game_playfield[row][column], :color, on_read: ->(color_value) {
         | 
| 40 | 
            +
                          unless color_value.nil?
         | 
| 41 | 
            +
                            color = color(color_value)
         | 
| 42 | 
            +
                            rgb(color.red + 4*BEVEL_CONSTANT, color.green + 4*BEVEL_CONSTANT, color.blue + 4*BEVEL_CONSTANT)
         | 
| 43 | 
            +
                          end
         | 
| 44 | 
            +
                        }]
         | 
| 45 | 
            +
                      }
         | 
| 46 | 
            +
                      polygon(block_size, 0, block_size - bevel_pixel_size, bevel_pixel_size, block_size - bevel_pixel_size, block_size - bevel_pixel_size, block_size, block_size) {
         | 
| 47 | 
            +
                        background <= [game_playfield[row][column], :color, on_read: ->(color_value) {
         | 
| 48 | 
            +
                          unless color_value.nil?
         | 
| 49 | 
            +
                            color = color(color_value)
         | 
| 50 | 
            +
                            rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
         | 
| 51 | 
            +
                          end
         | 
| 52 | 
            +
                        }]
         | 
| 53 | 
            +
                      }
         | 
| 54 | 
            +
                      polygon(block_size, block_size, 0, block_size, bevel_pixel_size, block_size - bevel_pixel_size, block_size - bevel_pixel_size, block_size - bevel_pixel_size) {
         | 
| 55 | 
            +
                        background <= [game_playfield[row][column], :color, on_read: ->(color_value) {
         | 
| 56 | 
            +
                          unless color_value.nil?
         | 
| 57 | 
            +
                            color = color(color_value)
         | 
| 58 | 
            +
                            rgb(color.red - 2*BEVEL_CONSTANT, color.green - 2*BEVEL_CONSTANT, color.blue - 2*BEVEL_CONSTANT)
         | 
| 59 | 
            +
                          end
         | 
| 60 | 
            +
                        }]
         | 
| 61 | 
            +
                      }
         | 
| 62 | 
            +
                      polygon(0, 0, 0, block_size, bevel_pixel_size, block_size - bevel_pixel_size, bevel_pixel_size, bevel_pixel_size) {
         | 
| 63 | 
            +
                        background <= [game_playfield[row][column], :color, on_read: ->(color_value) {
         | 
| 64 | 
            +
                          unless color_value.nil?
         | 
| 65 | 
            +
                            color = color(color_value)
         | 
| 66 | 
            +
                            rgb(color.red - BEVEL_CONSTANT, color.green - BEVEL_CONSTANT, color.blue - BEVEL_CONSTANT)
         | 
| 67 | 
            +
                          end
         | 
| 68 | 
            +
                        }]
         | 
| 69 | 
            +
                      }
         | 
| 70 | 
            +
                      rectangle(0, 0, block_size, block_size) {
         | 
| 71 | 
            +
                        foreground <= [game_playfield[row][column], :color, on_read: ->(color_value) {
         | 
| 72 | 
            +
                          color_value == Model::Block::COLOR_CLEAR ? :gray : color_value
         | 
| 73 | 
            +
                        }]
         | 
| 74 | 
            +
                      }
         | 
| 75 | 
            +
                      
         | 
| 32 76 | 
             
                    }
         | 
| 33 77 | 
             
                  }
         | 
| 34 78 | 
             
                end
         |