/** \file control.c * Control Utilities */ /* * Copyright 2016 Martin Fischer <m_fischer@sf.net> * * 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 <stdio.h> #include <stdlib.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" #define GTKCONTROLHILITEWIDTH (4) /** * Cause the control <b> 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 <b> 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(); } if (b->type == B_LIST || b->type == B_DROPLIST ) { gtk_widget_set_sensitive(gtk_bin_get_child(GTK_BIN(b->widget)), active); gtk_combo_box_set_button_sensitivity(GTK_COMBO_BOX(b->widget), active?GTK_SENSITIVITY_ON:GTK_SENSITIVITY_OFF); } else { gtk_widget_set_sensitive(GTK_WIDGET(b->widget), active); } } /** * Returns the width of <label>. * This is used for computing window layout. * Typically the width to the longest label is computed and used as * the X-position for <controls>. * * \param label IN label * \returns width of label including some space */ wWinPix_t wLabelWidth( const char * label) { GtkWidget * widget; GtkRequisition requisition; widget = gtk_label_new(wlibConvertInput(label)); gtk_widget_size_request(widget, &requisition); g_object_ref_sink (widget); gtk_widget_destroy(widget); g_object_unref(widget); return requisition.width+8; } /** * Get width of a control * * \param b IN Control * \returns width */ wWinPix_t wControlGetWidth( wControl_p b) { return b->w; } /** * Get height of a control * * \param b IN Control * \returns height */ wWinPix_t wControlGetHeight( wControl_p b) { return b->h; } /** * Get x position of a control * * \param b IN Control * \returns position */ wWinPix_t wControlGetPosX( wControl_p b) /* Control */ { return b->realX; } /** * Get y position of a control * * \param b IN Control * \returns position */ wWinPix_t wControlGetPosY( wControl_p b) /* Control */ { return b->realY - BORDERSIZE - ((b->parent->option&F_MENUBAR) ?b->parent->menu_height:0); } /** * Set the fixed position of a control within its parent window * * \param b IN control * \param x IN x position * \param y IN y position */ void wControlSetPos( wControl_p b, wWinPix_t x, wWinPix_t y) { b->realX = x; b->realY = y + BORDERSIZE + ((b->parent->option&F_MENUBAR) ?b->parent->menu_height:0); if (b->widget) { gtk_fixed_move(GTK_FIXED(b->parent->widget), b->widget, b->realX, b->realY); } if (b->label) { GtkRequisition requisition, reqwidget; gtk_widget_size_request(b->label, &requisition); if (b->widget) { gtk_widget_size_request(b->widget, &reqwidget); } else { reqwidget.height = requisition.height; } gtk_fixed_move(GTK_FIXED(b->parent->widget), b->label, b->realX-b->labelW, b->realY+(reqwidget.height/2 - requisition.height/2)); } } /** * Set the label for a control * * \param b IN control * \param labelStr IN the new label */ void wControlSetLabel( wControl_p b, const char * labelStr) { GtkRequisition requisition,reqwidget; if (b->label) { gtk_label_set_text(GTK_LABEL(b->label), wlibConvertInput(labelStr)); gtk_widget_size_request(b->label, &requisition); if (b->widget) { gtk_widget_size_request(b->widget, &reqwidget); } else { reqwidget.height = requisition.height; } b->labelW = requisition.width+8; gtk_fixed_move(GTK_FIXED(b->parent->widget), b->label, b->realX-b->labelW, b->realY+(reqwidget.height/2 - requisition.height/2)); } else { b->labelW = wlibAddLabel(b, labelStr); } } /** * Set the context ie. additional user data for a control * * \param b IN control * \param context IN user date */ void wControlSetContext( wControl_p b, void * context) { b->data = context; } /** * Not implemented * * \param b IN */ void wControlSetFocus( wControl_p b) { } wBool_t wControlExpose ( GtkWidget * widget, GdkEventExpose * event, wControl_p b ) { GdkWindow * win = gtk_widget_get_window(b->widget); cairo_t * cr = NULL; if (win) { cr = gdk_cairo_create(win); } else { return TRUE; } if (b->outline) { cairo_set_source_rgb(cr, 0.23, 0.37, 0.80); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_line_width(cr, GTKCONTROLHILITEWIDTH); cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); cairo_rectangle(cr,event->area.x+2, event->area.y+2, event->area.width-4, event->area.height-4); cairo_stroke(cr); } cairo_destroy(cr); return FALSE; } /** * Draw a rectangle around a control * \param b IN the control * \param hilite IN unused * \returns * * */ void wControlHilite( wControl_p b, wBool_t hilite) { // cairo_t *cr; // int off = GTKCONTROLHILITEWIDTH/2+1; if ( debugWindow >= 1 ) { printf( "wControlHIlite( %s, %d )\n", b->labelStr, hilite ); } if (b->widget == NULL) { return; } b->outline = hilite; if (b->widget) { gtk_widget_queue_draw(b->widget); } }