/*
 * Java-Gnome Bindings Library
 *
 * Copyright 1998-2004 the Java-Gnome Team, all rights reserved.
 *
 * The Java-Gnome bindings library is free software distributed under
 * the terms of the GNU Library General Public License version 2.
 */

package org.gnu.gdk;
import org.gnu.glib.GObject;
import org.gnu.glib.Handle;
import org.gnu.glib.Type;
import org.gnu.pango.Font;
import org.gnu.pango.GlyphString;
import org.gnu.pango.Layout;
import org.gnu.pango.LayoutLine;

/**
 * Provides support for drawing points, lines, arcs, and text onto what we
 * call 'drawables'.  Drawables, as the name suggests, are things which support
 * drawing onto them and are either org.gnu.gdk.Window or org.gnu.gdk.Pixmap
 * objects.
 */
 
public class Drawable extends GObject 
{
	
	public Drawable(Handle handle){
		super(handle);
	}
	
	/**
     *  Returns the size of the Drawable. 
	 */
    public Dimension getSize(){
		int width[]=new int[1];
		int height[]=new int[1];
		Drawable.gdk_drawable_get_size(getHandle(),width,height);
		return new Dimension(width[0],height[0]);
	}
	
	/**
     * Sets the Colormap associated with the Drawable.  Normally this happens
     * automatically when the Drawable is created.   
     * @param cmap
	 */
    public void setColormap(Colormap cmap){
		Drawable.gdk_drawable_set_colormap(getHandle(),cmap.getHandle());
	}
	
    /**
     * Gets the Colormap for the Drawable if one is set; returns null
     * otherwise.
     */
	public Colormap getColormap(){
	    Handle hndl = gdk_drawable_get_colormap(getHandle());
        if (null == hndl)
            return null;
		GObject obj = getGObjectFromHandle(hndl);
		if (null != obj)
			return (Colormap)obj;
		return new Colormap(hndl);
	}
	
	/**
     * Gets the Visual describing the pixel format of this Drawable. 
	 */
    public Visual getVisual(){
	    Handle hndl = gdk_drawable_get_visual(getHandle());
		GObject obj = getGObjectFromHandle(hndl);
		if (null != obj)
			return (Visual)obj;
		return new Visual(hndl);
	}
	
	
	/**
     * Obtains the bit depth of the Drawable, this is, the number
     * of bits that make up a pixel. 
	 */
    public int getDepth(){
		return Drawable.gdk_drawable_get_depth(getHandle());
	}
	
    /**
     * Obtains the pixels from a server-side Drawable as a client-side Image.
     * The format of the Image depends on the Visual for the current display
     * which makes manipulating Image extremely difficult.
     * @param x
     * @param y
     * @param width
     * @param height
     */
	public Image getImage(int x, int y, int width, int height){
	    Handle hndl = gdk_drawable_get_image(getHandle(),x,y,width,height);
		GObject obj = getGObjectFromHandle(hndl);
		if (null != obj)
			return (Image)obj;
		return new Image(hndl);
	}
	
	/**
     * Computes the Region of a Drawable that potentially can be written to
     * by drawing primitives.  This Region will not take into account the
     * clip region for the GC, and may also not take into account other factors
     * such as if the Window is obscured by other Windows.   
	 */
    public Region getClipRegion(){
		return new Region(Drawable.gdk_drawable_get_clip_region(getHandle()));
	}
	
    /**
     * Computes the Region of a Drawable that is potentially visible.
     */
	public Region getVisibleRegion(){
		return new Region(Drawable.gdk_drawable_get_visible_region(getHandle()));
	}
	
	public void drawRGBImage(GC gc, int x, int y, int width, int height, RgbDither dither, byte[] buffer, int rowStride) {
		gdk_draw_rgb_image(getHandle(), gc.getHandle(), x, y, width, height, dither.getValue(), buffer, rowStride);
	}

	public void drawRGBImage(int x, int y, int width, int height, RgbDither dither, byte[] buffer, int rowStride) {
		drawRGBImage(GC.getDefaultGC(this), x, y, width, height, dither, buffer, rowStride);
	}

