/*
* Copyright (c) by Allin Cottrell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* treeutils.c for gretl */
#include "gretl.h"
#include "treeutils.h"
#include "datafiles.h"
/* these live in dialogs.c */
extern GtkWidget *active_edit_id;
extern GtkWidget *active_edit_name;
extern GtkWidget *active_edit_text;
static gint list_alpha_compare (GtkTreeModel *model,
GtkTreeIter *a, GtkTreeIter *b,
gpointer p)
{
gchar *vname_a, *vname_b;
gint ret;
gtk_tree_model_get(model, a, 1, &vname_a, -1);
gtk_tree_model_get(model, b, 1, &vname_b, -1);
if (strcmp(vname_a, "const") == 0) {
ret = 0;
} else if (strcmp(vname_b, "const") == 0) {
ret = 1;
} else {
ret = strcmp(vname_a, vname_b);
}
g_free(vname_a);
g_free(vname_b);
return ret;
}
static gint list_id_compare (GtkTreeModel *model,
GtkTreeIter *a, GtkTreeIter *b,
gpointer p)
{
gchar *vnum_a, *vnum_b;
gint ret;
gtk_tree_model_get(model, a, 0, &vnum_a, -1);
gtk_tree_model_get(model, b, 0, &vnum_b, -1);
ret = strcmp(vnum_a, vnum_b);
g_free(vnum_a);
g_free(vnum_b);
return ret;
}
static gboolean no_select_row_zero (GtkTreeSelection *selection,
GtkTreeModel *model,
GtkTreePath *path,
gboolean path_currently_selected,
gpointer data)
{
if (tree_path_get_row_number(path) == 0) {
return FALSE;
}
return TRUE;
}
static void my_gtk_entry_append_text (GtkEntry *entry, gchar *add)
{
const gchar *old = gtk_entry_get_text(entry);
gchar *new = g_strdup_printf("%s%s", old, add);
gtk_entry_set_text(entry, new);
gtk_editable_set_position(GTK_EDITABLE(entry), -1);
g_free(new);
}
static void update_dialogs_from_varclick (int active_var)
{
const gchar *edttext;
if (active_edit_id != NULL) {
gchar addvar[9];
edttext = gtk_entry_get_text(GTK_ENTRY(active_edit_id));
if (*edttext != '\0') {
sprintf(addvar, " %d", active_var);
} else {
sprintf(addvar, "%d", active_var);
}
my_gtk_entry_append_text(GTK_ENTRY(active_edit_id), addvar);
} else if (active_edit_name != NULL) {
edttext = gtk_entry_get_text(GTK_ENTRY(active_edit_name));
my_gtk_entry_append_text(GTK_ENTRY(active_edit_name),
datainfo->varname[active_var]);
} else if (active_edit_text != NULL) {
GtkTextBuffer *tbuf;
tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(active_edit_text));
if (tbuf != NULL) {
gtk_text_buffer_insert_at_cursor(tbuf,
datainfo->varname[active_var],
-1);
}
}
}
gboolean main_varclick (GtkWidget *widget, GdkEventButton *event,
windata_t *win)
{
GtkTreeView *view = GTK_TREE_VIEW(win->listbox);
GtkTreePath *path;
gint row = 0;
if (gtk_tree_view_get_path_at_pos(view, event->x, event->y, &path,
NULL, NULL, NULL)) {
row = tree_path_get_row_number(path);
if (row != 0) {
gchar *varnum;
g_object_set_data(G_OBJECT(win->listbox), "active_row",
GINT_TO_POINTER(row));
tree_view_get_string(view, row, 0, &varnum);
win->active_var = atoi(varnum);
g_free(varnum);
update_dialogs_from_varclick(win->active_var);
}
gtk_tree_path_free(path);
} else {
/* clicked below the lines representing variables */
return FALSE;
}
return (row == 0);
}
static void
bool_col_toggled (GtkCellRendererToggle *cell, gchar *path_str, windata_t *vwin)
{
GtkTreeView *treeview = GTK_TREE_VIEW(vwin->listbox);
GtkTreeModel *model = gtk_tree_view_get_model(treeview);
GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
GtkTreeIter iter;
gboolean val;
gint col;
col = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(vwin->w), "boolcol"));
gtk_tree_model_get_iter(model, &iter, path);
gtk_tree_model_get(model, &iter, col, &val, -1);
if (val) {
return;
}
if (vwin->role == FUNC_FILES) {
vwin->active_var = atoi(path_str);
browser_load_func(NULL, vwin);
}
gtk_list_store_set(GTK_LIST_STORE(model), &iter, col, TRUE, -1);
gtk_tree_path_free(path);
}
static gint tree_store_go_to (windata_t *vwin, int k)
{
GtkTreeView *view = GTK_TREE_VIEW(vwin->listbox);
GtkTreeModel *model = gtk_tree_view_get_model(view);
GtkTreePath *path = NULL;
GtkTreeIter iter;
int rows;
if (!gtk_tree_model_get_iter_first(model, &iter)) {
return FALSE;
}
if (vwin == mdata && !gtk_tree_model_iter_next(model, &iter)) {
return FALSE;
}
if (k == GDK_Home) {
path = gtk_tree_model_get_path(model, &iter);
} else if (k == GDK_End) {
rows = gtk_tree_model_iter_n_children(model, NULL);
path = gtk_tree_path_new_from_indices(rows - 1, -1);
} else {
/* page up/down */
GdkRectangle r;
gint wx, wy;
gtk_tree_view_get_visible_rect(view, &r);
if (k == GDK_Page_Down) {
gtk_tree_view_tree_to_widget_coords(view, r.x, r.y + r.height,
&wx, &wy);
gtk_tree_view_get_path_at_pos(view, wx, wy, &path,
NULL, NULL, NULL);
if (path == NULL) {
rows = gtk_tree_model_iter_n_children(model, NULL);
path = gtk_tree_path_new_from_indices(rows - 1, -1);
}
gtk_tree_view_scroll_to_cell(view, path, NULL,
TRUE, 0.0, 0.0);
} else {
gtk_tree_view_tree_to_widget_coords(view, r.x, r.y,
&wx, &wy);
gtk_tree_view_get_path_at_pos(view, wx, wy, &path,
NULL, NULL, NULL);
gtk_tree_view_scroll_to_cell(view, path, NULL,
TRUE, 1.0, 0.0);
if (vwin == mdata && r.y == 0) {
gtk_tree_path_free(path);
path = gtk_tree_path_new_from_indices(1, -1);
}
}
}
if (path != NULL) {
gtk_tree_view_set_cursor(view, path, NULL, FALSE);
gtk_tree_path_free(path);
}
return TRUE;
}
static gint catch_listbox_key (GtkWidget *w, GdkEventKey *key, windata_t *vwin)
{
int k = key->keyval;
if (k == GDK_q) {
/* Q = quit */
if (vwin != mdata) {
gtk_widget_destroy(vwin->w);
}
return TRUE;
} else if (k == GDK_f) {
/* F = find */
GdkModifierType mods;
if (vwin == mdata && !data_status) {
return TRUE;
}
gdk_window_get_pointer(w->window, NULL, NULL, &mods);
if (mods & GDK_CONTROL_MASK) {
menu_find(vwin, 1, NULL);
return TRUE;
}
} else if (k == GDK_Home || k == GDK_End ||
k == GDK_Page_Up || k == GDK_Page_Down) {
/* motion keys not supported by default */
return tree_store_go_to(vwin, k);
}
return FALSE;
}
void vwin_add_list_box (windata_t *vwin, GtkBox *box,
int ncols, gboolean hidden_col,
GType *types, const char **titles,
int tree)
{
GtkListStore *lstore = NULL;
GtkTreeStore *tstore = NULL;
GtkWidget *view, *scroller;
GtkCellRenderer *renderer;
GtkCellRenderer *bool_renderer = NULL;
GtkTreeViewColumn *column;
GtkTreeSelection *select;
int i, viscols = ncols;
if (hidden_col) {
viscols--;
}
if (tree) {
tstore = gtk_tree_store_newv(ncols, types);
vwin->listbox = view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(tstore));
g_object_unref(G_OBJECT(tstore));
} else {
lstore = gtk_list_store_newv(ncols, types);
vwin->listbox = view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(lstore));
g_object_unref(G_OBJECT(lstore));
}
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);
renderer = gtk_cell_renderer_text_new();
g_object_set(renderer, "ypad", 0, NULL);
for (i=0; i<viscols; i++) {
if (types[i] == G_TYPE_BOOLEAN) {
bool_renderer = gtk_cell_renderer_toggle_new();
g_object_set_data(G_OBJECT(vwin->w), "boolcol", GINT_TO_POINTER(i));
g_signal_connect(bool_renderer, "toggled",
G_CALLBACK(bool_col_toggled), vwin);
column = gtk_tree_view_column_new_with_attributes(_(titles[i]),
bool_renderer,
"active", i,
NULL);
#if 1
gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_fixed_width(GTK_TREE_VIEW_COLUMN(column), 50);
#endif
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
} else {
column = gtk_tree_view_column_new_with_attributes(_(titles[i]),
renderer,
"text", i,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
if (vwin != mdata) {
g_object_set(G_OBJECT(column), "resizable", TRUE, NULL);
}
}
}
if (hidden_col) {
column = gtk_tree_view_column_new_with_attributes(NULL,
renderer,
"text", i,
NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
gtk_tree_view_column_set_visible(column, FALSE);
}
/* set the selection properties on the tree view */
select = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
if (vwin == mdata) {
/* gretl main window */
gtk_tree_selection_set_mode(select, GTK_SELECTION_EXTENDED);
gtk_tree_selection_set_select_function(select,
(GtkTreeSelectionFunc)
no_select_row_zero,
NULL, NULL);
gtk_widget_set_events(view, GDK_POINTER_MOTION_MASK
| GDK_POINTER_MOTION_HINT_MASK);
g_signal_connect(G_OBJECT(view), "motion_notify_event",
G_CALLBACK(listbox_drag), NULL);
} else {
gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
g_signal_connect(G_OBJECT(select), "changed",
G_CALLBACK(listbox_select_row),
vwin);
}
g_signal_connect(G_OBJECT(view), "key_press_event",
G_CALLBACK(catch_listbox_key),
vwin);
g_signal_connect(G_OBJECT(view), "button_press_event",
G_CALLBACK(listbox_double_click),
vwin);
/* set sort properties on the tree model */
if (tstore != NULL) {
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(tstore), 0,
(GtkTreeIterCompareFunc)
list_id_compare,
NULL, NULL);
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(tstore), 1,
(GtkTreeIterCompareFunc)
list_alpha_compare,
NULL, NULL);
}
scroller = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroller),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroller),
GTK_SHADOW_IN);
gtk_container_add(GTK_CONTAINER(scroller), view);
gtk_box_pack_start(box, scroller, TRUE, TRUE, TRUE);
gtk_widget_show(view);
gtk_widget_show(scroller);
}
void tree_view_get_string (GtkTreeView *view, int row, int col, gchar **val)
{
GtkTreeModel *model;
GtkTreeIter iter;
gchar *path;
model = gtk_tree_view_get_model(view);
path = g_strdup_printf("%d", row);
gtk_tree_model_get_iter_from_string(model, &iter, path);
gtk_tree_model_get(model, &iter, col, val, -1);
g_free(path);
}
void tree_view_get_int (GtkTreeView *view, int row, int col, int *val)
{
GtkTreeModel *model;
GtkTreeIter iter;
gchar *path;
model = gtk_tree_view_get_model(view);
path = g_strdup_printf("%d", row);
gtk_tree_model_get_iter_from_string(model, &iter, path);
gtk_tree_model_get(model, &iter, col, val, -1);
g_free(path);
}
int tree_path_get_row_number (GtkTreePath *path)
{
return gtk_tree_path_get_indices(path)[0];
}
static void add_to_selection_count (GtkTreeModel *model, GtkTreePath *path,
GtkTreeIter *iter, int *count)
{
*count += 1;
}
static void add_to_selection_list (GtkTreeModel *model, GtkTreePath *path,
GtkTreeIter *iter, int *list)
{
gchar *varnum = NULL;
gtk_tree_model_get(model, iter, 0, &varnum, -1);
list[0] += 1;
list[list[0]] = atoi(varnum);
g_free(varnum);
}
int *main_window_selection_as_list (void)
{
GtkTreeSelection *select;
int *list = NULL;
int scount = 0;
select = gtk_tree_view_get_selection(GTK_TREE_VIEW(mdata->listbox));
gtk_tree_selection_selected_foreach(select,
(GtkTreeSelectionForeachFunc)
add_to_selection_count,
&scount);
if (scount > 0) {
list = gretl_list_new(scount);
}
if (list != NULL) {
list[0] = 0;
gtk_tree_selection_selected_foreach(select,
(GtkTreeSelectionForeachFunc)
add_to_selection_list,
list);
}
return list;
}
syntax highlighted by Code2HTML, v. 0.9.1