summaryrefslogtreecommitdiff
path: root/app/wlib/gtklib/gtksingle.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/wlib/gtklib/gtksingle.c')
-rw-r--r--app/wlib/gtklib/gtksingle.c645
1 files changed, 645 insertions, 0 deletions
diff --git a/app/wlib/gtklib/gtksingle.c b/app/wlib/gtklib/gtksingle.c
new file mode 100644
index 0000000..d106e17
--- /dev/null
+++ b/app/wlib/gtklib/gtksingle.c
@@ -0,0 +1,645 @@
+/*
+ * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtksingle.c,v 1.2 2009-05-15 18:54:20 m_fischer Exp $
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis
+ *
+ * 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 <math.h>
+#include <gtk/gtk.h>
+
+#include "gtkint.h"
+
+/*
+ *****************************************************************************
+ *
+ * Text Boxes
+ *
+ *****************************************************************************
+ */
+
+struct wString_t {
+ WOBJ_COMMON
+ char * valueP;
+ wIndex_t valueL;
+ wStringCallBack_p action;
+ wBool_t busy;
+ };
+
+void wStringSetValue(
+ wString_p b,
+ const char * arg )
+{
+ wBool_t busy;
+ if (b->widget == 0) abort();
+ busy = b->busy;
+ b->busy = TRUE;
+ gtk_entry_set_text( GTK_ENTRY(b->widget), arg );
+ b->busy = busy;
+}
+
+
+void wStringSetWidth(
+ wString_p b,
+ wPos_t w )
+{
+#ifndef GTK1
+ gtk_widget_set_size_request( b->widget, w, -1 );
+#else
+ gtk_widget_set_usize( b->widget, w, -1 );
+#endif
+ b->w = w;
+}
+
+
+const char * wStringGetValue(
+ wString_p b )
+{
+ if (b->widget == 0) abort();
+ return gtk_entry_get_text( GTK_ENTRY(b->widget) );
+}
+
+
+static void triggerString(
+ wControl_p b )
+{
+ wString_p bs = (wString_p)b;
+ const char * s;
+
+ if (b == 0)
+ return;
+ if (bs->widget == 0) abort();
+ s = gtk_entry_get_text( GTK_ENTRY(bs->widget) );
+ if (debugWindow >= 2) printf("%s text = %s\n", bs->labelStr?bs->labelStr:"No label", s );
+ if (s == NULL)
+ return;
+ if (debugWindow >= 2) printf("triggerString( %s )\n", s );
+ if (bs->action) {
+ bs->busy = TRUE;
+ bs->action( s, bs->data );
+ bs->busy = FALSE;
+ }
+ gtkSetTrigger( NULL, NULL );
+ return;
+}
+
+
+static void stringActivated(
+ GtkEntry * widget,
+ wString_p b )
+{
+ const char * s;
+ if (b == 0)
+ return;
+ s = wStringGetValue(b);
+
+ if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s );
+ if (b->valueP)
+ strcpy( b->valueP, s );
+ if (b->action) {
+ b->busy = TRUE;
+ b->action( s, b->data );
+ b->busy = FALSE;
+ }
+}
+
+static void stringChanged(
+ GtkEntry * widget,
+ wString_p b )
+{
+ const char *new_value;
+ if (b == 0)
+ return;
+ if (b->busy)
+ return;
+ new_value = wStringGetValue(b);
+ if (b->valueP != NULL)
+ strcpy( b->valueP, new_value );
+ if (b->action)
+ gtkSetTrigger( (wControl_p)b, triggerString );
+ return;
+}
+
+wString_p wStringCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ wPos_t width,
+ char *valueP,
+ wIndex_t valueL,
+ wStringCallBack_p action,
+ void *data )
+{
+ wString_p b;
+
+ b = (wString_p)gtkAlloc( parent, B_TEXT, x, y, labelStr, sizeof *b, data );
+ b->valueP = valueP;
+ b->action = action;
+ b->option = option;
+ b->valueL = valueL;
+ gtkComputePos( (wControl_p)b );
+
+ if (valueL) {
+ b->widget = (GtkWidget*)gtk_entry_new_with_max_length( valueL );
+ } else {
+ b->widget = (GtkWidget*)gtk_entry_new();
+ }
+ if (b->widget == 0) abort();
+
+#ifndef GTK1
+ gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
+#else
+ gtk_container_add( GTK_CONTAINER(parent->widget), b->widget );
+ gtk_widget_set_uposition( b->widget, b->realX, b->realY );
+#endif
+ if ( width )
+#ifndef GTK1
+ gtk_widget_set_size_request( b->widget, width, -1 );
+#else
+ gtk_widget_set_usize( b->widget, width, -1 );
+#endif
+ gtkControlGetSize( (wControl_p)b );
+ if (labelStr)
+ b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
+ /*b->w += 4;*/
+ /*b->h += 4;*/
+ if (b->valueP)
+ wStringSetValue( b, b->valueP );
+ gtk_widget_show( b->widget );
+ gtkAddButton( (wControl_p)b );
+ gtkAddHelpString( b->widget, helpStr );
+ gtk_signal_connect( GTK_OBJECT(b->widget), "changed", GTK_SIGNAL_FUNC(stringChanged), b );
+ gtk_signal_connect( GTK_OBJECT(b->widget), "activate", GTK_SIGNAL_FUNC(stringActivated), b );
+ if (option & BO_READONLY)
+ gtk_entry_set_editable( GTK_ENTRY(b->widget), FALSE );
+ return b;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Floating Point Value Boxes
+ *
+ *****************************************************************************
+ */
+
+
+struct wFloat_t {
+ WOBJ_COMMON
+ double low, high;
+ double oldValue;
+ double * valueP;
+ wFloatCallBack_p action;
+ wBool_t busy;
+ };
+
+
+void wFloatSetValue(
+ wFloat_p b,
+ double arg )
+{
+ char message[80];
+ if (b->widget == 0) abort();
+ sprintf( message, "%0.3f", arg );
+ if (!b->busy) {
+ b->busy = TRUE;
+ gtk_entry_set_text( GTK_ENTRY(b->widget), message );
+ b->busy = FALSE;
+ }
+ if (b->valueP)
+ *b->valueP = arg;
+}
+
+
+double wFloatGetValue(
+ wFloat_p b )
+{
+ double ret;
+ const char * cp;
+ if (b->widget == 0) abort();
+ cp = gtk_entry_get_text( GTK_ENTRY(b->widget) );
+ ret = atof( cp );
+ return ret;
+}
+
+
+static void triggerFloat(
+ wControl_p b )
+{
+ wFloat_p bf = (wFloat_p)b;
+ const char * s;
+ char * cp;
+ double v;
+
+ if (b == 0)
+ return;
+ if (bf->widget == 0) abort();
+ s = gtk_entry_get_text( GTK_ENTRY(bf->widget) );
+ if (debugWindow >= 2) printf("%s text = %s\n", bf->labelStr?bf->labelStr:"No label", s );
+ if (s == NULL)
+ return;
+ v = strtod( s, &cp );
+ if (*cp!=0 || v < bf->low || v > bf->high)
+ return;
+ /*if (bf->oldValue == v)
+ return;*/
+ if (debugWindow >= 2) printf("triggerFloat( %0.3f )\n", v );
+ bf->oldValue = v;
+ if (bf->valueP)
+ *bf->valueP = v;
+ if (bf->action) {
+ bf->busy = TRUE;
+ bf->action( v, bf->data );
+ bf->busy = FALSE;
+ }
+ gtkSetTrigger( NULL, NULL );
+ return;
+}
+
+
+static void floatActivated(
+ GtkEntry *widget,
+ wFloat_p b )
+{
+ const char * s;
+ char * cp;
+ double v;
+ char val_s[80];
+
+ if (b == 0)
+ return;
+ if (b->widget == 0) abort();
+ s = gtk_entry_get_text( GTK_ENTRY(b->widget) );
+ if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s );
+ if (s != NULL) {
+ v = strtod( s, &cp );
+ if (*cp != '\n' && *cp != '\0') {
+ wNoticeEx( NT_ERROR, "The value you have entered is not a valid number\nPlease try again", "Ok", NULL );
+ } else if (v < b->low || v > b->high) {
+ sprintf( val_s, "Please enter a value between %0.3f and %0.3f", b->low, b->high );
+ wNoticeEx( NT_ERROR, val_s, "Ok", NULL );
+ } else {
+ if (debugWindow >= 2) printf("floatActivated( %0.3f )\n", v );
+ b->oldValue = v;
+ if (b->valueP)
+ *b->valueP = v;
+ if (b->action) {
+ gtkSetTrigger( NULL, NULL );
+ b->busy = TRUE;
+ b->action( v, b->data );
+ b->busy = FALSE;
+ }
+ return;
+ }
+ sprintf( val_s, "%0.3f", b->oldValue);
+ b->busy = TRUE;
+ gtk_entry_set_text( GTK_ENTRY(b->widget), val_s );
+ b->busy = FALSE;
+ }
+ return;
+}
+
+static void floatChanged(
+ GtkEntry *widget,
+ wFloat_p b )
+{
+ const char * s;
+ char * cp;
+ double v;
+
+ if (b == 0)
+ return;
+ if (b->widget == 0) abort();
+ if (b->busy)
+ return;
+ s = gtk_entry_get_text( GTK_ENTRY(b->widget) );
+ if (s == NULL)
+ return;
+ if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s );
+ if ( s[0] == '\0' ||
+ strcmp( s, "-" ) == 0 ||
+ strcmp( s, "." ) == 0 ) {
+ v = 0;
+ } else {
+ v = strtod( s, &cp );
+ if (*cp != '\0'
+#ifdef LATER
+ || v < b->low || v > b->high
+#endif
+ ) {
+ wBeep();
+ wFloatSetValue( b, b->oldValue );
+ return;
+ }
+ }
+ b->oldValue = v;
+ if (b->valueP != NULL) {
+ *b->valueP = v;
+ }
+ if (b->action)
+ gtkSetTrigger( (wControl_p)b, triggerFloat );
+ return;
+}
+
+wFloat_p wFloatCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ wPos_t width,
+ double low,
+ double high,
+ double *valueP,
+ wFloatCallBack_p action,
+ void *data )
+{
+ wFloat_p b;
+
+ b = (wFloat_p)gtkAlloc( parent, B_TEXT, x, y, labelStr, sizeof *b, data );
+ b->valueP = valueP;
+ b->action = action;
+ b->option = option;
+ b->low = low;
+ b->high = high;
+ gtkComputePos( (wControl_p)b );
+
+ b->widget = (GtkWidget*)gtk_entry_new_with_max_length( 20 );
+ if (b->widget == 0) abort();
+
+#ifndef GTK1
+ gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
+#else
+ gtk_container_add( GTK_CONTAINER(parent->widget), b->widget );
+ gtk_widget_set_uposition( b->widget, b->realX, b->realY );
+#endif
+ if ( width )
+#ifndef GTK1
+ gtk_widget_set_size_request( b->widget, width, -1 );
+#else
+ gtk_widget_set_usize( b->widget, width, -1 );
+#endif
+ gtkControlGetSize( (wControl_p)b );
+ if (labelStr)
+ b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
+ /*b->w += 4;*/
+ /*b->h += 4;*/
+ if (b->valueP)
+ wFloatSetValue( b, *b->valueP );
+ else
+ wFloatSetValue( b, b->low>0?b->low:0.0 );
+ gtk_widget_show( b->widget );
+ gtkAddButton( (wControl_p)b );
+ gtkAddHelpString( b->widget, helpStr );
+ gtk_signal_connect( GTK_OBJECT(b->widget), "changed", GTK_SIGNAL_FUNC(floatChanged), b );
+ gtk_signal_connect( GTK_OBJECT(b->widget), "activate", GTK_SIGNAL_FUNC(floatActivated), b );
+ if (option & BO_READONLY)
+ gtk_entry_set_editable( GTK_ENTRY(b->widget), FALSE );
+ return b;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Integer Value Boxes
+ *
+ *****************************************************************************
+ */
+
+
+struct wInteger_t {
+ WOBJ_COMMON
+ long low, high;
+ long oldValue;
+ long * valueP;
+ wIntegerCallBack_p action;
+ wBool_t busy;
+ };
+
+
+void wIntegerSetValue(
+ wInteger_p b,
+ long arg )
+{
+ char message[80];
+ if (b->widget == 0) abort();
+ sprintf( message, "%ld", arg );
+ if (!b->busy) {
+ b->busy = TRUE;
+ gtk_entry_set_text( GTK_ENTRY(b->widget), message );
+ b->busy = FALSE;
+ }
+ if (b->valueP)
+ *b->valueP = arg;
+}
+
+
+long wIntegerGetValue(
+ wInteger_p b )
+{
+ long ret;
+ const char * cp;
+ if (b->widget == 0) abort();
+ cp = gtk_entry_get_text( GTK_ENTRY(b->widget) );
+ ret = atol( cp );
+ return ret;
+}
+
+
+static void triggerInteger(
+ wControl_p b )
+{
+ wInteger_p bi = (wInteger_p)b;
+ const char * s;
+ char * cp;
+ long v;
+
+ if (b == 0)
+ return;
+ if (bi->widget == 0) abort();
+ s = gtk_entry_get_text( GTK_ENTRY(bi->widget) );
+ if (debugWindow >= 2) printf("%s text = %s\n", bi->labelStr?bi->labelStr:"No label", s );
+ if (s == NULL)
+ return;
+ v = strtol( s, &cp, 10 );
+ if (*cp!=0 || v < bi->low || v > bi->high)
+ return;
+ /*if (bi->oldValue == v)
+ return;*/
+ if (debugWindow >= 2) printf("triggerInteger( %ld )\n", v );
+ bi->oldValue = v;
+ if (bi->valueP)
+ *bi->valueP = v;
+ if (bi->action) {
+ bi->busy = TRUE;
+ bi->action( v, bi->data );
+ bi->busy = FALSE;
+ }
+ gtkSetTrigger( NULL, NULL );
+ return;
+}
+
+
+
+static void integerActivated(
+ GtkEntry *widget,
+ wInteger_p b )
+{
+ const char * s;
+ char * cp;
+ long v;
+ char val_s[80];
+
+ if (b == 0)
+ return;
+ if (b->widget == 0) abort();
+ s = gtk_entry_get_text( GTK_ENTRY(b->widget) );
+ if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s );
+ if (s != NULL) {
+ v = strtod( s, &cp );
+ if (*cp != '\n' && *cp != '\0') {
+ wNoticeEx( NT_ERROR, "The value you have entered is not a valid number\nPlease try again", "Ok", NULL );
+ } else if (v < b->low || v > b->high) {
+ sprintf( val_s, "Please enter a value between %ld and %ld", b->low, b->high );
+ wNoticeEx( NT_ERROR, val_s, "Ok", NULL );
+ } else {
+ if (debugWindow >= 2) printf("integerActivated( %ld )\n", v );
+ b->oldValue = v;
+ if (b->valueP)
+ *b->valueP = v;
+ if (b->action) {
+ gtkSetTrigger( NULL, NULL );
+ b->busy = TRUE;
+ b->action( v, b->data );
+ b->busy = FALSE;
+ }
+ return;
+ }
+ sprintf( val_s, "%ld", b->oldValue);
+ b->busy = TRUE;
+ gtk_entry_set_text( GTK_ENTRY(b->widget), val_s );
+ b->busy = FALSE;
+ }
+ return;
+}
+
+static void integerChanged(
+ GtkEntry *widget,
+ wInteger_p b )
+{
+ const char * s;
+ char * cp;
+ long v;
+
+ if (b == 0)
+ return;
+ if (b->widget == 0) abort();
+ if (b->busy)
+ return;
+ s = gtk_entry_get_text( GTK_ENTRY(b->widget) );
+ if (s == NULL)
+ return;
+ if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s );
+ if ( s[0] == '\0' ||
+ strcmp( s, "-" ) == 0 ) {
+ v = 0;
+ } else {
+ v = strtol( s, &cp, 10 );
+ if (*cp != '\0'
+#ifdef LATER
+ || v < b->low || v > b->high
+#endif
+ ) {
+ wBeep();
+ wIntegerSetValue( b, b->oldValue );
+ return;
+ }
+ }
+ b->oldValue = v;
+ if (b->valueP != NULL) {
+ *b->valueP = v;
+ }
+ if (b->action)
+ gtkSetTrigger( (wControl_p)b, triggerInteger );
+ return;
+}
+
+wInteger_p wIntegerCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ wPos_t width,
+ long low,
+ long high,
+ long *valueP,
+ wIntegerCallBack_p action,
+ void *data )
+{
+ wInteger_p b;
+
+ b = (wInteger_p)gtkAlloc( parent, B_TEXT, x, y, labelStr, sizeof *b, data );
+ b->valueP = valueP;
+ b->action = action;
+ b->option = option;
+ b->low = low;
+ b->high = high;
+ gtkComputePos( (wControl_p)b );
+
+ b->widget = (GtkWidget*)gtk_entry_new_with_max_length( 20 );
+ if (b->widget == 0) abort();
+
+#ifndef GTK1
+ gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
+#else
+ gtk_container_add( GTK_CONTAINER(parent->widget), b->widget );
+ gtk_widget_set_uposition( b->widget, b->realX, b->realY );
+#endif
+ if ( width )
+#ifndef GTK1
+ gtk_widget_set_size_request( b->widget, width, -1 );
+#else
+ gtk_widget_set_usize( b->widget, width, -1 );
+#endif
+ gtkControlGetSize( (wControl_p)b );
+ if (labelStr)
+ b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
+ /*b->w += 4;*/
+ /*b->h += 4;*/
+ if (b->valueP)
+ wIntegerSetValue( b, *b->valueP );
+ else
+ wIntegerSetValue( b, b->low>0?b->low:0.0 );
+ gtk_widget_show( b->widget );
+ gtkAddButton( (wControl_p)b );
+ gtkAddHelpString( b->widget, helpStr );
+ gtk_signal_connect( GTK_OBJECT(b->widget), "changed", GTK_SIGNAL_FUNC(integerChanged), b );
+ gtk_signal_connect( GTK_OBJECT(b->widget), "activate", GTK_SIGNAL_FUNC(integerActivated), b );
+ if (option & BO_READONLY)
+ gtk_entry_set_editable( GTK_ENTRY(b->widget), FALSE );
+ return b;
+}