	public void drawRGBImageDitherAlign(GC gc, int x, int y, int width, int height, RgbDither dither, byte[] buffer, int rowStride, int xdith, int ydith) {
		gdk_draw_rgb_image_dithalign(getHandle(), gc.getHandle(), x, y, width, height, dither.getValue(), buffer, rowStride, xdith, ydith);
	}

	public void drawRGBImageDitherAlign(int x, int y, int width, int height, RgbDither dither, byte[] buffer, int rowStride, int xdith, int ydith) {
		drawRGBImageDitherAlign(GC.getDefaultGC(this), x, y, width, height, dither, buffer, rowStride, xdith, ydith);
	}

	public void drawRGB32Image(GC gc, int x, int y, int width, int height, RgbDither dither, byte[] buffer, int rowStride) {
		gdk_draw_rgb_32_image(getHandle(), gc.getHandle(), x, y, width, height, dither.getValue(), buffer, rowStride);
	}

	public void drawRGB32Image(int x, int y, int width, int height, RgbDither dither, byte[] buffer, int rowStride) {
		drawRGB32Image(GC.getDefaultGC(this), x, y, width, height, dither, buffer, rowStride);
	}

	public void drawRGB32ImageDitherAlign(GC gc, int x, int y, int width, int height, RgbDither dither, byte[] buffer, int rowStride, int xdith, int ydith) {
		gdk_draw_rgb_32_image_dithalign(getHandle(), gc.getHandle(), x, y, width, height, dither.getValue(), buffer, rowStride, xdith, ydith);
	}

	public void drawRGB32ImageDitherAlign(int x, int y, int width, int height, RgbDither dither, byte[] buffer, int rowStride, int xdith, int ydith) {
		drawRGB32ImageDitherAlign(GC.getDefaultGC(this), x, y, width, height, dither, buffer, rowStride, xdith, ydith);
	}

	public void drawGrayImage(GC gc, int x, int y, int width, int height, RgbDither dither, byte[] buffer, int rowStride) {
		gdk_draw_gray_image(getHandle(), gc.getHandle(), x, y, width, height, dither.getValue(), buffer, rowStride);
	}

	public void drawGrayImage(int x, int y, int width, int height, RgbDither dither, byte[] buffer, int rowStride) {
		drawGrayImage(GC.getDefaultGC(this), x, y, width, height, dither, buffer, rowStride);
	}

	public void drawIndexedImage(GC gc, int x, int y, int width, int height, RgbDither dither, byte[] buffer, int rowStride, RgbCmap cmap) {
		gdk_draw_indexed_image(getHandle(), gc.getHandle(), x, y, width, height, dither.getValue(), buffer, rowStride, cmap.getHandle());
	}

	public void drawIndexedImage(int x, int y, int width, int height, RgbDither dither, byte[] buffer, int rowStride, RgbCmap cmap) {
		drawIndexedImage(GC.getDefaultGC(this), x, y, width, height, dither, buffer, rowStride, cmap);
	}

	/**
     * Draws an outlined or filled polygon. 
     * @param gc
     * @param filled
     * @param points
	 */
    public void drawPolygon(GC gc, boolean filled, Point[] points) {
	    Handle[] hndls = new Handle[points.length];
		for (int i = 0; i < points.length; i++) {
			hndls[i] = points[i].getHandle();
		}
		gdk_draw_polygon(getHandle(), gc.getHandle(), filled, hndls);
	}
	
    /**
     * Convience method that draws an outlined or filled polygon
     * using the default GC.
     * @param filled
     * @param points
     */
    public void drawPolygon(boolean filled, Point[] points) {
    	drawPolygon(GC.getDefaultGC(this), filled, points);
	}
	
    /**
     * Copies the width x height region of the Drawable at coordinates
     * (xsrc,ysrc) to coordinates (xdest,ydest).
     * @param gc
     * @param src
     * @param xsrc
     * @param ysrc
     * @param xdest
     * @param ydest
     * @param width
     * @param height
     */
	public void drawDrawable(GC gc, Drawable src, int xsrc, int ysrc, int xdest, int ydest, int width, int height) {
		gdk_draw_drawable(getHandle(), gc.getHandle(), src.getHandle(), xsrc, ysrc, xdest, ydest, width, height);
	}
	
