1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * gtkD is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with gtkD; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
17  */
18 
19 module TestIdle;
20 
21 //debug = trace
22 
23 private import cairo.Context;
24 private import cairo.ImageSurface;
25 
26 private import gtk.VBox;
27 private import gtk.HBox;
28 private import gtk.Box;
29 
30 private import gtk.DrawingArea;
31 private import gdk.Event;
32 private import gtk.Widget;
33 private import gtk.ComboBox;
34 private import gtk.ComboBoxText;
35 
36 private import gdk.Color;
37 private import gdk.Cairo;
38 
39 private import gtk.SpinButton;
40 private import gtk.Adjustment;
41 
42 private import std.stdio;
43 
44 private import glib.Idle;
45 private import glib.Timeout;
46 
47 
48 /**
49  * This tests the gtkD drawing area widget
50  */
51 class TestIdle : VBox
52 {
53 
54 	SpinButton timeoutSpin;
55 
56 	this()
57 	{
58 
59 		debug(1)
60 		{
61 			writeln("instantiating TestTimeout");
62 		}
63 
64 		super(false,7);
65 
66 		TestDrawing drawingArea = new TestDrawing();
67 
68 		ComboBoxText operators = new ComboBoxText();
69 		operators.appendText("CLEAR");
70 		operators.appendText("SOURCE");
71 		operators.appendText("OVER");
72 		operators.appendText("IN");
73 		operators.appendText("OUT");
74 		operators.appendText("ATOP");
75 		operators.appendText("DEST");
76 		operators.appendText("DEST_OVER");
77 		operators.appendText("DEST_IN");
78 		operators.appendText("DEST_OUT");
79 		operators.appendText("DEST_ATOP");
80 		operators.appendText("XOR");
81 		operators.appendText("ADD");
82 		operators.appendText("SATURATE");
83 		operators.appendText("MULTIPLY");
84 		operators.appendText("SCREEN");
85 		operators.appendText("OVERLAY");
86 		operators.appendText("DARKEN");
87 		operators.appendText("LIGHTEN");
88 		operators.appendText("COLOR_DODGE");
89 		operators.appendText("COLOR_BURN");
90 		operators.appendText("HARD_LIGHT");
91 		operators.appendText("SOFT_LIGHT");
92 		operators.appendText("DIFFERENCE");
93 		operators.appendText("EXCLUSION");
94 		operators.appendText("HSL_HUE");
95 		operators.appendText("HSL_SATURATION");
96 		operators.appendText("HSL_COLOR");
97 		operators.appendText("HSL_LUMINOSITY");
98 		operators.setActive(2);
99 		operators.addOnChanged(&drawingArea.onOperatorChanged);
100 
101 		ComboBoxText callType = new ComboBoxText();
102 		callType.appendText("Idle");
103 		callType.appendText("Timeout");
104 		callType.setActive(1);
105 		callType.addOnChanged(&drawingArea.onCallTypeChanged);
106 
107 		timeoutSpin = new SpinButton(new Adjustment(200.0, 1.0, 1000.0, 1.0, 100.0, 0),1,0);
108 		timeoutSpin.addOnValueChanged(&drawingArea.onTimeoutSpinValueChanged);
109 		Box controlBox = new HBox(false, 7);
110 
111 		controlBox.packStart(operators, false, false, 2);
112 		controlBox.packStart(callType, false, false, 2);
113 		controlBox.packStart(timeoutSpin, false, false, 2);
114 
115 		packStart(drawingArea,true,true,0);
116 		packStart(controlBox,false,false,0);
117 	}
118 
119 	class TestDrawing : DrawingArea
120 	{
121 
122 		Idle mainIdle;
123 		Timeout mainTimeout;
124 
125 		bool continueIdleCallback;
126 		CairoOperator operator = CairoOperator.OVER;
127 
128 		int x =0;
129 		int y =0;
130 		int xi =1;
131 		int yi =1;
132 		int totalcount = 0;
133 		int count = 0;
134 		int width;
135 		int height;
136 		ImageSurface surface;
137 
138 		CallType callType = CallType.Timeout;
139 
140 		this()
141 		{
142 			setSizeRequest(333,334);
143 
144 			addOnMap(&onMap);
145 			addOnUnmap(&onUnmap);
146 			addOnSizeAllocate(&onSizeAllocate);
147 			addOnDraw(&onDraw);
148 		}
149 
150 		public void onMap(Widget widget)
151 		{
152 			debug(trace) writeln("idle.onMap");
153 			continueIdleCallback = true;
154 			x = 0;
155 			y = 0;
156 			xi = 1;
157 			yi = 1;
158 			resetCallType();
159 		}
160 
161 		public void onUnmap(Widget widget)
162 		{
163 			debug(trace) writeln("idle.onUnmap");
164 			continueIdleCallback = false;
165 		}
166 
167 		void onSizeAllocate(GtkAllocation* allocation, Widget widget)
168 		{
169 			width = allocation.width;
170 			height = allocation.height;
171 			x = 0;
172 			y = 0;
173 			xi = 1;
174 			yi = 1;
175 
176 			surface = ImageSurface.create(CairoFormat.ARGB32, width, height);
177 		}
178 
179 		void onTimeoutSpinValueChanged(SpinButton spin)
180 		{
181 			if ( callType == CallType.Timeout )
182 			{
183 				resetCallType();
184 			}
185 		}
186 
187 		void resetCallType()
188 		{
189 			if ( mainIdle !is null )
190 			{
191 				mainIdle.stop();
192 			}
193 			if ( mainTimeout !is null )
194 			{
195 				mainTimeout.stop();
196 			}
197 			switch ( callType )
198 			{
199 				case CallType.Idle: mainIdle = new Idle(&idleCallback); break;
200 				case CallType.Timeout: mainTimeout = new Timeout(timeoutSpin.getValueAsInt(),&idleCallback, true); break;
201 				default: mainIdle = new Idle(&idleCallback); break;
202 			}
203 		}
204 
205 		bool onDraw(Scoped!Context context, Widget widget)
206 		{
207 			//Fill the Widget with the surface we are drawing on.
208 			context.setSourceSurface(surface, 0, 0);
209 			context.paint();
210 
211 			return true;
212 		}
213 
214 		bool idleCallback()
215 		{
216 			Context context = Context.create(surface);
217 			context.setLineWidth(1);
218 			context.setOperator(operator);
219 
220 			int xf;
221 			int yf;
222 
223 			if ( xi<0 )xf = x;	// going back
224 			else xf = width-x;
225 
226 			if ( yi<0 )yf = y;	// going up
227 			else yf = height-y;
228 
229 			if ( xf<yf ) yf=xf;
230 
231 			//writefln("%s %s -> %s %s (%s %s)\n",x,y,xf,yf,x+yf*xi, y+yf*yi);
232 			context.moveTo(x, y);
233 			context.lineTo(x+yf*xi, y+yf*yi);
234 			context.stroke();
235 
236 			x += yf*xi;
237 			y += yf*yi;
238 
239 			if ( x>=width || x<=0 ) xi = -xi;
240 			if ( y>=height || y<=0 ) yi = -yi;
241 
242 			//Redraw the Widget.
243 			this.queueDraw();
244 
245 			return continueIdleCallback;
246 		}
247 
248 		void onCallTypeChanged(ComboBoxText comboBoxText)
249 		{
250 			debug(trace) writefln("gcOptions = %s", comboBoxText.getActiveText());
251 			switch ( comboBoxText.getActiveText() )
252 			{
253 				case "Idle":    callType = CallType.Idle;    break;
254 				case "Timeout": callType = CallType.Timeout; break;
255 				default:        callType = CallType.Timeout; break;
256 			}
257 			resetCallType();
258 		}
259 
260 		void onOperatorChanged(ComboBoxText comboBoxText)
261 		{
262 			debug(trace) writefln("CairoOperator = %s", comboBoxText.getActiveText());
263 			switch ( comboBoxText.getActiveText() )
264 			{
265 				case "CLEAR":          operator = CairoOperator.CLEAR;          break;
266 				case "SOURCE":         operator = CairoOperator.SOURCE;         break;
267 				case "OVER":           operator = CairoOperator.OVER;           break;
268 				case "IN":             operator = CairoOperator.IN;             break;
269 				case "OUT":            operator = CairoOperator.OUT;            break;
270 				case "ATOP":           operator = CairoOperator.ATOP;           break;
271 				case "DEST":           operator = CairoOperator.DEST;           break;
272 				case "DEST_OVER":      operator = CairoOperator.DEST_OVER;      break;
273 				case "DEST_IN":        operator = CairoOperator.DEST_IN;        break;
274 				case "DEST_OUT":       operator = CairoOperator.DEST_OUT;       break;
275 				case "DEST_ATOP":      operator = CairoOperator.DEST_ATOP;      break;
276 				case "XOR":            operator = CairoOperator.XOR;            break;
277 				case "ADD":            operator = CairoOperator.ADD;            break;
278 				case "SATURATE":       operator = CairoOperator.SATURATE;       break;
279 				case "MULTIPLY":       operator = CairoOperator.MULTIPLY;       break;
280 				case "SCREEN":         operator = CairoOperator.SCREEN;         break;
281 				case "OVERLAY":        operator = CairoOperator.OVERLAY;        break;
282 				case "DARKEN":         operator = CairoOperator.DARKEN;         break;
283 				case "LIGHTEN":        operator = CairoOperator.LIGHTEN;        break;
284 				case "COLOR_DODGE":    operator = CairoOperator.COLOR_DODGE;    break;
285 				case "COLOR_BURN":     operator = CairoOperator.COLOR_BURN;     break;
286 				case "HARD_LIGHT":     operator = CairoOperator.HARD_LIGHT;     break;
287 				case "SOFT_LIGHT":     operator = CairoOperator.SOFT_LIGHT;     break;
288 				case "DIFFERENCE":     operator = CairoOperator.DIFFERENCE;     break;
289 				case "EXCLUSION":      operator = CairoOperator.EXCLUSION;      break;
290 				case "HSL_HUE":        operator = CairoOperator.HSL_HUE;        break;
291 				case "HSL_SATURATION": operator = CairoOperator.HSL_SATURATION; break;
292 				case "HSL_COLOR":      operator = CairoOperator.HSL_COLOR;      break;
293 				case "HSL_LUMINOSITY": operator = CairoOperator.HSL_LUMINOSITY; break;
294 				default:               operator = CairoOperator.OVER;           break;
295 			}
296 		}
297 	}
298 }
299 
300 enum CallType
301 {
302 	Idle,
303 	Timeout,
304 }
305