How to right align an array of numbers in Ruby Shoes? - ruby

Tried align: right and sprintf, but for some reason it does not do a right alignment.
[ 50, 100, 50 ]
50
100
50
Is this a limitation of Shoes 4?

I tested this with green shoes since i don't use Shoes4 but it should be the same.
Shoes.app do
flow do
[ 50, 100, 50 ].each do |number|
para number, :align => 'right'
end
end
end

Related

Ruby - Hash function with unknown number of arguments

I'm trying to make a calorie counter for the below hash menu. in this example I've passed 3 arguments - what would the function need to look like it the number of parameters/arguments is unknown?
#menu = {
"hamburger" => 250,
"Cheese burger" => 350,
"cola" => 35,
"salad" => 120,
"dessert" => 350
}
def order(a, b, c)
return #menu[a] + #menu[b] + #menu[c]
end
puts order("hamburger", "Cheese burger", "cola")
tried
def order(**a)
total = 0
total += #menu[**a]
end
i know (*a) works for arrays.
I'd like to be able to get results for
puts order("hamburger")
and equally for
puts order("Cheese burger", "salad"), for example
In Ruby, it is often possible to write the code exactly the same way you would describe the solution in English. In this case, you need to get the values at specific keys of the hash and then compute the sum of the values.
You can use the Hash#values_at method to get the values at the specific keys and you can use the Array#sum method to compute the sum of the values:
def order(*items)
#menu.values_at(*items).sum
end
Note that it is strange to use an instance variable of the top-level main object. It would make much more sense to use a constant:
MENU = {
'hamburger' => 250,
'Cheese burger' => 350,
'cola' => 35,
'salad' => 120,
'dessert' => 350,
}
def order(*items)
MENU.values_at(*items).sum
end
It would also make sense to freeze the hash:
MENU = {
'hamburger' => 250,
'Cheese burger' => 350,
'cola' => 35,
'salad' => 120,
'dessert' => 350,
}.freeze
And last but not least, I find the name of the order method somewhat misleading. It is also ambiguous: is order meant to be a noun and this is meant to be a getter method that retrieves an order? Or is it meant to be a verb and it is meant to be a command method which tells the object to execute an order?
Either way, it does not seem that the method is doing either of those two things, rather it seems to compute a total. So, the name should probably reflect that.
I would do:
MENU = {
"hamburger" => 250,
"Cheese burger" => 350,
"cola" => 35,
"salad" => 120,
"dessert" => 350
}
def order(*args)
MENU.values_at(*args).sum
end
order("hamburger", "Cheese burger", "cola")
#=> 635
Read about the Ruby Splat Operator, Hash#values_at and Array#sum.
When you really want to use each (what I would not recommend), like mentioned in the comment, then you can implement it like this:
def order(*args)
total = 0
args.each { |name| total += MENU[name] }
total
end
or
def order(*args)
total = 0
MENU.values_at(*args).each { |value| total += value }
total
end

Button on the canavas. Ruby Tk

Is there any way to put button(TK) on the TkCanavas widget ? I need to capture mouse button actions on diffrent parts of canavas to do a little TicTacToe game. I used TkCanavas because of drawing field lines and putting objects on exact coordinates
require 'tk'
class Window
##xs = [60,145,235,60,145,235,60,145,235]
##ys = [140,140,140,225,225,225,315,315,315] #coordinates of circles and crosses
def run
root = TkRoot.new { title 'TicTacToe' }
root.geometry("300x400+300+300")
img = TkPhotoImage.new(:file => 'cross.gif')
cv = TkCanvas.new(root)
cv.place(:height => 400, :width => 300)
cv.create(TkcImage, ##xs[2], ##ys[2], :image => img)
cv.create(TkButton, 60, 140,120,200 ) #
cv.create(TkcLine, 20, 180, 280, 180) #
cv.create(TkcLine, 20, 270, 280, 270) #Field lines
cv.create(TkcLine, 100, 100, 100, 360) #
cv.create(TkcLine, 190,100, 190, 360) #
TkcText.new(cv, 140, 30, :font => 'Arial 14',
:text => 'TicTacToe', :anchor => 'center')
Tk.mainloop
end
end
Try using TkcRectangle instead of TkButton. You can bind events to the rectangle like you can to the button.

Ruby Shoes Hover element

Hover element dosen't work. Where is problem? How fix it?
Shoes.app :width => 635, :height => 410 do
background image "http://PATH_TO_IMAGE"
a = stack :width => 360, :height => 200, :margin_left => 250, :margin_top => 200 do
hover do
a.clear { para "Some Text qwe qwe qwerty", :stroke => black }
end
leave do
a.clear { background image "http://PATH_TO_IMAGE" }
end
end
end
I think in principle you cannot use image as the argument for background.
I also am not sure if that is effect you want to achieve but it shows what you did wrong:
Shoes.app :width => 635, :height => 410 do
a = stack :width => 360, :height => 200 do
image "http://PATH_TO_IMAGE"
hover do
a.clear {para "Some Text qwe qwe qwerty", :stroke => black }
end
leave do
a.clear { image "http://PATH_TO_IMAGE" }
end
end
end

Can't align middle a list_box

I can't align middle a list_box in ruby shoes. I have test a few things, including :right => "50" or :left => "50", but it still not work.
Shoes.app do
stack :width => "100%", :height => "45%" do
a = list_box :items => ["lol","b"], :width => 50, :align => "center"
end
end
I did not find a direct way but you can use this hack
module Shoes::Types
def centr
left=(self.parent.width-self.style[:width])/2
self.move(left,self.top)
end
def middle
top=(self.parent.height-self.style[:height])/2
self.move(self.left,top)
end
end
Shoes.app do
#c=stack :width=>50, :height=>30 do
a=list_box :items => ["lol","b"], :width => 50, :height=>30
end
#c.centr.middle
end
What is done is actually first to extend the functionality of slots so that you can place them in the center or middle of the containing slot. Then you wrap your listbox in a tiny slot, which you center.

How can I get vertical alignment in flow slot in Shoes?

The default vertical alignment in a flow slot is apparently to top-align the elements. Here's a sample:
Shoes.app (:title => "Vertical Alignment", :width => 300, :height => 150) do
background "#DFA"
flow :margin => 30 do
title "BIG"
tagline "MEDIUM"
inscription "SMALL"
end
end
How do I get the flow slot to center-align its elements short of calculating a :rise value for each element? I would have expected a vertical-alignment style for flow slots and a horizontal-alignment style for stack slots, but I don't see anything like that. What did I miss?
To my knowledge, there's no style for vertical alignment. There is horizontal alignment which is useful in stacks:
Shoes.app (:title => "Horizontal Alignment", :width => 300, :height => 150) do
background "#DFA"
stack :margin => 30 do
title "BIG", :align => 'center'
tagline "MEDIUM", :align => 'center'
inscription "SMALL", :align => 'center'
end
end
Keep in mind that Shoes is very much still a work in progress, so _why will probably get around to it eventually.

Resources