284 lines
8.8 KiB
C
284 lines
8.8 KiB
C
/***************************************************************************
|
|
* Copyright (C) 04/2008 by Olaf Rempel *
|
|
* razzor@kopf-tisch.de *
|
|
* *
|
|
* 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; version 2 of the License *
|
|
* *
|
|
* 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. *
|
|
***************************************************************************/
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "tdc_store.h"
|
|
#include "tdc_parser.h"
|
|
#include "tdc_proto.h"
|
|
|
|
#include "gui_graph_tab.h"
|
|
|
|
enum {
|
|
COL_ID = 0, /* UINT */
|
|
COL_GRAPH, /* BOOLEAN */
|
|
COL_VALUE, /* POINTER to var */
|
|
COL_VALUE_EDIT, /* BOOLEAN */
|
|
COL_TYPE, /* STRING */
|
|
COL_NAME, /* STRING */
|
|
};
|
|
|
|
static GtkListStore *list_store;
|
|
|
|
static int viewmode = 0;
|
|
static int sortmode = GTK_SORT_ASCENDING;
|
|
static struct tdc_var *current_edited_var;
|
|
|
|
static void cell_graph_toggle(GtkCellRendererToggle *cell,
|
|
gchar *path_string,
|
|
gpointer user_data)
|
|
{
|
|
GtkTreeIter it;
|
|
gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(user_data), &it, path_string);
|
|
|
|
gboolean toggle;
|
|
struct tdc_var *var;
|
|
|
|
gtk_tree_model_get(GTK_TREE_MODEL(user_data), &it,
|
|
COL_GRAPH, &toggle,
|
|
COL_VALUE, &var,
|
|
-1);
|
|
|
|
if (var->flags & TDC_GUI_GRAPH) {
|
|
var->flags &= ~TDC_GUI_GRAPH;
|
|
|
|
if (var->privdata_graphtab != NULL)
|
|
gui_graphtab_remove_var(var);
|
|
|
|
} else {
|
|
if (var->privdata_graphtab == NULL)
|
|
/* bailout if no new graph allowed */
|
|
if (gui_graphtab_add_var(var) < 0)
|
|
return;
|
|
|
|
var->flags |= TDC_GUI_GRAPH;
|
|
}
|
|
|
|
// FIXME: assuming board 1
|
|
tdcstore_graph_refresh(1, -1);
|
|
|
|
gtk_list_store_set(GTK_LIST_STORE(user_data), &it,
|
|
COL_GRAPH, !toggle,
|
|
-1);
|
|
}
|
|
|
|
static gboolean header_toggle_update(GtkTreeModel *model,
|
|
GtkTreePath *path,
|
|
GtkTreeIter *iter,
|
|
gpointer data)
|
|
{
|
|
gtk_tree_model_row_changed(model, path, iter);
|
|
return FALSE;
|
|
}
|
|
|
|
static void value_edit_started(GtkCellRenderer *renderer,
|
|
GtkCellEditable *editable,
|
|
gchar *path,
|
|
gpointer user_data)
|
|
{
|
|
GtkTreeIter it;
|
|
gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(list_store), &it, path);
|
|
gtk_tree_model_get(GTK_TREE_MODEL(list_store), &it, COL_VALUE, ¤t_edited_var, -1);
|
|
}
|
|
|
|
static void value_edit_canceled(GtkCellRenderer *renderer, gpointer user_data)
|
|
{
|
|
current_edited_var = NULL;
|
|
}
|
|
|
|
static void value_edit_done(GtkCellRendererText *cell,
|
|
gchar *path,
|
|
gchar *text,
|
|
gpointer user_data)
|
|
{
|
|
GtkTreeIter it;
|
|
gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(list_store), &it, path);
|
|
|
|
struct tdc_var *var;
|
|
gtk_tree_model_get(GTK_TREE_MODEL(list_store), &it, COL_VALUE, &var, -1);
|
|
|
|
if (tdcvar_parse_value(var, text) >= 0) {
|
|
// FIXME: assuming board 1
|
|
tdcparser_send_setvalue(1, var->id);
|
|
}
|
|
|
|
current_edited_var = NULL;
|
|
}
|
|
|
|
static gint sort_by_name_func(GtkTreeModel *model,
|
|
GtkTreeIter *a,
|
|
GtkTreeIter *b,
|
|
gpointer userdata)
|
|
{
|
|
gint ret = 0;
|
|
|
|
gchar *name1, *name2;
|
|
gtk_tree_model_get(model, a, COL_NAME, &name1, -1);
|
|
gtk_tree_model_get(model, b, COL_NAME, &name2, -1);
|
|
|
|
if (name1 == NULL || name2 == NULL) {
|
|
if (name1 != NULL || name2 != NULL)
|
|
ret = (name1 == NULL) ? -1 : 1;
|
|
|
|
} else {
|
|
ret = g_utf8_collate(name1, name2);
|
|
}
|
|
|
|
g_free(name1);
|
|
g_free(name2);
|
|
return ret;
|
|
}
|
|
|
|
static void header_name_toggle(GtkTreeViewColumn *treeviewcolumn,
|
|
gpointer user_data)
|
|
{
|
|
sortmode = (sortmode == GTK_SORT_ASCENDING) ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING;
|
|
|
|
GtkTreeSortable *sortable = GTK_TREE_SORTABLE(list_store);
|
|
gtk_tree_sortable_set_sort_func(sortable, COL_NAME, sort_by_name_func, NULL, NULL);
|
|
gtk_tree_sortable_set_sort_column_id(sortable, COL_NAME, sortmode);
|
|
}
|
|
|
|
static void header_value_toggle(GtkTreeViewColumn *treeviewcolumn,
|
|
gpointer user_data)
|
|
{
|
|
viewmode = (viewmode +1) & 0x01;
|
|
gtk_tree_model_foreach(GTK_TREE_MODEL(list_store), header_toggle_update, NULL);
|
|
}
|
|
|
|
static void cell_value_func(GtkTreeViewColumn *column,
|
|
GtkCellRenderer *cell,
|
|
GtkTreeModel *model,
|
|
GtkTreeIter *iter,
|
|
gpointer data)
|
|
{
|
|
struct tdc_var *var;
|
|
gtk_tree_model_get(model, iter, COL_VALUE, &var, -1);
|
|
|
|
char buf[32];
|
|
tdcvar_get_value(var, buf, sizeof(buf), viewmode);
|
|
g_object_set(cell, "text", buf, NULL);
|
|
}
|
|
|
|
gint gui_vartab_init(GtkNotebook *notebook)
|
|
{
|
|
list_store = gtk_list_store_new(6,
|
|
G_TYPE_UINT, G_TYPE_BOOLEAN,
|
|
G_TYPE_POINTER, G_TYPE_BOOLEAN,
|
|
G_TYPE_STRING, G_TYPE_STRING);
|
|
|
|
GtkTreeSortable *sortable = GTK_TREE_SORTABLE(list_store);
|
|
gtk_tree_sortable_set_sort_func(sortable, COL_NAME, sort_by_name_func, NULL, NULL);
|
|
gtk_tree_sortable_set_sort_column_id(sortable, COL_NAME, sortmode);
|
|
|
|
GtkWidget *view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store));
|
|
g_object_unref(list_store);
|
|
gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(view), GTK_TREE_VIEW_GRID_LINES_VERTICAL);
|
|
|
|
GtkTreeViewColumn *col;
|
|
GtkCellRenderer *renderer;
|
|
|
|
col = gtk_tree_view_column_new();
|
|
gtk_tree_view_column_set_title(col, "Graph");
|
|
gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
|
|
renderer = gtk_cell_renderer_toggle_new();
|
|
g_object_set(renderer, "activatable", TRUE, NULL);
|
|
g_signal_connect(renderer, "toggled", (GCallback)cell_graph_toggle, list_store);
|
|
gtk_tree_view_column_pack_start(col, renderer, FALSE);
|
|
gtk_tree_view_column_add_attribute(col, renderer, "active", COL_GRAPH);
|
|
|
|
col = gtk_tree_view_column_new();
|
|
gtk_tree_view_column_set_title(col, "Value");
|
|
gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
|
|
g_object_set(col, "clickable", TRUE, NULL);
|
|
g_signal_connect(col, "clicked", (GCallback)header_value_toggle, NULL);
|
|
renderer = gtk_cell_renderer_text_new();
|
|
g_signal_connect(renderer, "edited", (GCallback)value_edit_done, NULL);
|
|
g_signal_connect(renderer, "editing-started", (GCallback)value_edit_started, NULL);
|
|
g_signal_connect(renderer, "editing-canceled", (GCallback)value_edit_canceled, NULL);
|
|
|
|
gtk_tree_view_column_pack_start(col, renderer, FALSE);
|
|
gtk_tree_view_column_add_attribute(col, renderer, "editable", COL_VALUE_EDIT);
|
|
gtk_tree_view_column_set_cell_data_func(col, renderer, cell_value_func, NULL, NULL);
|
|
|
|
col = gtk_tree_view_column_new();
|
|
gtk_tree_view_column_set_title(col, "Type");
|
|
gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
|
|
renderer = gtk_cell_renderer_text_new();
|
|
gtk_tree_view_column_pack_start(col, renderer, FALSE);
|
|
gtk_tree_view_column_add_attribute(col, renderer, "text", COL_TYPE);
|
|
|
|
col = gtk_tree_view_column_new();
|
|
gtk_tree_view_column_set_title(col, "Name");
|
|
gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
|
|
g_object_set(col, "clickable", TRUE, NULL);
|
|
g_signal_connect(col, "clicked", (GCallback)header_name_toggle, NULL);
|
|
renderer = gtk_cell_renderer_text_new();
|
|
gtk_tree_view_column_pack_start(col, renderer, FALSE);
|
|
gtk_tree_view_column_add_attribute(col, renderer, "text", COL_NAME);
|
|
|
|
GtkWidget *scrollbar = gtk_scrolled_window_new(NULL, NULL);
|
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbar), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
|
gtk_container_add(GTK_CONTAINER(scrollbar), view);
|
|
|
|
GtkWidget *label = gtk_label_new(" Variables ");
|
|
return gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrollbar, label);
|
|
}
|
|
|
|
void gui_vartab_add_var(struct tdc_var *var)
|
|
{
|
|
GtkTreeIter it;
|
|
gtk_list_store_append(list_store, &it);
|
|
|
|
char typestr[32];
|
|
tdcvar_get_type(var, typestr, sizeof(typestr));
|
|
|
|
gtk_list_store_set(list_store, &it,
|
|
COL_ID, var->id,
|
|
COL_GRAPH, FALSE,
|
|
COL_VALUE, var,
|
|
COL_VALUE_EDIT, !(var->flags & TDC_READONLY),
|
|
COL_TYPE, typestr,
|
|
COL_NAME, var->name,
|
|
-1);
|
|
|
|
var->privdata_vartab = gtk_tree_iter_copy(&it);
|
|
}
|
|
|
|
int gui_vartab_update_var(struct tdc_var *var)
|
|
{
|
|
// TODO: update even in graph mode every xxx ms
|
|
if (var == current_edited_var || (var->flags & TDC_GUI_GRAPH))
|
|
return 0;
|
|
|
|
/* do a dummy write to update cells */
|
|
GtkTreeIter *it = (GtkTreeIter *)var->privdata_vartab;
|
|
gtk_list_store_set(list_store, it, -1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void gui_vartab_remove_var(struct tdc_var *var)
|
|
{
|
|
GtkTreeIter *it = (GtkTreeIter *)var->privdata_vartab;
|
|
gtk_list_store_remove(list_store, it);
|
|
gtk_tree_iter_free(it);
|
|
|
|
var->privdata_vartab = NULL;
|
|
}
|