Crossfire Client, Branch
R11627
|
00001 const char * const rcsid_gtk2_spells_c = 00002 "$Id: spells.c 9201 2008-06-01 17:32:45Z anmaster $"; 00003 /* 00004 Crossfire client, a client program for the crossfire program. 00005 00006 Copyright (C) 2006-2007 Mark Wedel & Crossfire Development Team 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 2 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program; if not, write to the Free Software 00020 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00021 00022 The author can be reached via e-mail to crossfire@metalforge.org 00023 */ 00024 00030 #ifdef HAVE_CONFIG_H 00031 # include <config.h> 00032 #endif 00033 00034 #include <gtk/gtk.h> 00035 #include <glade/glade.h> 00036 00037 #include "client.h" 00038 00039 #include "image.h" 00040 #include "gtk2proto.h" 00041 #include "metaserver.h" 00042 #include "main.h" 00043 00044 enum Styles { 00045 Style_Attuned, Style_Repelled, Style_Denied, Style_Normal, Style_Last 00046 }; 00047 00048 static GtkWidget *spell_window, *spell_treeview, *spell_invoke, *spell_cast, 00049 *spell_options, *spell_label[Style_Last], *spell_eventbox[Style_Last]; 00050 static GtkListStore *spell_store; 00051 static GtkTreeSelection *spell_selection; 00052 00053 enum {LIST_IMAGE, LIST_NAME, LIST_LEVEL, LIST_TIME, LIST_COST, 00054 LIST_DAMAGE, LIST_SKILL, LIST_PATH, LIST_DESCRIPTION, LIST_BACKGROUND, LIST_MAX_SP, LIST_TAG, 00055 LIST_FOREGROUND, LIST_FONT}; 00056 00057 static const char *Style_Names[Style_Last] = { 00058 "spell_attuned", "spell_repelled", "spell_denied", "spell_normal" 00059 }; 00061 static GtkStyle *spell_styles[Style_Last]; 00063 static int has_init=0; 00064 00072 void spell_get_styles(void) 00073 { 00074 int i; 00075 GtkStyle *tmp_style; 00076 static int style_has_init=0; 00077 00078 for (i=0; i < Style_Last; i++) { 00079 if (style_has_init && spell_styles[i]) g_object_unref(spell_styles[i]); 00080 tmp_style = gtk_rc_get_style_by_paths(gtk_settings_get_default(), NULL, 00081 Style_Names[i], G_TYPE_NONE); 00082 if (tmp_style) { 00083 spell_styles[i] = g_object_ref(tmp_style); 00084 } 00085 else { 00086 LOG(LOG_INFO, "spells.c::spell_get_styles", "Unable to find style for %s", 00087 Style_Names[i]); 00088 spell_styles[i] = NULL; 00089 } 00090 } 00091 style_has_init=1; 00092 } 00093 00104 static gboolean spell_selection_func ( 00105 GtkTreeSelection *selection, 00106 GtkTreeModel *model, 00107 GtkTreePath *path, 00108 gboolean path_currently_selected, 00109 gpointer userdata) 00110 { 00111 gtk_widget_set_sensitive(spell_invoke, TRUE); 00112 gtk_widget_set_sensitive(spell_cast, TRUE); 00113 return TRUE; 00114 } 00115 00119 void update_spell_information(void) 00120 { 00121 Spell *spell; 00122 GtkTreeIter iter; 00123 char buf[MAX_BUF]; 00124 GtkStyle *row_style; 00125 PangoFontDescription *font=NULL; 00126 GdkColor *foreground=NULL, *background=NULL; 00127 int i; 00128 00129 /* If the window/spellstore hasn't been created, return. */ 00130 if (!has_init) return; 00131 cpl.spells_updated=0; 00132 00133 /* We could try to do this in spell_get_styles, but if the window 00134 * isn't active, it won't work. This is called whenever the window 00135 * is made active, so we know it will work, and the time 00136 * to set this info here, even though it may not change often, 00137 * is pretty trivial. 00138 */ 00139 for (i=0; i < Style_Last; i++) { 00140 if (spell_styles[i]) { 00141 gtk_widget_modify_fg(spell_label[i],GTK_STATE_NORMAL, 00142 &spell_styles[i]->text[GTK_STATE_NORMAL]); 00143 gtk_widget_modify_font(spell_label[i], spell_styles[i]->font_desc); 00144 gtk_widget_modify_bg(spell_eventbox[i],GTK_STATE_NORMAL, 00145 &spell_styles[i]->base[GTK_STATE_NORMAL]); 00146 } else { 00147 gtk_widget_modify_fg(spell_label[i],GTK_STATE_NORMAL, NULL); 00148 gtk_widget_modify_font(spell_label[i], NULL); 00149 gtk_widget_modify_bg(spell_eventbox[i],GTK_STATE_NORMAL, NULL); 00150 } 00151 } 00152 00153 gtk_list_store_clear(spell_store); 00154 for (spell = cpl.spelldata; spell; spell=spell->next) { 00155 gtk_list_store_append(spell_store, &iter); 00156 00157 buf[0] = 0; 00158 if (spell->sp) snprintf(buf, sizeof(buf), "%d Mana ", spell->sp); 00159 if (spell->grace) snprintf(buf + strlen(buf), sizeof(buf)-strlen(buf), "%d Grace", spell->grace); 00160 00161 if (spell->path & cpl.stats.denied) { row_style = spell_styles[Style_Denied]; } 00162 else if (spell->path & cpl.stats.repelled) { row_style = spell_styles[Style_Repelled]; } 00163 else if (spell->path & cpl.stats.attuned) { row_style = spell_styles[Style_Attuned]; } 00164 else row_style = spell_styles[Style_Normal]; 00165 00166 if (row_style) { 00167 foreground = &row_style->text[GTK_STATE_NORMAL]; 00168 background = &row_style->base[GTK_STATE_NORMAL]; 00169 font = row_style->font_desc; 00170 } else { 00171 foreground=NULL; 00172 background=NULL; 00173 font=NULL; 00174 } 00175 00176 gtk_list_store_set(spell_store, &iter, 00177 LIST_NAME, spell->name, 00178 LIST_LEVEL, spell->level, 00179 LIST_COST, buf, 00180 LIST_DAMAGE, spell->dam, 00181 LIST_SKILL, spell->skill, 00182 LIST_DESCRIPTION, spell->message, 00183 LIST_BACKGROUND, background, 00184 LIST_FOREGROUND, foreground, 00185 LIST_FONT, font, 00186 LIST_MAX_SP, (spell->sp > spell->grace)?spell->sp:spell->grace, 00187 LIST_TAG, spell->tag, 00188 -1); 00189 } 00190 } 00191 00197 void 00198 on_spells_activate (GtkMenuItem *menuitem, 00199 gpointer user_data) 00200 { 00201 GladeXML *xml_tree; 00202 GtkWidget *widget; 00203 00204 if (!has_init) { 00205 GtkCellRenderer *renderer; 00206 GtkTreeViewColumn *column; 00207 00208 spell_window = glade_xml_get_widget(dialog_xml, "spell_window"); 00209 xml_tree = glade_get_widget_tree(GTK_WIDGET(spell_window)); 00210 00211 spell_invoke = glade_xml_get_widget(xml_tree,"spell_invoke"); 00212 spell_cast = glade_xml_get_widget(xml_tree,"spell_cast"); 00213 spell_options = glade_xml_get_widget(xml_tree,"spell_options"); 00214 spell_treeview = glade_xml_get_widget(xml_tree, "spell_treeview"); 00215 00216 g_signal_connect ((gpointer) spell_treeview, "row_activated", 00217 G_CALLBACK (on_spell_treeview_row_activated), NULL); 00218 g_signal_connect ((gpointer) spell_cast, "clicked", 00219 G_CALLBACK (on_spell_cast_clicked), NULL); 00220 g_signal_connect ((gpointer) spell_invoke, "clicked", 00221 G_CALLBACK (on_spell_invoke_clicked), NULL); 00222 00223 widget = glade_xml_get_widget(xml_tree, "spell_close"); 00224 g_signal_connect ((gpointer) widget, "clicked", 00225 G_CALLBACK (on_spell_close_clicked), NULL); 00226 00227 spell_store = gtk_list_store_new(14, 00228 G_TYPE_OBJECT, /* Image - not used */ 00229 G_TYPE_STRING, /* Name */ 00230 G_TYPE_INT, /* Level */ 00231 G_TYPE_INT, /* Time */ 00232 G_TYPE_STRING, /* SP/Grace */ 00233 G_TYPE_INT, /* Damage */ 00234 G_TYPE_STRING, /* Skill name */ 00235 G_TYPE_INT, /* Spell path */ 00236 G_TYPE_STRING, /* Description */ 00237 GDK_TYPE_COLOR, /* Change the background color of the entry */ 00238 G_TYPE_INT, 00239 G_TYPE_INT, 00240 GDK_TYPE_COLOR, 00241 PANGO_TYPE_FONT_DESCRIPTION 00242 ); 00243 00244 gtk_tree_view_set_model(GTK_TREE_VIEW(spell_treeview), GTK_TREE_MODEL(spell_store)); 00245 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(spell_treeview), TRUE); 00246 00247 /* Note it is intentional we don't show (render) some fields: 00248 * image - we don't have images right now it seems. 00249 * time - not sure if it worth the space. 00250 * spell path - done by color 00251 */ 00252 renderer = gtk_cell_renderer_text_new (); 00253 column = gtk_tree_view_column_new_with_attributes ("Spell", renderer, 00254 "text", LIST_NAME, 00255 NULL); 00256 gtk_tree_view_append_column (GTK_TREE_VIEW (spell_treeview), column); 00257 gtk_tree_view_column_set_sort_column_id(column, LIST_NAME); 00258 gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND); 00259 gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND); 00260 gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT); 00261 00262 renderer = gtk_cell_renderer_text_new (); 00263 column = gtk_tree_view_column_new_with_attributes ("Level", renderer, 00264 "text", LIST_LEVEL, 00265 NULL); 00266 gtk_tree_view_append_column (GTK_TREE_VIEW (spell_treeview), column); 00267 gtk_tree_view_column_set_sort_column_id(column, LIST_LEVEL); 00268 gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND); 00269 gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND); 00270 gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT); 00271 00272 renderer = gtk_cell_renderer_text_new (); 00273 column = gtk_tree_view_column_new_with_attributes ("SP/Mana Cost", renderer, 00274 "text", LIST_COST, 00275 NULL); 00276 gtk_tree_view_append_column (GTK_TREE_VIEW (spell_treeview), column); 00277 00278 /* since this is a string column, it would do a string sort. Instead, 00279 * we set up a int column and tie this column to sort on that. 00280 */ 00281 gtk_tree_view_column_set_sort_column_id(column, LIST_MAX_SP); 00282 gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND); 00283 gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND); 00284 gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT); 00285 00286 renderer = gtk_cell_renderer_text_new (); 00287 column = gtk_tree_view_column_new_with_attributes ("Damage", renderer, 00288 "text", LIST_DAMAGE, 00289 NULL); 00290 gtk_tree_view_append_column (GTK_TREE_VIEW (spell_treeview), column); 00291 gtk_tree_view_column_set_sort_column_id(column, LIST_DAMAGE); 00292 gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND); 00293 gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND); 00294 gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT); 00295 00296 column = gtk_tree_view_column_new_with_attributes ("Skill", renderer, 00297 "text", LIST_SKILL, 00298 NULL); 00299 gtk_tree_view_append_column (GTK_TREE_VIEW (spell_treeview), column); 00300 gtk_tree_view_column_set_sort_column_id(column, LIST_SKILL); 00301 gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND); 00302 gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND); 00303 gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT); 00304 00305 renderer = gtk_cell_renderer_text_new (); 00306 column = gtk_tree_view_column_new_with_attributes ("Description", renderer, 00307 "text", LIST_DESCRIPTION, 00308 NULL); 00309 gtk_tree_view_append_column (GTK_TREE_VIEW (spell_treeview), column); 00310 gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND); 00311 gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND); 00312 gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT); 00313 00314 spell_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(spell_treeview)); 00315 gtk_tree_selection_set_mode (spell_selection, GTK_SELECTION_BROWSE); 00316 gtk_tree_selection_set_select_function(spell_selection, spell_selection_func, 00317 NULL, NULL); 00318 00319 00320 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(spell_store), 00321 LIST_NAME, 00322 GTK_SORT_ASCENDING); 00323 00324 /* the style code will set the colors for these */ 00325 spell_label[Style_Attuned] = 00326 glade_xml_get_widget(xml_tree, "spell_label_attuned"); 00327 spell_label[Style_Repelled] = 00328 glade_xml_get_widget(xml_tree, "spell_label_repelled"); 00329 spell_label[Style_Denied] = 00330 glade_xml_get_widget(xml_tree, "spell_label_denied"); 00331 spell_label[Style_Normal] = 00332 glade_xml_get_widget(xml_tree, "spell_label_normal"); 00333 00334 /* We use eventboxes because the label widget is a transparent widget - 00335 * we can't set the background in it and have it work. 00336 * But we can set the background in the event box, and put the label 00337 * widget in the eventbox. 00338 */ 00339 spell_eventbox[Style_Attuned] = 00340 glade_xml_get_widget(xml_tree, "spell_eventbox_attuned"); 00341 spell_eventbox[Style_Repelled] = 00342 glade_xml_get_widget(xml_tree, "spell_eventbox_repelled"); 00343 spell_eventbox[Style_Denied] = 00344 glade_xml_get_widget(xml_tree, "spell_eventbox_denied"); 00345 spell_eventbox[Style_Normal] = 00346 glade_xml_get_widget(xml_tree, "spell_eventbox_normal"); 00347 } 00348 gtk_widget_set_sensitive(spell_invoke, FALSE); 00349 gtk_widget_set_sensitive(spell_cast, FALSE); 00350 gtk_widget_show(spell_window); 00351 spell_get_styles(); 00352 00353 has_init=1; 00354 /* has to be called after has_init is set to 1 */ 00355 update_spell_information(); 00356 00357 } 00358 00366 void 00367 on_spell_treeview_row_activated (GtkTreeView *treeview, 00368 GtkTreePath *path, 00369 GtkTreeViewColumn *column, 00370 gpointer user_data) 00371 { 00372 GtkTreeIter iter; 00373 GtkTreeModel *model; 00374 int tag; 00375 char command[MAX_BUF]; 00376 const char *options = NULL; 00377 00378 model = gtk_tree_view_get_model(treeview); 00379 if (gtk_tree_model_get_iter(model, &iter, path)) { 00380 gtk_tree_model_get(model, &iter, LIST_TAG, &tag, -1); 00381 00382 if (!tag) { 00383 LOG(LOG_ERROR,"spells.c:on_spell_cast_clicked", "Unable to get spell tag\n"); 00384 return; 00385 } 00386 snprintf(command, MAX_BUF-1, "cast %d %s", tag, options); 00387 send_command(command, -1, 1); 00388 } 00389 } 00390 00396 void 00397 on_spell_cast_clicked (GtkButton *button, 00398 gpointer user_data) 00399 { 00400 const char *options = NULL; 00401 char command[MAX_BUF]; 00402 GtkTreeIter iter; 00403 GtkTreeModel *model; 00404 int tag; 00405 00406 options = gtk_entry_get_text(GTK_ENTRY(spell_options)); 00407 00408 if (gtk_tree_selection_get_selected (spell_selection, &model, &iter)) { 00409 gtk_tree_model_get(model, &iter, LIST_TAG, &tag, -1); 00410 00411 if (!tag) { 00412 LOG(LOG_ERROR,"spells.c:on_spell_cast_clicked", "Unable to get spell tag\n"); 00413 return; 00414 } 00415 snprintf(command, MAX_BUF-1, "cast %d %s", tag, options); 00416 send_command(command, -1, 1); 00417 } 00418 00419 } 00420 00426 void 00427 on_spell_invoke_clicked (GtkButton *button, 00428 gpointer user_data) 00429 { 00430 const char *options = NULL; 00431 char command[MAX_BUF]; 00432 GtkTreeIter iter; 00433 GtkTreeModel *model; 00434 int tag; 00435 00436 options = gtk_entry_get_text(GTK_ENTRY(spell_options)); 00437 00438 if (gtk_tree_selection_get_selected (spell_selection, &model, &iter)) { 00439 gtk_tree_model_get(model, &iter, LIST_TAG, &tag, -1); 00440 00441 if (!tag) { 00442 LOG(LOG_ERROR,"spells.c:on_spell_invoke_clicked", "Unable to get spell tag\n"); 00443 return; 00444 } 00445 snprintf(command, MAX_BUF-1, "invoke %d %s", tag, options); 00446 send_command(command, -1, 1); 00447 } 00448 } 00449 00455 void 00456 on_spell_close_clicked (GtkButton *button, 00457 gpointer user_data) 00458 { 00459 gtk_widget_hide(spell_window); 00460 00461 }