aboutsummaryrefslogtreecommitdiff
path: root/src/app.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/app.rs')
-rw-r--r--src/app.rs147
1 files changed, 69 insertions, 78 deletions
diff --git a/src/app.rs b/src/app.rs
index 3c57f27..bcc9c3a 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -1,9 +1,9 @@
1use crate::{ 1use crate::{
2 bitmap::{MapPoint, Pixmap}, 2 bitmap::{Axis, MapPoint, Pixmap},
3 undo::{ModifyRecord, OpKind, Operation, UndoStack}, 3 undo::{ModifyRecord, OpKind, Operation, UndoStack},
4}; 4};
5 5
6use std::convert::{From, TryFrom}; 6use std::convert::From;
7 7
8use sdl2::{ 8use sdl2::{
9 event::Event, 9 event::Event,
@@ -19,17 +19,18 @@ use sdl2::{
19use crate::consts::{BLACK, GRID_COLOR, WHITE}; 19use crate::consts::{BLACK, GRID_COLOR, WHITE};
20 20
21pub struct AppState<'ctx> { 21pub struct AppState<'ctx> {
22 start: Point, 22 active_color: bool,
23 pixmap: Pixmap<bool>,
24 zoom: u8,
25 brush_size: u8, 23 brush_size: u8,
26 grid: Grid,
27 context: &'ctx Sdl,
28 canvas: Canvas<Window>, 24 canvas: Canvas<Window>,
25 context: &'ctx Sdl,
26 current_operation: Operation,
27 grid: Grid,
29 last_point: Option<Point>, 28 last_point: Option<Point>,
30 active_color: bool, 29 pixmap: Pixmap<bool>,
30 start: Point,
31 symmetry: Symmetry,
31 undo_stack: UndoStack<Operation>, 32 undo_stack: UndoStack<Operation>,
32 current_operation: Operation, 33 zoom: u8,
33} 34}
34 35
35struct Grid { 36struct Grid {
@@ -240,14 +241,9 @@ impl<'ctx> AppState<'ctx> {
240 } 241 }
241 } 242 }
242 243
243 fn modify<F>(&mut self, func: F) 244 fn redraw(&mut self) {
244 where 245 self.canvas.set_draw_color(BLACK);
245 F: FnOnce(&mut Self),
246 {
247 func(self);
248 self.canvas.set_draw_color(Color::RGB(0, 0, 0));
249 self.canvas.clear(); 246 self.canvas.clear();
250 self.canvas.set_draw_color(Color::RGB(64, 64, 64));
251 self.draw(); 247 self.draw();
252 self.canvas.present(); 248 self.canvas.present();
253 } 249 }
@@ -274,17 +270,18 @@ impl<'ctx> AppState<'ctx> {
274 270
275 let pixmap = Pixmap::new_with(width, height, false); 271 let pixmap = Pixmap::new_with(width, height, false);
276 Self { 272 Self {
277 start: Point::new(60, 60), 273 active_color: true,
278 zoom: 5,
279 brush_size: 0, 274 brush_size: 0,
280 pixmap,
281 grid: Grid::new(),
282 canvas, 275 canvas,
283 context, 276 context,
277 current_operation: Vec::new(),
278 grid: Grid::new(),
284 last_point: None, 279 last_point: None,
285 active_color: true, 280 pixmap,
281 start: Point::new(60, 60),
282 symmetry: Default::default(),
286 undo_stack: UndoStack::new(), 283 undo_stack: UndoStack::new(),
287 current_operation: Vec::new(), 284 zoom: 5,
288 } 285 }
289 } 286 }
290 287
@@ -305,52 +302,53 @@ impl<'ctx> AppState<'ctx> {
305 } => { 302 } => {
306 match k { 303 match k {
307 // pan 304 // pan
308 Keycode::W => self.modify(|e| e.pan((0, 10))), 305 Keycode::W => self.pan((0, 10)),
309 Keycode::A => self.modify(|e| e.pan((10, 0))), 306 Keycode::A => self.pan((10, 0)),
310 Keycode::S => self.modify(|e| e.pan((0, -10))), 307 Keycode::S => self.pan((0, -10)),
311 Keycode::D => self.modify(|e| e.pan((-10, 0))), 308 Keycode::D => self.pan((-10, 0)),
312 // zoom 309 // zoom
313 Keycode::C => { 310 Keycode::C => {
314 let cursor = (mouse.x(), mouse.y()); 311 let cursor = (mouse.x(), mouse.y());
315 self.modify(|e| e.zoom_in(cursor)); 312 self.zoom_in(cursor);
316 } 313 }
317 Keycode::Z => { 314 Keycode::Z => {
318 let cursor = (mouse.x(), mouse.y()); 315 let cursor = (mouse.x(), mouse.y());
319 self.modify(|e| e.zoom_out(cursor)); 316 self.zoom_out(cursor);
320 } 317 }
321 // brush ops 318 // brush ops
322 Keycode::Q => self.decrease_brush_size(), 319 Keycode::Q => self.decrease_brush_size(),
323 Keycode::E => self.increase_brush_size(), 320 Keycode::E => self.increase_brush_size(),
324 // flip color 321 // flip color
325 Keycode::X => self.modify(|e| e.change_active_color()), 322 Keycode::X => self.change_active_color(),
326 // toggle grid 323 // toggle grid
327 Keycode::Tab => self.modify(|e| e.toggle_grid()), 324 Keycode::Tab => self.toggle_grid(),
328 // line drawing 325 // line drawing
329 Keycode::F => self.modify(|e| { 326 Keycode::F => {
330 let end = (mouse.x(), mouse.y()).into(); 327 let end = (mouse.x(), mouse.y()).into();
331 if let Some(start) = e.last_point { 328 if let Some(start) = self.last_point {
332 if let Ok(o) = e.paint_line(start, end) { 329 if let Ok(o) = self.paint_line(start, end) {
333 e.commit_operation(); 330 self.commit_operation();
334 e.current_operation = 331 self.current_operation =
335 o.into_iter().filter(|v| !v.old_val == v.val).collect(); 332 o.into_iter().filter(|v| !v.old_val == v.val).collect();
336 e.commit_operation(); 333 self.commit_operation();
337 e.last_point = Some(end); 334 self.last_point = Some(end);
338 } 335 }
339 } 336 }
340 }), 337 }
338 Keycode::V => self.cycle_symmetry(),
341 // exit 339 // exit
342 Keycode::Escape => break 'running, 340 Keycode::Escape => break 'running,
343 // undo & redo 341 // undo & redo
344 Keycode::U => self.modify(|e| { 342 Keycode::U => {
345 if let Some(op) = e.undo_stack.undo() { 343 if let Some(op) = self.undo_stack.undo() {
346 e.apply_operation(op, OpKind::Undo); 344 self.apply_operation(op, OpKind::Undo);
347 } 345 }
348 }), 346 }
349 Keycode::R => self.modify(|e| { 347 Keycode::R => {
350 if let Some(op) = e.undo_stack.redo() { 348 if let Some(op) = self.undo_stack.redo() {
351 e.apply_operation(op, OpKind::Redo); 349 self.apply_operation(op, OpKind::Redo);
352 } 350 }
353 }), 351 }
354 _ => (), 352 _ => (),
355 } 353 }
356 } 354 }
@@ -358,57 +356,50 @@ impl<'ctx> AppState<'ctx> {
358 Event::MouseButtonDown { 356 Event::MouseButtonDown {
359 x, y, mouse_btn, .. 357 x, y, mouse_btn, ..
360 } => { 358 } => {
361 self.modify(|e| { 359 let pt = (x, y);
362 let pt = (x, y); 360 self.last_point = Some(pt.into());
363 e.last_point = Some(pt.into()); 361 let val = match mouse_btn {
364 let val = match mouse_btn { 362 MouseButton::Right => !self.active_color,
365 MouseButton::Right => !e.active_color, 363 _ => self.active_color,
366 _ => e.active_color, 364 };
367 }; 365 if let Ok(o) = self.paint_point(pt, val) {
368 if let Ok(o) = e.paint_point(pt, val) { 366 self.current_operation.extend(o);
369 e.current_operation.extend(o); 367 }
370 }
371 });
372 } 368 }
373 // click and drag 369 // click and drag
374 Event::MouseMotion { 370 Event::MouseMotion {
375 x, y, mousestate, .. 371 x, y, mousestate, ..
376 } => { 372 } => {
377 if mousestate.is_mouse_button_pressed(MouseButton::Left) { 373 if mousestate.is_mouse_button_pressed(MouseButton::Left) {
378 self.modify(|e| { 374 let pt = (x, y);
379 let pt = (x, y); 375 let val = self.active_color;
380 let val = e.active_color; 376 if let Ok(o) = self.paint_point(pt, val) {
381 if let Ok(o) = e.paint_point(pt, val) { 377 self.current_operation.extend(o);
382 e.current_operation.extend(o); 378 }
383 }
384 });
385 } else if mousestate.is_mouse_button_pressed(MouseButton::Right) { 379 } else if mousestate.is_mouse_button_pressed(MouseButton::Right) {
386 self.modify(|e| { 380 let pt = (x, y);
387 let pt = (x, y); 381 let val = !self.active_color;
388 let val = !e.active_color; 382 if let Ok(o) = self.paint_point(pt, val) {
389 if let Ok(o) = e.paint_point(pt, val) { 383 self.current_operation.extend(o);
390 e.current_operation.extend(o); 384 }
391 }
392 });
393 } 385 }
394 } 386 }
395 // end of operation 387 // end of operation
396 Event::MouseButtonUp { .. } => self.modify(|e| { 388 Event::MouseButtonUp { .. } => {
397 let op = e 389 let op = self
398 .current_operation 390 .current_operation
399 .drain(..) 391 .drain(..)
400 .filter(|v| !v.old_val == v.val) 392 .filter(|v| !v.old_val == v.val)
401 .collect::<Vec<_>>(); 393 .collect::<Vec<_>>();
402 e.undo_stack.push(op); 394 self.undo_stack.push(op);
403 }), 395 }
404 Event::Quit { .. } => { 396 Event::Quit { .. } => {
405 break 'running; 397 break 'running;
406 } 398 }
407 _ => { 399 _ => {}
408 self.modify(|_| ());
409 }
410 } 400 }
411 } 401 }
402 self.redraw();
412 } 403 }
413 } 404 }
414} 405}