Mercurial > projects > doodle
comparison canvas.d @ 13:f0ade1b49fe7
Checkpoint
author | "David Bryant <bagnose@gmail.com>" |
---|---|
date | Sun, 12 Jul 2009 01:04:35 +0930 |
parents | a093c4fbdd43 |
children | 0b7e7d43a79d |
comparison
equal
deleted
inserted
replaced
12:a093c4fbdd43 | 13:f0ade1b49fe7 |
---|---|
36 this(in Layer[] layers, EventHandler event_handler, in double ppi) { | 36 this(in Layer[] layers, EventHandler event_handler, in double ppi) { |
37 super(3, 3, 0); | 37 super(3, 3, 0); |
38 | 38 |
39 mLayers = layers.dup; | 39 mLayers = layers.dup; |
40 mEventHandler = event_handler; | 40 mEventHandler = event_handler; |
41 mPPI = ppi; | |
41 | 42 |
42 const double MM_PER_INCH = 25.4; | 43 const double MM_PER_INCH = 25.4; |
43 mZoom = 0.25 * ppi / MM_PER_INCH; | 44 mZoom = 0.25 * mPPI / MM_PER_INCH; |
45 | |
46 // Take the union of the bounds of each layer to | |
47 // determine the canvas size | |
44 | 48 |
45 Rectangle total_layer_bounds; | 49 Rectangle total_layer_bounds; |
46 | 50 |
47 foreach (ref layer; mLayers) { | 51 foreach (ref layer; mLayers) { |
48 total_layer_bounds = total_layer_bounds | layer.bounds; | 52 total_layer_bounds = total_layer_bounds | layer.bounds; |
49 } | 53 } |
54 | |
55 assert(total_layer_bounds.valid); | |
50 | 56 |
51 mCanvasLeftBottom = total_layer_bounds.min_corner - total_layer_bounds.size; | 57 mCanvasLeftBottom = total_layer_bounds.min_corner - total_layer_bounds.size; |
52 mCanvasRightTop = total_layer_bounds.max_corner + total_layer_bounds.size; | 58 mCanvasRightTop = total_layer_bounds.max_corner + total_layer_bounds.size; |
53 mViewCentre = mCanvasLeftBottom + (mCanvasRightTop - mCanvasLeftBottom) / 2.0; | 59 mViewCentre = mCanvasLeftBottom + (mCanvasRightTop - mCanvasLeftBottom) / 2.0; |
54 | 60 |
55 mHRuler = new HRuler(); | 61 // Create our child widgets and register callbacks |
62 | |
63 mHRuler = new HRuler; | |
56 attach(mHRuler, | 64 attach(mHRuler, |
57 1, 2, | 65 1, 2, |
58 0, 1, | 66 0, 1, |
59 AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.SHRINK, | 67 AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.SHRINK, |
60 0, 0); | 68 0, 0); |
61 mHRuler.setMetric(GtkMetricType.CENTIMETERS); | 69 mHRuler.setMetric(GtkMetricType.CENTIMETERS); |
62 | 70 |
63 mVRuler = new VRuler(); | 71 mVRuler = new VRuler; |
64 attach(mVRuler, | 72 attach(mVRuler, |
65 0, 1, | 73 0, 1, |
66 1, 2, | 74 1, 2, |
67 AttachOptions.SHRINK, AttachOptions.FILL | AttachOptions.EXPAND, | 75 AttachOptions.SHRINK, AttachOptions.FILL | AttachOptions.EXPAND, |
68 0, 0); | 76 0, 0); |
69 mVRuler.setMetric(GtkMetricType.CENTIMETERS); | 77 mVRuler.setMetric(GtkMetricType.CENTIMETERS); |
70 | 78 |
71 mDrawingArea = new DrawingArea(); | 79 mDrawingArea = new DrawingArea; |
72 mDrawingArea.addOnRealize(&onRealize); | 80 mDrawingArea.addOnRealize(&onRealize); |
73 mDrawingArea.addOnConfigure(&onConfigure); | 81 mDrawingArea.addOnConfigure(&onConfigure); |
74 mDrawingArea.addOnExpose(&onExpose); | 82 mDrawingArea.addOnExpose(&onExpose); |
75 mDrawingArea.addOnButtonPress(&onButtonPress); | 83 mDrawingArea.addOnButtonPress(&onButtonPress); |
76 mDrawingArea.addOnButtonRelease(&onButtonRelease); | 84 mDrawingArea.addOnButtonRelease(&onButtonRelease); |
116 mZoom = clamp_zoom(factor * mZoom); | 124 mZoom = clamp_zoom(factor * mZoom); |
117 mViewCentre = old_model_datum - screen_to_model(pixel_distance); | 125 mViewCentre = old_model_datum - screen_to_model(pixel_distance); |
118 | 126 |
119 //Point new_model_datum = screen_to_model(screen_datum); | 127 //Point new_model_datum = screen_to_model(screen_datum); |
120 | 128 |
121 update_adjustments(); | 129 update_adjustments; |
122 //update_rulers(new_model_datum); | 130 //update_rulers(new_model_datum); |
123 update_rulers(); | 131 update_rulers; |
124 queueDraw(); | 132 queueDraw; |
125 } | 133 } |
126 | 134 |
127 override void rel_pan(Vector screen_displacement) { | 135 override void rel_pan(Vector screen_displacement) { |
128 mViewCentre = mViewCentre + screen_to_model(screen_displacement); | 136 mViewCentre = mViewCentre + screen_to_model(screen_displacement); |
129 | 137 |
130 update_adjustments(); | 138 update_adjustments; |
131 update_rulers(); | 139 update_rulers; |
132 queueDraw(); | 140 queueDraw; |
133 } | 141 } |
134 | 142 |
135 override double zoom() const { return mZoom; } | 143 override double zoom() const { |
136 override Point model_to_screen(Point model) const { return Point.DEFAULT + mViewSize / 2.0 + mZoom * (model - mViewCentre); } | 144 return mZoom; |
137 override Point screen_to_model(Point screen) const { return mViewCentre + (screen - mViewSize / 2.0 - Point.DEFAULT) / mZoom; } | 145 } |
138 override Vector model_to_screen(Vector model) const { return mZoom * model; } | 146 |
139 override Vector screen_to_model(Vector screen) const { return screen / mZoom; } | 147 override Point model_to_screen(Point model) const { |
140 override double model_to_screen(double model) const { return mZoom * model; } | 148 return Point.DEFAULT + mViewSize / 2.0 + mZoom * (model - mViewCentre); |
141 override double screen_to_model(double screen) const { return screen / mZoom; } | 149 } |
142 override Rectangle model_to_screen(Rectangle model) const { return Rectangle(model_to_screen(model.position), model_to_screen(model.size)); } | 150 |
143 override Rectangle screen_to_model(Rectangle model) const { return Rectangle(screen_to_model(model.position), screen_to_model(model.size)); } | 151 override Point screen_to_model(Point screen) const { |
152 return mViewCentre + (screen - mViewSize / 2.0 - Point.DEFAULT) / mZoom; | |
153 } | |
154 | |
155 override Vector model_to_screen(Vector model) const { | |
156 return mZoom * model; | |
157 } | |
158 | |
159 override Vector screen_to_model(Vector screen) const { | |
160 return screen / mZoom; | |
161 } | |
162 | |
163 override double model_to_screen(double model) const { | |
164 return mZoom * model; | |
165 } | |
166 | |
167 override double screen_to_model(double screen) const { | |
168 return screen / mZoom; | |
169 } | |
170 | |
171 override Rectangle model_to_screen(Rectangle model) const { | |
172 return Rectangle(model_to_screen(model.position), model_to_screen(model.size)); | |
173 } | |
174 | |
175 override Rectangle screen_to_model(Rectangle model) const { | |
176 return Rectangle(screen_to_model(model.position), screen_to_model(model.size)); | |
177 } | |
144 | 178 |
145 private { | 179 private { |
146 | 180 |
147 void onRealize(Widget widget) { | 181 void onRealize(Widget widget) { |
148 assert(widget is mDrawingArea); | 182 assert(widget is mDrawingArea); |
151 | 185 |
152 bool onConfigure(GdkEventConfigure * event, Widget widget) { | 186 bool onConfigure(GdkEventConfigure * event, Widget widget) { |
153 assert(widget is mDrawingArea); | 187 assert(widget is mDrawingArea); |
154 | 188 |
155 mViewSize = Vector(cast(double)event.width, cast(double)event.height); | 189 mViewSize = Vector(cast(double)event.width, cast(double)event.height); |
156 update_adjustments(); | 190 update_adjustments; |
157 update_rulers(); | 191 update_rulers; |
158 | 192 |
159 | 193 |
160 return true; | 194 return true; |
161 } | 195 } |
162 | 196 |
163 bool onExpose(GdkEventExpose * event, Widget widget) { | 197 bool onExpose(GdkEventExpose * event, Widget widget) { |
164 assert(widget is mDrawingArea); | 198 assert(widget is mDrawingArea); |
165 | 199 |
166 Drawable dr = mDrawingArea.getWindow(); | 200 Drawable dr = mDrawingArea.getWindow; |
167 | 201 |
168 int width, height; | 202 int width, height; |
169 dr.getSize(width, height); | 203 dr.getSize(width, height); |
170 //writefln("Got expose %dx%d\n", width, height); | 204 //writefln("Got expose %dx%d\n", width, height); |
171 | 205 |
176 event is null ? | 210 event is null ? |
177 Rectangle(Point(0.0, 0.0), Vector(cast(double)width, cast(double)height)) : | 211 Rectangle(Point(0.0, 0.0), Vector(cast(double)width, cast(double)height)) : |
178 Rectangle(Point(cast(double)event.area.x, cast(double)event.area.y), | 212 Rectangle(Point(cast(double)event.area.x, cast(double)event.area.y), |
179 Vector(cast(double)event.area.width, cast(double)event.area.height)); | 213 Vector(cast(double)event.area.width, cast(double)event.area.height)); |
180 | 214 |
181 model_cr.save(); screen_cr.save(); { | 215 model_cr.save; screen_cr.save; { |
182 // Setup model context | 216 // Setup model context |
183 | 217 |
184 rectangle(model_cr, damage); | 218 rectangle(model_cr, damage); |
185 model_cr.clip(); | 219 model_cr.clip; |
186 | 220 |
187 GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct(); | 221 GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct(); |
188 GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct(); | 222 GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct(); |
189 | 223 |
190 model_cr.translate(mCanvasLeftBottom.x - gtk_adjustment_get_value(h_gtkAdjustment), | 224 model_cr.translate(mCanvasLeftBottom.x - gtk_adjustment_get_value(h_gtkAdjustment), |
191 mCanvasLeftBottom.y - gtk_adjustment_get_value(v_gtkAdjustment)); | 225 mCanvasLeftBottom.y - gtk_adjustment_get_value(v_gtkAdjustment)); |
192 model_cr.scale(mZoom, mZoom); | 226 model_cr.scale(mZoom, -mZoom); |
193 | 227 |
194 // Setup screen context | 228 // Setup screen context |
195 | 229 |
230 screen_cr.translate(0.0, mViewSize.y); | |
231 screen_cr.scale(1.0, -1.0); | |
196 rectangle(screen_cr, damage); | 232 rectangle(screen_cr, damage); |
197 screen_cr.clip(); | 233 screen_cr.clip; |
198 | 234 |
199 // Fill the background | 235 // Fill the background |
200 | 236 |
201 screen_cr.save(); { | 237 screen_cr.save; { |
202 // Make the window light grey | 238 // Make the window light grey |
203 screen_cr.setSourceRgba(1.0, 1.0, 1.0, 0.7); | 239 screen_cr.setSourceRgba(1.0, 1.0, 1.0, 0.7); |
204 rectangle(screen_cr, damage); | 240 rectangle(screen_cr, damage); |
205 screen_cr.fill(); | 241 screen_cr.fill; |
206 } screen_cr.restore(); | 242 } screen_cr.restore; |
207 | 243 |
208 // Draw each layer | 244 // Draw each layer |
209 | 245 |
210 foreach(ref layer; mLayers) { | 246 foreach(ref layer; mLayers) { |
211 model_cr.save(); screen_cr.save(); { | 247 model_cr.save; screen_cr.save; { |
212 layer.draw(this, damage, model_cr, screen_cr); | 248 layer.draw(this, damage, model_cr, screen_cr); |
213 } screen_cr.restore(); model_cr.restore(); | 249 } screen_cr.restore; model_cr.restore; |
214 } | 250 } |
215 } screen_cr.restore(); model_cr.restore(); | 251 } screen_cr.restore; model_cr.restore; |
216 | 252 |
217 return true; | 253 return true; |
218 } | 254 } |
219 | 255 |
220 bool onButtonPress(GdkEventButton * event, Widget widget) { | 256 bool onButtonPress(GdkEventButton * event, Widget widget) { |
297 | 333 |
298 return true; | 334 return true; |
299 } | 335 } |
300 | 336 |
301 void onValueChanged(Adjustment adjustment) { | 337 void onValueChanged(Adjustment adjustment) { |
302 GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct(); | 338 GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct; |
303 GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct(); | 339 GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct; |
304 | 340 |
305 Point view_left_bottom = Point(gtk_adjustment_get_value(h_gtkAdjustment), | 341 Point view_left_bottom = Point(gtk_adjustment_get_value(h_gtkAdjustment), |
306 gtk_adjustment_get_value(v_gtkAdjustment)); | 342 gtk_adjustment_get_value(v_gtkAdjustment)); |
307 //writefln("%s", view_left_bottom); | 343 //writefln("%s", view_left_bottom); |
308 Vector model_size = screen_to_model(mViewSize); | 344 Vector model_size = screen_to_model(mViewSize); |
309 mViewCentre = view_left_bottom + model_size / 2.0; | 345 mViewCentre = view_left_bottom + model_size / 2.0; |
310 | 346 |
311 update_rulers(); | 347 update_rulers; |
312 | 348 |
313 queueDraw(); | 349 queueDraw; |
314 } | 350 } |
315 | 351 |
316 void update_rulers() { | 352 void update_rulers() { |
317 Vector model_size = screen_to_model(mViewSize); | 353 Vector model_size = screen_to_model(mViewSize); |
318 | 354 |
363 gtk_adjustment_set_value(v_gtkAdjustment, view_left_bottom.y); | 399 gtk_adjustment_set_value(v_gtkAdjustment, view_left_bottom.y); |
364 gtk_adjustment_set_step_increment(v_gtkAdjustment, canvas_size.y / 10.0); | 400 gtk_adjustment_set_step_increment(v_gtkAdjustment, canvas_size.y / 10.0); |
365 gtk_adjustment_set_page_increment(v_gtkAdjustment, canvas_size.y / 5.0); | 401 gtk_adjustment_set_page_increment(v_gtkAdjustment, canvas_size.y / 5.0); |
366 gtk_adjustment_set_page_size(v_gtkAdjustment, model_size.y); | 402 gtk_adjustment_set_page_size(v_gtkAdjustment, model_size.y); |
367 | 403 |
368 mHAdjustment.changed(); | 404 mHAdjustment.changed; |
369 mHAdjustment.valueChanged(); | 405 mHAdjustment.valueChanged; |
370 mVAdjustment.changed(); | 406 mVAdjustment.changed; |
371 mVAdjustment.valueChanged(); | 407 mVAdjustment.valueChanged; |
372 } | 408 } |
373 | 409 |
374 double clamp_zoom(double zoom) { return clamp(zoom, 0.02, 50.0); } | 410 double clamp_zoom(double zoom) { return clamp(zoom, 0.02, 50.0); } |
375 | |
376 EventHandler mEventHandler; | |
377 | 411 |
378 // Model units are in millimetres | 412 // Model units are in millimetres |
379 // Screen units are in pixels | 413 // Screen units are in pixels |
380 | 414 |
381 double mZoom; // pixels-per-model-unit (mm) | 415 double mZoom; // pixels-per-model-unit (mm) |
395 Adjustment mVAdjustment; | 429 Adjustment mVAdjustment; |
396 VScrollbar mVScrollbar; | 430 VScrollbar mVScrollbar; |
397 | 431 |
398 // Layers: | 432 // Layers: |
399 Layer[] mLayers; | 433 Layer[] mLayers; |
434 EventHandler mEventHandler; | |
435 double mPPI; | |
400 } | 436 } |
401 } | 437 } |