@@ -29,6 +29,13 @@ use std::cmp::min;
29
29
30
30
use crate :: commands:: * ;
31
31
32
+ #[ derive( PartialEq , Clone , Copy ) ]
33
+ pub enum MouseMode {
34
+ None ,
35
+ Panning ,
36
+ RootFinding
37
+ }
38
+
32
39
pub struct FractalWidget < ' a > {
33
40
pub image_width : usize ,
34
41
pub image_height : usize ,
@@ -39,7 +46,7 @@ pub struct FractalWidget<'a> {
39
46
pub root_pos_current : ( f64 , f64 ) ,
40
47
pub cached_image : Option < <D2DRenderContext < ' a > as RenderContext >:: Image > ,
41
48
pub needs_buffer_refresh : bool ,
42
- pub show_selecting_box : bool ,
49
+ pub mouse_mode : MouseMode ,
43
50
pub renderer_zoom : FloatExtended ,
44
51
pub renderer_rotate : ( f64 , f64 )
45
52
}
@@ -128,20 +135,30 @@ impl<'a> Widget<FractalData> for FractalWidget<'a> {
128
135
129
136
data. sender . lock ( ) . send ( THREAD_RESET_RENDERER_FULL ) . unwrap ( ) ;
130
137
}
131
- // TODO this section sometimes blocks. Needs to be fixed
132
138
Event :: MouseMove ( e) => {
133
- // if data.mouse_mode != 0 {
134
- if data. mouse_mode != 0 {
135
- self . pos2 = ( e. pos . x , e. pos . y ) ;
136
-
137
- let top_left = ( self . pos1 . 0 . min ( self . pos2 . 0 ) , self . pos1 . 1 . min ( self . pos2 . 1 ) ) ;
138
- let bottom_right = ( self . pos1 . 0 . max ( self . pos2 . 0 ) , self . pos1 . 1 . max ( self . pos2 . 1 ) ) ;
139
+ // If the rendering / root finding has not completed, stop
140
+ if data. rendering_stage != 0 || data. root_stage == 1 {
141
+ return ;
142
+ }
139
143
140
- self . root_pos_current = ( 0.5 * ( top_left. 0 + bottom_right. 0 ) , 0.5 * ( top_left. 1 + bottom_right. 1 ) ) ;
144
+ match self . mouse_mode {
145
+ MouseMode :: RootFinding => {
146
+ self . pos2 = ( e. pos . x , e. pos . y ) ;
141
147
142
- ctx . request_paint ( ) ;
143
- }
148
+ let top_left = ( self . pos1 . 0 . min ( self . pos2 . 0 ) , self . pos1 . 1 . min ( self . pos2 . 1 ) ) ;
149
+ let bottom_right = ( self . pos1 . 0 . max ( self . pos2 . 0 ) , self . pos1 . 1 . max ( self . pos2 . 1 ) ) ;
144
150
151
+ self . root_pos_current = ( 0.5 * ( top_left. 0 + bottom_right. 0 ) , 0.5 * ( top_left. 1 + bottom_right. 1 ) ) ;
152
+
153
+ ctx. request_paint ( ) ;
154
+ }
155
+ MouseMode :: Panning => {
156
+ self . pos2 = ( e. pos . x , e. pos . y ) ;
157
+
158
+ ctx. request_paint ( ) ;
159
+ } ,
160
+ MouseMode :: None => { } ,
161
+ }
145
162
146
163
// if data.rendering_stage == 0 {
147
164
// let size = ctx.size().to_rect();
@@ -174,90 +191,151 @@ impl<'a> Widget<FractalData> for FractalWidget<'a> {
174
191
return ;
175
192
}
176
193
177
- // Zoom in, use the mouse position
178
194
if e. button == MouseButton :: Left {
179
195
self . pos1 = ( e. pos . x , e. pos . y ) ;
180
196
self . pos2 = ( e. pos . x , e. pos . y ) ;
181
197
182
- if data. mouse_mode == 2 {
183
- self . show_selecting_box = true ;
198
+ self . mouse_mode = if data. mouse_mode == 2 {
199
+ MouseMode :: RootFinding
184
200
} else {
185
- data . mouse_mode = 1 ;
201
+ MouseMode :: Panning
186
202
}
187
203
}
188
-
189
- if e. button == MouseButton :: Right {
190
- ctx. submit_command ( MULTIPLY_ZOOM . with ( 1.0 / data. zoom_scale_factor ) ) ;
191
- }
192
204
} ,
193
205
Event :: MouseUp ( e) => {
206
+ // If the rendering / root finding has not completed, stop
207
+ if data. rendering_stage != 0 || data. root_stage == 1 {
208
+ return ;
209
+ }
210
+
194
211
if e. button == MouseButton :: Left {
195
- if data. mouse_mode == 2 {
196
- self . pos2 = ( e. pos . x , e. pos . y ) ;
212
+ match self . mouse_mode {
213
+ MouseMode :: RootFinding => {
214
+ self . pos2 = ( e. pos . x , e. pos . y ) ;
197
215
198
- ctx. submit_command ( CALCULATE_ROOT ) ;
199
- } else {
200
- data. mouse_mode = 0 ;
216
+ ctx. submit_command ( CALCULATE_ROOT ) ;
217
+ } ,
218
+ MouseMode :: Panning => {
219
+ self . pos2 = ( e. pos . x , e. pos . y ) ;
201
220
202
- let mut settings = data. settings . lock ( ) ;
203
- let mut renderer = data. renderer . lock ( ) ;
204
-
205
- let size = ctx. size ( ) . to_rect ( ) ;
206
-
207
- let i = renderer. image_width as f64 / 2.0 - ( self . pos2 . 0 - self . pos1 . 0 ) * renderer. image_width as f64 / size. width ( ) ;
208
- let j = renderer. image_height as f64 / 2.0 - ( self . pos2 . 1 - self . pos1 . 1 ) * renderer. image_height as f64 / size. height ( ) ;
209
-
210
- let cos_rotate = renderer. rotate . cos ( ) ;
211
- let sin_rotate = renderer. rotate . sin ( ) ;
221
+ let mut settings = data. settings . lock ( ) ;
222
+ let renderer = data. renderer . lock ( ) ;
223
+
224
+ let size = ctx. size ( ) . to_rect ( ) ;
225
+
226
+ let i = renderer. image_width as f64 / 2.0 - ( self . pos2 . 0 - self . pos1 . 0 ) * renderer. image_width as f64 / size. width ( ) ;
227
+ let j = renderer. image_height as f64 / 2.0 - ( self . pos2 . 1 - self . pos1 . 1 ) * renderer. image_height as f64 / size. height ( ) ;
228
+
229
+ let cos_rotate = renderer. rotate . cos ( ) ;
230
+ let sin_rotate = renderer. rotate . sin ( ) ;
231
+
232
+ let delta_pixel = 4.0 / ( ( renderer. image_height - 1 ) as f64 * renderer. zoom . mantissa ) ;
233
+ let delta_top_left = get_delta_top_left ( delta_pixel, renderer. image_width , renderer. image_height , cos_rotate, sin_rotate) ;
234
+
235
+ let element = ComplexFixed :: new (
236
+ i * delta_pixel * cos_rotate - j * delta_pixel * sin_rotate + delta_top_left. re ,
237
+ i * delta_pixel * sin_rotate + j * delta_pixel * cos_rotate + delta_top_left. im
238
+ ) ;
239
+
240
+ let element = ComplexExtended :: new ( element, -renderer. zoom . exponent ) ;
212
241
213
- let delta_pixel = 4.0 / ( ( renderer. image_height - 1 ) as f64 * renderer. zoom . mantissa ) ;
214
- let delta_top_left = get_delta_top_left ( delta_pixel, renderer. image_width , renderer. image_height , cos_rotate, sin_rotate) ;
242
+ let mut location = renderer. center_reference . c . clone ( ) ;
215
243
216
- let element = ComplexFixed :: new (
217
- i * delta_pixel * cos_rotate - j * delta_pixel * sin_rotate + delta_top_left. re ,
218
- i * delta_pixel * sin_rotate + j * delta_pixel * cos_rotate + delta_top_left. im
219
- ) ;
244
+ let precision = location. real ( ) . prec ( ) ;
245
+
246
+ let temp = FloatArbitrary :: with_val ( precision, element. exponent ) . exp2 ( ) ;
247
+ let temp2 = FloatArbitrary :: with_val ( precision, element. mantissa . re ) ;
248
+ let temp3 = FloatArbitrary :: with_val ( precision, element. mantissa . im ) ;
249
+
250
+ * location. mut_real ( ) += & temp2 * & temp;
251
+ * location. mut_imag ( ) += & temp3 * & temp;
252
+
253
+ // Set the overrides for the current location
254
+ settings. set ( "real" , location. real ( ) . to_string ( ) ) . unwrap ( ) ;
255
+ settings. set ( "imag" , location. imag ( ) . to_string ( ) ) . unwrap ( ) ;
256
+
257
+ data. real = settings. get_str ( "real" ) . unwrap ( ) ;
258
+ data. imag = settings. get_str ( "imag" ) . unwrap ( ) ;
259
+
260
+ self . mouse_mode = MouseMode :: None ;
220
261
221
- let element = ComplexExtended :: new ( element, -renderer. zoom . exponent ) ;
222
- let mut zoom = renderer. zoom ;
262
+ ctx. submit_command ( RESET_RENDERER_FULL ) ;
263
+ } ,
264
+ MouseMode :: None => { } ,
265
+ }
266
+ }
267
+ }
268
+ Event :: Wheel ( e) => {
269
+ if e. wheel_delta . y > 0.0 {
270
+ ctx. submit_command ( MULTIPLY_ZOOM . with ( 1.0 / data. zoom_scale_factor ) ) ;
271
+ } else {
272
+ // If the rendering / root finding has not completed, stop
273
+ if data. rendering_stage != 0 || data. root_stage == 1 {
274
+ return ;
275
+ }
223
276
224
- zoom . mantissa * = data. zoom_scale_factor ;
225
- zoom . reduce ( ) ;
277
+ let mut settings = data. settings . lock ( ) ;
278
+ let mut renderer = data . renderer . lock ( ) ;
226
279
227
- let mut location = renderer . center_reference . c . clone ( ) ;
280
+ let size = ctx . size ( ) . to_rect ( ) ;
228
281
229
- let precision = location. real ( ) . prec ( ) ;
230
-
231
- let temp = FloatArbitrary :: with_val ( precision, element. exponent ) . exp2 ( ) ;
232
- let temp2 = FloatArbitrary :: with_val ( precision, element. mantissa . re ) ;
233
- let temp3 = FloatArbitrary :: with_val ( precision, element. mantissa . im ) ;
234
-
235
- * location. mut_real ( ) += & temp2 * & temp;
236
- * location. mut_imag ( ) += & temp3 * & temp;
237
-
238
- data. zoom = extended_to_string_long ( zoom) ;
239
-
240
- // Set the overrides for the current location
241
- settings. set ( "real" , location. real ( ) . to_string ( ) ) . unwrap ( ) ;
242
- settings. set ( "imag" , location. imag ( ) . to_string ( ) ) . unwrap ( ) ;
243
- settings. set ( "zoom" , data. zoom . clone ( ) ) . unwrap ( ) ;
244
-
245
- data. real = settings. get_str ( "real" ) . unwrap ( ) ;
246
- data. imag = settings. get_str ( "imag" ) . unwrap ( ) ;
247
-
248
- renderer. adjust_iterations ( ) ;
249
-
250
- settings. set ( "iterations" , renderer. maximum_iteration as i64 ) . unwrap ( ) ;
251
- data. iteration_limit = renderer. maximum_iteration as i64 ;
252
-
253
- self . pos1 = ( 0.0 , 0.0 ) ;
254
- self . pos2 = ( 0.0 , 0.0 ) ;
282
+ let i = e. pos . x * renderer. image_width as f64 / size. width ( ) ;
283
+ let j = e. pos . y * renderer. image_height as f64 / size. height ( ) ;
255
284
256
- ctx. submit_command ( RESET_RENDERER_FULL ) ;
257
- }
285
+ let cos_rotate = renderer. rotate . cos ( ) ;
286
+ let sin_rotate = renderer. rotate . sin ( ) ;
287
+
288
+ let delta_pixel = 4.0 / ( ( renderer. image_height - 1 ) as f64 * renderer. zoom . mantissa ) ;
289
+ let delta_top_left = get_delta_top_left ( delta_pixel, renderer. image_width , renderer. image_height , cos_rotate, sin_rotate) ;
290
+
291
+ let element = ComplexFixed :: new (
292
+ i * delta_pixel * cos_rotate - j * delta_pixel * sin_rotate + delta_top_left. re ,
293
+ i * delta_pixel * sin_rotate + j * delta_pixel * cos_rotate + delta_top_left. im
294
+ ) ;
295
+
296
+ let element = ComplexExtended :: new ( element, -renderer. zoom . exponent ) ;
297
+ let mut zoom = renderer. zoom ;
298
+
299
+ zoom. mantissa *= data. zoom_scale_factor ;
300
+ zoom. reduce ( ) ;
301
+
302
+ let mut location = renderer. center_reference . c . clone ( ) ;
303
+
304
+ let precision = location. real ( ) . prec ( ) ;
305
+
306
+ let temp = FloatArbitrary :: with_val ( precision, element. exponent ) . exp2 ( ) ;
307
+ let temp2 = FloatArbitrary :: with_val ( precision, element. mantissa . re ) ;
308
+ let temp3 = FloatArbitrary :: with_val ( precision, element. mantissa . im ) ;
309
+
310
+ * location. mut_real ( ) += & temp2 * & temp;
311
+ * location. mut_imag ( ) += & temp3 * & temp;
312
+
313
+ data. zoom = extended_to_string_long ( zoom) ;
314
+
315
+ // Set the overrides for the current location
316
+ settings. set ( "real" , location. real ( ) . to_string ( ) ) . unwrap ( ) ;
317
+ settings. set ( "imag" , location. imag ( ) . to_string ( ) ) . unwrap ( ) ;
318
+ settings. set ( "zoom" , data. zoom . clone ( ) ) . unwrap ( ) ;
319
+
320
+ data. real = settings. get_str ( "real" ) . unwrap ( ) ;
321
+ data. imag = settings. get_str ( "imag" ) . unwrap ( ) ;
322
+
323
+ renderer. adjust_iterations ( ) ;
324
+
325
+ settings. set ( "iterations" , renderer. maximum_iteration as i64 ) . unwrap ( ) ;
326
+ data. iteration_limit = renderer. maximum_iteration as i64 ;
327
+
328
+ self . mouse_mode = MouseMode :: None ;
329
+
330
+ ctx. submit_command ( RESET_RENDERER_FULL ) ;
258
331
}
259
332
}
260
333
Event :: KeyUp ( e) => {
334
+ // If the rendering / root finding has not completed, stop
335
+ if data. rendering_stage != 0 || data. root_stage == 1 {
336
+ return ;
337
+ }
338
+
261
339
// Shortcut keys
262
340
if e. key == KbKey :: Character ( "Z" . to_string ( ) ) || e. key == KbKey :: Character ( "z" . to_string ( ) ) {
263
341
ctx. submit_command ( MULTIPLY_ZOOM . with ( 2.0 ) ) ;
@@ -304,7 +382,7 @@ impl<'a> Widget<FractalData> for FractalWidget<'a> {
304
382
}
305
383
306
384
if let Some ( root_zoom) = command. get ( ROOT_FINDING_COMPLETE ) {
307
- self . show_selecting_box = false ;
385
+ self . mouse_mode = MouseMode :: None ;
308
386
309
387
data. root_progress = 1.0 ;
310
388
data. root_iteration = 64 ;
@@ -1310,6 +1388,8 @@ impl<'a> Widget<FractalData> for FractalWidget<'a> {
1310
1388
. make_image ( self . image_width , self . image_height , & temporary_image, ImageFormat :: Rgb )
1311
1389
. unwrap ( ) ) ;
1312
1390
1391
+ self . pos1 = self . pos2 ;
1392
+
1313
1393
self . needs_buffer_refresh = false ;
1314
1394
}
1315
1395
@@ -1323,16 +1403,16 @@ impl<'a> Widget<FractalData> for FractalWidget<'a> {
1323
1403
1324
1404
let mut image_position = Rect :: new ( 0.0 , 0.0 , self . image_width as f64 , self . image_height as f64 ) ;
1325
1405
1326
- if ! self . show_selecting_box {
1406
+ if self . mouse_mode != MouseMode :: RootFinding {
1327
1407
let x_delta = self . pos2 . 0 - self . pos1 . 0 ;
1328
1408
let y_delta = self . pos2 . 1 - self . pos1 . 1 ;
1329
-
1409
+
1330
1410
image_position. x0 -= x_delta. min ( 0.0 ) * self . image_width as f64 / size. x1 ;
1331
1411
image_position. y0 -= y_delta. min ( 0.0 ) * self . image_height as f64 / size. y1 ;
1332
1412
1333
1413
image_position. x1 -= x_delta. max ( 0.0 ) * self . image_width as f64 / size. x1 ;
1334
1414
image_position. y1 -= y_delta. max ( 0.0 ) * self . image_height as f64 / size. y1 ;
1335
-
1415
+
1336
1416
size. x0 += x_delta. max ( 0.0 ) ;
1337
1417
size. y0 += y_delta. max ( 0.0 ) ;
1338
1418
@@ -1342,7 +1422,7 @@ impl<'a> Widget<FractalData> for FractalWidget<'a> {
1342
1422
1343
1423
ctx. draw_image_area ( self . cached_image . as_ref ( ) . unwrap ( ) , image_position, size, interpolation_mode) ;
1344
1424
1345
- if self . show_selecting_box {
1425
+ if self . mouse_mode == MouseMode :: RootFinding {
1346
1426
let rect = Rect :: from_origin_size ( self . pos1 , ( self . pos2 . 0 - self . pos1 . 0 , self . pos2 . 1 - self . pos1 . 1 ) ) ;
1347
1427
let fill_color = Color :: rgba8 ( 0 , 0 , 0 , 150 ) ;
1348
1428
ctx. fill ( rect, & fill_color) ;
0 commit comments