view mde/gui/renderer/IRenderer.d @ 147:075705ad664a

Added a border widget.
author Diggory Hardy <diggory.hardy@gmail.com>
date Wed, 11 Feb 2009 13:02:30 +0000
parents 2ac3e0012788
children
line wrap: on
line source

/* LICENSE BLOCK
Part of mde: a Modular D game-oriented Engine
Copyright © 2007-2008 Diggory Hardy

This program is free software: you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation, either
version 2 of the License, or (at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>. */

/** Interface for the renderer. This is planned to replace decoration.d */
module mde.gui.renderer.IRenderer;

public import mde.gui.types;
import mde.font.font;

/** Interface for renderers.
*
* Renderers provide unified drawing methods for widget, e.g. to draw a window
* background, a frame, or a button.
* 
* A theme could be hard-coded into a renderer, or use a texture set and/or
* scripting with a more flexible renderer. There's currently no support for
* per-widget theming, although it shouldn't be too hard (e.g. if widgets get a
* renderer from their parent instead of the manager).
* 
* The renderer interface could be improved by using more objects and interfaces
* (e.g. with a generic drawable interface for getting dimensions and drawing),
* but requiring more class objects seems excessive and structs don't support
* interfaces in D1. */
interface IRenderer
{
    //BEGIN Types
    /** For floating widget borders. Like TextAdapter above, could be more flexible. */
    struct Border {
        /** Border type.
         * 
         * No border, small non-functional border, movement only border, resize only border, or
         * full border. */
        enum BTYPE : int {
            NONE = 0, SMALL = 1, LARGE = 2, MOVE = 4, RESIZE = 8, BOTH = MOVE | RESIZE
        }
        /** Which edges of a window are being resized.
         *
         * E.g. X1 == left, X2 | Y1 == right and top. */
        enum RESIZE : int {
            NONE = 0x0, X1 = 0x1, X2 = 0x2, Y1 = 0x4, Y2 = 0x8
        }
        
        wdim x1,x2;     /// First and second (lef & right) horizontal borders
        wdim y1,y2;     /// First and second vertical borders
        RESIZE capability;      /// Which resizes are possible.
        
        void opAddAssign (Border d) {
            x1 += d.x1;
            x2 += d.x2;
            y1 += d.y1;
            y2 += d.y2;
        }
        
        /** Used to tell if a click on a window's border is for resizing or moving.
         *
         * Depends on setSizable's parameters.
         *
         * Params:
         *   cx =
         *   cy = click coordinates relative to window border
         *   w  =
         *   h  = window size
         *
         * Returns:
         *   RESIZE = Describes whether the click resizes or moves the widget. */
        RESIZE getResize (wdim cx, wdim cy, wdim w, wdim h) {
            RESIZE r = RESIZE.NONE;
            if (cx + cy < x1 + y1)
                r = RESIZE.X1 | RESIZE.Y1;
            else if (cx + h - cy < x1 + y2)
                r = RESIZE.X1 | RESIZE.Y2;
            else if (w - cx + cy < x2 + y1)
                r = RESIZE.X2 | RESIZE.Y1;
            else if (w - cx + h - cy < x2 + y2)
                r = RESIZE.X2 | RESIZE.Y2;
            return r & capability;
        }
    }
    
    /** For drawing text - one instance per string.
     *
     * NOTE: currently inflexible. Could use (function) pointers, class interfaces or struct
     * interfaces when available to allow flexibility. */
    struct TextAdapter {
	char[] text () {
	    return content;
	}
        void text (char[] str) {
            content = str;
	    textCache.cacheVer = -1;	// force update
        }
	
	void colour (int colour = 0xFFFFFF) {
	    colour_ = Colour (colour);
	}
	
	/** If not size_t.max, an edit marker is drawn before character index. */
	void index (size_t index = size_t.max) {
	    index_ = index;
	}
        /** Set the edit index for a click at x.
         *
         * TODO: this uses the left edge of the cached bitmap to compare against; it should
         * probably use the glyph position. The font system needs some redesigning anyway. */
        size_t setIndex (wdrel x) {
            foreach (i,ch; textCache.chars)
                if (x < ch.xPos) {
                    index_ = i;
                    goto gotIndex;
                }
            index_ = textCache.chars.length;
            gotIndex:
            return index_;
        }
        
        void getDimensions (out wdsize w, out wdsize h) {
            font.updateBlock (content, textCache);
            w = cast(wdim) textCache.w;
            h = cast(wdim) textCache.h;
        }
        
        void draw (wdabs x, wdabs y) {
            font.textBlock (x,y, content, textCache, colour_, index_);
        }
        
        char[] content;
        TextBlock textCache;
	size_t index_;
        Colour colour_;
        FontStyle font;
    }
    //END Types
    
    //BEGIN Methods
    /** Returns a Border containing dimensions.
     *
     * Params:
     *	type	= Flags from BTYPE describing whether the border allows resizing and moving and
     *		its size. */
    Border getBorder (Border.BTYPE type, bool wSizable, bool hSizable);
    
    /** Return the renderer's between-widget spacing (for layout widgets). */
    wdim layoutSpacing ();
    
    /** Restrict following draw operations to given box.
     *
     * Restrict "pushes" a restriction onto a stack; relax must be called afterwards to "pop" the
     * restriction. */
    void restrict (wdim x, wdim y, wdim w, wdim h);
    void relax ();      /// ditto
    
    /** Draw a border. */
    void drawBorder (Border* border, wdim x, wdim y, wdim w, wdim h);
    
    /** Draw vertical and horizontal spacers.
     *
     * x,y and w,h are the position and size of the grid containing spacers.
     * 
     * For each col in cols, spacers should be drawn in the rectangle
     * [x+col-layoutSpacing,x+col)*[y,y+h), and similarly for rows. */
    void drawSpacers (wdabs x, wdabs y, wdsize w, wdsize h, wdims cols, wdims rows);
    
    /** Draws a widget background. Usually doesn't do anything since backgrounds are transparent.
     *
     * It used to be required for all widgets to do this, but I lapsed since mostly it's unused. */
    void drawWidgetBack (wdim x, wdim y, wdim w, wdim h);
    
    /** Draws a blank widget (temporary) */
    void drawBlank (wdim x, wdim y, wdim w, wdim h);
    
    /** Draws a button frame, in if pushed == true. */
    void drawButton (wdim x, wdim y, wdim w, wdim h, bool pushed);
    
    /** Toggle buttons.
     *
     * These have a fixed size which getToggleSize returns. */
    wdimPair getToggleSize ();
    void drawToggle (wdim x, wdim y, bool state, bool pushed);  /// ditto
    
    /** Slider / progress bar.
     *
     * Width is resizable. */
    wdimPair getSliderSize ();
    void drawSlider (wdim x, wdim y, wdim w, double proportion);
    
    /** Get a TextAdapter to draw some text.
     *
     * If no colour is passes, a default is used (white). */
    TextAdapter getAdapter (int colour = 0xFFFFFF);
    //END Methods
}