comparison canvas.d @ 2:d6f44347373d

* Switched over to geometry done with structs instead of classes. * Removed direct access to gtk structs * Refactoring
author David Bryant <daveb@acres.com.au>
date Fri, 10 Jul 2009 15:15:27 +0930
parents e907d2c54ec3
children 7d57cae10805
comparison
equal deleted inserted replaced
1:c18e3f93d114 2:d6f44347373d
18 import gtk.VScrollbar; 18 import gtk.VScrollbar;
19 import gtk.DrawingArea; 19 import gtk.DrawingArea;
20 import gtk.Adjustment; 20 import gtk.Adjustment;
21 21
22 import tk.misc; 22 import tk.misc;
23 import tk.geometry; 23 import tk.geometry2;
24 import tk.types; 24 import tk.types;
25 import tk.events; 25 import tk.events;
26 import tk.gtk_support; 26 import tk.gtk_support;
27 27
28 private import gtkc.gtk; 28 private import gtkc.gtk;
29 29
30 import icanvas; 30 import icanvas;
31 import cairo_support;
31 32
32 // x and y run right and up respectively 33 // x and y run right and up respectively
33
34 void rectangle(Context cr, Point corner1, Point corner2) {
35 double x = corner1.x;
36 double y = corner1.y;
37 double w = corner2.x - corner1.x;
38 double h = corner2.y - corner1.y;
39
40 if (w < 0.0) { x += w; w = -w; }
41 if (h < 0.0) { y += h; h = -h; }
42
43 //writefln("Rect: %f %f %f %f\n", x, y, w, h);
44
45 cr.rectangle(x, y, w, h);
46 }
47 34
48 class Canvas : Table, ICanvas { 35 class Canvas : Table, ICanvas {
49 static this() { 36 static this() {
50 ORIGIN = new Point(0.0, 0.0); 37 ORIGIN = Point2(0.0, 0.0);
51 INITIAL_PAGE_SIZE = new Vector(210.0, 297.0); // A4 38 INITIAL_PAGE_SIZE = Vector2(210.0, 297.0); // A4
52 } 39 }
53 40
54 this(ICanvasEventHandler event_handler) { 41 this(ICanvasEventHandler event_handler) {
55 super(3, 3, 0); 42 super(3, 3, 0);
56 43
58 45
59 const double PPI = 120.0; 46 const double PPI = 120.0;
60 const double MM_PER_INCH = 25.4; 47 const double MM_PER_INCH = 25.4;
61 mZoom = 0.25 * PPI / MM_PER_INCH; 48 mZoom = 0.25 * PPI / MM_PER_INCH;
62 49
63 mPageLeftBottom = ORIGIN.clone(); 50 mPageLeftBottom = ORIGIN;
64 mPageRightTop = ORIGIN + INITIAL_PAGE_SIZE; 51 mPageRightTop = ORIGIN + INITIAL_PAGE_SIZE;
65 mViewCentre = ORIGIN + INITIAL_PAGE_SIZE / 2.0; 52 mViewCentre = ORIGIN + INITIAL_PAGE_SIZE / 2.0;
66 53
67 mCanvasLeftBottom = mPageLeftBottom - 3.0 * INITIAL_PAGE_SIZE; 54 mCanvasLeftBottom = mPageLeftBottom - 3.0 * INITIAL_PAGE_SIZE;
68 mCanvasRightTop = mPageRightTop + 3.0 * INITIAL_PAGE_SIZE; 55 mCanvasRightTop = mPageRightTop + 3.0 * INITIAL_PAGE_SIZE;
99 AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL | AttachOptions.EXPAND, 86 AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL | AttachOptions.EXPAND,
100 0, 0); 87 0, 0);
101 88
102 // value, lower, upper, step-inc, page-inc, page-size 89 // value, lower, upper, step-inc, page-inc, page-size
103 // Give the adjustments dummy values until we receive a configure 90 // Give the adjustments dummy values until we receive a configure
104 mHAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 1.0); 91 mHAdjustment = new Adjustment(0.25, 0.0, 1.0, 0.2, 0.5, 0.5);
105 mHAdjustment.addOnValueChanged(&onValueChanged); 92 mHAdjustment.addOnValueChanged(&onValueChanged);
106 mHScrollbar = new HScrollbar(mHAdjustment); 93 mHScrollbar = new HScrollbar(mHAdjustment);
107 attach(mHScrollbar, 94 attach(mHScrollbar,
108 1, 2, 95 1, 2,
109 2, 3, 96 2, 3,
110 AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.SHRINK, 97 AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.SHRINK,
111 0, 0); 98 0, 0);
112 99
113 mVAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 0.4); 100 mVAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 0.5);
114 mVAdjustment.addOnValueChanged(&onValueChanged); 101 mVAdjustment.addOnValueChanged(&onValueChanged);
115 mVScrollbar = new VScrollbar(mVAdjustment); 102 mVScrollbar = new VScrollbar(mVAdjustment);
116 attach(mVScrollbar, 103 attach(mVScrollbar,
117 2, 3, 104 2, 3,
118 1, 2, 105 1, 2,
119 AttachOptions.SHRINK, 106 AttachOptions.SHRINK,
120 AttachOptions.FILL | AttachOptions.EXPAND, 107 AttachOptions.FILL | AttachOptions.EXPAND,
121 0, 0); 108 0, 0);
122 } 109 }
123 110
124 override void rel_zoom(Point screen_datum, double factor) { 111 override void rel_zoom(Point2 screen_datum, double factor) {
125 // Work out pixel distance from current centre to datum, 112 // Work out pixel distance from current centre to datum,
126 // Do the zoom, then work out the new centre that keeps the 113 // Do the zoom, then work out the new centre that keeps the
127 // pixel distance the same 114 // pixel distance the same
128 115
129 Point old_model_datum = screen_to_model(screen_datum); 116 Point2 old_model_datum = screen_to_model(screen_datum);
130 Vector pixel_distance = model_to_screen(old_model_datum - mViewCentre); 117 Vector2 pixel_distance = model_to_screen(old_model_datum - mViewCentre);
131 mZoom = clamp_zoom(factor * mZoom); 118 mZoom = clamp_zoom(factor * mZoom);
132 mViewCentre = old_model_datum - screen_to_model(pixel_distance); 119 mViewCentre = old_model_datum - screen_to_model(pixel_distance);
133 120
134 Point new_model_datum = screen_to_model(screen_datum); 121 Point2 new_model_datum = screen_to_model(screen_datum);
135 122
136 update_adjustments(); 123 update_adjustments();
137 //update_rulers(new_model_datum); 124 //update_rulers(new_model_datum);
138 update_rulers(); 125 update_rulers();
139 queueDraw(); 126 queueDraw();
140 } 127 }
141 128
142 override void rel_pan(Vector screen_displacement) { 129 override void rel_pan(Vector2 screen_displacement) {
143 mViewCentre = mViewCentre + screen_to_model(screen_displacement); 130 mViewCentre = mViewCentre + screen_to_model(screen_displacement);
144 131
145 update_adjustments(); 132 update_adjustments();
146 update_rulers(); 133 update_rulers();
147 queueDraw(); 134 queueDraw();
155 } 142 }
156 143
157 bool onConfigure(GdkEventConfigure * event, Widget widget) { 144 bool onConfigure(GdkEventConfigure * event, Widget widget) {
158 assert(widget is mDrawingArea); 145 assert(widget is mDrawingArea);
159 146
160 mViewSize = new Vector(cast(double)event.width, cast(double)event.height); 147 mViewSize = Vector2(cast(double)event.width, cast(double)event.height);
161 update_adjustments(); 148 update_adjustments();
162 update_rulers(); 149 update_rulers();
163 150
164 151
165 return 1; 152 return true;
166 } 153 }
167 154
168 bool onExpose(GdkEventExpose * event, Widget widget) { 155 bool onExpose(GdkEventExpose * event, Widget widget) {
169 assert(widget is mDrawingArea); 156 assert(widget is mDrawingArea);
170 157
192 cr.fill(); 179 cr.fill();
193 180
194 { 181 {
195 // Make the paper white, with a border 182 // Make the paper white, with a border
196 183
197 Point screen_page_left_bottom = model_to_screen(mPageLeftBottom); 184 Point2 screen_page_left_bottom = model_to_screen(mPageLeftBottom);
198 Point screen_page_right_top = model_to_screen(mPageRightTop); 185 Point2 screen_page_right_top = model_to_screen(mPageRightTop);
199 186
200 cr.setSourceRgba(1.0, 1.0, 1.0, 1.0); 187 cr.setSourceRgba(1.0, 1.0, 1.0, 1.0);
201 rectangle(cr, screen_page_left_bottom, screen_page_right_top); 188 rectangle(cr, screen_page_left_bottom, screen_page_right_top);
202 cr.fill(); 189 cr.fill();
203 190
204 cr.setSourceRgba(0.0, 0.0, 0.0, 1.0); 191 cr.setSourceRgba(0.0, 0.0, 0.0, 1.0);
205 rectangle(cr, screen_page_left_bottom, screen_page_right_top); 192 rectangle(cr, screen_page_left_bottom, screen_page_right_top);
206 cr.stroke(); 193 cr.stroke();
207 } 194 }
208 195
209 return 1; 196 return true;
210 } 197 }
211 198
212 bool onButtonEvent(GdkEventButton * event, Widget widget) { 199 bool onButtonEvent(GdkEventButton * event, Widget widget) {
213 assert(widget is mDrawingArea); 200 assert(widget is mDrawingArea);
214 //writefln("Got button event\n"); 201 //writefln("Got button event\n");
215 202
216 Point screen_point = new Point(event.x + 0.5, event.y + 0.5); 203 Point2 screen_point = Point2(event.x + 0.5, event.y + 0.5);
217 Point model_point = screen_to_model(screen_point); 204 Point2 model_point = screen_to_model(screen_point);
218 205
219 auto button_event = new ButtonEvent(gtk2tk_click(event.type), 206 auto button_event = new ButtonEvent(gtk2tk_click(event.type),
220 gtk2tk_button(event.button), 207 gtk2tk_button(event.button),
221 screen_point, 208 screen_point,
222 model_point, 209 model_point,
223 gtk2tk_mask(event.state)); 210 gtk2tk_mask(event.state));
224 211
225 //mEventHandle.handle_button_press 212 //mEventHandle.handle_button_press
226 213
227 return 1; 214 return true;
228 } 215 }
229 216
230 bool onKeyEvent(GdkEventKey * event, Widget widget) { 217 bool onKeyEvent(GdkEventKey * event, Widget widget) {
231 assert(widget is mDrawingArea); 218 assert(widget is mDrawingArea);
232 //writefln("Got key event\n"); 219 //writefln("Got key event\n");
233 220
234 //auto key_event = new KeyEvent("", 221 //auto key_event = new KeyEvent("",
235 // mEventHandle.handle_key(key_event); 222 // mEventHandle.handle_key(key_event);
236 223
237 return 1; 224 return true;
238 } 225 }
239 226
240 bool onMotionNotify(GdkEventMotion * event, Widget widget) { 227 bool onMotionNotify(GdkEventMotion * event, Widget widget) {
241 assert(widget is mDrawingArea); 228 assert(widget is mDrawingArea);
242 //writefln("Got motion notify\n"); 229 //writefln("Got motion notify\n");
243 gtk_widget_event(mHRuler.getWidgetStruct(), cast(GdkEvent *)event); 230 gtk_widget_event(mHRuler.getWidgetStruct(), cast(GdkEvent *)event);
244 gtk_widget_event(mVRuler.getWidgetStruct(), cast(GdkEvent *)event); 231 gtk_widget_event(mVRuler.getWidgetStruct(), cast(GdkEvent *)event);
245 232
246 Point screen_point = new Point(event.x + 0.5, event.y + 0.5); 233 Point2 screen_point = Point2(event.x + 0.5, event.y + 0.5);
247 Point model_point = screen_to_model(screen_point); 234 Point2 model_point = screen_to_model(screen_point);
248 235
249 auto motion_event = new MotionEvent(screen_point, 236 auto motion_event = new MotionEvent(screen_point,
250 model_point, 237 model_point,
251 gtk2tk_mask(event.state)); 238 gtk2tk_mask(event.state));
252 239
253 mEventHandler.handle_motion(this, motion_event); 240 mEventHandler.handle_motion(this, motion_event);
254 241
255 return 1; 242 return true;
256 } 243 }
257 244
258 bool onScroll(GdkEventScroll * event, Widget widget) { 245 bool onScroll(GdkEventScroll * event, Widget widget) {
259 assert(widget is mDrawingArea); 246 assert(widget is mDrawingArea);
260 //writefln("Got scroll\n"); 247 //writefln("Got scroll\n");
261 248
262 Point screen_point = new Point(event.x + 0.5, event.y + 0.5); 249 Point2 screen_point = Point2(event.x + 0.5, event.y + 0.5);
263 Point model_point = screen_to_model(screen_point); 250 Point2 model_point = screen_to_model(screen_point);
264 251
265 auto scroll_event = new ScrollEvent(gtk2tk_direction(event.direction), 252 auto scroll_event = new ScrollEvent(gtk2tk_direction(event.direction),
266 screen_point, 253 screen_point,
267 model_point, 254 model_point,
268 gtk2tk_mask(event.state)); 255 gtk2tk_mask(event.state));
269 256
270 mEventHandler.handle_scroll(this, scroll_event); 257 mEventHandler.handle_scroll(this, scroll_event);
271 258
272 return 1; 259 return true;
273 } 260 }
274 261
275 void onValueChanged(Adjustment adjustment) { 262 void onValueChanged(Adjustment adjustment) {
276 GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct(); 263 GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct();
277 GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct(); 264 GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct();
278 265
279 Point view_left_bottom = new Point(h_gtkAdjustment.value, v_gtkAdjustment.value); 266 Point2 view_left_bottom = Point2(gtk_adjustment_get_value(h_gtkAdjustment),
267 gtk_adjustment_get_value(v_gtkAdjustment));
280 writefln("%s", view_left_bottom); 268 writefln("%s", view_left_bottom);
281 Vector model_size = screen_to_model(mViewSize); 269 Vector2 model_size = screen_to_model(mViewSize);
282 mViewCentre = view_left_bottom + model_size / 2.0; 270 mViewCentre = view_left_bottom + model_size / 2.0;
283 271
284 update_rulers(); 272 update_rulers();
285 273
286 queueDraw(); 274 queueDraw();
287 } 275 }
288 276
289 void update_rulers() { 277 void update_rulers() {
290 Vector model_size = screen_to_model(mViewSize); 278 Vector2 model_size = screen_to_model(mViewSize);
291 279
292 Point view_left_bottom = mViewCentre - model_size / 2.0; 280 Point2 view_left_bottom = mViewCentre - model_size / 2.0;
293 Point view_right_top = mViewCentre + model_size / 2.0; 281 Point2 view_right_top = mViewCentre + model_size / 2.0;
294 282
295 mHRuler.setRange(view_left_bottom.x, 283 mHRuler.setRange(view_left_bottom.x,
296 view_right_top.x, 284 view_right_top.x,
297 0.0, // TODO preserve the value 285 0.0, // TODO preserve the value
298 mZoom * 2000.0); 286 mZoom * 2000.0);
301 0.0, 289 0.0,
302 mZoom * 2000.0); 290 mZoom * 2000.0);
303 } 291 }
304 292
305 void update_adjustments() { 293 void update_adjustments() {
306 Vector model_size = screen_to_model(mViewSize); 294 Vector2 model_size = screen_to_model(mViewSize);
307 295
308 Point view_left_bottom = mViewCentre - model_size / 2.0; 296 Point2 view_left_bottom = mViewCentre - model_size / 2.0;
309 Point view_right_top = mViewCentre + model_size / 2.0; 297 Point2 view_right_top = mViewCentre + model_size / 2.0;
310 298
311 // Adjust the canvas size if necessary 299 // Adjust the canvas size if necessary
312 mCanvasLeftBottom = min_extents(mCanvasLeftBottom, view_left_bottom); 300 mCanvasLeftBottom = min_extents(mCanvasLeftBottom, view_left_bottom);
313 mCanvasRightTop = max_extents(mCanvasRightTop, view_right_top); 301 mCanvasRightTop = max_extents(mCanvasRightTop, view_right_top);
314 302
315 Vector canvas_size = mCanvasRightTop - mCanvasLeftBottom; 303 Vector2 canvas_size = mCanvasRightTop - mCanvasLeftBottom;
316 Vector page_size = mPageRightTop - mPageLeftBottom; 304 Vector2 page_size = mPageRightTop - mPageLeftBottom;
317 305
318 // Update the adjustments 306 // Update the adjustments
319 307
320 GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct(); 308 GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct();
321 GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct(); 309 GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct();
322 310
323 h_gtkAdjustment.lower = mCanvasLeftBottom.x; 311 gtk_adjustment_set_lower(h_gtkAdjustment, mCanvasLeftBottom.x);
324 h_gtkAdjustment.upper = mCanvasRightTop.x; 312 gtk_adjustment_set_upper(h_gtkAdjustment, mCanvasRightTop.x);
325 h_gtkAdjustment.value = view_left_bottom.x; 313 gtk_adjustment_set_value(h_gtkAdjustment, view_left_bottom.x);
326 h_gtkAdjustment.step_increment = canvas_size.x / 10.0; 314 gtk_adjustment_set_step_increment(h_gtkAdjustment, canvas_size.x / 10.0);
327 h_gtkAdjustment.page_increment = canvas_size.x / 5.0; 315 gtk_adjustment_set_page_increment(h_gtkAdjustment, canvas_size.x / 5.0);
328 h_gtkAdjustment.page_size = model_size.x; 316 gtk_adjustment_set_page_size(h_gtkAdjustment, model_size.x);
329 317
330 v_gtkAdjustment.lower = mCanvasLeftBottom.y; 318 gtk_adjustment_set_lower(v_gtkAdjustment, mCanvasLeftBottom.y);
331 v_gtkAdjustment.upper = mCanvasRightTop.y; 319 gtk_adjustment_set_upper(v_gtkAdjustment, mCanvasRightTop.y);
332 v_gtkAdjustment.value = view_left_bottom.y; 320 gtk_adjustment_set_value(v_gtkAdjustment, view_left_bottom.y);
333 v_gtkAdjustment.step_increment = canvas_size.y / 10.0; 321 gtk_adjustment_set_step_increment(v_gtkAdjustment, canvas_size.y / 10.0);
334 v_gtkAdjustment.page_increment = canvas_size.y / 5.0; 322 gtk_adjustment_set_page_increment(v_gtkAdjustment, canvas_size.y / 5.0);
335 v_gtkAdjustment.page_size = model_size.y; 323 gtk_adjustment_set_page_size(v_gtkAdjustment, model_size.y);
336 324
337 mHAdjustment.changed(); 325 mHAdjustment.changed();
338 mHAdjustment.valueChanged(); 326 mHAdjustment.valueChanged();
339 mVAdjustment.changed(); 327 mVAdjustment.changed();
340 mVAdjustment.valueChanged(); 328 mVAdjustment.valueChanged();
341 } 329 }
342 330
343 Point model_to_screen(Point model) { return ORIGIN + mViewSize / 2.0 + mZoom * (model - mViewCentre); } 331 Point2 model_to_screen(Point2 model) { return ORIGIN + mViewSize / 2.0 + mZoom * (model - mViewCentre); }
344 Point screen_to_model(Point screen) { return mViewCentre + (screen - mViewSize / 2.0 - ORIGIN) / mZoom; } 332 Point2 screen_to_model(Point2 screen) { return mViewCentre + (screen - mViewSize / 2.0 - ORIGIN) / mZoom; }
345 Vector model_to_screen(Vector model) { return mZoom * model; } 333 Vector2 model_to_screen(Vector2 model) { return mZoom * model; }
346 Vector screen_to_model(Vector screen) { return screen / mZoom; } 334 Vector2 screen_to_model(Vector2 screen) { return screen / mZoom; }
347 double model_to_screen(double model) { return mZoom * model; } 335 double model_to_screen(double model) { return mZoom * model; }
348 double screen_to_model(double screen) { return screen / mZoom; } 336 double screen_to_model(double screen) { return screen / mZoom; }
349 337
350 double clamp_zoom(double zoom) { return clamp(zoom, 0.1, 10.0); } 338 double clamp_zoom(double zoom) { return clamp(zoom, 0.1, 10.0); }
351 339
352 static const Point ORIGIN; 340 static const Point2 ORIGIN;
353 static const Vector INITIAL_PAGE_SIZE; 341 static const Vector2 INITIAL_PAGE_SIZE;
354 342
355 ICanvasEventHandler mEventHandler; 343 ICanvasEventHandler mEventHandler;
356 344
357 // Model units are in millimetres 345 // Model units are in millimetres
358 // Screen units are in pixels 346 // Screen units are in pixels
359 347
360 double mZoom; // pixels-per-mm 348 double mZoom; // pixels-per-mm
361 Point mViewCentre; // model: where in the model is the centre of our view 349 Point2 mViewCentre; // model: where in the model is the centre of our view
362 350
363 Point mCanvasLeftBottom; // model: bottom left corner of canvas 351 Point2 mCanvasLeftBottom; // model: bottom left corner of canvas
364 Point mCanvasRightTop; // model: top right corner of canvas 352 Point2 mCanvasRightTop; // model: top right corner of canvas
365 Point mPageLeftBottom; // model: bottom left corner of page 353 Point2 mPageLeftBottom; // model: bottom left corner of page
366 Point mPageRightTop; // model: top right corner of page 354 Point2 mPageRightTop; // model: top right corner of page
367 355
368 Vector mViewSize; // screen: size of view window in pixels 356 Vector2 mViewSize; // screen: size of view window in pixels
369 357
370 HRuler mHRuler; 358 HRuler mHRuler;
371 VRuler mVRuler; 359 VRuler mVRuler;
372 DrawingArea mDrawingArea; 360 DrawingArea mDrawingArea;
373 Adjustment mHAdjustment; 361 Adjustment mHAdjustment;