1 /// Plot style handler 2 module plot2d.style; 3 4 import plot2d.types; 5 6 /// 7 interface ValueHandler(Key, Value) 8 { 9 /// 10 Value opIndex(Key); 11 /// 12 void opIndexAssign(Value, Key); 13 /// 14 Value get(Key, lazy Value); 15 /// 16 void set(Key, Value); 17 } 18 19 /// 20 interface Style 21 { 22 /// 23 alias SVH(T) = ValueHandler!(string, T); 24 /// 25 Style getSubstyle(string name); 26 27 @property 28 { 29 /// 30 SVH!double number(); 31 /// 32 SVH!Color color(); 33 /// 34 SVH!string strval(); 35 } 36 } 37 38 /// 39 interface Stylized 40 { 41 /// get sub style from root and set style 42 final void setRootStyle(Style root) 43 { setStyle(root.getSubstyle(styleName)); } 44 /// 45 void setStyle(Style); 46 47 @property 48 { 49 /// 50 string styleName(); 51 /// 52 Style style(); 53 } 54 55 /// 56 mixin template StylizedHelper(string NAME="") 57 { 58 import std.exception : enforce; 59 60 protected Style __style; 61 public override 62 { 63 void setStyle(Style s) 64 { __style = enforce(s, "style is null"); } 65 66 @property 67 { 68 string styleName() { return NAME; } 69 Style style() 70 { 71 if (__style is null) 72 __style = new PlainStyle(null); 73 return __style; 74 } 75 } 76 } 77 } 78 } 79 80 /// 81 class PlainStyle : Style 82 { 83 protected: 84 /// 85 Style parent; 86 87 /// 88 string trName(string parameter) 89 { return parameter; } 90 91 class SVHP(Value, string fld) : SVH!Value 92 { 93 Value defaultValue; 94 Value[string] data; 95 96 this(Value dv) { defaultValue = dv; } 97 98 override: 99 /// 100 Value opIndex(string p) 101 { 102 if (this.outer.parent !is null) 103 mixin("return this.outer.parent." 104 ~fld~".opIndex(trName(p));"); 105 else return data.get(p, defaultValue); 106 } 107 /// 108 void opIndexAssign(Value val, string p) 109 { 110 if (this.outer.parent !is null) 111 mixin("this.outer.parent."~fld~ 112 ".opIndexAssign(val, trName(p));"); 113 else data[p] = val; 114 } 115 /// 116 Value get(string p, lazy Value val) 117 { 118 if (this.outer.parent !is null) 119 mixin("return this.outer.parent." 120 ~fld~".get(trName(p), val);"); 121 else return data.get(p, val); 122 } 123 /// 124 void set(string p, Value val) 125 { 126 if (this.outer.parent !is null) 127 mixin("this.outer.parent." 128 ~fld~".set(trName(p), val);"); 129 else data[p] = val; 130 } 131 } 132 133 SVH!double _number; 134 SVH!Color _color; 135 SVH!string _strval; 136 137 public: 138 139 /// 140 this(Style p) 141 { 142 parent = p; 143 _number = new SVHP!(double, "number")(0.0); 144 _color = new SVHP!(Color, "color")(Color.init); 145 _strval = new SVHP!(string, "strval")(""); 146 } 147 148 override 149 { 150 /// 151 Style getSubstyle(string name) 152 { return new PlainStyle(this); } 153 154 @property 155 { 156 SVH!double number() { return _number; } 157 SVH!Color color() { return _color; } 158 SVH!string strval() { return _strval; } 159 } 160 } 161 } 162 163 /// 164 class NSStyle : PlainStyle 165 { 166 protected: 167 /// namespace 168 string ns; 169 170 /// 171 override string trName(string p) 172 { 173 if (p[0] == '.') 174 { 175 if (parent !is null) return p; 176 else return p[1..$]; 177 } 178 else return ns ~ "." ~ p; 179 } 180 181 public: 182 183 /// 184 this() { super(null); } 185 186 /// 187 this(NSStyle p, string n) 188 { 189 super(p); 190 ns = n; 191 } 192 193 /// 194 override Style getSubstyle(string name) 195 { return new NSStyle(this, name); } 196 } 197 198 /+ TODO parser 199 ` 200 gridlabel: 201 fontsize: 15 202 fontface: Monospace 203 color: rgba(0,0,0,.8) 204 205 axis: 206 linewidth: 1.5 207 color: rgba(0,0,0,.7) 208 209 grid: 210 linewidth: 1 211 color: rgba(0,0,0,.2) 212 213 chart: 214 linewidth: 2 215 216 trechart > chart: 217 limlinewidth: 1 218 limlinealpha: 0.4 219 limfillalpha: 0.3 220 ` 221 +/