view mde/gui/content/Content.d @ 94:9520cc0448e5

Boolean options are now encapsulated within a Content class (currently an experiment). This should facilitate generic option editing widgets.
author Diggory Hardy <diggory.hardy@gmail.com>
date Thu, 23 Oct 2008 17:45:49 +0100
parents 4d5d53e4f881
children 2a364c7d82c9
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/>. */

/** The content system − common types.
 */
module mde.gui.content.Content;

import Int = tango.text.convert.Integer;

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

/** IContent − interface for all Content classes.
 *
 * Services like copy/paste could work on universal content. However, they would need to run a
 * conversion to the appropriate type (or try next-oldest item on clipboard?).
 *
 * Currently Content instances can only have their data set on creation.
 * Each Content class should provide a method to get it's content, e.g. the method text().
 *
 * Extensions to content:
 * 
 * These extensions require that a content can notify any dependants of changes.
 * 
 * Use as a state switch (one option from an enumeration). E.g. a button/selection box could set a
 * state, and a tabbed box could show a tab based on this. Or could represent an option.
 */
//TODO - write a generic IContent displaying widget. Also a generic editable?
// Don't include dimension/drawing stuff because it's renderer specific and content should not be!
// NOTE: an interface or a class?
interface IContent
{
    /+ NOTE: None of this is really used yet, but was (mostly) intended for clipboard copying.
    /** Return a copy of self. */
    IContent dup ();
    
    /** Attempt to convert the content to a specific type (may simply return this if appropriate).
     *
     * Annoyingly we can't use cast because overloading by return type isn't supported. */
    // FIXME: throw or return null on error or unsupported conversion?
    ContentText	toText ();
    ContentInt	toInt ();	/// ditto
    +/
    
    
    
    /** Generically return strings.
     *
     * This serves two purposes: generically returning a string of/related to the content (i == 0),
     * and returning associated descriptors. Functions should adhere to (or add to) this table.
     *
     *  $(TABLE
     *  $(TR $(TH i) $(TH returns))
     *  $(TR $(TD 0) $(TD value))
     *  $(TR $(TD 1) $(TD Translated name or null))
     *  $(TR $(TD 2) $(TD Translated description or null))
     *  $(TR $(TD other) $(TD null))
     *  ) */
    char[] toString (uint i);
}

/** Base class for content containing a simple value.
 *
 * All derived classes should support functions to set/get any ValueContent type, but return the 
 * default value of any type other than it's own. */
abstract class ValueContent : IContent
{
    protected this () {}
    
    void name (char[] n, char[] d = null) {
        name_ = n;
        desc_ = d;
    }
protected:
    char[] name_, desc_;// name and description, loaded by lookup.Translation
}

class BoolContent : ValueContent
{
    this () {}
    this (bool val) {
        v = val;
    }
    
    /// Get the text.
    char[] toString (uint i) {
        debug logger.trace ("BoolContent.toString");
        return (i == 0) ? v ? "true" : "false"
             : (i == 1) ? name_
             : (i == 2) ? desc_
             : null;
    }
    
    void opAssign (bool val) {
        v = val;
    }
    bool opCall () {
        return v;
    }
    
    protected bool v;
}

/** Text content. */
class TextContent : ValueContent
{
    this () {}
    this (char[] text, char[] name = null) {
        text_ = text;
        name_ = name;
    }
    /+
    ContentText dup () {
        return new ContentText (text_);
    }
    
    ContentText toText () {
        return this;
    }
    ContentInt  toInt () {
        // FIXME: convert
        return null;
    }
    +/
    
    /// Get the text.
    char[] toString (uint i) {
        debug logger.trace ("TextContent.toString");
        return (i == 0) ? text_
            : (i == 1) ? name_
            : (i == 2) ? desc_
            : null;
    }
    
protected:
    char[] text_;
}
/+
/** Integer content. */
class ContentInt : IContent
{
    this () {}
    this (int integer) {
        int_ = integer;
    }
    
    ContentInt dup () {
        return new ContentInt (int_);
    }
    
    ContentText toText () {
        return new ContentText(toString);
    }
    ContentInt  toInt () {
        return this;
    }
    
    /// Get the integer.
    int integer () {
        return int_;
    }
    
    char[] toString () {
        return Int.toString (int_);
    }
    
protected:
    int int_;
}
+/