/**********************************************************************
*
* FreeDoko a Doppelkopf-Game
*
* Copyright (C) 2001 – 2018 by Diether Knof and Borg Enders
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You can find this license in the file 'gpl.txt'.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Contact:
* Diether Knof dknof@posteo.de
*
*********************************************************************/
#include "constants.h"
#ifdef USE_UI_GTKMM
#include "table_part.h"
#include "ui.h"
namespace UI_GTKMM_NS {
/** constructor
**
** @param table the table
**/
Table::Part::Part(Table& table) :
Base{&table}
{ }
/** destructor
**/
Table::Part::~Part() = default;
/** @return the table
**/
Table&
Table::Part::table()
{
return *dynamic_cast
(this->parent);
} // Table& Part::table()
/** @return the table
**/
Table const&
Table::Part::table() const
{
return *dynamic_cast(this->parent);
} // Table const& Part::table() const
/** @return the corresponding game
**/
Game const&
Table::Part::game() const
{
return this->ui->game();
} // Game const& Part::game() const
/** returns the surface
** If the surface is outdated, redraw it.
**
** @return surface with the drawing in it
**/
Cairo::RefPtr
Table::Part::surface()
{
if ( this->surface_
&& !this->changed())
return this->surface_;
auto const outline = this->outline();
this->surface_ = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32,
outline.width(),
outline.height());
auto cr = Cairo::Context::create(this->surface_);
if (::debug("table")) {
cr->save();
cr->set_source_rgba(0, 0, 1, 0.2);
cr->rectangle(0, 0, outline.width(), outline.height());
cr->fill();
cr->restore();
}
//cr->set_source(this->surface_, outline.x(), outline.y());
cr->set_source(this->surface_, 0, 0);
cr->translate(-outline.x(), -outline.y());
this->draw(cr);
return this->surface_;
} // Cairo::RefPtr Table::Part::surface()
/** Force a redraw
**/
void
Table::Part::force_redraw()
{
this->surface_.clear();
} // void Part::force_redraw()
/** constructor
**
** @param values
**/
Table::Part::Outline::Outline(int x, int y, int width, int height) :
x([x](){ return x; }),
y([y](){ return y; }),
width([width](){ return width; }),
height([height](){ return height; })
{ }
/** constructor
**
** @param values
**/
Table::Part::Outline::Outline(function x, function y,
function width, function height) :
x(std::move(x)),
y(std::move(y)),
width(std::move(width)),
height(std::move(height))
{ }
/** transform the cr according to the geometry
**
** @param cr context to transfomrm
**/
void
Table::Part::Geometry::transform(Cairo::RefPtr<::Cairo::Context> cr) const
{
switch (this->rotation) {
case Rotation::up:
cr->transform(Cairo::Matrix(1, 0, 0, 1,
this->pos_x(),
this->pos_y()));
break;
case Rotation::down:
cr->transform(Cairo::Matrix(-1, 0, 0, -1,
this->pos_x(),
this->pos_y()));
break;
case Rotation::right:
cr->transform(Cairo::Matrix(0, 1, -1, 0,
this->pos_x(),
this->pos_y()));
break;
case Rotation::left:
cr->transform(Cairo::Matrix(0, -1, 1, 0,
this->pos_x(),
this->pos_y()));
break;
} // switch (this->rotation)
} // void Table::Part::Geometry::transform(Cairo::RefPtr<::Cairo::Context> cr) const
/** transform the coordinates
**
** @param x x position
** @param y y position
** @param width width
** @param height height
**/
Table::Part::Outline
Table::Part::Geometry::transform(Outline const outline) const
{
auto const x = outline.x();
auto const y = outline.y();
auto const width = outline.width();
auto const height = outline.height();
switch (this->rotation) {
case Rotation::up:
return {this->pos_x() + x,
this->pos_y() + y,
width,
height};
case Rotation::down:
return {this->pos_x() - x - width,
this->pos_y() - y - height,
width,
height};
case Rotation::right:
return {this->pos_x() - y - height,
this->pos_y() + x,
height,
width};
case Rotation::left:
return {this->pos_x() + y,
this->pos_y() - x - width,
height,
width};
} // switch (this->rotation)
return {};
} // Outline Table::Part::Geometry::transform(Outline outline) const
/** retransforms the coordinates
**
** @param x x position
** @param y y position
**/
void
Table::Part::Geometry::retransform(int& x, int& y) const
{
x -= this->pos_x();
y -= this->pos_y();
switch (this->rotation) {
case Rotation::up:
return ;
case Rotation::down:
x = -x;
y = -y;
return ;
case Rotation::right:
{
int const t = x;
x = y;
y = -t;
}
return ;
case Rotation::left:
{
int const t = x;
x = -y;
y = t;
}
return ;
} // switch (this->rotation)
} // void Table::Part::Geometry::retransform(int& x, int& y) const
/** write the outline into the output stream
**
** @param ostr output stream
** @param outline outline to write
**
** @return output stream
**/
ostream&
operator<<(ostream& ostr, Table::Part::Outline const& outline)
{
ostr << outline.width() << 'x' << outline.height()
<< '+' << outline.x() << '+' << outline.y();
return ostr;
} // ostream& operator<<(ostream& ostr, Table::Part::Outline outline)
/** write the geometry into the output stream
**
** @param ostr output stream
** @param geometry geometry to write
**
** @return output stream
**/
ostream&
operator<<(ostream& ostr, Table::Part::Geometry const& geometry)
{
ostr << geometry.width() << 'x' << geometry.height()
<< '+' << geometry.pos_x() << '+' << geometry.pos_y();
return ostr;
} // ostream& operator<<(ostream& ostr, Table::Part::Geometry geometry)
/** write the geometry into the output stream
**
** @param ostr output stream
** @param geometry geometry to write
**
** @return output stream
**/
Table::Part::Outline
operator+(Table::Part::Outline const lhs,
Table::Part::Outline const rhs)
{
return {[=](){
return min(lhs.x(), rhs.x());
},
[=](){
return min(lhs.y(), rhs.y());
},
[=](){
return (max(lhs.x() + lhs.width(),
rhs.x() + rhs.width())
- min(lhs.x(), rhs.x()));
},
[=](){
return (max(lhs.y() + lhs.height(),
rhs.y() + rhs.height())
- min(lhs.y(), rhs.y()));
}
};
} // Outline operator+(Outline lhs, Outline rhs)
} // namespace UI_GTKMM_NS
#endif // #ifdef USE_UI_GTKMM