    /**
     * Convience method that copies the width x height region of 
     * the Drawable at coordinates (xsrc,ysrc) to coordinates 
     * (xdest,ydest) using the default GC.
     * @param src
     * @param xsrc
     * @param ysrc
     * @param xdest
     * @param ydest
     * @param width
     * @param height
     */
	public void drawDrawable(Drawable src, int xsrc, int ysrc, int xdest, int ydest, int width, int height) {
		drawDrawable(GC.getDefaultGC(this), src, xsrc, ysrc, xdest, ydest, width, height);
	}
	
    /**
     * Draw an Image onto this Drawable.  The depth of the Image must
     * match the depth of this Drawable.
     * @param gc
     * @param image
     * @param xsrc
     * @param ysrc
     * @param xdest
     * @param ydest
     * @param width
     * @param height
     */
	public void drawImage(GC gc, Image image, int xsrc, int ysrc, int xdest, int ydest, int width, int height) {
		gdk_draw_image(getHandle(), gc.getHandle(), image.getHandle(), xsrc, ysrc, xdest, ydest, width, height);
	}
	
    /**
     * Draw an Image onto this Drawable using the default GC.  
     * The depth of the Image must match the depth of this Drawable.
     * @param image
     * @param xsrc
     * @param ysrc
     * @param xdest
     * @param ydest
     * @param width
     * @param height
     */
	public void drawImage(Image image, int xsrc, int ysrc, int xdest, int ydest, int width, int height) {
		drawImage(GC.getDefaultGC(this), image, xsrc, ysrc, xdest, ydest, width, height);
	}
	
	/**
     * Draw a number of points using the forground color and other
     * attributes of the GC. 
     * @param gc
     * @param points
	 */
    public void drawPoints(GC gc, Point[] points) {
	    Handle[] hndls = new Handle[points.length];
		for (int i = 0; i < points.length; i++) {
			hndls[i] = points[i].getHandle();
		}
		gdk_draw_points(getHandle(), gc.getHandle(), hndls);
	}

	/**
     * Draw a number of points using the forground color and other
     * attributes of the default GC. 
     * @param points
	 */
    public void drawPoints(Point[] points) {
    	drawPoints(GC.getDefaultGC(this), points);
	}

    /**
     * Draw a number of unconnected lines.
     * @param gc
     * @param segments
     */
	public void drawSegments(GC gc, Segment[] segments) {
	    Handle[] hndls = new Handle[segments.length];
		for (int i = 0; i < segments.length; i++) {
			hndls[i] = segments[i].getHandle();
		}
		gdk_draw_segments(getHandle(), gc.getHandle(), hndls);
	}
	
    /**
     * Draw a number of unconnected lines using the default
     * GC.
     * @param segments
     */
	public void drawSegments(Segment[] segments) {
		drawSegments(GC.getDefaultGC(this), segments);
	}
	
	/**
     * Draw a series of lines connecting the given points.  The
     * way in which joins between lines are drawn is determined
     * by the CapStyle value in GC. 
     * @param gc
     * @param points
	 */
    public void drawLines(GC gc, Point[] points) {
	    Handle[] hndls = new Handle[points.length];
		for (int i = 0; i < points.length; i++) {
			hndls[i] = points[i].getHandle();
		}
		gdk_draw_lines(getHandle(), gc.getHandle(), hndls);
	}

	/**
     * Draw a series of lines connecting the given points.  The
     * way in which joins between lines are drawn is determined
     * by the CapStyle value in the default GC. 
     * @param points
	 */
    public void drawLines(Point[] points) {
    	drawLines(GC.getDefaultGC(this), points);
	}

	/**
     * This is a low-level function.  Normally, 99 percent of text rendering should
     * be down using drawLayout() instead.
     * <p>
     * A glyph is a single image in a font.  This method draws a
     * sequence of glyphs.
     * @param gc
     * @param font
     * @param x
     * @param y
     * @param glyphs
	 */
    public void drawGlyphs(GC gc, Font font, int x, int y, GlyphString glyphs) {
		gdk_draw_glyphs(getHandle(), gc.getHandle(), font.getHandle(), x, y, glyphs.getHandle());
	}

