1 /**********************************************************************
2 *
3 * FreeDoko a Doppelkopf-Game
4 *
5 * Copyright (C) 2001 – 2018 by Diether Knof and Borg Enders
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You can find this license in the file 'gpl.txt'.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 *
23 * Contact:
24 * Diether Knof dknof@posteo.de
25 *
26 *********************************************************************/
27
28 #include "constants.h"
29
30 #ifdef USE_UI_GTKMM
31
32 #include "table_part.h"
33 #include "ui.h"
34
35 namespace UI_GTKMM_NS {
36
37 /** constructor
38 **
39 ** @param table the table
40 **/
Part(Table & table)41 Table::Part::Part(Table& table) :
42 Base{&table}
43 { }
44
45 /** destructor
46 **/
47 Table::Part::~Part() = default;
48
49 /** @return the table
50 **/
51 Table&
table()52 Table::Part::table()
53 {
54 return *dynamic_cast<Table*>(this->parent);
55 } // Table& Part::table()
56
57 /** @return the table
58 **/
59 Table const&
table() const60 Table::Part::table() const
61 {
62 return *dynamic_cast<Table*>(this->parent);
63 } // Table const& Part::table() const
64
65 /** @return the corresponding game
66 **/
67 Game const&
game() const68 Table::Part::game() const
69 {
70 return this->ui->game();
71 } // Game const& Part::game() const
72
73 /** returns the surface
74 ** If the surface is outdated, redraw it.
75 **
76 ** @return surface with the drawing in it
77 **/
78 Cairo::RefPtr<Cairo::ImageSurface>
surface()79 Table::Part::surface()
80 {
81 if ( this->surface_
82 && !this->changed())
83 return this->surface_;
84
85 auto const outline = this->outline();
86 this->surface_ = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32,
87 outline.width(),
88 outline.height());
89 auto cr = Cairo::Context::create(this->surface_);
90 if (::debug("table")) {
91 cr->save();
92 cr->set_source_rgba(0, 0, 1, 0.2);
93 cr->rectangle(0, 0, outline.width(), outline.height());
94 cr->fill();
95 cr->restore();
96 }
97 //cr->set_source(this->surface_, outline.x(), outline.y());
98 cr->set_source(this->surface_, 0, 0);
99 cr->translate(-outline.x(), -outline.y());
100 this->draw(cr);
101
102 return this->surface_;
103 } // Cairo::RefPtr<Cairo::ImageSurface> Table::Part::surface()
104
105 /** Force a redraw
106 **/
107 void
force_redraw()108 Table::Part::force_redraw()
109 {
110 this->surface_.clear();
111 } // void Part::force_redraw()
112
113 /** constructor
114 **
115 ** @param values
116 **/
Outline(int x,int y,int width,int height)117 Table::Part::Outline::Outline(int x, int y, int width, int height) :
118 x([x](){ return x; }),
__anonf56cd8700202()119 y([y](){ return y; }),
__anonf56cd8700302()120 width([width](){ return width; }),
__anonf56cd8700402()121 height([height](){ return height; })
122 { }
123
124 /** constructor
125 **
126 ** @param values
127 **/
Outline(function<int ()> x,function<int ()> y,function<int ()> width,function<int ()> height)128 Table::Part::Outline::Outline(function<int()> x, function<int()> y,
129 function<int()> width, function<int()> height) :
130 x(std::move(x)),
131 y(std::move(y)),
132 width(std::move(width)),
133 height(std::move(height))
134 { }
135
136 /** transform the cr according to the geometry
137 **
138 ** @param cr context to transfomrm
139 **/
140 void
transform(Cairo::RefPtr<::Cairo::Context> cr) const141 Table::Part::Geometry::transform(Cairo::RefPtr<::Cairo::Context> cr) const
142 {
143 switch (this->rotation) {
144 case Rotation::up:
145 cr->transform(Cairo::Matrix(1, 0, 0, 1,
146 this->pos_x(),
147 this->pos_y()));
148 break;
149 case Rotation::down:
150 cr->transform(Cairo::Matrix(-1, 0, 0, -1,
151 this->pos_x(),
152 this->pos_y()));
153 break;
154 case Rotation::right:
155 cr->transform(Cairo::Matrix(0, 1, -1, 0,
156 this->pos_x(),
157 this->pos_y()));
158 break;
159 case Rotation::left:
160 cr->transform(Cairo::Matrix(0, -1, 1, 0,
161 this->pos_x(),
162 this->pos_y()));
163 break;
164 } // switch (this->rotation)
165 } // void Table::Part::Geometry::transform(Cairo::RefPtr<::Cairo::Context> cr) const
166
167 /** transform the coordinates
168 **
169 ** @param x x position
170 ** @param y y position
171 ** @param width width
172 ** @param height height
173 **/
174 Table::Part::Outline
transform(Outline const outline) const175 Table::Part::Geometry::transform(Outline const outline) const
176 {
177 auto const x = outline.x();
178 auto const y = outline.y();
179 auto const width = outline.width();
180 auto const height = outline.height();
181 switch (this->rotation) {
182 case Rotation::up:
183 return {this->pos_x() + x,
184 this->pos_y() + y,
185 width,
186 height};
187 case Rotation::down:
188 return {this->pos_x() - x - width,
189 this->pos_y() - y - height,
190 width,
191 height};
192 case Rotation::right:
193 return {this->pos_x() - y - height,
194 this->pos_y() + x,
195 height,
196 width};
197 case Rotation::left:
198 return {this->pos_x() + y,
199 this->pos_y() - x - width,
200 height,
201 width};
202 } // switch (this->rotation)
203 return {};
204 } // Outline Table::Part::Geometry::transform(Outline outline) const
205
206 /** retransforms the coordinates
207 **
208 ** @param x x position
209 ** @param y y position
210 **/
211 void
retransform(int & x,int & y) const212 Table::Part::Geometry::retransform(int& x, int& y) const
213 {
214 x -= this->pos_x();
215 y -= this->pos_y();
216 switch (this->rotation) {
217 case Rotation::up:
218 return ;
219 case Rotation::down:
220 x = -x;
221 y = -y;
222 return ;
223 case Rotation::right:
224 {
225 int const t = x;
226 x = y;
227 y = -t;
228 }
229 return ;
230 case Rotation::left:
231 {
232 int const t = x;
233 x = -y;
234 y = t;
235 }
236 return ;
237 } // switch (this->rotation)
238 } // void Table::Part::Geometry::retransform(int& x, int& y) const
239
240 /** write the outline into the output stream
241 **
242 ** @param ostr output stream
243 ** @param outline outline to write
244 **
245 ** @return output stream
246 **/
247 ostream&
operator <<(ostream & ostr,Table::Part::Outline const & outline)248 operator<<(ostream& ostr, Table::Part::Outline const& outline)
249 {
250 ostr << outline.width() << 'x' << outline.height()
251 << '+' << outline.x() << '+' << outline.y();
252 return ostr;
253 } // ostream& operator<<(ostream& ostr, Table::Part::Outline outline)
254
255 /** write the geometry into the output stream
256 **
257 ** @param ostr output stream
258 ** @param geometry geometry to write
259 **
260 ** @return output stream
261 **/
262 ostream&
operator <<(ostream & ostr,Table::Part::Geometry const & geometry)263 operator<<(ostream& ostr, Table::Part::Geometry const& geometry)
264 {
265 ostr << geometry.width() << 'x' << geometry.height()
266 << '+' << geometry.pos_x() << '+' << geometry.pos_y();
267 return ostr;
268 } // ostream& operator<<(ostream& ostr, Table::Part::Geometry geometry)
269
270 /** write the geometry into the output stream
271 **
272 ** @param ostr output stream
273 ** @param geometry geometry to write
274 **
275 ** @return output stream
276 **/
277 Table::Part::Outline
operator +(Table::Part::Outline const lhs,Table::Part::Outline const rhs)278 operator+(Table::Part::Outline const lhs,
279 Table::Part::Outline const rhs)
280 {
281 return {[=](){
282 return min(lhs.x(), rhs.x());
283 },
284 [=](){
285 return min(lhs.y(), rhs.y());
286 },
287 [=](){
288 return (max(lhs.x() + lhs.width(),
289 rhs.x() + rhs.width())
290 - min(lhs.x(), rhs.x()));
291 },
292 [=](){
293 return (max(lhs.y() + lhs.height(),
294 rhs.y() + rhs.height())
295 - min(lhs.y(), rhs.y()));
296 }
297 };
298 } // Outline operator+(Outline lhs, Outline rhs)
299 } // namespace UI_GTKMM_NS
300
301 #endif // #ifdef USE_UI_GTKMM
302