/* -*- Mode: C; c-basic-offset: 4 -*- * pygtk- Python bindings for the GTK toolkit. * Copyright (C) 1998-2003 James Henstridge * * gdkcolor.override: gtk.gdk.Color and gtk.gdk.ColorMap overrides * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA */ %% ignore gdk_color_copy gdk_color_free gdk_color_hash gdk_color_equal %% override gdk_color_new kwargs static int _wrap_gdk_color_new(PyGBoxed *self, PyObject *args, PyObject *kwargs) { static char *kwlist1[] = {"red", "green", "blue", "pixel", NULL }; static char *kwlist2[] = { "spec", NULL }; PyObject *red = Py_None, *green = Py_None, *blue = Py_None; const char *spec = NULL; GdkColor colour; /* Note: this constructor has become quite complicated, because it * is heavily overloaded. Additionally, we try to optimize a * little. */ if (PyArg_ParseTupleAndKeywords(args, kwargs, "|s:gdk.Color", kwlist2, &spec)) { if (!spec) memset(&colour, 0, sizeof(colour)); else if (!gdk_color_parse(spec, &colour)) { PyErr_SetString(PyExc_ValueError, "unable to parse colour specification"); return -1; } goto success; } PyErr_Clear(); if (PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOk:gdk.Color", kwlist1, &red, &green, &blue, &colour.pixel)) { /* We don't allow mixing floats and non-floats as that is too * error-prone. All non-floats are deemed integers in case * they have __int__() method. */ int have_floats = 0; int have_nonfloats = 0; if (red == Py_None) colour.red = 0; else { if (PyFloat_Check(red)) { have_floats = 1; colour.red = MIN(MAX(0.0, PyFloat_AsDouble(red)), 1.0) * 65535.0; } else { have_nonfloats = 1; colour.red = PyInt_AsLong(red); } } if (PyErr_Occurred()) return -1; if (green == Py_None) colour.green = 0; else { if (PyFloat_Check(green)) { if (have_nonfloats) goto mixed_types_error; have_floats = 1; colour.green = MIN(MAX(0.0, PyFloat_AsDouble(green)), 1.0) * 65535.0; } else { if (have_floats) goto mixed_types_error; have_nonfloats = 1; colour.green = PyInt_AsLong(green); } } if (PyErr_Occurred()) return -1; if (blue == Py_None) colour.blue = 0; else { if (PyFloat_Check(blue)) { if (have_nonfloats) goto mixed_types_error; colour.blue = MIN(MAX(0.0, PyFloat_AsDouble(blue)), 1.0) * 65535.0; } else { if (have_floats) goto mixed_types_error; colour.blue = PyInt_AsLong(blue); } } if (PyErr_Occurred()) return -1; goto success; mixed_types_error: PyErr_SetString(PyExc_TypeError, "arguments must either be all integers or all floats"); return -1; } PyErr_Clear(); PyErr_SetString(PyExc_TypeError, "Usage:\n" " gtk.gdk.Color(red, green, blue, pixel) [all are optional]\n" " gtk.gdk.Color(spec) [see gtk.gdk.color_parse()]"); return -1; success: self->boxed = g_boxed_copy(GDK_TYPE_COLOR, &colour); self->free_on_dealloc = TRUE; self->gtype = GDK_TYPE_COLOR; return 0; } %% define color_from_hsv kwargs static PyObject * _wrap_color_from_hsv (PyObject *ignored, PyObject *args, PyObject*kwargs) { static char *kwlist[] = { "hue", "saturation", "value", NULL }; gdouble hue, saturation, value; gdouble red, green, blue; GdkColor color; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ddd:gtk.gdk.color_from_hsv", kwlist, &hue, &saturation, &value)) return NULL; /* See documentation of the class for rationale. */ hue -= floor(hue); if (saturation > 1.0) saturation = 1.0; else if (saturation < 0.0) saturation = 0.0; if (value > 1.0) value = 1.0; else if (value < 0.0) value = 0.0; gtk_hsv_to_rgb(hue, saturation, value, &red, &green, &blue); color.red = red * 65535.0; color.green = green * 65535.0; color.blue = blue * 65535.0; return pyg_boxed_new(GDK_TYPE_COLOR, &color, TRUE, TRUE); } %% override-attr GdkColor.red static int _wrap_gdk_color__set_red(PyObject *self, PyObject *value, void *closure) { long red = PyInt_AsLong(value); if (red == -1 && PyErr_Occurred()) return -1; else { pyg_boxed_get(self, GdkColor)->red = red; return 0; } } %% override-attr GdkColor.blue static int _wrap_gdk_color__set_blue(PyObject *self, PyObject *value, void *closure) { long blue = PyInt_AsLong(value); if (blue == -1 && PyErr_Occurred()) return -1; else { pyg_boxed_get(self, GdkColor)->blue = blue; return 0; } } %% override-attr GdkColor.green static int _wrap_gdk_color__set_green(PyObject *self, PyObject *value, void *closure) { long green = PyInt_AsLong(value); if (green == -1 && PyErr_Occurred()) return -1; else { pyg_boxed_get(self, GdkColor)->green = green; return 0; } } %% override-attr GdkColor.pixel static int _wrap_gdk_color__set_pixel(PyObject *self, PyObject *value, void *closure) { long pixel = PyInt_AsLong(value); if (pixel == -1 && PyErr_Occurred()) return -1; else { pyg_boxed_get(self, GdkColor)->pixel = pixel; return 0; } } %% override-attr GdkColor.red_float static PyObject * _wrap_gdk_color__get_red_float(PyObject *self, void *closure) { return PyFloat_FromDouble(pyg_boxed_get(self, GdkColor)->red / 65535.0); } static int _wrap_gdk_color__set_red_float(PyObject *self, PyObject *value, void *closure) { double red = PyFloat_AsDouble(value); if (red == -1 && PyErr_Occurred()) return -1; else { pyg_boxed_get(self, GdkColor)->red = MIN(MAX(0.0, red), 1.0) * 65535.0; return 0; } } %% override-attr GdkColor.green_float static PyObject * _wrap_gdk_color__get_green_float(PyObject *self, void *closure) { return PyFloat_FromDouble(pyg_boxed_get(self, GdkColor)->green / 65535.0); } static int _wrap_gdk_color__set_green_float(PyObject *self, PyObject *value, void *closure) { double green = PyFloat_AsDouble(value); if (green == -1 && PyErr_Occurred()) return -1; else { pyg_boxed_get(self, GdkColor)->green = MIN(MAX(0.0, green), 1.0) * 65535.0; return 0; } } %% override-attr GdkColor.blue_float static PyObject * _wrap_gdk_color__get_blue_float(PyObject *self, void *closure) { return PyFloat_FromDouble(pyg_boxed_get(self, GdkColor)->blue / 65535.0); } static int _wrap_gdk_color__set_blue_float(PyObject *self, PyObject *value, void *closure) { double blue = PyFloat_AsDouble(value); if (blue == -1 && PyErr_Occurred()) return -1; else { pyg_boxed_get(self, GdkColor)->blue = MIN(MAX(0.0, blue), 1.0) * 65535.0; return 0; } } %% override-attr GdkColor.hue static PyObject * _wrap_gdk_color__get_hue(PyObject *self, void *closure) { GdkColor *color = pyg_boxed_get(self, GdkColor); gdouble red = color->red / 65535.0; gdouble green = color->green / 65535.0; gdouble blue = color->blue / 65535.0; gdouble hue; gtk_rgb_to_hsv(red, green, blue, &hue, NULL, NULL); return PyFloat_FromDouble(hue); } %% override-attr GdkColor.saturation static PyObject * _wrap_gdk_color__get_saturation(PyObject *self, void *closure) { GdkColor *color = pyg_boxed_get(self, GdkColor); gdouble red = color->red / 65535.0; gdouble green = color->green / 65535.0; gdouble blue = color->blue / 65535.0; gdouble saturation; gtk_rgb_to_hsv(red, green, blue, NULL, &saturation, NULL); return PyFloat_FromDouble(saturation); } %% override-attr GdkColor.value static PyObject * _wrap_gdk_color__get_value(PyObject *self, void *closure) { GdkColor *color = pyg_boxed_get(self, GdkColor); gdouble red = color->red / 65535.0; gdouble green = color->green / 65535.0; gdouble blue = color->blue / 65535.0; gdouble value; gtk_rgb_to_hsv(red, green, blue, NULL, NULL, &value); return PyFloat_FromDouble(value); } %% override gdk_color_parse kwargs static PyObject * _wrap_gdk_color_parse(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "spec", NULL }; const char *spec; GdkColor colour = { 0, }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:color_parse", kwlist, &spec)) return NULL; if (!gdk_color_parse(spec, &colour)) { PyErr_SetString(PyExc_ValueError, "unable to parse colour specification"); return NULL; } /* pyg_boxed_new handles NULL checking */ return pyg_boxed_new (GDK_TYPE_COLOR, &colour, TRUE, TRUE); } %% override gdk_colormap_alloc_color kwargs static PyObject * _wrap_gdk_colormap_alloc_color(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist1[] = { "red", "green", "blue", "writeable", "best_match", NULL }; static char *kwlist2[] = { "spec", "writeable", "best_match", NULL }; static char *kwlist3[] = { "color", "writeable", "best_match", NULL }; GdkColor colour = { 0, 0, 0, 0 }; gboolean writeable = FALSE; gboolean best_match = TRUE; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "HHH|ii:GdkColormap.alloc_color", kwlist1, &colour.red, &colour.green, &colour.blue, &writeable, &best_match)) { PyObject *pycolour; PyErr_Clear(); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|ii:GdkColormap.alloc_color", kwlist3, &pycolour, &writeable, &best_match)) { return NULL; } if (!pyg_boxed_check(pycolour, GDK_TYPE_COLOR)) { gchar *color_name; PyErr_Clear(); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ii:GdkColormap.alloc_color", kwlist2, &color_name, &writeable, &best_match)) { return NULL; } if (!gdk_color_parse(color_name, &colour)) { PyErr_SetString(PyExc_ValueError, "unable to parse colour specification"); return NULL; } } else { colour = *pyg_boxed_get(pycolour, GdkColor); } } if (!gdk_colormap_alloc_color(GDK_COLORMAP(self->obj), &colour, writeable, best_match)) { PyErr_SetString(PyExc_RuntimeError, "couldn't allocate colour"); return NULL; } return pyg_boxed_new(GDK_TYPE_COLOR, &colour, TRUE, TRUE); } %% override gdk_color_alloc kwargs static PyObject * _wrap_gdk_color_alloc(PyGObject *self, PyObject *args, PyObject *kwargs) { if (!PyErr_Warn(PyExc_DeprecationWarning, "use GdkColormap.alloc_color")<0) return NULL; return _wrap_gdk_colormap_alloc_color(self, args, kwargs); } %% override-slot GdkColor.tp_richcompare static PyObject * _wrap_gdk_color_tp_richcompare(PyObject *self, PyObject *other, int op) { PyObject *result; if (PyObject_TypeCheck(self, &PyGdkColor_Type) && PyObject_TypeCheck(other, &PyGdkColor_Type)) { GdkColor *color1 = pyg_boxed_get(self, GdkColor); GdkColor *color2 = pyg_boxed_get(other, GdkColor); switch (op) { case Py_EQ: result = (gdk_color_equal(color1, color2) ? Py_True : Py_False); break; case Py_NE: result = (!gdk_color_equal(color1, color2) ? Py_True : Py_False); break; default: result = Py_NotImplemented; } } else result = Py_NotImplemented; Py_INCREF(result); return result; } %% override-slot GdkColor.tp_repr static int pygdk_color_to_string_smart(char *buffer, int length, GdkColor *color) { /* We use g_snprintf() because PyString_FromFormat() doesn't support %0Nx-like formats * (i.e. with leading zeros). * * Note that numbers here are used so that there is no off-by-one errors in * 'eval(repr(color))', i.e. so that 'eval(repr(color)) == color'. See * pango_color_parse() for justification of these numbers. Three-nibble color * components are deemed unimportant. */ if (color->red % 0x1111 == 0 && color->green % 0x1111 == 0 && color->blue % 0x1111 == 0) { return g_snprintf(buffer, length, "#%01x%01x%01x", color->red / 0x1111, color->green / 0x1111, color->blue / 0x1111); } else if (color->red % 0x0101 == 0 && color->green % 0x0101 == 0 && color->blue % 0x0101 == 0) { return g_snprintf(buffer, length, "#%02x%02x%02x", color->red / 0x0101, color->green / 0x0101, color->blue / 0x0101); } else { return g_snprintf(buffer, length, "#%04x%04x%04x", color->red, color->green, color->blue); } } static PyObject * _wrap_gdk_color_tp_repr(PyGBoxed *self) { static char buffer[0x40]; int length = 0; length += g_snprintf(buffer + length, sizeof buffer - length, "%s('", self->ob_type->tp_name); length += pygdk_color_to_string_smart(buffer + length, sizeof buffer - length, pyg_boxed_get(self, GdkColor)); length += g_snprintf(buffer + length, sizeof buffer - length, "')"); return PyString_FromStringAndSize(buffer, length); } %% override-slot GdkColor.tp_str static PyObject * _wrap_gdk_color_tp_str(PyGBoxed *self) { /* gtk.gdk.Color has a meaningful informal representation, so we define both __repr__ * and __str__, unlike for most other types. */ static char buffer[1 + 4*3 + 1]; /* # + at most 4 digits per component + \0 */ int length = pygdk_color_to_string_smart(buffer, sizeof buffer, pyg_boxed_get(self, GdkColor)); return PyString_FromStringAndSize(buffer, length); } %% override gdk_colormap_query_color kwargs static PyObject * _wrap_gdk_colormap_query_color(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "pixel", NULL }; GdkColor colour = { 0, 0, 0, 0 }; PyObject *py_pixel; gulong pixel; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:GdkColormap.query_color", kwlist, &py_pixel)) return NULL; if (PyLong_Check(py_pixel)) { pixel = PyLong_AsUnsignedLong(py_pixel); if (PyErr_Occurred()) return NULL; } else if (PyInt_Check(py_pixel)) pixel = PyInt_AS_LONG(py_pixel); else { PyErr_SetString(PyExc_TypeError, "GdkColormap.query_color: pixel must be" " either int or long"); return NULL; } gdk_colormap_query_color(GDK_COLORMAP(self->obj), pixel, &colour); return pyg_boxed_new(GDK_TYPE_COLOR, &colour, TRUE, TRUE); }