	/**
         * This is a low-level function.  Normally, 99 percent of text rendering should
         * be down using drawLayout() instead.
         * <p>
         * A glyph is a single image in a font.  This method draws a
         * sequence of glyphs.
         * @param font
         * @param x
         * @param y
         * @param glyphs
	 */
    public void drawGlyphs(Font font, int x, int y, GlyphString glyphs) {
    	drawGlyphs(GC.getDefaultGC(this), font, x, y, glyphs);
	}

    /**
     * Render a LayoutLine onto this Drawable.  
     * @param gc
     * @param x
     * @param y
     * @param line
     */
	public void drawLayoutLine(GC gc, int x, int y, LayoutLine line) {
		gdk_draw_layout_line(getHandle(), gc.getHandle(), x, y, line.getHandle());
	}

    /**
     * Render a LayoutLine onto this Drawable using the default GC.  
     * @param x
     * @param y
     * @param line
     */
	public void drawLayoutLine(int x, int y, LayoutLine line) {
		drawLayoutLine(GC.getDefaultGC(this), x, y, line);
	}

    /**
     * Render a Layout onto this Drawable.
     * @param gc
     * @param x
     * @param y
     * @param layout
     */
	public void drawLayout(GC gc, int x, int y, Layout layout) {
		gdk_draw_layout(getHandle(), gc.getHandle(), x, y, layout.getHandle());
	}

    /**
     * Render a Layout onto this Drawable using the default GC.
     * @param x
     * @param y
     * @param layout
     */
	public void drawLayout(int x, int y, Layout layout) {
		drawLayout(GC.getDefaultGC(this), x, y, layout);
	}

    /**
     * Render a LayoutLne onto this Drawable overriding the layout's normal
     * colors with the provided forground and background.
     * @param gc
     * @param x
     * @param y
     * @param line
     * @param foreground
     * @param background
     */
	public void drawLayoutLineWithColors(GC gc, int x, int y, LayoutLine line, Color foreground, Color background) {
		gdk_draw_layout_line_with_colors(getHandle(), gc.getHandle(), x, y, line.getHandle(), foreground.getHandle(), background.getHandle());
	}

    /**
     * Render a LayoutLne onto this Drawable overriding the layout's normal
     * colors with the provided forground and background and using the default
     * GC.
     * @param x
     * @param y
     * @param line
     * @param foreground
     * @param background
     */
	public void drawLayoutLineWithColors(int x, int y, LayoutLine line, Color foreground, Color background) {
		drawLayoutLineWithColors(GC.getDefaultGC(this), x, y, line, foreground, background);
	}

    /**
     * Render a Layout onto this Drawable overriding the layout's normal
     * colors with the provided forground and background.
     * @param gc
     * @param x
     * @param y
     * @param layout
     * @param foreground
     * @param background
     */
	public void drawLayoutWithColors(GC gc, int x, int y, Layout layout, Color foreground, Color background) {
		gdk_draw_layout_with_colors(getHandle(), gc.getHandle(), x, y, layout.getHandle(), foreground.getHandle(), background.getHandle());
	}
    
    /**
     * Render a Layout onto this Drawable overriding the layout's normal
     * colors with the provided forground and background using the
     * default GC.
     * @param x
     * @param y
     * @param layout
     * @param foreground
     * @param background
     */
	public void drawLayoutWithColors(int x, int y, Layout layout, Color foreground, Color background) {
		drawLayoutWithColors(GC.getDefaultGC(this), x, y, layout, foreground, background);
	}
    
    /**
     * Get the Display associated with the Drawable.
     */
    public Display getDisplay() {
        Handle hndl = gdk_drawable_get_display(getHandle());
        GObject obj = getGObjectFromHandle(hndl);
        if (null != obj)
            return (Display)obj;
        return new Display(hndl);
    }
    
    /**
     * Get the Screen associated with the Drawable.
     */
    public Screen getScreen() {
        Handle hndl = gdk_drawable_get_screen(getHandle());
        GObject obj = getGObjectFromHandle(hndl);
        if (null != obj)
            return (Screen)obj;
        return new Screen(hndl);
    }

    /**
     * Draw a point using the foreground color and other attributes
     * of the GC.
     * @param gc
     * @param x
     * @param y
     */
    public void drawPoint(GC gc, int x, int y) {
        gdk_draw_point(getHandle(), gc.getHandle(), x, y);
    }
    
