summaryrefslogtreecommitdiff
path: root/app/wlib/gtklib/droplist.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/wlib/gtklib/droplist.c')
-rw-r--r--app/wlib/gtklib/droplist.c456
1 files changed, 456 insertions, 0 deletions
diff --git a/app/wlib/gtklib/droplist.c b/app/wlib/gtklib/droplist.c
new file mode 100644
index 0000000..3252905
--- /dev/null
+++ b/app/wlib/gtklib/droplist.c
@@ -0,0 +1,456 @@
+/** \file droplist.c
+ * Dropdown list functions
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) Dave Bullis 2005, Martin Fischer 2016
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include "gtkint.h"
+#include "i18n.h"
+
+/* define the column count for the tree model */
+#define DROPLIST_TEXTCOLUMNS 1
+
+/**
+ * Add the data columns to the droplist. If dropList has an entry field
+ * the first text column is not added here as this is done by GTK
+ * automatically.
+ *
+ * \param dropList IN
+ * \param columns IN
+ * \returns number of columns created
+ */
+
+int
+wlibDropListAddColumns(GtkWidget *dropList, int columns)
+{
+ int i;
+ int start = 0;
+ GtkCellRenderer *cell;
+
+ if (gtk_combo_box_get_has_entry(GTK_COMBO_BOX(dropList))) {
+ start = 1;
+ }
+
+ /* Create cell renderer. */
+ cell = gtk_cell_renderer_text_new();
+
+ for (i = start; i < columns; i++) {
+ /* Pack it into the droplist */
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropList), cell, TRUE);
+
+ /* Connect renderer to data source */
+ gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropList),
+ cell,
+ "text",
+ LISTCOL_TEXT + i,
+ NULL);
+ }
+
+ return (i);
+}
+
+/**
+ * Get the number of rows in drop list
+ *
+ * \param b IN widget
+ * \return number of rows
+ */
+
+wIndex_t wDropListGetCount(wList_p b)
+{
+ return (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(b->listStore), NULL));
+}
+
+/**
+ * Clear the whole droplist
+ *
+ * \param b IN the droplist
+ * \return
+ */
+
+void
+wDropListClear(wList_p b)
+{
+ wlibListStoreClear(b->listStore);
+}
+
+/**
+ * Get the user data / context information for a row in the droplist
+ * \param b IN widget
+ * \param inx IN row
+ * \returns pointer to context information
+ */
+
+void *wDropListGetItemContext(wList_p b, wIndex_t inx)
+{
+ GtkTreeIter iter;
+ wListItem_p data = NULL;
+
+ if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(b->listStore), &iter, NULL,
+ inx)) {
+ gtk_tree_model_get(GTK_TREE_MODEL(b->listStore),
+ &iter,
+ LISTCOL_DATA, (void *)&data,
+ -1);
+ }
+
+ if (data) {
+ return (data->itemData);
+ } else {
+ return (NULL);
+ }
+}
+
+/**
+ * Add an entry to a dropdown list. Only single text entries are allowed
+ *
+ * \param b IN the widget
+ * \param text IN string to add
+ * \return describe the return value
+ */
+
+void wDropListAddValue(
+ wList_p b,
+ char *text,
+ wListItem_p data)
+{
+ GtkTreeIter iter;
+
+ assert(b != NULL);
+ assert(text != NULL);
+
+ gtk_list_store_append(b->listStore, &iter); // append new row to tree store
+
+ gtk_list_store_set(b->listStore, &iter,
+ LISTCOL_TEXT, text,
+ LISTCOL_DATA, (void *)data,
+ -1);
+}
+
+/**
+ * Set the value to the entry field of a droplist
+ * \param bl IN
+ * \param val IN
+ */
+
+void wListSetValue(
+ wList_p bl,
+ const char * val)
+{
+ assert(bl->listStore!=NULL);
+
+ bl->recursion++;
+
+ if (bl->type == B_DROPLIST) {
+ bl->editted = TRUE;
+ gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(bl->widget))), val);
+
+ if (bl->action) {
+ bl->action(-1, val, 0, bl->data, NULL);
+ }
+ } else {
+ assert(FALSE);
+ }
+
+ bl->recursion--;
+}
+
+/**
+ * Makes the <val>th entry (0-origin) the current selection.
+ * If <val> if '-1' then no entry is selected.
+ *
+ * \param b IN the widget
+ * \param val IN the index
+ *
+ * \todo it seems BL_NONE is not used in current code, check and clean up
+ */
+
+void wDropListSetIndex(wList_p b, int val)
+{
+ if ((b->option&BL_NONE)!=0 && val < 0) {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(b->widget), -1);
+ } else {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(b->widget), val);
+ }
+}
+
+/**
+ * Set the values for a row in the droplist
+ *
+ * \param b IN drop list widget
+ * \param row IN index
+ * \param labelStr IN new text
+ * \param bm IN ignored
+ * \param itemData IN ignored
+ * \return
+ */
+
+wBool_t wDropListSetValues(
+ wList_p b,
+ wIndex_t row,
+ const char * labelStr,
+ wIcon_p bm,
+ void *itemData)
+{
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(b->listStore), &iter, NULL,
+ row)) {
+ gtk_list_store_set(b->listStore,
+ &iter,
+ LISTCOL_TEXT, labelStr,
+ -1);
+ return (TRUE);
+ } else {
+ return (FALSE);
+ }
+}
+
+/**
+ * Signal handler for the "changed"-signal in drop list's entry field.
+ * Get the entered text and calls the 'action' for handling of entered
+ * value.
+ * *
+ * \param entry IN entry field of the droplist
+ * \param data IN the drop list handle
+ * \return
+ */
+
+static void DropListEntryEntered(
+ GtkEntry * entry,
+ gpointer userData)
+{
+ const gchar * text;
+
+ text = gtk_entry_get_text(entry);
+
+ if (text && *text != '\0') {
+ gchar *copyOfText = g_strdup(text);
+ ((wList_p)userData)->editted = TRUE;
+ ((wList_p)userData)->action(-1, copyOfText, 1, ((wList_p)userData)->data, NULL);
+ g_free((gpointer)copyOfText);
+ } else {
+ wBeep();
+ }
+}
+
+/**
+ * Signal handler for the "changed"-signal in drop list. Gets the selected
+ * text and determines the selected row in the tree model.
+ *
+ * \param comboBox IN the combo_box
+ * \param data IN the drop list handle
+ * \return
+ */
+
+static int DropListSelectChild(
+ GtkComboBox * comboBox,
+ gpointer data)
+{
+ wList_p bl = (wList_p)data;
+ GtkTreeIter iter;
+
+ wIndex_t inx = 0;
+ gchar *string;
+ wListItem_p addData;
+
+ if (bl->recursion) {
+ return 0;
+ }
+
+ bl->editted = FALSE;
+
+ /* Obtain currently selected item from combo box.
+ * If nothing is selected, do nothing. */
+ if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(comboBox), &iter)) {
+ GtkTreeModel *model;
+
+ /* Obtain data model from combo box. */
+ model = gtk_combo_box_get_model(comboBox);
+
+ /* get the selected row */
+ string = gtk_tree_model_get_string_from_iter(model,
+ &iter);
+ inx = atoi(string);
+ g_free(string);
+
+ /* Obtain string from model. */
+ gtk_tree_model_get(model, &iter,
+ LISTCOL_TEXT, &string,
+ LISTCOL_DATA, (void *)&addData,
+ -1);
+
+ } else {
+ return 0;
+ }
+
+ /* selection changed, store new selections and call back */
+ if (bl->last != inx) {
+
+ bl->last = inx;
+
+ if (bl->valueP) {
+ *bl->valueP = inx;
+ }
+
+ /* selection changed -> callback */
+ if (string && bl->action) {
+ bl->action(inx, string, 1, bl->data, addData->itemData);
+ }
+ }
+
+ g_free(string);
+ return 1;
+}
+
+/**
+ * Create a droplist for a given liststore
+ *
+ * \param ls IN list store for dropbox
+ * \param editable IN droplist with entry field
+ * \returns the newly created widget
+ */
+
+GtkWidget *
+wlibNewDropList(GtkListStore *ls, int editable)
+{
+ GtkWidget *widget;
+
+ if (editable) {
+ widget = gtk_combo_box_new_with_model_and_entry(GTK_TREE_MODEL(ls));
+ } else {
+ widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(ls));
+ }
+
+ return (widget);
+}
+
+/**
+ * Create a drop down list. The drop down is created and intialized with the supplied values.
+ *
+ * \param IN parent Parent window
+ * \param IN x, X-position
+ * \param IN y Y-position
+ * \param IN helpStr Help string
+ * \param IN labelStr Label
+ * \param IN option Options
+ * \param IN number Number of displayed entries
+ * \param IN width Width
+ * \param IN valueP Selected index
+ * \param IN action Callback
+ * \param IN data Context
+ */
+
+wList_p wDropListCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ long number,
+ wPos_t width,
+ long *valueP,
+ wListCallBack_p action,
+ void *data)
+{
+ wList_p b;
+
+ b = (wList_p)wlibAlloc(parent, B_DROPLIST, x, y, labelStr, sizeof *b, data);
+ b->option = option;
+ b->number = number;
+ b->count = 0;
+ b->last = -1;
+ b->valueP = valueP;
+ b->action = action;
+ b->listX = b->realX;
+ b->colCnt = 0;
+ b->colWidths = NULL;
+ b->colRightJust = NULL;
+ b->editable = ((option & BL_EDITABLE) != 0);
+
+ assert(width != 0);
+
+ wlibComputePos((wControl_p)b);
+
+
+ // create tree store for storing the contents
+ b->listStore = wlibNewListStore(DROPLIST_TEXTCOLUMNS);
+
+ if (!b->listStore) {
+ abort();
+ }
+
+ // create the droplist
+ b->widget = wlibNewDropList(b->listStore,
+ option & BL_EDITABLE);
+
+ if (b->widget == 0) {
+ abort();
+ }
+
+ g_object_unref(G_OBJECT(b->listStore));
+
+ wlibDropListAddColumns(b->widget, DROPLIST_TEXTCOLUMNS);
+
+ gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(b->widget),
+ LISTCOL_TEXT);
+
+ // combo's style
+ gtk_rc_parse_string("style \"my-style\" { GtkComboBox::appears-as-list = 1 } widget \"*.mycombo\" style \"my-style\" ");
+ gtk_widget_set_name(b->widget,"mycombo");
+
+ g_signal_connect(GTK_OBJECT(b->widget), "changed",
+ G_CALLBACK(DropListSelectChild), b);
+
+ if (option & BL_EDITABLE) {
+ g_signal_connect(gtk_bin_get_child(GTK_BIN(b->widget)),
+ "changed",
+ G_CALLBACK(DropListEntryEntered),
+ b);
+ }
+
+ gtk_widget_set_size_request(b->widget, width, -1);
+
+ gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY);
+ wlibControlGetSize((wControl_p)b);
+
+ if (labelStr) {
+ b->labelW = wlibAddLabel((wControl_p)b, labelStr);
+ }
+
+ gtk_widget_show(b->widget);
+ wlibAddButton((wControl_p)b);
+ wlibAddHelpString(b->widget, helpStr);
+
+ return b;
+}
+