view mde/gui/widget/Widget.d @ 45:0fd51d2c6c8a

Several changes to resising windows and layout widgets. This commit still has some bugs. Moved the implementable widgets from mde.gui.widget.Widget to miscWidgets, leaving base widgets in Widget. Rewrote some of GridLayoutWidget's implementation. Made many operations general to work for either columns or rows. Some optimisations were intended but ended up being removed due to problems. Allowed layout's to resize from either direction (only with window resizes). committer: Diggory Hardy <diggory.hardy@gmail.com>
author Diggory Hardy <diggory.hardy@gmail.com>
date Thu, 22 May 2008 11:34:09 +0100
parents 07bd1a09e161
children 03fa79a48c48
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.
 *
 * This module contains some base widget classes suitable for widget classes to inherit. However,
 * inheriting one of them is by no means necessary for a widget so long as the IWidget interface is
 * implemented. */
module mde.gui.widget.Widget;

public import mde.gui.widget.Ifaces;
import mde.gui.renderer.IRenderer;

/** An abstract base widget class.
*
* This abstract class, and the more concrete FixedWidget and ScalableWidget classes provides a
* useful basic implementation for widgets. Widgets need not inherit these (they only need implement
* IWidget); they are simply provided for convenience and to promote code reuse. */
abstract class Widget : IWidget
{
//BEGIN Load and save
    // Base this(). All widgets must check data.length is correct before calling this method.
    this (IWindow wind, int[] data) {
        window = wind;
        widgetType = data[0];
    }
    
    // Most widgets don't need to do adjustments based on mutable data, however they usually do
    // still need to set their size.
    int[] adjust (int[] data) {
        setSize (0,0,true,true);
        return data;
    }
    
    // Widget type should always be the first value. Any widget using extra creation data will need
    // to reimplemnt this method.
    int[] getCreationData () {
        return [widgetType];
    }
    // Most widgets don't use mutable data.
    int[] getMutableData () {
        return [];
    }
//END Load and save
    
//BEGIN Size and position
    bool isWSizable () {    return false;   }
    bool isHSizable () {    return false;   }
    
    /* Return minimal/fixed size. */
    void getMinimalSize (out int a, out int b) {
        a = mw;
        b = mh;
    }
    
    void getCurrentSize (out int cw, out int ch) {
        cw = w;
        ch = h;
    }
    
    /* Set size: minimal size is (mw,mh). Note that both resizable and fixed widgets should allow
     * enlarging, so in both cases this is a correct implementation. */
    void setSize (int nw, int nh, bool, bool) {
        w = (nw >= mw ? nw : mw);
        h = (nh >= mh ? nh : mh);
    }
    
    void setPosition (int nx, int ny) {
        x = nx;
        y = ny;
    }
//END Size and position
    
//BEGIN Events
    /* This method is only called when the location is over this widget; hence for all widgets
     * without children this method is valid. */
    IWidget getWidget (int,int) {
        return this;
    }
    
    /* Dummy event method (suitable for all widgets which don't respond to events). */
    void clickEvent (ushort cx, ushort cy, ubyte b, bool state) {}
//END Events
    
    /* Basic draw method: draw the background (all widgets should do this). */
    void draw () {
        window.renderer.drawWidgetBack (x,y, w,h);
    }
    
protected:
    final int widgetType;	// the type (stored for saving)
    IWindow window;		// the enclosing window
    int x, y;			// position
    int w, h;			// size
    int mw = 0, mh = 0;		// minimal or fixed size, depending on whether the widget is
    				// resizible; both types of widgets should actually be expandable.
}

/** A base for fixed-size widgets taking their size from the creation data. */
class FixedWidget : Widget {
    // Check data.length is at least 3 before calling!
    this (IWindow wind, int[] data) {
        mw = data[1];
        mh = data[2];
        super (wind, data);
        w = mw;
        h = mh;
    }
    
    int[] getCreationData () {
        return [widgetType, mw, mh];
    }
}
/** A base for resizable widgets. */
class SizableWidget : Widget {
    // Check data.length is at least 1 before calling!
    this (IWindow wind, int[] data) {
        super (wind, data);
    }
    
    bool isWSizable () {    return true;    }
    bool isHSizable () {    return true;    }
}