summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tdegtk/Makefile.am15
-rw-r--r--tdegtk/tdegtk-draw.c1062
-rw-r--r--tdegtk/tdegtk-draw.cpp1273
-rw-r--r--tdegtk/tdegtk-hooks.cpp100
-rw-r--r--tdegtk/tdegtk-hooks.h63
-rw-r--r--tdegtk/tdegtk-signals.cpp89
-rw-r--r--tdegtk/tdegtk-signals.h64
-rw-r--r--tdegtk/tdegtk-theme.c51
-rw-r--r--tdegtk/tdegtk-theme.cpp788
-rw-r--r--tdegtk/tdegtk-types.h25
-rw-r--r--tdegtk/tdegtk-utils.cpp1064
-rw-r--r--tdegtk/tdegtk-utils.h428
-rw-r--r--tdegtk/tdegtk-widgetlookup.cpp231
-rw-r--r--tdegtk/tdegtk-widgetlookup.h92
-rw-r--r--tdegtk/tqtcairopainter.cpp14
-rw-r--r--tdegtk/tqtcairopainter.h4
-rwxr-xr-xtests/compare3
-rw-r--r--tests/test-painter.cpp90
18 files changed, 4332 insertions, 1124 deletions
diff --git a/tdegtk/Makefile.am b/tdegtk/Makefile.am
index 208c447..26f45dd 100644
--- a/tdegtk/Makefile.am
+++ b/tdegtk/Makefile.am
@@ -7,6 +7,10 @@ source_h = \
$(srcdir)/tdegtk-draw.h \
$(srcdir)/tdegtk-engine.h \
$(srcdir)/tdegtk-support.h \
+ $(srcdir)/tdegtk-hooks.h \
+ $(srcdir)/tdegtk-signals.h \
+ $(srcdir)/tdegtk-widgetlookup.h \
+ $(srcdir)/tdegtk-utils.h \
$(srcdir)/tdegtk-types.h
source_c = \
@@ -14,10 +18,14 @@ source_c = \
$(srcdir)/gtkroundedbox.c \
$(srcdir)/raico-blur.c \
$(srcdir)/tdegtk-cairo-support.c \
- $(srcdir)/tdegtk-draw.c \
+ $(srcdir)/tdegtk-draw.cpp \
$(srcdir)/tdegtk-engine.c \
$(srcdir)/tdegtk-support.c \
- $(srcdir)/tdegtk-theme.c
+ $(srcdir)/tdegtk-hooks.cpp \
+ $(srcdir)/tdegtk-signals.cpp \
+ $(srcdir)/tdegtk-widgetlookup.cpp \
+ $(srcdir)/tdegtk-utils.cpp \
+ $(srcdir)/tdegtk-theme.cpp
enginedir = $(libdir)/gtk-3.0/$(GTK_VERSION)/theming-engines
engine_LTLIBRARIES = libtdegtk.la
@@ -25,8 +33,9 @@ engine_LTLIBRARIES = libtdegtk.la
libtdegtk_la_SOURCES = $(source_h) $(source_c)
libtdegtk_la_CFLAGS = $(TDEGTK_CFLAGS)
+libtdegtk_la_CXXFLAGS = $(TDEGTK_CXXFLAGS) -I/usr/include/tqt -I/usr/include/tqt3 -I/opt/trinity/include $(TDEGTK_CFLAGS)
-libtdegtk_la_LIBADD = $(TDEGTK_LIBADD)
+libtdegtk_la_LIBADD = $(TDEGTK_LIBADD) libtqtcairo.la -ltqt -ltqt-mt -L/opt/trinity/lib -ltdecore
libtdegtk_la_LDFLAGS = $(TDEGTK_LDFLAGS)
diff --git a/tdegtk/tdegtk-draw.c b/tdegtk/tdegtk-draw.c
deleted file mode 100644
index f1fa2df..0000000
--- a/tdegtk/tdegtk-draw.c
+++ /dev/null
@@ -1,1062 +0,0 @@
-/* The TdeGtk Theming Engine for Gtk+.
- * Copyright (C) 2011 Canonical Ltd
- *
- * 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 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 St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- * Authored by Andrea Cimitan <andrea.cimitan@canonical.com>
- *
- */
-
-#include <cairo.h>
-#include <gtk/gtk.h>
-#include <math.h>
-
-#include "tdegtk-cairo-support.h"
-#include "tdegtk-draw.h"
-#include "tdegtk-support.h"
-#include "tdegtk-types.h"
-
-/* draw a texture placed on the centroid */
-static gboolean
-draw_centroid_texture (GtkThemingEngine *engine,
- cairo_t *cr,
- gdouble x,
- gdouble y,
- gdouble width,
- gdouble height)
-{
- GtkStateFlags state;
- GValue value = { 0, };
- cairo_pattern_t *texture = NULL;
- cairo_surface_t *surface = NULL;
- gboolean retval = FALSE;
-
- state = gtk_theming_engine_get_state (engine);
-
- gtk_theming_engine_get_property (engine, "-tdegtk-centroid-texture", state, &value);
-
- if (!G_VALUE_HOLDS_BOXED (&value))
- return FALSE;
-
- texture = g_value_dup_boxed (&value);
- g_value_unset (&value);
-
- if (texture != NULL)
- cairo_pattern_get_surface (texture, &surface);
-
- if (surface != NULL)
- {
- cairo_save (cr);
-
- cairo_set_source_surface (cr, surface, (gint) (x + width / 2 - cairo_image_surface_get_width (surface) / 2),
- (gint) (y + height / 2 - cairo_image_surface_get_height (surface) / 2));
- cairo_paint (cr);
-
- cairo_restore (cr);
-
- retval = TRUE;
- }
-
- if (texture != NULL)
- cairo_pattern_destroy (texture);
-
- return retval;
-}
-
-static void
-tdegtk_draw_activity (DRAW_ARGS)
-{
- /* playground for effects */
- tdegtk_cairo_draw_background (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
- tdegtk_cairo_draw_frame (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
-}
-
-static void
-tdegtk_draw_arrow (GtkThemingEngine *engine,
- cairo_t *cr,
- gdouble angle,
- gdouble x,
- gdouble y,
- gdouble size)
-{
- GtkStateFlags state;
- GdkRGBA color;
- gdouble size_reduction = 2;
-
- state = gtk_theming_engine_get_state (engine);
-
- gtk_theming_engine_get_color (engine, state, &color);
-
- cairo_save (cr);
-
- /* use floor function to adjust doubles */
- y = floor (y);
- x = floor (x);
- size = floor (size);
-
- size -= size_reduction;
-
- cairo_translate (cr, size_reduction / 2, size_reduction / 2);
- cairo_translate (cr, x + (gint) (size / 2.0) + 0.5, y + (gint) (size / 2.0) + 0.5);
- cairo_rotate (cr, angle - G_PI_2);
- cairo_translate (cr, (gint) (size / 4.0), 0);
-
- /* FIXME this + 1/- 1 is done to fix blurred diagonal lines.
- * I know it's not nice at all, but it fix a visual bug */
- cairo_move_to (cr, - (gint) (size / 2.0), - (gint) (size / 2.0));
- cairo_rel_line_to (cr, (gint) (size / 2.0) + 1, (gint) (size / 2.0));
- cairo_rel_line_to (cr, - (gint) (size / 2.0) - 1, (gint) (size / 2.0));
- cairo_close_path (cr);
-
- cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha * 0.75);
- cairo_fill_preserve (cr);
-
- gdk_cairo_set_source_rgba (cr, &color);
- cairo_stroke (cr);
-
- cairo_restore (cr);
-}
-
-static void
-tdegtk_draw_cell_background (DRAW_ARGS,
- GtkRegionFlags flags)
-{
- GtkJunctionSides junction;
- guint hidden_side;
-
- junction = GTK_JUNCTION_RIGHT | GTK_JUNCTION_LEFT;
-
- hidden_side = SIDE_RIGHT | SIDE_LEFT;
-
- if ((flags & GTK_REGION_FIRST) != 0)
- {
- junction &= ~(GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMLEFT);
- hidden_side &= ~(SIDE_LEFT);
- }
- if ((flags & GTK_REGION_LAST) != 0)
- {
- junction &= ~(GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMRIGHT);
- hidden_side &= ~(SIDE_RIGHT);
- }
-
- tdegtk_cairo_draw_background (engine, cr,
- x, y, width, height,
- hidden_side, junction);
-}
-
-static void
-tdegtk_draw_cell_frame (DRAW_ARGS,
- GtkRegionFlags flags)
-{
- GtkJunctionSides junction;
- guint hidden_side;
-
- junction = GTK_JUNCTION_RIGHT | GTK_JUNCTION_LEFT;
-
- hidden_side = SIDE_RIGHT | SIDE_LEFT;
-
- if ((flags & GTK_REGION_FIRST) != 0)
- {
- junction &= ~(GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMLEFT);
- hidden_side &= ~(SIDE_LEFT);
- }
- if ((flags & GTK_REGION_LAST) != 0)
- {
- junction &= ~(GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMRIGHT);
- hidden_side &= ~(SIDE_RIGHT);
- }
-
- tdegtk_cairo_draw_frame (engine, cr,
- x, y, width, height,
- hidden_side, junction);
-}
-
-static void
-tdegtk_draw_check (DRAW_ARGS)
-{
- GtkStateFlags state;
- gboolean in_menu;
- gboolean draw_bullet, inconsistent;
-
- state = gtk_theming_engine_get_state (engine);
-
- in_menu = gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_MENUITEM);
- inconsistent = (state & GTK_STATE_FLAG_INCONSISTENT) != 0;
- draw_bullet = (state & GTK_STATE_FLAG_ACTIVE) != 0;
- draw_bullet |= inconsistent;
-
- if (!in_menu)
- {
- tdegtk_cairo_draw_background (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
- tdegtk_cairo_draw_frame (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
- }
-
- if (draw_bullet)
- {
- GdkRGBA *bullet_color;
-
- gtk_theming_engine_get (engine, state,
- "-tdegtk-bullet-color", &bullet_color,
- NULL);
-
- if (inconsistent)
- {
- cairo_save (cr);
-
- cairo_set_line_width (cr, 2.0);
- cairo_move_to (cr, 3, height / 2.0);
- cairo_line_to (cr, width - 3, height / 2.0);
-
- cairo_restore (cr);
- }
- else
- {
- cairo_translate (cr, x, y);
-
- if (in_menu)
- {
- cairo_scale (cr, width / 18.0, height / 18.0);
- cairo_translate (cr, 2.0, 3.0);
- }
- else
- {
- GdkRGBA *bullet_outline_color;
-
- gtk_theming_engine_get (engine, state,
- "-tdegtk-bullet-outline-color", &bullet_outline_color,
- NULL);
-
- cairo_scale (cr, width / 18.0, height / 18.0);
-
- /* thick's outline */
- cairo_move_to (cr, 5.0, 5.65);
- cairo_line_to (cr, 8.95, 9.57);
- cairo_line_to (cr, 16.0, 2.54);
- cairo_line_to (cr, 16.0, 8.36);
- cairo_line_to (cr, 10.6, 15.1);
- cairo_line_to (cr, 7.6, 15.1);
- cairo_line_to (cr, 2.95, 10.48);
- cairo_line_to (cr, 2.95, 7.65);
- cairo_close_path (cr);
-
- gdk_cairo_set_source_rgba (cr, bullet_outline_color);
- cairo_fill (cr);
-
- cairo_translate (cr, 4.0, 2.0);
-
- gdk_rgba_free (bullet_outline_color);
- }
-
- /* thick */
- cairo_move_to (cr, 0.0, 6.0);
- cairo_line_to (cr, 0.0, 8.0);
- cairo_line_to (cr, 4.0, 12.0);
- cairo_line_to (cr, 6.0, 12.0);
- cairo_line_to (cr, 15.0, 1.0);
- cairo_line_to (cr, 15.0, 0.0);
- cairo_line_to (cr, 14.0, 0.0);
- cairo_line_to (cr, 5.0, 9.0);
- cairo_line_to (cr, 1.0, 5.0);
- cairo_close_path (cr);
- }
-
- gdk_cairo_set_source_rgba (cr, bullet_color);
- cairo_fill (cr);
-
- gdk_rgba_free (bullet_color);
- }
-}
-
-static void
-tdegtk_draw_common (DRAW_ARGS)
-{
- tdegtk_cairo_draw_background (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
- tdegtk_cairo_draw_frame (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
-}
-
-static void
-tdegtk_draw_common_background (DRAW_ARGS)
-{
- tdegtk_cairo_draw_background (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
-}
-
-static void
-tdegtk_draw_common_frame (DRAW_ARGS)
-{
- tdegtk_cairo_draw_frame (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
-}
-
-static void
-tdegtk_draw_expander (DRAW_ARGS)
-{
- GtkStateFlags state;
- GdkRGBA color;
- gint size;
- gdouble angle = G_PI_2;
-
- state = gtk_theming_engine_get_state (engine);
-
- gtk_theming_engine_get_color (engine, state, &color);
-
- cairo_save (cr);
-
- /* use floor function to adjust doubles */
- size = floor (MIN (width, height));
-
- x += (gint) (width / 2) - size / 2;
- y += (gint) (height / 2) - size / 2;
-
- if ((state & GTK_STATE_FLAG_ACTIVE) == 0)
- angle = 0;
-
- cairo_translate (cr, x + size / 2.0 + 0.5, y + size / 2.0 + 0.5);
- cairo_rotate (cr, angle);
- cairo_translate (cr, size / 4.0, 0);
-
- /* FIXME this + 1/- 1 is done to fix blurred diagonal lines.
- * I know it's not nice at all, but it fix a visual bug */
- cairo_move_to (cr, - size / 2.0, - size / 2.0);
- cairo_rel_line_to (cr, size / 2.0 + 1, size / 2.0);
- cairo_rel_line_to (cr, - size / 2.0 - 1, size / 2.0);
- cairo_close_path (cr);
-
- cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha * 0.75);
- cairo_fill_preserve (cr);
-
- gdk_cairo_set_source_rgba (cr, &color);
- cairo_stroke (cr);
-
- cairo_restore (cr);
-}
-
-static void
-tdegtk_draw_extension (DRAW_ARGS,
- GtkPositionType gap_side)
-{
- GtkBorder border;
- GtkBorder *outer_border;
- GtkJunctionSides junction = 0;
- GtkStateFlags state;
- gboolean has_outer_stroke = FALSE;
- gdouble bg_offset = 0;
- guint hidden_side = 0;
-
- state = gtk_theming_engine_get_state (engine);
-
- gtk_theming_engine_get (engine, state,
- "-tdegtk-outer-stroke-width", &outer_border,
- NULL);
- gtk_theming_engine_get_border (engine, state, &border);
-
- if (!tdegtk_gtk_border_is_zero (outer_border))
- has_outer_stroke = TRUE;
-
- cairo_save (cr);
-
- /* FIXME doesn't work properly with not homogenuos border-width,
- * especially between tab and notebook.
- * I guess the issue comes from the fact draw_background
- * is looking at border dimensions while we're not,
- * or we're doing it wrong.
- * draw_background is looking at SIDE_BOTTOM and
- * sets border to 0 for this side */
- switch (gap_side)
- {
- case GTK_POS_TOP:
- junction = GTK_JUNCTION_TOP;
- hidden_side = SIDE_TOP;
-
- if (has_outer_stroke)
- {
- y -= outer_border->bottom;
- height += outer_border->bottom;
- }
-
- if ((state & GTK_STATE_FLAG_ACTIVE) != 0)
- bg_offset = border.bottom;
-
- cairo_translate (cr, x + width, y + height);
- cairo_rotate (cr, G_PI);
- break;
- default:
- case GTK_POS_BOTTOM:
- junction = GTK_JUNCTION_BOTTOM;
- hidden_side = SIDE_BOTTOM;
-
- if (has_outer_stroke)
- height += outer_border->top;
-
- if ((state & GTK_STATE_FLAG_ACTIVE) != 0)
- bg_offset = border.top;
-
- cairo_translate (cr, x, y);
- break;
- case GTK_POS_LEFT:
- junction = GTK_JUNCTION_LEFT;
- hidden_side = SIDE_LEFT;
-
- if (has_outer_stroke)
- {
- x -= outer_border->right;
- width += outer_border->right;
- }
-
- if ((state & GTK_STATE_FLAG_ACTIVE) != 0)
- bg_offset = border.right;
-
- cairo_translate (cr, x + width, y);
- cairo_rotate (cr, G_PI / 2);
- break;
- case GTK_POS_RIGHT:
- junction = GTK_JUNCTION_RIGHT;
- hidden_side = SIDE_RIGHT;
-
- if (has_outer_stroke)
- width += outer_border->left;
-
- if ((state & GTK_STATE_FLAG_ACTIVE) != 0)
- bg_offset = border.left;
-
- cairo_translate (cr, x, y + height);
- cairo_rotate (cr, - G_PI / 2);
- break;
- }
-
- if (gap_side == GTK_POS_TOP ||
- gap_side == GTK_POS_BOTTOM)
- tdegtk_cairo_draw_background (engine, cr, 0, 0, width, height + bg_offset, SIDE_BOTTOM, GTK_JUNCTION_BOTTOM);
- else
- tdegtk_cairo_draw_background (engine, cr, 0, 0, height, width + bg_offset, SIDE_BOTTOM, GTK_JUNCTION_BOTTOM);
- cairo_restore (cr);
-
- /* FIXME the frame on bottom bar has the wrong gradient,
- * while should be reflected */
- tdegtk_cairo_draw_frame (engine, cr, x, y, width, height, hidden_side, junction);
-
- gtk_border_free (outer_border);
-}
-
-static void
-tdegtk_draw_focus (DRAW_ARGS)
-{
- GdkRGBA *fill_color, *border_color, *outer_stroke_color;
- GtkStateFlags state;
- gint focus_pad, line_width;
- gint radius;
-
- state = gtk_theming_engine_get_state (engine);
-
- gtk_theming_engine_get (engine, state,
- "-tdegtk-focus-border-color", &border_color,
- "-tdegtk-focus-border-radius", &radius,
- "-tdegtk-focus-fill-color", &fill_color,
- "-tdegtk-focus-outer-stroke-color", &outer_stroke_color,
- NULL);
- gtk_theming_engine_get_style (engine,
- "focus-padding", &focus_pad,
- "focus-line-width", &line_width,
- NULL);
-
- x += focus_pad;
- y += focus_pad;
- width -= focus_pad * 2;
- height -= focus_pad * 2;
-
- cairo_save (cr);
-
- cairo_set_line_width (cr, line_width);
-
- /* first layer, background */
- tdegtk_cairo_round_rect (cr, x, y,
- width, height,
- radius, SIDE_ALL, GTK_JUNCTION_NONE);
- gdk_cairo_set_source_rgba (cr, fill_color);
- cairo_fill (cr);
-
- /* second layer, outer stroke */
- tdegtk_cairo_round_rect_inner (cr, x - line_width, y - line_width,
- width + line_width * 2, height + line_width * 2,
- radius + 1, SIDE_ALL, GTK_JUNCTION_NONE);
- gdk_cairo_set_source_rgba (cr, outer_stroke_color);
- cairo_stroke (cr);
-
- /* third layer, border */
- tdegtk_cairo_round_rect_inner (cr, x, y,
- width, height,
- radius, SIDE_ALL, GTK_JUNCTION_NONE);
- gdk_cairo_set_source_rgba (cr, border_color);
- cairo_stroke (cr);
-
- cairo_restore (cr);
-
- gdk_rgba_free (border_color);
- gdk_rgba_free (fill_color);
- gdk_rgba_free (outer_stroke_color);
-}
-
-static void
-tdegtk_draw_frame_gap (DRAW_ARGS,
- GtkPositionType gap_side,
- gdouble xy0_gap,
- gdouble xy1_gap)
-{
- GtkBorder border;
- GtkBorder *outer_border;
- GtkCssBorderCornerRadius *top_left_radius, *top_right_radius;
- GtkCssBorderCornerRadius *bottom_left_radius, *bottom_right_radius;
- GtkCssBorderRadius border_radius = { { 0, }, };
- GtkJunctionSides junction;
- GtkStateFlags state;
- gboolean has_outer_stroke = FALSE;
- gdouble x0, y0, x1, y1, xc, yc, wc, hc;
-
- xc = yc = wc = hc = 0;
-
- junction = gtk_theming_engine_get_junction_sides (engine);
-
- state = gtk_theming_engine_get_state (engine);
-
- gtk_theming_engine_get (engine, state,
- /* Can't use border-radius as it's an int for
- * backwards compat */
- "border-top-left-radius", &top_left_radius,
- "border-top-right-radius", &top_right_radius,
- "border-bottom-right-radius", &bottom_right_radius,
- "border-bottom-left-radius", &bottom_left_radius,
- "-tdegtk-outer-stroke-width", &outer_border,
- NULL);
- gtk_theming_engine_get_border (engine, state, &border);
-
- if (!tdegtk_gtk_border_is_zero (outer_border))
- has_outer_stroke = TRUE;
-
- if (top_left_radius)
- border_radius.top_left = *top_left_radius;
- g_free (top_left_radius);
- if (top_right_radius)
- border_radius.top_right = *top_right_radius;
- g_free (top_right_radius);
- if (bottom_right_radius)
- border_radius.bottom_right = *bottom_right_radius;
- g_free (bottom_right_radius);
- if (bottom_left_radius)
- border_radius.bottom_left = *bottom_left_radius;
- g_free (bottom_left_radius);
-
- cairo_save (cr);
-
- switch (gap_side)
- {
- case GTK_POS_TOP:
- xc = x + xy0_gap + border.left;
- yc = y;
- wc = MAX (xy1_gap - xy0_gap - (border.left + border.right), 0);
- hc = border.top * 2;
-
- if (has_outer_stroke)
- {
- xc += outer_border->left;
- wc = MAX (xy1_gap - xy0_gap - (outer_border->left + outer_border->right) - (border.left + border.right), 0);
- hc += outer_border->top;
- }
-
- if (xy0_gap < border_radius.top_left.horizontal)
- junction |= GTK_JUNCTION_CORNER_TOPLEFT;
-
- if (xy1_gap > width - border_radius.top_right.horizontal)
- junction |= GTK_JUNCTION_CORNER_TOPRIGHT;
- break;
- default:
- case GTK_POS_BOTTOM:
- xc = x + xy0_gap + border.left;
- yc = y + height - border.bottom * 2;
- wc = MAX (xy1_gap - xy0_gap - (border.left + border.right), 0);
- hc = border.bottom * 2;
-
- if (has_outer_stroke)
- {
- xc += outer_border->left;
- yc -= outer_border->bottom;
- wc = MAX (xy1_gap - xy0_gap - (outer_border->left + outer_border->right) - (border.left + border.right), 0);
- hc += outer_border->bottom;
- }
-
- if (xy0_gap < border_radius.bottom_left.horizontal)
- junction |= GTK_JUNCTION_CORNER_BOTTOMLEFT;
-
- if (xy1_gap > width - border_radius.bottom_right.horizontal)
- junction |= GTK_JUNCTION_CORNER_BOTTOMRIGHT;
-
- break;
- case GTK_POS_LEFT:
- xc = x;
- yc = y + xy0_gap + border.top;
- wc = border.left * 2;
- hc = MAX (xy1_gap - xy0_gap - (border.top + border.bottom), 0);
-
- if (has_outer_stroke)
- {
- yc += outer_border->top;
- wc += outer_border->left;
- hc = MAX (xy1_gap - xy0_gap - (outer_border->top + outer_border->bottom) - (border.top + border.bottom), 0);
- }
-
- if (xy0_gap < border_radius.top_left.vertical)
- junction |= GTK_JUNCTION_CORNER_TOPLEFT;
-
- if (xy1_gap > height - border_radius.bottom_left.vertical)
- junction |= GTK_JUNCTION_CORNER_BOTTOMLEFT;
-
- break;
- case GTK_POS_RIGHT:
- xc = x + width - border.right * 2;
- yc = y + xy0_gap + border.top;
- wc = border.right * 2;
- hc = MAX (xy1_gap - xy0_gap - (border.top + border.bottom), 0);
-
- if (has_outer_stroke)
- {
- xc -= outer_border->right;
- yc += outer_border->top;
- wc += outer_border->right;
- hc = MAX (xy1_gap - xy0_gap - (outer_border->top + outer_border->bottom) - (border.top + border.bottom), 0);
- }
-
- if (xy0_gap < border_radius.top_right.vertical)
- junction |= GTK_JUNCTION_CORNER_TOPRIGHT;
-
- if (xy1_gap > height - border_radius.bottom_right.vertical)
- junction |= GTK_JUNCTION_CORNER_BOTTOMRIGHT;
-
- break;
- }
-
- /* clip the gap */
- cairo_clip_extents (cr, &x0, &y0, &x1, &y1);
- cairo_rectangle (cr, x0, y0, x1 - x0, yc - y0);
- cairo_rectangle (cr, x0, yc, xc - x0, hc);
- cairo_rectangle (cr, xc + wc, yc, x1 - (xc + wc), hc);
- cairo_rectangle (cr, x0, yc + hc, x1 - x0, y1 - (yc + hc));
- cairo_clip (cr);
-
- /* draw the frame, gap area will not be drawn */
- tdegtk_cairo_draw_frame (engine, cr, x, y, width, height, 0, junction);
-
- cairo_restore (cr);
-
- gtk_border_free (outer_border);
-}
-
-static void
-tdegtk_draw_grip (DRAW_ARGS)
-{
- GdkRGBA border_color;
- GdkRGBA *inner_stroke_color;
- GtkStateFlags state;
- gint lx, ly;
-
- state = gtk_theming_engine_get_state (engine);
-
- gtk_theming_engine_get (engine, state,
- "-tdegtk-inner-stroke-color", &inner_stroke_color,
- NULL);
- gtk_theming_engine_get_border_color (engine, state, &border_color);
-
- for (ly = 0; ly < 4; ly++)
- {
- /* vertically, four rows of dots */
- for (lx = 0; lx <= ly; lx++)
- {
- /* horizontally */
- int ny = (3.5 - ly) * 3;
- int nx = lx * 3;
-
- gdk_cairo_set_source_rgba (cr, inner_stroke_color);
- cairo_rectangle (cr, x + width - nx - 1, y + height - ny - 1, 2, 2);
- cairo_fill (cr);
-
- gdk_cairo_set_source_rgba (cr, &border_color);
- cairo_rectangle (cr, x + width - nx - 1, y + height - ny - 1, 1, 1);
- cairo_fill (cr);
- }
- }
-
- gdk_rgba_free (inner_stroke_color);
-}
-
-static void
-tdegtk_draw_handle (DRAW_ARGS)
-{
- gdouble line_width;
- gint i, bar_y, num_bars, bar_spacing, bar_width, bar_height;
-
- tdegtk_cairo_draw_background (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
-
- if (draw_centroid_texture (engine, cr, x, y, width, height))
- return;
-
- tdegtk_get_line_width (engine, &line_width);
-
- bar_y = 1;
- num_bars = 3;
- bar_spacing = 3;
- bar_width = 3;
- bar_height = num_bars * bar_spacing * line_width;
-
- cairo_save (cr);
-
- cairo_translate (cr, x + (gint) (width / 2), y + (gint) (height / 2));
-
- if (height > width)
- cairo_translate (cr, - bar_width / 2 - 0.5, - bar_height / 2 + 0.5);
- else
- {
- cairo_translate (cr, - bar_height / 2 + 0.5, bar_width / 2 + 0.5);
- cairo_rotate (cr, - G_PI / 2);
- }
-
- for (i = 0; i < num_bars; i++)
- {
- /* draw bars */
- cairo_move_to (cr, 0, bar_y);
- cairo_line_to (cr, bar_width, bar_y);
- tdegtk_cairo_set_source_border (engine, cr, bar_width, 3);
- cairo_stroke (cr);
-
- cairo_move_to (cr, 0, bar_y + line_width);
- cairo_line_to (cr, bar_width, bar_y + line_width);
- tdegtk_cairo_set_source_inner_stroke (engine, cr, bar_width, line_width);
- cairo_stroke (cr);
-
- bar_y += bar_spacing;
- }
-
- cairo_restore (cr);
-}
-
-static void
-tdegtk_draw_line (GtkThemingEngine *engine,
- cairo_t *cr,
- gdouble x0,
- gdouble y0,
- gdouble x1,
- gdouble y1)
-{
- /* line endings */
- if (y0 == y1)
- {
- y0 += 0.5;
- y1 += 0.5;
- x0 += 0.5;
- x1 -= 0.5;
- }
- else if (x0 == x1)
- {
- x0 += 0.5;
- x1 += 0.5;
- y0 += 0.5;
- y1 -= 0.5;
- }
-
- cairo_move_to (cr, x0, y0);
- cairo_line_to (cr, x1, y1);
- tdegtk_cairo_set_source_border (engine, cr, MAX (x1 - x0, 1), MAX (y1 - y0, 1));
- cairo_stroke (cr);
-}
-
-static void
-tdegtk_draw_notebook (DRAW_ARGS,
- GtkPositionType gap_side,
- gdouble xy0_gap,
- gdouble xy1_gap)
-{
- tdegtk_cairo_draw_background (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
- tdegtk_draw_frame_gap (engine, cr,
- x, y, width, height,
- gap_side, xy0_gap, xy1_gap);
-}
-
-static void
-tdegtk_draw_radio (DRAW_ARGS)
-{
- GtkStateFlags state;
- gboolean in_menu;
- gboolean draw_bullet, inconsistent;
-
- state = gtk_theming_engine_get_state (engine);
-
- in_menu = gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_MENUITEM);
- inconsistent = (state & GTK_STATE_FLAG_INCONSISTENT) != 0;
- draw_bullet = (state & GTK_STATE_FLAG_ACTIVE) != 0;
- draw_bullet |= inconsistent;
-
- if (!in_menu)
- {
- tdegtk_cairo_draw_background (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
- tdegtk_cairo_draw_frame (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
- }
-
- if (draw_bullet)
- {
- GdkRGBA *bullet_color;
-
- gtk_theming_engine_get (engine, state,
- "-tdegtk-bullet-color", &bullet_color,
- NULL);
-
- if (inconsistent)
- {
- cairo_save (cr);
-
- cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
- cairo_set_line_width (cr, 2.0);
-
- cairo_move_to(cr, 5, height / 2.0);
- cairo_line_to(cr, width - 5, height / 2.0);
-
- gdk_cairo_set_source_rgba (cr, bullet_color);
- cairo_stroke (cr);
-
- cairo_restore (cr);
- }
- else
- {
- if (in_menu)
- cairo_arc (cr, x + width / 2.0, y + height / 2.0,
- (width + height) / 4.0 - 4, 0, G_PI * 2);
- else
- {
- GdkRGBA *bullet_outline_color;
-
- gtk_theming_engine_get (engine, state,
- "-tdegtk-bullet-outline-color", &bullet_outline_color,
- NULL);
-
- /* bullet's outline */
- cairo_arc (cr, x + width / 2.0, y + height / 2.0,
- (width + height) / 4.0 - 4, 0, G_PI * 2);
- gdk_cairo_set_source_rgba (cr, bullet_outline_color);
- cairo_fill (cr);
-
- cairo_arc (cr, x + width / 2.0, y + height / 2.0,
- (width + height) / 4.0 - 5, 0, G_PI * 2);
-
- gdk_rgba_free (bullet_outline_color);
- }
-
- /* bullet */
- gdk_cairo_set_source_rgba (cr, bullet_color);
- cairo_fill (cr);
- }
-
- gdk_rgba_free (bullet_color);
- }
-}
-
-static void
-tdegtk_draw_separator (DRAW_ARGS)
-{
- gdouble line_width;
-
- tdegtk_get_line_width (engine, &line_width);
-
- if (line_width == 0)
- return;
-
- /* FIXME right code should be
- * if (gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_VERTICAL))
- * but doesn't work for separator tool item. */
- if (width > height)
- {
- cairo_move_to (cr, x, y + (gint) (height / 2) + line_width / 2);
- cairo_line_to (cr, x + width, y + (gint) (height / 2) + line_width / 2);
- tdegtk_cairo_set_source_inner_stroke (engine, cr, width, line_width);
- cairo_stroke (cr);
-
- cairo_move_to (cr, x, y + (gint) (height / 2) - line_width / 2);
- cairo_line_to (cr, x + width, y + (gint) (height / 2) - line_width / 2);
- tdegtk_cairo_set_source_border (engine, cr, width, line_width);
- cairo_stroke (cr);
- }
- else
- {
- cairo_move_to (cr, x + (gint) (width / 2) + line_width / 2, y);
- cairo_line_to (cr, x + (gint) (width / 2) + line_width / 2, y + height);
- tdegtk_cairo_set_source_inner_stroke (engine, cr, line_width, height);
- cairo_stroke (cr);
-
- cairo_move_to (cr, x + (gint) (width / 2) - line_width / 2, y);
- cairo_line_to (cr, x + (gint) (width / 2) - line_width / 2, y + height);
- tdegtk_cairo_set_source_border (engine, cr, line_width, height);
- cairo_stroke (cr);
- }
-}
-
-static void
-tdegtk_draw_slider (DRAW_ARGS,
- GtkOrientation orientation)
-{
- /* use orientation, if needed */
- tdegtk_cairo_draw_background (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
-
- draw_centroid_texture (engine, cr, x, y, width, height);
-
- tdegtk_cairo_draw_frame (engine, cr,
- x, y, width, height,
- 0, gtk_theming_engine_get_junction_sides (engine));
-}
-
-static void
-tdegtk_draw_spinbutton_background (DRAW_ARGS)
-{
- GtkBorder border, *outer_border;
- GtkJunctionSides junction;
- GtkStateFlags state;
-
- junction = gtk_theming_engine_get_junction_sides (engine);
-
- state = gtk_theming_engine_get_state (engine);
-
- gtk_theming_engine_get (engine, state,
- "-tdegtk-outer-stroke-width", &outer_border,
- NULL);
- gtk_theming_engine_get_border (engine, state, &border);
-
- cairo_save (cr);
-
- cairo_rectangle (cr, x, y, width, height);
- cairo_clip (cr);
-
- if (!(junction & GTK_JUNCTION_CORNER_TOPRIGHT))
- {
- y = ceil (y);
- height = floor (height);
- height += border.bottom + outer_border->bottom;
- }
- else
- {
- y = floor (y);
- height = ceil (height);
- y -= outer_border->top;
- height += outer_border->bottom;
- }
-
- tdegtk_cairo_draw_background (engine, cr,
- x, y, width, height,
- 0, junction);
-
- cairo_restore (cr);
-
- gtk_border_free (outer_border);
-}
-
-static void
-tdegtk_draw_spinbutton_frame (DRAW_ARGS)
-{
- GtkBorder border, *outer_border;
- GtkJunctionSides junction;
- GtkStateFlags state;
-
- junction = gtk_theming_engine_get_junction_sides (engine);
-
- state = gtk_theming_engine_get_state (engine);
-
- gtk_theming_engine_get (engine, state,
- "-tdegtk-outer-stroke-width", &outer_border,
- NULL);
- gtk_theming_engine_get_border (engine, state, &border);
-
- cairo_save (cr);
-
- cairo_rectangle (cr, x, y, width, height);
- cairo_clip (cr);
-
- if (!(junction & GTK_JUNCTION_CORNER_TOPRIGHT))
- {
- y = ceil (y);
- height = floor (height);
- height += border.bottom + outer_border->bottom;
- }
- else
- {
- y = floor (y);
- height = ceil (height);
- y -= outer_border->top;
- height += outer_border->bottom;
- }
-
- tdegtk_cairo_draw_frame (engine, cr,
- x, y, width, height,
- 0, junction);
-
- cairo_restore (cr);
-
- gtk_border_free (outer_border);
-}
-
-void
-tdegtk_register_style_default (TdeGtkStyleFunctions *functions)
-{
- g_assert (functions);
-
- functions->draw_activity = tdegtk_draw_activity;
- functions->draw_arrow = tdegtk_draw_arrow;
- functions->draw_cell_background = tdegtk_draw_cell_background;
- functions->draw_cell_frame = tdegtk_draw_cell_frame;
- functions->draw_check = tdegtk_draw_check;
- functions->draw_common = tdegtk_draw_common;
- functions->draw_common_background = tdegtk_draw_common_background;
- functions->draw_common_frame = tdegtk_draw_common_frame;
- functions->draw_expander = tdegtk_draw_expander;
- functions->draw_extension = tdegtk_draw_extension;
- functions->draw_focus = tdegtk_draw_focus;
- functions->draw_frame_gap = tdegtk_draw_frame_gap;
- functions->draw_grip = tdegtk_draw_grip;
- functions->draw_handle = tdegtk_draw_handle;
- functions->draw_line = tdegtk_draw_line;
- functions->draw_notebook = tdegtk_draw_notebook;
- functions->draw_radio = tdegtk_draw_radio;
- functions->draw_separator = tdegtk_draw_separator;
- functions->draw_slider = tdegtk_draw_slider;
- functions->draw_spinbutton_background = tdegtk_draw_spinbutton_background;
- functions->draw_spinbutton_frame = tdegtk_draw_spinbutton_frame;
-}
diff --git a/tdegtk/tdegtk-draw.cpp b/tdegtk/tdegtk-draw.cpp
new file mode 100644
index 0000000..77c0b7c
--- /dev/null
+++ b/tdegtk/tdegtk-draw.cpp
@@ -0,0 +1,1273 @@
+/* The TdeGtk Theming Engine for Gtk+.
+ * Copyright (C) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+ *
+ * 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 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 St, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#include <cairo.h>
+#include <gtk/gtk.h>
+#include <math.h>
+
+#include <tqapplication.h>
+#include <tqpainter.h>
+#include <tqstyle.h>
+
+#include "tdegtk-cairo-support.h"
+#include "tdegtk-draw.h"
+#include "tdegtk-support.h"
+#include "tdegtk-types.h"
+#include "tdegtk-widgetlookup.h"
+#include "tdegtk-utils.h"
+
+#include "tqtcairopainter.h"
+
+#define DEBUG_FILL_BACKGROUND_WITH_COLOR(p,x,y,z) TQBrush brush2( TQColor(x,y,z), TQBrush::SolidPattern ); \
+ p.setBrush( brush2 ); \
+ p.setPen( TQt::NoPen ); \
+ p.drawRect( 0,0, 5000,5000 );
+
+#define DRAW_FILLED_RECTANGLE_OVER_ENTIRE_AREA(p,x) p.setBrush(x); \
+ p.setPen(TQt::NoPen); \
+ p.drawRect(0, 0, width, height);
+
+#define DRAW_FILLED_RECTANGLE_OVER_SPECIFIC_AREA(p,b,x,y,w,h) p.setBrush(b); \
+ p.setPen(TQt::NoPen); \
+ p.drawRect(x, y, w, h);
+
+WidgetLookup m_widgetLookup;
+
+// Keep this in sync with gtkToTQPaletteColorGroup() below
+static TQColorGroup gtkToTQtColorGroup(GtkThemingEngine* engine, GtkStateFlags state) {
+// GdkRGBA *background_color;
+// GdkRGBA *foreground_color;
+// gtk_theming_engine_get(engine, state, GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &background_color, NULL);
+// gtk_theming_engine_get(engine, state, GTK_STYLE_PROPERTY_COLOR, &foreground_color, NULL);
+
+// GTK_STATE_FLAG_ACTIVE
+// GTK_STATE_FLAG_PRELIGHT
+// GTK_STATE_FLAG_SELECTED
+// GTK_STATE_FLAG_INSENSITIVE
+// GTK_STATE_FLAG_INCONSISTENT
+// GTK_STATE_FLAG_FOCUSED
+
+ TQColorGroup cg;
+// if (state & GTK_STATE_FLAG_INCONSISTENT) {
+// cg = tqApp->palette().inactive();
+// }
+ /*else*/ if (state & GTK_STATE_FLAG_INSENSITIVE) {
+ cg = tqApp->palette().disabled();
+ }
+ else {
+ cg = tqApp->palette().active();
+ }
+// cg.setColor(TQColorGroup::Background, TQColor((background_color->red*255.0),(background_color->green*255.0),(background_color->blue*255.0)));
+// cg.setColor(TQColorGroup::Foreground, TQColor((foreground_color->red*255.0),(foreground_color->green*255.0),(foreground_color->blue*255.0)));
+
+ return cg;
+}
+
+// Keep this in sync with gtkToTQtColorGroup() above
+static TQPalette::ColorGroup gtkToTQPaletteColorGroup(GtkThemingEngine* engine, GtkStateFlags state) {
+ TQPalette::ColorGroup cg = TQPalette::Active;
+
+ if (state & GTK_STATE_FLAG_INSENSITIVE) {
+ cg = TQPalette::Disabled;
+ }
+ else {
+ cg = TQPalette::Active;
+ }
+
+ return cg;
+}
+
+static TQStyle::SFlags gtkToTQtStyleFlags(GtkThemingEngine* engine, GtkStateFlags state, TQt3WidgetType wt) {
+ TQStyle::SFlags sflags = TQStyle::Style_Default;
+
+ gboolean active, inconsistent, mousedown, prelight, focused, disabled, in_menu;
+ in_menu = gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_MENUITEM);
+ prelight = (state & GTK_STATE_FLAG_PRELIGHT) != 0;
+ focused = (state & GTK_STATE_FLAG_FOCUSED) != 0;
+ disabled = (state & GTK_STATE_FLAG_INSENSITIVE) != 0;
+ inconsistent = (state & GTK_STATE_FLAG_INCONSISTENT) != 0;
+ mousedown = (state & GTK_STATE_FLAG_SELECTED) != 0;
+ active = (state & GTK_STATE_FLAG_ACTIVE) != 0;
+
+ if ((wt == TQT3WT_TQRadioButton) || (wt == TQT3WT_TQCheckBox) || (wt == TQT3WT_TQPushButton)) {
+ if (!inconsistent) {
+ if (active) {
+ sflags |= TQStyle::Style_On;
+ }
+ else {
+ sflags |= TQStyle::Style_Off;
+ }
+ }
+ if (mousedown) {
+ sflags |= TQStyle::Style_Down;
+ }
+ if (prelight) {
+ sflags |= TQStyle::Style_MouseOver;
+ }
+ if (focused) {
+ sflags |= TQStyle::Style_HasFocus;
+ }
+ if (!disabled) {
+ sflags |= TQStyle::Style_Enabled;
+ }
+ }
+ else if (wt == TQT3WT_GTKTreeViewCell) {
+ if (!inconsistent) {
+ if (active) {
+ sflags |= TQStyle::Style_On;
+ }
+ else {
+ sflags |= TQStyle::Style_Off;
+ }
+ }
+ if (prelight) {
+ sflags |= TQStyle::Style_MouseOver;
+ }
+ if (focused) {
+ sflags |= TQStyle::Style_HasFocus;
+ }
+ if (!disabled) {
+ sflags |= TQStyle::Style_Enabled;
+ }
+ }
+ else {
+ if (active) {
+ sflags |= TQStyle::Style_Down;
+ }
+ if (prelight) {
+ sflags |= TQStyle::Style_MouseOver;
+ }
+ if (focused) {
+ sflags |= TQStyle::Style_HasFocus;
+ }
+ if (!disabled) {
+ sflags |= TQStyle::Style_Enabled;
+ }
+ }
+
+ return sflags;
+}
+
+static TQColorGroup::ColorRole backgroundModeToColorRole(TQt::BackgroundMode mode) {
+ TQColorGroup::ColorRole ret = TQColorGroup::Background;
+
+ if (mode == TQt::PaletteForeground) {
+ ret = TQColorGroup::Foreground;
+ }
+ else if (mode == TQt::PaletteBackground) {
+ ret = TQColorGroup::Background;
+ }
+ else if (mode == TQt::PaletteButton) {
+ ret = TQColorGroup::Button;
+ }
+ else if (mode == TQt::PaletteLight) {
+ ret = TQColorGroup::Light;
+ }
+ else if (mode == TQt::PaletteMidlight) {
+ ret = TQColorGroup::Midlight;
+ }
+ else if (mode == TQt::PaletteDark) {
+ ret = TQColorGroup::Dark;
+ }
+ else if (mode == TQt::PaletteMid) {
+ ret = TQColorGroup::Mid;
+ }
+ else if (mode == TQt::PaletteText) {
+ ret = TQColorGroup::Text;
+ }
+ else if (mode == TQt::PaletteBrightText) {
+ ret = TQColorGroup::BrightText;
+ }
+ else if (mode == TQt::PaletteButtonText) {
+ ret = TQColorGroup::ButtonText;
+ }
+ else if (mode == TQt::PaletteBase) {
+ ret = TQColorGroup::Base;
+ }
+ else if (mode == TQt::PaletteShadow) {
+ ret = TQColorGroup::Shadow;
+ }
+ else if (mode == TQt::PaletteHighlight) {
+ ret = TQColorGroup::Highlight;
+ }
+ else if (mode == TQt::PaletteHighlightedText) {
+ ret = TQColorGroup::HighlightedText;
+ }
+ else if (mode == TQt::PaletteLink) {
+ ret = TQColorGroup::Link;
+ }
+ else if (mode == TQt::PaletteLinkVisited) {
+ ret = TQColorGroup::LinkVisited;
+ }
+
+ return ret;
+}
+
+/* draw a texture placed on the centroid */
+static gboolean
+draw_centroid_texture (GtkThemingEngine *engine,
+ cairo_t *cr,
+ gdouble x,
+ gdouble y,
+ gdouble width,
+ gdouble height)
+{
+ GtkStateFlags state;
+ GValue value = { 0, };
+ cairo_pattern_t *texture = NULL;
+ cairo_surface_t *surface = NULL;
+ gboolean retval = FALSE;
+
+ state = gtk_theming_engine_get_state (engine);
+
+ gtk_theming_engine_get_property (engine, "-tdegtk-centroid-texture", state, &value);
+
+ if (!G_VALUE_HOLDS_BOXED (&value))
+ return FALSE;
+
+ texture = (cairo_pattern_t*)g_value_dup_boxed (&value);
+ g_value_unset (&value);
+
+ if (texture != NULL)
+ cairo_pattern_get_surface (texture, &surface);
+
+ if (surface != NULL)
+ {
+ cairo_save (cr);
+
+ cairo_set_source_surface (cr, surface, (gint) (x + width / 2 - cairo_image_surface_get_width (surface) / 2),
+ (gint) (y + height / 2 - cairo_image_surface_get_height (surface) / 2));
+ cairo_paint (cr);
+
+ cairo_restore (cr);
+
+ retval = TRUE;
+ }
+
+ if (texture != NULL)
+ cairo_pattern_destroy (texture);
+
+ return retval;
+}
+
+static void
+tdegtk_draw_activity (DRAW_ARGS)
+{
+ /* playground for effects */
+ tdegtk_cairo_draw_background (engine, cr,
+ x, y, width, height,
+ 0, gtk_theming_engine_get_junction_sides (engine));
+ tdegtk_cairo_draw_frame (engine, cr,
+ x, y, width, height,
+ 0, gtk_theming_engine_get_junction_sides (engine));
+}
+
+static void
+tdegtk_draw_arrow (GtkThemingEngine *engine,
+ cairo_t *cr,
+ gdouble angle,
+ gdouble x,
+ gdouble y,
+ gdouble size)
+{
+ TQRect boundingRect(0, 0, size, size);
+ TQt3CairoPaintDevice pd(NULL, x, y, size, size, cr);
+ TQPainter p(&pd);
+
+ DEBUG_FILL_BACKGROUND_WITH_COLOR(p,128,0,255);
+
+ GtkStateFlags state;
+ state = gtk_theming_engine_get_state(engine);
+
+ GtkArrowType arrow_direction;
+
+ if ((angle <= ((G_PI/2)-(G_PI/4))) || (angle > ((3*(G_PI/2))+(G_PI/4)))) {
+ arrow_direction = GTK_ARROW_UP;
+ }
+ else if ((angle <= ((G_PI)-(G_PI/4))) && (angle > ((0)+(G_PI/4)))) {
+ arrow_direction = GTK_ARROW_RIGHT;
+ }
+ else if ((angle <= ((3*(G_PI/2))-(G_PI/4))) && (angle > ((G_PI/2)+(G_PI/4)))) {
+ arrow_direction = GTK_ARROW_DOWN;
+ }
+ else {
+ arrow_direction = GTK_ARROW_LEFT;
+ }
+
+ if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_SCROLLBAR)) {
+ TQStringList objectTypes;
+ objectTypes.append(TQSCROLLBAR_OBJECT_NAME_STRING);
+ TQPalette objectPalette = tqApp->palette(objectTypes);
+
+ TQStyleControlElementData ceData;
+ TQStyle::ControlElementFlags elementFlags;
+ ceData.widgetObjectTypes = objectTypes;
+ ceData.rect = boundingRect;
+ ceData.orientation = ((arrow_direction == GTK_ARROW_UP) || (arrow_direction == GTK_ARROW_DOWN))?TQt::Vertical:TQt::Horizontal;
+
+ bool subline = ((arrow_direction == GTK_ARROW_DOWN) || (arrow_direction == GTK_ARROW_RIGHT))?false:true;
+
+ // Draw slider arrow buttons
+ TQRect scrollpagerect = tqApp->style().querySubControlMetrics(TQStyle::CC_ScrollBar, ceData, elementFlags, (subline)?TQStyle::SC_ScrollBarSubLine:TQStyle::SC_ScrollBarAddLine, gtkToTQtStyleFlags(engine, state, TQT3WT_NONE));
+ if (ceData.orientation == TQt::Vertical) {
+ scrollpagerect.setY(ceData.rect.y());
+ scrollpagerect.setHeight(ceData.rect.height());
+ }
+ else {
+ scrollpagerect.setX(ceData.rect.x());
+ scrollpagerect.setWidth(ceData.rect.width());
+ }
+ tqApp->style().drawPrimitive((subline)?TQStyle::PE_ScrollBarSubLine:TQStyle::PE_ScrollBarAddLine, &p, scrollpagerect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE) | ((ceData.orientation == TQt::Horizontal)?TQStyle::Style_Horizontal:TQStyle::Style_Default));
+ }
+
+ p.end();
+
+ return;
+
+ GdkRGBA color;
+ gdouble size_reduction = 2;
+
+ state = gtk_theming_engine_get_state (engine);
+
+ gtk_theming_engine_get_color (engine, state, &color);
+
+ cairo_save (cr);
+
+ /* use floor function to adjust doubles */
+ y = floor (y);
+ x = floor (x);
+ size = floor (size);
+
+ size -= size_reduction;
+
+ cairo_translate (cr, size_reduction / 2, size_reduction / 2);
+ cairo_translate (cr, x + (gint) (size / 2.0) + 0.5, y + (gint) (size / 2.0) + 0.5);
+ cairo_rotate (cr, angle - G_PI_2);
+ cairo_translate (cr, (gint) (size / 4.0), 0);
+
+ /* FIXME this + 1/- 1 is done to fix blurred diagonal lines.
+ * I know it's not nice at all, but it fix a visual bug */
+ cairo_move_to (cr, - (gint) (size / 2.0), - (gint) (size / 2.0));
+ cairo_rel_line_to (cr, (gint) (size / 2.0) + 1, (gint) (size / 2.0));
+ cairo_rel_line_to (cr, - (gint) (size / 2.0) - 1, (gint) (size / 2.0));
+ cairo_close_path (cr);
+
+ cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha * 0.75);
+ cairo_fill_preserve (cr);
+
+ gdk_cairo_set_source_rgba (cr, &color);
+ cairo_stroke (cr);
+
+ cairo_restore (cr);
+}
+
+static void
+tdegtk_draw_cell_background (DRAW_ARGS,
+ GtkRegionFlags flags)
+{
+ GtkJunctionSides junction;
+ guint hidden_side;
+
+ junction = (GtkJunctionSides)(GTK_JUNCTION_RIGHT | GTK_JUNCTION_LEFT);
+
+ hidden_side = SIDE_RIGHT | SIDE_LEFT;
+
+ if ((flags & GTK_REGION_FIRST) != 0)
+ {
+ junction = (GtkJunctionSides)(junction & ~(GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMLEFT));
+ hidden_side &= ~(SIDE_LEFT);
+ }
+ if ((flags & GTK_REGION_LAST) != 0)
+ {
+ junction = (GtkJunctionSides)(junction & ~(GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMRIGHT));
+ hidden_side &= ~(SIDE_RIGHT);
+ }
+
+ tdegtk_cairo_draw_background (engine, cr,
+ x, y, width, height,
+ hidden_side, junction);
+}
+
+static void
+tdegtk_draw_cell_frame (DRAW_ARGS,
+ GtkRegionFlags flags)
+{
+ GtkJunctionSides junction;
+ guint hidden_side;
+
+ junction = (GtkJunctionSides)(GTK_JUNCTION_RIGHT | GTK_JUNCTION_LEFT);
+
+ hidden_side = SIDE_RIGHT | SIDE_LEFT;
+
+ if ((flags & GTK_REGION_FIRST) != 0)
+ {
+ junction = (GtkJunctionSides)(junction & ~(GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMLEFT));
+ hidden_side &= ~(SIDE_LEFT);
+ }
+ if ((flags & GTK_REGION_LAST) != 0)
+ {
+ junction = (GtkJunctionSides)(junction & ~(GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMRIGHT));
+ hidden_side &= ~(SIDE_RIGHT);
+ }
+
+ tdegtk_cairo_draw_frame (engine, cr,
+ x, y, width, height,
+ hidden_side, junction);
+}
+
+static void
+tdegtk_draw_check (DRAW_ARGS)
+{
+ TQRect boundingRect(0, 0, width, height);
+ TQt3CairoPaintDevice pd(NULL, x, y, width, height, cr);
+ TQPainter p(&pd);
+
+ DEBUG_FILL_BACKGROUND_WITH_COLOR(p,255,0,0);
+
+ GtkStateFlags state;
+ state = gtk_theming_engine_get_state(engine);
+ const GtkWidgetPath* path(gtk_theming_engine_get_path(engine));
+
+ if (gtk_widget_path_is_type(path, GTK_TYPE_TREE_VIEW)) {
+ tqApp->style().drawPrimitive(TQStyle::PE_Indicator, &p, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_GTKTreeViewCell));
+ }
+ else {
+ tqApp->style().drawPrimitive(TQStyle::PE_Indicator, &p, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_TQCheckBox));
+ }
+ p.end();
+}
+
+static void
+tdegtk_draw_common (DRAW_ARGS)
+{
+ TQRect boundingRect(0, 0, width, height);
+ TQt3CairoPaintDevice pd(NULL, x, y, width, height, cr);
+ TQPainter p(&pd);
+
+ DEBUG_FILL_BACKGROUND_WITH_COLOR(p,0,255,255);
+
+ GtkStateFlags state;
+ state = gtk_theming_engine_get_state(engine);
+ //tqApp->style().drawPrimitive(TQStyle::PE_Indicator, &p, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE));
+
+ p.end();
+}
+
+static void
+tdegtk_draw_common_background (DRAW_ARGS)
+{
+ TQRect boundingRect(0, 0, width, height);
+ TQt3CairoPaintDevice pd(NULL, x, y, width, height, cr);
+ TQPainter p(&pd);
+
+ DEBUG_FILL_BACKGROUND_WITH_COLOR(p,0,0,255);
+
+ GtkStateFlags state;
+ state = gtk_theming_engine_get_state(engine);
+
+ if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_ENTRY)) {
+ TQStringList objectTypes;
+ objectTypes.append(TQLINEEDIT_OBJECT_NAME_STRING);
+ TQPalette objectPalette = tqApp->palette(objectTypes);
+
+ // Draw background
+ TQBrush brush = objectPalette.brush(gtkToTQPaletteColorGroup(engine, state), TQColorGroup::Base);
+ DRAW_FILLED_RECTANGLE_OVER_ENTIRE_AREA(p, brush)
+ }
+
+ if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_SCROLLBAR)) {
+ TQStringList objectTypes;
+ objectTypes.append(TQSCROLLBAR_OBJECT_NAME_STRING);
+ TQPalette objectPalette = tqApp->palette(objectTypes);
+
+ TQStyleControlElementData ceData;
+ TQStyle::ControlElementFlags elementFlags;
+ ceData.widgetObjectTypes = objectTypes;
+ ceData.rect = boundingRect;
+ ceData.orientation = (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_VERTICAL))?TQt::Vertical:TQt::Horizontal;
+
+ // Draw frame
+ tqApp->style().drawPrimitive(TQStyle::PE_PanelLineEdit, &p, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE));
+ }
+
+ if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_BUTTON)) {
+ TQStringList objectTypes;
+ objectTypes.append(TQBUTTON_OBJECT_NAME_STRING);
+ TQPalette objectPalette = tqApp->palette(objectTypes);
+
+ // Draw background
+ TQBrush brush = objectPalette.brush(gtkToTQPaletteColorGroup(engine, state), TQColorGroup::Background);
+ DRAW_FILLED_RECTANGLE_OVER_ENTIRE_AREA(p, brush)
+ }
+
+ if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_TOOLTIP)) {
+ TQStringList objectTypes;
+ objectTypes.append(TQTIPLABEL_OBJECT_NAME_STRING);
+ TQPalette objectPalette = tqApp->palette(objectTypes);
+
+ // Draw background
+ TQBrush brush = objectPalette.brush(gtkToTQPaletteColorGroup(engine, state), TQColorGroup::Background);
+ DRAW_FILLED_RECTANGLE_OVER_ENTIRE_AREA(p, brush)
+ }
+
+ if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_BACKGROUND)) {
+ TQStringList objectTypes;
+ objectTypes.append(TQWIDGET_OBJECT_NAME_STRING);
+ TQPalette objectPalette = tqApp->palette(objectTypes);
+
+ // Draw background
+ TQBrush brush = objectPalette.brush(gtkToTQPaletteColorGroup(engine, state), TQColorGroup::Background);
+ DRAW_FILLED_RECTANGLE_OVER_ENTIRE_AREA(p, brush)
+ }
+
+ p.end();
+}
+
+static void
+tdegtk_draw_common_frame (DRAW_ARGS)
+{
+ TQRect boundingRect(0, 0, width, height);
+ TQt3CairoPaintDevice pd(NULL, x, y, width, height, cr);
+ TQPainter p(&pd);
+
+ GtkStateFlags state;
+ state = gtk_theming_engine_get_state(engine);
+
+ if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_SCROLLBAR)) {
+ if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_BUTTON)) {
+ // Scrollbar buttons are drawn in the arrow handler
+ }
+ else {
+ TQStringList objectTypes;
+ objectTypes.append(TQSCROLLBAR_OBJECT_NAME_STRING);
+ TQPalette objectPalette = tqApp->palette(objectTypes);
+
+ TQStyleControlElementData ceData;
+ TQStyle::ControlElementFlags elementFlags;
+ ceData.widgetObjectTypes = objectTypes;
+ ceData.rect = boundingRect;
+ ceData.orientation = (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_VERTICAL))?TQt::Vertical:TQt::Horizontal;
+
+ // Draw background
+ // HACK
+ // PE_ScrollBarAddPage and PE_ScrollBarSubPage are separate in TQt3
+ // Apparently there is no such distinction in GTK3!
+ TQRect scrollpagerect = tqApp->style().querySubControlMetrics(TQStyle::CC_ScrollBar, ceData, elementFlags, TQStyle::SC_ScrollBarAddPage, gtkToTQtStyleFlags(engine, state, TQT3WT_NONE));
+ if (ceData.orientation == TQt::Vertical) {
+ scrollpagerect.setY(ceData.rect.y());
+ scrollpagerect.setHeight(ceData.rect.height());
+ }
+ else {
+ scrollpagerect.setX(ceData.rect.x());
+ scrollpagerect.setWidth(ceData.rect.width());
+ }
+ tqApp->style().drawPrimitive(TQStyle::PE_ScrollBarAddPage, &p, scrollpagerect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE));
+ }
+ }
+ else {
+ if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_BUTTON)) {
+ // Draw frame
+ tqApp->style().drawPrimitive(TQStyle::PE_ButtonBevel, &p, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_TQPushButton));
+ }
+
+ if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_ENTRY)) {
+ TQStringList objectTypes;
+ objectTypes.append(TQLINEEDIT_OBJECT_NAME_STRING);
+ TQPalette objectPalette = tqApp->palette(objectTypes);
+
+ // Draw frame
+ tqApp->style().drawPrimitive(TQStyle::PE_PanelLineEdit, &p, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE));
+ }
+ }
+
+ p.end();
+}
+
+static void
+tdegtk_draw_expander (DRAW_ARGS)
+{
+ GtkStateFlags state;
+ GdkRGBA color;
+ gint size;
+ gdouble angle = G_PI_2;
+
+ state = gtk_theming_engine_get_state (engine);
+
+ gtk_theming_engine_get_color (engine, state, &color);
+
+ cairo_save (cr);
+
+ /* use floor function to adjust doubles */
+ size = floor (MIN (width, height));
+
+ x += (gint) (width / 2) - size / 2;
+ y += (gint) (height / 2) - size / 2;
+
+ if ((state & GTK_STATE_FLAG_ACTIVE) == 0)
+ angle = 0;
+
+ cairo_translate (cr, x + size / 2.0 + 0.5, y + size / 2.0 + 0.5);
+ cairo_rotate (cr, angle);
+ cairo_translate (cr, size / 4.0, 0);
+
+ /* FIXME this + 1/- 1 is done to fix blurred diagonal lines.
+ * I know it's not nice at all, but it fix a visual bug */
+ cairo_move_to (cr, - size / 2.0, - size / 2.0);
+ cairo_rel_line_to (cr, size / 2.0 + 1, size / 2.0);
+ cairo_rel_line_to (cr, - size / 2.0 - 1, size / 2.0);
+ cairo_close_path (cr);
+
+ cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha * 0.75);
+ cairo_fill_preserve (cr);
+
+ gdk_cairo_set_source_rgba (cr, &color);
+ cairo_stroke (cr);
+
+ cairo_restore (cr);
+}
+
+static void
+tdegtk_draw_extension (DRAW_ARGS,
+ GtkPositionType gap_side)
+{
+ TQRect boundingRect(0, 0, width, height);
+ TQt3CairoPaintDevice pd(NULL, x, y, width, height, cr);
+ TQPainter p(&pd);
+
+ DEBUG_FILL_BACKGROUND_WITH_COLOR(p,255,255,0);
+
+ const GtkWidgetPath* path;
+ GtkStateFlags state;
+ GtkWidget* widget;
+
+ path = gtk_theming_engine_get_path(engine);
+ state = gtk_theming_engine_get_state(engine);
+ widget = m_widgetLookup.find(cr, path);
+
+ if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_NOTEBOOK)) {
+ // Check tab properties
+ const int tabIndex = Gtk::gtk_notebook_find_tab(widget, x+width/2, y+height/2);
+// Style::instance().animations().tabWidgetEngine().updateTabRect(widget, tabIndex, x, y, width, height);
+// bool prelight = (tabIndex == Style::instance().animations().tabWidgetEngine().hoveredTab(widget));
+ bool prelight = false;
+ GtkNotebook* notebook = GTK_NOTEBOOK(widget);
+// bool firstTab = (tabIndex == 0);
+// bool lastTab = (tabIndex == gtk_notebook_get_n_pages(notebook)-1);
+ const int currentPage = gtk_notebook_get_current_page(notebook);
+ const int numPages = gtk_notebook_get_n_pages(notebook);
+
+ TQStringList objectTypes;
+ objectTypes.append(TQTABBAR_OBJECT_NAME_STRING);
+ TQPalette objectPalette = tqApp->palette(objectTypes);
+
+ TQStyleControlElementData ceData;
+ TQStyle::ControlElementFlags elementFlags;
+ ceData.widgetObjectTypes = objectTypes;
+ ceData.rect = boundingRect;
+
+ TQTab tqt3Tab;
+ tqt3Tab.setIdentifier(tabIndex);
+ TQStyleOption tabOpt(&tqt3Tab, (prelight)?&tqt3Tab:(TQTab*)NULL);
+
+ elementFlags = elementFlags | TQStyle::CEF_HasParentWidget;
+ ceData.parentWidgetData.widgetObjectTypes.append(TQTABBAR_OBJECT_NAME_STRING);
+
+ int tab_overlap = tqApp->style().pixelMetric(TQStyle::PM_TabBarTabOverlap);
+
+ boundingRect = TQRect(0, 0, width+(tab_overlap*2)-tab_overlap, height);
+ TQt3CairoPaintDevice pd2(NULL, x-tab_overlap, y, width+(tab_overlap*2), height, cr);
+ TQPainter p2(&pd2);
+
+ switch (gap_side) {
+ default:
+ case GTK_POS_TOP:
+ ceData.tabBarData.shape = TQTabBar::RoundedBelow;
+ break;
+ case GTK_POS_LEFT:
+ // FIXME
+ // TQt3 does not know how to draw these
+ ceData.tabBarData.shape = TQTabBar::RoundedAbove;
+ break;
+ case GTK_POS_BOTTOM:
+ ceData.tabBarData.shape = TQTabBar::RoundedAbove;
+ break;
+ case GTK_POS_RIGHT:
+ // FIXME
+ // TQt3 does not know how to draw these
+ ceData.tabBarData.shape = TQTabBar::RoundedAbove;
+ break;
+ }
+ ceData.tabBarData.tabCount = numPages;
+ ceData.tabBarData.identIndexMap[tqt3Tab.identifier()] = tabIndex;
+
+ cairo_save(cr);
+ cairo_reset_clip(cr);
+
+ // Draw background
+ TQBrush brush = objectPalette.brush(gtkToTQPaletteColorGroup(engine, state), TQColorGroup::Background);
+ DRAW_FILLED_RECTANGLE_OVER_SPECIFIC_AREA(p2, brush, 0, 0, width, height)
+
+ // Draw tab
+ tqApp->style().drawControl(TQStyle::CE_TabBarTab, &p2, ceData, elementFlags, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE) | ((tabIndex==currentPage)?TQStyle::Style_Selected:TQStyle::Style_Default), tabOpt);
+
+ cairo_restore(cr);
+ }
+
+ p.end();
+}
+
+static void
+tdegtk_draw_focus (DRAW_ARGS)
+{
+ GtkStateFlags state;
+
+ state = gtk_theming_engine_get_state (engine);
+
+ return;
+}
+
+static void
+tdegtk_draw_frame_gap (DRAW_ARGS,
+ GtkPositionType gap_side,
+ gdouble xy0_gap,
+ gdouble xy1_gap)
+{
+ TQRect boundingRect(0, 0, width, height);
+ TQt3CairoPaintDevice pd(NULL, x, y, width, height, cr);
+ TQPainter p(&pd);
+
+ DEBUG_FILL_BACKGROUND_WITH_COLOR(p,255,128,0);
+
+ p.end();
+
+ return;
+
+ GtkBorder border;
+ GtkBorder *outer_border;
+ GtkCssBorderCornerRadius *top_left_radius, *top_right_radius;
+ GtkCssBorderCornerRadius *bottom_left_radius, *bottom_right_radius;
+ GtkCssBorderRadius border_radius = { { 0, }, };
+ GtkJunctionSides junction;
+ GtkStateFlags state;
+ gboolean has_outer_stroke = FALSE;
+ gdouble x0, y0, x1, y1, xc, yc, wc, hc;
+
+ xc = yc = wc = hc = 0;
+
+ junction = gtk_theming_engine_get_junction_sides (engine);
+
+ state = gtk_theming_engine_get_state (engine);
+
+ gtk_theming_engine_get (engine, state,
+ /* Can't use border-radius as it's an int for
+ * backwards compat */
+ "border-top-left-radius", &top_left_radius,
+ "border-top-right-radius", &top_right_radius,
+ "border-bottom-right-radius", &bottom_right_radius,
+ "border-bottom-left-radius", &bottom_left_radius,
+ "-tdegtk-outer-stroke-width", &outer_border,
+ NULL);
+ gtk_theming_engine_get_border (engine, state, &border);
+
+ if (!tdegtk_gtk_border_is_zero (outer_border))
+ has_outer_stroke = TRUE;
+
+ if (top_left_radius)
+ border_radius.top_left = *top_left_radius;
+ g_free (top_left_radius);
+ if (top_right_radius)
+ border_radius.top_right = *top_right_radius;
+ g_free (top_right_radius);
+ if (bottom_right_radius)
+ border_radius.bottom_right = *bottom_right_radius;
+ g_free (bottom_right_radius);
+ if (bottom_left_radius)
+ border_radius.bottom_left = *bottom_left_radius;
+ g_free (bottom_left_radius);
+
+ cairo_save (cr);
+
+ switch (gap_side)
+ {
+ case GTK_POS_TOP:
+ xc = x + xy0_gap + border.left;
+ yc = y;
+ wc = MAX (xy1_gap - xy0_gap - (border.left + border.right), 0);
+ hc = border.top * 2;
+
+ if (has_outer_stroke)
+ {
+ xc += outer_border->left;
+ wc = MAX (xy1_gap - xy0_gap - (outer_border->left + outer_border->right) - (border.left + border.right), 0);
+ hc += outer_border->top;
+ }
+
+ if (xy0_gap < border_radius.top_left.horizontal)
+ junction = (GtkJunctionSides)(junction | GTK_JUNCTION_CORNER_TOPLEFT);
+
+ if (xy1_gap > width - border_radius.top_right.horizontal)
+ junction = (GtkJunctionSides)(junction | GTK_JUNCTION_CORNER_TOPRIGHT);
+ break;
+ default:
+ case GTK_POS_BOTTOM:
+ xc = x + xy0_gap + border.left;
+ yc = y + height - border.bottom * 2;
+ wc = MAX (xy1_gap - xy0_gap - (border.left + border.right), 0);
+ hc = border.bottom * 2;
+
+ if (has_outer_stroke)
+ {
+ xc += outer_border->left;
+ yc -= outer_border->bottom;
+ wc = MAX (xy1_gap - xy0_gap - (outer_border->left + outer_border->right) - (border.left + border.right), 0);
+ hc += outer_border->bottom;
+ }
+
+ if (xy0_gap < border_radius.bottom_left.horizontal)
+ junction = (GtkJunctionSides)(junction | GTK_JUNCTION_CORNER_BOTTOMLEFT);
+
+ if (xy1_gap > width - border_radius.bottom_right.horizontal)
+ junction = (GtkJunctionSides)(junction | GTK_JUNCTION_CORNER_BOTTOMRIGHT);
+
+ break;
+ case GTK_POS_LEFT:
+ xc = x;
+ yc = y + xy0_gap + border.top;
+ wc = border.left * 2;
+ hc = MAX (xy1_gap - xy0_gap - (border.top + border.bottom), 0);
+
+ if (has_outer_stroke)
+ {
+ yc += outer_border->top;
+ wc += outer_border->left;
+ hc = MAX (xy1_gap - xy0_gap - (outer_border->top + outer_border->bottom) - (border.top + border.bottom), 0);
+ }
+
+ if (xy0_gap < border_radius.top_left.vertical)
+ junction = (GtkJunctionSides)(junction | GTK_JUNCTION_CORNER_TOPLEFT);
+
+ if (xy1_gap > height - border_radius.bottom_left.vertical)
+ junction = (GtkJunctionSides)(junction | GTK_JUNCTION_CORNER_BOTTOMLEFT);
+
+ break;
+ case GTK_POS_RIGHT:
+ xc = x + width - border.right * 2;
+ yc = y + xy0_gap + border.top;
+ wc = border.right * 2;
+ hc = MAX (xy1_gap - xy0_gap - (border.top + border.bottom), 0);
+
+ if (has_outer_stroke)
+ {
+ xc -= outer_border->right;
+ yc += outer_border->top;
+ wc += outer_border->right;
+ hc = MAX (xy1_gap - xy0_gap - (outer_border->top + outer_border->bottom) - (border.top + border.bottom), 0);
+ }
+
+ if (xy0_gap < border_radius.top_right.vertical)
+ junction = (GtkJunctionSides)(junction | GTK_JUNCTION_CORNER_TOPRIGHT);
+
+ if (xy1_gap > height - border_radius.bottom_right.vertical)
+ junction = (GtkJunctionSides)(junction | GTK_JUNCTION_CORNER_BOTTOMRIGHT);
+
+ break;
+ }
+
+ /* clip the gap */
+ cairo_clip_extents (cr, &x0, &y0, &x1, &y1);
+ cairo_rectangle (cr, x0, y0, x1 - x0, yc - y0);
+ cairo_rectangle (cr, x0, yc, xc - x0, hc);
+ cairo_rectangle (cr, xc + wc, yc, x1 - (xc + wc), hc);
+ cairo_rectangle (cr, x0, yc + hc, x1 - x0, y1 - (yc + hc));
+ cairo_clip (cr);
+
+ /* draw the frame, gap area will not be drawn */
+ tdegtk_cairo_draw_frame (engine, cr, x, y, width, height, 0, junction);
+
+ cairo_restore (cr);
+
+ gtk_border_free (outer_border);
+}
+
+static void
+tdegtk_draw_grip (DRAW_ARGS)
+{
+ GdkRGBA border_color;
+ GdkRGBA *inner_stroke_color;
+ GtkStateFlags state;
+ gint lx, ly;
+
+ state = gtk_theming_engine_get_state (engine);
+
+ gtk_theming_engine_get (engine, state,
+ "-tdegtk-inner-stroke-color", &inner_stroke_color,
+ NULL);
+ gtk_theming_engine_get_border_color (engine, state, &border_color);
+
+ for (ly = 0; ly < 4; ly++)
+ {
+ /* vertically, four rows of dots */
+ for (lx = 0; lx <= ly; lx++)
+ {
+ /* horizontally */
+ int ny = (3.5 - ly) * 3;
+ int nx = lx * 3;
+
+ gdk_cairo_set_source_rgba (cr, inner_stroke_color);
+ cairo_rectangle (cr, x + width - nx - 1, y + height - ny - 1, 2, 2);
+ cairo_fill (cr);
+
+ gdk_cairo_set_source_rgba (cr, &border_color);
+ cairo_rectangle (cr, x + width - nx - 1, y + height - ny - 1, 1, 1);
+ cairo_fill (cr);
+ }
+ }
+
+ gdk_rgba_free (inner_stroke_color);
+}
+
+static void
+tdegtk_draw_handle (DRAW_ARGS)
+{
+ TQRect boundingRect(0, 0, width, height);
+ TQt3CairoPaintDevice pd(NULL, x, y, width, height, cr);
+ TQPainter p(&pd);
+
+ DEBUG_FILL_BACKGROUND_WITH_COLOR(p,0,128,255);
+
+ p.end();
+
+ return;
+
+ gdouble line_width;
+ gint i, bar_y, num_bars, bar_spacing, bar_width, bar_height;
+
+ tdegtk_cairo_draw_background (engine, cr,
+ x, y, width, height,
+ 0, gtk_theming_engine_get_junction_sides (engine));
+
+ if (draw_centroid_texture (engine, cr, x, y, width, height))
+ return;
+
+ tdegtk_get_line_width (engine, &line_width);
+
+ bar_y = 1;
+ num_bars = 3;
+ bar_spacing = 3;
+ bar_width = 3;
+ bar_height = num_bars * bar_spacing * line_width;
+
+ cairo_save (cr);
+
+ cairo_translate (cr, x + (gint) (width / 2), y + (gint) (height / 2));
+
+ if (height > width)
+ cairo_translate (cr, - bar_width / 2 - 0.5, - bar_height / 2 + 0.5);
+ else
+ {
+ cairo_translate (cr, - bar_height / 2 + 0.5, bar_width / 2 + 0.5);
+ cairo_rotate (cr, - G_PI / 2);
+ }
+
+ for (i = 0; i < num_bars; i++)
+ {
+ /* draw bars */
+ cairo_move_to (cr, 0, bar_y);
+ cairo_line_to (cr, bar_width, bar_y);
+ tdegtk_cairo_set_source_border (engine, cr, bar_width, 3);
+ cairo_stroke (cr);
+
+ cairo_move_to (cr, 0, bar_y + line_width);
+ cairo_line_to (cr, bar_width, bar_y + line_width);
+ tdegtk_cairo_set_source_inner_stroke (engine, cr, bar_width, line_width);
+ cairo_stroke (cr);
+
+ bar_y += bar_spacing;
+ }
+
+ cairo_restore (cr);
+}
+
+static void
+tdegtk_draw_line (GtkThemingEngine *engine,
+ cairo_t *cr,
+ gdouble x0,
+ gdouble y0,
+ gdouble x1,
+ gdouble y1)
+{
+ /* line endings */
+ if (y0 == y1)
+ {
+ y0 += 0.5;
+ y1 += 0.5;
+ x0 += 0.5;
+ x1 -= 0.5;
+ }
+ else if (x0 == x1)
+ {
+ x0 += 0.5;
+ x1 += 0.5;
+ y0 += 0.5;
+ y1 -= 0.5;
+ }
+
+ cairo_move_to (cr, x0, y0);
+ cairo_line_to (cr, x1, y1);
+ tdegtk_cairo_set_source_border (engine, cr, MAX (x1 - x0, 1), MAX (y1 - y0, 1));
+ cairo_stroke (cr);
+}
+
+static void
+tdegtk_draw_notebook (DRAW_ARGS,
+ GtkPositionType gap_side,
+ gdouble xy0_gap,
+ gdouble xy1_gap)
+{
+ TQRect boundingRect(0, 0, width, height);
+ TQt3CairoPaintDevice pd(NULL, x, y, width, height, cr);
+ TQPainter p(&pd);
+
+ DEBUG_FILL_BACKGROUND_WITH_COLOR(p,0,255,0);
+
+ GtkStateFlags state;
+ state = gtk_theming_engine_get_state(engine);
+ //tqApp->style().drawPrimitive(TQStyle::PE_ExclusiveIndicator, &p, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE));
+
+ p.end();
+}
+
+static void
+tdegtk_draw_radio (DRAW_ARGS)
+{
+ TQRect boundingRect(0, 0, width, height);
+ TQt3CairoPaintDevice pd(NULL, x, y, width, height, cr);
+ TQPainter p(&pd);
+
+ DEBUG_FILL_BACKGROUND_WITH_COLOR(p,255,0,0);
+
+ GtkStateFlags state;
+ state = gtk_theming_engine_get_state(engine);
+ const GtkWidgetPath* path(gtk_theming_engine_get_path(engine));
+
+ if (gtk_widget_path_is_type(path, GTK_TYPE_TREE_VIEW)) {
+ tqApp->style().drawPrimitive(TQStyle::PE_ExclusiveIndicator, &p, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_GTKTreeViewCell));
+ }
+ else {
+ tqApp->style().drawPrimitive(TQStyle::PE_ExclusiveIndicator, &p, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_TQRadioButton));
+ }
+
+ p.end();
+}
+
+static void
+tdegtk_draw_separator (DRAW_ARGS)
+{
+ gdouble line_width;
+
+ tdegtk_get_line_width (engine, &line_width);
+
+ if (line_width == 0)
+ return;
+
+ /* FIXME right code should be
+ * if (gtk_theming_engine_has_class (engine, GTK_STYLE_CLASS_VERTICAL))
+ * but doesn't work for separator tool item. */
+ if (width > height)
+ {
+ cairo_move_to (cr, x, y + (gint) (height / 2) + line_width / 2);
+ cairo_line_to (cr, x + width, y + (gint) (height / 2) + line_width / 2);
+ tdegtk_cairo_set_source_inner_stroke (engine, cr, width, line_width);
+ cairo_stroke (cr);
+
+ cairo_move_to (cr, x, y + (gint) (height / 2) - line_width / 2);
+ cairo_line_to (cr, x + width, y + (gint) (height / 2) - line_width / 2);
+ tdegtk_cairo_set_source_border (engine, cr, width, line_width);
+ cairo_stroke (cr);
+ }
+ else
+ {
+ cairo_move_to (cr, x + (gint) (width / 2) + line_width / 2, y);
+ cairo_line_to (cr, x + (gint) (width / 2) + line_width / 2, y + height);
+ tdegtk_cairo_set_source_inner_stroke (engine, cr, line_width, height);
+ cairo_stroke (cr);
+
+ cairo_move_to (cr, x + (gint) (width / 2) - line_width / 2, y);
+ cairo_line_to (cr, x + (gint) (width / 2) - line_width / 2, y + height);
+ tdegtk_cairo_set_source_border (engine, cr, line_width, height);
+ cairo_stroke (cr);
+ }
+}
+
+static void
+tdegtk_draw_slider (DRAW_ARGS,
+ GtkOrientation orientation)
+{
+ TQRect boundingRect(0, 0, width, height);
+ TQt3CairoPaintDevice pd(NULL, x, y, width, height, cr);
+ TQPainter p(&pd);
+
+ DEBUG_FILL_BACKGROUND_WITH_COLOR(p,255,0,255);
+
+ GtkStateFlags state;
+ state = gtk_theming_engine_get_state(engine);
+
+ if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_SCROLLBAR)) {
+ TQStringList objectTypes;
+ objectTypes.append(TQSCROLLBAR_OBJECT_NAME_STRING);
+ TQPalette objectPalette = tqApp->palette(objectTypes);
+
+ TQStyleControlElementData ceData;
+ TQStyle::ControlElementFlags elementFlags;
+ ceData.widgetObjectTypes = objectTypes;
+ ceData.rect = boundingRect;
+ ceData.orientation = (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_VERTICAL))?TQt::Vertical:TQt::Horizontal;
+
+ // Draw slider
+ TQRect scrollpagerect = tqApp->style().querySubControlMetrics(TQStyle::CC_ScrollBar, ceData, elementFlags, TQStyle::SC_ScrollBarSlider, gtkToTQtStyleFlags(engine, state, TQT3WT_NONE));
+ if (ceData.orientation == TQt::Vertical) {
+ scrollpagerect.setY(ceData.rect.y());
+ scrollpagerect.setHeight(ceData.rect.height());
+ }
+ else {
+ scrollpagerect.setX(ceData.rect.x());
+ scrollpagerect.setWidth(ceData.rect.width());
+ }
+ tqApp->style().drawPrimitive(TQStyle::PE_ScrollBarSlider, &p, scrollpagerect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE));
+ }
+
+ p.end();
+}
+
+static void
+tdegtk_draw_spinbutton_background (DRAW_ARGS)
+{
+ GtkBorder border, *outer_border;
+ GtkJunctionSides junction;
+ GtkStateFlags state;
+
+ junction = gtk_theming_engine_get_junction_sides (engine);
+
+ state = gtk_theming_engine_get_state (engine);
+
+ gtk_theming_engine_get (engine, state,
+ "-tdegtk-outer-stroke-width", &outer_border,
+ NULL);
+ gtk_theming_engine_get_border (engine, state, &border);
+
+ cairo_save (cr);
+
+ cairo_rectangle (cr, x, y, width, height);
+ cairo_clip (cr);
+
+ if (!(junction & GTK_JUNCTION_CORNER_TOPRIGHT))
+ {
+ y = ceil (y);
+ height = floor (height);
+ height += border.bottom + outer_border->bottom;
+ }
+ else
+ {
+ y = floor (y);
+ height = ceil (height);
+ y -= outer_border->top;
+ height += outer_border->bottom;
+ }
+
+ tdegtk_cairo_draw_background (engine, cr,
+ x, y, width, height,
+ 0, junction);
+
+ cairo_restore (cr);
+
+ gtk_border_free (outer_border);
+}
+
+static void
+tdegtk_draw_spinbutton_frame (DRAW_ARGS)
+{
+ GtkBorder border, *outer_border;
+ GtkJunctionSides junction;
+ GtkStateFlags state;
+
+ junction = gtk_theming_engine_get_junction_sides (engine);
+
+ state = gtk_theming_engine_get_state (engine);
+
+ gtk_theming_engine_get (engine, state,
+ "-tdegtk-outer-stroke-width", &outer_border,
+ NULL);
+ gtk_theming_engine_get_border (engine, state, &border);
+
+ cairo_save (cr);
+
+ cairo_rectangle (cr, x, y, width, height);
+ cairo_clip (cr);
+
+ if (!(junction & GTK_JUNCTION_CORNER_TOPRIGHT))
+ {
+ y = ceil (y);
+ height = floor (height);
+ height += border.bottom + outer_border->bottom;
+ }
+ else
+ {
+ y = floor (y);
+ height = ceil (height);
+ y -= outer_border->top;
+ height += outer_border->bottom;
+ }
+
+ tdegtk_cairo_draw_frame (engine, cr,
+ x, y, width, height,
+ 0, junction);
+
+ cairo_restore (cr);
+
+ gtk_border_free (outer_border);
+}
+
+void
+tdegtk_register_style_default (TdeGtkStyleFunctions *functions)
+{
+ g_assert (functions);
+
+ functions->draw_activity = tdegtk_draw_activity;
+ functions->draw_arrow = tdegtk_draw_arrow;
+ functions->draw_cell_background = tdegtk_draw_cell_background;
+ functions->draw_cell_frame = tdegtk_draw_cell_frame;
+ functions->draw_check = tdegtk_draw_check;
+ functions->draw_common = tdegtk_draw_common;
+ functions->draw_common_background = tdegtk_draw_common_background;
+ functions->draw_common_frame = tdegtk_draw_common_frame;
+ functions->draw_expander = tdegtk_draw_expander;
+ functions->draw_extension = tdegtk_draw_extension;
+ functions->draw_focus = tdegtk_draw_focus;
+ functions->draw_frame_gap = tdegtk_draw_frame_gap;
+ functions->draw_grip = tdegtk_draw_grip;
+ functions->draw_handle = tdegtk_draw_handle;
+ functions->draw_line = tdegtk_draw_line;
+ functions->draw_notebook = tdegtk_draw_notebook;
+ functions->draw_radio = tdegtk_draw_radio;
+ functions->draw_separator = tdegtk_draw_separator;
+ functions->draw_slider = tdegtk_draw_slider;
+ functions->draw_spinbutton_background = tdegtk_draw_spinbutton_background;
+ functions->draw_spinbutton_frame = tdegtk_draw_spinbutton_frame;
+}
diff --git a/tdegtk/tdegtk-hooks.cpp b/tdegtk/tdegtk-hooks.cpp
new file mode 100644
index 0000000..dbb291f
--- /dev/null
+++ b/tdegtk/tdegtk-hooks.cpp
@@ -0,0 +1,100 @@
+/*
+* this file was largely taken from the oxygen gtk engine
+* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
+* Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com>
+*
+* 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 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 St, Fifth Floor, Boston,
+* MA 02110-1301, USA.
+*/
+
+#include "tdegtk-hooks.h"
+#include "../config.h"
+
+#include <cassert>
+#include <iostream>
+
+ #if TDEGTK_DEBUG
+ static int counter( 0 );
+ #endif
+
+ //__________________________________________________________________
+ bool Hook::connect( const std::string& signal, GType typeId, GSignalEmissionHook hookFunction, gpointer data )
+ {
+ // make sure that signal is not already connected
+ assert( _signalId == 0 && _hookId == 0 );
+
+ // check type id
+ if( !g_type_class_peek( typeId ) )
+ {
+
+ #if TDEGTK_DEBUG
+ std::cerr << "Oxygen::Hook::connect - typeId " << g_type_name(typeId) << " not yet installed" << std::endl;
+ #endif
+
+ g_type_class_ref( typeId );
+
+ }
+
+ // store signal id
+ _signalId = g_signal_lookup( signal.c_str(), typeId );
+ if( !_signalId )
+ {
+
+ #if TDEGTK_DEBUG
+ std::cerr << "Oxygen::Hook::connect - signal " << signal << " not installed." << std::endl;
+ #endif
+
+ return false;
+
+ }
+
+ // store attributes and create connection
+ _hookId = g_signal_add_emission_hook(
+ _signalId,
+ (GQuark)0L,
+ hookFunction,
+ data, 0L);
+
+ #if TDEGTK_DEBUG
+ ++counter;
+ std::cerr << "Oxygen::Hook::connect - hook: " << _hookId << " counter: " << counter << std::endl;
+ #endif
+
+ return true;
+
+ }
+
+ //____________________________________________________________________
+ void Hook::disconnect( void )
+ {
+
+ // disconnect signal
+ if( _signalId > 0 && _hookId > 0 )
+ {
+
+ #if TDEGTK_DEBUG
+ --counter;
+ std::cerr << "Oxygen::Hook::disconnect - hook: " << _hookId << " counter: " << counter << std::endl;
+ #endif
+
+ g_signal_remove_emission_hook( _signalId, _hookId );
+
+ }
+
+ _signalId = 0;
+ _hookId = 0;
+
+ }
+
diff --git a/tdegtk/tdegtk-hooks.h b/tdegtk/tdegtk-hooks.h
new file mode 100644
index 0000000..a12244d
--- /dev/null
+++ b/tdegtk/tdegtk-hooks.h
@@ -0,0 +1,63 @@
+#ifndef tdegtk_hooks_h
+#define tdegtk_hooks_h
+/*
+* this file was largely taken from the oxygen gtk engine
+* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
+* Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com>
+*
+* 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 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 St, Fifth Floor, Boston,
+* MA 02110-1301, USA.
+*/
+
+#include <gtk/gtk.h>
+#include <string>
+
+
+ //! handles gtk signal hooks
+ class Hook
+ {
+ public:
+
+ //! constructor
+ Hook( void ):
+ _signalId(0),
+ _hookId(0)
+ {}
+
+ //! destructor
+ virtual ~Hook( void )
+ {}
+
+
+
+ //! connect
+ bool connect( const std::string&, GType, GSignalEmissionHook, gpointer );
+
+ bool connect( const std::string& signal, GSignalEmissionHook hook, gpointer data )
+ { return connect( signal, GTK_TYPE_WIDGET, hook, data ); }
+
+ //! disconnect
+ void disconnect( void );
+
+ private:
+
+ //! signal id
+ guint _signalId;
+ gulong _hookId;
+
+ };
+
+#endif
+
diff --git a/tdegtk/tdegtk-signals.cpp b/tdegtk/tdegtk-signals.cpp
new file mode 100644
index 0000000..131de88
--- /dev/null
+++ b/tdegtk/tdegtk-signals.cpp
@@ -0,0 +1,89 @@
+
+/*
+* this file was largely taken from the oxygen gtk engine
+* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
+*
+* 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 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 St, Fifth Floor, Boston,
+* MA 02110-1301, USA.
+*/
+
+#include "tdegtk-signals.h"
+#include "../config.h"
+
+#include <iostream>
+
+
+ #if OXYGEN_DEBUG
+ static int counter( 0 );
+ #endif
+
+ //____________________________________________________________________
+ bool Signal::connect( GObject* object, const std::string& signal, GCallback callback, gpointer data, bool after )
+ {
+ // make sure that signal is not already connected
+ assert( _object == 0L && _id == 0 );
+
+ // check object
+ if( !object ) return false;
+
+ // first try lookup signal
+ if( !g_signal_lookup( signal.c_str(), G_OBJECT_TYPE(object) ) )
+ {
+
+ #if OXYGEN_DEBUG
+ std::cerr << "Oxygen::Signal::connect - signal " << signal << " not installed on widget " << object << std::endl;
+ #endif
+
+ return false;
+
+ }
+
+ // store attributes and create connection
+ _object = object;
+ if(after) _id = g_signal_connect_after( object, signal.c_str(), callback, data );
+ else _id = g_signal_connect( object, signal.c_str(), callback, data );
+
+ #if OXYGEN_DEBUG
+ ++counter;
+ std::cerr << "Oxygen::Signal::connect - _id: " << _id << " counter: " << counter << std::endl;
+ #endif
+
+ return true;
+
+ }
+
+ //____________________________________________________________________
+ void Signal::disconnect( void )
+ {
+
+ // disconnect signal
+ if( _object && _id > 0 )
+ {
+
+ #if OXYGEN_DEBUG
+ --counter;
+ std::cerr << "Oxygen::Signal::disconnect - _id: " << _id << " counter: " << counter << std::endl;
+ #endif
+
+ g_signal_handler_disconnect( _object, _id );
+
+ }
+
+ // reset members
+ _object = 0L;
+ _id = 0;
+
+ }
+
diff --git a/tdegtk/tdegtk-signals.h b/tdegtk/tdegtk-signals.h
new file mode 100644
index 0000000..1d0310c
--- /dev/null
+++ b/tdegtk/tdegtk-signals.h
@@ -0,0 +1,64 @@
+#ifndef tdegtk_signal_h
+#define tdegtk_signal_h
+
+/*
+* this file was largely taken from the oxygen gtk engine
+* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
+*
+* 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 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 St, Fifth Floor, Boston,
+* MA 02110-1301, USA.
+*/
+
+#include <gtk/gtk.h>
+#include <cassert>
+#include <string>
+
+ //! handles gtk signal connections
+ class Signal
+ {
+ public:
+
+ //! constructor
+ Signal( void ):
+ _id(0),
+ _object(0L)
+ {}
+
+ //! destructor
+ virtual ~Signal( void )
+ {}
+
+ //! true if connected
+ bool isConnected( void ) const
+ { return _id > 0 && _object; }
+
+ //! connect
+ bool connect( GObject*, const std::string&, GCallback, gpointer, bool after=false );
+
+ //! disconnect
+ void disconnect( void );
+
+ private:
+
+ //! signal id
+ guint _id;
+
+ //! connected object
+ GObject* _object;
+
+ };
+
+#endif
+
diff --git a/tdegtk/tdegtk-theme.c b/tdegtk/tdegtk-theme.c
deleted file mode 100644
index 564a0fd..0000000
--- a/tdegtk/tdegtk-theme.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* The TdeGtk Theming Engine for Gtk+.
- * Copyright (C) 2011 Canonical Ltd
- *
- * 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 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 St, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- * Authored by Andrea Cimitan <andrea.cimitan@canonical.com>
- *
- */
-
-#include <gmodule.h>
-#include <gtk/gtk.h>
-
-#include "tdegtk-engine.h"
-
-G_MODULE_EXPORT void theme_init (GTypeModule *module);
-
-G_MODULE_EXPORT void theme_exit (void);
-
-G_MODULE_EXPORT GtkThemingEngine* create_engine (void);
-
-G_MODULE_EXPORT void
-theme_init (GTypeModule *module)
-{
- tdegtk_engine_register_types (module);
-}
-
-G_MODULE_EXPORT void
-theme_exit (void)
-{
-}
-
-G_MODULE_EXPORT GtkThemingEngine*
-create_engine (void)
-{
- return GTK_THEMING_ENGINE (g_object_new (TDEGTK_TYPE_ENGINE,
- "name", "tdegtk",
- NULL));
-}
diff --git a/tdegtk/tdegtk-theme.cpp b/tdegtk/tdegtk-theme.cpp
new file mode 100644
index 0000000..28ff8e9
--- /dev/null
+++ b/tdegtk/tdegtk-theme.cpp
@@ -0,0 +1,788 @@
+/* The TdeGtk Theming Engine for Gtk+.
+ * Copyright (C) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+ *
+ * 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 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 St, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#define TDEGTK_THEME_THEME_DIRECTORY_NAME "tdegtk"
+#define TDEGTK_THEME_CONTROL_FILE_NAME "gtk.css"
+#define RC_CACHE_VERSION TQString("1")
+#define DEBUG_PRINT(x) if (gtk3TQtDebug) printf(x"\n\r");
+#define DEBUG_PRINT_ARGS(x,y) if (gtk3TQtDebug) printf(x"\n\r",y);
+
+bool gtk3TQtEnable = false;
+int gtk3TQtDebug = false;
+bool tde_showIconsOnPushButtons = false;
+
+void initTDESettings();
+void writeGtkThemeControlFile(int forceRecreate);
+
+extern "C" {
+ #include <gmodule.h>
+ #include <gtk/gtk.h>
+
+ #include "tdegtk-engine.h"
+
+ G_MODULE_EXPORT void theme_init(GTypeModule *module);
+
+ G_MODULE_EXPORT void theme_exit(void);
+
+ G_MODULE_EXPORT GtkThemingEngine* create_engine(void);
+
+ G_MODULE_EXPORT void theme_init(GTypeModule *module) {
+ tdegtk_engine_register_types(module);
+ }
+
+ G_MODULE_EXPORT void theme_exit(void) {
+ //
+ }
+}
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <utility>
+#include <vector>
+#include <fstream>
+#include <sstream>
+
+#include <tqpainter.h>
+#include <tqapplication.h>
+#include <tqdir.h>
+#include <tqfile.h>
+#include <tqstyle.h>
+#include <tqslider.h>
+#include <tqscrollbar.h>
+#include <tqregexp.h>
+#include <tqfont.h>
+
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+
+#include <gdk/gdkx.h>
+
+#include "tdegtk-widgetlookup.h"
+
+extern WidgetLookup m_widgetLookup;
+
+typedef std::pair<std::string, unsigned int> SizePair;
+typedef std::vector<SizePair> SizeMap;
+SizeMap icon_sizes;
+
+G_MODULE_EXPORT GtkThemingEngine* create_engine(void) {
+ gtk3TQtEnable = true;
+
+ gtk3TQtDebug = (getenv("GTK3_TQT_ENGINE_DEBUG") != NULL) ? 1 : 0;
+ DEBUG_PRINT("Creating KApplication")
+
+ int argc = 1;
+ char** argv;
+ // Supply it with fake data to keep KApplication happy
+ argv = (char**) malloc(sizeof(char*));
+ argv[0] = (char*) malloc(sizeof(char) * 21);
+ strncpy(argv[0], "gtk3-tqt-application", 21);
+
+ KAboutData aboutData("gtk3-tqt-engine", I18N_NOOP("gtk3-tqt-engine"), "v0.1",
+ "GTK3 TQt theme engine", KAboutData::License_GPL,
+ "(c) 2012, Timothy Pearson",
+ "", 0 /* TODO: Website */, "kb9vqf@pearsoncomputing.net");
+ KCmdLineArgs::init(argc, const_cast<char**>(argv), &aboutData);
+
+ KApplication::disableAutoDcopRegistration();
+ new KApplication(gdk_x11_get_default_xdisplay(), true, 0, 0, true);
+
+ initTDESettings();
+
+ // initialize icon sizes
+ icon_sizes.push_back(std::make_pair("panel-menu", 16));
+ icon_sizes.push_back(std::make_pair("panel", 32));
+ icon_sizes.push_back(std::make_pair("gtk-small-toolbar", 22));
+ icon_sizes.push_back(std::make_pair("gtk-large-toolbar", 22));
+ icon_sizes.push_back(std::make_pair("gtk-dnd", 48));
+ icon_sizes.push_back(std::make_pair("gtk-button", 16));
+ icon_sizes.push_back(std::make_pair("gtk-menu", 16));
+ icon_sizes.push_back(std::make_pair("gtk-dialog", 32));
+ icon_sizes.push_back(std::make_pair("", 16));
+
+ writeGtkThemeControlFile(false);
+
+ // Initialize hooks
+ m_widgetLookup.initializeHooks();
+
+ return GTK_THEMING_ENGINE (g_object_new (TDEGTK_TYPE_ENGINE, "name", "tdegtk", NULL));
+}
+
+// =========================================================================================================
+//
+// TQt3/GTK Theme Control Functions
+//
+// =========================================================================================================
+
+TQStringList tdeSearchPaths;
+TQString iconTheme;
+TQStringList iconThemeDirs;
+TQColor alternateBackgroundColour;
+int showIconsOnButtons;
+int toolbarStyle;
+
+TQString tdeConfigValue(const TQString& section, const TQString& name, const TQString& def) {
+ KConfig currentConfig;
+ currentConfig.setGroup(section);
+ return currentConfig.readEntry(name, def);
+}
+
+bool tdeBoolConfigValue(const TQString& section, const TQString& name, bool def) {
+ KConfig currentConfig;
+ currentConfig.setGroup(section);
+ return currentConfig.readBoolEntry(name, def);
+}
+
+TQString tdeFindDir(const TQString& suffix, const TQString& file1, const TQString& file2) {
+ for ( TQStringList::Iterator it = tdeSearchPaths.begin(); it != tdeSearchPaths.end(); ++it )
+ {
+ if ((TQFile::exists((*it) + suffix + file1)) || (TQFile::exists((*it) + suffix + file2)))
+ return (*it) + suffix;
+ }
+ return TQString();
+}
+
+TQString runCommand(const TQString& command) {
+ FILE* p = popen(command.latin1(), "r");
+ if ((p == NULL) || (p < 0))
+ return TQString();
+
+ TQString ret;
+ while (!feof(p))
+ {
+ char buffer[256];
+ int n = fread(buffer, 1, 255, p);
+ buffer[n] = '\0';
+ ret += buffer;
+ }
+ pclose(p);
+
+ return ret.stripWhiteSpace();
+}
+
+void initTDESettings() {
+ tdeSearchPaths.clear();
+
+ TQString tdeHome = getenv("TDEHOME");
+ TQString tdeDirs = getenv("TDEDIRS");
+ TQString tdeDir = getenv("TDEDIR");
+
+ if (!tdeHome.isEmpty()) {
+ tdeSearchPaths.append(tdeHome);
+ }
+ tdeSearchPaths.append(runCommand("tde-config --localprefix"));
+
+ if (!tdeDirs.isEmpty()) {
+ tdeSearchPaths += TQStringList::split(':', tdeDirs);
+ }
+ if (!tdeDir.isEmpty()) {
+ tdeSearchPaths.append(tdeDir);
+ }
+ tdeSearchPaths.append(runCommand("tde-config --prefix"));
+
+ iconTheme = tdeConfigValue("Icons", "Theme", "crystalsvg");
+ tde_showIconsOnPushButtons = tdeBoolConfigValue("KDE", "ShowIconsOnPushButtons", false);
+
+ TQStringList back = TQStringList::split(',', tdeConfigValue("General", "alternateBackground", "238,246,255"));
+ alternateBackgroundColour.setRgb(back[0].toInt(), back[1].toInt(), back[2].toInt());
+
+ showIconsOnButtons = (tdeConfigValue("KDE", "ShowIconsOnPushButtons", "true").lower() == "true");
+
+ TQString tmp = tdeConfigValue("Toolbar style", "IconText", "true").lower();
+ if (tmp == "icononly") {
+ toolbarStyle = 0;
+ }
+ else if (tmp == "icontextright") {
+ toolbarStyle = 3;
+ }
+ else if (tmp == "textonly") {
+ toolbarStyle = 1;
+ }
+ else if (tmp == "icontextbottom") {
+ toolbarStyle = 2;
+ }
+ else {
+ // Should never happen, but just in case we fallback to TDE's default "icononly"
+ toolbarStyle = 0;
+ }
+}
+
+void gtk3_tqt_load_resource_string(const char* css_string) {
+ GtkCssProvider *provider;
+
+ provider = gtk_css_provider_new();
+ gtk_css_provider_load_from_data(provider, css_string, -1, NULL);
+ GdkDisplay *display = gdk_display_get_default();
+ GdkScreen *screen = gdk_display_get_default_screen(display);
+ gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ g_object_unref(provider);
+
+ DEBUG_PRINT_ARGS("gtk3_tqt_load_resource_string(%s)", css_string)
+}
+
+void gtk3_tqt_reload_theme_definition_file(const char* filename) {
+ GtkCssProvider *provider;
+ GError *error;
+
+ provider = gtk_css_provider_new();
+ GdkDisplay *display = gdk_display_get_default();
+ GdkScreen *screen = gdk_display_get_default_screen(display);
+ gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ g_object_unref(provider);
+ if (!gtk_css_provider_load_from_path(provider, filename, &error)) {
+ g_printerr("%s: error parsing %s: %s\n", G_STRFUNC, filename, error->message);
+ g_clear_error(&error);
+ }
+}
+
+TQString tdeFontToGTKFontString(TQFont font) {
+ TQString fontDescriptor = "font: ";
+ fontDescriptor.append(font.family());
+ if (font.bold()) {
+ fontDescriptor.append(" bold");
+ }
+ if (font.italic()) {
+ fontDescriptor.append(" italic");
+ }
+ if (font.pointSizeFloat() != -1) {
+ fontDescriptor.append(TQString(" %1").arg(font.pointSizeFloat()));
+ }
+ else {
+ fontDescriptor.append(TQString(" %1px").arg(font.pixelSize()));
+ }
+
+ return fontDescriptor;
+}
+
+// Thanks Martin Dvorak of metatheme
+TQString parse_rc_string(const TQString& defs, const TQString& pattern, bool widgetClass = true) {
+ static int dynamic_counter = 0;
+ ++dynamic_counter;
+
+ return pattern + " {\n\t" + defs + ";\n}\n\n";
+}
+
+GtkIconSet* generateIconSet(const std::string& gtkIconName, const std::string& tdeIconName, TQStringList pathList) {
+ if (tdeIconName == "NONE") {
+ return 0L;
+ }
+
+ bool empty = true;
+
+ // create iconSet
+ GtkIconSet* iconSet = gtk_icon_set_new();
+
+ // loop over iconSizes
+ for (SizeMap::const_iterator sizeIter = icon_sizes.begin(); sizeIter != icon_sizes.end(); ++sizeIter) {
+ // generate full icon name
+ std::ostringstream iconFileStream;
+ iconFileStream << sizeIter->second << "x" << sizeIter->second << "/" << tdeIconName;
+
+ // loop over provided path to see if at least one icon is found
+ for (TQStringList::const_iterator pathIter = pathList.begin(); pathIter != pathList.end(); ++pathIter) {
+ std::string filename((*pathIter + '/' + iconFileStream.str()).latin1());
+ if (!std::ifstream(filename.c_str())) {
+ continue;
+ }
+
+ empty = false;
+ GtkIconSource* iconSource(gtk_icon_source_new());
+
+ // set name
+ gtk_icon_source_set_filename(iconSource, filename.c_str());
+
+ // set direction and state wildcarded
+ gtk_icon_source_set_direction_wildcarded(iconSource, TRUE);
+ gtk_icon_source_set_state_wildcarded(iconSource, TRUE);
+
+ // set size
+ if (sizeIter->first.empty()) {
+ gtk_icon_source_set_size_wildcarded(iconSource, TRUE);
+ }
+ else {
+ GtkIconSize size = gtk_icon_size_from_name(sizeIter->first.c_str());
+ if (size != GTK_ICON_SIZE_INVALID) {
+ gtk_icon_source_set_size_wildcarded(iconSource, FALSE);
+ gtk_icon_source_set_size(iconSource, size);
+ }
+ }
+
+ // add source to iconSet
+ gtk_icon_set_add_source(iconSet, iconSource);
+ break;
+ }
+ }
+
+ // if nothing found, return;
+ if (empty) {
+ gtk_icon_set_unref(iconSet);
+ return 0L;
+ }
+ else {
+ return iconSet;
+ }
+
+}
+
+void doIconMapping(const char* gtkName, const char * tdeName, GtkIconFactory* factory, TQStringList tdeIconThemeDirs) {
+ GtkIconSet* iconSet = generateIconSet(gtkName, tdeName, tdeIconThemeDirs);
+ if (iconSet) {
+ gtk_icon_factory_add(factory, gtkName, iconSet);
+ gtk_icon_set_unref(iconSet);
+ }
+}
+
+TQString colorString(TQColor color) {
+ TQString ret = "rgb(";
+ ret += TQString::number(color.red()) + ", ";
+ ret += TQString::number(color.green()) + ", ";
+ ret += TQString::number(color.blue()) + ")";
+
+ return ret;
+}
+
+void setColour(TQString name, TQString state, TQColor color) {
+ state = ":" + state;
+ if (state == ":normal") {
+ state = "";
+ }
+ gtk3_tqt_load_resource_string(parse_rc_string(name + ": " + colorString(color), "*" + state).latin1());
+}
+
+static TQStringList iconInheritsDirs(const TQString& icondir) {
+ TQFile index;
+ index.setName(icondir + "index.theme");
+ if( !index.open( IO_ReadOnly )) {
+ index.setName(icondir + "index.desktop");
+ if( !index.open( IO_ReadOnly ))
+ return TQStringList();
+ }
+ char buf[1024];
+ TQRegExp reg( "^\\s*Inherits=([^\\n]*)" );
+ for(;;) {
+ if( index.readLine(buf, 1023) <= 0 ) {
+ break;
+ }
+ if( reg.search(buf, 0) >= 0 ) {
+ return TQStringList::split(",", reg.cap(1));
+ }
+ }
+ return TQStringList();
+}
+
+void addIconThemeDir(const TQString& theme) {
+ // Try to find this theme's directory
+ TQString icondir = tdeFindDir("/share/icons/" + theme + "/", "index.theme", "index.desktop");
+ if(icondir.isEmpty()) {
+ return;
+ }
+ if (iconThemeDirs.contains(icondir)) {
+ return;
+ }
+
+ // Add this theme to the list
+ iconThemeDirs.append(icondir);
+
+ // Do it again for any parent themes
+ TQStringList parents = iconInheritsDirs(icondir);
+ for ( TQStringList::Iterator it=parents.begin() ; it!=parents.end(); ++it) {
+ addIconThemeDir((*it).stripWhiteSpace());
+ }
+}
+
+void writeGtkThemeControlFile(int forceRecreate) {
+ if (!gtk3TQtEnable) {
+ return;
+ }
+
+ DEBUG_PRINT("writeGtkThemeControlFile()")
+
+ // Set colors
+ // Normal
+ setColour("color", "normal", tqApp->palette().active().text());
+ setColour("background-color", "normal", tqApp->palette().active().background());
+// setColour("text", "normal", tqApp->palette().active().text());
+// setColour("base", "normal", tqApp->palette().active().base());
+
+ // Active (on)
+ setColour("color", "active", tqApp->palette().active().text());
+ setColour("background-color", "active", tqApp->palette().active().background());
+// setColour("text", "active", tqApp->palette().active().text());
+// setColour("base", "active", tqApp->palette().active().base());
+
+ // Mouseover
+ setColour("color", "prelight", tqApp->palette().active().text()); // menu items - change?
+ setColour("background-color", "prelight", tqApp->palette().active().highlight());
+// setColour("text", "prelight", tqApp->palette().active().text());
+// setColour("base", "prelight", tqApp->palette().active().base());
+
+ // Selected
+ setColour("color", "selected", tqApp->palette().active().highlightedText());
+ setColour("background-color", "selected", tqApp->palette().active().highlight());
+// setColour("text", "selected", tqApp->palette().active().highlightedText());
+// setColour("base", "selected", tqApp->palette().active().highlight());
+
+ // Disabled
+ setColour("color", "insensitive", tqApp->palette().disabled().text());
+ setColour("background-color", "insensitive", tqApp->palette().disabled().background());
+// setColour("text", "insensitive", tqApp->palette().disabled().text());
+// setColour("base", "insensitive", tqApp->palette().disabled().background());
+
+ // Set up global application settings
+ GtkSettings* gtksettings = gtk_settings_get_default();
+ GtkSettingsValue svalue;
+ if (gtksettings) {
+ g_object_set(gtksettings, "gtk-alternative-button-order", TRUE, NULL);
+ g_object_set(gtksettings, "gtk-button-images", tde_showIconsOnPushButtons, NULL);
+ g_object_set(gtksettings, "gtk-menu-popup-delay", tqApp->style().styleHint(TQStyle::SH_PopupMenu_SubMenuPopupDelay), NULL);
+ // Handle toolbar text display
+ if (toolbarStyle == 3) {
+ // This is broken by GTK bug #68700
+ g_object_set(gtksettings, "gtk-toolbar-style", GTK_TOOLBAR_BOTH_HORIZ, NULL);
+ }
+ else if (toolbarStyle == 2) {
+ g_object_set(gtksettings, "gtk-toolbar-style", GTK_TOOLBAR_BOTH, NULL);
+ }
+ else if (toolbarStyle == 1) {
+ g_object_set(gtksettings, "gtk-toolbar-style", GTK_TOOLBAR_TEXT, NULL);
+ }
+ else {
+ g_object_set(gtksettings, "gtk-toolbar-style", GTK_TOOLBAR_ICONS, NULL);
+ }
+ }
+
+ // This function takes quite a long time to execute, and is run at the start of every app.
+ // In order to speed it up, we can store the results in a file, along with the name of icon
+ // theme and style. This file can then be regenerated when the icon theme or style change.
+
+ TQDir curDir;
+ TQString themeFilePath = TQDir::homeDirPath();
+ curDir.setPath(themeFilePath);
+ if (!curDir.exists()) {
+ curDir.mkdir(themeFilePath);
+ }
+ themeFilePath = themeFilePath + "/.themes/";
+ curDir.setPath(themeFilePath);
+ if (!curDir.exists()) {
+ curDir.mkdir(themeFilePath);
+ }
+ themeFilePath = themeFilePath + TQString(TDEGTK_THEME_THEME_DIRECTORY_NAME) + "/";
+ curDir.setPath(themeFilePath);
+ if (!curDir.exists()) {
+ curDir.mkdir(themeFilePath);
+ }
+ themeFilePath = themeFilePath + "gtk-3.0/";
+ curDir.setPath(themeFilePath);
+ if (!curDir.exists()) {
+ curDir.mkdir(themeFilePath);
+ }
+
+ themeFilePath = themeFilePath + TDEGTK_THEME_CONTROL_FILE_NAME;
+ TQFile themeFile(themeFilePath);
+ TQTextStream stream;
+
+ if (!forceRecreate && themeFile.exists())
+ {
+ themeFile.open(IO_ReadOnly);
+ stream.setDevice(TQT_TQIODEVICE(&themeFile));
+
+ if (stream.readLine() == "/* " + iconTheme + ", " + tqApp->style().name() + ", " + RC_CACHE_VERSION + " */")
+ {
+ // This cache matches the current icon theme and style
+ gtk3_tqt_reload_theme_definition_file(themeFilePath.latin1());
+ return;
+ }
+
+ stream.unsetDevice();
+ themeFile.close();
+ }
+
+ themeFile.open(IO_WriteOnly | IO_Truncate);
+ stream.setDevice(TQT_TQIODEVICE(&themeFile));
+
+ stream << "/* " << iconTheme << ", " << tqApp->style().name() << ", " << RC_CACHE_VERSION << " */\n\n";
+ stream << "/* This file was generated by the Gtk TQt Theme Engine */\n";
+ stream << "/* It will be recreated when you change your TDE icon theme or widget style */\n\n";
+
+ stream << "\n";
+ stream << "* {\n\tengine:tdegtk;\n}\n";
+ stream << "\n";
+
+ TQScrollBar sbar(NULL);
+ sbar.setOrientation(TQt::Horizontal);
+ sbar.setValue(1);
+ sbar.resize(200,25);
+
+ // The following code determines how many buttons are on a scrollbar
+ // It works by looking at each pixel of the scrollbar's area not taken up by the groove,
+ // and asking the style which subcontrol is at that location.
+ TQRect rect = tqApp->style().querySubControlMetrics(TQStyle::CC_ScrollBar, &sbar, TQStyle::SC_ScrollBarGroove);
+
+ bool back1 = false;
+ bool forward1 = false;
+ bool back2 = false;
+ bool forward2 = false;
+
+ TQStyle::SubControl sc = TQStyle::SC_None;
+ for (TQPoint pos(0,7) ; pos.x()<rect.x() ; pos.setX(pos.x()+1))
+ {
+ TQStyle::SubControl sc2 = tqApp->style().querySubControl(TQStyle::CC_ScrollBar, &sbar, pos);
+ if (sc != sc2)
+ {
+ if (sc2 == TQStyle::SC_ScrollBarAddLine) forward1 = true;
+ if (sc2 == TQStyle::SC_ScrollBarSubLine) back1 = true;
+ sc = sc2;
+ }
+ }
+ sc = TQStyle::SC_None;
+ for (TQPoint pos(rect.x()+rect.width(),7) ; pos.x()<200 ; pos.setX(pos.x()+1))
+ {
+ TQStyle::SubControl sc2 = tqApp->style().querySubControl(TQStyle::CC_ScrollBar, &sbar, pos);
+ if (sc != sc2)
+ {
+ if (sc2 == TQStyle::SC_ScrollBarAddLine) forward2 = true;
+ if (sc2 == TQStyle::SC_ScrollBarSubLine) back2 = true;
+ sc = sc2;
+ }
+ }
+
+ bool combobox_appears_as_list = (!(tqApp->style().styleHint(TQStyle::SH_ComboBox_Popup) || tqApp->style().styleHint(TQStyle::SH_GUIStyle) == TQt::MotifStyle));
+ stream << parse_rc_string(TQString("-GtkComboBox-appears-as-list: %1px").arg(combobox_appears_as_list), "*");
+
+ stream << parse_rc_string(TQString("-GtkScrollbar-has-backward-stepper: ") + (back1 ? "1" : "0"), "*");
+ stream << parse_rc_string(TQString("-GtkScrollbar-has-forward-stepper: ") + (forward2 ? "1" : "0"), "*");
+ stream << parse_rc_string(TQString("-GtkScrollbar-has-secondary-forward-stepper: ") + (forward1 ? "1" : "0"), "*");
+ stream << parse_rc_string(TQString("-GtkScrollbar-has-secondary-backward-stepper: ") + (back2 ? "1" : "0"), "*");
+
+ stream << parse_rc_string("-GtkScrollbar-stepper-size: " + TQString::number(tqApp->style().querySubControlMetrics(TQStyle::CC_ScrollBar, &sbar, TQStyle::SC_ScrollBarSubLine).width() - 1), "*");
+
+ stream << parse_rc_string("-GtkScrollbar-min-slider-length: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ScrollBarSliderMin)), "*");
+ stream << parse_rc_string("-GtkScrollbar-slider-width: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ScrollBarExtent)-2), "*");
+
+ stream << parse_rc_string("-GtkButton-child-displacement-x: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ButtonShiftHorizontal)), "*");
+ stream << parse_rc_string("-GtkButton-child-displacement-y: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ButtonShiftVertical)), "*");
+ stream << parse_rc_string("-GtkButton-default-border: 0 0 0 0", "*");
+ stream << parse_rc_string("-GtkButton-default-outside-border: 0 0 0 0", "*");
+#ifdef USE_NATIVE_GTK_BUTTON_DRAWING
+ stream << parse_rc_string("-GtkButton-inner-border: 2 2 2 2", "*");
+#else
+ if (tde_showIconsOnPushButtons) {
+ stream << parse_rc_string("-GtkButton-inner-border: 10 10 2 2", "*"); // Allow space for the icon on either side of the text
+ }
+ else {
+ stream << parse_rc_string("-GtkButton-inner-border: 2 2 2 2", "*");
+ }
+#endif
+
+ stream << parse_rc_string("-GtkButtonBox-child_min_height: 0", "*");
+ stream << parse_rc_string("-GtkButtonBox-child_internal_pad_x: 0", "*");
+ stream << parse_rc_string("-GtkButtonBox-child_internal_pad_y: 0", "*");
+
+ TQSlider slider(NULL); // To keep BlueCurve happy
+ stream << parse_rc_string("-GtkScale-slider-length: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_SliderLength, &slider)), "*");
+
+ stream << parse_rc_string("-GtkRange-arrow-scaling: 1.0", "GtkScrollbar");
+
+ stream << parse_rc_string("-xthickness: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_DefaultFrameWidth)), "*.GtkMenu");
+ stream << parse_rc_string("-ythickness: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_DefaultFrameWidth)), "*.GtkMenu");
+ stream << parse_rc_string("-xthickness: 5", "*.GtkMenu.Gtk*MenuItem");
+ stream << parse_rc_string("-xthickness: 3", "*.GtkNotebook");
+ stream << parse_rc_string("-ythickness: 3", "*.GtkNotebook");
+ stream << parse_rc_string("-ythickness: 1", "*.GtkButton");
+ stream << parse_rc_string("-color: " + colorString(TQColor(0,0,0)), "gtk-tooltips.GtkLabel", false);
+
+ stream << parse_rc_string("-xthickness: 1", "*.GtkButton.*");
+ stream << parse_rc_string("-ythickness: 1", "*.GtkButton.*");
+
+// stream << parse_rc_string("GtkTreeView::allow-rules = 0", "*");
+// stream << parse_rc_string("GtkTreeView::tree-line-width = 1", "*");
+// stream << parse_rc_string("GtkTreeView::vertical-separator = 30", "*");
+// //stream << parse_rc_string("GtkTreeView::odd-row-color = { 0.0, 0.0, 0.0 }", "*");
+
+ stream << parse_rc_string("-GtkButton-inner-border: 0 0 0 0", "*GtkToolbar*GtkButton*");
+ stream << parse_rc_string("-GtkButton-inner-border: 0 0 0 0", "*GtkToolbar*GtkToggleButton*");
+ stream << parse_rc_string("-GtkButton-inner-border: 0 0 0 0", "*GtkNotebook*GtkButton*");
+ stream << parse_rc_string("-GtkButton-inner-border: 0 0 0 0", "*GtkNotebook*GtkToggleButton*");
+
+ // TQt calls them tab boxes, GTK calls them notebooks (!??!?) Either way they are a pain...
+ //stream << parse_rc_string("-GtkNotebook-tab-overlap: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_TabBarTabOverlap)), "*");
+ stream << parse_rc_string("-GtkNotebook-tab-overlap: 0", "*"); // Overlap is handled in the style engine itself
+ stream << parse_rc_string("-GtkNotebook-tab-curvature: 0", "*");
+
+ // This sets both the radio button and check box sizes
+ stream << parse_rc_string("-GtkCheckButton-indicator-size: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_IndicatorHeight)), "*");
+
+ // FIXME
+ // GtkCellRendererToggle indicator-size must be set as follows, however GTK3 does not provide any means to change the default size!
+ // See upstream GTK bug #687076
+ //stream << parse_rc_string("-GtkCellRendererToggle-indicator-size: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_IndicatorHeight)), "*");
+
+ // FIXME
+ // There must be a way to set the selected tab offset (shift)
+ // If not, it may be neccessary to override the GTK text drawing routines for notebooks to insert the proper shift
+ //stream << parse_rc_string("-????: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_TabBarTabShiftHorizontal)), "*");
+
+ stream << parse_rc_string("-GtkButton-child-displacement-x: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ButtonShiftHorizontal)), "*");
+ stream << parse_rc_string("-GtkButton-child-displacement-y: " + TQString::number(tqApp->style().pixelMetric(TQStyle::PM_ButtonShiftVertical)), "*");
+
+ // Set up fonts
+ TQFont generalFont = KGlobalSettings::generalFont();
+ TQFont toolBarFont = KGlobalSettings::toolBarFont();
+ TQFont menuFont = KGlobalSettings::menuFont();
+ // TQFont windowTitleFont = KGlobalSettings::windowTitleFont();
+ // TQFont taskbarFont = KGlobalSettings::taskbarFont();
+
+ stream << parse_rc_string(tdeFontToGTKFontString(generalFont), "*");
+ stream << parse_rc_string(tdeFontToGTKFontString(toolBarFont), "*GtkToolbar*GtkButton*");
+ stream << parse_rc_string(tdeFontToGTKFontString(menuFont), "*.GtkMenu");
+
+ // Set up icons
+ // Build the list of icon theme directories.
+ // This function is recursive - it gets the directories of all the inherited themes as well
+ addIconThemeDir(iconTheme);
+
+ if (iconThemeDirs.isEmpty()) {
+ themeFile.close();
+ if (!forceRecreate) {
+ gtk3_tqt_reload_theme_definition_file(themeFilePath.latin1());
+ }
+ return;
+ }
+
+ GtkIconFactory* factory;
+ factory = gtk_icon_factory_new();
+
+ doIconMapping("gtk-about", "actions/about_kde.png", factory, iconThemeDirs);
+ doIconMapping("gtk-add", "actions/add.png", factory, iconThemeDirs);
+ doIconMapping("gtk-apply", "actions/apply.png", factory, iconThemeDirs);
+ doIconMapping("gtk-bold", "actions/text_bold.png", factory, iconThemeDirs);
+ doIconMapping("gtk-cancel", "actions/button_cancel.png", factory, iconThemeDirs);
+ doIconMapping("gtk-cdrom", "devices/cdrom_unmount.png", factory, iconThemeDirs);
+ doIconMapping("gtk-clear", "actions/editclear.png", factory, iconThemeDirs);
+ doIconMapping("gtk-close", "actions/fileclose.png", factory, iconThemeDirs);
+ doIconMapping("gtk-color-picker", "actions/colorpicker.png", factory, iconThemeDirs);
+ doIconMapping("gtk-copy", "actions/editcopy.png", factory, iconThemeDirs);
+ doIconMapping("gtk-convert", "actions/gtk-convert.png", factory, iconThemeDirs);
+ doIconMapping("gtk-connect", "actions/connect_creating.png", factory, iconThemeDirs);
+ doIconMapping("gtk-cut", "actions/editcut.png", factory, iconThemeDirs);
+ doIconMapping("gtk-delete", "actions/editdelete.png", factory, iconThemeDirs);
+ doIconMapping("gtk-dialog-authentication", "status/gtk-dialog-authentication", factory, iconThemeDirs);
+ doIconMapping("gtk-dialog-error", "actions/messagebox_critical.png", factory, iconThemeDirs);
+ doIconMapping("gtk-dialog-info", "actions/messagebox_info.png", factory, iconThemeDirs);
+ doIconMapping("gtk-dialog-question", "actions/help.png", factory, iconThemeDirs);
+ doIconMapping("gtk-dialog-warning", "actions/messagebox_warning.png", factory, iconThemeDirs);
+ doIconMapping("gtk-directory", "filesystems/folder.png", factory, iconThemeDirs);
+ doIconMapping("gtk-disconnect", "actions/connect_no.png", factory, iconThemeDirs);
+ doIconMapping("gtk-dnd", "mimetypes/empty.png", factory, iconThemeDirs);
+ doIconMapping("gtk-dnd-multiple", "mimetypes/kmultiple.png", factory, iconThemeDirs);
+ doIconMapping("gtk-edit", "actions/edit.png", factory, iconThemeDirs); //2.6
+ doIconMapping("gtk-execute", "actions/exec.png", factory, iconThemeDirs);
+ doIconMapping("gtk-file", "mimetypes/empty.png", factory, iconThemeDirs);
+ doIconMapping("gtk-find", "actions/find.png", factory, iconThemeDirs);
+ doIconMapping("gtk-find-and-replace", "actions/find.png", factory, iconThemeDirs); // Is there a TDE "find and replace" icon? FIXME
+ doIconMapping("gtk-floppy", "devices/3floppy_unmount.png", factory, iconThemeDirs);
+ doIconMapping("gtk-fullscreen", "actions/window-fullscreen.png", factory, iconThemeDirs);
+ doIconMapping("gtk-goto-bottom", "actions/bottom.png", factory, iconThemeDirs);
+ doIconMapping("gtk-goto-first", "actions/start.png", factory, iconThemeDirs);
+ doIconMapping("gtk-goto-last", "actions/finish.png", factory, iconThemeDirs);
+ doIconMapping("gtk-goto-top", "actions/top.png", factory, iconThemeDirs);
+ doIconMapping("gtk-go-back", "actions/back.png", factory, iconThemeDirs);
+ doIconMapping("gtk-go-down", "actions/down.png", factory, iconThemeDirs);
+ doIconMapping("gtk-go-forward", "actions/forward.png", factory, iconThemeDirs);
+ doIconMapping("gtk-go-up", "actions/up.png", factory, iconThemeDirs);
+ doIconMapping("gtk-harddisk", "devices/hdd_unmount.png", factory, iconThemeDirs);
+ doIconMapping("gtk-help", "apps/khelpcenter.png", factory, iconThemeDirs);
+ doIconMapping("gtk-home", "filesystems/folder_home.png", factory, iconThemeDirs);
+ doIconMapping("gtk-indent", "actions/indent.png", factory, iconThemeDirs);
+ doIconMapping("gtk-index", "actions/contents.png", factory, iconThemeDirs);
+ doIconMapping("gtk-info", "actions/messagebox_info.png", factory, iconThemeDirs);
+ doIconMapping("gtk-italic", "actions/text_italic.png", factory, iconThemeDirs);
+ doIconMapping("gtk-jump-to", "actions/goto.png", factory, iconThemeDirs);
+ doIconMapping("gtk-justify-center", "actions/text_center.png", factory, iconThemeDirs);
+ doIconMapping("gtk-justify-fill", "actions/text_block.png", factory, iconThemeDirs);
+ doIconMapping("gtk-justify-left", "actions/text_left.png", factory, iconThemeDirs);
+ doIconMapping("gtk-justify-right", "actions/text_right.png", factory, iconThemeDirs);
+ doIconMapping("gtk-leave-fullscreen", "actions/window-nofullscreen.png", factory, iconThemeDirs);
+ doIconMapping("gtk-media-forward", "player-fwd.png", factory, iconThemeDirs);
+ doIconMapping("gtk-media-next", "actions/player-end.png", factory, iconThemeDirs);
+ doIconMapping("gtk-media-pause", "actions/player-pause.png", factory, iconThemeDirs);
+ doIconMapping("gtk-media-previous", "actions/player-start.png", factory, iconThemeDirs);
+ doIconMapping("gtk-media-record", "actions/gtk-media-record.png", factory, iconThemeDirs); // FIXME
+ doIconMapping("gtk-media-rewind", "actions/player-rew.png", factory, iconThemeDirs);
+ doIconMapping("gtk-media-stop", "actions/player-stop.png", factory, iconThemeDirs);
+ doIconMapping("gtk-missing-image", "mimetypes/unknown.png", factory, iconThemeDirs);
+ doIconMapping("gtk-network", "filesystems/network.png", factory, iconThemeDirs);
+ doIconMapping("gtk-new", "actions/filenew.png", factory, iconThemeDirs);
+ doIconMapping("gtk-no", "actions/gtk-no.png", factory, iconThemeDirs);
+ doIconMapping("gtk-ok", "actions/button_ok.png", factory, iconThemeDirs);
+ doIconMapping("gtk-open", "actions/fileopen.png", factory, iconThemeDirs);
+ //doIconMapping("gtk-orientation-landscape", factory, iconThemeDirs); // FIXME
+ //doIconMapping("gtk-orientation-portrait", factory, iconThemeDirs); // FIXME
+ //doIconMapping("gtk-orientation-reverse-landscape", factory, iconThemeDirs); // FIXME
+ //doIconMapping("gtk-orientation-reverse-portrait"", factory, iconThemeDirs); // FIXME
+ doIconMapping("gtk-paste", "actions/editpaste.png", factory, iconThemeDirs);
+ doIconMapping("gtk-preferences", "actions/configure.png", factory, iconThemeDirs);
+ doIconMapping("gtk-print", "actions/fileprint.png", factory, iconThemeDirs);
+ doIconMapping("gtk-print-preview", "actions/filequickprint.png", factory, iconThemeDirs);
+ doIconMapping("gtk-properties", "actions/configure.png", factory, iconThemeDirs);
+ doIconMapping("gtk-quit", "actions/exit.png", factory, iconThemeDirs);
+ doIconMapping("gtk-redo", "actions/redo.png", factory, iconThemeDirs);
+ doIconMapping("gtk-refresh", "actions/reload.png", factory, iconThemeDirs);
+ doIconMapping("gtk-remove", "actions/remove.png", factory, iconThemeDirs);
+ doIconMapping("gtk-revert-to-saved", "actions/revert.png", factory, iconThemeDirs);
+ doIconMapping("gtk-save", "actions/filesave.png", factory, iconThemeDirs);
+ doIconMapping("gtk-save-as", "actions/filesaveas.png", factory, iconThemeDirs);
+ doIconMapping("gtk-select-all", "actions/gtk-select-all.png", factory, iconThemeDirs); // FIXME
+ doIconMapping("gtk-select-color", "actions/colorize.png", factory, iconThemeDirs);
+ doIconMapping("gtk-select-font", "mimetypes/font.png", factory, iconThemeDirs);
+ //doIconMapping("gtk-sort-ascending", "??", factory, iconThemeDirs); // FIXME
+ //doIconMapping("gtk-sort-descending", "??", factory, iconThemeDirs); // FIXME
+ doIconMapping("gtk-spell-check", "actions/spellcheck.png", factory, iconThemeDirs);
+ doIconMapping("gtk-stop", "actions/stop.png", factory, iconThemeDirs);
+ doIconMapping("gtk-strikethrough", "actions/text_strike.png", factory, iconThemeDirs);
+ doIconMapping("gtk-undelete", "actions/gtk-undelete.png", factory, iconThemeDirs); // FIXME
+ doIconMapping("gtk-underline", "actions/text_under.png", factory, iconThemeDirs);
+ doIconMapping("gtk-undo", "actions/undo.png", factory, iconThemeDirs);
+ doIconMapping("gtk-unindent", "actions/unindent.png", factory, iconThemeDirs);
+ doIconMapping("gtk-yes", "actions/button_ok.png", factory, iconThemeDirs); // Verify mapping here
+ doIconMapping("gtk-zoom-100", "actions/viewmag1.png", factory, iconThemeDirs);
+ doIconMapping("gtk-zoom-fit", "actions/viewmagfit.png", factory, iconThemeDirs);
+ doIconMapping("gtk-zoom-in", "actions/viewmag+.png", factory, iconThemeDirs);
+ doIconMapping("gtk-zoom-out", "actions/viewmag-.png", factory, iconThemeDirs);
+
+ // Other icons that really should have Trinity equivalents in tdelibs
+ doIconMapping("list-add", "actions/add.png", factory, iconThemeDirs);
+ doIconMapping("list-remove", "actions/remove.png", factory, iconThemeDirs);
+
+ gtk_icon_factory_add_default(factory);
+
+ themeFile.close();
+
+ if (!forceRecreate) {
+ gtk3_tqt_reload_theme_definition_file(themeFilePath.latin1());
+ }
+}
+// ========================================================================================================= \ No newline at end of file
diff --git a/tdegtk/tdegtk-types.h b/tdegtk/tdegtk-types.h
index ba280d2..ad94d5f 100644
--- a/tdegtk/tdegtk-types.h
+++ b/tdegtk/tdegtk-types.h
@@ -1,5 +1,5 @@
/* The TdeGtk Theming Engine for Gtk+.
- * Copyright (C) 2011 Canonical Ltd
+ * Copyright (C) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,7 +16,8 @@
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
- * Authored by Andrea Cimitan <andrea.cimitan@canonical.com>
+ * Portions of this file written by
+ * Andrea Cimitan <andrea.cimitan@canonical.com>
*
*/
@@ -61,6 +62,26 @@ typedef enum
TDEGTK_NUM_STYLES = 1
} TdeGtkStyles;
+enum TQt3WidgetType {
+ TQT3WT_NONE,
+ TQT3WT_TQProgressBar,
+ TQT3WT_TQTabBar,
+ TQT3WT_TQRadioButton,
+ TQT3WT_TQCheckBox,
+ TQT3WT_TQPushButton,
+ TQT3WT_TQPopupMenu,
+ TQT3WT_TQComboBox,
+ TQT3WT_TQSlider,
+ TQT3WT_TQScrollBar,
+ TQT3WT_TQSpinBox,
+ TQT3WT_TQSpinWidget,
+ TQT3WT_TQTitleBar,
+ TQT3WT_TQMenuBar,
+ TQT3WT_TQToolBox,
+ TQT3WT_TQToolButton,
+ TQT3WT_GTKTreeViewCell,
+};
+
typedef struct _TdeGtkStyleFunctions TdeGtkStyleFunctions;
struct _TdeGtkStyleFunctions
diff --git a/tdegtk/tdegtk-utils.cpp b/tdegtk/tdegtk-utils.cpp
new file mode 100644
index 0000000..ad93793
--- /dev/null
+++ b/tdegtk/tdegtk-utils.cpp
@@ -0,0 +1,1064 @@
+/*
+* this file was largely taken from the oxygen gtk engine
+* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
+* Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com>
+*
+* GdkPixbuf modification code from Walmis
+* <http://gnome-look.org/content/show.php?content=77783&forumpage=3>
+*
+* 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 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 St, Fifth Floor, Boston,
+* MA 02110-1301, USA.
+*/
+
+#include "tdegtk-utils.h"
+//#include "oxygengtktypenames.h"
+#include "config.h"
+
+#include <cmath>
+#include <cstring>
+#include <gtk/gtk.h>
+#include <iostream>
+#include <set>
+
+ //_____________________________________________________________________________
+ std::ostream& operator << ( std::ostream& out, const GtkWidgetPath* path )
+ {
+ if( !path )
+ {
+
+ out << " (null)";
+
+ } else {
+
+ for( gint pos=0; pos<gtk_widget_path_length( path ); ++pos )
+ {
+ const char* name( g_type_name( gtk_widget_path_iter_get_object_type( path, pos ) ) );
+ if(!name) break;
+ out << "/" << name;
+ }
+
+ }
+
+ return out;
+
+ }
+
+
+
+ //____________________________________________________________
+ void Gtk::gtk_container_adjust_buttons_state(GtkContainer* container,gpointer data)
+ {
+ if(GTK_IS_BUTTON(container))
+ {
+
+ int x(0),y(0);
+ GtkWidget* button=GTK_WIDGET(container);
+ GtkAllocation allocation( gtk_widget_get_allocation( button ) );
+
+ GdkDeviceManager* manager( gdk_display_get_device_manager( gtk_widget_get_display( button ) ) );
+ GdkDevice* pointer( gdk_device_manager_get_client_pointer( manager ) );
+ gdk_window_get_device_position( gtk_widget_get_window( button ), pointer, &x, &y, 0L);
+
+ if( !(x>0 && y>0 &&
+ x < allocation.width &&
+ y < allocation.height) && gtk_widget_get_state(button)==GTK_STATE_ACTIVE )
+ { gtk_widget_set_state(button,GTK_STATE_NORMAL); }
+
+ gtk_button_set_relief(GTK_BUTTON(button),GTK_RELIEF_NORMAL);
+ gtk_widget_set_size_request(button,16,16);
+
+ return;
+
+ }
+
+ if(GTK_IS_CONTAINER(container))
+ { gtk_container_foreach(container,(GtkCallback)gtk_container_adjust_buttons_state,0L); }
+
+ }
+
+ //____________________________________________________________
+ bool Gtk::gtk_widget_path_has_type( const GtkWidgetPath* path, GType type )
+ {
+
+ if( !path ) return false;
+ for( gint pos=0; pos<gtk_widget_path_length( path ); ++pos )
+ {
+ const GType local( gtk_widget_path_iter_get_object_type( path, pos ) );
+ if( local == type || g_type_is_a( local, type ) )
+ { return true; }
+ }
+
+ return false;
+
+ }
+
+ //____________________________________________________________
+ bool Gtk::gtk_widget_is_applet( GtkWidget* widget )
+ {
+ if( !widget ) return false;
+
+ #if OXYGEN_DEBUG
+ std::cerr << "Gtk::gtk_widget_is_applet(): " << Gtk::gtk_widget_path(widget) << std::endl;
+ #endif
+
+ static const char* names[] =
+ {
+ "Panel",
+ "PanelWidget",
+ "PanelApplet",
+ "XfcePanelWindow",
+ 0
+ };
+
+ // check widget name
+ std::string name( G_OBJECT_TYPE_NAME( widget ) );
+ for( unsigned int i = 0; names[i]; ++i )
+ { if( g_object_is_a( G_OBJECT( widget ), names[i] ) || name.find( names[i] ) == 0 ) return true; }
+
+ // also check parent
+ if( GtkWidget* parent = gtk_widget_get_parent( widget ) )
+ {
+ name = G_OBJECT_TYPE_NAME( parent );
+ for( unsigned int i = 0; names[i]; ++i )
+ { if( g_object_is_a( G_OBJECT( parent ), names[i] ) || name.find( names[i] ) == 0 ) return true; }
+
+ }
+
+ // also check first widget path element (needed for xfce panel)
+ std::string widgetPath=Gtk::gtk_widget_path(widget);
+ {
+ for( unsigned int i = 0; names[i]; ++i )
+ {
+ if( widgetPath.find(names[i]) != std::string::npos )
+ return true;
+ }
+ }
+
+ return false;
+
+ }
+
+ //____________________________________________________________
+ void Gtk::gtk_widget_print_tree( GtkWidget* widget )
+ {
+
+ if( !widget ) return;
+ std::cerr << "Oxygen::Gtk::gtk_widget_print_tree - widget: " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
+ while( ( widget = gtk_widget_get_parent( widget ) ) )
+ { std::cerr << " parent: " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl; }
+
+ }
+
+ //________________________________________________________
+ bool Gtk::gdk_default_screen_is_composited( void )
+ {
+ GdkScreen* screen( gdk_screen_get_default() );
+ return (screen && gdk_screen_is_composited( screen ) );
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_widget_has_rgba( GtkWidget* widget )
+ {
+
+ if( !widget ) return false;
+ if( !gdk_default_screen_is_composited() ) return false;
+ return gdk_visual_has_rgba( gtk_widget_get_visual (widget) );
+
+ }
+
+ //________________________________________________________
+ bool Gtk::gdk_window_is_base( GdkWindow* window )
+ {
+
+ if( !GDK_IS_WINDOW( window ) ) return false;
+
+ GdkWindowTypeHint hint = gdk_window_get_type_hint( window );
+
+ #if OXYGEN_DEBUG
+ std::cerr << "Gtk::gdk_window_is_base - " << TypeNames::windowTypeHint( hint ) << std::endl;
+ #endif
+
+ return(
+ hint == GDK_WINDOW_TYPE_HINT_NORMAL ||
+ hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
+ hint == GDK_WINDOW_TYPE_HINT_UTILITY );
+ }
+
+ //________________________________________________________
+ bool Gtk::gdk_window_nobackground( GdkWindow* window )
+ {
+ if( !GDK_IS_WINDOW( window ) ) return false;
+
+ GdkWindowTypeHint hint = gdk_window_get_type_hint( window );
+ return( hint == GDK_WINDOW_TYPE_HINT_COMBO || hint == GDK_WINDOW_TYPE_HINT_TOOLTIP );
+
+ }
+
+ //________________________________________________________
+ bool Gtk::gdk_window_has_rgba( GdkWindow* window )
+ {
+
+ if( !window ) return false;
+
+ if( !gdk_default_screen_is_composited() ) return false;
+ return gdk_visual_has_rgba( gdk_window_get_visual( window ) );
+
+ }
+
+ //________________________________________________________
+ bool Gtk::gdk_visual_has_rgba( GdkVisual* visual )
+ {
+ // check depth
+ if( gdk_visual_get_depth( visual ) != 32 ) return false;
+
+ // check red pixel
+ guint32 redMask;
+ gdk_visual_get_red_pixel_details( visual, &redMask, 0L, 0L );
+ if( redMask != 0xff0000 ) return false;
+
+ // check green pixel
+ guint32 greenMask;
+ gdk_visual_get_green_pixel_details( visual, &greenMask, 0L, 0L );
+ if( greenMask != 0x00ff00 ) return false;
+
+ // check blue pixel
+ guint32 blueMask;
+ gdk_visual_get_blue_pixel_details( visual, &blueMask, 0L, 0L );
+ if( blueMask != 0x0000ff ) return false;
+
+ return true;
+
+ }
+
+ //________________________________________________________
+ bool Gtk::g_object_is_a( const GObject* object, const std::string& typeName )
+ {
+
+ if( object )
+ {
+ const GType tmp( g_type_from_name( typeName.c_str() ) );
+ if( tmp )
+ { return g_type_check_instance_is_a( (GTypeInstance*) object, tmp ); }
+ }
+
+ return false;
+ }
+
+ //________________________________________________________
+ std::string Gtk::gtk_widget_path( GtkWidget* widget )
+ {
+
+ if(GTK_IS_WIDGET(widget))
+ {
+ gchar* widgetPath;
+ gtk_widget_path( widget, 0L, &widgetPath, 0L);
+ const std::string out( widgetPath );
+ g_free( widgetPath );
+ return out;
+ }
+ return std::string("not-widget");
+
+ }
+
+ //________________________________________________________
+ GtkWidget* Gtk::gtk_widget_find_parent( GtkWidget* widget, GType type )
+ {
+
+ for( GtkWidget* parent = widget; parent; parent = gtk_widget_get_parent( parent ) )
+ { if( G_TYPE_CHECK_INSTANCE_TYPE( parent, type ) ) return parent; }
+
+ return 0L;
+ }
+
+ //________________________________________________________
+ GtkWidget* Gtk::gtk_parent_groupbox( GtkWidget* widget )
+ {
+
+ for( GtkWidget* parent = widget; parent; parent = gtk_widget_get_parent( parent ) )
+ { if( gtk_widget_is_groupbox( parent ) ) return parent; }
+
+ return 0L;
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_widget_is_parent( GtkWidget* widget, GtkWidget* potentialParent )
+ {
+
+ for( GtkWidget* parent = gtk_widget_get_parent( widget ); parent; parent = gtk_widget_get_parent( parent ) )
+ { if( potentialParent==parent ) return true; }
+
+ return false;
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_parent_is_shadow_in( GtkWidget* widget )
+ {
+ for( GtkWidget* parent = gtk_widget_get_parent( widget ); parent; parent = gtk_widget_get_parent( parent ) )
+ {
+ if( GTK_IS_FRAME( parent ) && gtk_frame_get_shadow_type( GTK_FRAME( parent ) ) == GTK_SHADOW_IN ) return true;
+ if( GTK_IS_SCROLLED_WINDOW( parent ) && gtk_scrolled_window_get_shadow_type( GTK_SCROLLED_WINDOW( parent ) ) == GTK_SHADOW_IN ) return true;
+ }
+
+ return false;
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_button_is_flat( GtkWidget* widget )
+ {
+ if( !GTK_IS_BUTTON( widget ) ) return false;
+ return ( gtk_button_get_relief( GTK_BUTTON( widget ) ) == GTK_RELIEF_NONE );
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_button_is_header( GtkWidget* widget )
+ { return GTK_IS_BUTTON( widget ) && gtk_parent_tree_view( widget ); }
+
+ //________________________________________________________
+ bool Gtk::gtk_button_is_in_path_bar( GtkWidget* widget )
+ {
+ if( !( GTK_IS_BUTTON( widget ) && gtk_widget_get_parent( widget ) ) ) return false;
+
+ std::string name(G_OBJECT_TYPE_NAME( gtk_widget_get_parent( widget ) ) );
+ return name == "GtkPathBar" || name == "NautilusPathBar";
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_path_bar_button_is_last( GtkWidget* widget )
+ {
+
+ GtkWidget* parent( gtk_widget_get_parent( widget ) );
+
+ // get parent and check type
+ if( !( parent && GTK_IS_CONTAINER( parent ) ) ) return false;
+
+ // get children
+ GList* children( gtk_container_get_children( GTK_CONTAINER( parent ) ) );
+
+ /*
+ for some reason, pathbar buttons are ordered in the container in reverse order.
+ meaning that the last button (in the pathbar) is stored first in the list.
+ */
+ bool result = (widget == g_list_first( children )->data );
+ if( children ) g_list_free( children );
+ return result;
+
+ }
+
+ //________________________________________________________
+ GtkWidget* Gtk::gtk_button_find_image(GtkWidget* button)
+ {
+
+ // check widget type
+ if(!GTK_IS_CONTAINER(button)) return 0L;
+
+ GtkWidget* result( 0L );
+ GList* children( gtk_container_get_children( GTK_CONTAINER( button ) ) );
+ for( GList *child = g_list_first( children ); child; child = g_list_next( child ) )
+ {
+ if( GTK_IS_IMAGE( child->data ) )
+ {
+ result = GTK_WIDGET( child->data );
+ break;
+
+ } else if( GTK_IS_CONTAINER( child->data ) ) {
+
+ result = gtk_button_find_image( GTK_WIDGET(child->data ) );
+ break;
+
+ }
+
+ }
+
+ if( children ) g_list_free( children );
+ return result;
+
+ }
+
+ //________________________________________________________
+ GtkWidget* Gtk::gtk_button_find_label(GtkWidget* button)
+ {
+
+ // check widget type
+ if( !GTK_IS_CONTAINER(button) ) return 0L;
+
+ GtkWidget* result( 0L );
+ GList* children( gtk_container_get_children( GTK_CONTAINER( button ) ) );
+ for( GList *child = g_list_first( children ); child; child = g_list_next( child ) )
+ {
+
+ if( GTK_IS_LABEL( child->data) )
+ {
+ result = GTK_WIDGET( child->data );
+ break;
+
+ } else if( GTK_IS_CONTAINER( child->data ) ) {
+
+ result = gtk_button_find_image(GTK_WIDGET(child->data));
+ break;
+
+ }
+
+ }
+
+ if( children ) g_list_free( children );
+ return result;
+
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_combobox_has_frame( GtkWidget* widget )
+ {
+
+ GValue val = { 0, };
+ g_value_init(&val, G_TYPE_BOOLEAN);
+ g_object_get_property( G_OBJECT( widget ), "has-frame", &val );
+ return (bool) g_value_get_boolean( &val );
+
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_combobox_is_tree_view( GtkWidget* widget )
+ {
+ // check types and path
+ if( !widget && GTK_IS_TREE_VIEW( widget ) && GTK_IS_SCROLLED_WINDOW( gtk_widget_get_parent( widget ) ) ) return false;
+ return Gtk::gtk_widget_path( widget ) == "gtk-combobox-popup-window.GtkScrolledWindow.GtkTreeView";
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_combobox_is_scrolled_window( GtkWidget* widget )
+ {
+ // check types and path
+ if( !GTK_IS_SCROLLED_WINDOW(widget) ) return false;
+ return Gtk::gtk_widget_path( widget ) == "gtk-combobox-popup-window.GtkScrolledWindow";
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_combobox_is_viewport( GtkWidget* widget )
+ {
+ if( !GTK_IS_VIEWPORT(widget) ) return false;
+ static const std::string match( "gtk-combo-popup-window" );
+ return Gtk::gtk_widget_path( widget ).substr( 0, match.size() ) == match;
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_combobox_is_frame( GtkWidget* widget )
+ {
+ if( !GTK_IS_FRAME(widget) ) return false;
+ static const std::string match( "gtk-combo-popup-window" );
+ return Gtk::gtk_widget_path( widget ).substr( 0, match.size() ) == match;
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_combobox_appears_as_list( GtkWidget* widget )
+ {
+ gboolean appearsAsList;
+ gtk_widget_style_get( widget, "appears-as-list", &appearsAsList, NULL );
+ return (bool) appearsAsList;
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_notebook_tab_contains( GtkWidget* widget, int tab, int x, int y )
+ {
+
+ if( !( tab >= 0 && GTK_IS_NOTEBOOK( widget ) ) ) return false;
+
+ // cast to notebook and check against number of pages
+ GtkNotebook* notebook( GTK_NOTEBOOK( widget ) );
+ if( tab >= gtk_notebook_get_n_pages( notebook ) ) return false;
+
+ // retrieve page and tab label
+ GtkWidget* page( gtk_notebook_get_nth_page( notebook, tab ) );
+ GtkWidget* tabLabel( gtk_notebook_get_tab_label( notebook, page ) );
+
+ // get allocted size and compare to position
+ const GtkAllocation allocation( gtk_widget_get_allocation( tabLabel ) );
+ return Gtk::gdk_rectangle_contains( &allocation, x, y );
+
+ }
+
+ //________________________________________________________
+ int Gtk::gtk_notebook_find_tab( GtkWidget* widget, int x, int y )
+ {
+
+ if( !GTK_IS_NOTEBOOK( widget ) ) return -1;
+
+ // cast to notebook and check against number of pages
+ GtkNotebook* notebook( GTK_NOTEBOOK( widget ) );
+ int tab(-1);
+ int minDistance( -1 );
+ for( int i = gtk_notebook_find_first_tab( widget ); i < gtk_notebook_get_n_pages( notebook ); ++i )
+ {
+
+ // retrieve page and tab label
+ GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) );
+ if( !page ) continue;
+
+ // get label
+ GtkWidget* tabLabel( gtk_notebook_get_tab_label( notebook, page ) );
+ if(!tabLabel) continue;
+
+ // get allocted size and compare to position
+ const GtkAllocation allocation( gtk_widget_get_allocation( tabLabel ) );
+
+ // get manhattan length
+ const int distance = int(
+ std::abs( double( allocation.x + allocation.width/2 - x ) ) +
+ std::abs( double( allocation.y + allocation.height/2 - y ) ) );
+ if( minDistance < 0 || distance < minDistance )
+ {
+ tab = i;
+ minDistance = distance;
+ }
+ }
+
+ return tab;
+
+ }
+
+ //________________________________________________________
+ int Gtk::gtk_notebook_find_first_tab( GtkWidget* widget )
+ {
+
+ // TODO: reimplement with gtk+3.0
+ return 0;
+
+// if( !GTK_IS_NOTEBOOK( widget ) ) return 0;
+//
+// // cast to notebook
+// GtkNotebook* notebook( GTK_NOTEBOOK( widget ) );
+// return g_list_position( notebook->children, notebook->first_tab );
+
+ }
+
+ //____________________________________________________________
+ bool Gtk::gtk_notebook_is_tab_label(GtkNotebook* notebook, GtkWidget* widget )
+ {
+
+ for( int i = 0; i < gtk_notebook_get_n_pages( notebook ); ++i )
+ {
+ // retrieve page and tab label
+ GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) );
+ if( !page ) continue;
+
+ GtkWidget* tabLabel( gtk_notebook_get_tab_label( notebook, page ) );
+ if( widget == tabLabel ) return true;
+ }
+
+ return false;
+
+ }
+
+
+ //____________________________________________________________
+ void Gtk::gtk_notebook_get_tabbar_rect( GtkNotebook* notebook, GdkRectangle* rect )
+ {
+ // check notebook and rect
+ if( !( notebook && rect ) ) return;
+
+ // check tab visibility
+ GList* children( gtk_container_get_children( GTK_CONTAINER( notebook ) ) );
+ if( !( gtk_notebook_get_show_tabs( notebook ) && children ) )
+ {
+ if( children ) g_list_free( children );
+ *rect = gdk_rectangle();
+ return;
+ }
+
+ // free children
+ if( children ) g_list_free( children );
+
+ // get full rect
+ gtk_widget_get_allocation( GTK_WIDGET( notebook ), rect );
+
+ // adjust to account for borderwidth
+ guint borderWidth( gtk_container_get_border_width( GTK_CONTAINER( notebook ) ) );
+ rect->x += borderWidth;
+ rect->y += borderWidth;
+ rect->height -= 2*borderWidth;
+ rect->width -= 2*borderWidth;
+
+ // get current page
+ int pageIndex( gtk_notebook_get_current_page( notebook ) );
+ if( !( pageIndex >= 0 && pageIndex < gtk_notebook_get_n_pages( notebook ) ) )
+ {
+ *rect = gdk_rectangle();
+ return;
+ }
+
+ GtkWidget* page( gtk_notebook_get_nth_page( notebook, pageIndex ) );
+ if( !page )
+ {
+ *rect = gdk_rectangle();
+ return;
+ }
+
+ // removes page allocated size from rect, based on tabwidget orientation
+ const GtkAllocation pageAllocation( gtk_widget_get_allocation( page ) );
+ switch( gtk_notebook_get_tab_pos( notebook ) )
+ {
+ case GTK_POS_BOTTOM:
+ rect->y += pageAllocation.height;
+ rect->height -= pageAllocation.height;
+ break;
+
+ case GTK_POS_TOP:
+ rect->height -= pageAllocation.height;
+ break;
+
+ case GTK_POS_RIGHT:
+ rect->x += pageAllocation.width;
+ rect->width -= pageAllocation.width;
+ break;
+
+ case GTK_POS_LEFT:
+ rect->width -= pageAllocation.width;
+ break;
+ }
+
+ return;
+
+ }
+
+ //____________________________________________________________
+ bool Gtk::gtk_notebook_has_visible_arrows( GtkNotebook* notebook )
+ {
+
+ if( !gtk_notebook_get_show_tabs( notebook ) ) return false;
+
+ // loop over pages
+ for( int i = 0; i < gtk_notebook_get_n_pages( notebook ); ++i )
+ {
+
+ // retrieve page and tab label
+ GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) );
+ if( !page ) continue;
+
+ GtkWidget* label( gtk_notebook_get_tab_label( notebook, page ) );
+ if( label && !gtk_widget_get_mapped( label ) ) return true;
+ }
+
+ return false;
+
+ }
+
+ //____________________________________________________________
+ bool Gtk::gtk_notebook_update_close_buttons(GtkNotebook* notebook)
+ {
+ int numPages=gtk_notebook_get_n_pages( notebook );
+ for( int i = 0; i < numPages; ++i )
+ {
+
+ // retrieve page
+ GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) );
+ if( !page ) continue;
+
+ // retrieve tab label
+ GtkWidget* tabLabel( gtk_notebook_get_tab_label( notebook, page ) );
+ if( tabLabel && GTK_IS_CONTAINER( tabLabel ) )
+ { gtk_container_adjust_buttons_state( GTK_CONTAINER( tabLabel ) ); }
+
+ }
+ return FALSE;
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_notebook_is_close_button(GtkWidget* widget)
+ {
+ if( GtkNotebook* nb=GTK_NOTEBOOK(gtk_parent_notebook(widget) ) )
+ {
+ // check if the button resides on tab label, not anywhere on the tab
+ bool tabLabelIsParent=false;
+ for( int i=0; i < gtk_notebook_get_n_pages(nb); ++i )
+ {
+ GtkWidget* tabLabel( gtk_notebook_get_tab_label(nb,gtk_notebook_get_nth_page( nb, i ) ) );
+ if( gtk_widget_is_parent( widget, GTK_WIDGET(tabLabel) ) )
+ { tabLabelIsParent=true; }
+ }
+
+ if( !tabLabelIsParent ) return false;
+
+ // make sure button has no text and some image (for now, just hope it's a close icon)
+ if( gtk_button_find_image(widget) && !gtk_button_get_label( GTK_BUTTON(widget) ) )
+ { return true; }
+
+ // check for pidgin 'x' close button
+ if( GtkWidget* label = gtk_button_find_label(widget) )
+ {
+
+ const gchar* labelText=gtk_label_get_text( GTK_LABEL(label) );
+ if(!strcmp(labelText,"×")) // It's not letter 'x' - it's a special symbol
+ {
+ gtk_widget_hide( label );
+ return true;
+ } else return false;
+
+ } else return false;
+
+ } else return false;
+
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_scrolled_window_force_sunken( GtkWidget* widget)
+ {
+
+ // FMIconView (from nautilus) always get sunken
+ if( g_object_is_a( G_OBJECT( widget ), "FMIconView" ) ) return true;
+
+ // other checks require widget to be of type GtkBin
+ if( !GTK_IS_BIN( widget ) ) return false;
+
+ // retrieve child
+ GtkWidget* child( gtk_bin_get_child( GTK_BIN( widget ) ) );
+ if( GTK_IS_TREE_VIEW( child ) || GTK_IS_ICON_VIEW( child ) ) return true;
+ else return false;
+
+ }
+
+ //________________________________________________________
+ bool Gtk::gdk_window_map_to_toplevel( GdkWindow* window, gint* x, gint* y, gint* w, gint* h, bool frame )
+ {
+
+ // always initialize arguments (to invalid values)
+ if( x ) *x=0;
+ if( y ) *y=0;
+ if( w ) *w = -1;
+ if( h ) *h = -1;
+
+ if( !( window && GDK_IS_WINDOW( window ) ) ) return false;
+ if( gdk_window_get_window_type( window ) == GDK_WINDOW_OFFSCREEN ) return false;
+
+ // get window size and height
+ if( frame ) gdk_toplevel_get_frame_size( window, w, h );
+ else gdk_toplevel_get_size( window, w, h );
+ Gtk::gdk_window_get_toplevel_origin( window, x, y );
+ return ((!w) || *w > 0) && ((!h) || *h>0);
+
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_widget_map_to_toplevel( GtkWidget* widget, gint* x, gint* y, gint* w, gint* h, bool frame )
+ {
+
+ // always initialize arguments (to invalid values)
+ if( x ) *x=0;
+ if( y ) *y=0;
+ if( w ) *w = -1;
+ if( h ) *h = -1;
+
+ if( !widget ) return false;
+
+ // get window
+ GdkWindow* window( gtk_widget_get_parent_window( widget ) );
+ if( !( window && GDK_IS_WINDOW( window ) ) ) return false;
+ if( gdk_window_get_window_type( window ) == GDK_WINDOW_OFFSCREEN ) return false;
+
+ if( frame ) gdk_toplevel_get_frame_size( window, w, h );
+ else gdk_toplevel_get_size( window, w, h );
+ int xlocal, ylocal;
+ const bool success( gtk_widget_translate_coordinates( widget, gtk_widget_get_toplevel( widget ), 0, 0, &xlocal, &ylocal ) );
+ if( success )
+ {
+
+ if( x ) *x=xlocal;
+ if( y ) *y=ylocal;
+
+ }
+
+ return success && ((!w) || *w > 0) && ((!h) || *h>0);
+
+ }
+
+ //________________________________________________________
+ bool Gtk::gtk_widget_map_to_parent( GtkWidget* widget, GtkWidget* parent, gint* x, gint* y, gint* w, gint* h )
+ {
+
+ // always initialize arguments (to invalid values)
+ if( x ) *x=0;
+ if( y ) *y=0;
+ if( w ) *w = -1;
+ if( h ) *h = -1;
+
+ if( !( widget && parent ) ) return false;
+
+ const GtkAllocation allocation( gtk_widget_get_allocation( parent ) );
+ if( w ) *w = allocation.width;
+ if( h ) *h = allocation.height;
+
+ int xlocal, ylocal;
+ const bool success( gtk_widget_translate_coordinates( widget, parent, 0, 0, &xlocal, &ylocal ) );
+ if( success )
+ {
+
+ if( x ) *x=xlocal;
+ if( y ) *y=ylocal;
+
+ }
+
+ return success && ((!w) || *w > 0) && ((!h) || *h>0);
+
+ }
+
+ //________________________________________________________
+ bool Gtk::gdk_window_translate_origin( GdkWindow* parent, GdkWindow* child, gint* x, gint* y )
+ {
+ if( x ) *x = 0;
+ if( y ) *y = 0;
+ if( !( parent && child ) ) return false;
+ while( child && GDK_IS_WINDOW( child ) &&
+ child != parent &&
+ gdk_window_get_window_type( child ) == GDK_WINDOW_CHILD )
+ {
+ gint xloc;
+ gint yloc;
+ gdk_window_get_position( child, &xloc, &yloc );
+ if( x ) *x += xloc;
+ if( y ) *y += yloc;
+ child = gdk_window_get_parent( child );
+ }
+
+ return( child == parent );
+
+ }
+
+ //________________________________________________________
+ void Gtk::gdk_toplevel_get_size( GdkWindow* window, gint* w, gint* h )
+ {
+
+ if( !( window && GDK_IS_WINDOW( window ) ) )
+ {
+ if( w ) *w = -1;
+ if( h ) *h = -1;
+ return;
+ }
+
+ if( GdkWindow* topLevel = gdk_window_get_toplevel( window ) )
+ {
+
+ if( w ) *w = gdk_window_get_width( topLevel );
+ if( h ) *h = gdk_window_get_height( topLevel );
+
+ } else {
+
+ if( w ) *w = gdk_window_get_width( window );
+ if( h ) *h = gdk_window_get_height( window );
+
+ }
+
+ return;
+
+ }
+
+ //________________________________________________________
+ void Gtk::gdk_toplevel_get_frame_size( GdkWindow* window, gint* w, gint* h )
+ {
+
+ if( !( window && GDK_IS_WINDOW( window ) ) )
+ {
+ if( w ) *w = -1;
+ if( h ) *h = -1;
+ return;
+ }
+
+ GdkWindow* topLevel = gdk_window_get_toplevel( window );
+ if( topLevel && GDK_IS_WINDOW( topLevel ) )
+ {
+ if( gdk_window_get_window_type( topLevel ) == GDK_WINDOW_OFFSCREEN )
+ {
+
+ if( w ) *w = gdk_window_get_width(topLevel);
+ if( h ) *h = gdk_window_get_height(topLevel);
+
+ } else {
+
+ GdkRectangle rect = {0, 0, -1, -1};
+ gdk_window_get_frame_extents( topLevel, &rect );
+
+ if( w ) *w = rect.width;
+ if( h ) *h = rect.height;
+
+ }
+ }
+
+ return;
+
+ }
+
+ //________________________________________________________
+ void Gtk::gdk_window_get_toplevel_origin( GdkWindow* window, gint* x, gint* y )
+ {
+ if( x ) *x = 0;
+ if( y ) *y = 0;
+ if( !window ) return;
+ while( window && GDK_IS_WINDOW( window ) && gdk_window_get_window_type( window ) == GDK_WINDOW_CHILD )
+ {
+ gint xloc;
+ gint yloc;
+ gdk_window_get_position( window, &xloc, &yloc );
+ if( x ) *x += xloc;
+ if( y ) *y += yloc;
+ window = gdk_window_get_parent( window );
+ }
+
+ return;
+ }
+
+ //___________________________________________________________
+ GdkPixbuf* Gtk::gdk_pixbuf_set_alpha( const GdkPixbuf *pixbuf, double alpha )
+ {
+
+ g_return_val_if_fail( pixbuf != 0L, 0L);
+ g_return_val_if_fail( GDK_IS_PIXBUF( pixbuf ), 0L );
+
+ /* Returns a copy of pixbuf with it's non-completely-transparent pixels to
+ have an alpha level "alpha" of their original value. */
+ GdkPixbuf* target( gdk_pixbuf_add_alpha( pixbuf, false, 0, 0, 0 ) );
+ if( alpha >= 1.0 ) return target;
+ if( alpha < 0 ) alpha = 0;
+
+ const int width( gdk_pixbuf_get_width( target ) );
+ const int height( gdk_pixbuf_get_height( target ) );
+ const int rowstride( gdk_pixbuf_get_rowstride( target ) );
+ unsigned char* data = gdk_pixbuf_get_pixels( target );
+
+ for( int y = 0; y < height; ++y )
+ {
+
+ for( int x = 0; x < width; ++x )
+ {
+ /* The "4" is the number of chars per pixel, in this case, RGBA,
+ the 3 means "skip to the alpha" */
+ unsigned char* current = data + ( y*rowstride ) + ( x*4 ) + 3;
+ *(current) = (unsigned char) ( *( current )*alpha );
+ }
+ }
+
+ return target;
+ }
+
+ //_________________________________________________________
+ bool Gtk::gdk_pixbuf_to_gamma(GdkPixbuf* pixbuf, double value)
+ {
+ if(gdk_pixbuf_get_colorspace(pixbuf)==GDK_COLORSPACE_RGB &&
+ gdk_pixbuf_get_bits_per_sample(pixbuf)==8 &&
+ gdk_pixbuf_get_has_alpha(pixbuf) &&
+ gdk_pixbuf_get_n_channels(pixbuf)==4)
+ {
+ double gamma=1./(2.*value+0.5);
+ unsigned char* data=gdk_pixbuf_get_pixels(pixbuf);
+ const int height=gdk_pixbuf_get_height(pixbuf);
+ const int width=gdk_pixbuf_get_width(pixbuf);
+ const int rowstride=gdk_pixbuf_get_rowstride(pixbuf);
+ for(int x=0;x<width;++x)
+ {
+ for(int y=0; y<height; y++)
+ {
+ unsigned char* p=data + y*rowstride + x*4;
+ *p=(char)(pow((*p/255.),gamma)*255); ++p;
+ *p=(char)(pow((*p/255.),gamma)*255); ++p;
+ *p=(char)(pow((*p/255.),gamma)*255);
+ }
+
+ }
+
+ return true;
+
+ } else return false;
+
+ }
+
+ //___________________________________________________________
+ GdkPixbuf* Gtk::gdk_pixbuf_resize( GdkPixbuf* src, int width, int height )
+ {
+ if( width == gdk_pixbuf_get_width( src ) && height == gdk_pixbuf_get_height( src ) )
+ {
+
+ return static_cast<GdkPixbuf*>(g_object_ref (src));
+
+ } else {
+
+ return gdk_pixbuf_scale_simple( src, width, height, GDK_INTERP_BILINEAR );
+
+ }
+
+ }
+
+ //___________________________________________________________
+ void Gtk::gtk_viewport_get_position( GtkViewport* viewport, gint* x, gint* y )
+ {
+
+ // initialize
+ if( x ) *x = 0;
+ if( y ) *y = 0;
+
+ // get windows and derive offsets
+ gint xBin(0), yBin(0);
+ gdk_window_get_geometry( gtk_viewport_get_bin_window( viewport ), &xBin, &yBin, 0, 0 );
+
+ gint xView(0), yView(0);
+ gdk_window_get_geometry( gtk_viewport_get_view_window( viewport ), &xView, &yView, 0, 0 );
+
+ // calculate offsets
+ if( x ) *x = xView - xBin;
+ if( y ) *y = yView - yBin;
+
+ // also correct from widget thickness
+ GtkStyle* style( gtk_widget_get_style( GTK_WIDGET( viewport ) ) );
+ if( style )
+ {
+ if( x ) *x -= style->xthickness;
+ if( y ) *y -= style->ythickness;
+ }
+
+ return;
+
+ }
+
+ //___________________________________________________________
+ GtkWidget* Gtk::gtk_dialog_find_button(GtkDialog* dialog,gint response_id)
+ {
+
+ // get children of dialog's action area
+ GList* children( gtk_container_get_children( GTK_CONTAINER( gtk_dialog_get_action_area( dialog ) ) ) );
+
+ #if OXYGEN_DEBUG
+ std::cerr << "Oxygen::Gtk::gtk_dialog_find_button - buttons: ";
+ #endif
+
+ for( GList *child = g_list_first( children ); child; child = g_list_next( child ) )
+ {
+
+ // check data
+ if( !GTK_IS_WIDGET( child->data ) ) continue;
+ GtkWidget* childWidget( GTK_WIDGET( child->data ) );
+
+ const gint id( gtk_dialog_get_response_for_widget(dialog, childWidget ) );
+
+ #if OXYGEN_DEBUG
+ std::cerr << Gtk::TypeNames::response( (GtkResponseType) id ) << ", ";
+ #endif
+ if( id == response_id ) return childWidget;
+
+ }
+
+ #if OXYGEN_DEBUG
+ std::cerr << std::endl;
+ #endif
+
+ if( children ) g_list_free( children );
+ return 0L;
+
+ }
+
diff --git a/tdegtk/tdegtk-utils.h b/tdegtk/tdegtk-utils.h
new file mode 100644
index 0000000..0b97689
--- /dev/null
+++ b/tdegtk/tdegtk-utils.h
@@ -0,0 +1,428 @@
+#ifndef tdegtk_utils_h
+#define tdegtk_utils_h
+/*
+* this file was largely taken from the oxygen gtk engine
+* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
+* Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com>
+*
+* GdkPixbuf modification code from Walmis
+* <http://gnome-look.org/content/show.php?content=77783&forumpage=3>
+*
+* 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 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 St, Fifth Floor, Boston,
+* MA 02110-1301, USA.
+*/
+
+// #include "oxygenrgba.h"
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include <cmath>
+#include <string>
+
+#if 0
+ //! GdkRectangle streamer
+ inline std::ostream& operator << (std::ostream& out, const GdkRectangle& rect )
+ {
+ out << "( " << rect.x << "," << rect.y << "," << rect.width << "," << rect.height << ")";
+ return out;
+ }
+
+ //! GtkBorder streamer
+ inline std::ostream& operator << (std::ostream& out, const GtkBorder& border )
+ {
+ out << "( " << border.left << "," << border.right << "," << border.top << "," << border.bottom << ")";
+ return out;
+ }
+
+ //! streamer for GtkWidgetPath
+ std::ostream& operator << ( std::ostream& out, const GtkWidgetPath* path );
+
+ //! GtkContainer streamer
+ inline std::ostream& operator << (std::ostream& out, GtkContainer* container)
+ {
+ GList* children=gtk_container_get_children(container);
+ for(GList* child=g_list_first(children); child; child=g_list_next(child))
+ {
+ out << G_OBJECT_TYPE_NAME(child->data) << " ";
+ }
+ g_list_free(children);
+ return out;
+ }
+#endif
+
+ namespace Gtk
+ {
+
+ //! mouse button enumeration
+ enum MouseButton
+ {
+ NoButton = 0,
+ LeftButton = 1,
+ RightButton = 2,
+ MidButton = 3
+ };
+
+ //@!name gdk utilities
+ //@{
+
+#if 0
+ //! returns OxygenRgba color from GdkColor
+ /*! TODO: remove as obsolete */
+ inline ColorUtils::Rgba gdk_get_color( const GdkColor& color )
+ {
+ return ColorUtils::Rgba(
+ double(color.red)/0xffff,
+ double(color.green)/0xffff,
+ double(color.blue)/0xffff );
+ }
+
+ //! returns OxygenRgba color from GdkColor
+ inline ColorUtils::Rgba gdk_get_color( const GdkRGBA& color )
+ { return ColorUtils::Rgba( color.red, color.green, color.blue, color.alpha ); }
+#endif
+
+ //! map widget origin to top level
+ /*!
+ x and y correspond to (0,0) maped to toplevel window;
+ w and h correspond to toplevel window frame size
+ */
+ bool gdk_window_map_to_toplevel( GdkWindow*, gint*, gint*, gint*, gint*, bool frame = false );
+
+ //! map widget origin to top level
+ /*!
+ x and y correspond to (0,0) maped to toplevel window;
+ w and h correspond to toplevel window frame size
+ */
+ bool gtk_widget_map_to_toplevel( GtkWidget*, gint*, gint*, gint*, gint*, bool frame = false );
+
+ //! map widget onto another (parent) widget
+ /*! second argument can be any parent in widget's ancestry tree */
+ bool gtk_widget_map_to_parent( GtkWidget*, GtkWidget*, gint*, gint*, gint*, gint* );
+
+ //! map window/widget origin to top level
+ inline bool gdk_map_to_toplevel( GdkWindow* window, GtkWidget* widget, gint* x, gint* y, gint* w, gint* h, bool frame = false )
+ {
+ if( window && GDK_IS_WINDOW( window ) ) return gdk_window_map_to_toplevel( window, x, y, w, h, frame );
+ else return gtk_widget_map_to_toplevel( widget, x, y, w, h, frame );
+ }
+
+ //! map window origin to top level
+ inline bool gdk_map_to_toplevel( GdkWindow* window, gint* x, gint* y, gint* w, gint* h, bool frame = false )
+ { return gdk_window_map_to_toplevel( window, x, y, w, h, frame ); }
+
+ //! translate origin of child window into parent
+ /*! returns true on success */
+ bool gdk_window_translate_origin( GdkWindow*, GdkWindow*, gint*, gint* );
+
+ //! get top level windows dimension
+ void gdk_toplevel_get_size( GdkWindow*, gint*, gint* );
+
+ //! get top level windows dimension
+ void gdk_toplevel_get_frame_size( GdkWindow*, gint*, gint* );
+
+ //! get position relatve to toplevel
+ void gdk_window_get_toplevel_origin( GdkWindow*, gint*, gint* );
+
+ //! add alpha channel to pixbuf
+ GdkPixbuf* gdk_pixbuf_set_alpha( const GdkPixbuf*, double );
+
+ //! changes the gamma value of an image
+ bool gdk_pixbuf_to_gamma( GdkPixbuf* pixbuf, double value );
+
+ //! resize pixbuf
+ GdkPixbuf* gdk_pixbuf_resize( GdkPixbuf* src, int width, int height );
+
+ //! returns initialized GdkRectangle
+ inline GdkRectangle gdk_rectangle( int x = 0, int y = 0, int w = -1, int h = -1 )
+ {
+ GdkRectangle out = {x, y, w, h};
+ return out;
+ }
+
+ //! returns true if rectangle is valid
+ inline bool gdk_rectangle_is_valid( const GdkRectangle* rect )
+ { return rect && rect->width > 0 && rect->height > 0; }
+
+ //! performs union of two rectangle, properly accounting for their validity
+ inline void gdk_rectangle_union( const GdkRectangle* first, const GdkRectangle* second, GdkRectangle* out )
+ {
+ if( !out ) return;
+ const bool firstIsValid( Gtk::gdk_rectangle_is_valid( first ) );
+ const bool secondIsValid( Gtk::gdk_rectangle_is_valid( second ) );
+ if( firstIsValid && secondIsValid ) ::gdk_rectangle_union( first, second, out );
+ else if( secondIsValid ) *out = *second;
+ else *out = *first;
+ }
+
+ //! returns true if given rectangle contains point
+ inline bool gdk_rectangle_contains( const GdkRectangle* rect, int x, int y )
+ {
+ return
+ rect &&
+ ( rect->x <= x && (rect->x + rect->width) > x ) &&
+ ( rect->y <= y && (rect->y + rect->height) > y );
+ }
+
+ //@}
+
+ //! get arrow orientation from angle
+ inline GtkArrowType gtk_arrow_get_type( const double& angle )
+ {
+ static const double delta( 0.001 );
+ if( std::abs( angle ) < delta ) return GTK_ARROW_UP;
+ else if( std::abs( angle - M_PI/2 ) < delta ) return GTK_ARROW_RIGHT;
+ else if( std::abs( angle - M_PI ) < delta ) return GTK_ARROW_DOWN;
+ else return GTK_ARROW_LEFT;
+ }
+
+ //! returns true if widget's layout is reversed
+ inline bool gtk_widget_layout_is_reversed( GtkWidget* widget )
+ { return widget ? gtk_widget_get_direction( widget ) == GTK_TEXT_DIR_RTL : false; }
+
+ //! returns true if widget's layout is reversed
+ inline bool gtk_theming_engine_layout_is_reversed( GtkThemingEngine* engine )
+ { return engine ? gtk_theming_engine_get_direction( engine ) == GTK_TEXT_DIR_RTL : false; }
+
+ //! set all buttons in the container to state NORMAL
+ void gtk_container_adjust_buttons_state( GtkContainer*, gpointer=0L );
+
+ //! returns widget allocation
+ inline GtkAllocation gtk_widget_get_allocation( GtkWidget* widget )
+ {
+ GtkAllocation allocation = { 0, 0, -1, -1 };
+ ::gtk_widget_get_allocation( widget, &allocation );
+ return allocation;
+ }
+
+ //! returns true if given path as given type
+ bool gtk_widget_path_has_type( const GtkWidgetPath*, GType );
+
+ //! returns true if widget is a groupbox (a la Qt)
+ inline bool gtk_widget_is_groupbox( GtkWidget* widget )
+ {
+ return
+ GTK_IS_FRAME( widget ) &&
+ gtk_frame_get_label_widget( GTK_FRAME( widget ) ) &&
+ gtk_frame_get_shadow_type( GTK_FRAME( widget ) ) == GTK_SHADOW_OUT;
+ }
+
+ //! returns true if widget (or one of its parent) has a custom background
+ bool gtk_widget_has_custom_background( GtkWidget*, GtkStateType = GTK_STATE_NORMAL );
+
+ //! returns true if is an Gnome applet
+ bool gtk_widget_is_applet( GtkWidget* );
+
+ //! print some widget information
+ void gtk_widget_print_tree( GtkWidget* );
+
+ //! returns true if widget supports rgba
+ bool gtk_widget_has_rgba( GtkWidget* );
+
+ //! returns true if default screen is composited
+ bool gdk_default_screen_is_composited( void );
+
+ //! returns true if window supports rgba
+ bool gdk_window_has_rgba( GdkWindow* );
+
+ //! true if visual supports rgba
+ bool gdk_visual_has_rgba( GdkVisual* );
+
+ //! returns true if window is a base window
+ bool gdk_window_is_base( GdkWindow* );
+
+ //! returns true if window is a base window that do not need painting
+ bool gdk_window_nobackground( GdkWindow* );
+
+ //! true if object match a given type
+ bool g_object_is_a( const GObject*, const std::string& );
+
+ //! trigger area update using GdkRectangle
+ inline void gtk_widget_queue_draw( GtkWidget* widget, const GdkRectangle* rect = 0L )
+ {
+ if( !gdk_rectangle_is_valid( rect ) ) ::gtk_widget_queue_draw( widget );
+ else ::gtk_widget_queue_draw_area( widget, rect->x, rect->y, rect->width, rect->height );
+ }
+
+ //!@name check parent type
+ //@{
+
+ //! returns widget path as a string
+ std::string gtk_widget_path( GtkWidget* );
+
+ //! return parent of given type if any
+ GtkWidget* gtk_widget_find_parent( GtkWidget*, GType );
+
+ //! return parent of given type
+ inline GtkWidget* gtk_widget_find_parent( GtkWidget* widget, const std::string& typeName )
+ {
+ const GType tmp( g_type_from_name( typeName.c_str() ) );
+ return tmp ? gtk_widget_find_parent( widget, tmp ): 0L;
+ }
+
+ //! return parent "group box" if any.
+ GtkWidget* gtk_parent_groupbox( GtkWidget* widget );
+
+ //! return parent button if any.
+ inline GtkWidget* gtk_parent_button( GtkWidget* widget )
+ { return gtk_widget_find_parent( widget, GTK_TYPE_BUTTON ); }
+
+ //! return parent menu if any
+ inline GtkWidget* gtk_parent_menubar( GtkWidget* widget )
+ { return gtk_widget_find_parent( widget, GTK_TYPE_MENU_BAR ); }
+
+ //! return parent menu if any
+ inline GtkWidget* gtk_parent_menu( GtkWidget* widget )
+ { return gtk_widget_find_parent( widget, GTK_TYPE_MENU ); }
+
+ //! return parent treeview if any.
+ inline GtkWidget* gtk_parent_tree_view( GtkWidget* widget )
+ { return gtk_widget_find_parent( widget, GTK_TYPE_TREE_VIEW ); }
+
+ //! return parent combobox if any.
+ inline GtkWidget* gtk_parent_combobox( GtkWidget* widget )
+ { return gtk_widget_find_parent( widget, GTK_TYPE_COMBO_BOX ); }
+
+ //! return parent combobox if any.
+ inline GtkWidget* gtk_parent_combobox_entry( GtkWidget* widget )
+ {
+ GtkWidget* parent( gtk_parent_combobox( widget ) );
+ return ( parent && gtk_combo_box_get_has_entry( GTK_COMBO_BOX( parent ) ) ) ? parent:0L;
+ }
+
+ //! return parent scrolled window if any.
+ inline GtkWidget* gtk_parent_scrolled_window( GtkWidget* widget )
+ { return gtk_widget_find_parent( widget, GTK_TYPE_SCROLLED_WINDOW ); }
+
+ //! return parent statusbar if any.
+ inline GtkWidget* gtk_parent_statusbar( GtkWidget* widget )
+ { return gtk_widget_find_parent( widget, GTK_TYPE_STATUSBAR ); }
+
+ //! return parent combobox if any.
+ inline GtkWidget* gtk_parent_notebook( GtkWidget* widget )
+ { return gtk_widget_find_parent( widget, GTK_TYPE_NOTEBOOK ); }
+
+ //! returns true if potentialParent is (maybe indirect) parent of widget
+ bool gtk_widget_is_parent( GtkWidget*, GtkWidget* potentialParent );
+
+ //! returns true if one of the parent widgets has a sunken shadow
+ bool gtk_parent_is_shadow_in( GtkWidget* );
+
+ //@}
+
+ //! true if a widget (orientable) is horizontal
+ inline bool gtk_widget_is_horizontal( GtkWidget* widget )
+ {
+ if( !GTK_IS_ORIENTABLE( widget ) ) return true;
+ return gtk_orientable_get_orientation( GTK_ORIENTABLE( widget ) ) == GTK_ORIENTATION_HORIZONTAL;
+ }
+
+
+ //! true if a widget (orientable) is vertical
+ inline bool gtk_widget_is_vertical( GtkWidget* widget )
+ {
+ if( !GTK_IS_ORIENTABLE( widget ) ) return false;
+ return gtk_orientable_get_orientation( GTK_ORIENTABLE( widget ) ) == GTK_ORIENTATION_VERTICAL;
+ }
+
+ //! true if scrolled window must be forced to have a sunken frame
+ bool gtk_scrolled_window_force_sunken( GtkWidget* );
+
+ //!@name button utilities
+ //@{
+
+ //! true for 'flat' buttons (e.g. toolbuttons)
+ bool gtk_button_is_flat( GtkWidget* );
+
+ //! true for treeview headers and affiliated
+ bool gtk_button_is_header( GtkWidget* );
+
+ //! true for buttons in path bars
+ bool gtk_button_is_in_path_bar( GtkWidget* widget );
+
+ //! true if widget is last in path bar
+ bool gtk_path_bar_button_is_last( GtkWidget* widget );
+
+ //! returns an image on button-container
+ GtkWidget* gtk_button_find_image( GtkWidget* );
+
+ //! returns an image on button-container
+ GtkWidget* gtk_button_find_label( GtkWidget* );
+
+ //@}
+
+ //!@name combobox utilities
+ //@{
+
+ //! returns true if combobox has frame
+ bool gtk_combobox_has_frame( GtkWidget* );
+
+ //! true if widget is the treeview of a combobox
+ bool gtk_combobox_is_tree_view( GtkWidget* );
+
+ //! true if widget is the treeview of a combobox
+ bool gtk_combobox_is_scrolled_window( GtkWidget* );
+
+ //! true if widget is the treeview of a combobox
+ bool gtk_combobox_is_viewport( GtkWidget* );
+
+ //! true if widget is the treeview of a combobox
+ bool gtk_combobox_is_frame( GtkWidget* );
+
+ //! true if combobox must appear as list
+ bool gtk_combobox_appears_as_list( GtkWidget* );
+
+ //@}
+
+ //!@name notebook utilities
+ //@{
+
+ //! returns true if position is in hovered tab
+ //* this should move to OxygenTabWidgetData
+ bool gtk_notebook_tab_contains( GtkWidget*, int tab, int x, int y );
+
+ //! returns tab matching position or -1 if none
+ int gtk_notebook_find_tab( GtkWidget*, int x, int y );
+
+ //! returns index of first visible tab
+ int gtk_notebook_find_first_tab( GtkWidget* );
+
+ //! returns true if widget is one of the notebook's tab labels
+ bool gtk_notebook_is_tab_label( GtkNotebook*, GtkWidget* );
+
+ //! returns tabbar rect in notebook
+ void gtk_notebook_get_tabbar_rect( GtkNotebook*, GdkRectangle* );
+
+ //! returns true if notebook has visible scrollbar arrows
+ /*! arrows are dimmed visible if at least one of the child tab_labels is unmapped */
+ bool gtk_notebook_has_visible_arrows( GtkNotebook* );
+
+ // make all the buttons on the tabs normal
+ bool gtk_notebook_update_close_buttons( GtkNotebook*);
+
+ //! returns true if widget is a notebook close button
+ bool gtk_notebook_is_close_button( GtkWidget* );
+
+ //@}
+
+ //! calculates viewport offsets (between view window and bin window
+ void gtk_viewport_get_position( GtkViewport*, gint*, gint* );
+
+ //! returns a widget which has response_id as response id for dialog
+ GtkWidget* gtk_dialog_find_button( GtkDialog*, gint );
+
+ }
+
+#endif
diff --git a/tdegtk/tdegtk-widgetlookup.cpp b/tdegtk/tdegtk-widgetlookup.cpp
new file mode 100644
index 0000000..79ed0e9
--- /dev/null
+++ b/tdegtk/tdegtk-widgetlookup.cpp
@@ -0,0 +1,231 @@
+/*
+* this file was largely taken from the oxygen gtk engine
+* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
+* Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com>
+*
+* Hook-setup code provided by Ruslan
+*
+* 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 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 St, Fifth Floor, Boston,
+* MA 02110-1301, USA.
+*/
+
+#include "tdegtk-widgetlookup.h"
+#include "config.h"
+
+#include <iostream>
+#include <cairo/cairo-gobject.h>
+
+// #define TDEGTK_DEBUG 1
+
+ //__________________________________________________________________
+ WidgetLookup::WidgetLookup( void ):
+ _hooksInitialized( false ),
+ _context( 0L )
+ {}
+
+
+ //_____________________________________________________
+ WidgetLookup::~WidgetLookup( void )
+ {
+
+ // disconnect hooks
+ _drawHook.disconnect();
+
+ }
+
+ //_____________________________________________________
+ void WidgetLookup::initializeHooks( void )
+ {
+
+ #if TDEGTK_DEBUG
+ std::cerr << "Oxygen::WidgetLookup::initializeHooks" << std::endl;
+ #endif
+
+ if( _hooksInitialized ) return;
+
+ // install hook and test
+ if( !_drawHook.connect( "draw", (GSignalEmissionHook)drawHook, this ) ) return;
+
+ // set initialization flag
+ _hooksInitialized = true;
+
+ return;
+
+ }
+
+ //_____________________________________________________
+ GtkWidget* WidgetLookup::find( cairo_t* context, const GtkWidgetPath* path ) const
+ {
+
+ // check path
+ if( !path ) return 0L;
+
+ // get length and check
+ const gint length( gtk_widget_path_length( path ) );
+ if( length < 1 ) return 0L;
+
+ // lookup last type
+ return find( context, gtk_widget_path_iter_get_object_type( path, length-1 ) );
+
+ }
+
+ //_____________________________________________________
+ GtkWidget* WidgetLookup::find( cairo_t* context, GType type ) const
+ {
+ // check context
+ if( context != _context )
+ {
+ #if TDEGTK_DEBUG
+ std::cerr << "Oxygen::WidgetLookup::find - invalid context: " << context << std::endl;
+ #endif
+ return 0L;
+ }
+
+ #if TDEGTK_DEBUG
+ std::cerr
+ << "Oxygen::WidgetLookup::find -"
+ << " context: " << context
+ << " type: " << g_type_name( type )
+ << std::endl;
+ #endif
+
+ // look for type in stored widgets
+ /* we loop backward, since last added widgets are more likely to be looked up */
+ for( WidgetList::const_reverse_iterator iter = _widgets.rbegin(); iter != _widgets.rend(); ++iter )
+ {
+ // compare types and return if matched
+ if( G_OBJECT_TYPE( *iter ) == type )
+ {
+ #if TDEGTK_DEBUG
+ std::cerr
+ << "Oxygen::WidgetLookup::find -"
+ << " context: " << context
+ << " type: " << g_type_name( type )
+ << " found: " << *iter
+ << std::endl;
+ #endif
+ return *iter;
+ }
+ }
+
+ #if TDEGTK_DEBUG
+ std::cerr
+ << "Oxygen::WidgetLookup::find -"
+ << " context: " << context
+ << " type: " << g_type_name( type )
+ << " - no match found"
+ << std::endl;
+ #endif
+
+ return 0L;
+
+ }
+
+ //_____________________________________________________
+ void WidgetLookup::bind( GtkWidget* widget, cairo_t* context )
+ {
+ // check if context has changed and clear widgets if yes
+ if( context != _context )
+ {
+
+ #if TDEGTK_DEBUG
+ std::cerr
+ << "Oxygen::WidgetLookup::bind -"
+ << " context: " << _context
+ << " widgets: " << _widgets.size()
+ << std::endl;
+ #endif
+
+ _context = context;
+ _widgets.clear();
+ }
+
+ _widgets.push_back( widget );
+
+ // add to all widgets map
+ if( _allWidgets.find( widget ) == _allWidgets.end() )
+ {
+ Signal destroyId;
+ destroyId.connect( G_OBJECT( widget ), "destroy", G_CALLBACK( destroyNotifyEvent ), this );
+ _allWidgets.insert( std::make_pair( widget, destroyId ) );
+ }
+
+ }
+
+ //____________________________________________________________________________________________
+ void WidgetLookup::unregisterWidget( GtkWidget* widget )
+ {
+
+ #if TDEGTK_DEBUG
+ std::cerr << "Oxygen::WidgetLookup::unregisterWidget - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
+ #endif
+
+ // find in map
+ WidgetMap::iterator iter( _allWidgets.find( widget ) );
+ assert( iter != _allWidgets.end() );
+
+ // disconnect signal
+ iter->second.disconnect();
+
+ // erase from lists
+ _allWidgets.erase( widget );
+ _widgets.remove( widget );
+
+ }
+
+ //_____________________________________________________
+ gboolean WidgetLookup::drawHook( GSignalInvocationHint*, guint numParams, const GValue* params, gpointer data )
+ {
+
+ // check number of parameters
+ if( numParams < 2 ) return FALSE;
+
+ // get widget from params
+ GtkWidget* widget( GTK_WIDGET( g_value_get_object( params ) ) );
+
+ // check type
+ if( !GTK_IS_WIDGET( widget ) ) return FALSE;
+
+ // check second parameter type.
+ if( !G_VALUE_HOLDS( params+1, CAIRO_GOBJECT_TYPE_CONTEXT ) )
+ { return FALSE; }
+
+ // retrieve context and cast
+ cairo_t* context( static_cast<cairo_t*>( g_value_get_boxed(params+1) ) );
+
+ #if TDEGTK_DEBUG
+ std::cerr
+ << "Oxygen::WidgetLookup::drawHook -"
+ << " widget: " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")"
+ << " context: " << context
+ << std::endl;
+ #endif
+
+ // bind widget and context
+ static_cast<WidgetLookup*>( data )->bind( widget, context );
+
+ return TRUE;
+
+ }
+
+
+ //____________________________________________________________________________________________
+ gboolean WidgetLookup::destroyNotifyEvent( GtkWidget* widget, gpointer data )
+ {
+ static_cast<WidgetLookup*>(data)->unregisterWidget( widget );
+ return FALSE;
+ }
+
+
diff --git a/tdegtk/tdegtk-widgetlookup.h b/tdegtk/tdegtk-widgetlookup.h
new file mode 100644
index 0000000..98a7b96
--- /dev/null
+++ b/tdegtk/tdegtk-widgetlookup.h
@@ -0,0 +1,92 @@
+#ifndef tdegtk_widgetlookup_h
+#define tdegtk_widgetlookup_h
+/*
+* this file was largely taken from the oxygen gtk engine
+* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
+* Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com>
+*
+* 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 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 St, Fifth Floor, Boston,
+* MA 02110-1301, USA.
+*/
+
+#include "tdegtk-hooks.h"
+#include "tdegtk-signals.h"
+
+#include <cairo/cairo.h>
+#include <gtk/gtk.h>
+
+#include <list>
+#include <map>
+
+
+ //! uses the widget's "draw" signal to bind GtkWidget and cairo context
+ /*! this allows us to retrieve painted widgets from ThemingEngine rendering primitives */
+ class WidgetLookup
+ {
+
+ public:
+
+ //! constructor
+ explicit WidgetLookup( void );
+
+ //! destructor
+ virtual ~WidgetLookup( void );
+
+ //! initialize hooks
+ void initializeHooks( void );
+
+ //! find widget matching given context and type
+ GtkWidget* find( cairo_t*, const GtkWidgetPath* ) const;
+
+ //! find widget matching given context and type
+ GtkWidget* find( cairo_t*, GType ) const;
+
+ protected:
+
+ //! bind widget to context
+ void bind( GtkWidget*, cairo_t* );
+
+ //! unregister widget
+ void unregisterWidget( GtkWidget* );
+
+ //! hook connected to widget's "draw" signal
+ static gboolean drawHook( GSignalInvocationHint*, guint, const GValue*, gpointer );
+
+ //! destruction callback
+ static gboolean destroyNotifyEvent( GtkWidget*, gpointer );
+
+ private:
+
+ //! true if hooks are initialized
+ bool _hooksInitialized;
+
+ //! hook connected to widget's "draw" signal
+ Hook _drawHook;
+
+ //! store current context
+ cairo_t* _context;
+
+ //! store list of associated widgets, to keep track of destruction
+ typedef std::list<GtkWidget*> WidgetList;
+ WidgetList _widgets;
+
+ //! keep track of all registered widgets, and associated destroy callback
+ typedef std::map< GtkWidget*, Signal > WidgetMap;
+ WidgetMap _allWidgets;
+
+ };
+
+#endif
+
diff --git a/tdegtk/tqtcairopainter.cpp b/tdegtk/tqtcairopainter.cpp
index c19a736..6d3b2cf 100644
--- a/tdegtk/tqtcairopainter.cpp
+++ b/tdegtk/tqtcairopainter.cpp
@@ -327,16 +327,16 @@ void TQt3CairoPaintDevice::transferIntermediateSurface() {
if (!m_clipRegionEnabled) {
// Clipping disabled
- cairo_set_source_surface(m_devicePainter, m_intermediateSurface, 0, 0);
+ cairo_set_source_surface(m_devicePainter, m_intermediateSurface, m_offsetX, m_offsetY);
cairo_set_operator(m_devicePainter, overlayMerge?CAIRO_OPERATOR_OVER:CAIRO_OPERATOR_SOURCE);
cairo_paint(m_devicePainter);
}
else {
// Clipping enabled
cairo_surface_t* maskSurface = TQImageToCairoSurface(m_clipRegion);
- cairo_set_source_surface(m_devicePainter, m_intermediateSurface, 0, 0);
+ cairo_set_source_surface(m_devicePainter, m_intermediateSurface, m_offsetX, m_offsetY);
cairo_set_operator(m_devicePainter, overlayMerge?CAIRO_OPERATOR_OVER:CAIRO_OPERATOR_SOURCE);
- cairo_mask_surface(m_devicePainter, maskSurface, 0, 0);
+ cairo_mask_surface(m_devicePainter, maskSurface, m_offsetX, m_offsetY);
cairo_surface_destroy(maskSurface);
}
@@ -1083,16 +1083,18 @@ void TQt3CairoPaintDevice::setCairoTransformations() {
Constructs TQt3CairoPaintDevice on an existing QPainter
*/
-TQt3CairoPaintDevice::TQt3CairoPaintDevice( cairo_surface_t *cairosurface, int width, int height, cairo_t *overridepainter )
+TQt3CairoPaintDevice::TQt3CairoPaintDevice( cairo_surface_t *cairosurface, int x, int y, int width, int height, cairo_t *overridepainter )
: TQPaintDevice( TQInternal::Picture | TQInternal::ExternalDevice )
{
init();
+ m_offsetX = x;
+ m_offsetY = y;
if (width >= 0) {
m_width = width;
}
if (height >= 0) {
- m_height = width;
+ m_height = height;
}
if (overridepainter) {
m_overridePainter = overridepainter;
@@ -1138,6 +1140,8 @@ TQt3CairoPaintDevice::~TQt3CairoPaintDevice()
void TQt3CairoPaintDevice::init() {
m_width = -1;
m_height = -1;
+ m_offsetX = 0;
+ m_offsetY = 0;
m_intermediateSurface = NULL;
m_painter = NULL;
diff --git a/tdegtk/tqtcairopainter.h b/tdegtk/tqtcairopainter.h
index 20a03d3..67ccd79 100644
--- a/tdegtk/tqtcairopainter.h
+++ b/tdegtk/tqtcairopainter.h
@@ -40,7 +40,7 @@ typedef TQPtrStack<TQWMatrix> TQWMatrixStack;
class Q_EXPORT TQt3CairoPaintDevice : public TQPaintDevice // picture class
{
public:
- TQt3CairoPaintDevice( cairo_surface_t *, int width = -1, int height = -1, cairo_t *overridepainter = NULL );
+ TQt3CairoPaintDevice( cairo_surface_t *, int x = 0, int y = 0, int width = -1, int height = -1, cairo_t *overridepainter = NULL );
~TQt3CairoPaintDevice();
protected:
@@ -75,6 +75,8 @@ class Q_EXPORT TQt3CairoPaintDevice : public TQPaintDevice // picture class
private:
mutable int m_width;
mutable int m_height;
+ mutable int m_offsetX;
+ mutable int m_offsetY;
cairo_surface_t *m_surface;
cairo_surface_t *m_intermediateSurface;
diff --git a/tests/compare b/tests/compare
new file mode 100755
index 0000000..83726c5
--- /dev/null
+++ b/tests/compare
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+composite -compose subtract tqt3.png stroke.png diff.png
diff --git a/tests/test-painter.cpp b/tests/test-painter.cpp
index 3c21432..f912009 100644
--- a/tests/test-painter.cpp
+++ b/tests/test-painter.cpp
@@ -257,6 +257,96 @@ void runTests(TQPaintDevice* pd) {
cg.setColor(TQColorGroup::Foreground, TQColor(0,0,0));
tqApp->style().drawPrimitive(TQStyle::PE_ExclusiveIndicator, &p, TQRect(400, 400, 16, 16), cg, TQStyle::Style_Down);
+ // Tab bar tab tests
+ {
+ int currentPage;
+ int numPages=3;
+ int tabIndex=2;
+
+ int x = 0;
+ int y = 300;
+ int width = 50;
+ int height = 20;
+
+ for (currentPage=0;currentPage<numPages;currentPage++) {
+ TQRect boundingRect(0, 0, width, height);
+
+ TQStringList objectTypes;
+ objectTypes.append(TQTABBAR_OBJECT_NAME_STRING);
+ TQPalette objectPalette = tqApp->palette(objectTypes);
+
+ TQStyleControlElementData ceData;
+ TQStyle::ControlElementFlags elementFlags;
+ ceData.widgetObjectTypes = objectTypes;
+ ceData.rect = boundingRect;
+
+ TQTab tqt3Tab;
+ tqt3Tab.setIdentifier(currentPage);
+ TQStyleOption tabOpt(&tqt3Tab, (TQTab*)NULL);
+
+ elementFlags = elementFlags | TQStyle::CEF_HasParentWidget;
+ ceData.parentWidgetData.widgetObjectTypes.append(TQTABBAR_OBJECT_NAME_STRING);
+
+ int tab_overlap = tqApp->style().pixelMetric(TQStyle::PM_TabBarTabOverlap);
+ x = x + width + tab_overlap;
+
+ boundingRect = TQRect(x, y, width+(tab_overlap*2), height);
+
+ ceData.tabBarData.shape = TQTabBar::RoundedAbove;
+ ceData.tabBarData.tabCount = numPages;
+ ceData.tabBarData.identIndexMap[tqt3Tab.identifier()] = currentPage;
+
+ TQColorGroup cg = tqApp->palette().active();
+
+ // Draw tab
+ tqApp->style().drawControl(TQStyle::CE_TabBarTab, &p, ceData, elementFlags, boundingRect, cg, ((tabIndex==currentPage)?TQStyle::Style_Selected:TQStyle::Style_Default), tabOpt);
+ }
+ }
+ {
+ int currentPage;
+ int numPages=3;
+ int tabIndex=2;
+
+ int x = (50*4);
+ int y = 325;
+ int width = 50;
+ int height = 20;
+
+ for (currentPage=(numPages-1);currentPage>=0;currentPage--) {
+ TQRect boundingRect(0, 0, width, height);
+
+ TQStringList objectTypes;
+ objectTypes.append(TQTABBAR_OBJECT_NAME_STRING);
+ TQPalette objectPalette = tqApp->palette(objectTypes);
+
+ TQStyleControlElementData ceData;
+ TQStyle::ControlElementFlags elementFlags;
+ ceData.widgetObjectTypes = objectTypes;
+ ceData.rect = boundingRect;
+
+ TQTab tqt3Tab;
+ tqt3Tab.setIdentifier(currentPage);
+ TQStyleOption tabOpt(&tqt3Tab, (TQTab*)NULL);
+
+ elementFlags = elementFlags | TQStyle::CEF_HasParentWidget;
+ ceData.parentWidgetData.widgetObjectTypes.append(TQTABBAR_OBJECT_NAME_STRING);
+
+ int tab_overlap = tqApp->style().pixelMetric(TQStyle::PM_TabBarTabOverlap);
+ x = x - width - tab_overlap;
+
+ boundingRect = TQRect(x, y, width+(tab_overlap*2), height);
+
+ ceData.tabBarData.shape = TQTabBar::RoundedAbove;
+ ceData.tabBarData.tabCount = numPages;
+ ceData.tabBarData.identIndexMap[tqt3Tab.identifier()] = currentPage;
+
+ TQColorGroup cg = tqApp->palette().active();
+
+ // Draw tab
+ tqApp->style().drawControl(TQStyle::CE_TabBarTab, &p, ceData, elementFlags, boundingRect, cg, ((tabIndex==currentPage)?TQStyle::Style_Selected:TQStyle::Style_Default), tabOpt);
+ }
+ }
+
p.end();
}