Use macros instead of raw numbers for login type
[rofl0r-ixchat.git] / src / fe-gtk / chanview-tree.h
blob7f2a19ffb317fd4ea57ea6a63260dd0dc9fd94c6
1 /* file included in chanview.c */
3 typedef struct
5 GtkTreeView *tree;
6 GtkWidget *scrollw; /* scrolledWindow */
7 } treeview;
9 #include "../common/xchat.h"
10 #include "../common/xchatc.h"
11 #include "fe-gtk.h"
12 #include "maingui.h"
14 #include <gdk/gdk.h>
15 #include <gtk/gtktreeview.h>
17 static void /* row-activated, when a row is double clicked */
18 cv_tree_activated_cb (GtkTreeView *view, GtkTreePath *path,
19 GtkTreeViewColumn *column, gpointer data)
21 if (gtk_tree_view_row_expanded (view, path))
22 gtk_tree_view_collapse_row (view, path);
23 else
24 gtk_tree_view_expand_row (view, path, FALSE);
27 static void /* row selected callback */
28 cv_tree_sel_cb (GtkTreeSelection *sel, chanview *cv)
30 GtkTreeModel *model;
31 GtkTreeIter iter;
32 chan *ch;
34 if (gtk_tree_selection_get_selected (sel, &model, &iter))
36 gtk_tree_model_get (model, &iter, COL_CHAN, &ch, -1);
38 cv->focused = ch;
39 cv->cb_focus (cv, ch, ch->tag, ch->userdata);
43 static gboolean
44 cv_tree_click_cb (GtkTreeView *tree, GdkEventButton *event, chanview *cv)
46 chan *ch;
47 GtkTreeSelection *sel;
48 GtkTreePath *path;
49 GtkTreeIter iter;
50 int ret = FALSE;
52 if (event->button != 3 && event->state == 0)
53 return FALSE;
55 sel = gtk_tree_view_get_selection (tree);
56 if (gtk_tree_view_get_path_at_pos (tree, event->x, event->y, &path, 0, 0, 0))
58 if (event->button == 2)
60 gtk_tree_selection_unselect_all (sel);
61 gtk_tree_selection_select_path (sel, path);
63 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (cv->store), &iter, path))
65 gtk_tree_model_get (GTK_TREE_MODEL (cv->store), &iter, COL_CHAN, &ch, -1);
66 ret = cv->cb_contextmenu (cv, ch, ch->tag, ch->userdata, event);
68 gtk_tree_path_free (path);
70 return ret;
73 static void
74 cv_tree_init (chanview *cv)
76 GtkWidget *view, *win;
77 GtkCellRenderer *renderer;
78 static const GtkTargetEntry dnd_src_target[] =
80 {"XCHAT_CHANVIEW", GTK_TARGET_SAME_APP, 75 }
82 static const GtkTargetEntry dnd_dest_target[] =
84 {"XCHAT_USERLIST", GTK_TARGET_SAME_APP, 75 }
87 win = gtk_scrolled_window_new (0, 0);
88 /*gtk_container_set_border_width (GTK_CONTAINER (win), 1);*/
89 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (win),
90 GTK_SHADOW_IN);
91 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (win),
92 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
93 gtk_container_add (GTK_CONTAINER (cv->box), win);
94 gtk_widget_show (win);
96 view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (cv->store));
97 gtk_widget_set_name (view, "xchat-tree");
98 if (cv->style)
99 gtk_widget_set_style (view, cv->style);
100 /*gtk_widget_modify_base (view, GTK_STATE_NORMAL, &colors[COL_BG]);*/
101 GTK_WIDGET_UNSET_FLAGS (view, GTK_CAN_FOCUS);
102 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
104 if (!(prefs.gui_tweaks & 8))
105 gtk_tree_view_set_enable_tree_lines (GTK_TREE_VIEW (view), TRUE);
107 gtk_container_add (GTK_CONTAINER (win), view);
109 /* icon column */
110 if (cv->use_icons)
112 renderer = gtk_cell_renderer_pixbuf_new ();
113 if (prefs.gui_tweaks & 32)
114 g_object_set (G_OBJECT (renderer), "ypad", 0, NULL);
115 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
116 -1, NULL, renderer,
117 "pixbuf", COL_PIXBUF, NULL);
120 /* main column */
121 renderer = gtk_cell_renderer_text_new ();
122 if (prefs.gui_tweaks & 32)
123 g_object_set (G_OBJECT (renderer), "ypad", 0, NULL);
124 gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (renderer), 1);
125 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
126 -1, NULL, renderer,
127 "text", COL_NAME, "attributes", COL_ATTR, NULL);
129 g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (view))),
130 "changed", G_CALLBACK (cv_tree_sel_cb), cv);
131 g_signal_connect (G_OBJECT (view), "button-press-event",
132 G_CALLBACK (cv_tree_click_cb), cv);
133 g_signal_connect (G_OBJECT (view), "row-activated",
134 G_CALLBACK (cv_tree_activated_cb), NULL);
136 gtk_drag_dest_set (view, GTK_DEST_DEFAULT_ALL, dnd_dest_target, 1,
137 GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
138 gtk_drag_source_set (view, GDK_BUTTON1_MASK, dnd_src_target, 1, GDK_ACTION_COPY);
140 g_signal_connect (G_OBJECT (view), "drag_begin",
141 G_CALLBACK (mg_drag_begin_cb), NULL);
142 g_signal_connect (G_OBJECT (view), "drag_drop",
143 G_CALLBACK (mg_drag_drop_cb), NULL);
144 g_signal_connect (G_OBJECT (view), "drag_motion",
145 G_CALLBACK (mg_drag_motion_cb), NULL);
146 g_signal_connect (G_OBJECT (view), "drag_end",
147 G_CALLBACK (mg_drag_end_cb), NULL);
149 ((treeview *)cv)->tree = GTK_TREE_VIEW (view);
150 ((treeview *)cv)->scrollw = win;
151 gtk_widget_show (view);
154 static void
155 cv_tree_postinit (chanview *cv)
157 gtk_tree_view_expand_all (((treeview *)cv)->tree);
160 static void *
161 cv_tree_add (chanview *cv, chan *ch, char *name, GtkTreeIter *parent)
163 GtkTreePath *path;
165 if (parent)
167 /* expand the parent node */
168 path = gtk_tree_model_get_path (GTK_TREE_MODEL (cv->store), parent);
169 if (path)
171 gtk_tree_view_expand_row (((treeview *)cv)->tree, path, FALSE);
172 gtk_tree_path_free (path);
176 return NULL;
179 static void
180 cv_tree_change_orientation (chanview *cv)
184 static void
185 cv_tree_focus (chan *ch)
187 GtkTreeView *tree = ((treeview *)ch->cv)->tree;
188 GtkTreeModel *model = gtk_tree_view_get_model (tree);
189 GtkTreePath *path;
190 GtkTreeIter parent;
191 GdkRectangle cell_rect;
192 GdkRectangle vis_rect;
193 gint dest_y;
195 /* expand the parent node */
196 if (gtk_tree_model_iter_parent (model, &parent, &ch->iter))
198 path = gtk_tree_model_get_path (model, &parent);
199 if (path)
201 /*if (!gtk_tree_view_row_expanded (tree, path))
203 gtk_tree_path_free (path);
204 return;
206 gtk_tree_view_expand_row (tree, path, FALSE);
207 gtk_tree_path_free (path);
211 path = gtk_tree_model_get_path (model, &ch->iter);
212 if (path)
214 /* This full section does what
215 * gtk_tree_view_scroll_to_cell (tree, path, NULL, TRUE, 0.5, 0.5);
216 * does, except it only scrolls the window if the provided cell is
217 * not visible. Basic algorithm taken from gtktreeview.c */
219 /* obtain information to see if the cell is visible */
220 gtk_tree_view_get_background_area (tree, path, NULL, &cell_rect);
221 gtk_tree_view_get_visible_rect (tree, &vis_rect);
223 /* The cordinates aren't offset correctly */
224 gtk_tree_view_widget_to_tree_coords( tree, cell_rect.x, cell_rect.y, NULL, &cell_rect.y );
226 /* only need to scroll if out of bounds */
227 if (cell_rect.y < vis_rect.y ||
228 cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
230 dest_y = cell_rect.y - ((vis_rect.height - cell_rect.height) * 0.5);
231 if (dest_y < 0)
232 dest_y = 0;
233 gtk_tree_view_scroll_to_point (tree, -1, dest_y);
235 /* theft done, now make it focused like */
236 gtk_tree_view_set_cursor (tree, path, NULL, FALSE);
237 gtk_tree_path_free (path);
241 static void
242 cv_tree_move_focus (chanview *cv, gboolean relative, int num)
244 chan *ch;
246 if (relative)
248 num += cv_find_number_of_chan (cv, cv->focused);
249 num %= cv->size;
250 /* make it wrap around at both ends */
251 if (num < 0)
252 num = cv->size - 1;
255 ch = cv_find_chan_by_number (cv, num);
256 if (ch)
257 cv_tree_focus (ch);
260 static void
261 cv_tree_remove (chan *ch)
265 static void
266 move_row (chan *ch, int delta, GtkTreeIter *parent)
268 GtkTreeStore *store = ch->cv->store;
269 GtkTreeIter *src = &ch->iter;
270 GtkTreeIter dest = ch->iter;
271 GtkTreePath *dest_path;
273 if (delta < 0) /* down */
275 if (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &dest))
276 gtk_tree_store_swap (store, src, &dest);
277 else /* move to top */
278 gtk_tree_store_move_after (store, src, NULL);
280 } else
282 dest_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &dest);
283 if (gtk_tree_path_prev (dest_path))
285 gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &dest, dest_path);
286 gtk_tree_store_swap (store, src, &dest);
287 } else
288 { /* move to bottom */
289 gtk_tree_store_move_before (store, src, NULL);
292 gtk_tree_path_free (dest_path);
296 static void
297 cv_tree_move (chan *ch, int delta)
299 GtkTreeIter parent;
301 /* do nothing if this is a server row */
302 if (gtk_tree_model_iter_parent (GTK_TREE_MODEL (ch->cv->store), &parent, &ch->iter))
303 move_row (ch, delta, &parent);
306 static void
307 cv_tree_move_family (chan *ch, int delta)
309 move_row (ch, delta, NULL);
312 static void
313 cv_tree_cleanup (chanview *cv)
315 if (cv->box)
316 /* kill the scrolled window */
317 gtk_widget_destroy (((treeview *)cv)->scrollw);
320 static void
321 cv_tree_set_color (chan *ch, PangoAttrList *list)
323 /* nothing to do, it's already set in the store */
326 static void
327 cv_tree_rename (chan *ch, char *name)
329 /* nothing to do, it's already renamed in the store */
332 static chan *
333 cv_tree_get_parent (chan *ch)
335 chan *parent_ch = NULL;
336 GtkTreeIter parent;
338 if (gtk_tree_model_iter_parent (GTK_TREE_MODEL (ch->cv->store), &parent, &ch->iter))
340 gtk_tree_model_get (GTK_TREE_MODEL (ch->cv->store), &parent, COL_CHAN, &parent_ch, -1);
343 return parent_ch;
346 static gboolean
347 cv_tree_is_collapsed (chan *ch)
349 chan *parent = cv_tree_get_parent (ch);
350 GtkTreePath *path = NULL;
351 gboolean ret;
353 if (parent == NULL)
354 return FALSE;
356 path = gtk_tree_model_get_path (GTK_TREE_MODEL (parent->cv->store),
357 &parent->iter);
358 ret = !gtk_tree_view_row_expanded (((treeview *)parent->cv)->tree, path);
359 gtk_tree_path_free (path);
361 return ret;