1 // Written by Christopher E. Miller
2 // See the included license.txt for copyright and license details.
3 
4 
5 ///
6 module dfl.colordialog;
7 
8 private import dfl.commondialog, dfl.base, dfl.internal.winapi, dfl.internal.wincom;
9 private import dfl.internal.utf, dfl.application, dfl.drawing, dfl.internal.dlib;
10 
11 
12 ///
13 class ColorDialog: CommonDialog // docmain
14 {
15 	this()
16 	{
17 		Application.ppin(cast(void*)this);
18 		
19 		cc.lStructSize = cc.sizeof;
20 		cc.Flags = INIT_FLAGS;
21 		cc.rgbResult = Color.empty.toArgb();
22 		cc.lCustData = cast(typeof(cc.lCustData))cast(void*)this;
23 		cc.lpfnHook = cast(typeof(cc.lpfnHook))&ccHookProc;
24 		_initcust();
25 	}
26 	
27 	
28 	///
29 	@property void allowFullOpen(bool byes) // setter
30 	{
31 		if(byes)
32 			cc.Flags &= ~CC_PREVENTFULLOPEN;
33 		else
34 			cc.Flags |= CC_PREVENTFULLOPEN;
35 	}
36 	
37 	/// ditto
38 	@property bool allowFullOpen() // getter
39 	{
40 		return (cc.Flags & CC_PREVENTFULLOPEN) != CC_PREVENTFULLOPEN;
41 	}
42 	
43 	
44 	///
45 	@property void anyColor(bool byes) // setter
46 	{
47 		if(byes)
48 			cc.Flags |= CC_ANYCOLOR;
49 		else
50 			cc.Flags &= ~CC_ANYCOLOR;
51 	}
52 	
53 	/// ditto
54 	@property bool anyColor() // getter
55 	{
56 		return (cc.Flags & CC_ANYCOLOR) == CC_ANYCOLOR;
57 	}
58 	
59 	
60 	///
61 	@property void solidColorOnly(bool byes) // setter
62 	{
63 		if(byes)
64 			cc.Flags |= CC_SOLIDCOLOR;
65 		else
66 			cc.Flags &= ~CC_SOLIDCOLOR;
67 	}
68 	
69 	/// ditto
70 	@property bool solidColorOnly() // getter
71 	{
72 		return (cc.Flags & CC_SOLIDCOLOR) == CC_SOLIDCOLOR;
73 	}
74 	
75 	
76 	///
77 	final @property void color(Color c) // setter
78 	{
79 		cc.rgbResult = c.toRgb();
80 	}
81 	
82 	/// ditto
83 	final @property Color color() // getter
84 	{
85 		return Color.fromRgb(cc.rgbResult);
86 	}
87 	
88 	
89 	///
90 	final @property void customColors(COLORREF[] colors) // setter
91 	{
92 		if(colors.length >= _cust.length)
93 			_cust[] = colors[0 .. _cust.length];
94 		else
95 			_cust[0 .. colors.length] = colors[];
96 	}
97 	
98 	/// ditto
99 	final @property COLORREF[] customColors() // getter
100 	{
101 		return _cust;
102 	}
103 	
104 	
105 	///
106 	@property void fullOpen(bool byes) // setter
107 	{
108 		if(byes)
109 			cc.Flags |= CC_FULLOPEN;
110 		else
111 			cc.Flags &= ~CC_FULLOPEN;
112 	}
113 	
114 	/// ditto
115 	@property bool fullOpen() // getter
116 	{
117 		return (cc.Flags & CC_FULLOPEN) == CC_FULLOPEN;
118 	}
119 	
120 	
121 	///
122 	@property void showHelp(bool byes) // setter
123 	{
124 		if(byes)
125 			cc.Flags |= CC_SHOWHELP;
126 		else
127 			cc.Flags &= ~CC_SHOWHELP;
128 	}
129 	
130 	/// ditto
131 	@property bool showHelp() // getter
132 	{
133 		return (cc.Flags & CC_SHOWHELP) == CC_SHOWHELP;
134 	}
135 	
136 	
137 	///
138 	override DialogResult showDialog()
139 	{
140 		return runDialog(GetActiveWindow()) ?
141 			DialogResult.OK : DialogResult.CANCEL;
142 	}
143 	
144 	/// ditto
145 	override DialogResult showDialog(IWindow owner)
146 	{
147 		return runDialog(owner ? owner.handle : GetActiveWindow()) ?
148 			DialogResult.OK : DialogResult.CANCEL;
149 	}
150 	
151 	
152 	///
153 	override void reset()
154 	{
155 		cc.Flags = INIT_FLAGS;
156 		cc.rgbResult = Color.empty.toArgb();
157 		_initcust();
158 	}
159 	
160 	
161 	///
162 	protected override bool runDialog(HWND owner)
163 	{
164 		if(!_runDialog(owner))
165 		{
166 			if(!CommDlgExtendedError())
167 				return false;
168 			_cantrun();
169 		}
170 		return true;
171 	}
172 	
173 	
174 	private BOOL _runDialog(HWND owner)
175 	{
176 		if(cc.rgbResult == Color.empty.toArgb())
177 			cc.Flags &= ~CC_RGBINIT;
178 		else
179 			cc.Flags |= CC_RGBINIT;
180 		cc.hwndOwner = owner;
181 		cc.lpCustColors = _cust.ptr;
182 		return ChooseColorA(&cc);
183 	}
184 	
185 	
186 	private:
187 	enum DWORD INIT_FLAGS = CC_ENABLEHOOK;
188 	
189 	CHOOSECOLORA cc;
190 	COLORREF[16] _cust;
191 	
192 	
193 	void _initcust()
194 	{
195 		COLORREF cdef;
196 		cdef = Color(0xFF, 0xFF, 0xFF).toRgb();
197 		foreach(ref COLORREF cref; _cust)
198 		{
199 			cref = cdef;
200 		}
201 	}
202 }
203 
204 
205 private extern(Windows) UINT ccHookProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
206 {
207 	enum PROP_STR = "DFL_ColorDialog";
208 	ColorDialog cd;
209 	UINT result = 0;
210 	
211 	try
212 	{
213 		if(msg == WM_INITDIALOG)
214 		{
215 			CHOOSECOLORA* cc;
216 			cc = cast(CHOOSECOLORA*)lparam;
217 			SetPropA(hwnd, PROP_STR.ptr, cast(HANDLE)cc.lCustData);
218 			cd = cast(ColorDialog)cast(void*)cc.lCustData;
219 		}
220 		else
221 		{
222 			cd = cast(ColorDialog)cast(void*)GetPropA(hwnd, PROP_STR.ptr);
223 		}
224 		
225 		if(cd)
226 		{
227 			result = cast(UINT)cd.hookProc(hwnd, msg, wparam, lparam);
228 		}
229 	}
230 	catch(DThrowable e)
231 	{
232 		Application.onThreadException(e);
233 	}
234 	
235 	return result;
236 }
237