From 16e9630b79f0a7a90c6cedb6781175bb8b337dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sat, 29 Apr 2017 12:11:08 +0200 Subject: New upstream version 4.3.0 --- app/wlib/gtklib/CMakeLists.txt | 56 +- app/wlib/gtklib/bitmap.c | 136 +++++ app/wlib/gtklib/boxes.c | 203 +++++++ app/wlib/gtklib/button.c | 630 ++++++++++++++++++++ app/wlib/gtklib/color.c | 466 +++++++++++++++ app/wlib/gtklib/control.c | 283 +++++++++ app/wlib/gtklib/droplist.c | 456 +++++++++++++++ app/wlib/gtklib/dynarr.h | 5 + app/wlib/gtklib/filesel.c | 43 +- app/wlib/gtklib/font.c | 403 +++++++++++++ app/wlib/gtklib/gtkbitmap.c | 85 --- app/wlib/gtklib/gtkbutton.c | 461 --------------- app/wlib/gtklib/gtkcolor.c | 476 --------------- app/wlib/gtklib/gtkdraw-cairo.c | 138 ++--- app/wlib/gtklib/gtkfont.c | 342 ----------- app/wlib/gtklib/gtkhelp.c | 733 ------------------------ app/wlib/gtklib/gtkint.h | 263 ++++++--- app/wlib/gtklib/gtklist.c | 1131 ------------------------------------ app/wlib/gtklib/gtkmenu.c | 873 ---------------------------- app/wlib/gtklib/gtkmisc.c | 1210 --------------------------------------- app/wlib/gtklib/gtksimple.c | 366 ------------ app/wlib/gtklib/gtksingle.c | 645 --------------------- app/wlib/gtklib/gtksplash.c | 142 ----- app/wlib/gtklib/gtktext.c | 670 ---------------------- app/wlib/gtklib/gtkwindow.c | 856 --------------------------- app/wlib/gtklib/gtkxpm.c | 173 ------ app/wlib/gtklib/help.c | 69 +++ app/wlib/gtklib/ixhelp.c | 441 ++++++++++++++ app/wlib/gtklib/lines.c | 150 +++++ app/wlib/gtklib/list.c | 547 ++++++++++++++++++ app/wlib/gtklib/liststore.c | 267 +++++++++ app/wlib/gtklib/main.c | 107 ++++ app/wlib/gtklib/menu.c | 1084 +++++++++++++++++++++++++++++++++++ app/wlib/gtklib/message.c | 168 ++++++ app/wlib/gtklib/notice.c | 297 ++++++++++ app/wlib/gtklib/osxhelp.c | 133 +++++ app/wlib/gtklib/pixbuf.c | 99 ++++ app/wlib/gtklib/png.c | 64 +++ app/wlib/gtklib/print.c | 1000 +++++++++++++++++--------------- app/wlib/gtklib/single.c | 335 +++++++++++ app/wlib/gtklib/splash.c | 144 +++++ app/wlib/gtklib/square10.bmp | 8 - app/wlib/gtklib/text.c | 590 +++++++++++++++++++ app/wlib/gtklib/timer.c | 144 +++++ app/wlib/gtklib/tooltip.c | 255 +++++++++ app/wlib/gtklib/treeview.c | 530 +++++++++++++++++ app/wlib/gtklib/util.c | 672 ++++++++++++++++++++++ app/wlib/gtklib/window.c | 936 ++++++++++++++++++++++++++++++ app/wlib/gtklib/wpref.c | 128 ++--- app/wlib/include/wlib.h | 174 +++--- app/wlib/mswlib/mswedit.c | 2 +- app/wlib/mswlib/mswmisc.c | 2 +- 52 files changed, 10618 insertions(+), 8973 deletions(-) create mode 100644 app/wlib/gtklib/bitmap.c create mode 100644 app/wlib/gtklib/boxes.c create mode 100644 app/wlib/gtklib/button.c create mode 100644 app/wlib/gtklib/color.c create mode 100644 app/wlib/gtklib/control.c create mode 100644 app/wlib/gtklib/droplist.c create mode 100644 app/wlib/gtklib/font.c delete mode 100644 app/wlib/gtklib/gtkbitmap.c delete mode 100644 app/wlib/gtklib/gtkbutton.c delete mode 100644 app/wlib/gtklib/gtkcolor.c delete mode 100644 app/wlib/gtklib/gtkfont.c delete mode 100644 app/wlib/gtklib/gtkhelp.c delete mode 100644 app/wlib/gtklib/gtklist.c delete mode 100644 app/wlib/gtklib/gtkmenu.c delete mode 100644 app/wlib/gtklib/gtkmisc.c delete mode 100644 app/wlib/gtklib/gtksimple.c delete mode 100644 app/wlib/gtklib/gtksingle.c delete mode 100644 app/wlib/gtklib/gtksplash.c delete mode 100644 app/wlib/gtklib/gtktext.c delete mode 100644 app/wlib/gtklib/gtkwindow.c delete mode 100644 app/wlib/gtklib/gtkxpm.c create mode 100644 app/wlib/gtklib/help.c create mode 100644 app/wlib/gtklib/ixhelp.c create mode 100644 app/wlib/gtklib/lines.c create mode 100644 app/wlib/gtklib/list.c create mode 100644 app/wlib/gtklib/liststore.c create mode 100644 app/wlib/gtklib/main.c create mode 100644 app/wlib/gtklib/menu.c create mode 100644 app/wlib/gtklib/message.c create mode 100644 app/wlib/gtklib/notice.c create mode 100644 app/wlib/gtklib/osxhelp.c create mode 100644 app/wlib/gtklib/pixbuf.c create mode 100644 app/wlib/gtklib/png.c create mode 100644 app/wlib/gtklib/single.c create mode 100644 app/wlib/gtklib/splash.c delete mode 100644 app/wlib/gtklib/square10.bmp create mode 100644 app/wlib/gtklib/text.c create mode 100644 app/wlib/gtklib/timer.c create mode 100644 app/wlib/gtklib/tooltip.c create mode 100644 app/wlib/gtklib/treeview.c create mode 100644 app/wlib/gtklib/util.c create mode 100644 app/wlib/gtklib/window.c (limited to 'app/wlib') diff --git a/app/wlib/gtklib/CMakeLists.txt b/app/wlib/gtklib/CMakeLists.txt index cce9866..a8cae9f 100644 --- a/app/wlib/gtklib/CMakeLists.txt +++ b/app/wlib/gtklib/CMakeLists.txt @@ -4,26 +4,51 @@ FILE(GLOB HEADERS *.h) INCLUDE (FindGTKUnixPrint.cmake) SET(SOURCES - gtkbitmap.c - gtkbutton.c - gtkcolor.c - gtkdraw-cairo.c + bitmap.c + boxes.c + button.c + color.c + control.c + droplist.c filesel.c - gtkfont.c - gtkhelp.c - gtklist.c - gtkmenu.c - gtkmisc.c - gtksimple.c - gtksingle.c - gtksplash.c - gtktext.c - gtkwindow.c - gtkxpm.c + font.c + help.c + lines.c + list.c + liststore.c + main.c + menu.c + message.c + notice.c + pixbuf.c + png.c print.c + single.c + splash.c + text.c + timer.c + tooltip.c + treeview.c + util.c + window.c wpref.c +# cproto and cppcheck + +# end of refactored sources + gtkdraw-cairo.c ) +IF(APPLE) + SET(SOURCES + ${SOURCES} + osxhelp.c) + +ELSE(APPLE) + SET(SOURCES + ${SOURCES} + ixhelp.c) +ENDIF(APPLE) + SET_SOURCE_FILES_PROPERTIES(wpref.c PROPERTIES COMPILE_FLAGS -DEXPORT=) INCLUDE_DIRECTORIES(${XTrkCAD_BINARY_DIR}) @@ -35,3 +60,4 @@ ADD_LIBRARY(xtrkcad-wlib ${HEADERS} ${SOURCES}) TARGET_LINK_LIBRARIES(xtrkcad-wlib ${GTK_LIBRARIES}) TARGET_LINK_LIBRARIES(xtrkcad-wlib ${GTK_UNIX_PRINT_LIBRARIES}) TARGET_LINK_LIBRARIES(xtrkcad-wlib ${GTK_WEBKIT_LIBRARIES}) + diff --git a/app/wlib/gtklib/bitmap.c b/app/wlib/gtklib/bitmap.c new file mode 100644 index 0000000..dc7236b --- /dev/null +++ b/app/wlib/gtklib/bitmap.c @@ -0,0 +1,136 @@ +/** \file bitmap.c + * Bitmap creation + */ +/* XTrkCad - Model Railroad CAD + * Copyright (C) 2009 Daniel Spagnol, 2013 Martin Fischer + * + * 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 + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include +#include + +#include "gtkint.h" + +struct wBitmap_t { + WOBJ_COMMON +}; + +/** + * Create a static control for displaying a bitmap. + * + * \param parent IN parent window + * \param x, y IN position in parent window + * \param option IN ignored for now + * \param iconP IN icon to use in XPM format + * \return the control + */ + +wControl_p +wBitmapCreate( wWin_p parent, wPos_t x, wPos_t y, long options, wIcon_p iconP ) +{ + wBitmap_p bt; + GdkPixbuf *pixbuf; + GtkWidget *image; + + bt = wlibAlloc( parent, B_BITMAP, x, y, NULL, sizeof *bt, NULL ); + bt->w = iconP->w; + bt->h = iconP->h; + bt->option = options; + + /* + * Depending on the platform, parent->widget->window might still be null + * at this point. The window allocation should be forced before creating + * the pixmap. + */ + if ( gtk_widget_get_window( parent->widget ) == NULL ) + gtk_widget_realize( parent->widget ); /* force allocation, if pending */ + + /* create the bitmap from supplied xpm data */ + pixbuf = gdk_pixbuf_new_from_xpm_data( (const char **)iconP->bits ); + image = gtk_image_new_from_pixbuf( pixbuf ); + gtk_widget_show( image ); + g_object_unref( (gpointer)pixbuf ); + + bt->widget = gtk_fixed_new(); + gtk_widget_show( bt->widget ); + gtk_container_add( GTK_CONTAINER(bt->widget), image ); + + wlibComputePos( (wControl_p)bt ); + wlibControlGetSize( (wControl_p)bt ); + gtk_fixed_put( GTK_FIXED( parent->widget ), bt->widget, bt->realX, bt->realY ); + + return( (wControl_p)bt ); +} + +/** + * Create a two-tone icon + * + * \param w IN width of icon + * \param h IN height of icon + * \param bits IN bitmap + * \param color IN color + * \returns icon handle + */ + +wIcon_p wIconCreateBitMap( wPos_t w, wPos_t h, const char * bits, wDrawColor color ) +{ + wIcon_p ip; + ip = (wIcon_p)malloc( sizeof *ip ); + ip->gtkIconType = gtkIcon_bitmap; + ip->w = w; + ip->h = h; + ip->color = color; + ip->bits = bits; + return ip; +} + +/** + * Create an icon from a pixmap + * \param pm IN pixmap + * \returns icon handle + */ + +wIcon_p wIconCreatePixMap( char *pm[] ) +{ + wIcon_p ip; + ip = (wIcon_p)malloc( sizeof *ip ); + ip->gtkIconType = gtkIcon_pixmap; + ip->w = 0; + ip->h = 0; + ip->color = 0; + ip->bits = pm; + return ip; +} + +/** + * Set the color a two-tone icon + * + * \param ip IN icon handle + * \param color IN color to use + */ + +void wIconSetColor( wIcon_p ip, wDrawColor color ) +{ + ip->color = color; +} + diff --git a/app/wlib/gtklib/boxes.c b/app/wlib/gtklib/boxes.c new file mode 100644 index 0000000..cce6649 --- /dev/null +++ b/app/wlib/gtklib/boxes.c @@ -0,0 +1,203 @@ +/** \file boxes.c + * Window for drawing a rectangle + */ + +/* XTrkCad - Model Railroad CAD + * Copyright (C) 2005 Dave Bullis, + * 2016 Martin Fischer + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include +#include +#include + +#include "gtkint.h" + +struct wBox_t { + WOBJ_COMMON + wBoxType_e boxTyp; +}; + +#define B (1) +#define W (2) +#define SETCOLOR(ST, S, N ) \ + if (colors[ST][S][N] == B ) { \ + cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); \ + } else { \ + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); \ + } + +/** + * Set size of box window + * + * \param b IN window handle + * \param w IN new width + * \param h IN new height + * \return + * + */ + +void wBoxSetSize( + wBox_p b, + wPos_t w, + wPos_t h) +{ + b->w = w; + b->h = h; +} + +/** + * Draw the box + * \todo too many strokes, remove and test + * + * \param win IN window handle + * \param style IN frame style + * \param x IN x position + * \param y IN y position + * \param w IN width + * \param h IN height + * \return + */ + +void wlibDrawBox( + wWin_p win, + wBoxType_e style, + wPos_t x, + wPos_t y, + wPos_t w, + wPos_t h) +{ + wPos_t x0, y0, x1, y1; + GdkDrawable * window; + cairo_t *cr; + static char colors[8][4][2] = { + { /* ThinB */ {B,0}, {B,0}, {B,0}, {B,0} }, + { /* ThinW */ {W,0}, {W,0}, {W,0}, {W,0} }, + { /* AboveW */ {W,0}, {W,0}, {B,0}, {B,0} }, + { /* BelowW */ {B,0}, {B,0}, {W,0}, {W,0} }, + { /* ThickB */ {B,B}, {B,B}, {B,B}, {B,B} }, + { /* ThickW */ {W,W}, {W,W}, {W,W}, {W,W} }, + { /* RidgeW */ {W,B}, {W,B}, {B,W}, {B,W} }, + { /* TroughW*/ {B,W}, {B,W}, {W,B}, {W,B} } + }; + window = gtk_widget_get_window(win->widget); + cr = gdk_cairo_create(window); + cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); + cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); + cairo_set_line_width(cr, 1.0); + x0 = x; + x1 = x+w; + y0 = y; + y1 = y+h; + SETCOLOR(style, 0, 0); + cairo_move_to(cr, x0, y0); + cairo_line_to(cr, x0, y1); + cairo_stroke_preserve(cr); + SETCOLOR(style, 1, 0); + cairo_move_to(cr, x0, y0); + cairo_line_to(cr, x1, y0); + cairo_stroke_preserve(cr); + SETCOLOR(style, 2, 0); + cairo_move_to(cr, x1, y1); + cairo_line_to(cr, x0+1, y1); + cairo_stroke_preserve(cr); + SETCOLOR(style, 3, 0); + cairo_move_to(cr, x1, y1-1); + cairo_line_to(cr, x1, y0+1); + cairo_stroke_preserve(cr); + + if (style < wBoxThickB) { + return; + } + + x0++; + y0++; + x1--; + y1--; + SETCOLOR(style, 0, 1); + cairo_move_to(cr, x0, y0); + cairo_line_to(cr, x0, y1); + cairo_stroke_preserve(cr); + SETCOLOR(style, 1, 1); + cairo_move_to(cr, x0+1, y0); + cairo_line_to(cr, x1, y0); + cairo_stroke_preserve(cr); + SETCOLOR(style, 2, 1); + cairo_move_to(cr, x1, y1); + cairo_line_to(cr, x0+1, y1); + cairo_stroke_preserve(cr); + SETCOLOR(style, 3, 1); + cairo_move_to(cr, x1, y1-1); + cairo_line_to(cr, x1, y0+1); + cairo_stroke_preserve(cr); + cairo_destroy(cr); +} + +/** + * Force repainting of box window + * + * \param b IN box window + * \return + */ + +static void boxRepaint(wControl_p b) +{ + wBox_p bb = (wBox_p)(b); + wWin_p win = bb->parent; + wlibDrawBox(win, bb->boxTyp, bb->realX, bb->realY, bb->w, bb->h); +} + +/** + * Create new box + * + * \param parent IN parent window + * \param bx IN x position + * \param by IN y position + * \param labelStr IN label text (ignored) + * \param boxTyp IN style + * \param bw IN x width + * \param by IN y width + * \return window handle for newly created box + */ + +wBox_p wBoxCreate( + wWin_p parent, + wPos_t bx, + wPos_t by, + const char * labelStr, + wBoxType_e boxTyp, + wPos_t bw, + wPos_t bh) +{ + wBox_p b; + b = (wBox_p)wlibAlloc(parent, B_BOX, bx, by, labelStr, sizeof *b, NULL); + wlibComputePos((wControl_p)b); + b->boxTyp = boxTyp; + b->w = bw; + b->h = bh; + b->repaintProc = boxRepaint; + wlibAddButton((wControl_p)b); + return b; +} diff --git a/app/wlib/gtklib/button.c b/app/wlib/gtklib/button.c new file mode 100644 index 0000000..d9f4880 --- /dev/null +++ b/app/wlib/gtklib/button.c @@ -0,0 +1,630 @@ +/** \file button.c + * Toolbar button creation and handling + */ + +/* 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 +#include + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include +#include + +#include "gtkint.h" +#include "i18n.h" + +#define MIN_BUTTON_WIDTH (80) + +/* + ***************************************************************************** + * + * Simple Buttons + * + ***************************************************************************** + */ + +/** + * Set the state of the button + * + * \param bb IN the button + * \param value IN TRUE for active, FALSE for inactive + */ + +void wButtonSetBusy(wButton_p bb, int value) +{ + bb->recursion++; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bb->widget), value); + bb->recursion--; + bb->busy = value; +} + +/** + * Set the label of a button, does also allow to set an icon + * + * \param widget IN + * \param option IN + * \param labelStr IN + * \param labelG IN + * \param imageG IN + */ + +void wlibSetLabel( + GtkWidget *widget, + long option, + const char * labelStr, + GtkLabel * * labelG, + GtkWidget * * imageG) +{ + wIcon_p bm; + GdkBitmap * mask; + + if (widget == 0) { + abort(); + } + + if (labelStr) { + if (option&BO_ICON) { + GdkPixbuf *pixbuf; + + bm = (wIcon_p)labelStr; + + if (bm->gtkIconType == gtkIcon_pixmap) { + pixbuf = gdk_pixbuf_new_from_xpm_data((const char**)bm->bits); + } else { + pixbuf = wlibPixbufFromXBM( bm ); + } + 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 { + if (*labelG==NULL) { + *labelG = (GtkLabel*)gtk_label_new(wlibConvertInput(labelStr)); + gtk_container_add(GTK_CONTAINER(widget), (GtkWidget*)*labelG); + gtk_widget_show((GtkWidget*)*labelG); + } else { + gtk_label_set_text(*labelG, wlibConvertInput(labelStr)); + } + } + } +} + +/** + * Change only the text label of a button + * \param bb IN button handle + * \param labelStr IN new label string + */ + +void wButtonSetLabel(wButton_p bb, const char * labelStr) +{ + wlibSetLabel(bb->widget, bb->option, labelStr, &bb->labelG, &bb->imageG); +} + +/** + * Perform the user callback function + * + * \param bb IN button handle + */ + +void wlibButtonDoAction( + wButton_p bb) +{ + if (bb->action) { + bb->action(bb->data); + } +} + +/** + * Signal handler for button push + * \param widget IN the widget + * \param value IN the button handle (same as widget???) + */ + +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_active(GTK_TOGGLE_BUTTON(b->widget), FALSE); + b->recursion--; + } +} + +/** + * Create a button + * + * \param parent IN parent window + * \param x IN X-position + * \param y IN Y-position + * \param helpStr IN Help string + * \param labelStr IN Label + * \param option IN Options + * \param width IN Width of button + * \param action IN Callback + * \param data IN User data as context + * \returns button widget + */ + +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 = wlibAlloc(parent, B_BUTTON, x, y, labelStr, sizeof *b, data); + b->option = option; + b->action = action; + wlibComputePos((wControl_p)b); + + b->widget = gtk_toggle_button_new(); + g_signal_connect(GTK_OBJECT(b->widget), "clicked", + G_CALLBACK(pushButt), b); + if (width > 0) { + gtk_widget_set_size_request(b->widget, width, -1); + } + if( labelStr ){ + wButtonSetLabel(b, labelStr); + } + + gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY); + + if (option & BB_DEFAULT) { + gtk_widget_set_can_default(b->widget, GTK_CAN_DEFAULT); + gtk_widget_grab_default(b->widget); + gtk_window_set_default(GTK_WINDOW(parent->gtkwin), b->widget); + } + + wlibControlGetSize((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); + wlibAddButton((wControl_p)b); + wlibAddHelpString(b->widget, helpStr); + return b; +} + + +/* + ***************************************************************************** + * + * Choice Boxes + * + ***************************************************************************** + */ + +struct wChoice_t { + WOBJ_COMMON + long *valueP; + wChoiceCallBack_p action; + int recursion; +}; + + +/** + * Get the state of a group of buttons. If the group consists of + * radio buttons, the return value is the index of the selected button + * or -1 for none. If toggle buttons are checked, a bit is set for each + * button that is active. + * + * \param bc IN + * \returns state of group + */ + +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_get_children(GTK_CONTAINER(bc->widget)),inx=0; + child; child=child->next,inx++) { + if (gtk_toggle_button_get_active(child->data)) { + if (bc->type == B_TOGGLE) { + value |= (1<widget)),inx=0; + child; child=child->next,inx++) { + if (inx == value) { + bc->recursion++; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(child->data), TRUE); + bc->recursion--; + } + } + + if (children) { + g_list_free(children); + } +} + +/** + * Get the active button from a group of radio buttons + * + * \param bc IN + * \returns + */ + +long wRadioGetValue( + wChoice_p bc) /* Radio box */ +{ + return choiceGetValue(bc); +} + +/** + * Set a group of toggle buttons from a bitfield + * + * \param bc IN button group + * \param value IN bitfield + */ + +void wToggleSetValue( + wChoice_p bc, /* Toggle box */ + long value) /* Values */ +{ + GList * child, * children; + long inx; + bc->recursion++; + + for (children=child=gtk_container_get_children(GTK_CONTAINER(bc->widget)),inx=0; + child; child=child->next,inx++) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(child->data), + (value&(1<recursion--; +} + + +/** + * Get the active buttons from a group of toggle buttons + * + * \param b IN + * \returns + */ + +long wToggleGetValue( + wChoice_p b) /* Toggle box */ +{ + return choiceGetValue(b); +} + +/** + * Signal handler for button selection in radio buttons and toggle + * button group + * + * \param widget IN the button group + * \param b IN user data (button group????) + * \returns always 1 + */ + +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_get_active(GTK_TOGGLE_BUTTON(widget)))) { + return 1; + } + + if (bc->recursion) { + return 1; + } + + if (bc->valueP) { + *bc->valueP = value; + } + + if (bc->action) { + bc->action(value, bc->data); + } + + return 1; +} + +/** + * Signal handler used to draw a frame around a widget, used to visually + * group several buttons together + * + * \param b IN widget + */ + +static void choiceRepaint( + wControl_p b) +{ + wChoice_p bc = (wChoice_p)b; + + if (gtk_widget_get_visible(b->widget)) { + wlibDrawBox(bc->parent, wBoxBelow, bc->realX-1, bc->realY-1, bc->w+1, bc->h+1); + } +} + +/** + * Create a group of radio buttons. + * + * \param parent IN parent window + * \param x IN X-position + * \param y IN Y-position + * \param helpStr IN Help string + * \param labelStr IN Label + * \param option IN Options + * \param labels IN Labels + * \param valueP IN Selected value + * \param action IN Callback + * \param data IN User data as context + * \returns radio button widget + */ + +wChoice_p wRadioCreate( + wWin_p parent, + wPos_t x, + wPos_t y, + const char * helpStr, + const char * labelStr, + long option, + const char **labels, + long *valueP, + wChoiceCallBack_p action, + void *data) +{ + 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 = wlibAlloc(parent, B_RADIO, x, y, labelStr, sizeof *b, data); + b->option = option; + b->action = action; + b->valueP = valueP; + wlibComputePos((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_get_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); + g_signal_connect(GTK_OBJECT(butt), "toggled", + G_CALLBACK(pushChoice), b); + wlibAddHelpString(butt, helpStr); + } + + if (option & BB_DEFAULT) { + gtk_widget_set_can_default(b->widget, TRUE); + gtk_widget_grab_default(b->widget); + } + + if (valueP) { + wRadioSetValue(b, *valueP); + } + + if ((option & BC_NOBORDER)==0) { + b->repaintProc = choiceRepaint; + b->w += 2; + b->h += 2; + } + + 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); + return b; +} + +/** + * Create a group of toggle buttons. + * + * \param parent IN parent window + * \param x IN X-position + * \param y IN Y-position + * \param helpStr IN Help string + * \param labelStr IN Label + * \param option IN Options + * \param labels IN Labels + * \param valueP IN Selected value + * \param action IN Callback + * \param data IN User data as context + * \returns toggle button widget + */ + +wChoice_p wToggleCreate( + wWin_p parent, + wPos_t x, + wPos_t y, + const char * helpStr, + const char * labelStr, + long option, + const char **labels, + long *valueP, + wChoiceCallBack_p action, + void *data) +{ + wChoice_p b; + const char ** label; + + if ((option & BC_NOBORDER)==0) { + if (x>=0) { + x++; + } else { + x--; + } + + if (y>=0) { + y++; + } else { + y--; + } + } + + b = wlibAlloc(parent, B_TOGGLE, x, y, labelStr, sizeof *b, data); + b->option = option; + b->action = action; + wlibComputePos((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++) { + GtkWidget *butt; + + butt = gtk_check_button_new_with_label(_(*label)); + gtk_box_pack_start(GTK_BOX(b->widget), butt, TRUE, TRUE, 0); + gtk_widget_show(butt); + g_signal_connect(GTK_OBJECT(butt), "toggled", + G_CALLBACK(pushChoice), b); + wlibAddHelpString(butt, helpStr); + } + + if (valueP) { + wToggleSetValue(b, *valueP); + } + + if ((option & BC_NOBORDER)==0) { + b->repaintProc = choiceRepaint; + b->w += 2; + b->h += 2; + } + + 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); + return b; +} diff --git a/app/wlib/gtklib/color.c b/app/wlib/gtklib/color.c new file mode 100644 index 0000000..64b96ef --- /dev/null +++ b/app/wlib/gtklib/color.c @@ -0,0 +1,466 @@ +/** \file color.c + * code for the color selection dialog and color button + */ + +/* 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 +#include +#ifdef HAVE_MALLOC_H +#include +#endif + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include +#include + +#include "gtkint.h" + +wDrawColor wDrawColorWhite; +wDrawColor wDrawColorBlack; + +#define RGB(R,G,B) ( ((long)((R)&0xFF)<<16) | ((long)((G)&0xFF)<<8) | ((long)((B)&0xFF)) ) + +#define MAX_COLOR_DISTANCE (3) + +static GArray *colorMap_garray = NULL; // Change to use glib array + +static colorMap_t colorMap[] = { + { 255, 255, 255 }, /* White */ + { 0, 0, 0 }, /* Black */ + { 255, 0, 0 }, /* Red */ + { 0, 255, 0 }, /* Green */ + { 0, 0, 255 }, /* Blue */ + { 255, 255, 0 }, /* Yellow */ + { 255, 0, 255 }, /* Purple */ + { 0, 255, 255 }, /* Aqua */ + { 128, 0, 0 }, /* Dk. Red */ + { 0, 128, 0 }, /* Dk. Green */ + { 0, 0, 128 }, /* Dk. Blue */ + { 128, 128, 0 }, /* Dk. Yellow */ + { 128, 0, 128 }, /* Dk. Purple */ + { 0, 128, 128 }, /* Dk. Aqua */ + { 65, 105, 225 }, /* Royal Blue */ + { 0, 191, 255 }, /* DeepSkyBlue */ + { 125, 206, 250 }, /* LightSkyBlue */ + { 70, 130, 180 }, /* Steel Blue */ + { 176, 224, 230 }, /* Powder Blue */ + { 127, 255, 212 }, /* Aquamarine */ + { 46, 139, 87 }, /* SeaGreen */ + { 152, 251, 152 }, /* PaleGreen */ + { 124, 252, 0 }, /* LawnGreen */ + { 50, 205, 50 }, /* LimeGreen */ + { 34, 139, 34 }, /* ForestGreen */ + { 255, 215, 0 }, /* Gold */ + { 188, 143, 143 }, /* RosyBrown */ + { 139, 69, 19 }, /* SaddleBrown */ + { 245, 245, 220 }, /* Beige */ + { 210, 180, 140 }, /* Tan */ + { 210, 105, 30 }, /* Chocolate */ + { 165, 42, 42 }, /* Brown */ + { 255, 165, 0 }, /* Orange */ + { 255, 127, 80 }, /* Coral */ + { 255, 99, 71 }, /* Tomato */ + { 255, 105, 180 }, /* HotPink */ + { 255, 192, 203 }, /* Pink */ + { 176, 48, 96 }, /* Maroon */ + { 238, 130, 238 }, /* Violet */ + { 160, 32, 240 }, /* Purple */ + { 16, 16, 16 }, /* Gray */ + { 32, 32, 32 }, /* Gray */ + { 48, 48, 48 }, /* Gray */ + { 64, 64, 64 }, /* Gray */ + { 80, 80, 80 }, /* Gray */ + { 96, 96, 96 }, /* Gray */ + { 112, 112, 122 }, /* Gray */ + { 128, 128, 128 }, /* Gray */ + { 144, 144, 144 }, /* Gray */ + { 160, 160, 160 }, /* Gray */ + { 176, 176, 176 }, /* Gray */ + { 192, 192, 192 }, /* Gray */ + { 208, 208, 208 }, /* Gray */ + { 224, 224, 224 }, /* Gray */ + { 240, 240, 240 }, /* Gray */ + { 0, 0, 0 } /* BlackPixel */ +}; + +#define NUM_GRAYS (16) + +static GdkColormap * gtkColorMap; + +static char lastColorChar = '!'; + +/** + * Get a gray color + * + * \param percent IN gray value required + * \return definition for gray color + */ + +wDrawColor wDrawColorGray( + int percent) +{ + int n; + long rgb; + n = (percent * (NUM_GRAYS+1)) / 100; + + if (n <= 0) { + return wDrawColorBlack; + } else if (n > NUM_GRAYS) { + return wDrawColorWhite; + } else { + n = (n*256)/NUM_GRAYS; + rgb = RGB(n, n, n); + return wDrawFindColor(rgb); + } +} + +/** + * Get the color map for the main window + * + * \return + */ + +void wlibGetColorMap(void) +{ + if (gtkColorMap) { + return; + } + + gtkColorMap = gtk_widget_get_colormap(gtkMainW->widget); + return; +} + +/** + * Initialize a colorMap entry + * \todo no idea what this is required for + * + * \param t IN color code + * \return + */ + +static void init_colorMapValue(colorMap_t * t) +{ + t->rgb = RGB(t->red, t->green, t->blue); + t->normalColor.red = t->red*65535/255; + t->normalColor.green = t->green*65535/255; + t->normalColor.blue = t->blue*65535/255; + gdk_colormap_alloc_color(gtkColorMap, &t->normalColor, FALSE, TRUE); + t->invertColor = t->normalColor; + t->invertColor.pixel ^= g_array_index(colorMap_garray, colorMap_t, + wDrawColorWhite).normalColor.pixel; + t->colorChar = lastColorChar++; + + if (lastColorChar >= 0x7F) { + lastColorChar = '!'+1; + } else if (lastColorChar == '"') { + lastColorChar++; + } +} + +/** + * Allocate a color map and initialize with application default colors + * + * \return + */ + +static void init_colorMap(void) +{ + int gint; + colorMap_garray = g_array_sized_new(TRUE, TRUE, sizeof(colorMap_t), + sizeof(colorMap)/sizeof(colorMap_t)); + g_array_append_vals(colorMap_garray, &colorMap, + sizeof(colorMap)/sizeof(colorMap_t)); + + for (gint=0; gintlen; gint++) { + init_colorMapValue(&g_array_index(colorMap_garray, colorMap_t, gint)); + } +} + +/** + * Find the closest color from the palette and add a new color if there + * is no close match + * \todo improve method for finding best match (squared distances) + * + * \param rgb0 IN desired color + * \return palette index of matching color + */ + +wDrawColor wDrawFindColor( + long rgb0) +{ + wDrawColor cc; + int r0, g0, b0; + int d0; + int i; + colorMap_t tempMapValue; + wlibGetColorMap(); + cc = wDrawColorBlack; + r0 = (int)(rgb0>>16)&0xFF; + g0 = (int)(rgb0>>8)&0xFF; + b0 = (int)(rgb0)&0xFF; + d0 = 256*3; + + // Initialize garray if needed + if (colorMap_garray == NULL) { + init_colorMap(); + } + + // Iterate over entire garray + for (i=0; ilen; i++) { + int d1; + colorMap_t * cm_p; + + cm_p = &g_array_index(colorMap_garray, colorMap_t, i); + d1 = abs(r0-cm_p->red) + abs(g0-cm_p->green) + abs(b0-cm_p->blue); + + if (d1 == 0) { + return i; + } + + if (d1 < d0) { + d0 = d1; + cc = i; + } + } + + if (d0 <= MAX_COLOR_DISTANCE) { + return cc; + } + + // No good value - so add one + tempMapValue.red = r0; + tempMapValue.green = g0; + tempMapValue.blue = b0; + init_colorMapValue(&tempMapValue); + g_array_append_val(colorMap_garray,tempMapValue); + return i; +} + +/** + * Get the RGB code for a palette entry + * + * \param color IN the palette index + * \return RGB code + */ + +long wDrawGetRGB( + wDrawColor color) +{ + colorMap_t * colorMap_e; + wlibGetColorMap(); + + if (colorMap_garray == NULL) { + init_colorMap(); + } + + if (color < 0 || color > colorMap_garray->len) { + abort(); + } + + colorMap_e = &g_array_index(colorMap_garray, colorMap_t, color); + return colorMap_e->rgb; +} + +/** + * Get the color definition from the palette index + * + * \param color IN index into palette + * \param normal IN normal or inverted color + * \return the selected color definition + */ + +GdkColor* wlibGetColor( + wDrawColor color, + wBool_t normal) +{ + colorMap_t * colorMap_e; + wlibGetColorMap(); + + if (colorMap_garray == NULL) { + init_colorMap(); + } + + if (color < 0 || color > colorMap_garray->len) { + abort(); + } + + colorMap_e = &g_array_index(colorMap_garray, colorMap_t, color); + + if (normal) { + return &colorMap_e->normalColor; + } else { + return &colorMap_e->invertColor; + } +} + + +/* + ***************************************************************************** + * + * Color Selection Button + * + ***************************************************************************** + */ + +typedef struct { + wDrawColor * valueP; + const char * labelStr; + wColorSelectButtonCallBack_p action; + void * data; + wDrawColor color; + wButton_p button; +} colorData_t; + +/** + * Handle the color-set signal. + * + * \param widget color button + * \param user_data + */ + +static void +colorChange(GtkColorButton *widget, gpointer user_data) +{ + colorData_t *cd = user_data; + GdkColor newcolor; + long rgb; + + gtk_color_button_get_color(widget, &newcolor); + + rgb = RGB((int)(newcolor.red/256), (int)(newcolor.green/256), + (int)(newcolor.blue/256)); + cd->color = wDrawFindColor(rgb); + + if (cd->valueP) { + *(cd->valueP) = cd->color; + } + + if (cd->action) { + cd->action(cd->data, cd->color); + } +} + +/** + * Set the color for a color button + * + * \param bb IN button + * \param color IN palette index for color to use + * \return describe the return value + */ + +void wColorSelectButtonSetColor( + wButton_p bb, + wDrawColor color) +{ + GdkColor *colorOfButton = wlibGetColor(color, TRUE); + + gtk_color_button_set_color(GTK_COLOR_BUTTON(bb->widget), + colorOfButton); + ((colorData_t*)((wControl_p)bb)->data)->color = color; +} + + +/** + * Get the current palette index for a color button + * + * \param bb IN button handle + * \return palette index + */ + +wDrawColor wColorSelectButtonGetColor( + wButton_p bb) +{ + return ((colorData_t*)((wControl_p)bb)->data)->color; +} + +/** + * Create the button showing the current paint color and starting the color selection dialog. + * + * \param IN parent parent window + * \param IN x x coordinate + * \param IN Y y coordinate + * \param IN helpStr balloon help string + * \param IN labelStr Button label ??? + * \param IN option + * \param IN width + * \param IN valueP Current color ??? + * \param IN action Button callback procedure + * \param IN data ??? + * \return bb handle for created button + */ + +wButton_p wColorSelectButtonCreate( + wWin_p parent, + wPos_t x, + wPos_t y, + const char * helpStr, + const char * labelStr, + long option, + wPos_t width, + wDrawColor *valueP, + wColorSelectButtonCallBack_p action, + void * data) +{ + wButton_p b; + colorData_t * cd; + cd = malloc(sizeof(colorData_t)); + cd->valueP = valueP; + cd->action = action; + cd->data = data; + cd->labelStr = labelStr; + cd->color = (valueP?*valueP:0); + + b = wlibAlloc(parent, B_BUTTON, x, y, labelStr, sizeof *b, cd); + b->option = option; + wlibComputePos((wControl_p)b); + + b->widget = gtk_color_button_new(); + GtkStyle *style; + style = gtk_widget_get_style(b->widget); + style->xthickness = 1; + style->ythickness = 1; + gtk_widget_set_style(b->widget, style); + gtk_widget_set_size_request(GTK_WIDGET(b->widget), 22, 22); + g_signal_connect(GTK_OBJECT(b->widget), "color-set", + G_CALLBACK(colorChange), cd); + + gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY); + + if (option & BB_DEFAULT) { + gtk_widget_set_can_default(b->widget, GTK_CAN_DEFAULT); + gtk_widget_grab_default(b->widget); + gtk_window_set_default(GTK_WINDOW(parent->gtkwin), b->widget); + } + + wlibControlGetSize((wControl_p)b); + + gtk_widget_show(b->widget); + wlibAddButton((wControl_p)b); + wlibAddHelpString(b->widget, helpStr); + wColorSelectButtonSetColor(b, (valueP?*valueP:0)); + + if (labelStr) { + ((wControl_p)b)->labelW = wlibAddLabel((wControl_p)b, labelStr); + } + return b; +} diff --git a/app/wlib/gtklib/control.c b/app/wlib/gtklib/control.c new file mode 100644 index 0000000..e824c94 --- /dev/null +++ b/app/wlib/gtklib/control.c @@ -0,0 +1,283 @@ +/** \file control.c + * Control Utilities + */ +/* + * Copyright 2016 Martin Fischer + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + +#include +#include + +#define GTK_DISABLE_SINGLE_INCLUDES +#define GDK_DISABLE_DEPRECATED +#define GTK_DISABLE_DEPRECATED +#define GSEAL_ENABLE + +#include +#include + +#include "gtkint.h" + +#define GTKCONTROLHILITEWIDTH (3) + +/** + * Cause the control to be displayed or hidden. + * Used to hide control (such as a list) while it is being updated. + * + * \param b IN Control + * \param show IN TRUE for visible + */ + +void wControlShow( + wControl_p b, + wBool_t show) +{ + if (b->type == B_LINES) { + wlibLineShow((wLine_p)b, show); + return; + } + + if (b->widget == NULL) { + abort(); + } + + if (show) { + gtk_widget_show(b->widget); + + if (b->label) { + gtk_widget_show(b->label); + } + } else { + gtk_widget_hide(b->widget); + + if (b->label) { + gtk_widget_hide(b->label); + } + } +} + +/** + * Cause the control to be marked active or inactive. + * Inactive controls donot respond to actions. + * + * \param b IN Control + * \param active IN TRUE for active + */ + +void wControlActive( + wControl_p b, + int active) +{ + if (b->widget == NULL) { + abort(); + } + + gtk_widget_set_sensitive(GTK_WIDGET(b->widget), active); +} + +/** + * Returns the width of