Changeset 32

Show
Ignore:
Timestamp:
12/03/06 20:43:32 (2 years ago)
Author:
baxissimo
Message:

Added an implementation of exclusive toggle behavior in the form of RadioGroup?.
Needs to be made more robust with regard to attachments and detachments. Also it only works with Button-derived things. Would be nice if say, any Valuator could be used, but the Valuator interface doesn't have a hook for setting a callback.

In general the approach taken by RadioGroup? is to connect a bunch of signals up so that exclusivity is maintained. So everything relies on the RadioGroup? itself. An alternate approach is to put smarts into the Buttons. Have them be observers of the RadioGroup? rather than other way around. It makes heterogeneity easier (anything can observe and set the radiogroups value) But then the buttons need to have ID's and I really dislike that style.

I guess with things the way they are now, you actually _could_ do approach #2 if you have items that know their own ID.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/luigi/adapter.d

    r29 r32  
    4848    To implement a new adapter, derive from the InputAdapter interface, and mixin the  
    4949    InputAdapterMix.  This sets up the external interface and the signals. 
    50     Now all you have to do is  
    5150 */ 
    5251interface InputAdapter 
  • trunk/luigi/base.d

    r23 r32  
    7373 
    7474    /** Rect constructor */ 
    75     static Rect opCall(float rx = 0, float ry = 0, float rw = 0, float rh = 0) { 
    76         Rect r;  r.x = rx; r.y = ry; r.w = rw; r.h = rh
     75    static Rect opCall(float rx = 0, float ry = 0, float rwidth = 0, float rheight = 0) { 
     76        Rect r;  r.x = rx; r.y = ry; r.w = rwidth; r.h = rheight
    7777        return r; 
    7878    } 
    79     /** Value setter */ 
    80     void  set(float rx, float ry, float rw, float rh) { 
    81         x = rx; y = ry; w = rw; h = rh
    82     } 
    83     /** Value setter using point values */ 
     79    /** Set value using left,top,width,height convention */ 
     80    void  set(float xpos, float ypos, float rwidth, float rheight) { 
     81        x = xpos; y = ypos; w = rwidth; h = rheight
     82    } 
     83    /** Set value using left,top,right,bottom convention */ 
    8484    void  setLTRB(float leftx, float topy, float rightx, float bottomy) { 
    8585        set(leftx,topy,rightx-leftx,bottomy-topy); 
     
    128128 
    129129/** Size is used to describe the width and height of a box. 
    130     Width is given by size.w, and height by size.h 
    131     Can also be used as a point location with x and y fields 
    132     synonymous with w and h. 
     130    Width is given by size.width, and height by size.height 
     131    Several synonyms are provided for the .w and .h properties.  
     132    .width is equivalent to .w or .x. 
     133    .height is equivalent to .h or .y. 
    133134 */ 
    134135struct Size 
     
    141142    alias height h; 
    142143 
     144    /** Constructor */ 
    143145    static Size opCall(float _w, float _h) { 
    144146        Size s; s.width = _w;  s.height = _h; return s; 
    145147    } 
    146148 
     149    /** Allows Sizes to be added to using s1 += s2. */ 
    147150    void opAddAssign(Size o) { w+=o.w; h+=o.h; } 
     151 
     152    /** Allows Sizes to be subtracted from using s1 += s2. */ 
    148153    void opSubAssign(Size o) { w-=o.w; h-=o.h; } 
    149154 
     155    /** Return a printable representation of the Size */ 
    150156    char[] toString() { 
    151157        return string.format("(%0.1f,%0.1f)",w,h); 
     
    153159} 
    154160 
     161/** Point can be used as an alias for Size.   
     162    This is not a typedef so there is no compiler enforcement of the distinction, 
     163    but you can use Point vs Size as the situation dictates to indicate the 
     164    intent of the variable, be it a location or a displacement. 
     165 */ 
    155166alias Size Point; 
    156167 
    157168 
     169/** Color represents a standard 4-byte RGBA color value. 
     170    It is the type used to represent colors througout Luigi. 
     171    Color components can be accessed via .r, .g, .b, and .a properties. 
     172    Alternatively, one can use numerical indexing, e.g. c[0],c[1],c[2],c[3]. 
     173 */ 
    158174struct Color 
    159175{ 
     
    165181    } 
    166182 
     183    /** Constructor using integral values in the range 0--255 */ 
    167184    static Color opCall(int r_, int g_, int b_, int a_=255) { 
    168185        Color c; c.set(r_,g_,b_,a_); return c; 
    169186    } 
     187    /** Constructor using floating point  values in the range 0.0--1.0 */ 
    170188    static Color opCall(float r_, float g_, float b_, float a_=1.0) { 
    171189        Color c; c.set(r_,g_,b_,a_); return c; 
    172190    } 
    173191 
     192    /** Setter using integral values in the range 0--255 */ 
    174193    void set(int r_, int g_, int b_, int a_=255) { 
    175194        r=r_, g=g_, b=b_, a=a_; 
    176195    } 
    177196 
     197    /** Setter using floating point  values in the range 0.0--1.0 */ 
    178198    void set(float r_, float g_, float b_, float a_=1.0) { 
    179199        r=lrint(r_*255), g=lrint(g_*255), b=lrint(b_*255), a=lrint(a_*255); 
    180200    } 
    181201 
     202    /** Linearly interpolate between the two colors. 
     203        Params: 
     204            c1 = the first color  
     205            c2 = the second color 
     206            t  = the interpolation parameter between 0 and 1 
     207        Returns: the blended color  
     208                 If t==0 then the result is c1 
     209                 If t==1 then the result is c2 
     210    */ 
    182211    static Color lerp(Color c1, Color c2, float t) { 
    183212        Color ret; 
     
    189218    } 
    190219 
     220    /** Allows a color to be indexed with brackets []. 
     221        R,G,B,A components correspond to indexes 0,1,2,3. 
     222     */ 
    191223    ubyte opIndex(int i) { return v[i]; } 
    192224    ubyte opIndexAssign(int i, ubyte val) { return v[i]=val; } 
    193225 
     226    /** Return a pointer to the beginning of the 4 bytes that 
     227     *  make up this color.  Bytes are ordered R,G,B,A. 
     228     */ 
    194229    ubyte* ptr() { return &r; } 
    195230} 
     
    202237 * the sizes are identical.  If either type is an object then both must 
    203238 * be objects of either the same type or where one is a base class of 
    204  * the other.  Interfaces are not supported. 
     239 * the other.  Interfaces are not supported.  Used by min() and max() templates. 
    205240 */ 
    206241template largestOrConvertible( T, U ) 
     
    224259} 
    225260 
     261/** Returns the maximum of two values */ 
    226262template max( T, U ) 
    227263{ 
     
    231267    } 
    232268} 
     269 
     270/** Returns the minimum of two values */ 
    233271template min( T, U ) 
    234272{ 
     
    308346 
    309347/** 
    310  *  Remove an item from an array by value, and return it.  More performant than 
     348 *  Remove an item from an array by value, and return it. 
    311349 *  (modified from Cashew.utils) 
    312350 */ 
     
    326364} 
    327365 
    328 // Remove a range of elements from an array in place.   
    329 // It is not an error for the range to be empty or for start to be greater than end. 
    330 // If so, the array is not modified. 
    331 // Out of bounds checks performed only in debug mode. 
    332 // Returns: the array, which (is modified in-place). 
    333 // Note: This is an O(n) operation. 
     366/** 
     367 * Remove a range of elements from an array in place.   
     368 * It is not an error for the range to be empty or for start to be greater than end. 
     369 * If so, the array is not modified. 
     370 * Out of bounds checks performed only in debug mode. 
     371 * Returns: the array, which (is modified in-place). 
     372 * Note: This is an O(n) operation. 
     373 */ 
    334374template drop_range(T) 
    335375{ 
     
    349389/*********************************************************************************** 
    350390 * Lookup the index of the first element of an array that satisfies a delegate. 
     391 * Returns: the index of the value or NOT_FOUND if not found. 
    351392 */ 
    352393size_t find (T) (T[] haystack, bool delegate (T) dg) 
     
    369410/*********************************************************************************** 
    370411 * Lookup the index of the first element of an array that equals a given value 
     412 * Returns: the index of the value or NOT_FOUND if not found. 
    371413 */ 
    372414size_t find_item (T) (T[] haystack, T cmp) 
     
    388430 
    389431/*********************************************************************************** 
    390  * See if a particular item is in an array  
     432 * Return whether a particular item is in an array  
    391433 */ 
    392434bool contains(T) (T[] haystack, T cmp) 
  • trunk/luigi/example1.d

    r30 r32  
    7373        gui = new Overlay; 
    7474     
    75         //gui.arranger = new FlowArranger(Alignment.Left|Alignment.Bottom); 
    76         //gui.arranger = new GridArranger(2,2); 
    77         //BorderArranger layout = new BorderArranger(5,5); 
    7875        gui.arranger = new BorderArranger(Gaps(5)); 
    7976 
     
    8683        auto southGroup = gui.add_arranged(new FlowPanel, Region.South); 
    8784 
     85        auto rgrp = new RadioGroup; 
     86 
     87        with (westGroup) { 
     88            auto b20 = add_arranged(new Button("Tool0")); 
     89            auto b21 = add_arranged(new Button("Tool1")); 
     90            auto b22 = add_arranged(new Button("Tool2")); 
     91            auto b23 = add_arranged(new Button("Tool3")); 
     92            auto b24 = add_arranged(new Button("LongNameTool4")); 
     93            auto b25 = add_arranged(new Button("Tool5")); 
     94            auto b26 = add_arranged(new Button("Tool6")); 
     95            auto b27 = add_arranged(new Button("Tool7")); 
     96            auto b28 = add_arranged(new Button("Tool8")); 
     97            auto b29 = add_arranged(new Button("Tool9")); 
     98 
     99            rgrp.add(b20,b21,b22,b23,b24,b25,b26,b27,b28,b29); 
     100            rgrp.value = 0; 
     101            rgrp.selection_changed ~= (int t) { 
     102                writefln("Tool %s now selected", t); 
     103            }; 
     104 
     105            auto s01 = add_arranged(new Slider("Thingy")); 
     106            auto s02 = add_arranged(new Slider("Thingy")); 
     107            s02.vertical = true; 
     108            s01.precision = 0.1; 
     109            s02.precision = 0.1; 
     110 
     111            s01.value_changed.connect2nd( (double d){ writefln("Slider now %s",d); } ); 
     112            s02.value_changed.connect2nd( (double d){ writefln("Slider now %s",d); } ); 
     113            s02.value_changed.connect2nd(&s01.value); 
     114            s01.value_changed.connect2nd(&s02.value); 
     115        } 
     116 
    88117        with(eastGroup) { 
    89             alias eastGroup g; // workaround for http://tinyurl.com/u5eal 
    90             auto b0 = g.add_widget(new Button("Luigi")); 
    91             g.add_widget(new Button("Is")); 
    92             g.add_widget(new Button("My")); 
    93             g.add_widget(new Button("Pal")); 
    94             auto b1 = g.add_widget(new Button("Hide West")); 
    95             b1.is_toggle = true; 
    96             b0.disable(); 
    97             b1.clicked.connect( &westGroup.toggle_shown ); 
    98             b1.value_changed ~= (Widget w, bool v){ 
     118            auto b0 = add_widget(new Button("Luigi"));  b0.disable(); 
     119            auto b1 = add_widget(new Button("Is")); rgrp.add(b1,5); 
     120            auto b2 = add_widget(new Button("My")); rgrp.add(b2,7); 
     121            auto b3 = add_widget(new Button("Pal"));rgrp.add(b3,9); 
     122            auto b4 = add_widget(new Button("Hide West"));  
     123            b4.is_toggle = true; 
     124            b4.clicked.connect( &westGroup.toggle_shown ); 
     125            b4.value_changed ~= (Widget w, bool v){ 
    99126                Button b = cast(Button)w; assert(b); 
    100127                if (v) b.label = "Show West"; 
     
    104131        } 
    105132 
     133        with(southGroup) { 
     134            auto l0 = add_widget(new Label( "First Name:")); 
     135            auto t0 = add_widget(new TextField("Hello")); 
     136            auto l1 = add_widget(new Label( "Last Name:")); 
     137            auto t1 = add_widget(new TextField("Rumpelstiltskin")); 
     138            auto b4 = add_widget(new Button("Click me!")); 
     139            auto l2 = add_widget(new Label("Disabled label")); 
     140            l2.disable; 
     141            b4.clicked ~= (Widget w){ writefln("Ouch! Not so hard!"); }; 
     142        } 
     143 
    106144        with (northGroup) { 
    107             alias northGroup g; // workaround for http://tinyurl.com/u5eal 
    108             auto b10 =   g.add_widget(new Button("File")); 
    109             auto b11 =   g.add_widget(new Button("Edit")); 
    110             auto b12 =   g.add_widget(new Button("View")); 
    111             auto b13 =   g.add_widget(new Button("Favorites")); 
    112             auto b14 =   g.add_widget(new Button("Tools")); 
    113             auto b15 =   g.add_widget(new Button("Options")); 
    114             auto c15 =   g.add_widget(new Checkbox("Check it out!")); 
    115             auto b16 =   g.add_widget(new Button("Help")); 
     145            auto b10 =   add_widget(new Button("File")); 
     146            auto b11 =   add_widget(new Button("Edit")); 
     147            auto b12 =   add_widget(new Button("View")); 
     148            auto b13 =   add_widget(new Button("Favorites")); 
     149            auto b14 =   add_widget(new Button("Tools")); 
     150            auto b15 =   add_widget(new Button("Options")); 
     151            auto c15 =   add_widget(new Checkbox("Check it out!")); 
     152            auto b16 =   add_widget(new Button("Help")); 
    116153 
    117154            c15.value_changed ~= (Widget w, bool onoff) { 
     
    119156            }; 
    120157        } 
    121  
    122         with(southGroup) { 
    123             alias southGroup g; // workaround for http://tinyurl.com/u5eal 
    124             //Button b0 = add_widget(new Button("Hohoho!")); 
    125             auto l0 = g.add_widget(new Label( "First Name:")); 
    126             auto t0 = g.add_widget(new TextField("Hello")); 
    127             auto l1 = g.add_widget(new Label( "Last Name:")); 
    128             auto t1 = g.add_widget(new TextField("Rumpelstiltskin")); 
    129             auto b4 = g.add_widget(new Button("Click me!")); 
    130             auto l2 = g.add_widget(new Label("Disabled label")); 
    131             l2.disable; 
    132             b4.clicked ~= (Widget w){ writefln("Ouch! Not so hard!"); }; 
    133         } 
    134  
    135         with (westGroup) { 
    136             alias westGroup g; // workaround for http://tinyurl.com/u5eal 
    137             auto b20 = g.add_arranged(new Button("Tool0")); 
    138             auto b21 = g.add_arranged(new Button("Tool1")); 
    139             auto b22 = g.add_arranged(new Button("Tool2")); 
    140             auto b23 = g.add_arranged(new Button("Tool3")); 
    141             auto b24 = g.add_arranged(new Button("LongNameTool4")); 
    142             auto b25 = g.add_arranged(new Button("Tool5")); 
    143             auto b26 = g.add_arranged(new Button("Tool6")); 
    144             auto b27 = g.add_arranged(new Button("Tool7")); 
    145             auto b28 = g.add_arranged(new Button("Tool8")); 
    146             auto b29 = g.add_arranged(new Button("Tool9")); 
    147             auto s01 = g.add_arranged(new Slider("Thingy")); 
    148             auto s02 = g.add_arranged(new Slider("Thingy")); 
    149             s02.vertical = true; 
    150             s01.precision = 0.1; 
    151             s02.precision = 0.1; 
    152  
    153             s01.value_changed.connect2nd( (double d){ writefln("Slider now %s",d); } ); 
    154             s02.value_changed.connect2nd( (double d){ writefln("Slider now %s",d); } ); 
    155             s02.value_changed.connect2nd(&s01.value); 
    156             s01.value_changed.connect2nd(&s02.value); 
    157         } 
    158  
    159 /* 
    160        // This is my ideal version, but it requires more smarts from D 
    161         Button b3 = gui.add_widget(new Button("Mate!")).arranged(Region.East); 
    162 */ 
    163158    } 
    164159    return gui; 
  • trunk/luigi/example1_gld.d

    r29 r32  
    6767} 
    6868 
    69  
    7069luigui.Overlay create_gui(char[] theme) 
    7170{ 
     
    8887        auto southGroup = gui.add_arranged(new FlowPanel, Region.South); 
    8988 
    90         with(eastGroup) { 
    91             alias eastGroup g; // workaround for http://tinyurl.com/u5eal 
    92             auto b0 = g.add_widget(new Button("Luigi")); 
    93             g.add_widget(new Button("Is")); 
    94             g.add_widget(new Button("My")); 
    95             g.add_widget(new Button("Pal")); 
    96             auto b1 = g.add_widget(new Button("Hide West")); 
    97  
    98             b0.disable(); 
    99             b1.clicked.connect( &westGroup.toggle_shown ); 
    100         } 
    101  
    102         with (northGroup) { 
    103             alias northGroup g; // workaround for http://tinyurl.com/u5eal 
    104             auto b10 =   g.add_widget(new Button("File")); 
    105             auto b11 =   g.add_widget(new Button("Edit")); 
    106             auto b12 =   g.add_widget(new Button("View")); 
    107             auto b13 =   g.add_widget(new Button("Favorites")); 
    108             auto b14 =   g.add_widget(new Button("Tools")); 
    109             auto b15 =   g.add_widget(new Button("Options")); 
    110             auto c15 =   g.add_widget(new Checkbox("Check it out!")); 
    111             auto b16 =   g.add_widget(new Button("Help")); 
    112  
    113             c15.value_changed ~= (Widget w, bool onoff) { 
    114                 writefln(onoff?"checked!":"unchecked!");  
     89        auto rgrp = new RadioGroup; 
     90 
     91        with (westGroup) { 
     92            auto b20 = add_arranged(new Button("Tool0")); 
     93            auto b21 = add_arranged(new Button("Tool1")); 
     94            auto b22 = add_arranged(new Button("Tool2")); 
     95            auto b23 = add_arranged(new Button("Tool3")); 
     96            auto b24 = add_arranged(new Button("LongNameTool4")); 
     97            auto b25 = add_arranged(new Button("Tool5")); 
     98            auto b26 = add_arranged(new Button("Tool6")); 
     99            auto b27 = add_arranged(new Button("Tool7")); 
     100            auto b28 = add_arranged(new Button("Tool8")); 
     101            auto b29 = add_arranged(new Button("Tool9")); 
     102 
     103            rgrp.add(b20,b21,b22,b23,b24,b25,b26,b27,b28,b29); 
     104            rgrp.value = 0; 
     105            rgrp.selection_changed ~= (int t) { 
     106                writefln("Tool %s now selected", t); 
    115107            }; 
    116         } 
    117  
    118         with(southGroup) { 
    119             alias southGroup g; // workaround for http://tinyurl.com/u5eal 
    120             //Button b0 = add_widget(new Button("Hohoho!")); 
    121             auto l0 = g.add_widget(new Label( "First Name:")); 
    122             auto t0 = g.add_widget(new TextField("Hello")); 
    123             auto l1 = g.add_widget(new Label( "Last Name:")); 
    124             auto t1 = g.add_widget(new TextField("Rumpelstiltskin")); 
    125             auto b4 = g.add_widget(new Button("Click me!")); 
    126             auto l2 = g.add_widget(new Label("Disabled label")); 
    127             l2.disable; 
    128             b4.clicked ~= (Widget w){ writefln("Ouch! Not so hard!"); }; 
    129         } 
    130  
    131         with (westGroup) { 
    132             alias westGroup g; // workaround for http://tinyurl.com/u5eal 
    133             auto b20 = g.add_arranged(new Button("Tool0")); 
    134             auto b21 = g.add_arranged(new Button("Tool1")); 
    135             auto b22 = g.add_arranged(new Button("Tool2")); 
    136             auto b23 = g.add_arranged(new Button("Tool3")); 
    137             auto b24 = g.add_arranged(new Button("LongNameTool4")); 
    138             auto b25 = g.add_arranged(new Button("Tool5")); 
    139             auto b26 = g.add_arranged(new Button("Tool6")); 
    140             auto b27 = g.add_arranged(new Button("Tool7")); 
    141             auto b28 = g.add_arranged(new Button("Tool8")); 
    142             auto b29 = g.add_arranged(new Button("Tool9")); 
    143             auto s01 = g.add_arranged(new Slider("Thingy")); 
    144             auto s02 = g.add_arranged(new Slider("Thingy")); 
     108 
     109            auto s01 = add_arranged(new Slider("Thingy")); 
     110            auto s02 = add_arranged(new Slider("Thingy")); 
    145111            s02.vertical = true; 
    146112            s01.precision = 0.1; 
     
    151117            s02.value_changed.connect2nd(&s01.value); 
    152118            s01.value_changed.connect2nd(&s02.value); 
     119        } 
     120 
     121        with(eastGroup) { 
     122            auto b0 = add_widget(new Button("Luigi"));  b0.disable(); 
     123            auto b1 = add_widget(new Button("Is")); rgrp.add(b1,5); 
     124            auto b2 = add_widget(new Button("My")); rgrp.add(b2,7); 
     125            auto b3 = add_widget(new Button("Pal"));rgrp.add(b3,9); 
     126            auto b4 = add_widget(new Button("Hide West"));  
     127            b4.is_toggle = true; 
     128            b4.clicked.connect( &westGroup.toggle_shown ); 
     129            b4.value_changed ~= (Widget w, bool v){ 
     130                Button b = cast(Button)w; assert(b); 
     131                if (v) b.label = "Show West"; 
     132                else   b.label = "Hide West"; 
     133                b.get_root.arrange(); 
     134            }; 
     135        } 
     136 
     137        with(southGroup) { 
     138            auto l0 = add_widget(new Label( "First Name:")); 
     139            auto t0 = add_widget(new TextField("Hello")); 
     140            auto l1 = add_widget(new Label( "Last Name:")); 
     141            auto t1 = add_widget(new TextField("Rumpelstiltskin")); 
     142            auto b4 = add_widget(new Button("Click me!")); 
     143            auto l2 = add_widget(new Label("Disabled label")); 
     144            l2.disable; 
     145            b4.clicked ~= (Widget w){ writefln("Ouch! Not so hard!"); }; 
     146        } 
     147 
     148        with (northGroup) { 
     149            auto b10 =   add_widget(new Button("File")); 
     150            auto b11 =   add_widget(new Button("Edit")); 
     151            auto b12 =   add_widget(new Button("View")); 
     152            auto b13 =   add_widget(new Button("Favorites")); 
     153            auto b14 =   add_widget(new Button("Tools")); 
     154            auto b15 =   add_widget(new Button("Options")); 
     155            auto c15 =   add_widget(new Checkbox("Check it out!")); 
     156            auto b16 =   add_widget(new Button("Help")); 
     157 
     158            c15.value_changed ~= (Widget w, bool onoff) { 
     159                writefln(onoff?"checked!":"unchecked!");  
     160            }; 
    153161        } 
    154162    } 
  • trunk/luigi/gui.d

    r30 r32  
    22/** 
    33   Luigi is an OpenGL based GUI library. 
     4    
     5   The goal is to provide a simple but flexible way to add a simple 
     6   GUI to an OpenGL program. 
     7 
     8   Luigi supports themes and input adaptors.  Themes give you a way 
     9   to customize the look of GUI.  Input adaptors do the work of 
     10   taking events from the OS or from a windowing toolkit like GLD, and 
     11   turning them into something Luigi can use. 
    412*/  
    513//--------------------------------------------------------------------- 
    614/* 
    7  Copyright: 
    8  
    915  luigi/gui.d -- main import file for 'luigi' user interface library. 
    10   version 0.1, November 9, 2006 
     16  version 0.5, December 3, 2006 
    1117 
    1218  Copyright (C) 2006 William V. Baxter III 
     
    3137  William Baxter wbaxter@gmail.com 
    3238*/ 
    33  
     39//---------------------------------------------------------------------------- 
    3440/* 
    35   WARNING: Because of how overloading works in D as of 0.175,  
    36            ** ALL SETTERS SHOULD COME BEFORE GETTERS ** 
     41  WARNING: Because of how overloading works in D (at least as of DMD 0.176), 
     42           ******************************************* 
     43           ** ALL SETTERS MUST COME BEFORE GETTERS  ** 
     44           ******************************************* 
    3745  I.e. 
    3846 
     
    4351          int value() 
    4452 
    45    Otherwise, signal.connect will connect to the getter rather  
    46    than the setter. 
     53   Otherwise, signal.connect(value) will silently connect to the 
     54   getter rather than the setter. 
    4755 */ 
    4856 
     
    7987class Luigi 
    8088{ 
    81     // Singleton access 
     89    /// Return the singleton instance 
    8290    static Luigi opCall() { 
    8391        static Luigi instance = null; 
     
    8593        return instance; 
    8694    } 
     95 
     96    /// Return the singleton instance 
    8797    static Luigi inst() { 
    8898        return Luigi(); 
    8999    } 
    90100 
     101    /// Set the theme 
    91102    Theme theme(Theme th) { return m_theme=th; } 
     103    /// Get the current theme 
    92104    Theme theme() {  
    93105        if (!m_theme) { 
     
    97109    } 
    98110 
     111    /** Add a top level overlay.   
     112        This is called automatically by Overlay, so typically there is no  
     113        reason for users to call it themselves. 
     114    */ 
    99115    void add_overlay(Overlay ov) { 
    100116        m_guis ~= ov; 
     
    115131    } 
    116132 
     133    /** Returns the size of the specified window */ 
    117134    Size get_window_size(WindowHandle win) { 
    118135        return m_inputsys.get_window_size(win); 
    119136    } 
    120137 
     138    /** Set the current input adapter */ 
    121139    void adapter(InputAdapter inputsys) { 
    122140        m_inputsys = inputsys; 
    123141    } 
     142    /** Get the current input adapter */ 
     143    InputAdapter adapter() { 
     144        return m_inputsys; 
     145    } 
    124146 
    125147private: 
     
    129151 
    130152    ~this() { 
    131  
    132153    } 
    133154 
     
    135156    InputAdapter m_inputsys; 
    136157    Theme m_theme; 
    137 } 
    138  
    139  
    140 /** arranged() adds the specified widget to its parent's arranger 
    141  */ 
    142 T arranged(T, VArg...)(T widget, VArg varg) 
    143 { 
    144     static assert(is(T:Widget), "arranger_add requires a Widget as argument 0"); 
    145     assert(widget.parent, "arranged called on widget with no parent"); 
    146     assert(widget.parent.arranger, "arranged called on widget with parent.arranger"); 
    147     // Not really necessary to use the fancy DMD 0.173 feature here 
    148     // but I might as well.  A classic '...'/valist would have worked, but 
    149     // I hate looking at _argptrs and _arguments. 
    150     if (widget.parent && widget.parent.arranger && !widget.parent.arranger.auto_add) { 
    151         widget.parent.arranger.add(widget, varg); 
    152     } 
    153     return widget; 
    154158} 
    155159 
     
    204208    static assert(is(T:Panel), "PanelMixin should be derived from Panel"); 
    205209         
    206     /* These allow a panel subclass to create and add a child, and  
    207        return the object created/added with it's full derived type. 
    208      */        
     210    /** Add the widget to this panel. 
     211     * 
     212     * This method returns the widget passed in with its full derived type, 
     213     * so add_widget can be used like: 
     214     * --------- 
     215     *   auto b = border_panel.add_widget(new Button("Clicky")); 
     216     * --------- 
     217     * and the resulting b will have type Button. 
     218     * 
     219     * See_Also: add_arranged, Panel.add, Arranger.add 
     220     */ 
    209221    W add_widget(W)(W widget) 
    210222    { 
     
    213225        return widget; 
    214226    } 
     227 
     228    /** Add the widget to this panel and also to the panel's arranger 
     229     *  with arguments. 
     230     * 
     231     * This method returns the widget passed in with its full derived type, 
     232     * so add_arranged can be used like: 
     233     * --------- 
     234     *   auto b = border_panel.add_arranged(new Button("Clicky"), Region.East); 
     235     * --------- 
     236     * and the resulting b will have type Button. 
     237     * 
     238     * See_Also: add_widget, Panel.add, Arranger.add 
     239     */ 
    215240    W add_arranged(W, Varg...)(W widget, Varg args) 
    216241    { 
     
    16511676} 
    16521677 
    1653 class RadioGroup : Panel, Valuator 
    1654 
    1655     mixin WidgetMixin; 
    1656     mixin PanelMixin; 
    1657  
    1658     this(char[] label_) { 
    1659         super(); 
    1660         label = label_; 
    1661     } 
    1662  
    1663     override double value(double v) {  
    1664         return m_checkedItem=lrint(v);  
     1678/** RadioGroup is a non-GUI class that implements exclusive selection  
     1679    behavior using signals. 
     1680*/ 
     1681class RadioGroup : Valuator 
     1682
     1683    override double value(double v) { 
     1684        checked_item = lrint(v); 
     1685        return checked_item; 
    16651686    } 
    16661687    override double value() { return m_checkedItem; } 
    16671688 
    1668     char[] label; 
     1689    int checked_item(int v) { 
     1690        if (v == m_checkedItem) { return m_checkedItem; } 
     1691        m_checkedItem = v; 
     1692        selection_changed.emit(m_checkedItem); 
     1693 
     1694        // Make sure the one we want is indeed selected 
     1695        Button[] currentSels = opIndex(m_checkedItem); 
     1696        foreach(s; currentSels) { 
     1697            s.value = 1; 
     1698        } 
     1699 
     1700        return m_checkedItem; 
     1701    } 
     1702    int checked_item() { return m_checkedItem; } 
     1703 
     1704    this() { 
     1705        selection_changed = new SelectionChangedSignal; 
     1706    } 
     1707 
     1708    /** Have button b join this group, using value val */ 
     1709    void add(Button b, int val) { 
     1710        m_obj2id[b] = val; 
     1711        b.value_changed.connect( &_member_value_changed ); 
     1712        // Leave this up to the user? 
     1713        b.is_toggle = true; 
     1714    } 
     1715 
     1716    /** Have button b join this group, using the next available value. 
     1717     *  If this is the first item, the 0 is used as the value.  
     1718     */ 
     1719    void add(Button b, ...) { 
     1720        void do_add (Button btn) { 
     1721            int v = length() ? max_val()+1 : 0; 
     1722            add(btn,v); 
     1723        } 
     1724        do_add(b); 
     1725        for (int i=0; i<_arguments.length; i++) 
     1726        { 
     1727            if (_arguments[i] == typeid(Button)) { 
     1728                Button bb = *cast(Button*)_argptr; 
     1729                do_add(bb); 
     1730                _argptr += bb.sizeof; 
     1731            } 
     1732        } 
     1733    } 
     1734 
     1735    /** Have button b leave this group */ 
     1736    void remove(Button b) { 
     1737        assert(0, "Not implemented yet!"); 
     1738        m_obj2id.remove(b); 
     1739    } 
     1740 
     1741    /** Return the Button(s) assocated with the given group value. */ 
     1742    Button[] opIndex(int v) { 
     1743        Button [] ret; 
     1744        foreach(Button b, int val; m_obj2id) { 
     1745            if (v==val) ret ~= b; 
     1746        } 
     1747        return ret; 
     1748    } 
     1749 
     1750    /** Return the group value associated with the given button.  
     1751     *  Returns int.min if the item is not found 
     1752     */ 
     1753    int opIndex(Button b) { 
     1754        int *p = (b in m_obj2id); 
     1755        if (p) return *p; 
     1756        return int.min; 
     1757    } 
     1758 
     1759    /** Return the minimum value associated with any item in the group.  
     1760     *  Returns: the minimum value or int.max if there are no items. 
     1761     */ 
     1762    int min_val() { 
     1763        int minv = int.max; 
     1764        foreach(v; m_obj2id.values) { 
     1765            if (v < minv) minv = v; 
     1766        } 
     1767        return minv; 
     1768    } 
     1769 
     1770    /** Return the maximum value associated with any item in the group. */ 
     1771    int max_val() { 
     1772        int maxv = int.min; 
     1773        foreach(v; m_obj2id.values) { 
     1774            if (v > maxv) maxv = v; 
     1775        } 
     1776        return maxv; 
     1777    } 
     1778 
     1779    void _member_value_changed(Widget w, bool bSet) 
     1780    { 
     1781        Button b = cast(Button)w; 
     1782        if (!b) 
     1783            return; 
     1784        int new_check_id = opIndex(b); 
     1785        if (new_check_id == int.min) { 
     1786            return; 
     1787        } 
     1788        if (bSet && m_checkedItem != new_check_id) { 
     1789            // This is a new selection, different from previous 
     1790            int oldcheck = m_checkedItem; 
     1791            checked_item = new_check_id; 
     1792             
     1793            // Try to uncheck any old item 
     1794            if (oldcheck != int.min) { 
     1795                Button[] currentSels = opIndex(oldcheck); 
     1796                foreach(s; currentSels) { 
     1797                    s.value = 0; 
     1798                } 
     1799            } 
     1800        } 
     1801        else if (!bSet && m_checkedItem == new_check_id) { 
     1802            // Attempt to deselect current selection -- don't let it happen 
     1803            Button[] currentSels = opIndex(m_checkedItem); 
     1804            foreach(s; currentSels) { 
     1805                s.value = 1; 
     1806            } 
     1807        } 
     1808    } 
     1809 
     1810    int length() { return m_obj2id.length; } 
     1811 
     1812    alias FlexSignal!(int) SelectionChangedSignal; 
     1813    SelectionChangedSignal selection_changed; 
     1814 
    16691815private: 
    1670     int m_checkedItem; 
    1671 
     1816    int m_checkedItem = int.min; 
     1817    int[Button] m_obj2id; 
     1818
     1819 
     1820 
    16721821 
    16731822 
  • trunk/luigi/themes/std.d

    r31 r32  
    4646        panel_register(); 
    4747        spinner_register(); 
    48         radiogroup_register(); 
     48        /*radiogroup_register();*/ 
    4949        radiobutton_register(); 
    5050 
     
    709709    */ 
    710710    //----RADIOGROUP---------------------------------------------------------------- 
     711/* 
    711712    void radiogroup_register() { 
    712713        //addHandlers!(RadioGroup)(&radiogroup_draw, &radiogroup_best_size); 
     
    725726        fill_rect(w.rect); 
    726727    } 
     728*/ 
    727729    //----RADIOBUTTON---------------------------------------------------------------- 
    728730    void radiobutton_register() {