blob: 8c3c01f9fd41b9567f7b283911d12aa40c6485fb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.internal.theme;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.cairo.*;
import org.eclipse.swt.internal.gtk.*;
public class DrawData {
public int style;
public int[] state;
public Rectangle clientArea;
/** Part states */
public static final int SELECTED = 1 << 1;
public static final int FOCUSED = 1 << 2;
public static final int PRESSED = 1 << 3;
public static final int ACTIVE = 1 << 4;
public static final int DISABLED = 1 << 5;
public static final int HOT = 1 << 6;
public static final int DEFAULTED = 1 << 7;
public static final int GRAYED = 1 << 8;
/** Text and Image drawing flags */
public static final int DRAW_LEFT = 1 << 4;
public static final int DRAW_TOP = 1 << 5;
public static final int DRAW_RIGHT = 1 << 6;
public static final int DRAW_BOTTOM = 1 << 7;
public static final int DRAW_HCENTER = 1 << 8;
public static final int DRAW_VCENTER = 1 << 9;
/** Widget parts */
public static final int WIDGET_NOWHERE = -1;
public static final int WIDGET_WHOLE = 0;
/** Scrollbar parts */
public static final int SCROLLBAR_UP_ARROW = 1;
public static final int SCROLLBAR_DOWN_ARROW = 2;
public static final int SCROLLBAR_LEFT_ARROW = SCROLLBAR_UP_ARROW;
public static final int SCROLLBAR_RIGHT_ARROW = SCROLLBAR_DOWN_ARROW;
public static final int SCROLLBAR_UP_TRACK = 3;
public static final int SCROLLBAR_DOWN_TRACK = 4;
public static final int SCROLLBAR_LEFT_TRACK = SCROLLBAR_UP_TRACK;
public static final int SCROLLBAR_RIGHT_TRACK = SCROLLBAR_DOWN_TRACK;
public static final int SCROLLBAR_THUMB = 5;
/** Scale parts */
public static final int SCALE_UP_TRACK = 1;
public static final int SCALE_LEFT_TRACK = SCALE_UP_TRACK;
public static final int SCALE_DOWN_TRACK = 2;
public static final int SCALE_RIGHT_TRACK = SCALE_DOWN_TRACK;
public static final int SCALE_THUMB = 3;
/** ToolItem parts */
public static final int TOOLITEM_ARROW = 1;
/** Combo parts */
public static final int COMBO_ARROW = 1;
public DrawData() {
state = new int[1];
}
Rectangle computeTrim(Theme theme, GC gc) {
return new Rectangle(clientArea.x, clientArea.y, clientArea.width, clientArea.height);
}
void draw(Theme theme, GC gc, Rectangle bounds) {
}
void drawImage(Theme theme, Image image, GC gc, Rectangle bounds) {
long /*int*/ drawable = gc.getGCData().drawable;
Rectangle rect = image.getBounds();
int state_type = getStateType(DrawData.WIDGET_WHOLE);
if (state_type == OS.GTK_STATE_NORMAL) {
gc.drawImage(image, 0, 0, rect.width, rect.height, bounds.x, bounds.y, bounds.width, bounds.height);
} else {
long /*int*/ pixbuf = ImageList.createPixbuf(image);
long /*int*/ source = OS.gtk_icon_source_new();
if (source != 0) {
OS.gtk_icon_source_set_pixbuf(source, pixbuf);
//TODO - always uses buttonHandle
long /*int*/ buttonHandle = theme.buttonHandle;
long /*int*/ gtkStyle = gtk_widget_get_style (buttonHandle);
theme.transferClipping(gc, gtkStyle);
long /*int*/ rendered = OS.gtk_style_render_icon(gtkStyle, source, OS.GTK_TEXT_DIR_NONE, state_type, -1, buttonHandle, null);
OS.g_object_unref(pixbuf);
//TODO - stretching
if (rendered != 0) {
if (OS.USE_CAIRO) {
long /*int*/ cairo = OS.gdk_cairo_create (drawable);
OS.gdk_cairo_set_source_pixbuf (cairo, gc.handle, 0, 0);
Cairo.cairo_rectangle (cairo,bounds.x,bounds.y,bounds.width,bounds.height);
Cairo.cairo_fill(cairo);
Cairo.cairo_destroy(cairo);
} else {
OS.gdk_draw_pixbuf(drawable, gc.handle, rendered, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height, OS.GDK_RGB_DITHER_NORMAL, 0, 0);
}
OS.g_object_unref(rendered);
}
OS.gtk_icon_source_free(source);
}
}
}
void drawText(Theme theme, String text, int flags, GC gc, Rectangle bounds) {
long /*int*/ widget = getTextHandle(theme);
long /*int*/ gtkStyle = gtk_widget_get_style(widget);
long /*int*/ drawable = gc.getGCData().drawable;
theme.transferClipping (gc, gtkStyle);
byte[] buffer = Converter.wcsToMbcs(text, true);
long /*int*/ layout = OS.gtk_widget_create_pango_layout(widget, buffer);
int[] width = new int[1], height = new int[1];
OS.pango_layout_get_pixel_size(layout, width, height);
OS.pango_layout_set_width(layout, bounds.width * OS.PANGO_SCALE);
int x = bounds.x;
int y = bounds.y;
if ((flags & DrawData.DRAW_LEFT) != 0) {
OS.pango_layout_set_alignment(layout, OS.PANGO_ALIGN_LEFT);
}
if ((flags & DrawData.DRAW_HCENTER) != 0) {
OS.pango_layout_set_alignment(layout, OS.PANGO_ALIGN_CENTER);
}
if ((flags & DrawData.DRAW_RIGHT) != 0) {
OS.pango_layout_set_alignment(layout, OS.PANGO_ALIGN_RIGHT);
}
if ((flags & DrawData.DRAW_VCENTER) != 0) {
y += (bounds.height - height[0]) / 2;
}
if ((flags & DrawData.DRAW_BOTTOM) != 0) {
y += bounds.height - height[0];
}
int state_type = getStateType(DrawData.WIDGET_WHOLE);
byte[] detail = Converter.wcsToMbcs("label", true);
gtk_render_layout(gtkStyle, drawable, state_type, false, null, widget, detail, x, y, layout);
OS.g_object_unref(layout);
}
Rectangle getBounds(int part, Rectangle bounds) {
return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
}
int getStateType(int part) {
int state = this.state[part];
int state_type = OS.GTK_STATE_NORMAL;
if ((state & DrawData.DISABLED) != 0) {
state_type = OS.GTK_STATE_INSENSITIVE;
} else {
if ((state & DrawData.SELECTED) != 0) state_type = OS.GTK_STATE_ACTIVE;
if ((state & DrawData.HOT) != 0) {
if ((state & DrawData.PRESSED) != 0) {
state_type = OS.GTK_STATE_ACTIVE;
} else {
state_type = OS.GTK_STATE_PRELIGHT;
}
}
}
return state_type;
}
long /*int*/ getTextHandle(Theme theme) {
return theme.labelHandle;
}
int hit(Theme theme, Point position, Rectangle bounds) {
return -1;
}
Rectangle measureText(Theme theme, String text, int flags, GC gc, Rectangle bounds) {
long /*int*/ widget = getTextHandle(theme);
byte[] buffer = Converter.wcsToMbcs(text, true);
long /*int*/ layout = OS.gtk_widget_create_pango_layout(widget, buffer);
if (bounds != null) OS.pango_layout_set_width(layout, bounds.width);
if ((flags & DrawData.DRAW_LEFT) != 0) {
OS.pango_layout_set_alignment(layout, OS.PANGO_ALIGN_LEFT);
}
if ((flags & DrawData.DRAW_HCENTER) != 0) {
OS.pango_layout_set_alignment(layout, OS.PANGO_ALIGN_CENTER);
}
if ((flags & DrawData.DRAW_RIGHT) != 0) {
OS.pango_layout_set_alignment(layout, OS.PANGO_ALIGN_RIGHT);
}
int[] width = new int[1], height = new int[1];
OS.pango_layout_get_pixel_size(layout, width, height);
OS.g_object_unref(layout);
return new Rectangle(0, 0, width[0], height[0]);
}
void gtk_render_frame (long /*int*/ style, long /*int*/ window, int state_type, int shadow_type, GdkRectangle area, long /*int*/ widget, byte[] detail, int x , int y, int width, int height) {
if (OS.GTK3) {
OS.gtk_render_frame (style, window, x, y, width, height);
} else {
OS.gtk_paint_flat_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
}
}
void gtk_render_box (long /*int*/ style, long /*int*/ window, int state_type, int shadow_type, GdkRectangle area, long /*int*/ widget, byte[] detail, int x , int y, int width, int height) {
if (OS.GTK3) {
OS.gtk_render_frame (style, window, x, y, width, height);
OS.gtk_render_background (style, window, x, y, width, height);
} else {
OS.gtk_paint_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
}
}
void gtk_render_layout (long /*int*/ style, long /*int*/ window, int state_type, boolean use_text, GdkRectangle area, long /*int*/ widget, byte[] detail, int x , int y, long /*int*/ layout) {
if (OS.GTK3) {
OS.gtk_render_layout (style, window, x, y, layout);
} else {
OS.gtk_paint_layout (style, window, state_type, use_text, area, widget, detail, x , y, layout);
}
}
void gtk_render_focus (long /*int*/ style, long /*int*/ window, int state_type, GdkRectangle area, long /*int*/ widget, byte[] detail, int x , int y, int width, int height) {
if (OS.GTK3) {
OS.gtk_style_context_save (style);
OS.gtk_style_context_set_state (style, OS.gtk_widget_get_state_flags (widget));
Cairo.cairo_save (window);
OS.gtk_render_focus(style, window, x, y, width, height);
Cairo.cairo_restore (window);
OS.gtk_style_context_restore (style);
} else {
OS.gtk_paint_focus (style, window, state_type, area, widget, detail, x, y, width, height);
}
}
void gtk_render_arrow(long /*int*/ style, long /*int*/ window, int state_type, int shadow_type, GdkRectangle area, long /*int*/ widget, byte[] detail, int arrow_type, boolean fill, int x, int y, int width, int height) {
if (OS.GTK3) {
double angle = 0;
double size = 0;
switch (arrow_type) {
case OS.GTK_ARROW_UP:
angle = 0;
size = width;
break;
case OS.GTK_ARROW_RIGHT:
angle = Math.PI/2;
size = height;
break;
case OS.GTK_ARROW_DOWN:
angle = Math.PI;
size = width;
break;
case OS.GTK_ARROW_LEFT:
angle = (3 * Math.PI)/2;
size = height;
break;
}
OS.gtk_style_context_set_state(style, state_type);
OS.gtk_render_background(style, window, x, y, width, height);
OS.gtk_render_frame (style, window, x, y, width, height);
OS.gtk_render_arrow(style, window, angle, x, y, size);
} else {
OS.gtk_paint_arrow(style, window, state_type, shadow_type, area, widget, detail, arrow_type, fill, x, y, width, height);
}
}
long /*int*/ gtk_widget_get_style(long /*int*/ handle) {
return OS.GTK3 ? OS.gtk_widget_get_style_context(handle) : OS.gtk_widget_get_style(handle);
}
}