diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2017-04-29 12:11:08 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2017-04-29 12:11:08 +0200 |
commit | 16e9630b79f0a7a90c6cedb6781175bb8b337dc1 (patch) | |
tree | e1b09d277dec2057e6b995ec099dd2b1f2129b35 /app/wlib/gtklib/droplist.c | |
parent | 09795a01ef859f072920de9df974d1b03b9ab9a4 (diff) |
New upstream version 4.3.0upstream/4.3.0
Diffstat (limited to 'app/wlib/gtklib/droplist.c')
-rw-r--r-- | app/wlib/gtklib/droplist.c | 456 |
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; +} + |