view mde/gui/widget/miscContent.d @ 137:9f035cd139c6

BIG commit. Major change: old Options class is gone, all content values are loaded and saved automatically. All options updated to reflect this, some changed. Content restrutured a lot: New IContent module, Content module includes more functionality. New ContentLoader module to manage content loading/saving/translation. Translation module moved to content dir and cut down to reflect current usage. File format unchanged except renames: FontOptions -> Font, VideoOptions -> Screen. Font render mode and LCD filter options are now enums. GUI loading needs to create content (and set type for enums), but doesn't save/load value. Some setup of mainSchedule moved to mde.mainLoop. Content callbacks are called on content change now. ContentLists are set up implicitly from content symbols. Not as fast but much easier! Bug-fix in the new MTTagReader. Renamed MT *Reader maker functions to avoid confusion in paths.d. New mde.setup.logger module to allow logger setup before any other module's static this().
author Diggory Hardy <diggory.hardy@gmail.com>
date Sat, 07 Feb 2009 12:46:03 +0000
parents 9cff74f68b84
children c94ec5594449
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/>. */

/******************************************************************************
 * Widgets using content not organised into other modules.
 *****************************************************************************/
module mde.gui.widget.miscContent;

import mde.gui.widget.AParentWidget;
import mde.gui.exception;

import mde.content.AStringContent;

debug {
    import tango.util.log.Log : Log, Logger;
    private Logger logger;
    static this () {
	logger = Log.getLogger ("mde.gui.widget.miscContent");
    }
}

/// Editable boolean widget
class BoolContentWidget : AButtonWidget
{
    this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData, IContent c) {
	content = cast(BoolContent) c;
        if (content is null) throw new ContentException (this);
        super (mgr, parent, id);
        wdimPair s = mgr.renderer.getToggleSize;
        w = mw = s.x;
        h = mh = s.y;
    }
    
    override void draw () {
        mgr.renderer.drawToggle (x,y, content(), pushed);
    }
    
    override void activated () {
        content = !content();
    }
    
protected:
    BoolContent content;
}

/// A button connected to an EventContent
class ButtonContentWidget : AButtonWidget
{
    this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData, IContent c) {
	content = cast(Content) c;
        if (content is null) throw new ContentException (this);
        adapter = mgr.renderer.getAdapter ();
        super (mgr, parent, id);
    }
    
    override bool setup (uint n, uint flags) {
	if (!(flags & 3)) return false;	// string or renderer (and possibly font) changed
	adapter.text = content.toString(1);
	adapter.getDimensions (mw, mh);
	if (mw != w || mh != h) {
	    w = mw;
	    h = mh;
	}
	return true;
    }
    
    override void draw () {
	super.draw();
	adapter.draw (x,y);
    }
    
    override void activated () {
	content.endEvent;
    }
    
protected:
    IRenderer.TextAdapter adapter;
    Content content;
    int index;
}

/** A "tab" widget: it doesn't display the tabs, but shows one of a number of widgets dependant on
 * an EnumContent.
 *
 * Sizability is set once (currently true if any widget is sizable). Size is kept when switching
 * widgets if allowed (if this is large enough and resizable). */
class SwitchWidget : AParentWidget
{
    this (IWidgetManager mgr, IParentWidget parent, widgetID id, WidgetData data, IContent c) {
        super (mgr, parent, id);
        content = cast(EnumContent) c;
        if (content is null || (subWidgets.length = content.list.length) == 0)
            throw new ContentException (this);
        WDCheck (data, 1, subWidgets.length);
        
        foreach (i,sc; content.list)
            subWidgets[i] = mgr.makeWidget (this, data.strings[i], sc);
        currentW = subWidgets[content()];
        
        content.addCallback (&switchWidget);
    }
    
    override bool setup (uint n, uint flags) {
        bool r = super.setup (n, flags);
        if (r) {
            mw = currentW.minWidth;
            mh = currentW.minHeight;
            w = currentW.width;
            h = currentW.height;
            static if (SIZABILITY & SIZABILITY_ENUM.START_TRUE)
                    isWS = isHS = true;
            foreach (i,sc; content.list) {
                static if (SIZABILITY == SIZABILITY_ENUM.ANY_SUBWIDGETS) {
                    isWS |= subWidgets[i].isWSizable;
                    isHS |= subWidgets[i].isHSizable;
                } else static if (SIZABILITY == SIZABILITY_ENUM.ALL_SUBWIDGETS) {
                    isWS &= subWidgets[i].isWSizable;
                    isHS &= subWidgets[i].isHSizable;
                }
            }
        }
        return r;
    }
    
    override void minWChange (IChildWidget widget, wdim nmw) {
        if (widget !is currentW) return;
        mw = nmw;
        parent.minWChange (this, nmw);
    }
    override void minHChange (IChildWidget widget, wdim nmh) {
        if (widget !is currentW) return;
        mh = nmh;
        parent.minHChange (this, nmh);
    }
    
    override bool isWSizable () {
        return isWS;
    }
    override bool isHSizable () {
        return isHS;
    }
    
    override void setWidth (wdim nw, int dir) {
	w = (nw >= mw ? nw : mw);
        currentW.setWidth (w, dir);
    }
    override void setHeight (wdim nh, int dir) {
        h = (nh >= mh ? nh : mh);
        currentW.setHeight (h, dir);
    }
    
    override void setPosition (wdim nx, wdim ny) {
        x = nx;
        y = ny;
        currentW.setPosition (nx,ny);
    }
    
    override IChildWidget getWidget (wdim cx, wdim cy) {
        return currentW.getWidget (cx, cy);
    }
    
    override void draw () {
        currentW.draw;
    }
    
protected:
    // callback on content
    void switchWidget (Content) {
        currentW = subWidgets[content()];
        mw = currentW.minWidth;
        mh = currentW.minHeight;
        parent.minWChange (this, mw);
        parent.minHChange (this, mh);
        // If resizable and already large enough, don't resize; else do.
        if (isWS && w > mw) currentW.setWidth (w, -1);
        else w = currentW.width;
        if (isHS && h > mh) currentW.setHeight (h, -1);
        else h = currentW.height;
        currentW.setPosition (x,y);
    }
    
    IChildWidget currentW;
    EnumContent content;
    
    bool isWS, isHS;	// no infrastructure for changing sizability, so need to fix it.
}