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 TestDrawingArea; 20 21 //debug = trace; 22 23 private import gtk.VBox; 24 private import gdk.Font; 25 private import pango.PgContext; 26 private import pango.PgLayout; 27 private import gdk.ImageGdk; 28 29 version(Tango) private import tango.io.Stdout; 30 version(Tango) private import tango.stdc.stdio; 31 else private import std.stdio; 32 33 version(Tango) private import tango.math.Math; 34 else private import std.math; 35 36 private import gtk.Widget; 37 private import gtk.MenuItem; 38 private import gtk.ComboBox; 39 private import gtk.Menu; 40 private import gtk.Adjustment; 41 private import gtk.HBox; 42 private import gdk.Pixbuf; 43 //private import gdk.Point; 44 private import gdk.Color; 45 private import gdk.Drawable; 46 private import gdk.GC; 47 private import pango.PgFontDescription; 48 49 private import gtk.DrawingArea; 50 private import gtk.Image; 51 private import gtk.SpinButton; 52 53 private import gdk.Event; 54 55 private import gdk.Color; 56 57 //private import event.Event; 58 59 60 /** 61 * This tests the gtkD drawing area widget 62 */ 63 class TestDrawingArea : VBox 64 { 65 66 this() 67 { 68 debug(Tango) Stdout("TestDrawingArea.this() 1").newline; 69 super(false,4); 70 71 debug(Tango) Stdout("TestDrawingArea.this() 2").newline; 72 TestDrawing drawingArea = new TestDrawing(); 73 74 debug(Tango) Stdout("TestDrawingArea.this() 3").newline; 75 76 ComboBox gcOptions = new ComboBox(); 77 gcOptions.appendText("GC COPY"); 78 gcOptions.appendText("GC INVERT"); 79 gcOptions.appendText("GC XOR"); 80 gcOptions.appendText("GC CLEAR"); 81 gcOptions.appendText("GC AND"); 82 gcOptions.appendText("GC AND_REVERSE"); 83 gcOptions.appendText("GC AND_INVERT"); 84 gcOptions.appendText("GC NOOP"); 85 gcOptions.appendText("GC OR"); 86 gcOptions.appendText("GC EQUIV"); 87 gcOptions.appendText("GC OR_REVERSE"); 88 gcOptions.appendText("GC COPY_INVERT"); 89 gcOptions.appendText("GC OR_INVERT"); 90 gcOptions.appendText("GC NAND"); 91 gcOptions.appendText("GC NOR"); 92 gcOptions.appendText("GC SET"); 93 gcOptions.setActive(1); 94 gcOptions.addOnChanged(&drawingArea.onCGOptionsChanged); 95 96 debug(Tango) Stdout("TestDrawingArea.this() 4").newline; 97 98 ComboBox primOption = new ComboBox(); 99 primOption.appendText("Filled Arc"); 100 primOption.appendText("Arc"); 101 primOption.appendText("Line"); 102 primOption.appendText("Point"); 103 primOption.appendText("Rectangle"); 104 primOption.appendText("Filled Rectangle"); 105 primOption.appendText("Text"); 106 primOption.appendText("Pango text"); 107 primOption.appendText("Image"); 108 primOption.appendText("Polygon"); 109 primOption.setActive(0); 110 primOption.addOnChanged(&drawingArea.onPrimOptionChanged); 111 112 debug(Tango) Stdout("TestDrawingArea.this() 5").newline; 113 114 packStart(drawingArea,true,true,0); 115 116 HBox hbox = new HBox(false,4); 117 hbox.packStart(gcOptions,false,false,2); 118 hbox.packStart(primOption,false,false,2); 119 hbox.packStart(drawingArea.spin,false,false,2); 120 hbox.packStart(drawingArea.backSpin,false,false,2); 121 122 debug(Tango) Stdout("TestDrawingArea.this() 6").newline; 123 124 packStart(hbox, false, false, 0); 125 126 debug(Tango) Stdout("TestDrawingArea.this() END").newline; 127 } 128 129 130 class TestDrawing : DrawingArea 131 { 132 133 134 GdkFunction gcFunction = GdkFunction.INVERT; 135 Color paintColor; 136 Color black; 137 138 int width; 139 int height; 140 141 bool buttonIsDown; 142 143 string primitiveType; 144 PgFontDescription font; 145 Image image; 146 Pixbuf scaledPixbuf; 147 148 SpinButton spin; 149 SpinButton backSpin; 150 static GdkPoint[] polygonStar = [ 151 {0,4}, 152 {1,1}, 153 {4,0}, 154 {1,-1}, 155 {0,-4}, 156 {-1,-1}, 157 {-4,0}, 158 {-1,1} 159 ]; 160 161 this() 162 { 163 debug(Tango) Stdout("TestDrawing.this() 1").newline; 164 165 setSizeRequest(333,333); 166 width = getWidth(); 167 height = getHeight(); 168 169 debug(Tango) Stdout("TestDrawing.this() 2").newline; 170 171 primitiveType = "Filled Arc"; 172 font = PgFontDescription.fromString("Courier 48"); 173 174 image = new Image("../../../images/gtkDlogo_a_small.png"); 175 scaledPixbuf = image.getPixbuf(); 176 if (scaledPixbuf is null) 177 { 178 version(Tango) Stdout("\nFailed to load image gtkDlogo_a_small.png").newline; 179 else printf("\nFailed to load image file gtkDlogo_a_small.png\n"); 180 } 181 182 paintColor = new Color(cast(ubyte)0,cast(ubyte)0,cast(ubyte)0); 183 black = new Color(cast(ubyte)0,cast(ubyte)0,cast(ubyte)0); 184 185 spin = new SpinButton(new Adjustment(30, 1, 400, 1, 10, 0),1,0); 186 sizeSpinChanged(spin); 187 spin.addOnValueChanged(&sizeSpinChanged); 188 backSpin = new SpinButton(new Adjustment(5, 4, 100, 1, 10, 0),1,0); 189 backSpin.addOnValueChanged(&backSpinChanged); 190 191 192 193 addOnExpose(&exposeCallback); 194 // addOnMap(&mapCallback); 195 addOnMotionNotify(&onMotionNotify); 196 addOnSizeAllocate(&onSizeAllocate); 197 addOnButtonPress(&onButtonPress); 198 addOnButtonRelease(&onButtonRelease); 199 } 200 201 void onSizeAllocate(GtkAllocation* allocation, Widget widget) 202 { 203 width = allocation.width; 204 height = allocation.height; 205 } 206 207 208 public bool onButtonPress(GdkEventButton* event, Widget widget) 209 { 210 debug(trace) version(Tango) Stdout("button DOWN").newline; 211 else writefln("button DOWN"); 212 if ( event.button == 1 ) 213 { 214 debug(trace) version(Tango) Stdout("Button 1 down").newline; 215 else writefln("Button 1 down"); 216 buttonIsDown = true; 217 Drawable d = getWindow(); 218 GC gc = new GC(d); 219 gc.setForeground(new Color(cast(ubyte)0,cast(ubyte)0,cast(ubyte)0)); 220 gc.setFunction(gcFunction); 221 222 drawPrimitive(gc, d, cast(int)event.x, cast(int)event.y); //event.getX(), event.getY()); 223 224 gc.setForeground(black); 225 gc.setFunction(GdkFunction.COPY); 226 } 227 return false; 228 } 229 230 public bool onButtonRelease(GdkEventButton* event, Widget widget) 231 { 232 debug(trace) version(Tango) Stdout("button UP").newline; 233 else writefln("button UP"); 234 if ( event.button == 1 ) 235 { 236 debug(trace) version(Tango) Stdout("button 1 UP").newline; 237 else writefln("Button 1 UP"); 238 buttonIsDown = false; 239 } 240 return false; 241 } 242 243 244 public bool mapCallback(Widget d, Event event) 245 { 246 //printf("MAP CALLBACK\n"); 247 return false; 248 } 249 250 /** 251 * This will be called from the expose event call back. 252 * \bug this is called on get or loose focus - review 253 */ 254 public bool exposeCallback(GdkEventExpose* event, Widget widget) 255 { 256 //printf("testWindow.exposed ----------------------------- \n"); 257 drawPoints(getWindow()); 258 return true; 259 } 260 public bool noExposeCallback(Widget widget) 261 { 262 //printf("testWindow.noExposed ----------------------------- \n"); 263 return true; 264 } 265 266 267 public bool onMotionNotify(GdkEventMotion* event, Widget widget) 268 { 269 //printf("testWindow.mouseMoved ----------------------------- \n"); 270 if ( buttonIsDown ) 271 { 272 Drawable d = getWindow(); 273 GC gc = new GC(d); 274 gc.setForeground(paintColor); 275 gc.setFunction(gcFunction); 276 277 drawPrimitive(gc, d, cast(int)event.x, cast(int)event.y); 278 //d.drawPoint(event.getX(),event.getY()); 279 //d.drawArc(true,event.getX()-2,event.getY()-2,4,4,0,64*360); 280 //d.drawRectangle(true,event.getX()-2,event.getY()-2,4,4); 281 282 gc.setForeground(black); 283 gc.setFunction(GdkFunction.COPY); 284 } 285 return true; 286 } 287 288 public bool mouseButtonReleaseCallback(Widget widget, GdkEventButton event) 289 { 290 //printf("testWindow.buttonReleased ----------------------------- \n"); 291 return true; 292 } 293 294 static int backSpinCount = 0; 295 296 public void backSpinChanged(SpinButton spinButton) 297 { 298 299 debug(trace) version(Tango) Stdout.format("backSpinChanged - entry {}", ++backSpinCount).newline; 300 else writefln("backSpinChanged - entry %s", ++backSpinCount); 301 drawPoints(getWindow()); 302 GC gc = new GC(getWindow()); 303 debug(trace) version(Tango) Stdout("backSpinChanged - exit").newline; 304 else writefln("backSpinChanged - exit"); 305 } 306 307 public void sizeSpinChanged(SpinButton spinButton) 308 { 309 if ( !(scaledPixbuf is null)) 310 { 311 int width = spinButton.getValueAsInt(); 312 scaledPixbuf = image.getPixbuf(); 313 314 float ww = width * scaledPixbuf.getWidth() / 30; 315 float hh = width * scaledPixbuf.getHeight() / 30; 316 317 scaledPixbuf = scaledPixbuf.scaleSimple(cast(int)ww, cast(int)hh, GdkInterpType.HYPER); 318 } 319 } 320 321 322 323 public void drawPrimitive(GC gc, Drawable d, int x, int y) 324 { 325 int width = spin.getValueAsInt(); 326 int height = width * 3 / 4; 327 debug(trace) version(Tango) Stdout.format("primitiveType = {}", primitiveType).newline; 328 else writefln("primitiveType = %s", primitiveType); 329 switch ( primitiveType ) 330 { 331 case "Arc": 332 d.drawArc(gc, false,x-width/2,y-width/2,width,width,0,64*360); 333 break; 334 335 case "Filled Arc": 336 d.drawArc(gc, true,x-width/4,y-width/4,width/2,width/2,0,64*360); 337 break; 338 339 case "Line": 340 d.drawLine(gc, x, y, x+width, y); 341 break; 342 343 case "Point": 344 d.drawPoint(gc, x, y); 345 break; 346 347 case "Rectangle": 348 d.drawRectangle(gc, false, x-width/2, y-width/4, width, height); 349 break; 350 351 case "Filled Rectangle": 352 d.drawRectangle(gc, true, x-width/2, y-width/4, width, height); 353 break; 354 355 case "Text": 356 Font font = new Font("FreeMono 12"); 357 debug(trace) version(Tango) Stdout.format("Text font = {}", font).newline; 358 else writefln("Text font = %s", font); 359 d.drawString( font, gc,x, y, "gtkD toolkit"); 360 break; 361 362 case "Pango text": 363 //PgContext pc = getPangoContext(); 364 //PgLayout l = new PgLayout(pc); 365 PgLayout l = createPangoLayout("GtkD with D"); 366 //l.setText("GtkD with D"); 367 //PgFontDescription fd = l.getFontDescription(); 368 PgFontDescription fd = new PgFontDescription("Sans", width); 369 l.setFontDescription(fd); 370 371 d.drawLayout(gc, x,y,l); 372 break; 373 374 case "Image": 375 if ( !(scaledPixbuf is null)) 376 { 377 scaledPixbuf.renderToDrawable( d, gc, 378 //d.getDrawableStruct(), gc.getGCStruct(), 379 0, 0, x, y, 380 scaledPixbuf.getWidth(), scaledPixbuf.getHeight(), 381 GdkRgbDither.NONE, 0, 0 382 ); 383 } 384 break; 385 386 case "Polygon": 387 GdkPoint[] pol1; 388 pol1.length = polygonStar.length; 389 for ( int scale = 10 ; scale<= 300; scale+=15) 390 { 391 foreach(int i , ref GdkPoint p ; polygonStar) 392 { 393 pol1[i].x = p.x*scale/2+x; 394 pol1[i].y = p.y*scale/2+y; 395 } 396 d.drawPolygon(gc, true , pol1); 397 } 398 break; 399 400 default: 401 d.drawArc(gc, true,x-2,y-2,4,4,0,64*360); 402 break; 403 } 404 } 405 406 private void drawPoints(Drawable d) 407 { 408 int square = backSpin.getValueAsInt(); 409 int totalcount = 0; 410 int count = 0; 411 Color color = new Color(); 412 GC gc = new GC(d); 413 int width = this.width; 414 int height = this.height; 415 int x = 0; 416 int y = 0; 417 418 debug(trace) version(Tango) Stdout.format("w,h = {} {}",width ,height).newline; 419 else writefln("w,h = %s %s",width ,height); 420 421 debug(trace) version(Tango) Stdout.format("w,h = {} {}",width ,height).newline; 422 else writefln("w,h = %s %s",width ,height); 423 424 float dx = 256.0 / width; 425 float dy = 256.0 / height ; 426 float xx; 427 float yy; 428 while ( x < width || y <height ) 429 { 430 xx = x * dx; 431 yy = y * dy; 432 color.set8( cast(ubyte)xx, 433 cast(ubyte)yy, 434 cast(ubyte)(sqrt((xx*xx)+(yy*yy)))); 435 gc.setForeground(color); 436 if ( square > 1 ) 437 { 438 //d.drawPoint(gc, x,y); 439 d.drawRectangle(gc, true,x,y,square,square); 440 //d.foo(); 441 //d.drawArc(gc, 1, 10, 10, 100, 100, 45, 60); 442 } 443 else 444 { 445 d.drawPoint(gc, x,y); 446 } 447 x +=square; 448 if ( x > width) 449 { 450 if ( y>height) 451 { 452 //y=0; 453 } 454 else 455 { 456 x = 0; 457 y+=square; 458 } 459 } 460 ++totalcount; 461 } 462 gc.setForeground(black); 463 delete color; 464 } 465 466 void onCGOptionsChanged(ComboBox comboBox) 467 { 468 debug(trace) version(Tango) Stdout.format("gcOptions = {}", comboBox.getActiveText()).newline; 469 else writefln("gcOptions = %s", comboBox.getActiveText()); 470 switch ( comboBox.getActiveText() ) 471 { 472 case "GC COPY": gcFunction = GdkFunction.COPY; break; 473 case "GC INVERT": gcFunction = GdkFunction.INVERT; break; 474 case "GC XOR": gcFunction = GdkFunction.XOR; break; 475 case "GC CLEAR": gcFunction = GdkFunction.CLEAR; break; 476 case "GC AND": gcFunction = GdkFunction.AND; break; 477 case "GC AND_REVERSE": gcFunction = GdkFunction.AND_REVERSE; break; 478 case "GC AND_INVERT": gcFunction = GdkFunction.AND_INVERT; break; 479 case "GC NOOP": gcFunction = GdkFunction.NOOP; break; 480 case "GC OR": gcFunction = GdkFunction.OR; break; 481 case "GC EQUIV": gcFunction = GdkFunction.EQUIV; break; 482 case "GC OR_REVERSE": gcFunction = GdkFunction.OR_REVERSE; break; 483 case "GC COPY_INVERT": gcFunction = GdkFunction.COPY_INVERT; break; 484 case "GC OR_INVERT": gcFunction = GdkFunction.OR_INVERT; break; 485 case "GC NAND": gcFunction = GdkFunction.NAND; break; 486 case "GC NOR": gcFunction = GdkFunction.NOR; break; 487 case "GC SET": gcFunction = GdkFunction.SET; break; 488 default: gcFunction = GdkFunction.INVERT; break; 489 } 490 } 491 492 void onPrimOptionChanged(ComboBox comboBox) 493 { 494 primitiveType = comboBox.getActiveText(); 495 } 496 497 // 498 // void primitive(MenuItem item) 499 // { 500 // printf("TestDrawing.primitive item command = %.*s\n", item.getActionCommand().toString()); 501 // primitiveType.set(item.getActionCommand().dup); 502 // } 503 504 } 505 506 } 507