comparison doodle/gtk/canvas.d @ 41:f2e4e1d29b98

Bah
author daveb
date Tue, 01 Jun 2010 17:21:01 +0930
parents 1f97022e5c6d
children 1b4c9ba58673
comparison
equal deleted inserted replaced
40:1f97022e5c6d 41:f2e4e1d29b98
31 31
32 import gtkc.gtk; 32 import gtkc.gtk;
33 } 33 }
34 34
35 // x and y run right and up respectively 35 // x and y run right and up respectively
36 //
37 // Model units are millimetres.
38 //
39 // mZoom -> pixels-per-model-unit
40 // mViewSize -> size of view window in pixels
41 // mViewCentre -> location in model corresponding to centre of view
42 // mCanvasBounds -> size of the virtual canvas in model coordinates
43 //
44 // User operations:
45 // pan (middle click and drag)
46 // zoom about a point (hold control and move scroll wheel)
47 // resize the widget
36 48
37 class Canvas : Table, Viewport { 49 class Canvas : Table, Viewport {
38 this(in Layer[] layers, EventHandler event_handler, Grid grid, in double ppi) { 50 this(in Layer[] layers, EventHandler event_handler, Grid grid, in double ppi) {
39 super(3, 3, 0); 51 super(3, 3, 0);
40 52
182 mDamage = mDamage | area; 194 mDamage = mDamage | area;
183 } 195 }
184 196
185 private { 197 private {
186 198
199 void update_bounds() {
200 }
201
202
187 bool on_configure(GdkEventConfigure * event, Widget widget) { 203 bool on_configure(GdkEventConfigure * event, Widget widget) {
188 assert(widget is mDrawingArea); 204 assert(widget is mDrawingArea);
189 205
206 mViewSize = Vector(cast(double)event.width, cast(double)event.height);
207
208 Rectangle layer_bounds = Rectangle.DEFAULT;
209
210 foreach (ref layer; mLayers) {
211 layer_bounds = layer_bounds | layer.bounds;
212 }
213
214 assert(layer_bounds.valid);
215
216 Rectangle padded_layer_bounds = expand(move(layer_bounds, - layer_bounds.size), 2.0 * layer_bounds.size);
217
190 if (!mHadConfigure) { 218 if (!mHadConfigure) {
219 info("1");
191 const double MM_PER_INCH = 25.4; 220 const double MM_PER_INCH = 25.4;
192 mZoom = 0.25 * mPPI / MM_PER_INCH; 221 mZoom = 0.25 * mPPI / MM_PER_INCH;
193 222
194 // Take the union of the bounds of each layer to 223 mCanvasBounds = padded_layer_bounds;
195 // determine the canvas size
196
197 Rectangle layer_bounds = Rectangle.DEFAULT;
198
199 foreach (ref layer; mLayers) {
200 layer_bounds = layer_bounds | layer.bounds;
201 }
202
203 assert(layer_bounds.valid);
204
205 mCanvasBounds = expand(move(layer_bounds, -layer_bounds.size), 2.0 * layer_bounds.size);
206 mViewCentre = mCanvasBounds.centre; 224 mViewCentre = mCanvasBounds.centre;
207 225
208 mGrid.zoom_changed(mZoom); 226 mGrid.zoom_changed(mZoom);
209 227
210 mHadConfigure = true; 228 mHadConfigure = true;
211 } 229 }
212 230 else {
213 mViewSize = Vector(cast(double)event.width, cast(double)event.height); 231 // Use configure events as an opportunity
232 // to consolidate the canvas-bounds
233 // XXX nasty code.
234 Vector z = mViewSize / mZoom;
235 Rectangle r = Rectangle(mViewCentre - z / 2.0, z);
236 mCanvasBounds = r | padded_layer_bounds;
237 }
238
214 update_adjustments; 239 update_adjustments;
215 update_rulers; 240 update_rulers;
216 241
217 //writefln("Canvas bounds: %s", mCanvasBounds); 242 //writefln("Canvas bounds: %s", mCanvasBounds);
218 //writefln("View centre: %s", mViewCentre); 243 //writefln("View centre: %s", mViewCentre);
265 290
266 // Fill the background 291 // Fill the background
267 292
268 pixel_cr.save; { 293 pixel_cr.save; {
269 // Make the window light grey 294 // Make the window light grey
270 pixel_cr.setSourceRgba(0.6, 0.6, 0.6, 1.0); 295 pixel_cr.setSourceRgba(0.9, 0.9, 0.9, 1.0);
271 rectangle(pixel_cr, pixel_damage); 296 rectangle(pixel_cr, pixel_damage);
272 pixel_cr.fill; 297 pixel_cr.fill;
273 } pixel_cr.restore; 298 } pixel_cr.restore;
274 299
275 // Draw each layer 300 // Draw each layer
297 model_point, 322 model_point,
298 gtk2tk_mask(event.state)); 323 gtk2tk_mask(event.state));
299 324
300 mEventHandler.handle_button_press(this, button_event); 325 mEventHandler.handle_button_press(this, button_event);
301 326
302 process_damage; 327 fix_damage;
303 328
304 return true; 329 return true;
305 } 330 }
306 331
307 bool on_button_release(GdkEventButton * event, Widget widget) { 332 bool on_button_release(GdkEventButton * event, Widget widget) {
317 model_point, 342 model_point,
318 gtk2tk_mask(event.state)); 343 gtk2tk_mask(event.state));
319 344
320 mEventHandler.handle_button_release(this, button_event); 345 mEventHandler.handle_button_release(this, button_event);
321 346
322 process_damage; 347 fix_damage;
323 348
324 return true; 349 return true;
325 } 350 }
326 351
327 bool on_key_event(GdkEventKey * event, Widget widget) { 352 bool on_key_event(GdkEventKey * event, Widget widget) {
329 //writefln("Got key event\n"); 354 //writefln("Got key event\n");
330 355
331 //auto key_event = new KeyEvent("", 356 //auto key_event = new KeyEvent("",
332 // mEventHandle.handle_key(key_event); 357 // mEventHandle.handle_key(key_event);
333 358
334 process_damage; 359 fix_damage;
335 360
336 return true; 361 return true;
337 } 362 }
338 363
339 bool on_motion_notify(GdkEventMotion * event, Widget widget) { 364 bool on_motion_notify(GdkEventMotion * event, Widget widget) {
349 model_point, 374 model_point,
350 gtk2tk_mask(event.state)); 375 gtk2tk_mask(event.state));
351 376
352 mEventHandler.handle_motion(this, motion_event); 377 mEventHandler.handle_motion(this, motion_event);
353 378
354 process_damage; 379 fix_damage;
355 380
356 return true; 381 return true;
357 } 382 }
358 383
359 bool on_scroll(GdkEventScroll * event, Widget widget) { 384 bool on_scroll(GdkEventScroll * event, Widget widget) {
368 model_point, 393 model_point,
369 gtk2tk_mask(event.state)); 394 gtk2tk_mask(event.state));
370 395
371 mEventHandler.handle_scroll(this, scroll_event); 396 mEventHandler.handle_scroll(this, scroll_event);
372 397
373 process_damage; 398 fix_damage;
374 399
375 return true; 400 return true;
376 } 401 }
377 402
378 /* 403 /*
490 mHAdjustment.valueChanged; 515 mHAdjustment.valueChanged;
491 mVAdjustment.changed; 516 mVAdjustment.changed;
492 mVAdjustment.valueChanged; 517 mVAdjustment.valueChanged;
493 } 518 }
494 519
495 void process_damage() { 520 void fix_damage() {
496 if (mDamage.valid) { 521 if (mDamage.valid) {
497 //writefln("Damage: %s", mDamage); 522 //writefln("Damage: %s", mDamage);
498 int x, y, w, h; 523 int x, y, w, h;
499 mDamage.get_quantised(x, y, w, h); 524 mDamage.get_quantised(x, y, w, h);
500 mDrawingArea.queueDrawArea(x, cast(int)mViewSize.y - (y + h), w, h); 525 mDrawingArea.queueDrawArea(x, cast(int)mViewSize.y - (y + h), w, h);
539 bool mHadConfigure; 564 bool mHadConfigure;
540 Rectangle mDamage; // pixels 565 Rectangle mDamage; // pixels
541 566
542 // Model units are in millimetres 567 // Model units are in millimetres
543 // Screen units are in pixels 568 // Screen units are in pixels
544 double mZoom; // pixels-per-model-unit (mm) 569 double mZoom; // pixels-per-model-unit
545 Vector mViewSize; // pixel: size of view window in pixels 570 Vector mViewSize; // pixel: size of view window in pixels
546 Point mViewCentre; // model: where in the model is the centre of our view 571 Point mViewCentre; // model: where in the model is the centre of our view
547 Rectangle mCanvasBounds; // model: 572 Rectangle mCanvasBounds; // model:
548 573
549 // Child widgets: 574 // Child widgets: