1/* 2 * Color lines for GNOME 3 * Copyright © 1999 Free Software Foundation 4 * Authors: Robert Szokovacs <szo@appaloosacorp.hu> 5 * Szabolcs Ban <shooby@gnome.hu> 6 * Karuna Grewal <karunagrewal98@gmail.com> 7 * Ruxandra Simion <ruxandra.simion93@gmail.com> 8 * Copyright © 2007 Christian Persch 9 * 10 * This game is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2, or (at your option) 13 * any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, see <https://www.gnu.org/licenses/>. 22 */ 23 24[GtkTemplate (ui = "/org/gnome/five-or-more/ui/five-or-more.ui")] 25public class GameWindow : Gtk.ApplicationWindow 26{ 27 [GtkChild] 28 private Gtk.HeaderBar headerbar; 29 30 [GtkChild] 31 private Gtk.Box preview_hbox; 32 33 [GtkChild] 34 private Gtk.MenuButton primary_menu_button; 35 36 [GtkChild] 37 private Games.GridFrame grid_frame; 38 39 private Settings? settings = null; 40 private bool window_tiled; 41 public bool window_maximized { get; private set; } 42 public int window_width { get; private set; } 43 public int window_height { get; private set; } 44 45 private Game? game = null; 46 private ThemeRenderer? theme = null; 47 48 private Games.Scores.Context highscores; 49 private string[] status = { 50 _("Match five objects of the same type in a row to score!"), 51 _("You can’t move there!"), 52 _("Game Over!"), 53 _("Score: %d") 54 }; 55 56 public GameWindow (Gtk.Application app, Settings settings) 57 { 58 Object (application: app); 59 60 this.settings = settings; 61 game = new Game (settings); 62 theme = new ThemeRenderer (settings); 63 64 set_default_size (settings.get_int ("window-width"), settings.get_int ("window-height")); 65 if (settings.get_boolean ("window-is-maximized")) 66 maximize (); 67 68 NextPiecesWidget next_pieces_widget = new NextPiecesWidget (settings, game, theme); 69 preview_hbox.pack_start (next_pieces_widget); 70 next_pieces_widget.realize (); 71 next_pieces_widget.show (); 72 73 grid_frame.set (game.n_cols, game.n_rows); 74 game.board.board_changed.connect (() => { grid_frame.set (game.n_cols, game.n_rows); }); 75 game.notify["score"].connect ((s, p) => { set_status_message (status[StatusMessage.NONE].printf(game.score)); }); 76 game.notify["status-message"].connect ((s, p) => { set_status_message (status[game.status_message].printf(game.score)); }); 77 set_status_message (status[game.status_message]); 78 79 View game_view = new View (settings, game, theme); 80 grid_frame.add (game_view); 81 game_view.show (); 82 83 grid_frame.show (); 84 85 var importer = new Games.Scores.DirectoryImporter (); 86 highscores = new Games.Scores.Context.with_importer ("five-or-more", 87 _("Board Size: "), 88 this, 89 create_category_from_key, 90 Games.Scores.Style.POINTS_GREATER_IS_BETTER, 91 importer); 92 game.game_over.connect (score_cb); 93 } 94 95 protected override bool window_state_event (Gdk.EventWindowState event) 96 { 97 if ((event.changed_mask & Gdk.WindowState.MAXIMIZED) != 0) 98 window_maximized = (event.new_window_state & Gdk.WindowState.MAXIMIZED) != 0; 99 100 if ((event.changed_mask & Gdk.WindowState.TILED) != 0) 101 window_tiled = (event.new_window_state & Gdk.WindowState.TILED) != 0; 102 103 return false; 104 } 105 106 protected override void size_allocate (Gtk.Allocation allocation) 107 { 108 base.size_allocate (allocation); 109 110 if (window_maximized || window_tiled) 111 return; 112 113 window_width = allocation.width; 114 window_height = allocation.height; 115 } 116 117 private void score_cb () 118 { 119 120 string name = category_name_from_key (game.score_current_category); 121 var current_category = new Games.Scores.Category (game.score_current_category, name); 122 highscores.add_score (game.score, 123 current_category, 124 new Cancellable ()); 125 126 show_scores (); 127 } 128 129 public void restart_game () 130 { 131 game.restart (); 132 } 133 134 private void set_status_message (string? message) 135 { 136 headerbar.set_subtitle (message); 137 } 138 139 public void show_scores () 140 { 141 highscores.run_dialog (); 142 } 143 144 public void change_size (BoardSize size) 145 { 146 var game_size = settings.get_int ("size"); 147 148 if (game_size == size) 149 return; 150 151 primary_menu_button.set_active (false); 152 153 if (game.score > 0) { 154 var flags = Gtk.DialogFlags.DESTROY_WITH_PARENT; 155 var restart_game_dialog = new Gtk.MessageDialog (this, 156 flags, 157 Gtk.MessageType.WARNING, 158 Gtk.ButtonsType.NONE, 159 _("Are you sure you want to restart the game?"), 160 null); 161 restart_game_dialog.add_buttons (_("_Cancel"), Gtk.ResponseType.CANCEL, 162 _("_Restart"), Gtk.ResponseType.OK, 163 null); 164 165 var result = restart_game_dialog.run (); 166 restart_game_dialog.destroy (); 167 switch (result) 168 { 169 case Gtk.ResponseType.OK: 170 if (!settings.set_int (FiveOrMoreApp.KEY_SIZE, size)) 171 warning ("Failed to set size: %d", size); 172 break; 173 case Gtk.ResponseType.CANCEL: 174 break; 175 } 176 } else { 177 settings.set_int (FiveOrMoreApp.KEY_SIZE, size); 178 } 179 180 } 181 182 private Games.Scores.Category? create_category_from_key (string key) 183 { 184 string? name = category_name_from_key (key); 185 return new Games.Scores.Category (key, name); 186 } 187 188 private string category_name_from_key (string key) 189 { 190 for (int i = 0; i < game.n_categories; i++) { 191 if (Game.scorecats[i].key == key) 192 return Game.scorecats[i].name; 193 } 194 return ""; 195 } 196} 197