00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef USE_PCH
00025 #include "sys.h"
00026 #include <gtkmm/radioaction.h>
00027 #include <gtkmm/stock.h>
00028 #endif
00029
00030 #include "ChessPositionWidget.h"
00031 #include "CwChessboardCodes.h"
00032
00033 using namespace cwchess;
00034
00035 namespace cwmm {
00036
00037 bool ChessPositionWidget::execute(Move const& move)
00038 {
00039 Code code(piece_at(move.from()).code());
00040 if (code.is_a(pawn))
00041 {
00042 EnPassant const& en_passant(this->en_passant());
00043 if (en_passant.exists() && en_passant.index() == move.to())
00044 set_square(en_passant.pawn_index().col(), en_passant.pawn_index().row(), empty_square);
00045 }
00046 bool result = ChessPosition::execute(move);
00047 set_square(move.from().col(), move.from().row(), empty_square);
00048 if (move.is_promotion())
00049 code = move.promotion_type();
00050 set_square(move.to().col(), move.to().row(), code);
00051 uint8_t col_diff = move.to().col() - move.from().col();
00052 if (code.is_a(king) && col_diff && !(col_diff & 1))
00053 {
00054 IndexData rook_from_data = { move.from()() - 4 + 7 * (2 + move.to()() - move.from()()) / 4 };
00055 IndexData rook_to_data = { move.from()() + (move.to()() - move.from()()) / 2 };
00056 Index rook_from(rook_from_data);
00057 Index rook_to(rook_to_data);
00058 set_square(rook_from.col(), rook_from.row(), empty_square);
00059 set_square(rook_to.col(), rook_to.row(), (code.color() == white) ? ::white_rook : ::black_rook);
00060 }
00061 set_active_turn_indicator(to_move().is_white());
00062 }
00063
00064 void ChessPositionWidget::sync(void)
00065 {
00066
00067 for (Index index = index_begin; index != index_end; ++index)
00068 set_square(index.col(), index.row(), empty_square);
00069
00070
00071 for (Index index = index_begin; index != index_end; ++index)
00072 set_square(index.col(), index.row(), piece_at(index).code());
00073
00074
00075 set_active_turn_indicator(to_move().is_white());
00076 }
00077
00078 bool ChessPositionWidget::load_FEN(std::string const& FEN)
00079 {
00080 cwchess::ChessPosition tmp(*static_cast<ChessPosition*>(this));
00081 bool result = tmp.load_FEN(FEN);
00082 if (result)
00083 set_position(tmp);
00084 return result;
00085 }
00086
00087 bool ChessPositionWidget::popup_menu(GdkEventButton* event, int col, int row)
00088 {
00089 DoutEntering(dc::notice|dc::clipboard, "ChessPositionWidget::popup_menu(" << col << ", " << row << ")");
00090 M_placepiece_index = cwchess::Index(col, row);
00091 if (M_MenuPopup)
00092 {
00093 M_refActionGroup->get_action("PlacepieceBlackPawn")->set_sensitive(row != 0 && row != 7);
00094 M_refActionGroup->get_action("PlacepieceWhitePawn")->set_sensitive(row != 0 && row != 7);
00095 M_refActionGroup->get_action("PlacepieceBlackKing")->set_sensitive(!all(cwchess::black_king).test());
00096 M_refActionGroup->get_action("PlacepieceWhiteKing")->set_sensitive(!all(cwchess::white_king).test());
00097 if (to_move().is_white())
00098 M_refToMoveWhite_action->set_active(true);
00099 else
00100 M_refToMoveBlack_action->set_active(true);
00101 Piece const& piece(piece_at(M_placepiece_index));
00102 M_refActionGroup->get_action("PlacepieceNothing")->set_visible(piece != nothing);
00103 bool can_be_taken_en_passant =
00104 (piece == cwchess::white_pawn && M_placepiece_index.row() == 3&&
00105 piece_at(M_placepiece_index + south.offset) == nothing&&
00106 piece_at(M_placepiece_index + 2 * south.offset) == nothing) ||
00107 (piece == cwchess::black_pawn && M_placepiece_index.row() == 4&&
00108 piece_at(M_placepiece_index + north.offset) == nothing&&
00109 piece_at(M_placepiece_index + 2 * north.offset) == nothing);
00110 M_refActionGroup->get_action("AllowEnPassantCapture")->set_visible(can_be_taken_en_passant);
00111 if (can_be_taken_en_passant)
00112 {
00113 M_AllowEnPassantCapture_connection.block();
00114 M_refAllowEnPassantCapture_action->set_active(en_passant().exists() && en_passant().pawn_index() == M_placepiece_index);
00115 M_AllowEnPassantCapture_connection.unblock();
00116 }
00117 bool is_castle_piece =
00118 (piece == cwchess::white_king && M_placepiece_index == ie1) ||
00119 (piece == cwchess::black_king && M_placepiece_index == ie8) ||
00120 (piece == cwchess::white_rook && (M_placepiece_index == ia1 || M_placepiece_index == ih1)) ||
00121 (piece == cwchess::black_rook && (M_placepiece_index == ia8 || M_placepiece_index == ih8));
00122 M_refActionGroup->get_action("PieceHasMoved")->set_visible(is_castle_piece);
00123 if (is_castle_piece)
00124 {
00125 M_PieceHasMoved_connection.block();
00126 M_refPieceHasMoved_action->set_active(has_moved(M_placepiece_index));
00127 M_PieceHasMoved_connection.unblock();
00128 }
00129 update_paste_status();
00130 M_MenuPopup->popup(event->button, event->time);
00131 return true;
00132 }
00133 return false;
00134 }
00135
00136 void ChessPositionWidget::on_menu_placepiece_black_pawn(void)
00137 {
00138 place(cwchess::black_pawn, M_placepiece_index);
00139 }
00140
00141 void ChessPositionWidget::on_menu_placepiece_black_rook(void)
00142 {
00143 place(cwchess::black_rook, M_placepiece_index);
00144 }
00145
00146 void ChessPositionWidget::on_menu_placepiece_black_knight(void)
00147 {
00148 place(cwchess::black_knight, M_placepiece_index);
00149 }
00150
00151 void ChessPositionWidget::on_menu_placepiece_black_bishop(void)
00152 {
00153 place(cwchess::black_bishop, M_placepiece_index);
00154 }
00155
00156 void ChessPositionWidget::on_menu_placepiece_black_queen(void)
00157 {
00158 place(cwchess::black_queen, M_placepiece_index);
00159 }
00160
00161 void ChessPositionWidget::on_menu_placepiece_black_king(void)
00162 {
00163 place(cwchess::black_king, M_placepiece_index);
00164 }
00165
00166 void ChessPositionWidget::on_menu_placepiece_white_pawn(void)
00167 {
00168 place(cwchess::white_pawn, M_placepiece_index);
00169 }
00170
00171 void ChessPositionWidget::on_menu_placepiece_white_rook(void)
00172 {
00173 place(cwchess::white_rook, M_placepiece_index);
00174 }
00175
00176 void ChessPositionWidget::on_menu_placepiece_white_knight(void)
00177 {
00178 place(cwchess::white_knight, M_placepiece_index);
00179 }
00180
00181 void ChessPositionWidget::on_menu_placepiece_white_bishop(void)
00182 {
00183 place(cwchess::white_bishop, M_placepiece_index);
00184 }
00185
00186 void ChessPositionWidget::on_menu_placepiece_white_queen(void)
00187 {
00188 place(cwchess::white_queen, M_placepiece_index);
00189 }
00190
00191 void ChessPositionWidget::on_menu_placepiece_white_king(void)
00192 {
00193 place(cwchess::white_king, M_placepiece_index);
00194 }
00195
00196 void ChessPositionWidget::on_menu_placepiece_nothing(void)
00197 {
00198 place(cwchess::Code(), M_placepiece_index);
00199 }
00200
00201 void ChessPositionWidget::on_menu_allow_en_passant_capture(void)
00202 {
00203 bool en_passant_allowed = en_passant().exists() && en_passant().pawn_index() == M_placepiece_index;
00204 reset_en_passant();
00205 if (!en_passant_allowed)
00206 {
00207 Index passed_square(M_placepiece_index);
00208 if (piece_at(M_placepiece_index) == black)
00209 passed_square += north.offset;
00210 else
00211 passed_square += south.offset;
00212 set_en_passant(passed_square);
00213 }
00214 }
00215
00216 void ChessPositionWidget::on_menu_piece_has_moved(void)
00217 {
00218 if (has_moved(M_placepiece_index))
00219 clear_has_moved(M_placepiece_index);
00220 else
00221 set_has_moved(M_placepiece_index);
00222 }
00223
00224 void ChessPositionWidget::on_menu_copy_FEN(void)
00225 {
00226 DoutEntering(dc::clipboard, "ChessPositionWidget::on_menu_copy_FEN");
00227 Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
00228 std::list<Gtk::TargetEntry> targets;
00229 targets.push_back(Gtk::TargetEntry("UTF8_STRING"));
00230 Glib::ustring clipboard_store = FEN();
00231
00232 M_clipboard_content = clipboard_store;
00233
00234 if (!refClipboard->set(targets,
00235 sigc::mem_fun(*this,& ChessPositionWidget::on_clipboard_get),
00236 sigc::mem_fun(*this,& ChessPositionWidget::on_clipboard_clear)))
00237 g_warning("ChessPositionWidget::on_menu_copy_FEN(): setting the clipboard data failed.");
00238
00239 M_clipboard_content = clipboard_store;
00240 Dout(dc::clipboard, "Storing \"" << M_clipboard_content << "\".");
00241 }
00242
00243 void ChessPositionWidget::on_menu_paste_FEN(void)
00244 {
00245 DoutEntering(dc::clipboard, "ChessPositionWidget::on_menu_paste_FEN");
00246 Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
00247 refClipboard->request_text(sigc::mem_fun(*this,& ChessPositionWidget::on_clipboard_received));
00248 }
00249
00250 void ChessPositionWidget::on_clipboard_get(Gtk::SelectionData& selection_data, guint)
00251 {
00252 std::string const target = selection_data.get_target();
00253
00254 DoutEntering(dc::clipboard, "ChessPositionWidget::on_clipboard_get(...) with target data \"" << target << "\".");
00255
00256 if (target == "UTF8_STRING")
00257 {
00258 Dout(dc::clipboard, "Passing back \"" << M_clipboard_content << "\".");
00259 selection_data.set_text(M_clipboard_content);
00260 }
00261 else
00262 g_warning("ChessPositionWidget::on_clipboard_get(): Unexpected clipboard target format.");
00263 }
00264
00265 void ChessPositionWidget::on_clipboard_clear(void)
00266 {
00267 DoutEntering(dc::clipboard, "ChessPositionWidget::on_clipboard_clear()");
00268 M_clipboard_content.clear();
00269 }
00270
00271 void ChessPositionWidget::on_clipboard_received(Glib::ustring const& text)
00272 {
00273 DoutEntering(dc::clipboard, "ChessPositionWidget::on_clipboard_received(\"" << text << "\").");
00274
00275 if (!load_FEN(text) && !M_trying_primary)
00276 {
00277 Dout(dc::clipboard, "No FEN in CLIPBOARD. Trying PRIMARY.");
00278 Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get(GDK_SELECTION_PRIMARY);
00279 M_trying_primary = true;
00280 refClipboard->request_text(sigc::mem_fun(*this,& ChessPositionWidget::on_clipboard_received));
00281 }
00282 else
00283 M_trying_primary = false;
00284 }
00285
00286 void ChessPositionWidget::update_paste_status(void)
00287 {
00288 DoutEntering(dc::clipboard, "ChessPositionWidget::update_paste_status()");
00289 M_refActionGroup->get_action("PasteFEN")->set_sensitive(false);
00290 Dout(dc::clipboard, "paste disabled.");
00291 Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get();
00292 refClipboard->request_targets(sigc::mem_fun(*this,& ChessPositionWidget::on_clipboard_received_targets));
00293 }
00294
00295 void ChessPositionWidget::on_clipboard_received_targets(Glib::StringArrayHandle const& targets_array)
00296 {
00297 DoutEntering(dc::clipboard, "ChessPositionWidget::on_clipboard_received_targets(...).");
00298
00299 typedef std::list<Glib::ustring> targets_type;
00300 targets_type targets = targets_array;
00301 if (std::find(targets.begin(), targets.end(), "UTF8_STRING") != targets.end())
00302 {
00303 Dout(dc::clipboard, "Target found; paste enabled.");
00304 M_refActionGroup->get_action("PasteFEN")->set_sensitive(true);
00305 }
00306 }
00307
00308 void ChessPositionWidget::on_menu_swap_colors(void)
00309 {
00310 swap_colors();
00311 }
00312
00313 void ChessPositionWidget::on_menu_initial_position(void)
00314 {
00315 initial_position();
00316 }
00317
00318 void ChessPositionWidget::on_menu_clear_board(void)
00319 {
00320 clear();
00321 }
00322
00323 void ChessPositionWidget::on_menu_to_move_white(void)
00324 {
00325 to_move(white);
00326 }
00327
00328 void ChessPositionWidget::on_menu_to_move_black(void)
00329 {
00330 to_move(black);
00331 }
00332
00333 void ChessPositionWidget::initialize_menus(void)
00334 {
00335 DoutEntering(dc::notice, "ChessPositionWidget::initialize_menus");
00336
00337 M_refIconFactory = Gtk::IconFactory::create();
00338 M_refIconFactory->add_default();
00339
00340 GdkColor light_square_color;
00341 get_light_square_color(light_square_color);
00342
00343 int color_count = 0;
00344 for (bool iswhite = false; color_count < 2; ++color_count, iswhite = true)
00345 {
00346 using namespace cwchess;
00347 Type type(nothing);
00348 do
00349 {
00350 Glib::RefPtr<Gdk::Pixmap> icon_pixmap = Gdk::Pixmap::create(M_drawable->get_window(), 16, 16);
00351 Cairo::RefPtr<Cairo::Context> cairo_context = icon_pixmap->create_cairo_context();
00352 cairo_t* cr = cairo_context->cobj();
00353 cairo_set_source_rgb(cr, light_square_color.red / 65535.0, light_square_color.green / 65535.0, light_square_color.blue / 65535.0);
00354 cairo_paint(cr);
00355 std::string icon_str(iswhite ? "white_" : "black_");
00356 switch (type())
00357 {
00358 case nothing_bits:
00359 icon_str += "nothing";
00360 break;
00361 case pawn_bits:
00362 draw_pawn(cr, 8, 8, 16, iswhite);
00363 icon_str += "pawn";
00364 break;
00365 case rook_bits:
00366 draw_rook(cr, 8, 8, 16, iswhite);
00367 icon_str += "rook";
00368 break;
00369 case knight_bits:
00370 draw_knight(cr, 8, 8, 16, iswhite);
00371 icon_str += "knight";
00372 break;
00373 case bishop_bits:
00374 draw_bishop(cr, 8, 8, 16, iswhite);
00375 icon_str += "bishop";
00376 break;
00377 case queen_bits:
00378 draw_queen(cr, 8, 8, 16, iswhite);
00379 icon_str += "queen";
00380 break;
00381 case king_bits:
00382 draw_king(cr, 8, 8, 16, iswhite);
00383 icon_str += "king";
00384 break;
00385 }
00386 icon_str += "_icon";
00387 Glib::RefPtr<Gdk::Pixbuf> icon_pixbuf = Gdk::Pixbuf::create(Glib::RefPtr<Gdk::Drawable>::cast_static(icon_pixmap), 0, 0, 16, 16);
00388 M_refIconFactory->add(Gtk::StockID(icon_str.c_str()), Gtk::IconSet(icon_pixbuf));
00389
00390 do { TypeData type_data = { type() + 1 }; type = type_data; } while (type() == 4);
00391 }
00392 while (type() != 8);
00393 }
00394
00395 M_refActionGroup = Gtk::ActionGroup::create();
00396 M_refActionGroup->add(Gtk::Action::create("PlacepieceMenu", "Placepiece Menu"));
00397 M_refActionGroup->add(Gtk::Action::create("PlacepieceBlackPawn", Gtk::StockID("black_pawn_icon"), "Black Pawn"),
00398 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_black_pawn));
00399 M_refActionGroup->add(Gtk::Action::create("PlacepieceBlackRook", Gtk::StockID("black_rook_icon"), "Black Rook"),
00400 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_black_rook));
00401 M_refActionGroup->add(Gtk::Action::create("PlacepieceBlackKnight", Gtk::StockID("black_knight_icon"), "Black Knight"),
00402 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_black_knight));
00403 M_refActionGroup->add(Gtk::Action::create("PlacepieceBlackBishop", Gtk::StockID("black_bishop_icon"), "Black Bishop"),
00404 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_black_bishop));
00405 M_refActionGroup->add(Gtk::Action::create("PlacepieceBlackQueen", Gtk::StockID("black_queen_icon"), "Black Queen"),
00406 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_black_queen));
00407 M_refActionGroup->add(Gtk::Action::create("PlacepieceBlackKing", Gtk::StockID("black_king_icon"), "Black King"),
00408 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_black_king));
00409 M_refActionGroup->add(Gtk::Action::create("PlacepieceWhitePawn", Gtk::StockID("white_pawn_icon"), "White Pawn"),
00410 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_white_pawn));
00411 M_refActionGroup->add(Gtk::Action::create("PlacepieceWhiteRook", Gtk::StockID("white_rook_icon"), "White Rook"),
00412 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_white_rook));
00413 M_refActionGroup->add(Gtk::Action::create("PlacepieceWhiteKnight", Gtk::StockID("white_knight_icon"), "White Knight"),
00414 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_white_knight));
00415 M_refActionGroup->add(Gtk::Action::create("PlacepieceWhiteBishop", Gtk::StockID("white_bishop_icon"), "White Bishop"),
00416 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_white_bishop));
00417 M_refActionGroup->add(Gtk::Action::create("PlacepieceWhiteQueen", Gtk::StockID("white_queen_icon"), "White Queen"),
00418 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_white_queen));
00419 M_refActionGroup->add(Gtk::Action::create("PlacepieceWhiteKing", Gtk::StockID("white_king_icon"), "White King"),
00420 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_white_king));
00421 M_refActionGroup->add(Gtk::Action::create("PlacepieceNothing", Gtk::StockID("black_nothing_icon"), "Clear square"),
00422 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_placepiece_nothing));
00423 M_refAllowEnPassantCapture_action = Gtk::ToggleAction::create("AllowEnPassantCapture", "Allow e.p. capture");
00424 M_refActionGroup->add(M_refAllowEnPassantCapture_action);
00425 M_AllowEnPassantCapture_connection =
00426 M_refAllowEnPassantCapture_action->signal_toggled().connect(sigc::mem_fun(*this,& ChessPositionWidget::on_menu_allow_en_passant_capture));
00427 M_refPieceHasMoved_action = Gtk::ToggleAction::create("PieceHasMoved", "Has moved");
00428 M_refActionGroup->add(M_refPieceHasMoved_action);
00429 M_PieceHasMoved_connection =
00430 M_refPieceHasMoved_action->signal_toggled().connect(sigc::mem_fun(*this,& ChessPositionWidget::on_menu_piece_has_moved));
00431 M_refActionGroup->add(Gtk::Action::create("CopyFEN", Gtk::Stock::COPY, "Copy FEN"),
00432 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_copy_FEN));
00433 M_refActionGroup->add(Gtk::Action::create("PasteFEN", Gtk::Stock::PASTE, "Paste FEN"),
00434 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_paste_FEN));
00435 M_refActionGroup->add(Gtk::Action::create("SwapColors", "Swap colors"),
00436 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_swap_colors));
00437 M_refActionGroup->add(Gtk::Action::create("InitialPosition", "Initial position"),
00438 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_initial_position));
00439 M_refActionGroup->add(Gtk::Action::create("ClearBoard", "Clear board"),
00440 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_clear_board));
00441 Gtk::RadioAction::Group group_to_move;
00442 M_refToMoveWhite_action = Gtk::RadioAction::create(group_to_move, "ToMoveWhite", "White to play");
00443 M_refActionGroup->add(M_refToMoveWhite_action,
00444 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_to_move_white));
00445 M_refToMoveBlack_action = Gtk::RadioAction::create(group_to_move, "ToMoveBlack", "Black to play");
00446 M_refActionGroup->add(M_refToMoveBlack_action,
00447 sigc::mem_fun(*this,& ChessPositionWidget::on_menu_to_move_black));
00448
00449 M_refUIManager = Gtk::UIManager::create();
00450 M_refUIManager->insert_action_group(M_refActionGroup);
00451
00452
00453
00454
00455 Glib::ustring ui_info =
00456 "<ui>"
00457 " <popup name='PopupMenu'>"
00458 " <menuitem action='PlacepieceWhitePawn'/>"
00459 " <menuitem action='PlacepieceWhiteRook'/>"
00460 " <menuitem action='PlacepieceWhiteKnight'/>"
00461 " <menuitem action='PlacepieceWhiteBishop'/>"
00462 " <menuitem action='PlacepieceWhiteQueen'/>"
00463 " <menuitem action='PlacepieceWhiteKing'/>"
00464 " <separator/>"
00465 " <menuitem action='PlacepieceBlackPawn'/>"
00466 " <menuitem action='PlacepieceBlackRook'/>"
00467 " <menuitem action='PlacepieceBlackKnight'/>"
00468 " <menuitem action='PlacepieceBlackBishop'/>"
00469 " <menuitem action='PlacepieceBlackQueen'/>"
00470 " <menuitem action='PlacepieceBlackKing'/>"
00471 " <separator/>"
00472 " <menuitem action='AllowEnPassantCapture'/>"
00473 " <menuitem action='PieceHasMoved'/>"
00474 " <menuitem action='PlacepieceNothing'/>"
00475 " <separator/>"
00476 " <menuitem action='ToMoveWhite'/>"
00477 " <menuitem action='ToMoveBlack'/>"
00478 " <separator/>"
00479 " <menuitem action='CopyFEN'/>"
00480 " <menuitem action='PasteFEN'/>"
00481 " <menuitem action='SwapColors'/>"
00482 " <menuitem action='InitialPosition'/>"
00483 " <menuitem action='ClearBoard'/>"
00484 " </popup>"
00485 "</ui>";
00486 #ifdef GLIBMM_EXCEPTIONS_ENABLED
00487 try
00488 {
00489 M_refUIManager->add_ui_from_string(ui_info);
00490 }
00491 catch(const Glib::Error& ex)
00492 {
00493 std::cerr << "building menus failed: " << ex.what();
00494 }
00495 #else
00496 std::auto_ptr<Glib::Error> ex;
00497 M_refUIManager->add_ui_from_string(ui_info, ex);
00498 if(ex.get())
00499 {
00500 std::cerr << "building menus failed: " << ex->what();
00501 }
00502 #endif //GLIBMM_EXCEPTIONS_ENABLED
00503
00504
00505 M_MenuPopup = dynamic_cast<Gtk::Menu*>(M_refUIManager->get_widget("/PopupMenu"));
00506 if (!M_MenuPopup)
00507 g_warning("menu not found");
00508 else
00509 M_MenuPopup->signal_deactivate().connect(sigc::mem_fun(this,& ChessPositionWidget::popup_deactivated));
00510 }
00511
00512 void ChessPositionWidget::popup_deactivated(void)
00513 {
00514 Dout(dc::notice, "Calling ChessPositionWidget::popup_deactivated()");
00515 hide_cursor();
00516 }
00517
00518 bool ChessPositionWidget::on_button_press_event(GdkEventButton* event)
00519 {
00520 #ifdef CWDEBUG
00521 if (debug::channels::dc::event.is_on())
00522 Dout(dc::event, "Entering ChessPositionWidget::on_button_press_event(" << event << ")");
00523 else
00524 Dout(dc::notice|dc::clipboard, "Entering ChessPositionWidget::on_button_press_event()");
00525 debug::Indent __cwmm_chesspositionwidget_debug_indent(2);
00526 #endif
00527
00528
00529 gint col = x2col(event->x);
00530 gint row = y2row(event->y);
00531
00532
00533 if (!is_inside_board(col, row))
00534 return false;
00535
00536
00537 if (on_button_press(col, row, event))
00538 return true;
00539
00540
00541
00542 if (event->type != GDK_BUTTON_PRESS ||
00543 (M_widget_mode != mode_edit_position && M_widget_mode != mode_edit_game))
00544 return false;
00545
00546
00547 if (event->button == 1)
00548 {
00549 M_floating_piece_handle = -1;
00550 code_t code = get_square(col, row);
00551
00552
00553 if (code > 1)
00554 {
00555 bool pickup = true;
00556 if (M_widget_mode == mode_edit_position)
00557 {
00558
00559 place(Code(), Index(col, row));
00560 }
00561 else
00562 {
00563
00564 M_move_from = Index(col, row);
00565 if (piece_at(M_move_from).color() != to_move())
00566
00567 pickup = false;
00568 else
00569 {
00570
00571 set_square(col, row, empty_square);
00572 }
00573 }
00574 if (pickup)
00575 {
00576
00577 double hsside = 0.5 * sside();
00578 double fraction = hsside - (gint)hsside;
00579 M_floating_piece_handle = add_floating_piece(code, event->x - fraction, event->y - fraction, TRUE);
00580 M_signal_picked_up.emit(M_move_from,* this);
00581
00582 return true;
00583 }
00584 }
00585 }
00586
00587 else if (event->button == 3 && M_widget_mode == mode_edit_position)
00588 {
00589 if (popup_menu(event, col, row))
00590 return true;
00591 }
00592
00593
00594 return false;
00595 }
00596
00597 bool ChessPositionWidget::on_button_release_event(GdkEventButton* event)
00598 {
00599 #ifdef CWDEBUG
00600 if (debug::channels::dc::event.is_on())
00601 Dout(dc::event, "Entering ChessPositionWidget::on_button_release_event(" << event << ")");
00602 else
00603 Dout(dc::notice, "Entering ChessPositionWidget::on_button_release_event()");
00604 debug::Indent __cwmm_chesspositionwidget_debug_indent(2);
00605 #endif
00606
00607
00608 gint col = x2col(event->x);
00609 gint row = y2row(event->y);
00610
00611
00612 if (!is_inside_board(col, row))
00613 col = row = -1;
00614 if (on_button_release(col, row, event))
00615 return true;
00616
00617
00618 if (M_widget_mode != mode_edit_position && M_widget_mode != mode_edit_game)
00619 return false;
00620
00621
00622 if (event->button == 1 && M_floating_piece_handle != -1)
00623 {
00624 if (M_widget_mode == mode_edit_game || col != -1)
00625 {
00626
00627 code_t code = get_floating_piece(M_floating_piece_handle);
00628 if (M_widget_mode == mode_edit_position)
00629 {
00630
00631 place(cwchess::Code(code), cwchess::Index(col, row));
00632 }
00633 else
00634 {
00635
00636 cwchess::Index to(col, row);
00637 if (to == M_move_from || col == -1)
00638 {
00639
00640 set_square(M_move_from.col(), M_move_from.row(), code);
00641 }
00642 else
00643 {
00644
00645 cwchess::Move move(M_move_from, to, cwchess::nothing);
00646 cwchess::Piece piece(piece_at(M_move_from));
00647 cwchess::Color color(piece.color());
00648 if (((color == cwchess::black && row == 0) || (color == cwchess::white && row == 7)) && piece.code().is_a(cwchess::pawn))
00649 move. set_promotion(M_promotion->type(this, move));
00650 if (legal(move))
00651 {
00652 cwchess::ChessPosition previous_position(*this);
00653 execute(move);
00654 M_signal_moved.emit(move, previous_position,* this);
00655 }
00656 else
00657 {
00658
00659 set_square(M_move_from.col(), M_move_from.row(), code);
00660 M_signal_illegal.emit(move,* this);
00661 }
00662 }
00663 }
00664 }
00665
00666 remove_floating_piece(M_floating_piece_handle);
00667 M_floating_piece_handle = -1;
00668 M_signal_dropped.emit(col, row,* this);
00669
00670 return true;
00671 }
00672
00673 return false;
00674 }
00675
00676 }
00677