view mde/gui/widget/Widget.d @ 34:6b4116e6355c

Work on the Gui: some of the framework for drag & drop. Also made Window an IWidget. Implemented getWidget(x,y) to find the widget under this location for IWidgets (but not Gui). Made Window an IWidget and made it work a little more similarly to widgets. Implemented callbacks on the Gui for mouse events (enabling drag & drop, etc.). committer: Diggory Hardy <diggory.hardy@gmail.com>
author Diggory Hardy <diggory.hardy@gmail.com>
date Fri, 02 May 2008 16:03:52 +0100
parents 316b0230a849
children 57d000574d75
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/>. */

/// GUI Widget module.
module mde.gui.widget.Widget;

public import mde.gui.widget.Ifaces;
import mde.gui.IGui;
import mde.gui.exception;

import gl = mde.gl.basic;

import tango.io.Stdout;

/** A base widget class. Widgets need not inherit this (they only need implement IWidget), but this
* class provides a useful basic implementation for widgets.
*
* Do not use directly (i.e. only for inheriting from).
*/
class Widget : IWidget
{
    /** Minimum size is zero. */
    void getMinimumSize (out int w, out int h) {}   // w,h initialised to 0
    /** Current size. */
    void getCurrentSize (out int w, out int h) {
        w = this.w;
        h = this.h;
    }
    
    void setPosition (int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    /** Return self, since we don't have child widgets and the method wouldn't have been called
    * unless the location was over us. Valid for all widgets without children. */
    IWidget getWidget (int,int) {
        return this;
    }
    
    /** Dummy event method (widget doesn't respond to events) */
    void clickEvent (ushort cx, ushort cy, ubyte b, bool state) {}
    
    /** Basic draw method: draw the background (all widgets should do this) */
    void draw () {
        window.renderer.drawWidgetBack (x,y, w,h);
    }
    
protected:
    IWindow window;         // the enclosing window
    int x, y;               // position
    int w, h;               // size
}

//BEGIN Widgets
/// Draws a box. That's it.
class BoxWidget : Widget
{
    this (IWindow wind, IWidget, int[] data) {
        if (data.length != 2) throw new WidgetDataException;
        
        window = wind;
        
        w = data[0];
        h = data[1];
    }
    void draw () {
        gl.setColor(1f,0f,0f);
        window.renderer.drawBox (x,y, w,h);
    }
}

/// First interactible widget
class ButtonWidget : Widget
{
    bool pushed = false;    // true if button is pushed in (visually)
    // pushed is not the same as the button being clicked but not yet released.
    // it is whether the mouse is over the button after being clicked.
    
    this (IWindow wind, IWidget, int[] data) {
        if (data.length != 2) throw new WidgetDataException;
        
        window = wind;
        
        w = data[0];
        h = data[1];
    }
    
    void draw () {
        if (pushed)
            gl.setColor (1f, 0f, 1f);
        else
            gl.setColor (.6f, 0f, .6f);
        window.renderer.drawBox (x,y, w,h);
    }
    
    void getMinimumSize (out int w, out int h) {
        w = this.w; // button is not resizable
        h = this.h;
    }
    
    void clickEvent (ushort, ushort, ubyte b, bool state) {
        if (b == 1 && state == true) {
            pushed = true;
            window.gui.addClickCallback (&clickWhileHeld);
            window.gui.addMotionCallback (&motionWhileHeld);
        }
    }
    // Called when a mouse motion/click event occurs while (held == true)
    void clickWhileHeld (ushort cx, ushort cy, ubyte b, bool state) {
        if (cx >= x && cx < x+w && cy >= y && cy < y+h) // button event
            Stdout ("Button clicked!").newline;
        
        pushed = false;
        window.gui.removeCallbacks (cast(void*) this);
    }
    void motionWhileHeld (ushort cx, ushort cy) {
        if (cx >= x && cx < x+w && cy >= y && cy < y+h) pushed = true;
        else pushed = false;
    }
}
//END Widgets