/* The TdeGtk Theming Engine for Gtk+. * Copyright (C) 2012 Timothy Pearson * * 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 #include #include #include #include #include #include #include #include #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 "tdegtk-animations.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; Animations m_animations; // 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 (wt == TQT3WT_TQGroupBox) { if (prelight) { sflags |= TQStyle::Style_MouseOver; } if (focused) { sflags |= TQStyle::Style_HasFocus; } if (!disabled) { sflags |= TQStyle::Style_Enabled; } } else if (wt == TQT3WT_TQMenuItem) { 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)); } else { // Draw arrow TQStyle::PrimitiveElement pe; if (arrow_direction == GTK_ARROW_UP) { pe = TQStyle::PE_ArrowUp; } else if (arrow_direction == GTK_ARROW_DOWN) { pe = TQStyle::PE_ArrowDown; } else if (arrow_direction == GTK_ARROW_LEFT) { pe = TQStyle::PE_ArrowLeft; } else { pe = TQStyle::PE_ArrowRight; } tqApp->style().drawPrimitive(pe, &p, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE)); } 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) | ((ceData.orientation == TQt::Horizontal)?TQStyle::Style_Horizontal:TQStyle::Style_Default)); } 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_MENU)) || (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_MENUITEM))) { DEBUG_FILL_BACKGROUND_WITH_COLOR(p,255,128,255); // FIXME // Mouse movements in the popup menu should be tracked similarly to mouse movements in the tab bar // Many TQt3 styles highlight inactive menu items on hover; not providing this visual feedback may cause users to briefly think their GTK application has frozen up // // Register menu item with animation engine // m_animations.menuItemEngine().registerWidget(widget); // // // Check tab properties // int tabIndex = Gtk::gtk_notebook_find_tab(widget, x+width/2, y+height/2); // m_animations.tabWidgetEngine().updateTabRect(widget, tabIndex, x, y, width, height); // bool prelight = (tabIndex == m_animations.tabWidgetEngine().hoveredTab(widget)); // GtkMenuItem* menuitem = GTK_MENU_ITEM(widget); // const int currentPage = gtk_notebook_get_current_page(notebook); // const int numPages = gtk_notebook_get_n_pages(notebook); // bool selectedTab = (tabIndex==currentPage); TQStringList objectTypes; objectTypes.append(TQPOPUPMENU_OBJECT_NAME_STRING); TQPalette objectPalette = tqApp->palette(objectTypes); TQStyleControlElementData ceData; TQStyle::ControlElementFlags elementFlags; ceData.widgetObjectTypes = objectTypes; ceData.rect = boundingRect; TQMenuItem tqt3MenuItem; int maxAcceleratorTextWidth = 0; int maxIconWidth = IconSize(KIcon::Small) + 4; TQStyleOption menuOpt(&tqt3MenuItem, maxIconWidth, maxAcceleratorTextWidth); // if (???) elementFlags = elementFlags | TQStyle::TQStyle::CEF_IsCheckable; TQRect paintDeviceRect; TQRect backgroundRect; // Draw item tqApp->style().drawControl(TQStyle::CE_PopupMenuItem, &p, ceData, elementFlags, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_TQMenuItem) | ((gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_MENUITEM))?TQStyle::Style_Active:TQStyle::Style_Default), menuOpt); } 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) | ((ceData.orientation == TQt::Horizontal)?TQStyle::Style_Horizontal:TQStyle::Style_Default)); 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)); } if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_MENU)) { TQStringList objectTypes; objectTypes.append(TQPOPUPMENU_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_PanelPopup, &p, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE) | ((ceData.orientation == TQt::Horizontal)?TQStyle::Style_Horizontal:TQStyle::Style_Default)); } } 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)) { // Register tabbar with animation engine m_animations.tabWidgetEngine().registerWidget(widget); // Check tab properties int tabIndex = Gtk::gtk_notebook_find_tab(widget, x+width/2, y+height/2); m_animations.tabWidgetEngine().updateTabRect(widget, tabIndex, x, y, width, height); bool prelight = (tabIndex == m_animations.tabWidgetEngine().hoveredTab(widget)); 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); bool selectedTab = (tabIndex==currentPage); 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); int tab_to_frame_gap_height = 2; ceData.tabBarData.tabCount = numPages; ceData.tabBarData.identIndexMap[tqt3Tab.identifier()] = tabIndex; TQRect paintDeviceRect; TQRect backgroundRect; switch (gap_side) { default: case GTK_POS_TOP: ceData.tabBarData.shape = TQTabBar::RoundedBelow; paintDeviceRect = TQRect(x-tab_overlap, y-tab_to_frame_gap_height, width+(tab_overlap*2), height+tab_to_frame_gap_height); boundingRect = TQRect(0, 0, width+(tab_overlap*2)-tab_overlap, height+tab_to_frame_gap_height); backgroundRect = TQRect(tab_overlap, 0, width, height+2); break; case GTK_POS_LEFT: ceData.tabBarData.shape = TQTabBar::RoundedAbove; // FIXME // TQt3 does not know how to draw these // For now, draw a single unconnected tab in this location tabIndex = 0; ceData.tabBarData.tabCount = 1; tqt3Tab.setIdentifier(tabIndex); ceData.tabBarData.identIndexMap[tqt3Tab.identifier()] = tabIndex; paintDeviceRect = TQRect(x-tab_overlap, y, width+(tab_overlap*2), height); boundingRect = TQRect(0, 0, width+(tab_overlap*2)-tab_overlap, height); backgroundRect = TQRect(0, 0, width, height); break; case GTK_POS_BOTTOM: ceData.tabBarData.shape = TQTabBar::RoundedAbove; paintDeviceRect = TQRect(x-tab_overlap, y, width+(tab_overlap*2), height+tab_to_frame_gap_height); boundingRect = TQRect(0, 0, width+(tab_overlap*2)-tab_overlap, height+tab_to_frame_gap_height); backgroundRect = TQRect(tab_overlap, 0, width, height+2); break; case GTK_POS_RIGHT: ceData.tabBarData.shape = TQTabBar::RoundedAbove; // FIXME // TQt3 does not know how to draw these // For now, draw a single unconnected tab in this location tabIndex = 0; ceData.tabBarData.tabCount = 1; tqt3Tab.setIdentifier(tabIndex); ceData.tabBarData.identIndexMap[tqt3Tab.identifier()] = tabIndex; paintDeviceRect = TQRect(x-tab_overlap, y, width+(tab_overlap*2), height); boundingRect = TQRect(0, 0, width+(tab_overlap*2)-tab_overlap, height); backgroundRect = TQRect(0, 0, width, height); break; } cairo_save(cr); cairo_reset_clip(cr); TQt3CairoPaintDevice pd2(NULL, paintDeviceRect.x(), paintDeviceRect.y(), paintDeviceRect.width(), paintDeviceRect.height(), cr); TQPainter p2(&pd2); // Draw background TQBrush brush = objectPalette.brush(gtkToTQPaletteColorGroup(engine, state), TQColorGroup::Background); DRAW_FILLED_RECTANGLE_OVER_SPECIFIC_AREA(p2, brush, backgroundRect.x(), backgroundRect.y(), backgroundRect.width(), backgroundRect.height()) // Draw tab tqApp->style().drawControl(TQStyle::CE_TabBarTab, &p2, ceData, elementFlags, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE) | ((selectedTab)?TQStyle::Style_Selected:TQStyle::Style_Default) | ((prelight)?TQStyle::Style_MouseOver: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); 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_FRAME)) { GtkFrame* frame = GTK_FRAME(widget); GtkShadowType gtkShadowType = gtk_frame_get_shadow_type(frame); TQStringList objectTypes; objectTypes.append(TQGROUPBOX_OBJECT_NAME_STRING); TQPalette objectPalette = tqApp->palette(objectTypes); int groupBoxLineWidth = 1; int lineWidth = 0; int midLineWidth = 0; TQStyle::SFlags sflags = gtkToTQtStyleFlags(engine, state, TQT3WT_TQGroupBox); if (gtkShadowType == GTK_SHADOW_NONE) { lineWidth = 0; midLineWidth = 0; } else if (gtkShadowType == GTK_SHADOW_IN) { lineWidth = groupBoxLineWidth; midLineWidth = 0; sflags = sflags | TQStyle::Style_Sunken; } else if (gtkShadowType == GTK_SHADOW_OUT) { lineWidth = groupBoxLineWidth; midLineWidth = 0; sflags = sflags | TQStyle::Style_Raised; } else if (gtkShadowType == GTK_SHADOW_ETCHED_IN) { lineWidth = groupBoxLineWidth; midLineWidth = groupBoxLineWidth; sflags = sflags | TQStyle::Style_Sunken; } else if (gtkShadowType == GTK_SHADOW_ETCHED_OUT) { lineWidth = groupBoxLineWidth; midLineWidth = groupBoxLineWidth; sflags = sflags | TQStyle::Style_Raised; } TQStyleOption opt(lineWidth, midLineWidth); // Draw background TQBrush brush = objectPalette.brush(gtkToTQPaletteColorGroup(engine, state), TQColorGroup::Background); DRAW_FILLED_RECTANGLE_OVER_ENTIRE_AREA(p, brush) // Draw group box tqApp->style().drawPrimitive(TQStyle::PE_PanelGroupBox, &p, boundingRect, gtkToTQtColorGroup(engine, state), sflags, opt); // Draw background behind groupbox label DRAW_FILLED_RECTANGLE_OVER_SPECIFIC_AREA(p, brush, xy0_gap, x, (xy1_gap-xy0_gap), (height/2)) } p.end(); } 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); TQStringList objectTypes; objectTypes.append(TQTABWIDGET_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) // Draw tab frame tqApp->style().drawPrimitive(TQStyle::PE_PanelTabWidget, &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) | ((ceData.orientation == TQt::Horizontal)?TQStyle::Style_Horizontal:TQStyle::Style_Default)); } p.end(); } static void tdegtk_draw_spinbutton_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,128,255,0); p.end(); } static void tdegtk_draw_spinbutton_frame (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,128,255,128); p.end(); } 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; }