/********************************************************************** * * FreeDoko a Doppelkopf-Game * * Copyright (C) 2001-2007 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@gmx.de * Borg Enders borg@borgsoft.de * *********************************************************************/ #include "constants.h" #ifdef USE_UI_GTKMM #include "table.h" #include "poverty.h" #include "party_points.h" #include "party_finished.h" #include "last_trick.h" #include "trick.h" #include "hand.h" #include "trickpile.h" #include "icongroup.h" #include "name.h" #include "reservation.h" #include "ui.h" #include "cards.h" #include "utils.h" #include "gameinfo_dialog.h" #include "full_trick.h" #include "game_finished.h" #include "../../party/party.h" #include "../../party/rule.h" #include "../../game/game.h" #include "../../player/player.h" #include "../../card/trick.h" #include "../../misc/setting.h" #include "../../utils/string.h" #include #include using std::pow; namespace UI_GTKMM_NS { /** ** ** clear the full pixmap ** ** @param - ** ** @return - ** ** @version 0.5.4 ** ** @author Diether Knof ** **/ void Table::clear_all() { this->clear(Gdk::Rectangle(0, 0, this->width(), this->height())); return ; } // void Table::clear_all() /** ** ** clears the rectangle ** ** @param area area to clear ** ** @return - ** ** @version 0.6.2 ** ** @author Diether Knof ** **/ void Table::clear(Gdk::Rectangle const& area) { this->pixmap->draw_rectangle(this->gc, true, area.get_x(), area.get_y(), area.get_width(), area.get_height()); return ; } // void Table::clear(Gdk::Rectangle const& area) /** ** ** draw all ** ** @param update whether to update the area ** ** @return - ** ** @version 0.5.4 ** ** @author Diether Knof ** **/ void Table::draw_all(bool const update) { this->clear_all(); if (::game_status & GAMESTATUS::GAME) { for (vector::iterator h = this->hand_.begin(); h != this->hand_.end(); h++) (*h)->draw(false); for (vector::iterator t = this->trickpile_.begin(); t != this->trickpile_.end(); t++) (*t)->draw(false); for (vector::iterator t = this->icongroup_.begin(); t != this->icongroup_.end(); t++) (*t)->draw(false); for (vector::iterator n = this->name_.begin(); n != this->name_.end(); n++) (*n)->draw(false); if (this->trick_) this->trick_->draw(false); if ( (this->ui->game().type() == GAMETYPE::POVERTY) && (((::game_status == GAMESTATUS::GAME_POVERTY_SHIFT) || (::game_status == GAMESTATUS::GAME_REDISTRIBUTE) ) ) && this->poverty_) this->poverty().draw(false); } else if (::game_status == GAMESTATUS::PARTY_FINISHED) { #ifdef OUTDATED // -> party_summary window this->draw_party_summary(); #endif } else { // if (::game_status) this->draw_logo(); } // if (::game_status) if (update) this->update_full_area(); this->mouse_cursor_update(); return ; } // void Table::draw_all(bool const update = true) /** ** ** draw the logo ** ** @param - ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** ** @bug clip mask does not work (GTK-bug?) ** **/ void Table::draw_logo() { this->pixmap->draw_pixbuf(this->gc, this->ui->logo, 0, 0, (this->width() - this->ui->logo->get_width()) / 2, (this->height() - this->ui->logo->get_height()) / 2, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); { // draw a border with the cards vector border_card; // the border cards unsigned const card_width = this->ui->cards->width(); unsigned const card_height = this->ui->cards->height(); // the bitmap of the border cards on the top vector > border_card_top_bitmap; // the border of the top card row unsigned border_top_x; { // top border_card.clear(); border_card.push_back(Card(Card::HEART, Card::TEN)); border_card.push_back(Card(Card::CLUB, Card::QUEEN)); border_card.push_back(Card(Card::SPADE, Card::QUEEN)); border_card.push_back(Card(Card::HEART, Card::QUEEN)); border_card.push_back(Card(Card::DIAMOND, Card::QUEEN)); border_card.push_back(Card(Card::CLUB, Card::JACK)); border_card.push_back(Card(Card::SPADE, Card::JACK)); border_top_x = (card_width + ( (border_card.size() * card_height + card_width >= this->width()) ? 0 : ((this->width() - (border_card.size() * card_height + card_width) ) / border_card.size()) ) ); for (unsigned n = 0; n < border_card.size(); n++) { this->pixmap->draw_pixbuf(this->gc, this->ui->cards->card(border_card[n], LEFT), 0, 0, border_top_x + n * (this->width() - 2 * border_top_x - card_height) / (border_card.size() - 1), card_width / 2, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); // set the bitmap border_card_top_bitmap.push_back(bitmap(this->ui->cards->card(border_card[n], LEFT))); } // for (n < border_card.size()) } // top { // right border_card.clear(); border_card.push_back(Card(Card::HEART, Card::JACK)); border_card.push_back(Card(Card::DIAMOND, Card::JACK)); border_card.push_back(Card(Card::DIAMOND, Card::ACE)); border_card.push_back(Card(Card::DIAMOND, Card::TEN)); border_card.push_back(Card(Card::DIAMOND, Card::KING)); unsigned const border_y = (card_width + ( (border_card.size() * card_height + card_width >= this->height()) ? 0 : ((this->height() - (border_card.size() * card_height + card_width) ) / border_card.size()) ) ); for (unsigned n = 0; n < border_card.size(); n++) this->pixmap->draw_pixbuf(this->gc, this->ui->cards->card(border_card[n], UP), 0, 0, this->width() - 3 * card_width / 2, border_y + n * (this->height() - 2 * border_y - card_height) / (border_card.size() - 1), -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); } // right { // bottom border_card.clear(); border_card.push_back(Card(Card::DIAMOND, Card::NINE)); border_card.push_back(Card(Card::CLUB, Card::ACE)); border_card.push_back(Card(Card::CLUB, Card::TEN)); border_card.push_back(Card(Card::CLUB, Card::KING)); border_card.push_back(Card(Card::CLUB, Card::NINE)); border_card.push_back(Card(Card::HEART, Card::ACE)); border_card.push_back(Card(Card::HEART, Card::KING)); unsigned const border_x = (card_width + ( (border_card.size() * card_height + card_width >= this->width()) ? 0 : ((this->width() - (border_card.size() * card_height + card_width) ) / border_card.size()) ) ); for (unsigned n = 0; n < border_card.size(); n++) this->pixmap->draw_pixbuf(this->gc, this->ui->cards->card(border_card[n], RIGHT), 0, 0, border_x + (border_card.size() - 1 - n) * (this->width() - 2 * border_x - card_height) / (border_card.size() - 1), this->height() - 3 * card_width / 2, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); } // bottom { // left border_card.clear(); border_card.push_back(Card(Card::HEART, Card::NINE)); border_card.push_back(Card(Card::SPADE, Card::ACE)); border_card.push_back(Card(Card::SPADE, Card::TEN)); border_card.push_back(Card(Card::SPADE, Card::KING)); border_card.push_back(Card(Card::SPADE, Card::NINE)); unsigned const border_y = (card_width + ( (border_card.size() * card_height + card_width >= this->height()) ? 0 : ((this->height() - (border_card.size() * card_height + card_width) ) / border_card.size()) ) ); for (unsigned n = 0; n < border_card.size(); n++) { int const pos_x = card_width / 2; int const pos_y = (border_y + (border_card.size() - 1 - n) * (this->height() - 2 * border_y - card_height) / (border_card.size() - 1)); // for the overlapping of the left with the upper row // use a separate gc Glib::RefPtr bitmap_overlapping = bitmap(this->ui->cards->card(border_card[n], DOWN)); // for adding the bitmaps Glib::RefPtr gc_add = (!bitmap_overlapping ? Gdk::GC::create(this->pixmap) : Gdk::GC::create(bitmap_overlapping)); gc_add->set_function(Gdk::AND_INVERT); if (bitmap_overlapping) for (unsigned i = 0; i < border_card_top_bitmap.size(); i++) { bitmap_overlapping->draw_drawable(gc_add, border_card_top_bitmap[i], 0, 0, border_top_x + i * (this->width() - 2 * border_top_x - card_height) / (border_card.size() - 1) - pos_x, card_width / 2 - pos_y, card_height, card_width); } // for (i < border_card_top_bitmap.size()) Glib::RefPtr gc_overlapping = Gdk::GC::create(this->pixmap); if (bitmap_overlapping) gc_overlapping->set_clip_mask(bitmap_overlapping); gc_overlapping->set_clip_origin(pos_x, pos_y); #if 0 this->pixmap->draw_rectangle(gc_overlapping, true, pos_x, pos_y, card_width, card_height); #else this->pixmap->draw_pixbuf(gc_overlapping, this->ui->cards->card(border_card[n], DOWN), 0, 0, pos_x, pos_y, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); #endif } } // left } // draw a border with the cards return ; } // void Table::draw_logo() /** ** draw the party summary ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.8 **/ void Table::draw_party_summary() { /* * _________ * _________ | | * | |________ | | * | | | | | * | 75 | 50 | -50 | 100 | * Diether Erwin | Theo | Rudi | * |_______| */ Party const& party = this->ui->party(); int min_points = 0; // minimal points made by the players int max_points = 0; // maximal points made by the players for (vector::const_iterator p = party.players().begin(); p != party.players().end(); ++p) { int const points = party.pointsum(**p); if (points < min_points) min_points = points; if (points > max_points) max_points = points; } // for (p \in party.players()) if (max_points == min_points) max_points += 1; Gdk::Color color_pillar("brown"); Gdk::Color color_name(::setting(Setting::NAME_FONT_COLOR)); Gdk::Color color_winner_pillar("gold"); Gdk::Color color_winner_name(::setting(Setting::NAME_ACTIVE_FONT_COLOR)); int const border_x = this->width() / 10; int const border_y = this->height() / 10; int const total_width = this->width() - 2 * border_x; int const total_height = this->height() - 2 * border_y; int const baseline = (border_y + (max_points * total_height / (max_points - min_points)) ); int const width = total_width / party.playerno(); for (unsigned p = 0; p < party.playerno(); ++p) { Player const& player = party.player(p); bool winner = (party.rang(player) == 0); int const points = party.pointsum(player); int const pos_x = border_x + p * width; int height = (points * total_height / (max_points - min_points)); { // text Glib::RefPtr gc = Gdk::GC::create(this->pixmap); gc->set_rgb_fg_color( winner ? color_winner_name : color_name); { // draw name this->name_layout->set_text(player.name()); int layout_width, layout_height; this->name_layout->get_pixel_size(layout_width, layout_height); // bug: there seems to be a problem with italic characters layout_width += 2 * layout_height / 5; this->pixmap->draw_layout(gc, pos_x + (width - layout_width) / 2, ( (height >= 0) ? (baseline - layout_height * 6 / 5) : baseline ), this->name_layout); } // draw name { // draw points this->trickpile_points_layout->set_text(DK::Utils::String::to_string(points)); int layout_width, layout_height; this->trickpile_points_layout->get_pixel_size(layout_width, layout_height); // bug: there seems to be a problem with italic characters layout_width += 2 * layout_height / 5; // fix y-position so that the name and the points do not overlap if ( (height >= 0) && (height < layout_height) ) height = layout_height; else if ( (height < 0) && (height > -layout_height) ) height = -layout_height; this->pixmap->draw_layout(gc, pos_x + (width - layout_width) / 2, baseline - height + ( (height >= 0) ? ( - layout_height * 6 / 5) : ( layout_height * 1 / 5)), this->trickpile_points_layout); } // draw points } // text } // for ( p < party.playerno()) for (unsigned p = 0; p < party.playerno(); ++p) { Player const& player = party.player(p); int const points = party.pointsum(player); bool winner = (party.rang(player) == 0); int const pos_x = border_x + p * width; { // draw pillar int const height = (points * total_height / (max_points - min_points)); int const x = pos_x; int const y = ( (height >= 0) ? baseline - height : baseline ); int const w = width; int const h = ( (height >= 0) ? height : -height ); // ToDo: make the darkening faster Glib::RefPtr gc = Gdk::GC::create(this->pixmap); gc->set_function(Gdk::COPY); Glib::RefPtr image = this->pixmap->get_image(x, y, w, h); Gdk::Color c; int const round_border = w / 10; for (int i = 0; i < w; ++i) for (int j = 0; j < h; ++j) { // round border if (height >= 0) { if ((j < round_border) && ( ( (i < round_border) && ( ( QUAD(round_border - i) + QUAD(round_border - j) ) > QUAD(round_border) ) ) || ((i > w - round_border) && ( ( QUAD(round_border - (w - i)) + QUAD(round_border - j) ) > QUAD(round_border) ) ) ) ) continue; } else { if ((j > h - round_border) && ( ( (i < round_border) && ( ( QUAD(round_border - i) + QUAD(round_border - (h - j)) ) > QUAD(round_border) ) ) || ((i > w - round_border) && ( ( QUAD(round_border - (w - i)) + QUAD(round_border - (h - j)) ) > QUAD(round_border) ) ) ) ) continue; } image->get_colormap()->query_color(image->get_pixel(i, j), c); #if 0 if (winner) c.set_rgb_p(c.get_red_p() / 2, c.get_green_p() / 2, c.get_blue_p() / 2); else c.set_rgb_p(c.get_red_p() / 1.5, c.get_green_p() / 1.5, c.get_blue_p() / 1.5); #endif if (winner) c.set_rgb_p(pow(c.get_red_p(), 3), pow(c.get_green_p(), 3), pow(c.get_blue_p(), 3)); else c.set_rgb_p(pow(c.get_red_p(), 2), pow(c.get_green_p(), 2), pow(c.get_blue_p(), 2)); gc->set_rgb_fg_color(c); this->pixmap->draw_point(gc, x + i, y + j); } } // draw pillar } // for ( p < party.playerno()) return ; } // void Table::draw_party_summary() /** ** ** draw all hands ** ** @param - ** ** @return - ** ** @version 0.6.1 ** ** @author Diether Knof ** **/ void Table::draw_all_hands() { if (::game_status & GAMESTATUS::GAME) { for (vector::iterator h = this->hand_.begin(); h != this->hand_.end(); h++) (*h)->draw(true); } // if (::game_status & GAMESTATUS::GAME) return ; } // void Table::draw_all_hands() /** ** ** update all cards ** ** @param - ** ** @return - ** ** @version 0.6.1 ** ** @author Diether Knof ** **/ void Table::cards_update() { this->draw_all(); return ; } // void Table::cards_update() /** ** ** update all cards back ** ** @param - ** ** @return - ** ** @version 0.6.1 ** ** @author Diether Knof ** **/ void Table::cards_back_update() { this->draw_all_hands(); return ; } // void Table::cards_back_update() /** ** ** update all icons ** ** @param - ** ** @return - ** ** @version 0.6.1 ** ** @author Diether Knof ** **/ void Table::icons_update() { // update all, because the size of the icons can have changed this->draw_all(); return ; } // void Table::icons_update() /** ** ** update the full area ** (just copy the pixmap to the drawing_area) ** ** @param - ** ** @return - ** ** @version 0.5.4 ** ** @author Diether Knof ** **/ void Table::update_full_area() { this->update(Gdk::Rectangle(0, 0, -1, -1)); return ; } // void Table::update_full_area() /** ** ** update the area of the drawing area ** (just copy the area from the pixmap) ** ** @param area area to update ** ** @return - ** ** @version 0.6.2 ** ** @author Diether Knof ** **/ void Table::update(Gdk::Rectangle const& area) { this->get_window()->draw_drawable(this->gc, this->pixmap, area.get_x(), area.get_y(), area.get_x(), area.get_y(), area.get_width(), area.get_height()); return ; } // void Table::update(Gdk::Rectangle const& area); /** ** loads the background ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.7.4 **/ void Table::load_background() { try { Glib::RefPtr back_new = Gdk::Pixmap::create_from_xpm(this->pixmap, Gdk::Color(), ::setting.path(Setting::BACKGROUND)); if (!back_new) throw Glib::FileError(Glib::FileError::FAILED, "error loading pixmap from '" + ::setting.path(Setting::BACKGROUND) + "'"); this->gc->set_tile(back_new); this->draw_all(); } catch (Glib::FileError const& file_error) { this->ui->error(::translation("Error::loading the background %sbackground%", ::setting.value(Setting::BACKGROUND) ).translation()); } // try return ; } // void Table::load_background() /** ** ** the name of 'player' has changed ** ** @param player the player with the changed name ** ** @return - ** ** @version 0.6.1 ** ** @author Diether Knof ** **/ void Table::name_changed(Player const& player) { this->draw_all(); if (this->party_points_) this->party_points_->name_changed(player); this->gameinfo_->name_changed(player); if (this->last_trick_) this->last_trick_->name_changed(player); if (this->game_finished_) this->game_finished_->name_changed(player); if (this->party_finished_) this->party_finished_->name_changed(player); return ; } // void Table::name_changed(Player const& player) /** ** ** updates the font ** ** @param fontname the name of the new font ** @param type the type of the font ** ** @return - ** ** @version 0.6.1 ** ** @author Diether Knof ** **/ void Table::new_font(string const& fontname, Setting::TypeString const type) { switch (type) { case Setting::NAME_FONT: if (!this->name_layout) break; this->name_layout->set_font_description(Pango::FontDescription(fontname)); this->draw_all(); break; case Setting::TRICKPILE_POINTS_FONT: if (!this->trickpile_points_layout) break; this->trickpile_points_layout->set_font_description(Pango::FontDescription(fontname)); for (vector::iterator t = this->trickpile_.begin(); t != this->trickpile_.end(); t++) (*t)->draw(true); break; default: break; } // switch (type) return ; } // void Table::new_font(string const& fontname, Setting::TypeString const type) /** ** ** updates the ** ** @param colorname the name of the new color ** @param type the type of the font ** ** @return - ** ** @version 0.6.1 ** ** @author Diether Knof ** ** @todo using 'set_foreground' ** **/ void Table::new_color(string const& colorname, Setting::TypeString const type) { switch (type) { case Setting::NAME_FONT_COLOR: case Setting::NAME_ACTIVE_FONT_COLOR: case Setting::NAME_RESERVATION_FONT_COLOR: { Glib::RefPtr gc; switch (type) { case Setting::NAME_FONT_COLOR: gc = this->name_gc; break; case Setting::NAME_ACTIVE_FONT_COLOR: gc = this->name_active_gc; break; case Setting::NAME_RESERVATION_FONT_COLOR: gc = this->name_reservation_gc; break; default: break; } // switch (type) if (!gc) break; gc->set_rgb_fg_color(Gdk::Color(colorname)); for (vector::iterator n = this->name_.begin(); n != this->name_.end(); n++) (*n)->draw(); } break; case Setting::TRICKPILE_POINTS_FONT_COLOR: if (!this->trickpile_points_gc) break; this->trickpile_points_gc->set_rgb_fg_color(Gdk::Color(colorname)); #ifdef POSTPHONED this->trickpile_points_gc->set_foreground(Gdk::Color(colorname)); #endif for (vector::iterator t = this->trickpile_.begin(); t != this->trickpile_.end(); t++) (*t)->draw_points(true); break; case Setting::POVERTY_SHIFT_ARROW_COLOR: if (!this->poverty_shift_arrow_gc) break; this->poverty_shift_arrow_gc->set_rgb_fg_color(Gdk::Color(colorname)); if ((::game_status == GAMESTATUS::GAME_POVERTY_SHIFT) && this->poverty_) this->poverty().draw(); break; default: break; } // switch(type) return ; } // void Table::new_color(string const& colorname, Setting::TypeString const type) /** ** ** the setting has changed ** ** @param type the type that has changed ** ** @return - ** ** @version 0.6.1 ** ** @author Diether Knof ** **/ void Table::setting_update(int const type) { switch(type) { case Setting::SHOW_ALL_HANDS: this->draw_all_hands(); if ((::game_status == GAMESTATUS::GAME_POVERTY_SHIFT) && this->poverty_) this->poverty().draw(); break; case Setting::EMPHASIZE_VALID_CARDS: if ( (::game_status == GAMESTATUS::GAME_PLAY) && (this->ui->game().player_current().type() == Player::HUMAN) ) { this->draw_all(); this->mouse_cursor_update(); } break ; case Setting::AUTOMATIC_CARD_SUGGESTION: if (::setting(Setting::AUTOMATIC_CARD_SUGGESTION)) if ( (::game_status == GAMESTATUS::GAME_PLAY) && this->ui->party().rule()(Rule::CARD_HINT) && !this->ui->game().trick_current().isfull() && (this->ui->game().player_current().type() == Player::HUMAN)) this->show_card_suggestion(false); break; case Setting::SHOW_TRICKPILES_POINTS: for (vector::iterator t = this->trickpile_.begin(); t != this->trickpile_.end(); t++) (*t)->draw(); break; case Setting::ANNOUNCE_SWINES_AUTOMATICALLY: if (::game_status == GAMESTATUS::GAME_RESERVATION) { for (vector::iterator r = this->reservation_.begin(); r != this->reservation_.end(); ++r) (*r)->sensitivity_update(); } // if (::game_status == GAMESTATUS::GAME_RESERVATION) case Setting::BACKGROUND: this->load_background(); break; case Setting::ROTATE_TRICK_CARDS: #ifdef POSTPHONED // The old trick is not cleared fully this->trick_->draw(); #else this->draw_all(); #endif break; case Setting::NAME_FONT: case Setting::TRICKPILE_POINTS_FONT: this->new_font(::setting(static_cast(type)), static_cast(type)); break; case Setting::NAME_FONT_COLOR: case Setting::NAME_ACTIVE_FONT_COLOR: case Setting::TRICKPILE_POINTS_FONT_COLOR: case Setting::POVERTY_SHIFT_ARROW_COLOR: this->new_color(::setting(static_cast(type)), static_cast(type)); break; default: break; } // switch(type) return ; } // void Table::setting_update(int const type) /** ** update the mouse cursor ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.5 ** ** @todo close full trick / window ** @todo make announcement **/ void Table::mouse_cursor_update() { int x, y; this->get_pointer(x, y); CursorType new_cursor_type = DEFAULT; if (this->ui->busy()) new_cursor_type = BUSY; switch (::game_status) { case GAMESTATUS::GAME_POVERTY_SHIFT: DEBUG_ASSERTION(this->poverty_, "Table::mouse_cursor_update():\n" " 'this->poverty_' == NULL"); switch (this->poverty().possible_action(x, y)) { case Poverty::NONE: break; case Poverty::SHIFT_CARDS: new_cursor_type = POVERTY_SHIFT; break; case Poverty::ACCEPT_CARDS: new_cursor_type = POVERTY_ACCEPT; break; case Poverty::TAKE_CARD: if (this->poverty().cards[this->poverty().cardno_at_position(x, y)]) new_cursor_type = POVERTY_GET_CARD; break; case Poverty::PUT_CARD: if (this->poverty().cards[this->poverty().cardno_at_position(x, y)]) new_cursor_type = POVERTY_PUT_CARD; break; case Poverty::FILL_UP: new_cursor_type = POVERTY_FILL_UP; break; case Poverty::RETURN_CARDS: new_cursor_type = POVERTY_SHIFT_BACK; break; case Poverty::GET_CARDS_BACK: new_cursor_type = POVERTY_GETTING_BACK; break; } // switch (this->poverty().possible_action(x, y)) break; case GAMESTATUS::GAME_PLAY: { // the human player has to play a card Player& player = this->ui->game().player_current(); if (this->get_card()) { DEBUG_ASSERTION((player.type() == Player::HUMAN), "UI_GTKMM::Table::mouse_cursor_update():\n" " a card should be get, but the player '" << player.no() << "' is not human but '" << player.type() << "'"); Card const card = this->hand(player).card_at_position(x, y); if (card) { if (::setting(Setting::SHOW_IF_VALID) && player.game().rule()(Rule::SHOW_IF_VALID)) { if (player.game().trick_current().isvalid(card, player.hand())) new_cursor_type = CARD_VALID; else new_cursor_type = CARD_INVALID; } else { // if !(SHOW_IF_VALID) new_cursor_type = PLAY_CARD; } // if !(SHOW_IF_VALID) } // if (card) } // if (player.type() == Player::HUMAN) } break; default: if (this->full_trick_ && this->full_trick_->is_visible()) { new_cursor_type = CLOSE_FULL_TRICK; } // if (::game_status == ...) break; } // switch(::game_type) if (::in_running_game()) { Game const& game = this->ui->game(); for (vector::const_iterator p = game.players_begin(); p != game.players_end(); ++p) { if (this->trickpile(**p).over_trick(x, y)) new_cursor_type = SHOW_LAST_TRICK; if ((*p)->type() == Player::HUMAN) { if (this->icongroup(**p).mouse_over_next_announcement()) new_cursor_type = NEXT_ANNOUNCEMENT; } // if ((*p)->type() == Player::HUMAN) } // for (p \in game.player) } // if (::game_status in game) if (this->in_game_review()) new_cursor_type = GAME_REVIEW; if (this->cursor_type != new_cursor_type) { if ( (this->cursor_type == NEXT_ANNOUNCEMENT) || (new_cursor_type == NEXT_ANNOUNCEMENT) ) { this->cursor_type = new_cursor_type; this->draw_all(); } this->cursor_type = new_cursor_type; this->get_window()->set_cursor(Table::cursor(this->cursor_type)); } // if (this->cursor_type != new_cursor_type) return ; } // void Table::mouse_cursor_update() /** ** ** event: redraw part of the window ** ** @param event the event ** ** @return true ** ** @version 0.5.4 ** ** @author Diether Knof ** **/ bool Table::on_expose_event(GdkEventExpose* event) { this->update(Gdk::Rectangle(event->area.x, event->area.y, event->area.width, event->area.height)); return true; } // bool Table::on_expose_event(GdkEventExpose* event) /** ** ** event: the size has changed ** ** @param event the event ** ** @return true ** ** @version 0.5.4 ** ** @author Diether Knof ** **/ bool Table::on_configure_event(GdkEventConfigure* event) { this->pixmap = Gdk::Pixmap::create(this->get_window(), this->width(), this->height(), this->depth()); if (!this->gc) { this->gc = Gdk::GC::create(this->pixmap); this->gc->set_fill(Gdk::TILED); this->load_background(); this->poverty_shift_arrow_gc = Gdk::GC::create(this->pixmap); this->new_color(::setting(Setting::POVERTY_SHIFT_ARROW_COLOR), Setting::POVERTY_SHIFT_ARROW_COLOR); this->name_layout = this->create_pango_layout(""); this->new_font(::setting(Setting::NAME_FONT), Setting::NAME_FONT); this->name_gc = Gdk::GC::create(this->pixmap); this->new_color(::setting(Setting::NAME_FONT_COLOR), Setting::NAME_FONT_COLOR); this->name_active_gc = Gdk::GC::create(this->pixmap); this->new_color(::setting(Setting::NAME_ACTIVE_FONT_COLOR), Setting::NAME_ACTIVE_FONT_COLOR); this->name_reservation_gc = Gdk::GC::create(this->pixmap); this->new_color(::setting(Setting::NAME_RESERVATION_FONT_COLOR), Setting::NAME_RESERVATION_FONT_COLOR); this->trickpile_points_layout = this->create_pango_layout(""); this->new_font(::setting(Setting::TRICKPILE_POINTS_FONT), Setting::TRICKPILE_POINTS_FONT); this->trickpile_points_gc = Gdk::GC::create(this->pixmap); this->new_color(::setting(Setting::TRICKPILE_POINTS_FONT_COLOR), Setting::TRICKPILE_POINTS_FONT_COLOR); } // if (!this->gc) this->draw_all(); return true; } // bool Table::on_configure_event(GdkEventConfigure* event) /** ** event: mouse motion ** ** @param event the event ** ** @return whether there was a reaction ** ** @author Diether Knof ** ** @version 0.6.5 **/ bool Table::on_motion_notify_event(GdkEventMotion* event) { this->mouse_cursor_update(); return false; } // bool Table::on_motion_notify_event(GdkEventMotion* event) /** ** -> result ** ** @param type the cursor type ** ** @return the cursor for 'type' ** ** @author Diether Knof ** ** @version 0.6.5 **/ Gdk::Cursor const& Table::cursor(CursorType const type) { switch (type) { case NONE: DEBUG_ASSERTION(false, "Table::cursor(type):\n" " 'type' == NONE"); break; case DEFAULT: { static Gdk::Cursor const cursor(Gdk::X_CURSOR); return cursor; } break; case BUSY: { #ifdef POSTPHONED Glib::RefPtr pixbuf = Gdk::Pixbuf::create_from_file("ui/gtkmm/cursor/busy.png"); { GdkCursor* cursor = gdk_cursor_new_from_pixbuf(Gdk::Cursor(Gdk::X_CURSOR).get_display()->gobj(), pixbuf->gobj(), 0, 0); //Gdk::Cursor(Gdk::Pixbuf::create_from_file("ui/gtkmm/cursor/busy.png"),); return cursor; } #endif } { static Gdk::Cursor const cursor(Gdk::WATCH); return cursor; } //return Gdk::Cursor(Gdk::EXCHANGE); //return Gdk::Cursor(Gdk::CLOCK); case POVERTY_SHIFT: { static Gdk::Cursor const cursor(Gdk::SB_LEFT_ARROW); return cursor; } case POVERTY_SHIFT_BACK: { static Gdk::Cursor const cursor(Gdk::SB_RIGHT_ARROW); return cursor; } case POVERTY_GET_CARD: case POVERTY_PUT_CARD: case POVERTY_FILL_UP: { static Gdk::Cursor const cursor(Gdk::HAND1); return cursor; } case POVERTY_ACCEPT: case POVERTY_GETTING_BACK: { static Gdk::Cursor const cursor(Gdk::HAND2); return cursor; } case NEXT_ANNOUNCEMENT: { static Gdk::Cursor const cursor(Gdk::HAND2); return cursor; } case PLAY_CARD: { static Gdk::Cursor const cursor(Gdk::HAND1); return cursor; } case CARD_VALID: { static Gdk::Cursor const cursor(Gdk::HAND1); return cursor; } case CARD_INVALID: { static Gdk::Cursor const cursor(Gdk::PIRATE); return cursor; } case CLOSE_FULL_TRICK: { static Gdk::Cursor const cursor(Gdk::TOP_LEFT_ARROW); return cursor; } case SHOW_LAST_TRICK: { static Gdk::Cursor const cursor(Gdk::HAND2); return cursor; } case GAME_REVIEW: { static Gdk::Cursor const cursor(Gdk::SB_H_DOUBLE_ARROW); return cursor; } } // switch (type) { static Gdk::Cursor const cursor; return cursor; } } // static Gdk::Cursor const& Table::cursor(CursorType const type) } // namespace UI_GTKMM_NS #endif // #ifdef USE_UI_GTKMM