/********************************************************************** * * 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 "party_settings.h" #include "players.h" #include "rules.h" #include "ui.h" #include "translations.h" #include "main_window.h" #include "bug_report.h" #ifdef USE_NETWORK #include "network.h" #endif #include "first_run.h" #include "program_updated.h" #include "../../party/party.h" #include "../../player/player.h" #ifdef USE_NETWORK #include "../../network/server.h" #endif #include "widgets/stock_button.h" #include #include #include #include #include #include #include #include namespace UI_GTKMM_NS { /** ** constructor ** ** @param parent the parent object ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.6 **/ PartySettings::PartySettings(Base* const parent) : Base(parent), StickyDialog("PartySettings", *(parent->ui->main_window), false), players(NULL), rules(NULL), load_bug_report_button(NULL), start_party_button(NULL), close_button(NULL), seed_value(NULL), seed_random(NULL), startplayer(), startplayer_random(), switch_players_buttons(), configure_players(), configure_rules() #ifdef USE_NETWORK ,configure_network() #endif { this->ui->add_window(*this); this->init(); #if 0 this->signal_realize().connect(sigc::mem_fun(*this, &PartySettings::language_update)); #endif this->signal_show().connect(sigc::mem_fun(*this, &PartySettings::update)); this->signal_key_press_event().connect(sigc::mem_fun(*this, &PartySettings::key_press)); this->ui->bug_report->set_dnd_destination(*this); return ; } // PartySettings::PartySettings(Base* const parent) /** ** Destruktor ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.5.4 **/ PartySettings::~PartySettings() { delete this->players; delete this->rules; return ; } // PartySettings::~PartySettings() /** ** create all subelements ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.6 **/ void PartySettings::init() { #ifdef POSTPHONED Party& party = this->ui->party(); #else Party& party = ::party; #endif this->set_icon(this->ui->icon); this->ui->translations->add(*this, ::translation("~party settings")); this->set_position(Gtk::WIN_POS_CENTER_ON_PARENT); this->players = new Players(this); this->rules = new Rules(this); this->load_bug_report_button = Gtk::manage(new Gtk::StockButton(Gtk::Stock::OPEN, "load bug report")); this->ui->translations->add(*(this->load_bug_report_button->label), ::translation("load bug report")); #ifndef RELEASE this->add_action_widget(*(this->load_bug_report_button), Gtk::RESPONSE_NONE); #endif this->start_party_button = Gtk::manage(new Gtk::StockButton(Gtk::Stock::OK, "start party")); this->ui->translations->add(*this->start_party_button->label, ::translation("start party")); this->add_action_widget(*this->start_party_button, Gtk::RESPONSE_CLOSE); this->close_button = Gtk::manage(new Gtk::StockButton(Gtk::Stock::CLOSE, "close")); this->ui->translations->add(*(this->close_button->label), ::translation("close")); this->add_action_widget(*(this->close_button), Gtk::RESPONSE_CLOSE); // the elements in the tab 'general' this->seed_value = Gtk::manage(new Gtk::SpinButton(1, 0)); this->seed_value->set_value(0); this->seed_random = Gtk::manage(new Gtk::CheckButton("random")); this->ui->translations->add(*(static_cast(this->seed_random->get_child())), ::translation("random")); this->startplayer_random = Gtk::manage(new Gtk::RadioButton("random")); this->ui->translations->add(*(static_cast(this->startplayer_random->get_child())), ::translation("random")); this->configure_players = Gtk::manage(new Gtk::StockButton("configure players")); this->ui->translations->add(*(this->configure_players), ::translation("players")); this->configure_rules = Gtk::manage(new Gtk::StockButton(Gtk::Stock::PROPERTIES, "configure rules")); this->ui->translations->add(*(this->configure_rules), ::translation("rules")); #ifdef USE_NETWORK #if GTKMM_VERSION_GE(2,8) this->configure_network = Gtk::manage(new Gtk::StockButton(Gtk::Stock::NETWORK, "configure network")); #else this->configure_network = Gtk::manage(new Gtk::StockButton("configure network")); #endif this->ui->translations->add(*(this->configure_network), ::translation("network")); #endif this->seed_value->set_range(0, PSEUDO_RAND_MAX); this->seed_value->set_increments(1, 1000); { // create the startplayer buttons Gtk::RadioButton::Group startplayer_group = this->startplayer_random->get_group(); for (unsigned p = 0; p < party.playerno(); p++) this->startplayer.push_back(Gtk::manage(new Gtk::RadioButton(startplayer_group, party.player(p).name())) ); #ifdef OUTDATED // MS-Windows does not show the arrows this->switch_players_buttons.push_back(Gtk::manage(new Gtk::Button(Glib::ustring(1, static_cast(0x2196))))); // up left this->switch_players_buttons.push_back(Gtk::manage(new Gtk::Button(Glib::ustring(1, static_cast(0x2197))))); // up right this->switch_players_buttons.push_back(Gtk::manage(new Gtk::Button(Glib::ustring(1, static_cast(0x2199))))); // down right this->switch_players_buttons.push_back(Gtk::manage(new Gtk::Button(Glib::ustring(1, static_cast(0x2198))))); // down left #endif { // the switch buttons #include "arrows/arrow_lu.xpm" #include "arrows/arrow_ur.xpm" #include "arrows/arrow_rd.xpm" #include "arrows/arrow_dl.xpm" this->switch_players_buttons.push_back(Gtk::manage(new Gtk::Button())); this->switch_players_buttons.back()->add(*Gtk::manage(new Gtk::Image(Gdk::Pixbuf::create_from_xpm_data(arrow_lu_xpm)))); this->switch_players_buttons.push_back(Gtk::manage(new Gtk::Button())); this->switch_players_buttons.back()->add(*Gtk::manage(new Gtk::Image(Gdk::Pixbuf::create_from_xpm_data(arrow_ur_xpm)))); this->switch_players_buttons.push_back(Gtk::manage(new Gtk::Button())); this->switch_players_buttons.back()->add(*Gtk::manage(new Gtk::Image(Gdk::Pixbuf::create_from_xpm_data(arrow_rd_xpm)))); this->switch_players_buttons.push_back(Gtk::manage(new Gtk::Button())); this->switch_players_buttons.back()->add(*Gtk::manage(new Gtk::Image(Gdk::Pixbuf::create_from_xpm_data(arrow_dl_xpm)))); for (vector::iterator b = this->switch_players_buttons.begin(); b != this->switch_players_buttons.end(); ++b) (*b)->set_relief(Gtk::RELIEF_NONE); } // the switch buttons } // create the startplayer buttons { // Layout Gtk::HBox* hbox = Gtk::manage(new Gtk::HBox(false, 1 em)); hbox->set_border_width(1 em); this->get_vbox()->add(*hbox); { // actions { // configure Gtk::Alignment* alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, 1, 0)); hbox->pack_end(*alignment, false, true); Gtk::VBox* vbox = Gtk::manage(new Gtk::VBox(true, 1 ex)); alignment->add(*vbox); vbox->add(*this->configure_rules); vbox->add(*this->configure_players); #ifdef USE_NETWORK { vbox->add(*Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, 1, 0))); } vbox->add(*(this->configure_network)); #endif } // configure } // actions { // settings Gtk::Alignment* alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, 0, 0)); hbox->pack_start(*alignment, true, true); Gtk::VBox* vbox = Gtk::manage(new Gtk::VBox(true, 1 ex)); alignment->add(*vbox); { // seed Gtk::Frame* seed_frame = Gtk::manage(new Gtk::Frame("Game seed")); this->ui->translations->add(*(dynamic_cast(seed_frame->get_label_widget())), ::translation("game seed")); vbox->add(*seed_frame); Gtk::VBox* vbox2 = Gtk::manage(new Gtk::VBox(false, 10)); seed_frame->add(*vbox2); vbox2->set_border_width(2 ex); Gtk::Alignment* alignment2 = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, 0, 0)); vbox2->add(*alignment2); alignment2->add(*this->seed_value); alignment2 = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, 0, 0)); vbox2->add(*alignment2); alignment2->add(*this->seed_random); } // seed { // startplayer Gtk::Frame* startplayer_frame = Gtk::manage(new Gtk::Frame("~startplayer")); this->ui->translations->add(*(dynamic_cast(startplayer_frame->get_label_widget())), ::translation("startplayer")); vbox->add(*startplayer_frame); Gtk::Table* startplayer_table = Gtk::manage(new Gtk::Table(3, 3, true)); startplayer_frame->add(*startplayer_table); startplayer_table->set_border_width(2 ex); startplayer_table->set_spacings(10); startplayer_table->attach(*this->startplayer_random, 1, 2, 1, 2); startplayer_table->attach(*this->startplayer[0], 1, 2, 2, 3); startplayer_table->attach(*this->startplayer[1], 0, 1, 1, 2); startplayer_table->attach(*this->startplayer[2], 1, 2, 0, 1); startplayer_table->attach(*this->startplayer[3], 2, 3, 1, 2); startplayer_table->attach(*this->switch_players_buttons[0], 0, 1, 2, 3); startplayer_table->attach(*this->switch_players_buttons[1], 0, 1, 0, 1); startplayer_table->attach(*this->switch_players_buttons[2], 2, 3, 0, 1); startplayer_table->attach(*this->switch_players_buttons[3], 2, 3, 2, 3); } // startplayer } // settings } // Layout { // signals this->load_bug_report_button->signal_clicked().connect(sigc::mem_fun(*this, &PartySettings::load_bug_report) ); this->start_party_button->signal_clicked().connect(sigc::mem_fun(*this, &PartySettings::start_party_event) ); this->close_button->signal_clicked().connect(sigc::mem_fun(*this, &Gtk::Widget::hide) ); this->seed_value->signal_value_changed().connect(sigc::mem_fun(*this, &PartySettings::seed_change_event)); this->seed_random->signal_toggled().connect(sigc::mem_fun(*this, &PartySettings::seed_change_event)); this->seed_random->signal_toggled().connect(sigc::mem_fun(*this, &PartySettings::seed_value_sensitivity_update) ); this->startplayer_random->signal_toggled().connect(sigc::mem_fun(*this, &PartySettings::startplayer_change_event)); for (vector::iterator p = this->startplayer.begin(); p != this->startplayer.end(); ++p) (*p)->signal_toggled().connect(sigc::mem_fun(*this, &PartySettings::startplayer_change_event)); for (unsigned p = 0; p < this->switch_players_buttons.size(); ++p) this->switch_players_buttons[p]->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &PartySettings::switch_players_event), p)); this->signal_hide().connect(sigc::mem_fun(*(this->ui->bug_report->load_file_selector), &Gtk::Widget::hide)); this->configure_players->signal_clicked().connect(sigc::mem_fun0(*this->players, &Gtk::Window::present) ); this->configure_rules->signal_clicked().connect(sigc::mem_fun0(*this->rules, &Gtk::Window::present) ); #ifdef USE_NETWORK this->configure_network->signal_clicked().connect(sigc::mem_fun0(*this->ui->network, &Gtk::Window::present) ); #endif } // signals this->show_all_children(); this->update(); return ; } // void PartySettings::init() /** ** get the party settings ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.0 **/ void PartySettings::get() { Party& party = this->ui->party(); this->update(); this->players->create_backup(); this->rules->create_backup(); this->start_party_button->show(); this->start_party_button->grab_default(); this->start_party_button->grab_focus(); this->present(); while ( !this->ui->thrower && this->is_visible() && (::game_status == GAMESTATUS::PARTY_NEW)) ::ui->wait(); if (::game_status == GAMESTATUS::PARTY_NEW) { #ifdef NETWORK if (!::server->has_parent_connection()) { #endif // set the seed if (this->seed_random->get_active()) party.set_random_seed(); else party.set_seed(this->seed_value->get_value_as_int()); // set the startplayer if (this->startplayer_random->get_active()) party.set_random_startplayer(); else for (unsigned p = 0; p < party.playerno(); ++p) if (this->startplayer[p]->get_active()) { party.set_startplayer(p); break; } this->players->create_backup(); this->rules->create_backup(); #ifdef NETWORK } #endif } // if (::game_status == GAMESTATUS::PARTY_NEW) this->hide(); return ; } // void PartySettings::get() /** ** show the window. ** Shows/hides the action buttons ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.7.0 **/ void PartySettings::on_show() { this->Dialog::on_show(); if (this->ui->first_run_window) this->ui->first_run_window->raise(); if (this->ui->program_updated_window) this->ui->program_updated_window->raise(); this->update(); return ; } // void PartySettings::show() /** ** load the bug report ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.5.4 **/ void PartySettings::load_bug_report() { this->ui->bug_report->load_file_selector->present(); return ; } // void PartySettings::load_bug_report() /** ** update the sensitivity of all elements ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.7.2 **/ void PartySettings::sensitivity_update() { bool sensitive = (::game_status == GAMESTATUS::PARTY_NEW); #ifdef USE_NETWORK if ( ::server && ::server->has_parent_connection()) sensitive = false; #endif if (sensitive) this->seed_value_sensitivity_update(); else this->seed_value->set_sensitive(false); this->seed_random->set_sensitive(sensitive); for (vector::iterator p = this->startplayer.begin(); p != this->startplayer.end(); p++) (*p)->set_sensitive(sensitive); this->startplayer_random->set_sensitive(sensitive); for (vector::iterator p = this->switch_players_buttons.begin(); p != this->switch_players_buttons.end(); p++) (*p)->set_sensitive(sensitive); this->players->sensitivity_update(); this->rules->sensitivity_update(); this->load_bug_report_button->set_sensitive(sensitive); this->start_party_button->set_sensitive(sensitive); return ; } // void PartySettings::sensitivity_update() /** ** update the sensitivity of 'seed_value' ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.0 **/ void PartySettings::seed_value_sensitivity_update() { switch (::game_status) { case GAMESTATUS::PARTY_NEW: case GAMESTATUS::PARTY_INITIAL_LOADED: this->seed_value->set_sensitive(!(this->seed_random->get_active())); break; default: this->seed_value->set_sensitive(false); break; } // switch (::game_status); return ; } // void PartySettings::seed_value_sensitivity_update() /** ** update the widgets ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.5.4 **/ void PartySettings::update() { if (!this->is_visible()) return ; Party& party = this->ui->party(); this->sensitivity_update(); switch (::game_status) { case GAMESTATUS::PARTY_NEW: #ifndef RELEASE this->load_bug_report_button->show(); #endif this->start_party_button->show(); this->close_button->hide(); this->start_party_button->grab_default(); break; default: this->load_bug_report_button->hide(); this->start_party_button->hide(); this->close_button->show(); this->close_button->grab_default(); break; } // switch (::game_status) bool const random_seed = (party.seed() == UINT_MAX); if (!random_seed) this->seed_value->set_value(party.seed()); this->seed_random->set_active(random_seed); if (party.startplayer() == UINT_MAX) this->startplayer_random->set_active(true); else this->startplayer[party.startplayer()]->set_active(true); for (unsigned p = 0; p < party.playerno(); ++p) this->name_update(party.player(p)); this->players->update(); this->rules->update_all(); return ; } // void PartySettings::update() /** ** the players 'player_a' and 'player_b' have been switched ** ** @param player_a first player ** @param player_b second player ** ** @return - ** ** @author Diether Knof ** ** @version 0.7.2 **/ void PartySettings::players_switched(Player const& player_a, Player const& player_b) { this->name_update_local(player_a); this->name_update_local(player_b); this->players->players_switched(player_a, player_b); return ; } // void PartySettings::players_switched(Player player_a, Player player_b) /** ** update 'player' ** ** @param player player to update ** ** @return - ** ** @author Diether Knof ** ** @version 0.7.4 **/ void PartySettings::player_update(Player const& player) { this->name_update_local(player); this->players->player_update(player); return ; } // void PartySettings::player_update(Player player) /** ** update the name of 'player' ** ** @param player player with the new name ** ** @return - ** ** @author Diether Knof ** ** @version 0.5.4 **/ void PartySettings::name_update(Player const& player) { this->name_update_local(player); this->players->name_update(player); return ; } // void PartySettings::name_update(Player const& player) /** ** update the name of 'player' ** ** @param player player with the new name ** ** @return - ** ** @author Diether Knof ** ** @version 0.5.4 **/ void PartySettings::name_update_local(Player const& player) { #ifdef USE_NETWORK if (player.type() == Player::NETWORK) this->startplayer[player.no()]->set_label(player.name() + " *"); else this->startplayer[player.no()]->set_label(player.name()); #else this->startplayer[player.no()]->set_label(player.name()); #endif return ; } // void PartySettings::name_update_local(Player const& player) /** ** a new party is started ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.9 **/ void PartySettings::start_party_event() { this->hide(); ::game_status = GAMESTATUS::PARTY_NEW; return ; } // void PartySettings::start_party_event() /** ** the seed has changed ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.7.2 **/ void PartySettings::seed_change_event() { // set the seed if (this->seed_random->get_active()) this->ui->party().set_random_seed(); else this->ui->party().set_seed(this->seed_value->get_value_as_int()); return ; } // void PartySettings::seed_change_event() /** ** the startplayer has changed ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.7.2 **/ void PartySettings::startplayer_change_event() { // set the startplayer if (this->startplayer_random->get_active()) this->ui->party().set_random_startplayer(); else for (unsigned p = 0; p < this->ui->party().playerno(); ++p) if (this->startplayer[p]->get_active()) { this->ui->party().set_startplayer(p); break; } return ; } // void PartySettings::startplayer_change_event() /** ** players shall be switched ** ** @param p player to switch with the following ** ** @return - ** ** @author Diether Knof ** ** @version 0.7.2 ** ** @bug const cast **/ void PartySettings::switch_players_event(unsigned const p) { Party& party = const_cast(this->ui->party()); party.switch_players(p, (p + 1) % party.playerno()); return ; } // void PartySettings::switch_players_event(unsigned p) /** ** a key has been pressed ** ** @param key the key ** ** @return whether the key was used ** ** @author Diether Knof ** ** @version 0.6.6 **/ bool PartySettings::key_press(GdkEventKey* key) { bool used = false; if ((key->state & ~GDK_SHIFT_MASK) == 0) { switch (key->keyval) { case GDK_p: // show the players this->players->present(); used = true; break; case GDK_r: // show the rules this->rules->present(); used = true; break; } // switch (key->keyval) } // if ((key->state & ~GDK_SHIFT_MASK) == 0) return (used || this->ui->key_press(key)); } // bool PartySettings::key_press(GdkEventKey* key) } // namespace UI_GTKMM_NS #endif // #ifdef USE_UI_GTKMM