1 /**
2 * This module defines the notion of a $(PALETTE). $(PALETTE)s abstract the
3 * process of determining how to render the $(I cells) in a $(LATTICE) by the
4 * $(RENDERER), Allowing for more customization.
5 *
6 * It provides templates for testing whether a given object is a $(PALETTE),
7 * and what kind of $(PALETTE) it is.
8 *
9 * $(CALIB_ABSTRACT_DESC)
10 *
11 * Macros:
12 * IS_ANY = 
13 *     Tests if something is a $(B $0).
14 *     $(DDOC_BLANKLINE)
15 *     returns $(DDOC_BACKQUOTED true) if $(DDOC_BACKQUOTED T) is a $(B $0) where
16 *     the value specifing how a $(RENDERER) should display a $(I cell) can be of
17 *     any type. The $(I cell) can also be of any type.
18 *     $(DDOC_BLANKLINE)
19 *     This template is the same as $(B is$0) but the type of the display-value and
20 *     type of the $(I cells) need not be specified. Refer to $(B is$0) for more details about
21 *     what a $(B $0) is.
22 *     $(DDOC_BLANKLINE)
23 *     $(DDOC_PARAMS T type to be tested)
24 *     $(DDOC_RETURNS $(B true) if $(B T) is any $(B $0), $(B false) if not)
25 */
26 
27 module caLib_abstract.palette;
28 
29 import caLib_abstract.util : hasCellStateType, isCellStateTypesCompatible,
30     hasDisplayValueType, isDisplayValueTypesCompatible;
31 import caLib_util.structs : Color;
32 
33 
34 
35 /**
36 * Tests if something is a $(B Palette).
37 *
38 * Returns `true` if `T` is a $(B Palette) where `Dv` is the type of the value
39 * specifing how a $(RENDERER) should display a $(I cell) of type `Ct`
40 *
41 * A $(B Palette) is the most basic for of a $(PALETTE) defining the primitives: $(BR)
42 * `Dv getDisplayValue(string behaviour)(Ct cellState)` and
43 * `Dv getDisplayValue(Ct cellState)` where `Dv` is the type of the value describing
44 * how the cell `cellState` of type `Ct` should be rendererd.
45 *
46 * Params:
47 *	  T  = type to be tested
48 *     Ct = type of the cell
49 *     Dv = type whoms value describes how a cell of type Ct should be rendererd
50 *
51 * Returns: true if T is a $(B Neighbourhood), false if not
52 */
53 template isPalette(T, Ct, Dv)
54 {
55 	enum isPalette = 
56 		hasCellStateType!T &&
57 		hasDisplayValueType!T &&
58 		is(typeof(T.init.getDisplayValue!"_test"(Ct.init)) : Dv) &&
59 		is(typeof(T.init.getDisplayValue(Ct.init)) : Dv);
60 }
61 
62 unittest
63 {
64 	static assert( isPalette!(Palette!(string, byte), string, byte));
65 	static assert( isPalette!(Palette!(string, int), string, uint));
66 	static assert(!isPalette!(Palette!(string, int), int, string));
67 	static assert(!isPalette!(char[], int, int));
68 }
69 
70 
71 
72 ///$(IS_ANY Palette)
73 template isAnyPalette(T)
74 {
75 	static if(hasCellStateType!T && hasDisplayValueType!T)
76 	{
77 		enum isAnyPalette = isPalette!(T, T.CellStateType, T.DisplayValueType);
78 	}
79 	else
80 	{
81 		enum isAnyPalette = false;
82 	}
83 }
84 
85 unittest
86 {
87 	static assert(isAnyPalette!(Palette!(int, uint)));
88 }
89 
90 
91 /**
92 * Convinience template, same as $(B isPalette) but `Dv` is set to be of type
93 *`Color`.
94 *
95 * In almost all cases a $(PALETTE) will decide in what color a $(RENDERER) should
96 * render the $(LATTICE)s $(I cells). Thus this enum is added for convinience.
97 */
98 enum isColorPalette(T, Ct) = isPalette!(T, Ct, Color);
99 
100 
101 
102 ///$(IS_ANY ColorPalette)
103 template isAnyColorPalette(T)
104 {
105 	static if(hasDisplayValueType!T && is(T.DisplayValueType == Color))
106 	{
107 		enum isAnyColorPalette = isAnyPalette!(T);
108 	}
109 	else
110 	{
111 		enum isAnyColorPalette = false;
112 	}
113 }
114 
115 ///
116 unittest
117 {
118 	// a palette template
119 	struct A(Ct, Dv) {
120 		Dv getDisplayValue(string behaviour)(Ct cellState) {
121 			return Ct.init;
122 		}
123 
124 		Dv getDisplayValue(Ct cellState) { return getDisplayValue!""(cellState); }
125 	}
126 
127 	bool a =       isAnyPalette!(A!(int, byte)); // true for any values of A
128 	bool b = !isAnyColorPalette!(A!(int, int )); // false since A!(int, int ) does not return uint 
129 	bool c = !isAnyColorPalette!(A!(int, uint)); // true  since A!(int, uint) does     return uint
130 }
131 
132 
133 
134 version(unittest)
135 {
136 	struct Palette(Ct, Dv)
137 	{	
138 		alias CellStateType = Ct;
139 		alias DisplayValueType = Dv;
140 
141 		Dv getDisplayValue(string behaviour)(Ct cellState) { return Dv.init; }
142 		Dv getDisplayValue(Ct cellState) { return Dv.init; }
143 	}
144 }