Crossfire Client, Branches  R11627
spells.c
Go to the documentation of this file.
1 const char * const rcsid_gtk2_spells_c =
2  "$Id: spells.c 9201 2008-06-01 17:32:45Z anmaster $";
3 /*
4  Crossfire client, a client program for the crossfire program.
5 
6  Copyright (C) 2006-2007 Mark Wedel & Crossfire Development Team
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 
22  The author can be reached via e-mail to crossfire@metalforge.org
23 */
24 
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33 
34 #include <gtk/gtk.h>
35 #include <glade/glade.h>
36 
37 #include "client.h"
38 
39 #include "image.h"
40 #include "gtk2proto.h"
41 #include "metaserver.h"
42 #include "main.h"
43 
44 enum Styles {
46 };
47 
50 static GtkListStore *spell_store;
51 static GtkTreeSelection *spell_selection;
52 
56 
57 static const char *Style_Names[Style_Last] = {
58  "spell_attuned", "spell_repelled", "spell_denied", "spell_normal"
59 };
61 static GtkStyle *spell_styles[Style_Last];
63 static int has_init=0;
64 
72 void spell_get_styles(void)
73 {
74  int i;
75  GtkStyle *tmp_style;
76  static int style_has_init=0;
77 
78  for (i=0; i < Style_Last; i++) {
79  if (style_has_init && spell_styles[i]) g_object_unref(spell_styles[i]);
80  tmp_style = gtk_rc_get_style_by_paths(gtk_settings_get_default(), NULL,
81  Style_Names[i], G_TYPE_NONE);
82  if (tmp_style) {
83  spell_styles[i] = g_object_ref(tmp_style);
84  }
85  else {
86  LOG(LOG_INFO, "spells.c::spell_get_styles", "Unable to find style for %s",
87  Style_Names[i]);
88  spell_styles[i] = NULL;
89  }
90  }
91  style_has_init=1;
92 }
93 
104 static gboolean spell_selection_func (
105  GtkTreeSelection *selection,
106  GtkTreeModel *model,
107  GtkTreePath *path,
108  gboolean path_currently_selected,
109  gpointer userdata)
110 {
111  gtk_widget_set_sensitive(spell_invoke, TRUE);
112  gtk_widget_set_sensitive(spell_cast, TRUE);
113  return TRUE;
114 }
115 
120 {
121  Spell *spell;
122  GtkTreeIter iter;
123  char buf[MAX_BUF];
124  GtkStyle *row_style;
125  PangoFontDescription *font=NULL;
126  GdkColor *foreground=NULL, *background=NULL;
127  int i;
128 
129  /* If the window/spellstore hasn't been created, return. */
130  if (!has_init) return;
132 
133  /* We could try to do this in spell_get_styles, but if the window
134  * isn't active, it won't work. This is called whenever the window
135  * is made active, so we know it will work, and the time
136  * to set this info here, even though it may not change often,
137  * is pretty trivial.
138  */
139  for (i=0; i < Style_Last; i++) {
140  if (spell_styles[i]) {
141  gtk_widget_modify_fg(spell_label[i],GTK_STATE_NORMAL,
142  &spell_styles[i]->text[GTK_STATE_NORMAL]);
143  gtk_widget_modify_font(spell_label[i], spell_styles[i]->font_desc);
144  gtk_widget_modify_bg(spell_eventbox[i],GTK_STATE_NORMAL,
145  &spell_styles[i]->base[GTK_STATE_NORMAL]);
146  } else {
147  gtk_widget_modify_fg(spell_label[i],GTK_STATE_NORMAL, NULL);
148  gtk_widget_modify_font(spell_label[i], NULL);
149  gtk_widget_modify_bg(spell_eventbox[i],GTK_STATE_NORMAL, NULL);
150  }
151  }
152 
153  gtk_list_store_clear(spell_store);
154  for (spell = cpl.spelldata; spell; spell=spell->next) {
155  gtk_list_store_append(spell_store, &iter);
156 
157  buf[0] = 0;
158  if (spell->sp) snprintf(buf, sizeof(buf), "%d Mana ", spell->sp);
159  if (spell->grace) snprintf(buf + strlen(buf), sizeof(buf)-strlen(buf), "%d Grace", spell->grace);
160 
161  if (spell->path & cpl.stats.denied) { row_style = spell_styles[Style_Denied]; }
162  else if (spell->path & cpl.stats.repelled) { row_style = spell_styles[Style_Repelled]; }
163  else if (spell->path & cpl.stats.attuned) { row_style = spell_styles[Style_Attuned]; }
164  else row_style = spell_styles[Style_Normal];
165 
166  if (row_style) {
167  foreground = &row_style->text[GTK_STATE_NORMAL];
168  background = &row_style->base[GTK_STATE_NORMAL];
169  font = row_style->font_desc;
170  } else {
171  foreground=NULL;
172  background=NULL;
173  font=NULL;
174  }
175 
176  gtk_list_store_set(spell_store, &iter,
177  LIST_NAME, spell->name,
178  LIST_LEVEL, spell->level,
179  LIST_COST, buf,
180  LIST_DAMAGE, spell->dam,
181  LIST_SKILL, spell->skill,
182  LIST_DESCRIPTION, spell->message,
183  LIST_BACKGROUND, background,
184  LIST_FOREGROUND, foreground,
185  LIST_FONT, font,
186  LIST_MAX_SP, (spell->sp > spell->grace)?spell->sp:spell->grace,
187  LIST_TAG, spell->tag,
188  -1);
189  }
190 }
191 
197 void
198 on_spells_activate (GtkMenuItem *menuitem,
199  gpointer user_data)
200 {
201  GladeXML *xml_tree;
202  GtkWidget *widget;
203 
204  if (!has_init) {
205  GtkCellRenderer *renderer;
206  GtkTreeViewColumn *column;
207 
208  spell_window = glade_xml_get_widget(dialog_xml, "spell_window");
209  xml_tree = glade_get_widget_tree(GTK_WIDGET(spell_window));
210 
211  spell_invoke = glade_xml_get_widget(xml_tree,"spell_invoke");
212  spell_cast = glade_xml_get_widget(xml_tree,"spell_cast");
213  spell_options = glade_xml_get_widget(xml_tree,"spell_options");
214  spell_treeview = glade_xml_get_widget(xml_tree, "spell_treeview");
215 
216  g_signal_connect ((gpointer) spell_treeview, "row_activated",
217  G_CALLBACK (on_spell_treeview_row_activated), NULL);
218  g_signal_connect ((gpointer) spell_cast, "clicked",
219  G_CALLBACK (on_spell_cast_clicked), NULL);
220  g_signal_connect ((gpointer) spell_invoke, "clicked",
221  G_CALLBACK (on_spell_invoke_clicked), NULL);
222 
223  widget = glade_xml_get_widget(xml_tree, "spell_close");
224  g_signal_connect ((gpointer) widget, "clicked",
225  G_CALLBACK (on_spell_close_clicked), NULL);
226 
227  spell_store = gtk_list_store_new(14,
228  G_TYPE_OBJECT, /* Image - not used */
229  G_TYPE_STRING, /* Name */
230  G_TYPE_INT, /* Level */
231  G_TYPE_INT, /* Time */
232  G_TYPE_STRING, /* SP/Grace */
233  G_TYPE_INT, /* Damage */
234  G_TYPE_STRING, /* Skill name */
235  G_TYPE_INT, /* Spell path */
236  G_TYPE_STRING, /* Description */
237  GDK_TYPE_COLOR, /* Change the background color of the entry */
238  G_TYPE_INT,
239  G_TYPE_INT,
240  GDK_TYPE_COLOR,
241  PANGO_TYPE_FONT_DESCRIPTION
242  );
243 
244  gtk_tree_view_set_model(GTK_TREE_VIEW(spell_treeview), GTK_TREE_MODEL(spell_store));
245  gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(spell_treeview), TRUE);
246 
247  /* Note it is intentional we don't show (render) some fields:
248  * image - we don't have images right now it seems.
249  * time - not sure if it worth the space.
250  * spell path - done by color
251  */
252  renderer = gtk_cell_renderer_text_new ();
253  column = gtk_tree_view_column_new_with_attributes ("Spell", renderer,
254  "text", LIST_NAME,
255  NULL);
256  gtk_tree_view_append_column (GTK_TREE_VIEW (spell_treeview), column);
257  gtk_tree_view_column_set_sort_column_id(column, LIST_NAME);
258  gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND);
259  gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND);
260  gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT);
261 
262  renderer = gtk_cell_renderer_text_new ();
263  column = gtk_tree_view_column_new_with_attributes ("Level", renderer,
264  "text", LIST_LEVEL,
265  NULL);
266  gtk_tree_view_append_column (GTK_TREE_VIEW (spell_treeview), column);
267  gtk_tree_view_column_set_sort_column_id(column, LIST_LEVEL);
268  gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND);
269  gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND);
270  gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT);
271 
272  renderer = gtk_cell_renderer_text_new ();
273  column = gtk_tree_view_column_new_with_attributes ("SP/Mana Cost", renderer,
274  "text", LIST_COST,
275  NULL);
276  gtk_tree_view_append_column (GTK_TREE_VIEW (spell_treeview), column);
277 
278  /* since this is a string column, it would do a string sort. Instead,
279  * we set up a int column and tie this column to sort on that.
280  */
281  gtk_tree_view_column_set_sort_column_id(column, LIST_MAX_SP);
282  gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND);
283  gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND);
284  gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT);
285 
286  renderer = gtk_cell_renderer_text_new ();
287  column = gtk_tree_view_column_new_with_attributes ("Damage", renderer,
288  "text", LIST_DAMAGE,
289  NULL);
290  gtk_tree_view_append_column (GTK_TREE_VIEW (spell_treeview), column);
291  gtk_tree_view_column_set_sort_column_id(column, LIST_DAMAGE);
292  gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND);
293  gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND);
294  gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT);
295 
296  column = gtk_tree_view_column_new_with_attributes ("Skill", renderer,
297  "text", LIST_SKILL,
298  NULL);
299  gtk_tree_view_append_column (GTK_TREE_VIEW (spell_treeview), column);
300  gtk_tree_view_column_set_sort_column_id(column, LIST_SKILL);
301  gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND);
302  gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND);
303  gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT);
304 
305  renderer = gtk_cell_renderer_text_new ();
306  column = gtk_tree_view_column_new_with_attributes ("Description", renderer,
307  "text", LIST_DESCRIPTION,
308  NULL);
309  gtk_tree_view_append_column (GTK_TREE_VIEW (spell_treeview), column);
310  gtk_tree_view_column_add_attribute(column, renderer, "background-gdk", LIST_BACKGROUND);
311  gtk_tree_view_column_add_attribute(column, renderer, "foreground-gdk", LIST_FOREGROUND);
312  gtk_tree_view_column_add_attribute(column, renderer, "font-desc", LIST_FONT);
313 
314  spell_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(spell_treeview));
315  gtk_tree_selection_set_mode (spell_selection, GTK_SELECTION_BROWSE);
316  gtk_tree_selection_set_select_function(spell_selection, spell_selection_func,
317  NULL, NULL);
318 
319 
320  gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(spell_store),
321  LIST_NAME,
322  GTK_SORT_ASCENDING);
323 
324  /* the style code will set the colors for these */
326  glade_xml_get_widget(xml_tree, "spell_label_attuned");
328  glade_xml_get_widget(xml_tree, "spell_label_repelled");
330  glade_xml_get_widget(xml_tree, "spell_label_denied");
332  glade_xml_get_widget(xml_tree, "spell_label_normal");
333 
334  /* We use eventboxes because the label widget is a transparent widget -
335  * we can't set the background in it and have it work.
336  * But we can set the background in the event box, and put the label
337  * widget in the eventbox.
338  */
340  glade_xml_get_widget(xml_tree, "spell_eventbox_attuned");
342  glade_xml_get_widget(xml_tree, "spell_eventbox_repelled");
344  glade_xml_get_widget(xml_tree, "spell_eventbox_denied");
346  glade_xml_get_widget(xml_tree, "spell_eventbox_normal");
347  }
348  gtk_widget_set_sensitive(spell_invoke, FALSE);
349  gtk_widget_set_sensitive(spell_cast, FALSE);
350  gtk_widget_show(spell_window);
352 
353  has_init=1;
354  /* has to be called after has_init is set to 1 */
356 
357 }
358 
366 void
367 on_spell_treeview_row_activated (GtkTreeView *treeview,
368  GtkTreePath *path,
369  GtkTreeViewColumn *column,
370  gpointer user_data)
371 {
372  GtkTreeIter iter;
373  GtkTreeModel *model;
374  int tag;
375  char command[MAX_BUF];
376  const char *options = NULL;
377 
378  model = gtk_tree_view_get_model(treeview);
379  if (gtk_tree_model_get_iter(model, &iter, path)) {
380  gtk_tree_model_get(model, &iter, LIST_TAG, &tag, -1);
381 
382  if (!tag) {
383  LOG(LOG_ERROR,"spells.c:on_spell_cast_clicked", "Unable to get spell tag\n");
384  return;
385  }
386  snprintf(command, MAX_BUF-1, "cast %d %s", tag, options);
387  send_command(command, -1, 1);
388  }
389 }
390 
396 void
397 on_spell_cast_clicked (GtkButton *button,
398  gpointer user_data)
399 {
400  const char *options = NULL;
401  char command[MAX_BUF];
402  GtkTreeIter iter;
403  GtkTreeModel *model;
404  int tag;
405 
406  options = gtk_entry_get_text(GTK_ENTRY(spell_options));
407 
408  if (gtk_tree_selection_get_selected (spell_selection, &model, &iter)) {
409  gtk_tree_model_get(model, &iter, LIST_TAG, &tag, -1);
410 
411  if (!tag) {
412  LOG(LOG_ERROR,"spells.c:on_spell_cast_clicked", "Unable to get spell tag\n");
413  return;
414  }
415  snprintf(command, MAX_BUF-1, "cast %d %s", tag, options);
416  send_command(command, -1, 1);
417  }
418 
419 }
420 
426 void
427 on_spell_invoke_clicked (GtkButton *button,
428  gpointer user_data)
429 {
430  const char *options = NULL;
431  char command[MAX_BUF];
432  GtkTreeIter iter;
433  GtkTreeModel *model;
434  int tag;
435 
436  options = gtk_entry_get_text(GTK_ENTRY(spell_options));
437 
438  if (gtk_tree_selection_get_selected (spell_selection, &model, &iter)) {
439  gtk_tree_model_get(model, &iter, LIST_TAG, &tag, -1);
440 
441  if (!tag) {
442  LOG(LOG_ERROR,"spells.c:on_spell_invoke_clicked", "Unable to get spell tag\n");
443  return;
444  }
445  snprintf(command, MAX_BUF-1, "invoke %d %s", tag, options);
446  send_command(command, -1, 1);
447  }
448 }
449 
455 void
456 on_spell_close_clicked (GtkButton *button,
457  gpointer user_data)
458 {
459  gtk_widget_hide(spell_window);
460 
461 }
void on_spells_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: spells.c:198
uint32 spells_updated
Definition: client.h:289
static GtkWidget * spell_label[Style_Last]
Definition: spells.c:48
static XFontStruct * font
Definition: x11.c:192
uint16 grace
Definition: client.h:260
const char *const rcsid_gtk2_spells_c
Definition: spells.c:1
static const char * Style_Names[Style_Last]
Definition: spells.c:57
static GtkWidget * spell_eventbox[Style_Last]
Definition: spells.c:48
void on_spell_cast_clicked(GtkButton *button, gpointer user_data)
Definition: spells.c:397
static unsigned long background
Definition: x11.c:187
void on_spell_treeview_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
Definition: spells.c:367
uint32 repelled
Definition: client.h:236
Stats stats
Definition: client.h:285
static GtkWidget * spell_cast
Definition: spells.c:48
uint32 tag
Definition: client.h:255
GladeXML * dialog_xml
Definition: main.c:57
uint32 denied
Definition: client.h:239
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:178
#define TRUE
Definition: client-types.h:71
static GtkTreeSelection * spell_selection
Definition: spells.c:51
void on_spell_close_clicked(GtkButton *button, gpointer user_data)
Definition: spells.c:456
gchar * text
Definition: about.h:2
int send_command(const char *command, int repeat, int must_send)
Definition: player.c:195
void spell_get_styles(void)
Definition: spells.c:72
static unsigned long foreground
Definition: x11.c:187
void on_spell_invoke_clicked(GtkButton *button, gpointer user_data)
Definition: spells.c:427
Client_Player cpl
Definition: client.c:77
char message[10000]
Definition: client.h:253
static GtkWidget * spell_window
Definition: spells.c:48
Styles
Definition: inventory.c:68
struct Spell_struct * next
Definition: client.h:249
uint16 dam
Definition: client.h:261
#define MAX_BUF
Definition: client-types.h:128
Spell * spelldata
Definition: client.h:286
char name[256]
Definition: client.h:250
static GtkWidget * spell_treeview
Definition: spells.c:48
static int has_init
Definition: spells.c:63
uint32 attuned
Definition: client.h:233
uint16 sp
Definition: client.h:259
uint16 level
Definition: client.h:257
void update_spell_information(void)
Definition: spells.c:119
static gboolean spell_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata)
Definition: spells.c:104
static GtkListStore * spell_store
Definition: spells.c:50
static GtkStyle * spell_styles[Style_Last]
Definition: spells.c:61
#define FALSE
Definition: client-types.h:68
uint32 path
Definition: client.h:266
static GtkWidget * spell_invoke
Definition: spells.c:48
char * skill
Definition: client.h:264
static GtkWidget * spell_options
Definition: spells.c:48