    /**
     * Draw a point using the foreground color and other attributes
     * of the default GC.
     * @param x
     * @param y
     */
    public void drawPoint(int x, int y) {
    	drawPoint(GC.getDefaultGC(this), x, y);
    }
    
    /**
     * Draw a line using the foreground color and other attributes
     * of the GC.
     * @param gc
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     */
    public void drawLine(GC gc, int x1, int y1, int x2, int y2) {
        gdk_draw_line(getHandle(), gc.getHandle(), x1, y1, x2, y2);
    }

    /**
     * Draw a line using the foreground color and other attributes
     * of the default GC.
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     */
    public void drawLine(int x1, int y1, int x2, int y2) {
    	drawLine(GC.getDefaultGC(this), x1, y1, x2, y2);
    }

    /**
     * Render a rectangular portion of a Pixbuf to this Drawable.
     * @param gc
     * @param pixbuf
     * @param srcx
     * @param srcy
     * @param destx
     * @param desty
     * @param width
     * @param height
     * @param dither
     * @param xdither
     * @param ydither
     */
    public void drawPixbuf(GC gc, Pixbuf pixbuf, int srcx, int srcy, int destx, int desty, 
            int width, int height, RgbDither dither, int xdither, int ydither) {
        gdk_draw_pixbuf(getHandle(), gc.getHandle(), pixbuf.getHandle(), srcx, srcy, destx, desty,
                width, height, dither.getValue(), xdither, ydither);
    }

    /**
     * Render a rectangular portion of a Pixbuf to this Drawable.
     * @param pixbuf
     * @param srcx
     * @param srcy
     * @param destx
     * @param desty
     * @param width
     * @param height
     * @param dither
     * @param xdither
     * @param ydither
     */
    public void drawPixbuf(Pixbuf pixbuf, int srcx, int srcy, int destx, int desty, 
            int width, int height, RgbDither dither, int xdither, int ydither) {
    	drawPixbuf(GC.getDefaultGC(this), pixbuf, srcx, srcy, destx, desty,
                width, height, dither, xdither, ydither);
    }

    /**
     * Draws a rectangle outlined or filled using the forground color
     * and other attributes of the GC.
     * @param gc
     * @param filled
     * @param x
     * @param y
     * @param width
     * @param height
     */
    public void drawRectangle(GC gc, boolean filled, int x, int y, int width, int height) {
        gdk_draw_rectangle(getHandle(), gc.getHandle(), filled, x, y, width, height);
    }

    /**
     * Draws a rectangle outlined or filled using the forground color
     * and other attributes of the default GC.
     * @param filled
     * @param x
     * @param y
     * @param width
     * @param height
     */
    public void drawRectangle(boolean filled, int x, int y, int width, int height) {
    	drawRectangle(GC.getDefaultGC(this), filled, x, y, width, height);
    }

    /**
     * Draws an arc or a filled 'pie slice'.  The arc is defined by the 
     * bounding rectangle of the entire elipse, and the start and end
     * angles of the part of the elipse to be drawn.
     * @param gc
     * @param filled
     * @param x
     * @param y
     * @param width
     * @param height
     * @param angle1
     * @param angle2
     */
    public void drawArc(GC gc, boolean filled, int x, int y, int width, int height, int angle1, int angle2) {
        gdk_draw_arc(getHandle(), gc.getHandle(), filled, x, y, width, height, angle1, angle2);
    }

    /**
     * Draws an arc or a filled 'pie slice'.  The arc is defined by the 
     * bounding rectangle of the entire elipse, and the start and end
     * angles of the part of the elipse to be drawn.
     * @param filled
     * @param x
     * @param y
     * @param width
     * @param height
     * @param angle1
     * @param angle2
     */
    public void drawArc(boolean filled, int x, int y, int width, int height, int angle1, int angle2) {
    	drawArc(GC.getDefaultGC(this), filled, x, y, width, height, angle1, angle2);
    }

    /**
     * Retrieve the runtime type used by the GLib library.
     */
    public static Type getType() {
        return new Type(gdk_drawable_get_type());
    }
	
