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