shoes / shoes3

a tiny graphical app kit for ruby
http://walkabout.mvmanila.com
Other
179 stars 19 forks source link

Class widget behaves weird #437

Closed dredknight closed 5 years ago

dredknight commented 5 years ago

Is there any meaning behind this code working

class Boxcounter < Shoes::Widget

    def initialize() 

        @menu = flow;
        @menu.clear do
            @menu1 = flow left: 100, top: 100, width: 100, height: 100 do
                background black
            end
        end
    end

end

Shoes.app do
    @asd = boxcounter
end

and this one that gives error message: "undefined method boxcounter' for (Shoes::Types::App "Shoes") test.rb:19:inmethod_missing' test.rb:19:in `block (2 levels) in

'"

What is the difference and why widget cannot be called within button? May be it wont work with other elements?

class Boxcounter < Shoes::Widget

    def initialize() 

        @menu = flow;
        @menu.clear do
            @menu1 = flow left: 100, top: 100, width: 100, height: 100 do
                background black
            end
        end
    end

end

Shoes.app do

    button "press" do
        @asd = boxcounter
    end
end
ccoupe commented 5 years ago

I'm guessing here - the Boxcounter class is not in scope in the button block. You might try @asd = Shoes::Boxcounter or Shoes::boxcounter. You can also call some inspection methods in the block to find out what it knows or can find - puts self.class and puts self.methods and poke around.

dredknight commented 5 years ago

Thanks! After some tests it seems this is beyond broken to invest more time in it. I tried another approach.

class My_sign
   def initialize(shoes, text)
      @shoes = shoes
      @text = text
   end

   def in_front_of_the_door_says
      @shoes.send(:para, @text)
   end

end

Shoes.app do
   wooden_sign = My_sign.new(self, "beware of the dog")
   wooden_sign.in_front_of_the_door_says
end

Now the above code works without any issue, but I wonder how I can send flows and stacks.

class My_sign
   def initialize(shoes, text)
      @shoes = shoes
      @text = text
   end

   def in_front_of_the_door_says
      @shoes.send(:para, @text)
      @shoes.send(:flow, 100, 100, 50, 50) do
        border black
      end
   end
end

Shoes.app do
   wooden_sign = My_sign.new(self, "beware of the dog")
   wooden_sign.in_front_of_the_door_says
end

In the example above I try to create a a flow stack that has black border but whatever I try the error is always "bad arguments in flow"

Is there a way to see what and how I can send to @Shoes without guessing?

ccoupe commented 5 years ago

The following code does flow layouts in a user defined widget. It used to be in the wiki but doesn't seem to be linked to the menus. Sigh

class Row < Shoes::Widget
  attr_accessor :width, :align, :color, :back, :font, :size

  def initialize(fmts)
    @width = []
    @align = []
    @color = []
    @back = []
    @font = []
    @size = []
    fmts.each do |f|
      @width << f[:width] || 100
      @align << f[:align] || "left"
      @color << f[:color] || black
      @back << (f[:background] ? f[:background] : white)
      @font << (f[:font] ? f[:font] : "Arial")
      @size << f[:size] || 12
    end
  end

  def create(values)
    flow do
      values.each_index do |i| 
        flow width: @width[i] do
          background @back[i]
          para values[i], align: @align[i], stroke: @color[i], font: @font[i], size: @size[i]
        end
      end
    end
  end

end

Shoes.app resizable: true do
  @r = row [{width: 40, align: "right", color: green},
            {width: 100, align: "left", color: black},
            {width: 200, align: "center", color: blue},
            {width: 50, background: lightpink}]
  stack height: 200 ,width: 400, scroll: true do
    @r.create ["1","foobar","really long string"]
    @r.create ["2","not here","sort of a long string"]
    @r.create ["x","hmm","nothing to see"]
    @r.color[0] = red
    @r.create ["error", 12.45, "foo"]
    @r.color[0] = green
    @r.back[1] = lightgrey
    @r.font[2] = "Mono"
    @r.size[2] = 10
    @r.create [5, "oops, this overlows the field", "still working..."]
    @r.back[1] = white
    @r.create [6, 'a', 'b', 'c']
  end
end
dredknight commented 5 years ago

Thanks! I did some tests and it seems my code did not work properly because the flow was in the initialize section and not in separate method.

This is weird but I assume there are a lot of underwater rocks that cause this.

ccoupe commented 5 years ago

The new()/initialize method HAS to return on object of the class. That's standard object programming in any language. In Shoes 3.3.8 we will get a user layout object which is a lot like widget but has some required call back methods. It might be in 3.3.7 if you knew where to look. Incomplete if it is there.

dredknight commented 5 years ago

Thanks closing!