summaryrefslogtreecommitdiff
path: root/app/wlib/gtklib/gtkbutton.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/wlib/gtklib/gtkbutton.c')
-rw-r--r--app/wlib/gtklib/gtkbutton.c461
1 files changed, 461 insertions, 0 deletions
diff --git a/app/wlib/gtklib/gtkbutton.c b/app/wlib/gtklib/gtkbutton.c
new file mode 100644
index 0000000..7780535
--- /dev/null
+++ b/app/wlib/gtklib/gtkbutton.c
@@ -0,0 +1,461 @@
+/** \file gtkbutton.c
+ * Toolbar button creation and handling
+ *
+ * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkbutton.c,v 1.8 2009-10-03 04:49:01 dspagnol 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 <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+#include "i18n.h"
+
+#define MIN_BUTTON_WIDTH (80)
+
+/*
+ *****************************************************************************
+ *
+ * Simple Buttons
+ *
+ *****************************************************************************
+ */
+
+struct wButton_t {
+ WOBJ_COMMON
+ GtkLabel * labelG;
+ GtkWidget * imageG;
+ wButtonCallBack_p action;
+ int busy;
+ int recursion;
+ };
+
+
+void wButtonSetBusy( wButton_p bb, int value ) {
+ bb->recursion++;
+ gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(bb->widget), value );
+ bb->recursion--;
+ bb->busy = value;
+}
+
+
+void gtkSetLabel(
+ GtkWidget *widget,
+ long option,
+ const char * labelStr,
+ GtkLabel * * labelG,
+ GtkWidget * * imageG )
+{
+ wIcon_p bm;
+ GdkPixbuf *pixbuf;
+
+ GdkPixmap * pixmap;
+ GdkBitmap * mask;
+
+ GtkWidget * hbox;
+ if (widget == 0) abort();
+ if (labelStr){
+ if (option&BO_ICON) {
+ bm = (wIcon_p)labelStr;
+
+ // for XPM files use the pixbuf functions
+ if( bm->gtkIconType == gtkIcon_pixmap ) {
+ pixbuf = gdk_pixbuf_new_from_xpm_data( (const char**)bm->bits );
+ if (*imageG==NULL) {
+ *imageG = gtk_image_new_from_pixbuf( pixbuf );
+ gtk_container_add( GTK_CONTAINER( widget ), *imageG );
+ gtk_widget_show( *imageG );
+ } else {
+ gtk_image_set_from_pixbuf( GTK_IMAGE(*imageG), pixbuf );
+ }
+ g_object_unref( pixbuf );
+ } else {
+ // otherwise use the conversion to XPM
+ /** \todo { Should use the way via a pixbuf as well } */
+ pixmap = gtkMakeIcon( widget, bm, &mask );
+ if (*imageG==NULL) {
+ *imageG = gtk_image_new_from_pixmap( pixmap, NULL );
+ gtk_widget_show( *imageG );
+ gtk_container_add( GTK_CONTAINER( widget ), *imageG );
+ } else {
+ gtk_image_set_from_pixmap( GTK_IMAGE(*imageG), pixmap, NULL );
+ }
+ gdk_pixmap_unref( pixmap );
+ gdk_bitmap_unref( mask );
+ }
+ } else {
+ if (*labelG==NULL) {
+ *labelG = (GtkLabel*)gtk_label_new( gtkConvertInput(labelStr) );
+ gtk_container_add( GTK_CONTAINER(widget), (GtkWidget*)*labelG );
+ gtk_widget_show( (GtkWidget*)*labelG );
+ } else {
+ gtk_label_set( *labelG, gtkConvertInput(labelStr) );
+ }
+ }
+ }
+}
+
+void wButtonSetLabel( wButton_p bb, const char * labelStr) {
+ gtkSetLabel( bb->widget, bb->option, labelStr, &bb->labelG, &bb->imageG );
+}
+
+
+
+void gtkButtonDoAction(
+ wButton_p bb )
+{
+ if (bb->action)
+ bb->action( bb->data );
+}
+
+
+static void pushButt(
+ GtkWidget *widget,
+ gpointer value )
+{
+ wButton_p b = (wButton_p)value;
+ if (debugWindow >= 2) printf("%s button pushed\n", b->labelStr?b->labelStr:"No label" );
+ if (b->recursion)
+ return;
+ if (b->action)
+ b->action(b->data);
+ if (!b->busy) {
+ b->recursion++;
+ gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(b->widget), FALSE );
+ b->recursion--;
+ }
+}
+
+wButton_p wButtonCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ wPos_t width,
+ wButtonCallBack_p action,
+ void * data )
+{
+ wButton_p b;
+ b = gtkAlloc( parent, B_BUTTON, x, y, labelStr, sizeof *b, data );
+ b->option = option;
+ b->action = action;
+ gtkComputePos( (wControl_p)b );
+
+ b->widget = gtk_toggle_button_new();
+
+ gtk_signal_connect (GTK_OBJECT(b->widget), "clicked",
+ GTK_SIGNAL_FUNC(pushButt), b );
+ if (width > 0)
+ gtk_widget_set_size_request( b->widget, width, -1 );
+ wButtonSetLabel( b, labelStr );
+
+ gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
+ if (option & BB_DEFAULT) {
+ GTK_WIDGET_SET_FLAGS( b->widget, GTK_CAN_DEFAULT );
+ gtk_widget_grab_default( b->widget );
+ gtk_window_set_default( GTK_WINDOW(parent->gtkwin), b->widget );
+ }
+ gtkControlGetSize( (wControl_p)b );
+ if (width == 0 && b->w < MIN_BUTTON_WIDTH && (b->option&BO_ICON)==0) {
+ b->w = MIN_BUTTON_WIDTH;
+ gtk_widget_set_size_request( b->widget, b->w, b->h );
+ }
+ gtk_widget_show( b->widget );
+ gtkAddButton( (wControl_p)b );
+ gtkAddHelpString( b->widget, helpStr );
+ return b;
+}
+
+
+/*
+ *****************************************************************************
+ *
+ * Choice Boxes
+ *
+ *****************************************************************************
+ */
+
+struct wChoice_t {
+ WOBJ_COMMON
+ long *valueP;
+ wChoiceCallBack_p action;
+ int recursion;
+ };
+
+
+static long choiceGetValue(
+ wChoice_p bc )
+{
+ GList * child, * children;
+ long value, inx;
+ if (bc->type == B_TOGGLE)
+ value = 0;
+ else
+ value = -1;
+ for ( children=child=gtk_container_children(GTK_CONTAINER(bc->widget)),inx=0; child; child=child->next,inx++ ) {
+ if ( GTK_TOGGLE_BUTTON(child->data)->active ) {
+ if (bc->type == B_TOGGLE) {
+ value |= (1<<inx);
+ } else {
+ value = inx;
+ }
+ }
+ }
+ if ( children )
+ g_list_free( children );
+ return value;
+}
+
+EXPORT void wRadioSetValue(
+ wChoice_p bc, /* Radio box */
+ long value ) /* Value */
+/*
+*/
+{
+ GList * child, * children;
+ long inx;
+ for ( children=child=gtk_container_children(GTK_CONTAINER(bc->widget)),inx=0; child; child=child->next,inx++ ) {
+ if (inx == value) {
+ bc->recursion++;
+ gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(child->data), TRUE );
+ bc->recursion--;
+ }
+ }
+ if ( children )
+ g_list_free( children );
+}
+
+
+EXPORT long wRadioGetValue(
+ wChoice_p bc ) /* Radio box */
+/*
+*/
+{
+ return choiceGetValue(bc);
+}
+
+
+EXPORT void wToggleSetValue(
+ wChoice_p bc, /* Toggle box */
+ long value ) /* Values */
+/*
+*/
+{
+ GList * child, * children;
+ long inx;
+ bc->recursion++;
+ for ( children=child=gtk_container_children(GTK_CONTAINER(bc->widget)),inx=0; child; child=child->next,inx++ ) {
+ gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(child->data), (value&(1<<inx))!=0 );
+ }
+ if ( children )
+ g_list_free( children );
+ bc->recursion--;
+}
+
+
+EXPORT long wToggleGetValue(
+ wChoice_p b ) /* Toggle box */
+/*
+*/
+{
+ return choiceGetValue(b);
+}
+
+
+static int pushChoice(
+ GtkWidget *widget,
+ gpointer b )
+{
+ wChoice_p bc = (wChoice_p)b;
+ long value = choiceGetValue( bc );
+ if (debugWindow >= 2) printf("%s choice pushed = %ld\n", bc->labelStr?bc->labelStr:"No label", value );
+ if ( bc->type == B_RADIO && !(GTK_TOGGLE_BUTTON(widget))->active )
+ return 1;
+ if (bc->recursion)
+ return 1;
+ if (bc->valueP)
+ *bc->valueP = value;
+ if (bc->action)
+ bc->action( value, bc->data);
+ return 1;
+}
+
+
+static void choiceRepaint(
+ wControl_p b )
+{
+ wChoice_p bc = (wChoice_p)b;
+ if ( GTK_WIDGET_VISIBLE( b->widget ) )
+ gtkDrawBox( bc->parent, wBoxBelow, bc->realX-1, bc->realY-1, bc->w+1, bc->h+1 );
+}
+
+
+EXPORT wChoice_p wRadioCreate(
+ wWin_p parent, /* Parent window */
+ wPos_t x, /* X-position */
+ wPos_t y, /* Y-position */
+ const char * helpStr, /* Help string */
+ const char * labelStr, /* Label */
+ long option, /* Options */
+ const char **labels, /* Labels */
+ long *valueP, /* Selected value */
+ wChoiceCallBack_p action, /* Callback */
+ void *data ) /* Context */
+/*
+*/
+{
+ wChoice_p b;
+ const char ** label;
+ GtkWidget *butt0=NULL, *butt;
+
+ if ((option & BC_NOBORDER)==0) {
+ if (x>=0)
+ x++;
+ else
+ x--;
+ if (y>=0)
+ y++;
+ else
+ y--;
+ }
+ b = gtkAlloc( parent, B_RADIO, x, y, labelStr, sizeof *b, data );
+ b->option = option;
+ b->action = action;
+ b->valueP = valueP;
+ gtkComputePos( (wControl_p)b );
+
+ if (option&BC_HORZ)
+ b->widget = gtk_hbox_new( FALSE, 0 );
+ else
+ b->widget = gtk_vbox_new( FALSE, 0 );
+ if (b->widget == 0) abort();
+ for ( label=labels; *label; label++ ) {
+ butt = gtk_radio_button_new_with_label(
+ butt0?gtk_radio_button_group(GTK_RADIO_BUTTON(butt0)):NULL, _(*label) );
+ if (butt0==NULL)
+ butt0 = butt;
+ gtk_box_pack_start( GTK_BOX(b->widget), butt, TRUE, TRUE, 0 );
+ gtk_widget_show( butt );
+ gtk_signal_connect (GTK_OBJECT(butt), "toggled",
+ GTK_SIGNAL_FUNC( pushChoice ), b );
+ gtkAddHelpString( butt, helpStr );
+ }
+ if (option & BB_DEFAULT) {
+ GTK_WIDGET_SET_FLAGS( b->widget, GTK_CAN_DEFAULT );
+ gtk_widget_grab_default( b->widget );
+ /*gtk_window_set_default( GTK_WINDOW(parent->gtkwin), b->widget );*/
+ }
+ if (valueP)
+ wRadioSetValue( b, *valueP );
+
+ if ((option & BC_NOBORDER)==0) {
+ if (parent->gc == NULL) {
+ parent->gc = gdk_gc_new( parent->gtkwin->window );
+ gdk_gc_copy( parent->gc, parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] );
+ parent->gc_linewidth = 0;
+ gdk_gc_set_line_attributes( parent->gc, parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER );
+ }
+ b->repaintProc = choiceRepaint;
+ b->w += 2;
+ b->h += 2;
+ }
+
+ gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
+ gtkControlGetSize( (wControl_p)b );
+ if (labelStr)
+ b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
+ gtk_widget_show( b->widget );
+ gtkAddButton( (wControl_p)b );
+ return b;
+}
+
+wChoice_p wToggleCreate(
+ wWin_p parent, /* Parent window */
+ wPos_t x, /* X-position */
+ wPos_t y, /* Y-position */
+ const char * helpStr, /* Help string */
+ const char * labelStr, /* Label */
+ long option, /* Options */
+ const char **labels, /* Labels */
+ long *valueP, /* Selected value */
+ wChoiceCallBack_p action, /* Callback */
+ void *data ) /* Context */
+/*
+*/
+{
+ wChoice_p b;
+ const char ** label;
+ GtkWidget *butt;
+
+ if ((option & BC_NOBORDER)==0) {
+ if (x>=0)
+ x++;
+ else
+ x--;
+ if (y>=0)
+ y++;
+ else
+ y--;
+ }
+ b = gtkAlloc( parent, B_TOGGLE, x, y, labelStr, sizeof *b, data );
+ b->option = option;
+ b->action = action;
+ gtkComputePos( (wControl_p)b );
+
+ if (option&BC_HORZ)
+ b->widget = gtk_hbox_new( FALSE, 0 );
+ else
+ b->widget = gtk_vbox_new( FALSE, 0 );
+ if (b->widget == 0) abort();
+ for ( label=labels; *label; label++ ) {
+ butt = gtk_check_button_new_with_label(_(*label));
+ gtk_box_pack_start( GTK_BOX(b->widget), butt, TRUE, TRUE, 0 );
+ gtk_widget_show( butt );
+ gtk_signal_connect (GTK_OBJECT(butt), "toggled",
+ GTK_SIGNAL_FUNC( pushChoice ), b );
+ gtkAddHelpString( butt, helpStr );
+ }
+ if (valueP)
+ wToggleSetValue( b, *valueP );
+
+ if ((option & BC_NOBORDER)==0) {
+ if (parent->gc == NULL) {
+ parent->gc = gdk_gc_new( parent->gtkwin->window );
+ gdk_gc_copy( parent->gc, parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] );
+ parent->gc_linewidth = 0;
+ gdk_gc_set_line_attributes( parent->gc, parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER );
+ }
+ b->repaintProc = choiceRepaint;
+ b->w += 2;
+ b->h += 2;
+ }
+
+ gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
+ gtkControlGetSize( (wControl_p)b );
+ if (labelStr)
+ b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
+ gtk_widget_show( b->widget );
+ gtkAddButton( (wControl_p)b );
+ return b;
+}