true final version
[lp74.git] / src / data.rs
blob34353e06463e96c8971098d08898d37000cdff20
1 use std::usize;
3 use std::sync::mpsc::{Sender, Receiver};
4 use std::sync::mpsc;
5 use std::thread;
7 const SPACE_SIZE: usize = 21;
8 const NOF_DIM: usize = 3;
9 const DEFAULT_FACE_SIZE: usize = 64;
10 const NOF_THREADS: usize = 4;
12 #[derive(Clone, Copy, PartialEq, Debug)]
13 pub enum Axis {
14     X,
15     Y,
16     Z,
19 #[derive(Clone, Copy, PartialEq, Debug)]
20 pub enum Ori {
21     Top,
22     Back,
23     Side,
26 #[derive(Clone, Copy, PartialEq, Debug)]
27 pub enum Pos {
28     E(Edge),
29     F(Face),
32 #[derive(Clone, Copy, PartialEq, Debug)]
33 pub enum Change {
34     None,
35     Current,
36     Size(Edge, usize),
37     Space,
40 #[derive(Clone, Copy, PartialEq, Debug)]
41 pub enum PosKind {
42     Edge,
43     Face,
46 pub type Coord = (usize, usize, usize);
47 pub type Edge = (Coord, Axis);
48 pub type Face = (Coord, Ori);
49 pub type FaceColor = (f32, f32, f32);
50 pub type Surface = [Option<FaceColor>; NOF_DIM];
52 pub struct Space {
53     pub size: [[usize; SPACE_SIZE]; NOF_DIM],
54     pub faces: [[[Option<Surface>; SPACE_SIZE]; SPACE_SIZE]; SPACE_SIZE],
55     pub current: Pos,
56     pub change: Change,
59 impl Space {
60     fn new() -> Space {
61         let mid = SPACE_SIZE / 2;
62         let current_node = (mid, mid, mid);
63         let mut tmp = Space {
64             size: [[DEFAULT_FACE_SIZE; SPACE_SIZE]; NOF_DIM],
65             faces: [[[None; SPACE_SIZE]; SPACE_SIZE]; SPACE_SIZE],
66             current: Pos::E((current_node, Axis::X)),
67             change: Change::None,
68         };
69         tmp.add_empty_node(current_node);
70         tmp.add_face((current_node, Ori::Top));
71         tmp
72     }
74     #[inline]
75     pub fn axis_idx(a: Axis) -> usize {
76         match a {
77             Axis::X => 0,
78             Axis::Y => 1,
79             Axis::Z => 2,
80         }
81     }
83     #[inline]
84     pub fn ori_idx(o: Ori) -> usize {
85         match o {
86             Ori::Top => 0,
87             Ori::Side => 1,
88             Ori::Back => 2,
89         }
90     }
92     fn adj_faces(((x, y, z), a): Edge) -> Vec<Face> {
93         let mut faces = Vec::new();
94         match a {
95             Axis::X => {
96                 faces.push(((x, y, z), Ori::Top));
97                 faces.push(((x, y, z), Ori::Back));
98                 if y < (SPACE_SIZE - 1) {
99                     faces.push(((x, y+1, z), Ori::Top));
100                 }
101                 if z > 0 {
102                    faces.push(((x, y, z-1), Ori::Back));
103                 }
104             },
105             Axis::Y => {
106                 faces.push(((x, y, z), Ori::Top));
107                 faces.push(((x, y, z), Ori::Side));
108                 if x > 0 {
109                     faces.push(((x-1, y, z), Ori::Top));
110                 }
111                 if z > 0 {
112                     faces.push(((x, y, z-1), Ori::Side));
113                 }
114             },
115             Axis::Z => {
116                 faces.push(((x, y, z), Ori::Back));
117                 faces.push(((x, y, z), Ori::Side));
118                 if x > 0 {
119                     faces.push(((x-1, y, z), Ori::Back));
120                 }
121                 if y < (SPACE_SIZE - 1) {
122                     faces.push(((x, y+1, z), Ori::Side));
123                 }
124             },
125         }
126         faces
127     }
129     #[inline]
130     fn is_node(&self, (x, y, z): Coord) -> bool {
131         if x < SPACE_SIZE
132             && y < SPACE_SIZE
133             && z < SPACE_SIZE {
134             if let Some(_) = self.faces[x][y][z] {
135                 true
136             } else {
137                 false
138             }
139         } else {
140             false
141         }
142     }
144     #[inline]
145     fn is_face(&self, ((x, y, z), o): Face) -> bool {
146         self.is_node((x, y, z))
147             && match self.faces[x][y][z] {
148             Some(faces) => faces[Space::ori_idx(o)] != None,
149             None => false,
150         }
151     }
153     #[inline]
154     pub fn current_node_coord(&self) -> Coord {
155         match self.current {
156             Pos::E((n, _)) => n,
157             Pos::F((n, _)) => n,
158         }
159     }
161     pub fn row_size_before_current(&self, a: Axis) -> usize {
162         let (xcur, ycur, zcur) = self.current_node_coord();
163         let mut res = 0;
164         match a {
165             Axis::X => {
166                 for x in 0..xcur {
167                     res += self.size[Space::axis_idx(Axis::X)][x];
168                 }
169                 res += self.size[Space::axis_idx(Axis::X)][xcur] / 2;
170             },
171             Axis::Y => {
172                 for y in 0..ycur {
173                     res += self.size[Space::axis_idx(Axis::Y)][y];
174                 }
175                 res += self.size[Space::axis_idx(Axis::Y)][ycur] / 2;
176             },
177             Axis::Z => {
178                 for z in 0..zcur {
179                     res += self.size[Space::axis_idx(Axis::Z)][z];
180                 }
181                 res += self.size[Space::axis_idx(Axis::Z)][zcur] / 2;
182             },
183         }
184         res
185     }
187     #[inline]
188     pub fn row_size(&self, a: Axis) -> usize {
189         self.size[Space::axis_idx(a)].iter()
190             .fold(0, |row, &s| row + s)
191     }
193     #[inline]
194     pub fn get_edge_size(&self, ((x, y, z), a): Edge) -> usize {
195         self.size[Space::axis_idx(a)][match a {
196             Axis::X => x,
197             Axis::Y => y,
198             Axis::Z => z,
199         }]
200     }
202     pub fn set_current_face_color_if_any(&mut self, c: FaceColor) {
203         match self.current {
204             Pos::E(_) => panic!("current is not a face"),
205             Pos::F(((x, y, z), o)) => match self.faces[x][y][z] {
206                 Some(ref mut f) => f[Space::ori_idx(o)] = Some(c),
207                 None => panic!("no face here"),
208             },
209         }
210     }
212     fn edge_size_no_change(&mut self, ((x, y, z), a): Edge, new_size: usize) {
213         let size = &mut self.size[Space::axis_idx(a)][match a {
214             Axis::X => x,
215             Axis::Y => y,
216             Axis::Z => z,
217         }];
218         if *size != new_size {
219             *size = new_size;
220         }
221     }
223     #[inline]
224     pub fn edge_size(&mut self, e: Edge, new_size: usize) {
225         self.edge_size_no_change(e, new_size);
226         self.change = Change::Size(e, new_size);
227     }
229     pub fn inc_size(&mut self) {
230         match self.current {
231             Pos::E(e) => {
232                 let size = self.get_edge_size(e);
233                 if size < usize::MAX {
234                     self.edge_size(e, size + 1);
235                 }
236             },
237             Pos::F(_) => panic!("resize on a face"),
238         }
239     }
241     pub fn dec_size(&mut self) {
242         match self.current {
243             Pos::E(e) => {
244                 let size = self.get_edge_size(e);
245                 if size > 0 {
246                     self.edge_size(e, size - 1);
247                 }
248             },
249             Pos::F(_) => panic!("resize on a face"),
250         }
251     }
253     fn face_edges(&self, ((x, y, z), o): Face) -> Vec<Edge> {
254         let mut edges = Vec::new();
255         match o {
256             Ori::Top => {
257                 edges.push(((x, y, z), Axis::X));
258                 edges.push(((x, y, z), Axis::Y));
259                 if x < SPACE_SIZE-1 {
260                     edges.push(((x+1, y, z), Axis::Y));
261                 }
262                 if y > 0 {
263                     edges.push(((x, y-1, z), Axis::X));
264                 }
265             },
266             Ori::Back => {
267                 edges.push(((x, y, z), Axis::X));
268                 edges.push(((x, y, z), Axis::Z));
269                 if x < SPACE_SIZE-1 {
270                     edges.push(((x+1, y, z), Axis::Z));
271                 }
272                 if z < SPACE_SIZE-1 {
273                     edges.push(((x, y, z+1), Axis::X));
274                 }
275             },
276             Ori::Side => {
277                 edges.push(((x, y, z), Axis::Y));
278                 edges.push(((x, y, z), Axis::Z));
279                 if y > 0 {
280                     edges.push(((x, y-1, z), Axis::Z));
281                 }
282                 if z < SPACE_SIZE-1 {
283                     edges.push(((x, y, z+1), Axis::Y));
284                 }
285             },
286         }
287         edges
288     }
290     #[inline]
291     fn add_empty_node(&mut self, (x, y, z): Coord) {
292         assert!(!self.is_node((x, y, z)));
293         self.faces[x][y][z] = Some([None; NOF_DIM]);
294         self.change = Change::Space;
295     }
297     fn adj_available_faces(&self, e: Edge) -> Vec<Face> {
298         Space::adj_faces(e).iter()
299             .filter_map(|&adj_f| if self.is_face(adj_f) {
300                 None
301             } else {
302                 Some(adj_f)
303             }).collect::<Vec<_>>()
304     }
306     fn adj_existing_faces(&self, e: Edge) -> Vec<Face> {
307         Space::adj_faces(e).iter()
308             .filter_map(|&adj_f| if self.is_face(adj_f) {
309                 Some(adj_f)
310             } else {
311                 None
312             }).collect::<Vec<_>>()
313     }
315     pub fn dec_pos(&mut self) {
316         let tmp = match self.current {
317             Pos::E(((mut x, mut y, mut z), a)) => {
318                 match a {
319                     Axis::X => x -= 1,
320                     Axis::Y => y -= 1,
321                     Axis::Z => z -= 1,
322                 };
323                 (x, y, z)
324             },
325             Pos::F(((mut x, mut y, mut z), o)) => {
326                 match o {
327                     Ori::Top => z -= 1,
328                     Ori::Back => y -= 1,
329                     Ori::Side => x -= 1,
330                 };
331                 (x, y, z)
332             },
333         };
334         if self.is_node(tmp) {
335             self.change = Change::Current;
336             match self.current {
337                 Pos::E((ref mut n, _)) => *n = tmp,
338                 Pos::F((ref mut n, _)) => *n = tmp,
339             }
340         };
341     }
343     pub fn inc_pos(&mut self) {
344         let tmp = match self.current {
345             Pos::E(((mut x, mut y, mut z), a)) => {
346                 match a {
347                     Axis::X => x += 1,
348                     Axis::Y => y += 1,
349                     Axis::Z => z += 1,
350                 };
351                 (x, y, z)
352             },
353             Pos::F(((mut x, mut y, mut z), o)) => {
354                 match o {
355                     Ori::Top => z += 1,
356                     Ori::Back => y += 1,
357                     Ori::Side => x += 1,
358                 };
359                 (x, y, z)
360             },
361         };
362         if self.is_node(tmp) {
363             self.change = Change::Current;
364             match self.current {
365                 Pos::E((ref mut n, _)) => *n = tmp,
366                 Pos::F((ref mut n, _)) => *n = tmp,
367             }
368         };
369     }
371     pub fn inc_pos2(&mut self) {
372         let tmp = match self.current {
373             Pos::E(_) => panic!(),
374             Pos::F(((mut x, mut y, mut z), o)) => {
375                 match o {
376                     Ori::Top => y += 1,
377                     Ori::Back => x += 1,
378                     Ori::Side => z += 1,
379                 };
380                 (x, y, z)
381             },
382         };
383         if self.is_node(tmp) {
384             self.change = Change::Current;
385             match self.current {
386                 Pos::E(_) => {},
387                 Pos::F((ref mut n, _)) => *n = tmp,
388             }
389         };
390     }
392     pub fn dec_pos2(&mut self) {
393         let tmp = match self.current {
394             Pos::E(_) => panic!(),
395             Pos::F(((mut x, mut y, mut z), o)) => {
396                 match o {
397                     Ori::Top => y -= 1,
398                     Ori::Back => x -= 1,
399                     Ori::Side => z -= 1,
400                 };
401                 (x, y, z)
402             },
403         };
404         if self.is_node(tmp) {
405             self.change = Change::Current;
406             match self.current {
407                 Pos::E(_) => {},
408                 Pos::F((ref mut n, _)) => *n = tmp,
409             }
410         };
411     }
413     pub fn inc_pos3(&mut self) {
414         let tmp = match self.current {
415             Pos::E(_) => panic!(),
416             Pos::F(((mut x, mut y, mut z), o)) => {
417                 match o {
418                     Ori::Top => x += 1,
419                     Ori::Back => z += 1,
420                     Ori::Side => y += 1,
421                 };
422                 (x, y, z)
423             },
424         };
425         if self.is_node(tmp) {
426             self.change = Change::Current;
427             match self.current {
428                 Pos::E(_) => {},
429                 Pos::F((ref mut n, _)) => *n = tmp,
430             }
431         };
432     }
434     pub fn dec_pos3(&mut self) {
435         let tmp = match self.current {
436             Pos::E(_) => panic!(),
437             Pos::F(((mut x, mut y, mut z), o)) => {
438                 match o {
439                     Ori::Top => x -= 1,
440                     Ori::Back => z -= 1,
441                     Ori::Side => y -= 1,
442                 };
443                 (x, y, z)
444             },
445         };
446         if self.is_node(tmp) {
447             self.change = Change::Current;
448             match self.current {
449                 Pos::E(_) => {},
450                 Pos::F((ref mut n, _)) => *n = tmp,
451             }
452         };
453     }
455     pub fn rotate(&mut self) {
456         self.change = Change::Current;
457         match self.current {
458             Pos::E((_, ref mut a)) => match *a {
459                 Axis::X => *a = Axis::Y,
460                 Axis::Y => *a = Axis::Z,
461                 Axis::Z => *a = Axis::X,
462             },
463             Pos::F((_, ref mut o)) => match *o {
464                 Ori::Top => *o = Ori::Back,
465                 Ori::Back => *o = Ori::Side,
466                 Ori::Side => *o = Ori::Top,
467             },
468         }
469     }
471     pub fn set_pos_kind(&mut self, pk: PosKind) {
472         match pk {
473             PosKind::Face => if let Pos::E((c, a)) = self.current {
474                 self.change = Change::Current;
475                 self.current = Pos::F((c, match a {
476                     Axis::X => Ori::Side,
477                     Axis::Y => Ori::Back,
478                     Axis::Z => Ori::Top,
479                 }));
480             },
481             PosKind::Edge => if let Pos::F((c, o)) = self.current {
482                 self.change = Change::Current;
483                 self.current = Pos::E((c, match o {
484                     Ori::Side => Axis::X,
485                     Ori::Back => Axis::Y,
486                     Ori::Top => Axis::Z,
487                 }));
488             },
489         };
490     }
492     fn all_nodes_coord(&self) -> Vec<Coord> {
493         let mut nodes = Vec::new();
494         for x in 0..self.faces.len() {
495             for y in 0..self.faces[x].len() {
496                 for z in 0..self.faces[x][y].len() {
497                     if self.is_node((x, y, z)) {
498                         nodes.push((x, y, z));
499                     }
500                 }
501             }
502         }
503         nodes
504     }
506     fn connecting_edge(&self, f1: Face, f2: Face) -> Option<Edge> {
507         for e1 in self.face_edges(f1) {
508             for e2 in self.face_edges(f2) {
509                 if e1 == e2 {
510                     return Some(e1);
511                 }
512             }
513         }
514         None
515     }
517     fn all_faces(&self) -> Vec<Face> {
518         let mut faces = Vec::new();
519         for n in self.all_nodes_coord() {
520             for &o in [Ori::Top, Ori::Side, Ori::Back].iter() {
521                 if self.is_face((n, o)) {
522                     faces.push((n, o));
523                 }
524             }
525         }
526         faces
527     }
529     fn faces_map(&self) -> Vec<(Face, Vec<Face>)> {
530         let mut map = Vec::new();
531         for f in self.all_faces() {
532             let mut adj_faces = Vec::new();
533             for &e in self.face_edges(f).iter() {
534                 for &adj_f in self.adj_existing_faces(e).iter() {
535                     if f != adj_f {
536                         adj_faces.push(adj_f);
537                     }
538                 }
539             }
540             map.push((f, adj_faces));
541         }
542         map
543     }
545     #[inline]
546     fn face_dot_label_fmt(((x, y, z), o): Face, s: &str) -> String {
547         format!("f{0}_{1}_{2}_{3} [label=\"{0} {1} {2} {3}\" {4}]",
548                 x, y, z, Space::ori_idx(o), s)
549     }
551     #[inline]
552     fn face_dot_fmt(((x, y, z), o): Face) -> String {
553         format!("f{}_{}_{}_{}", x, y, z, Space::ori_idx(o))
554     }
556     fn dot_face_pairs(&self) -> Vec<(Face, Face)> {
557         let mut pairs = Vec::new();
558         {
559             let fmap = self.faces_map();
560             let (f_tx, f_rx): (Sender<(Face, Face)>, Receiver<(Face, Face)>) = mpsc::channel();
561             let mut nof_pairs = 0;
562             for map_chunk in fmap.chunks((fmap.len() / NOF_THREADS) + 1) {
563                 let thread_f_tx = f_tx.clone();
564                 let thread_mc = map_chunk.iter().map(|x| {
565                     nof_pairs += x.1.len();
566                     x.clone()
567                 }).collect::<Vec<(Face, Vec<Face>)>>();
568                 thread::spawn(move || {
569                     for (f, adj_fs) in thread_mc {
570                         for adj_f in adj_fs {
571                             thread_f_tx.send((f, adj_f)).unwrap();
572                         }
573                     }
574                 });
575             }
576             for _ in 0..nof_pairs {
577                 pairs.push(f_rx.recv().unwrap());
578             }
579         }
580         let mut i = 0;
581         pairs.iter().filter_map(|&(a1, b1)| {
582             i += 1;
583             if !pairs.iter().take(i-1)
584                   .any(|&(b2, a2)| a1 == a2 && b1 == b2) {
585                 Some((a1, b1))
586             } else {
587                 None
588             }
589         }).collect::<Vec<(Face, Face)>>()
590     }
592     fn dot_face_decls(&self) -> String {
593         let mut decls = String::new();
594         {
595             let faces = self.all_faces();
596             let (s_tx, s_rx): (Sender<String>, Receiver<String>) = mpsc::channel();
597             for faces_chunk in faces.chunks((faces.len() / NOF_THREADS) + 1) {
598                 let thread_s_tx = s_tx.clone();
599                 let thread_fs = faces_chunk.iter().map(|x| x.clone()).collect::<Vec<Face>>();
600                 let current = self.current;
601                 thread::spawn(move || {
602                     for f in thread_fs {
603                         thread_s_tx.send(format!("    {};\n", Space::face_dot_label_fmt(f,
604                             if Pos::F(f) == current { "color=red" } else { "" })))
605                             .unwrap();
606                     }
607                 });
608             }
609             for _ in 0..faces.len() {
610                 decls.push_str(&s_rx.recv().unwrap());
611             }
612         }
613         decls
614     }
616     pub fn dot_graph_code(&self) -> String {
617         let mut code = String::from("graph {\n");
618         code.push_str(&self.dot_face_decls());
619         for (a, b) in self.dot_face_pairs() {
620             code.push_str(&format!("    {} -- {}{};\n",
621                                    Space::face_dot_fmt(a),
622                                    Space::face_dot_fmt(b),
623                                    if let Some(e) = self.connecting_edge(a, b) {
624                                        if Pos::E(e) == self.current {
625                                            " [color=red]"
626                                        } else { "" }
627                                    } else { "" }));
628         }
629         code.push_str("}");
630         code
631     }
633     #[inline]
634     fn add_empty_node_if_none(&mut self, n: Coord) {
635         if !self.is_node(n) {
636             self.add_empty_node(n);
637         }
638     }
640     fn set_face(&mut self, ((x, y, z), o): Face, v: Option<FaceColor>) {
641         match self.faces[x][y][z] {
642             Some(ref mut f) => {
643                 if f[Space::ori_idx(o)] != v {
644                     self.change = Change::Space;
645                 }
646                 f[Space::ori_idx(o)] = v;
647             },
648             None => panic!("there is no node here"),
649         }
650     }
652     fn face_adj_available_faces(&self, f: Face) -> Vec<Face> {
653         let mut faces = Vec::new();
654         for e in self.face_edges(f) {
655             for adj_f in self.adj_available_faces(e) {
656                 if f != adj_f {
657                     faces.push(adj_f);
658                 }
659             }
660         }
661         faces
662     }
664     fn suround_with_nodes(&mut self, (n, o): Face) {
665         assert!(self.is_node(n));
666         for (nf, _) in self.face_adj_available_faces((n, o)) {
667             self.add_empty_node_if_none(nf);
668         }
669     }
671     #[inline]
672     pub fn add_face(&mut self, f: Face) {
673         self.suround_with_nodes(f);
674         self.set_face(f, Some((1.0, 1.0, 1.0)));
675     }
677     #[inline]
678     pub fn remove_face(&mut self, f: Face) {
679         assert!(self.is_face(f));
680         self.set_face(f, None);
681     }
683     pub fn set_current_face_if_none(&mut self) {
684         match self.current {
685             Pos::F(f) => if !self.is_face(f) { self.add_face(f) },
686             Pos::E(_) => {},
687         }
688     }
691 impl Clone for Space {
692     fn clone(&self) -> Space {
693         Space {
694             size: self.size,
695             faces: self.faces,
696             current: self.current,
697             change: self.change,
698         }
699     }
702 #[derive(Clone)]
703 enum Save {
704     Space(Space),
705     Current(Pos),
706     Size(Edge, usize),
709 pub struct History {
710     saves: Vec<Save>,
711     id: usize,
712     pub change: bool,
715 impl History {
716     fn new() -> History {
717         History {
718             saves: Vec::new(),
719             id: 0,
720             change: false,
721         }
722     }
724     fn add(&mut self, s: Save) {
725         if self.saves.len() > self.id {
726             while self.saves.len() > self.id {
727                 self.saves.pop();
728             }
729         }
730         self.saves.push(s);
731         self.id += 1;
732     }
734     pub fn has_prev(&self) -> bool {
735         self.id > 1
736     }
738     pub fn has_next(&self) -> bool {
739         self.saves.len() > self.id
740     }
742     fn prev(&mut self) -> Save {
743         assert!(self.has_prev());
744         self.id -= 1;
745         self.change = true;
746         self.saves[self.id-1].clone()
747     }
749     fn next(&mut self) -> Save {
750         assert!(self.has_next());
751         self.id += 1;
752         self.change = true;
753         self.saves[self.id-1].clone()
754     }
756     fn current(&self) -> Option<&Save> {
757         if self.id == 0 {
758             None
759         } else {
760             Some(&self.saves[self.id-1])
761         }
762     }
764     fn replace_current(&mut self, s: Save) {
765         assert!(self.id != 0);
766         self.saves[self.id-1] = s;
767     }
770 pub struct Data {
771     pub space: Space,
772     pub history: History,
775 impl Data {
776     pub fn new() -> Data {
777         Data { space: Space::new(), history: History::new() }
778     }
780     fn save_to_add(&self) -> Option<Save> {
781         match self.space.change {
782             Change::Space => {
783                 let mut space = self.space.clone();
784                 space.change = Change::None;
785                 Some(Save::Space(space))
786             }
787             Change::Current => Some(Save::Current(self.space.current)),
788             Change::Size(e, s) => Some(Save::Size(e, s)),
789             Change::None => None,
790         }
791     }
793     pub fn save_if_changed(&mut self) {
794         match self.save_to_add() {
795             Some(Save::Size(e, s)) =>
796                 match self.history.current() {
797                     Some(&Save::Size(e, _)) =>
798                         self.history.replace_current(Save::Size(e, s)),
799                     _ => self.history.add(Save::Size(e, s)),
800                 },
801             Some(s) => self.history.add(s),
802             None => {},
803         }
804         self.space.change = Change::None;
805     }
807     pub fn load_prev(&mut self) {
808         match self.history.prev() {
809             Save::Current(c) => self.space.current = c,
810             Save::Space(s) => self.space = s,
811             Save::Size(e, s) => self.space.edge_size_no_change(e, s),
812         }
813     }
815     pub fn load_next(&mut self) {
816         match self.history.next() {
817             Save::Current(c) => self.space.current = c,
818             Save::Space(s) => self.space = s,
819             Save::Size(e, s) => self.space.edge_size_no_change(e, s),
820         }
821     }
823     pub fn load_prev_if_any(&mut self) {
824         if self.history.has_prev() {
825             self.load_prev();
826         }
827     }
829     pub fn load_next_if_any(&mut self) {
830         if self.history.has_next() {
831             self.load_next();
832         }
833     }