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
);
141 g_signal_connect (G_OBJECT (view
), "drag_begin",
142 G_CALLBACK (mg_drag_begin_cb
), NULL
);
143 g_signal_connect (G_OBJECT (view
), "drag_drop",
144 G_CALLBACK (mg_drag_drop_cb
), NULL
);
145 g_signal_connect (G_OBJECT (view
), "drag_motion",
146 G_CALLBACK (mg_drag_motion_cb
), NULL
);
147 g_signal_connect (G_OBJECT (view
), "drag_end",
148 G_CALLBACK (mg_drag_end_cb
), NULL
);
151 ((treeview
*)cv
)->tree
= GTK_TREE_VIEW (view
);
152 ((treeview
*)cv
)->scrollw
= win
;
153 gtk_widget_show (view
);
157 cv_tree_postinit (chanview
*cv
)
159 gtk_tree_view_expand_all (((treeview
*)cv
)->tree
);
163 cv_tree_add (chanview
*cv
, chan
*ch
, char *name
, GtkTreeIter
*parent
)
169 /* expand the parent node */
170 path
= gtk_tree_model_get_path (GTK_TREE_MODEL (cv
->store
), parent
);
173 gtk_tree_view_expand_row (((treeview
*)cv
)->tree
, path
, FALSE
);
174 gtk_tree_path_free (path
);
182 cv_tree_change_orientation (chanview
*cv
)
187 cv_tree_focus (chan
*ch
)
189 GtkTreeView
*tree
= ((treeview
*)ch
->cv
)->tree
;
190 GtkTreeModel
*model
= gtk_tree_view_get_model (tree
);
193 GdkRectangle cell_rect
;
194 GdkRectangle vis_rect
;
197 /* expand the parent node */
198 if (gtk_tree_model_iter_parent (model
, &parent
, &ch
->iter
))
200 path
= gtk_tree_model_get_path (model
, &parent
);
203 /*if (!gtk_tree_view_row_expanded (tree, path))
205 gtk_tree_path_free (path);
208 gtk_tree_view_expand_row (tree
, path
, FALSE
);
209 gtk_tree_path_free (path
);
213 path
= gtk_tree_model_get_path (model
, &ch
->iter
);
216 /* This full section does what
217 * gtk_tree_view_scroll_to_cell (tree, path, NULL, TRUE, 0.5, 0.5);
218 * does, except it only scrolls the window if the provided cell is
219 * not visible. Basic algorithm taken from gtktreeview.c */
221 /* obtain information to see if the cell is visible */
222 gtk_tree_view_get_background_area (tree
, path
, NULL
, &cell_rect
);
223 gtk_tree_view_get_visible_rect (tree
, &vis_rect
);
225 /* The cordinates aren't offset correctly */
226 gtk_tree_view_widget_to_tree_coords( tree
, cell_rect
.x
, cell_rect
.y
, NULL
, &cell_rect
.y
);
228 /* only need to scroll if out of bounds */
229 if (cell_rect
.y
< vis_rect
.y
||
230 cell_rect
.y
+ cell_rect
.height
> vis_rect
.y
+ vis_rect
.height
)
232 dest_y
= cell_rect
.y
- ((vis_rect
.height
- cell_rect
.height
) * 0.5);
235 gtk_tree_view_scroll_to_point (tree
, -1, dest_y
);
237 /* theft done, now make it focused like */
238 gtk_tree_view_set_cursor (tree
, path
, NULL
, FALSE
);
239 gtk_tree_path_free (path
);
244 cv_tree_move_focus (chanview
*cv
, gboolean relative
, int num
)
250 num
+= cv_find_number_of_chan (cv
, cv
->focused
);
252 /* make it wrap around at both ends */
257 ch
= cv_find_chan_by_number (cv
, num
);
263 cv_tree_remove (chan
*ch
)
268 move_row (chan
*ch
, int delta
, GtkTreeIter
*parent
)
270 GtkTreeStore
*store
= ch
->cv
->store
;
271 GtkTreeIter
*src
= &ch
->iter
;
272 GtkTreeIter dest
= ch
->iter
;
273 GtkTreePath
*dest_path
;
275 if (delta
< 0) /* down */
277 if (gtk_tree_model_iter_next (GTK_TREE_MODEL (store
), &dest
))
278 gtk_tree_store_swap (store
, src
, &dest
);
279 else /* move to top */
280 gtk_tree_store_move_after (store
, src
, NULL
);
284 dest_path
= gtk_tree_model_get_path (GTK_TREE_MODEL (store
), &dest
);
285 if (gtk_tree_path_prev (dest_path
))
287 gtk_tree_model_get_iter (GTK_TREE_MODEL (store
), &dest
, dest_path
);
288 gtk_tree_store_swap (store
, src
, &dest
);
290 { /* move to bottom */
291 gtk_tree_store_move_before (store
, src
, NULL
);
294 gtk_tree_path_free (dest_path
);
299 cv_tree_move (chan
*ch
, int delta
)
303 /* do nothing if this is a server row */
304 if (gtk_tree_model_iter_parent (GTK_TREE_MODEL (ch
->cv
->store
), &parent
, &ch
->iter
))
305 move_row (ch
, delta
, &parent
);
309 cv_tree_move_family (chan
*ch
, int delta
)
311 move_row (ch
, delta
, NULL
);
315 cv_tree_cleanup (chanview
*cv
)
318 /* kill the scrolled window */
319 gtk_widget_destroy (((treeview
*)cv
)->scrollw
);
323 cv_tree_set_color (chan
*ch
, PangoAttrList
*list
)
325 /* nothing to do, it's already set in the store */
329 cv_tree_rename (chan
*ch
, char *name
)
331 /* nothing to do, it's already renamed in the store */
335 cv_tree_get_parent (chan
*ch
)
337 chan
*parent_ch
= NULL
;
340 if (gtk_tree_model_iter_parent (GTK_TREE_MODEL (ch
->cv
->store
), &parent
, &ch
->iter
))
342 gtk_tree_model_get (GTK_TREE_MODEL (ch
->cv
->store
), &parent
, COL_CHAN
, &parent_ch
, -1);
349 cv_tree_is_collapsed (chan
*ch
)
351 chan
*parent
= cv_tree_get_parent (ch
);
352 GtkTreePath
*path
= NULL
;
358 path
= gtk_tree_model_get_path (GTK_TREE_MODEL (parent
->cv
->store
),
360 ret
= !gtk_tree_view_row_expanded (((treeview
*)parent
->cv
)->tree
, path
);
361 gtk_tree_path_free (path
);