Changeset 32
- Timestamp:
- 12/03/06 20:43:32 (2 years ago)
- Files:
-
- trunk/luigi/adapter.d (modified) (1 diff)
- trunk/luigi/base.d (modified) (14 diffs)
- trunk/luigi/example1.d (modified) (4 diffs)
- trunk/luigi/example1_gld.d (modified) (3 diffs)
- trunk/luigi/gui.d (modified) (12 diffs)
- trunk/luigi/themes/std.d (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/luigi/adapter.d
r29 r32 48 48 To implement a new adapter, derive from the InputAdapter interface, and mixin the 49 49 InputAdapterMix. This sets up the external interface and the signals. 50 Now all you have to do is51 50 */ 52 51 interface InputAdapter trunk/luigi/base.d
r23 r32 73 73 74 74 /** 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; 77 77 return r; 78 78 } 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 */ 84 84 void setLTRB(float leftx, float topy, float rightx, float bottomy) { 85 85 set(leftx,topy,rightx-leftx,bottomy-topy); … … 128 128 129 129 /** 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. 133 134 */ 134 135 struct Size … … 141 142 alias height h; 142 143 144 /** Constructor */ 143 145 static Size opCall(float _w, float _h) { 144 146 Size s; s.width = _w; s.height = _h; return s; 145 147 } 146 148 149 /** Allows Sizes to be added to using s1 += s2. */ 147 150 void opAddAssign(Size o) { w+=o.w; h+=o.h; } 151 152 /** Allows Sizes to be subtracted from using s1 += s2. */ 148 153 void opSubAssign(Size o) { w-=o.w; h-=o.h; } 149 154 155 /** Return a printable representation of the Size */ 150 156 char[] toString() { 151 157 return string.format("(%0.1f,%0.1f)",w,h); … … 153 159 } 154 160 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 */ 155 166 alias Size Point; 156 167 157 168 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 */ 158 174 struct Color 159 175 { … … 165 181 } 166 182 183 /** Constructor using integral values in the range 0--255 */ 167 184 static Color opCall(int r_, int g_, int b_, int a_=255) { 168 185 Color c; c.set(r_,g_,b_,a_); return c; 169 186 } 187 /** Constructor using floating point values in the range 0.0--1.0 */ 170 188 static Color opCall(float r_, float g_, float b_, float a_=1.0) { 171 189 Color c; c.set(r_,g_,b_,a_); return c; 172 190 } 173 191 192 /** Setter using integral values in the range 0--255 */ 174 193 void set(int r_, int g_, int b_, int a_=255) { 175 194 r=r_, g=g_, b=b_, a=a_; 176 195 } 177 196 197 /** Setter using floating point values in the range 0.0--1.0 */ 178 198 void set(float r_, float g_, float b_, float a_=1.0) { 179 199 r=lrint(r_*255), g=lrint(g_*255), b=lrint(b_*255), a=lrint(a_*255); 180 200 } 181 201 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 */ 182 211 static Color lerp(Color c1, Color c2, float t) { 183 212 Color ret; … … 189 218 } 190 219 220 /** Allows a color to be indexed with brackets []. 221 R,G,B,A components correspond to indexes 0,1,2,3. 222 */ 191 223 ubyte opIndex(int i) { return v[i]; } 192 224 ubyte opIndexAssign(int i, ubyte val) { return v[i]=val; } 193 225 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 */ 194 229 ubyte* ptr() { return &r; } 195 230 } … … 202 237 * the sizes are identical. If either type is an object then both must 203 238 * 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. 205 240 */ 206 241 template largestOrConvertible( T, U ) … … 224 259 } 225 260 261 /** Returns the maximum of two values */ 226 262 template max( T, U ) 227 263 { … … 231 267 } 232 268 } 269 270 /** Returns the minimum of two values */ 233 271 template min( T, U ) 234 272 { … … 308 346 309 347 /** 310 * Remove an item from an array by value, and return it. More performant than348 * Remove an item from an array by value, and return it. 311 349 * (modified from Cashew.utils) 312 350 */ … … 326 364 } 327 365 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 */ 334 374 template drop_range(T) 335 375 { … … 349 389 /*********************************************************************************** 350 390 * 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. 351 392 */ 352 393 size_t find (T) (T[] haystack, bool delegate (T) dg) … … 369 410 /*********************************************************************************** 370 411 * 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. 371 413 */ 372 414 size_t find_item (T) (T[] haystack, T cmp) … … 388 430 389 431 /*********************************************************************************** 390 * See ifa particular item is in an array432 * Return whether a particular item is in an array 391 433 */ 392 434 bool contains(T) (T[] haystack, T cmp) trunk/luigi/example1.d
r30 r32 73 73 gui = new Overlay; 74 74 75 //gui.arranger = new FlowArranger(Alignment.Left|Alignment.Bottom);76 //gui.arranger = new GridArranger(2,2);77 //BorderArranger layout = new BorderArranger(5,5);78 75 gui.arranger = new BorderArranger(Gaps(5)); 79 76 … … 86 83 auto southGroup = gui.add_arranged(new FlowPanel, Region.South); 87 84 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 88 117 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){ 99 126 Button b = cast(Button)w; assert(b); 100 127 if (v) b.label = "Show West"; … … 104 131 } 105 132 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 106 144 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")); 116 153 117 154 c15.value_changed ~= (Widget w, bool onoff) { … … 119 156 }; 120 157 } 121 122 with(southGroup) {123 alias southGroup g; // workaround for http://tinyurl.com/u5eal124 //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/u5eal137 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 D161 Button b3 = gui.add_widget(new Button("Mate!")).arranged(Region.East);162 */163 158 } 164 159 return gui; trunk/luigi/example1_gld.d
r29 r32 67 67 } 68 68 69 70 69 luigui.Overlay create_gui(char[] theme) 71 70 { … … 88 87 auto southGroup = gui.add_arranged(new FlowPanel, Region.South); 89 88 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); 115 107 }; 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")); 145 111 s02.vertical = true; 146 112 s01.precision = 0.1; … … 151 117 s02.value_changed.connect2nd(&s01.value); 152 118 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 }; 153 161 } 154 162 } trunk/luigi/gui.d
r30 r32 2 2 /** 3 3 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. 4 12 */ 5 13 //--------------------------------------------------------------------- 6 14 /* 7 Copyright:8 9 15 luigi/gui.d -- main import file for 'luigi' user interface library. 10 version 0. 1, November 9, 200616 version 0.5, December 3, 2006 11 17 12 18 Copyright (C) 2006 William V. Baxter III … … 31 37 William Baxter wbaxter@gmail.com 32 38 */ 33 39 //---------------------------------------------------------------------------- 34 40 /* 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 ******************************************* 37 45 I.e. 38 46 … … 43 51 int value() 44 52 45 Otherwise, signal.connect will connect to the getter rather46 than the setter.53 Otherwise, signal.connect(value) will silently connect to the 54 getter rather than the setter. 47 55 */ 48 56 … … 79 87 class Luigi 80 88 { 81 // Singleton access89 /// Return the singleton instance 82 90 static Luigi opCall() { 83 91 static Luigi instance = null; … … 85 93 return instance; 86 94 } 95 96 /// Return the singleton instance 87 97 static Luigi inst() { 88 98 return Luigi(); 89 99 } 90 100 101 /// Set the theme 91 102 Theme theme(Theme th) { return m_theme=th; } 103 /// Get the current theme 92 104 Theme theme() { 93 105 if (!m_theme) { … … 97 109 } 98 110 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 */ 99 115 void add_overlay(Overlay ov) { 100 116 m_guis ~= ov; … … 115 131 } 116 132 133 /** Returns the size of the specified window */ 117 134 Size get_window_size(WindowHandle win) { 118 135 return m_inputsys.get_window_size(win); 119 136 } 120 137 138 /** Set the current input adapter */ 121 139 void adapter(InputAdapter inputsys) { 122 140 m_inputsys = inputsys; 123 141 } 142 /** Get the current input adapter */ 143 InputAdapter adapter() { 144 return m_inputsys; 145 } 124 146 125 147 private: … … 129 151 130 152 ~this() { 131 132 153 } 133 154 … … 135 156 InputAdapter m_inputsys; 136 157 Theme m_theme; 137 }138 139 140 /** arranged() adds the specified widget to its parent's arranger141 */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 here148 // but I might as well. A classic '...'/valist would have worked, but149 // 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;154 158 } 155 159 … … 204 208 static assert(is(T:Panel), "PanelMixin should be derived from Panel"); 205 209 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 */ 209 221 W add_widget(W)(W widget) 210 222 { … … 213 225 return widget; 214 226 } 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 */ 215 240 W add_arranged(W, Varg...)(W widget, Varg args) 216 241 { … … 1651 1676 } 1652 1677 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 */ 1681 class RadioGroup : Valuator 1682 { 1683 override double value(double v) { 1684 checked_item = lrint(v); 1685 return checked_item; 1665 1686 } 1666 1687 override double value() { return m_checkedItem; } 1667 1688 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 1669 1815 private: 1670 int m_checkedItem; 1671 } 1816 int m_checkedItem = int.min; 1817 int[Button] m_obj2id; 1818 } 1819 1820 1672 1821 1673 1822 trunk/luigi/themes/std.d
r31 r32 46 46 panel_register(); 47 47 spinner_register(); 48 radiogroup_register();48 /*radiogroup_register();*/ 49 49 radiobutton_register(); 50 50 … … 709 709 */ 710 710 //----RADIOGROUP---------------------------------------------------------------- 711 /* 711 712 void radiogroup_register() { 712 713 //addHandlers!(RadioGroup)(&radiogroup_draw, &radiogroup_best_size); … … 725 726 fill_rect(w.rect); 726 727 } 728 */ 727 729 //----RADIOBUTTON---------------------------------------------------------------- 728 730 void radiobutton_register() {
