Mercurial > projects > doodle
annotate doodle/gtk/canvas.d @ 41:f2e4e1d29b98
Bah
author | daveb |
---|---|
date | Tue, 01 Jun 2010 17:21:01 +0930 |
parents | 1f97022e5c6d |
children | 1b4c9ba58673 |
rev | line source |
---|---|
28
1754cb773d41
Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents:
27
diff
changeset
|
1 module doodle.gtk.canvas; |
0 | 2 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
3 public { |
28
1754cb773d41
Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents:
27
diff
changeset
|
4 import doodle.dia.icanvas; |
1754cb773d41
Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents:
27
diff
changeset
|
5 import doodle.tk.events; |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
6 } |
0 | 7 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
8 private { |
40 | 9 import doodle.core.logging; |
28
1754cb773d41
Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents:
27
diff
changeset
|
10 import doodle.gtk.conversions; |
1754cb773d41
Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents:
27
diff
changeset
|
11 import doodle.tk.misc; |
1754cb773d41
Part-way through getting to compile with configure/builder.
Graham St Jack <graham.stjack@internode.on.net>
parents:
27
diff
changeset
|
12 import doodle.cairo.routines; |
0 | 13 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
14 import cairo.Surface; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
15 |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
16 import std.math; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
17 import std.stdio; |
0 | 18 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
19 import gtk.Widget; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
20 import gtk.Toolbar; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
21 import gtk.Table; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
22 import gtk.HRuler; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
23 import gtk.VRuler; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
24 import gtk.Range; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
25 import gtk.HScrollbar; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
26 import gtk.VScrollbar; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
27 import gtk.DrawingArea; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
28 import gtk.Adjustment; |
0 | 29 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
30 import gdk.Drawable; |
0 | 31 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
32 import gtkc.gtk; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
33 } |
0 | 34 |
35 // x and y run right and up respectively | |
41 | 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 | |
0 | 48 |
10 | 49 class Canvas : Table, Viewport { |
35 | 50 this(in Layer[] layers, EventHandler event_handler, Grid grid, in double ppi) { |
0 | 51 super(3, 3, 0); |
52 | |
17 | 53 mDamage = Rectangle.DEFAULT; |
54 | |
11 | 55 mLayers = layers.dup; |
0 | 56 mEventHandler = event_handler; |
35 | 57 mGrid = grid; |
13 | 58 mPPI = ppi; |
0 | 59 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
60 /* |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
61 writefln("Layer bounds: %s", layer_bounds); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
62 writefln("Canvas bounds: %s", mCanvasBounds); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
63 writefln("View centre: %s", mViewCentre); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
64 */ |
0 | 65 |
13 | 66 // Create our child widgets and register callbacks |
67 | |
40 | 68 info("B1"); |
13 | 69 mHRuler = new HRuler; |
0 | 70 attach(mHRuler, |
71 1, 2, | |
72 0, 1, | |
73 AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.SHRINK, | |
74 0, 0); | |
20 | 75 mHRuler.setMetric(MetricType.PIXELS); |
0 | 76 |
40 | 77 info("B2"); |
13 | 78 mVRuler = new VRuler; |
0 | 79 attach(mVRuler, |
80 0, 1, | |
81 1, 2, | |
82 AttachOptions.SHRINK, AttachOptions.FILL | AttachOptions.EXPAND, | |
83 0, 0); | |
40 | 84 info("B3"); |
20 | 85 mVRuler.setMetric(MetricType.PIXELS); |
40 | 86 info("J"); |
0 | 87 |
13 | 88 mDrawingArea = new DrawingArea; |
27 | 89 mDrawingArea.addOnRealize(&on_realize); |
90 mDrawingArea.addOnConfigure(&on_configure); | |
91 mDrawingArea.addOnExpose(&on_expose); | |
92 mDrawingArea.addOnButtonPress(&on_button_press); | |
93 mDrawingArea.addOnButtonRelease(&on_button_release); | |
94 mDrawingArea.addOnKeyPress(&on_key_event); | |
95 mDrawingArea.addOnKeyRelease(&on_key_event); | |
96 mDrawingArea.addOnMotionNotify(&on_motion_notify); | |
97 mDrawingArea.addOnScroll(&on_scroll); | |
98 mDrawingArea.addOnEnterNotify(&on_enter_notify); | |
99 mDrawingArea.addOnLeaveNotify(&on_leave_notify); | |
20 | 100 mDrawingArea.setEvents(EventMask.EXPOSURE_MASK | |
101 EventMask.POINTER_MOTION_MASK | | |
102 EventMask.POINTER_MOTION_HINT_MASK | | |
103 EventMask.BUTTON_MOTION_MASK | | |
104 EventMask.BUTTON_PRESS_MASK | | |
105 EventMask.BUTTON_RELEASE_MASK | | |
106 EventMask.KEY_PRESS_MASK | | |
107 EventMask.KEY_RELEASE_MASK | | |
108 EventMask.ENTER_NOTIFY_MASK | | |
109 EventMask.LEAVE_NOTIFY_MASK | | |
110 EventMask.FOCUS_CHANGE_MASK | | |
111 EventMask.SCROLL_MASK); | |
40 | 112 info("M"); |
20 | 113 |
0 | 114 attach(mDrawingArea, |
115 1, 2, | |
116 1, 2, | |
117 AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL | AttachOptions.EXPAND, | |
118 0, 0); | |
119 | |
120 // value, lower, upper, step-inc, page-inc, page-size | |
121 // Give the adjustments dummy values until we receive a configure | |
12 | 122 mHAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 0.5); |
0 | 123 mHAdjustment.addOnValueChanged(&onValueChanged); |
124 mHScrollbar = new HScrollbar(mHAdjustment); | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
125 mHScrollbar.setInverted(false); |
0 | 126 attach(mHScrollbar, |
127 1, 2, | |
128 2, 3, | |
129 AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.SHRINK, | |
130 0, 0); | |
40 | 131 info("Q"); |
0 | 132 |
2
d6f44347373d
* Switched over to geometry done with structs instead of classes.
David Bryant <daveb@acres.com.au>
parents:
0
diff
changeset
|
133 mVAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 0.5); |
0 | 134 mVAdjustment.addOnValueChanged(&onValueChanged); |
135 mVScrollbar = new VScrollbar(mVAdjustment); | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
136 mVScrollbar.setInverted(true); |
0 | 137 attach(mVScrollbar, |
138 2, 3, | |
139 1, 2, | |
140 AttachOptions.SHRINK, | |
141 AttachOptions.FILL | AttachOptions.EXPAND, | |
142 0, 0); | |
143 } | |
144 | |
26 | 145 override void zoom_relative(in Point pixel_datum, in double factor) { |
0 | 146 // Work out pixel distance from current centre to datum, |
147 // Do the zoom, then work out the new centre that keeps the | |
148 // pixel distance the same | |
149 | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
150 Point old_model_datum = pixel_to_model(pixel_datum); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
151 Vector pixel_distance = model_to_pixel(old_model_datum - mViewCentre); |
0 | 152 mZoom = clamp_zoom(factor * mZoom); |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
153 mViewCentre = old_model_datum - pixel_to_model(pixel_distance); |
0 | 154 |
13 | 155 update_adjustments; |
156 update_rulers; | |
35 | 157 mGrid.zoom_changed(mZoom); |
13 | 158 queueDraw; |
0 | 159 } |
160 | |
26 | 161 override void pan_relative(in Vector pixel_displacement) { |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
162 mViewCentre = mViewCentre + pixel_to_model(pixel_displacement); |
0 | 163 |
13 | 164 update_adjustments; |
165 update_rulers; | |
166 queueDraw; | |
167 } | |
168 | |
27 | 169 override void set_cursor(in Cursor cursor) { |
170 CursorType cursor_type; | |
171 | |
172 switch (cursor) { | |
173 case Cursor.DEFAULT: | |
174 cursor_type = CursorType.ARROW; | |
175 break; | |
176 case Cursor.HAND: | |
177 cursor_type = CursorType.HAND1; | |
178 break; | |
179 case Cursor.CROSSHAIR: | |
180 cursor_type = CursorType.CROSSHAIR; | |
181 break; | |
40 | 182 default: |
183 assert(0); | |
27 | 184 } |
185 | |
186 mDrawingArea.setCursor(new gdk.Cursor.Cursor(cursor_type)); | |
187 } | |
188 | |
26 | 189 override void damage_model(in Rectangle area) { |
17 | 190 mDamage = mDamage | model_to_pixel(area); |
191 } | |
192 | |
26 | 193 override void damage_pixel(in Rectangle area) { |
18 | 194 mDamage = mDamage | area; |
195 } | |
196 | |
0 | 197 private { |
198 | |
41 | 199 void update_bounds() { |
200 } | |
201 | |
202 | |
27 | 203 bool on_configure(GdkEventConfigure * event, Widget widget) { |
0 | 204 assert(widget is mDrawingArea); |
205 | |
41 | 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 | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
218 if (!mHadConfigure) { |
41 | 219 info("1"); |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
220 const double MM_PER_INCH = 25.4; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
221 mZoom = 0.25 * mPPI / MM_PER_INCH; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
222 |
41 | 223 mCanvasBounds = padded_layer_bounds; |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
224 mViewCentre = mCanvasBounds.centre; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
225 |
35 | 226 mGrid.zoom_changed(mZoom); |
227 | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
228 mHadConfigure = true; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
229 } |
41 | 230 else { |
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 } | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
238 |
13 | 239 update_adjustments; |
240 update_rulers; | |
0 | 241 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
242 //writefln("Canvas bounds: %s", mCanvasBounds); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
243 //writefln("View centre: %s", mViewCentre); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
244 |
2
d6f44347373d
* Switched over to geometry done with structs instead of classes.
David Bryant <daveb@acres.com.au>
parents:
0
diff
changeset
|
245 return true; |
0 | 246 } |
247 | |
27 | 248 bool on_expose(GdkEventExpose * event, Widget widget) { |
0 | 249 assert(widget is mDrawingArea); |
250 | |
13 | 251 Drawable dr = mDrawingArea.getWindow; |
0 | 252 |
253 int width, height; | |
254 dr.getSize(width, height); | |
255 //writefln("Got expose %dx%d\n", width, height); | |
256 | |
12 | 257 scope model_cr = new Context(dr); |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
258 scope pixel_cr = new Context(dr); |
12 | 259 |
19 | 260 Rectangle pixel_damage = |
11 | 261 event is null ? |
19 | 262 Rectangle(Point(0.0, 0.0), mViewSize) : |
263 Rectangle(Point(cast(double)event.area.x, mViewSize.y - cast(double)(event.area.y + event.area.height)), | |
11 | 264 Vector(cast(double)event.area.width, cast(double)event.area.height)); |
0 | 265 |
19 | 266 Rectangle model_damage = pixel_to_model(pixel_damage); |
267 | |
268 //writefln("Pixel damage: %s, model damage: %s", pixel_damage, model_damage); | |
269 | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
270 model_cr.save; pixel_cr.save; { |
19 | 271 // Setup model context and clip |
12 | 272 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
273 GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
274 GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct; |
12 | 275 |
13 | 276 model_cr.scale(mZoom, -mZoom); |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
277 model_cr.translate(-gtk_adjustment_get_value(h_gtkAdjustment), |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
278 -gtk_adjustment_get_value(v_gtkAdjustment) - gtk_adjustment_get_page_size(v_gtkAdjustment)); |
0 | 279 |
19 | 280 rectangle(model_cr, model_damage); |
281 model_cr.clip; | |
282 | |
283 // Setup pixel context and clip | |
12 | 284 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
285 pixel_cr.translate(0.0, mViewSize.y); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
286 pixel_cr.scale(1.0, -1.0); |
19 | 287 |
288 rectangle(pixel_cr, pixel_damage); | |
289 pixel_cr.clip; | |
12 | 290 |
291 // Fill the background | |
292 | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
293 pixel_cr.save; { |
11 | 294 // Make the window light grey |
41 | 295 pixel_cr.setSourceRgba(0.9, 0.9, 0.9, 1.0); |
19 | 296 rectangle(pixel_cr, pixel_damage); |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
297 pixel_cr.fill; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
298 } pixel_cr.restore; |
12 | 299 |
300 // Draw each layer | |
0 | 301 |
11 | 302 foreach(ref layer; mLayers) { |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
303 model_cr.save; pixel_cr.save; { |
19 | 304 layer.draw(this, pixel_damage, pixel_cr, model_damage, model_cr); |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
305 } pixel_cr.restore; model_cr.restore; |
11 | 306 } |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
307 } pixel_cr.restore; model_cr.restore; |
0 | 308 |
2
d6f44347373d
* Switched over to geometry done with structs instead of classes.
David Bryant <daveb@acres.com.au>
parents:
0
diff
changeset
|
309 return true; |
0 | 310 } |
311 | |
27 | 312 bool on_button_press(GdkEventButton * event, Widget widget) { |
0 | 313 assert(widget is mDrawingArea); |
314 //writefln("Got button event\n"); | |
315 | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
316 Point pixel_point = Point(event.x + 0.5, mViewSize.y - (event.y + 0.5)); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
317 Point model_point = pixel_to_model(pixel_point); |
0 | 318 |
7 | 319 auto button_event = new ButtonEvent(gtk2tk_button_action(event.type), |
320 gtk2tk_button_name(event.button), | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
321 pixel_point, |
0 | 322 model_point, |
323 gtk2tk_mask(event.state)); | |
324 | |
5 | 325 mEventHandler.handle_button_press(this, button_event); |
326 | |
41 | 327 fix_damage; |
17 | 328 |
5 | 329 return true; |
330 } | |
331 | |
27 | 332 bool on_button_release(GdkEventButton * event, Widget widget) { |
5 | 333 assert(widget is mDrawingArea); |
334 //writefln("Got button event\n"); | |
335 | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
336 Point pixel_point = Point(event.x + 0.5, mViewSize.y - (event.y + 0.5)); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
337 Point model_point = pixel_to_model(pixel_point); |
5 | 338 |
7 | 339 auto button_event = new ButtonEvent(gtk2tk_button_action(event.type), |
340 gtk2tk_button_name(event.button), | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
341 pixel_point, |
5 | 342 model_point, |
343 gtk2tk_mask(event.state)); | |
344 | |
345 mEventHandler.handle_button_release(this, button_event); | |
0 | 346 |
41 | 347 fix_damage; |
17 | 348 |
2
d6f44347373d
* Switched over to geometry done with structs instead of classes.
David Bryant <daveb@acres.com.au>
parents:
0
diff
changeset
|
349 return true; |
0 | 350 } |
351 | |
27 | 352 bool on_key_event(GdkEventKey * event, Widget widget) { |
0 | 353 assert(widget is mDrawingArea); |
354 //writefln("Got key event\n"); | |
355 | |
356 //auto key_event = new KeyEvent("", | |
357 // mEventHandle.handle_key(key_event); | |
358 | |
41 | 359 fix_damage; |
17 | 360 |
2
d6f44347373d
* Switched over to geometry done with structs instead of classes.
David Bryant <daveb@acres.com.au>
parents:
0
diff
changeset
|
361 return true; |
0 | 362 } |
363 | |
27 | 364 bool on_motion_notify(GdkEventMotion * event, Widget widget) { |
0 | 365 assert(widget is mDrawingArea); |
366 //writefln("Got motion notify\n"); | |
367 gtk_widget_event(mHRuler.getWidgetStruct(), cast(GdkEvent *)event); | |
368 gtk_widget_event(mVRuler.getWidgetStruct(), cast(GdkEvent *)event); | |
369 | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
370 Point pixel_point = Point(event.x + 0.5, mViewSize.y - (event.y + 0.5)); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
371 Point model_point = pixel_to_model(pixel_point); |
0 | 372 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
373 auto motion_event = new MotionEvent(pixel_point, |
0 | 374 model_point, |
375 gtk2tk_mask(event.state)); | |
376 | |
377 mEventHandler.handle_motion(this, motion_event); | |
378 | |
41 | 379 fix_damage; |
17 | 380 |
2
d6f44347373d
* Switched over to geometry done with structs instead of classes.
David Bryant <daveb@acres.com.au>
parents:
0
diff
changeset
|
381 return true; |
0 | 382 } |
383 | |
27 | 384 bool on_scroll(GdkEventScroll * event, Widget widget) { |
0 | 385 assert(widget is mDrawingArea); |
386 //writefln("Got scroll\n"); | |
387 | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
388 Point pixel_point = Point(event.x + 0.5, mViewSize.y - (event.y + 0.5)); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
389 Point model_point = pixel_to_model(pixel_point); |
0 | 390 |
391 auto scroll_event = new ScrollEvent(gtk2tk_direction(event.direction), | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
392 pixel_point, |
0 | 393 model_point, |
394 gtk2tk_mask(event.state)); | |
395 | |
396 mEventHandler.handle_scroll(this, scroll_event); | |
397 | |
41 | 398 fix_damage; |
17 | 399 |
2
d6f44347373d
* Switched over to geometry done with structs instead of classes.
David Bryant <daveb@acres.com.au>
parents:
0
diff
changeset
|
400 return true; |
0 | 401 } |
402 | |
20 | 403 /* |
404 public enum GdkCrossingMode { | |
405 NORMAL, | |
406 GRAB, | |
407 UNGRAB, | |
408 GTK_GRAB, | |
409 GTK_UNGRAB, | |
410 STATE_CHANGED | |
411 } | |
412 | |
413 public struct GdkEventCrossing { | |
414 GdkEventType type; | |
415 GdkWindow *window; | |
416 byte sendEvent; | |
417 GdkWindow *subwindow; | |
418 uint time; | |
419 double x; | |
420 double y; | |
421 double xRoot; | |
422 double yRoot; | |
423 GdkCrossingMode mode; | |
424 GdkNotifyType detail; | |
425 int focus; | |
426 uint state; | |
427 } | |
428 */ | |
429 | |
27 | 430 bool on_enter_notify(GdkEventCrossing * event, Widget widget) { |
20 | 431 assert(widget is mDrawingArea); |
27 | 432 //writefln("Enter %d %d %d", cast(int)event.mode, event.focus, event.state); |
433 // TODO | |
20 | 434 return true; |
435 } | |
436 | |
27 | 437 bool on_leave_notify(GdkEventCrossing * event, Widget widget) { |
20 | 438 assert(widget is mDrawingArea); |
27 | 439 //writefln("Leave %d %d %d", cast(int)event.mode, event.focus, event.state); |
440 // TODO | |
20 | 441 return true; |
442 } | |
443 | |
0 | 444 void onValueChanged(Adjustment adjustment) { |
13 | 445 GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct; |
446 GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct; | |
0 | 447 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
448 Point view_left_top = Point(gtk_adjustment_get_value(h_gtkAdjustment), |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
449 gtk_adjustment_get_value(v_gtkAdjustment)); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
450 |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
451 Vector model_size = pixel_to_model(mViewSize); |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
452 |
9 | 453 //writefln("%s", view_left_bottom); |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
454 mViewCentre = view_left_top + model_size / 2.0; |
19 | 455 //writefln("onValueChanged mViewCentre: %s", mViewCentre); |
0 | 456 |
13 | 457 update_rulers; |
0 | 458 |
13 | 459 queueDraw; |
0 | 460 } |
461 | |
462 void update_rulers() { | |
26 | 463 invariant Vector model_size = pixel_to_model(mViewSize); |
0 | 464 |
26 | 465 invariant Point view_left_bottom = mViewCentre - model_size / 2.0; |
466 invariant Point view_right_top = mViewCentre + model_size / 2.0; | |
0 | 467 |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
468 // Define these just to obtain the position |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
469 // below and we can preserve it |
12 | 470 double lower, upper, position, max_size; |
471 | |
472 mHRuler.getRange(lower, upper, position, max_size); | |
0 | 473 mHRuler.setRange(view_left_bottom.x, |
474 view_right_top.x, | |
12 | 475 position, |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
476 mZoom * 50.0); |
12 | 477 |
478 mVRuler.getRange(lower, upper, position, max_size); | |
0 | 479 mVRuler.setRange(view_right_top.y, |
480 view_left_bottom.y, | |
14 | 481 position, |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
482 mZoom * 50.0); |
0 | 483 } |
484 | |
485 void update_adjustments() { | |
26 | 486 invariant Vector model_size = pixel_to_model(mViewSize); |
0 | 487 |
26 | 488 invariant Point view_left_bottom = mViewCentre - model_size / 2.0; |
489 invariant Point view_right_top = mViewCentre + model_size / 2.0; | |
0 | 490 |
491 // Adjust the canvas size if necessary | |
15 | 492 mCanvasBounds = Rectangle(min_extents(mCanvasBounds.min_corner, view_left_bottom), |
493 max_extents(mCanvasBounds.max_corner, view_right_top)); | |
0 | 494 |
495 // Update the adjustments | |
496 | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
497 GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct; |
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
498 GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct; |
0 | 499 |
15 | 500 gtk_adjustment_set_lower(h_gtkAdjustment, mCanvasBounds.min_corner.x); |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
501 gtk_adjustment_set_upper(h_gtkAdjustment, mCanvasBounds.max_corner.x); |
2
d6f44347373d
* Switched over to geometry done with structs instead of classes.
David Bryant <daveb@acres.com.au>
parents:
0
diff
changeset
|
502 gtk_adjustment_set_value(h_gtkAdjustment, view_left_bottom.x); |
15 | 503 gtk_adjustment_set_step_increment(h_gtkAdjustment, mCanvasBounds.size.x / 16.0); |
504 gtk_adjustment_set_page_increment(h_gtkAdjustment, mCanvasBounds.size.x / 4.0); | |
2
d6f44347373d
* Switched over to geometry done with structs instead of classes.
David Bryant <daveb@acres.com.au>
parents:
0
diff
changeset
|
505 gtk_adjustment_set_page_size(h_gtkAdjustment, model_size.x); |
0 | 506 |
15 | 507 gtk_adjustment_set_lower(v_gtkAdjustment, mCanvasBounds.min_corner.y); |
508 gtk_adjustment_set_upper(v_gtkAdjustment, mCanvasBounds.max_corner.y); | |
2
d6f44347373d
* Switched over to geometry done with structs instead of classes.
David Bryant <daveb@acres.com.au>
parents:
0
diff
changeset
|
509 gtk_adjustment_set_value(v_gtkAdjustment, view_left_bottom.y); |
15 | 510 gtk_adjustment_set_step_increment(v_gtkAdjustment, mCanvasBounds.size.y / 16.0); |
511 gtk_adjustment_set_page_increment(v_gtkAdjustment, mCanvasBounds.size.y / 4.0); | |
2
d6f44347373d
* Switched over to geometry done with structs instead of classes.
David Bryant <daveb@acres.com.au>
parents:
0
diff
changeset
|
512 gtk_adjustment_set_page_size(v_gtkAdjustment, model_size.y); |
0 | 513 |
13 | 514 mHAdjustment.changed; |
515 mHAdjustment.valueChanged; | |
516 mVAdjustment.changed; | |
517 mVAdjustment.valueChanged; | |
0 | 518 } |
519 | |
41 | 520 void fix_damage() { |
17 | 521 if (mDamage.valid) { |
18 | 522 //writefln("Damage: %s", mDamage); |
17 | 523 int x, y, w, h; |
524 mDamage.get_quantised(x, y, w, h); | |
27 | 525 mDrawingArea.queueDrawArea(x, cast(int)mViewSize.y - (y + h), w, h); |
17 | 526 mDamage = Rectangle.DEFAULT; |
527 } | |
528 else { | |
18 | 529 //writefln("No damage"); |
17 | 530 } |
531 } | |
532 | |
26 | 533 double clamp_zoom(in double zoom) { return clamp(zoom, 0.2, 10.0); } |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
534 |
27 | 535 Point model_to_pixel(in Point model) const { |
536 return Point.DEFAULT + mViewSize / 2.0 + mZoom * (model - mViewCentre); | |
537 } | |
538 | |
539 Point pixel_to_model(in Point pixel) const { | |
540 return mViewCentre + (pixel - mViewSize / 2.0 - Point.DEFAULT) / mZoom; | |
541 } | |
542 | |
543 Vector model_to_pixel(in Vector model) const { | |
544 return mZoom * model; | |
545 } | |
546 | |
547 Vector pixel_to_model(in Vector pixel) const { | |
548 return pixel / mZoom; | |
549 } | |
550 | |
551 Rectangle model_to_pixel(in Rectangle model) const { | |
552 return Rectangle(model_to_pixel(model.position), model_to_pixel(model.size)); | |
553 } | |
554 | |
555 Rectangle pixel_to_model(in Rectangle model) const { | |
556 return Rectangle(pixel_to_model(model.position), pixel_to_model(model.size)); | |
557 } | |
558 | |
559 void on_realize(Widget widget) { | |
560 assert(widget is mDrawingArea); | |
561 //writefln("Got realize\n"); | |
562 } | |
563 | |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
564 bool mHadConfigure; |
17 | 565 Rectangle mDamage; // pixels |
0 | 566 |
567 // Model units are in millimetres | |
568 // Screen units are in pixels | |
41 | 569 double mZoom; // pixels-per-model-unit |
16
9e63308b749c
* Fix up public/private includes
David Bryant <daveb@acres.com.au>
parents:
15
diff
changeset
|
570 Vector mViewSize; // pixel: size of view window in pixels |
3
7d57cae10805
Renamed geometry2 to geometry
David Bryant <daveb@acres.com.au>
parents:
2
diff
changeset
|
571 Point mViewCentre; // model: where in the model is the centre of our view |
15 | 572 Rectangle mCanvasBounds; // model: |
0 | 573 |
10 | 574 // Child widgets: |
0 | 575 HRuler mHRuler; |
576 VRuler mVRuler; | |
577 DrawingArea mDrawingArea; | |
578 Adjustment mHAdjustment; | |
579 HScrollbar mHScrollbar; | |
580 Adjustment mVAdjustment; | |
581 VScrollbar mVScrollbar; | |
11 | 582 |
583 Layer[] mLayers; | |
13 | 584 EventHandler mEventHandler; |
35 | 585 Grid mGrid; |
13 | 586 double mPPI; |
0 | 587 } |
588 } |