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