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 version(Tango) private import tango.io.Stdout;
43 version(Tango) private import tango.stdc.stdio;
44 else private import std.stdio;
45 
46 private import glib.Idle;
47 private import glib.Timeout;
48 
49 
50 /**
51  * This tests the gtkD drawing area widget
52  */
53 class TestIdle : VBox
54 {
55 
56 	SpinButton timeoutSpin;
57 
58 	this()
59 	{
60 
61 		debug(1)
62 		{
63 			printf("instantiating TestTimeout\n");
64 		}
65 
66 		super(false,7);
67 
68 		TestDrawing drawingArea = new TestDrawing();
69 
70 		ComboBoxText operators = new ComboBoxText();
71 		operators.appendText("CLEAR");
72 		operators.appendText("SOURCE");
73 		operators.appendText("OVER");
74 		operators.appendText("IN");
75 		operators.appendText("OUT");
76 		operators.appendText("ATOP");
77 		operators.appendText("DEST");
78 		operators.appendText("DEST_OVER");
79 		operators.appendText("DEST_IN");
80 		operators.appendText("DEST_OUT");
81 		operators.appendText("DEST_ATOP");
82 		operators.appendText("XOR");
83 		operators.appendText("ADD");
84 		operators.appendText("SATURATE");
85 		operators.appendText("MULTIPLY");
86 		operators.appendText("SCREEN");
87 		operators.appendText("OVERLAY");
88 		operators.appendText("DARKEN");
89 		operators.appendText("LIGHTEN");
90 		operators.appendText("COLOR_DODGE");
91 		operators.appendText("COLOR_BURN");
92 		operators.appendText("HARD_LIGHT");
93 		operators.appendText("SOFT_LIGHT");
94 		operators.appendText("DIFFERENCE");
95 		operators.appendText("EXCLUSION");
96 		operators.appendText("HSL_HUE");
97 		operators.appendText("HSL_SATURATION");
98 		operators.appendText("HSL_COLOR");
99 		operators.appendText("HSL_LUMINOSITY");
100 		operators.setActive(2);
101 		operators.addOnChanged(&drawingArea.onOperatorChanged);
102 
103 		ComboBoxText callType = new ComboBoxText();
104 		callType.appendText("Idle");
105 		callType.appendText("Timeout");
106 		callType.setActive(1);
107 		callType.addOnChanged(&drawingArea.onCallTypeChanged);
108 
109 		timeoutSpin = new SpinButton(new Adjustment(200.0, 1.0, 1000.0, 1.0, 100.0, 0),1,0);
110 		timeoutSpin.addOnValueChanged(&drawingArea.onTimeoutSpinValueChanged);
111 		Box controlBox = new HBox(false, 7);
112 
113 		controlBox.packStart(operators, false, false, 2);
114 		controlBox.packStart(callType, false, false, 2);
115 		controlBox.packStart(timeoutSpin, false, false, 2);
116 
117 		packStart(drawingArea,true,true,0);
118 		packStart(controlBox,false,false,0);
119 	}
120 
121 	class TestDrawing : DrawingArea
122 	{
123 
124 		Idle mainIdle;
125 		Timeout mainTimeout;
126 
127 		bool continueIdleCallback;
128 		CairoOperator operator = CairoOperator.OVER;
129 
130 		int x =0;
131 		int y =0;
132 		int xi =1;
133 		int yi =1;
134 		int totalcount = 0;
135 		int count = 0;
136 		int width;
137 		int height;
138 		ImageSurface surface;
139 
140 		CallType callType = CallType.Timeout;
141 
142 		this()
143 		{
144 			setSizeRequest(333,334);
145 
146 			addOnMap(&onMap);
147 			addOnUnmap(&onUnmap);
148 			addOnSizeAllocate(&onSizeAllocate);
149 			addOnDraw(&onDraw);
150 		}
151 
152 		public void onMap(Widget widget)
153 		{
154 			debug(trace) version(Tango) Stdout("idle.onMap").newline;
155 			else writefln("idle.onMap");
156 			continueIdleCallback = true;
157 			x = 0;
158 			y = 0;
159 			xi = 1;
160 			yi = 1;
161 			resetCallType();
162 		}
163 
164 		public void onUnmap(Widget widget)
165 		{
166 			debug(trace) version(Tango) Stdout("idle.onUnmap").newline;
167 			else writefln("idle.onUnmap");
168 			continueIdleCallback = false;
169 		}
170 
171 		void onSizeAllocate(GtkAllocation* allocation, Widget widget)
172 		{
173 			width = allocation.width;
174 			height = allocation.height;
175 			x = 0;
176 			y = 0;
177 			xi = 1;
178 			yi = 1;
179 
180 			surface = ImageSurface.create(CairoFormat.ARGB32, width, height);
181 		}
182 
183 		void onTimeoutSpinValueChanged(SpinButton spin)
184 		{
185 			if ( callType == CallType.Timeout )
186 			{
187 				resetCallType();
188 			}
189 		}
190 
191 		void resetCallType()
192 		{
193 			if ( mainIdle !is null )
194 			{
195 				mainIdle.stop();
196 			}
197 			if ( mainTimeout !is null )
198 			{
199 				mainTimeout.stop();
200 			}
201 			switch ( callType )
202 			{
203 				case CallType.Idle: mainIdle = new Idle(&idleCallback); break;
204 				case CallType.Timeout: mainTimeout = new Timeout(timeoutSpin.getValueAsInt(),&idleCallback, true); break;
205 				default: mainIdle = new Idle(&idleCallback); break;
206 			}
207 		}
208 
209 		bool onDraw(Context context, Widget widget)
210 		{
211 			//Fill the Widget with the surface we are drawing on.
212 			context.setSourceSurface(surface, 0, 0);
213 			context.paint();
214 
215 			return true;
216 		}
217 
218 		bool idleCallback()
219 		{
220 			Context context = Context.create(surface);
221 			context.setLineWidth(1);
222 			context.setOperator(operator);
223 
224 			int xf;
225 			int yf;
226 
227 			if ( xi<0 )xf = x;	// going back
228 			else xf = width-x;
229 
230 			if ( yi<0 )yf = y;	// going up
231 			else yf = height-y;
232 
233 			if ( xf<yf ) yf=xf;
234 
235 			//writefln("%s %s -> %s %s (%s %s)\n",x,y,xf,yf,x+yf*xi, y+yf*yi);
236 			context.moveTo(x, y);
237 			context.lineTo(x+yf*xi, y+yf*yi);
238 			context.stroke();
239 
240 			x += yf*xi;
241 			y += yf*yi;
242 
243 			if ( x>=width || x<=0 ) xi = -xi;
244 			if ( y>=height || y<=0 ) yi = -yi;
245 
246 			//Redraw the Widget.
247 			this.queueDraw();
248 
249 			return continueIdleCallback;
250 		}
251 
252 		void onCallTypeChanged(ComboBoxText comboBoxText)
253 		{
254 			debug(trace) version(Tango) Stdout.format("gcOptions = {}", comboBoxText.getActiveText()).newline;
255 			else writefln("gcOptions = %s", comboBoxText.getActiveText());
256 			switch ( comboBoxText.getActiveText() )
257 			{
258 				case "Idle":    callType = CallType.Idle;    break;
259 				case "Timeout": callType = CallType.Timeout; break;
260 				default:        callType = CallType.Timeout; break;
261 			}
262 			resetCallType();
263 		}
264 
265 		void onOperatorChanged(ComboBoxText comboBoxText)
266 		{
267 			debug(trace) version(Tango) Stdout.format("CairoOperator = {}", comboBoxText.getActiveText()).newline;
268 			else writefln("CairoOperator = %s", comboBoxText.getActiveText());
269 			switch ( comboBoxText.getActiveText() )
270 			{
271 				case "CLEAR":          operator = CairoOperator.CLEAR;          break;
272 				case "SOURCE":         operator = CairoOperator.SOURCE;         break;
273 				case "OVER":           operator = CairoOperator.OVER;           break;
274 				case "IN":             operator = CairoOperator.IN;             break;
275 				case "OUT":            operator = CairoOperator.OUT;            break;
276 				case "ATOP":           operator = CairoOperator.ATOP;           break;
277 				case "DEST":           operator = CairoOperator.DEST;           break;
278 				case "DEST_OVER":      operator = CairoOperator.DEST_OVER;      break;
279 				case "DEST_IN":        operator = CairoOperator.DEST_IN;        break;
280 				case "DEST_OUT":       operator = CairoOperator.DEST_OUT;       break;
281 				case "DEST_ATOP":      operator = CairoOperator.DEST_ATOP;      break;
282 				case "XOR":            operator = CairoOperator.XOR;            break;
283 				case "ADD":            operator = CairoOperator.ADD;            break;
284 				case "SATURATE":       operator = CairoOperator.SATURATE;       break;
285 				case "MULTIPLY":       operator = CairoOperator.MULTIPLY;       break;
286 				case "SCREEN":         operator = CairoOperator.SCREEN;         break;
287 				case "OVERLAY":        operator = CairoOperator.OVERLAY;        break;
288 				case "DARKEN":         operator = CairoOperator.DARKEN;         break;
289 				case "LIGHTEN":        operator = CairoOperator.LIGHTEN;        break;
290 				case "COLOR_DODGE":    operator = CairoOperator.COLOR_DODGE;    break;
291 				case "COLOR_BURN":     operator = CairoOperator.COLOR_BURN;     break;
292 				case "HARD_LIGHT":     operator = CairoOperator.HARD_LIGHT;     break;
293 				case "SOFT_LIGHT":     operator = CairoOperator.SOFT_LIGHT;     break;
294 				case "DIFFERENCE":     operator = CairoOperator.DIFFERENCE;     break;
295 				case "EXCLUSION":      operator = CairoOperator.EXCLUSION;      break;
296 				case "HSL_HUE":        operator = CairoOperator.HSL_HUE;        break;
297 				case "HSL_SATURATION": operator = CairoOperator.HSL_SATURATION; break;
298 				case "HSL_COLOR":      operator = CairoOperator.HSL_COLOR;      break;
299 				case "HSL_LUMINOSITY": operator = CairoOperator.HSL_LUMINOSITY; break;
300 				default:               operator = CairoOperator.OVER;           break;
301 			}
302 		}
303 	}
304 }
305 
306 enum CallType
307 {
308 	Idle,
309 	Timeout,
310 }
311