ボタンをつくる

ボタンのクラスに中心の座標と実体をRangeクラスを使って置いた。
context#rectangleを使うパターンと
線を描いていくパターンをつくってみた。

#!usr/bin/env ruby

require 'sdl'
require 'cairo'

class EventHandle
def initialize(handle)
@handle = handle
@type = {
SDL::Event::KeyDown => :sym,
SDL::Event::KeyUp => :sym,
SDL::Event::MouseButtonDown => :button,
SDL::Event::MouseButtonUp => :button
}
end

def handling(event)
name = event.class
if @type[name]
if callback = @handle[[name,event.method(@type[name]).call]]
return callback.call(event)
end
end
if callback = @handle[name]
return callback.call(event)
end
nil
end
end

class BackGround
def initialize(w, h)
@w, @h = w, h
end

def update(c)
c.set_source_color(Cairo::Color::BLACK)
c.rectangle(0, 0, @w, @h)
c.fill
end
end

class Button
def initialize(w, h)
@width, @height = 80, 30
@color = Cairo::Color::SILVER
@handle = EventHandle.new(
[SDL::Event::MouseButtonDown,SDL::Mouse::BUTTON_LEFT] => proc{|e| @color = Cairo::Color::RED if touch_point?(e)},
[SDL::Event::MouseButtonUp,SDL::Mouse::BUTTON_LEFT] => proc{|e| @color = Cairo::Color::SILVER}
)
end

def handling(e)
@handle.handling(e)
end

def touch_point?(e)
@range_x.include?(e.x - @x) && @range_y.include?(e.y - @y)
end
end

class Button1 < Button
def initialize(w, h)
super
@x, @y = w / 2, h / 3
cx, cy = @width / 2, @height / 2
@vectors = [
[-cx, -cy],
[cx, -cy],
[cx, cy],
[-cx, cy]]
@range_x = -cx .. cx
@range_y = -cy .. cy
end

def update(c)
c.matrix = Cairo::Matrix.translate(@x, @y)
c.set_source_color(@color)
@vectors.inject(true) do |b, v|
x, y = v
if b
c.move_to(x, y)
else
c.line_to(x, y)
end
b = false
end
c.close_path
c.fill_preserve
c.set_source_color(Cairo::Color::TEAL)
c.stroke
end
end

class Button2 < Button
def initialize(w, h)
super
@x, @y = w / 2, h / 3 * 2
cx, cy = @width / 2, @height / 2
@range_x = -cx .. cx
@range_y = -cy .. cy
end

def update(c)
c.matrix = Cairo::Matrix.translate(@x, @y)
c.set_source_color(@color)
c.rectangle(@range_x.first, @range_y.first, @range_x.last * 2, @range_y.last * 2)
c.fill_preserve
c.set_source_color(Cairo::Color::TEAL)
c.stroke
end
end

class Phase
def initialize(screen)
@screen = screen
@w, @h = @screen.w, @screen.h
@image = Cairo::ImageSurface.new(@w, @h)
@bg = BackGround.new(@w, @h)
@items = []
@items << Button1.new(@w, @h)
@items << Button2.new(@w, @h)
@handle = EventHandle.new(
SDL::Event::Quit => proc{exit},
[SDL::Event::KeyDown,SDL::Key::ESCAPE] => proc{exit}
)
end

def handling(e)
@handle.handling(e)
@items.each do |obj|
obj.handling(e)
end
end

def update
context = Cairo::Context.new(@image)
@bg.update(context)
@items.each do |obj|
obj.update(context)
end
surface = SDL::Surface.new_from(@image.data, @image.width, @image.height, 32, @image.stride, 0, 0, 0, 0)
@screen.put(surface, 0, 0)
end

def run
loop do
while e=SDL::Event.poll
self.handling(e)
end
self.update
@screen.flip
SDL.delay(20)
end
end
end

SDL.init(SDL::INIT_VIDEO)
screen = SDL::Screen.open(250, 250, SDL::Screen.info.bpp, SDL::SWSURFACE)
Phase.new(screen).run
[PR]
by gaziya | 2011-05-17 19:10