    /*
     * BEGINNING OF JNI CODE
     */
    native static final protected int gdk_drawable_get_type (); // ??? not in the api
    native static final protected Handle gdk_drawable_get_display(Handle drawable);
    native static final protected Handle gdk_drawable_get_screen(Handle drawable);
    native static final protected Handle gdk_drawable_get_visual (Handle drawable);
    native static final protected void gdk_drawable_set_colormap (Handle drawable, Handle colormap);
    native static final protected Handle gdk_drawable_get_colormap (Handle drawable);
    native static final protected int gdk_drawable_get_depth (Handle drawable);
    native static final protected void gdk_drawable_get_size (Handle drawable, int [] width, int[] height);
    native static final protected Handle gdk_drawable_get_clip_region (Handle drawable);
    native static final protected Handle gdk_drawable_get_visible_region (Handle drawable);
    native static final protected Handle gdk_drawable_get_image (Handle drawable, int x, int y, int width, int height);

    native static final protected void gdk_draw_point(Handle drawable, Handle gc, int x, int y);
    native static final protected void gdk_draw_points (Handle drawable, Handle gc, Handle [] points);
    native static final protected void gdk_draw_line(Handle drawable, Handle gc, int x1, int y1, int x2, int y2);
    native static final protected void gdk_draw_lines (Handle drawable, Handle gc, Handle[] points);
    native static final protected void gdk_draw_pixbuf(Handle drawable, Handle gc, Handle pixbuf, int srcx, int srcy, int destx, int desty, int width, int height, int dither, int xdith, int ydith);
    native static final protected void gdk_draw_segments (Handle drawable, Handle gc, Handle [] segments);
    native static final protected void gdk_draw_rectangle(Handle drawable, Handle gc, boolean filled, int x, int y, int width, int height);
    native static final protected void gdk_draw_arc(Handle drawable, Handle gc, boolean filled, int x, int y, int width, int height, int angle1, int angle2);
    native static final protected void gdk_draw_polygon (Handle drawable, Handle gc, boolean filled, Handle[] points);
    // need Trapezoid
    //native static final protected void gdk_draw_trapezoids(Handle drawable, Handle gc, Handle[] trapezoids);
    native static final protected void gdk_draw_glyphs (Handle drawable, Handle gc, Handle font, int x, int y, Handle glyphs);
    native static final protected void gdk_draw_layout_line (Handle drawable, Handle gc, int x, int y, Handle line);
    native static final protected void gdk_draw_layout_line_with_colors (Handle drawable, Handle gc, int x, int y, Handle line, Handle foreground, Handle background);
    native static final protected void gdk_draw_layout (Handle drawable, Handle gc, int x, int y, Handle layout);
    native static final protected void gdk_draw_layout_with_colors (Handle drawable, Handle gc, int x, int y, Handle layout, Handle foreground, Handle background);
    native static final protected void gdk_draw_drawable (Handle drawable, Handle gc, Handle src, int xsrc, int ysrc, int xdest, int ydest, int width, int height);
    native static final protected void gdk_draw_image (Handle drawable, Handle gc, Handle image, int xsrc, int ysrc, int xdest, int ydest, int width, int height);

    native static final protected void gdk_draw_rgb_image (Handle drawable, Handle gc, int x, int y, int width, int height, int dith, byte[] rgbBuf, int rowstride);
    native static final protected void gdk_draw_rgb_image_dithalign (Handle drawable, Handle gc, int x, int y, int width, int height, int dith, byte[] rgbBuf, int rowstride, int xDith, int yDith);
    native static final protected void gdk_draw_rgb_32_image (Handle drawable, Handle gc, int x, int y, int width, int height, int dith, byte[] rgbBuf, int rowstride);
    native static final protected void gdk_draw_rgb_32_image_dithalign (Handle drawable, Handle gc, int x, int y, int width, int height, int dith, byte[] rgbBuf, int rowstride, int xDith, int yDith);
    native static final protected void gdk_draw_gray_image (Handle drawable, Handle gc, int x, int y, int width, int height, int dith, byte[] rgbBuf, int rowstride);
    native static final protected void gdk_draw_indexed_image (Handle drawable, Handle gc, int x, int y, int width, int height, int dith, byte[] buf, int rowstride, Handle cmap);
    
    /*
     * END OF JNI CODE
     */
}
