Factor common code out of xboard and gnushogi engines.
[kaya/ydirson.git] / lib / board / pool.rb
blobfa311d6e104b8985792faf608d133f980c830db7
1 # Copyright (c) 2009 Paolo Capriotti <p.capriotti@gmail.com>
2
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 require 'item'
10 class Pool < Qt::GraphicsItemGroup
11   BACKGROUND_ZVALUE = -10
12   
13   include Observable
14   include ItemUtils
15   include TaggableSquares
16   
17   attr_reader :rect, :scene, :items, :theme
18   attr_reader :animator, :unit
19   square_tag :premove_src, :premove, :target => :extra
20   
21   def initialize(scene, theme, game)
22     super(nil, scene)
23     @scene = scene
24     @scene.add_clickable_element(self)
25     
26     @theme = theme
27     @game = game
28     
29     @items = []
30     @extra = ExtraItemContainer.new(self)
31     @size = Point.new(3, 5)
32     
33     @type_values = Hash.new(-1)
34     if @game.respond_to? :types
35       @game.types.each_with_index do |type, index|
36         @type_values[type] = index
37       end
38     end
39     
40     @animator = PoolAnimator.new(self)
41     @flipped = false
42   end
43   
44   def square_tag_container
45     @extra
46   end
47   
48   def flip(value)
49     @flipped = value
50   end
51   
52   def flipped?
53     @flipped
54   end
55   
56   def redraw
57     pieces = @items.map do |item|
58       destroy_item(item)
59       item.name
60     end
61     @items = []
62     
63     pieces.each_with_index do |piece, index|
64       add_piece(index, piece)
65     end
66     
67     @extra.redraw
68   end
70   def set_geometry(rect)
71     @rect = rect
72     
73     self.pos = @rect.top_left.to_f
74     
75     side = (@rect.width / @size.x).floor
76     @unit = Qt::Point.new(side, side)
77     redraw
78   end
79   
80   def add_piece(index, piece, opts = {})
81     opts = opts.merge :pos => to_real(index),
82                       :name => piece
83     item = create_item index, @theme.pieces.pixmap(piece, @unit), opts
84     items.insert(index, item)
85     item
86   end
87   
88   def remove_item(index, *args)
89     item = items.delete_at(index)
90     unless item.nil? or args.include?(:keep)
91       destroy_item item
92     end
93     item
94   end
95   
96   def on_click(pos)
97     
98   end
99   
100   def on_drag(pos)
101     index = to_logical(pos)
102     item = items[index]
103     if item
104       fire :drag => { :index => index,
105                       :item => item }
106     end
107   end
108   
109   def on_drop(old_pos, pos, data)
110     if data[:item]
111       fire :drop => data
112     end
113   end
114   
115   def to_logical(p)
116     y = p.y.to_f
117     if @flipped
118       y = rect.height - y
119     end
120     result = Point.new((p.x.to_f / @unit.x).floor,
121                        (y / @unit.y).floor)
122     y = result.y
123     x = y % 2 == 0 ? result.x : @size.x - result.x - 1
124     x + y * @size.x
125   end
126   
127   def to_real(index)
128     x = index % @size.x
129     y = index / @size.x
130     x = @size.x - x - 1 if y % 2 == 1
131     
132     rx = x * @unit.x
133     ry = if @flipped
134       rect.height - (y + 1) * @unit.y
135     else
136       y * @unit.y
137     end
138     
139     Qt::PointF.new(rx, ry)
140   end
141   
142   def compare(piece1, piece2)
143     [piece1.color.to_s, @type_values[piece1.type], piece1.type.to_s] <=>
144     [piece2.color.to_s, @type_values[piece2.type], piece2.type.to_s]
145   end
146   
147   class ExtraItemContainer
148     include ItemBag
149     include ItemUtils
150     
151     attr_reader :items
152     
153     def initialize(pool)
154       @pool = pool
155       @items = { }
156     end
157     
158     def redraw
159       @items.each do |key, item|
160         @pool.set_tag(key, @pool.tag(key))
161       end
162     end
163     
164     def item_parent
165       @pool
166     end
167     
168     def scene
169       @pool.scene
170     end
171   end