#! ruby

# cf:
# Delphi4 プログラミングバイブル p.303
# 7.2. 図形の描画

require 'phi'
include Phi
require 'dialogs'

class BaseShape
  attr :pen_size, true
  attr :pen_color, true
  attr :brush_color, true
  attr :rect
  def initialize
    @rect = Rect.new
  end
  def paint(canvas)
  end
end

module OvalPaint
  def paint(canvas)
    super
    canvas.draw_oval @rect
  end
end

module RectPaint
  def paint(canvas)
    super
    canvas.draw_rect @rect
  end
end

def rect_move(rect,x,y)
  if rect.left < x then rect.right  = x else rect.left = x end
  if rect.top  < y then rect.bottom = y else rect.top  = y end
end

module HasNumParam
  def set_num(n)
    self.caption = n.to_s
    @num = n
  end
  attr :num
end

module HasItems
  def add1(item)
#    super
    @items.push item
  end
  def add_items
    @items = []
    [1,2,4,8,16,32].each do |i|
      item = MenuItem.new
      self.add item
      item.extend HasNumParam
      item.set_num i
      item.group_index = 1
      item.radio_item = true
      def item.on_click
        parent.canvas.pen.width = @num
      end
      add1 item
    end
  end
end

class ShapeForm < Form
  
  def initialize
    super
    canvas.pen.style = Phi::PS_INSIDE_FRAME
    @shapes_list = []
    Phi.new_menu self, :menu, [
      Phi.new_item('&File', '', :mi_file).add(
        Phi.new_item('&new', 'Ctrl+N', :mi_new)
      ),
      Phi.new_item('&Color', '', :mi_color),
      Phi.new_item('&Size', '', :mi_size),
      Phi.new_item('&Help', '', :mi_help),
    ]
    menu_attr_flatten
    mi_size.extend HasItems
    mi_size.add_items
    
    def mi_size.on_click
      item = @items.find { |i| i.num == parent.canvas.pen.width }
      item = @items[-1] if item.nil?
      item.checked = true
    end
    
    def mi_color.on_click
      dlg = ColorDialog.new
      dlg.color = parent.canvas.pen.color
      parent.canvas.pen.color = dlg.color if dlg.execute
    end
    
    def mi_new.on_click
      if parent.shapes_list.empty? then return end
      if Phi.message_dlg('全ての図形を削除してもよろしいですか？', Phi::MT_CONFIRMATION, [Phi::MB_YES, Phi::MB_NO]) == Phi::MR_YES
        parent.shapes_list.clear
        parent.refresh
      end
    end
  end
  
  def on_mouse_down(btn,sft,x,y)
    if btn == Phi::MB_LEFT
      Phi.set_capture handle
      
      @shape = BaseShape.new
      if sft.include? Phi::SS_SHIFT
        @shape.extend OvalPaint
      else
        @shape.extend RectPaint
      end
      
      @shape.pen_size = canvas.pen.width
      @shape.pen_color = canvas.pen.color
      @shape.brush_color = canvas.brush.color
      
      r = @shape.rect
      r.left = x
      r.top = y
      r.right = x
      r.bottom = y
      
      @shapes_list.push @shape
      
      @dragging = true
    end
  end
  
  def on_mouse_move(sft,x,y)
    self.caption = sprintf 'Shapes (x=%d, y=%d)', x,y
    if @dragging
      canvas.draw_focus_rect @shape.rect
      rect_move @shape.rect, x,y
      canvas.draw_focus_rect @shape.rect
    end
  end
  
  def on_mouse_up(btn,sft,x,y)
    if @dragging
      @dragging = false
      Phi.release_capture
      canvas.draw_focus_rect @shape.rect
      rect_move @shape.rect, x,y
      Phi.invalidate_rect handle, @shape.rect, false
    end
  end
  
  def on_paint
    old_pen_color = canvas.pen.color
    old_pen_width = canvas.pen.width
    old_brush_color = canvas.brush.color
    
    @shapes_list.each { |shape| shape.paint(canvas) }
    
    canvas.pen.color = old_pen_color
    canvas.pen.width = old_pen_width
    canvas.brush.color = old_brush_color
  end
  
  attr :shapes_list
end

form = ShapeForm.new

form.show

Phi.mainloop
