1 /* file included in chanview.c */
6 GtkWidget
*scrollw
; /* scrolledWindow */
9 #include "../common/xchat.h"
10 #include "../common/xchatc.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
);
24 gtk_tree_view_expand_row (view
, path
, FALSE
);
27 static void /* row selected callback */
28 cv_tree_sel_cb (GtkTreeSelection
*sel
, chanview
*cv
)
34 if (gtk_tree_selection_get_selected (sel
, &model
, &iter
))
36 gtk_tree_model_get (model
, &iter
, COL_CHAN
, &ch
, -1);
39 cv
->cb_focus (cv
, ch
, ch
->tag
, ch
->userdata
);
44 cv_tree_click_cb (GtkTreeView
*tree
, GdkEventButton
*event
, chanview
*cv
)
47 GtkTreeSelection
*sel
;
52 if (event
->button
!= 3 && event
->state
== 0)
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
);
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
),
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");
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
);
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
),
117 "pixbuf", COL_PIXBUF
, NULL
);
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
),
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
);
155 cv_tree_postinit (chanview
*cv
)
157 gtk_tree_view_expand_all (((treeview
*)cv
)->tree
);
161 cv_tree_add (chanview
*cv
, chan
*ch
, char *name
, GtkTreeIter
*parent
)
167 /* expand the parent node */
168 path
= gtk_tree_model_get_path (GTK_TREE_MODEL (cv
->store
), parent
);
171 gtk_tree_view_expand_row (((treeview
*)cv
)->tree
, path
, FALSE
);
172 gtk_tree_path_free (path
);
180 cv_tree_change_orientation (chanview
*cv
)
185 cv_tree_focus (chan
*ch
)
187 GtkTreeView
*tree
= ((treeview
*)ch
->cv
)->tree
;
188 GtkTreeModel
*model
= gtk_tree_view_get_model (tree
);
191 GdkRectangle cell_rect
;
192 GdkRectangle vis_rect
;
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
);
201 /*if (!gtk_tree_view_row_expanded (tree, path))
203 gtk_tree_path_free (path);
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
);
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);
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
);
242 cv_tree_move_focus (chanview
*cv
, gboolean relative
, int num
)
248 num
+= cv_find_number_of_chan (cv
, cv
->focused
);
250 /* make it wrap around at both ends */
255 ch
= cv_find_chan_by_number (cv
, num
);
261 cv_tree_remove (chan
*ch
)
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
);
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
);
288 { /* move to bottom */
289 gtk_tree_store_move_before (store
, src
, NULL
);
292 gtk_tree_path_free (dest_path
);
297 cv_tree_move (chan
*ch
, int delta
)
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
);
307 cv_tree_move_family (chan
*ch
, int delta
)
309 move_row (ch
, delta
, NULL
);
313 cv_tree_cleanup (chanview
*cv
)
316 /* kill the scrolled window */
317 gtk_widget_destroy (((treeview
*)cv
)->scrollw
);
321 cv_tree_set_color (chan
*ch
, PangoAttrList
*list
)
323 /* nothing to do, it's already set in the store */
327 cv_tree_rename (chan
*ch
, char *name
)
329 /* nothing to do, it's already renamed in the store */
333 cv_tree_get_parent (chan
*ch
)
335 chan
*parent_ch
= NULL
;
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);
347 cv_tree_is_collapsed (chan
*ch
)
349 chan
*parent
= cv_tree_get_parent (ch
);
350 GtkTreePath
*path
= NULL
;
356 path
= gtk_tree_model_get_path (GTK_TREE_MODEL (parent
->cv
->store
),
358 ret
= !gtk_tree_view_row_expanded (((treeview
*)parent
->cv
)->tree
, path
);
359 gtk_tree_path_free (path
);