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