Skip to content

Commit fa04eb5

Browse files
committed
Make View Sync as well
1 parent 000630e commit fa04eb5

File tree

8 files changed

+49
-36
lines changed

8 files changed

+49
-36
lines changed

cursive-core/src/builder.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,9 @@ pub use self::resolvable::{NoConfig, Resolvable};
7272

7373
use crate::views::BoxedView;
7474

75+
use parking_lot::Mutex;
7576
use std::collections::{HashMap, HashSet};
76-
use std::sync::{Arc, Mutex};
77+
use std::sync::Arc;
7778

7879
use std::any::Any;
7980

@@ -140,7 +141,7 @@ struct Blueprints {
140141
}
141142

142143
/// Wrapper around a value that makes it Cloneable, but can only be resolved once.
143-
pub struct ResolveOnce<T>(std::sync::Arc<std::sync::Mutex<Option<T>>>);
144+
pub struct ResolveOnce<T>(Arc<Mutex<Option<T>>>);
144145

145146
/// Return a variable-maker (for use in store_with)
146147
pub fn resolve_once<T>(value: T) -> impl Fn(&Config, &Context) -> Result<T, Error>
@@ -151,7 +152,6 @@ where
151152
move |_, _| {
152153
value
153154
.lock()
154-
.unwrap()
155155
.take()
156156
.ok_or_else(|| Error::MakerFailed("variable was already resolved".to_string()))
157157
}
@@ -160,17 +160,17 @@ where
160160
impl<T> ResolveOnce<T> {
161161
/// Create a new `ResolveOnce` which will resolve, once, to the given value.
162162
pub fn new(value: T) -> Self {
163-
Self(std::sync::Arc::new(std::sync::Mutex::new(Some(value))))
163+
Self(Arc::new(Mutex::new(Some(value))))
164164
}
165165

166166
/// Take the value from self.
167167
pub fn take(&self) -> Option<T> {
168-
self.0.lock().unwrap().take()
168+
self.0.lock().take()
169169
}
170170

171171
/// Check if there is a value still to be resolved in self.
172172
pub fn is_some(&self) -> bool {
173-
self.0.lock().unwrap().is_some()
173+
self.0.lock().is_some()
174174
}
175175
}
176176

cursive-core/src/view/view_trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ impl std::error::Error for ViewNotFound {}
3131
/// Main trait defining a view behaviour.
3232
///
3333
/// This is what you should implement to define a custom View.
34-
pub trait View: Any + AnyView + Send {
34+
pub trait View: Any + AnyView + Send + Sync {
3535
/// Draws the view with the given printer (includes bounds) and focus.
3636
///
3737
/// This is the only *required* method to implement.

cursive-core/src/view/view_wrapper.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::{
2020
/// child view).
2121
///
2222
/// [`wrap_impl!`]: crate::wrap_impl!
23-
pub trait ViewWrapper: Send + 'static {
23+
pub trait ViewWrapper: Send + Sync + 'static {
2424
/// Type that this view wraps.
2525
type V: View + ?Sized;
2626

cursive-core/src/views/canvas.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ impl<T> Canvas<T> {
276276
}
277277
}
278278

279-
impl<T: 'static + Send> View for Canvas<T> {
279+
impl<T: 'static + Send + Sync> View for Canvas<T> {
280280
fn draw(&self, printer: &Printer) {
281281
(self.draw)(&self.state, printer);
282282
}

cursive-core/src/views/dialog.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
views::{BoxedView, Button, DummyView, LastSizeView, TextView},
1010
Cursive, Printer, Vec2, With,
1111
};
12-
use std::cell::Cell;
12+
use parking_lot::Mutex;
1313
use std::cmp::{max, min};
1414

1515
/// Identifies currently focused element in [`Dialog`].
@@ -64,7 +64,7 @@ impl crate::builder::Resolvable for DialogFocus {
6464

6565
struct ChildButton {
6666
button: LastSizeView<Button>,
67-
offset: Cell<Vec2>,
67+
offset: Mutex<Vec2>,
6868
}
6969

7070
impl ChildButton {
@@ -74,7 +74,7 @@ impl ChildButton {
7474
{
7575
ChildButton {
7676
button: LastSizeView::new(Button::new(label, cb)),
77-
offset: Cell::new(Vec2::zero()),
77+
offset: Mutex::new(Vec2::zero()),
7878
}
7979
}
8080
}
@@ -550,7 +550,7 @@ impl Dialog {
550550
let button = &mut self.buttons[button_id];
551551
button
552552
.button
553-
.on_event(event.relativized(button.offset.get()))
553+
.on_event(event.relativized(*button.offset.lock()))
554554
};
555555
match result {
556556
EventResult::Ignored => {
@@ -644,7 +644,7 @@ impl Dialog {
644644
let size = button.button.size;
645645
// Add some special effect to the focused button
646646
let position = Vec2::new(offset, y);
647-
button.offset.set(position);
647+
*button.offset.lock() = position;
648648
button.button.draw(
649649
&printer
650650
.offset(position)
@@ -722,7 +722,7 @@ impl Dialog {
722722
// Now that we have a relative position, checks for buttons?
723723
if let Some(i) = self.buttons.iter().position(|btn| {
724724
// If position fits there...
725-
position.fits_in_rect(btn.offset.get(), btn.button.size)
725+
position.fits_in_rect(*btn.offset.lock(), btn.button.size)
726726
}) {
727727
return Some(self.set_focus(DialogFocus::Button(i)));
728728
} else if position

cursive-core/src/views/focus_tracker.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ use crate::{
88
/// Detects focus events for a view.
99
pub struct FocusTracker<T> {
1010
view: T,
11-
on_focus_lost: Box<dyn FnMut(&mut T) -> EventResult + Send>,
12-
on_focus: Box<dyn FnMut(&mut T) -> EventResult + Send>,
11+
on_focus_lost: Box<dyn FnMut(&mut T) -> EventResult + Send + Sync>,
12+
on_focus: Box<dyn FnMut(&mut T) -> EventResult + Send + Sync>,
1313
}
1414

15-
impl<T: 'static> FocusTracker<T> {
15+
impl<T: Send + Sync + 'static> FocusTracker<T> {
1616
/// Wraps a view in a new `FocusTracker`.
1717
pub fn new(view: T) -> Self {
1818
FocusTracker {
@@ -26,7 +26,7 @@ impl<T: 'static> FocusTracker<T> {
2626
#[must_use]
2727
pub fn on_focus<F>(self, f: F) -> Self
2828
where
29-
F: 'static + FnMut(&mut T) -> EventResult + Send,
29+
F: 'static + FnMut(&mut T) -> EventResult + Send + Sync,
3030
{
3131
self.with(|s| s.set_on_focus(f))
3232
}
@@ -35,7 +35,7 @@ impl<T: 'static> FocusTracker<T> {
3535
#[crate::callback_helpers]
3636
pub fn set_on_focus<F>(&mut self, f: F)
3737
where
38-
F: 'static + FnMut(&mut T) -> EventResult + Send,
38+
F: 'static + FnMut(&mut T) -> EventResult + Send + Sync,
3939
{
4040
self.on_focus = Box::new(f);
4141
}
@@ -44,7 +44,7 @@ impl<T: 'static> FocusTracker<T> {
4444
#[must_use]
4545
pub fn on_focus_lost<F>(self, f: F) -> Self
4646
where
47-
F: 'static + FnMut(&mut T) -> EventResult + Send,
47+
F: 'static + FnMut(&mut T) -> EventResult + Send + Sync,
4848
{
4949
self.with(|s| s.set_on_focus_lost(f))
5050
}
@@ -53,7 +53,7 @@ impl<T: 'static> FocusTracker<T> {
5353
#[crate::callback_helpers]
5454
pub fn set_on_focus_lost<F>(&mut self, f: F)
5555
where
56-
F: 'static + FnMut(&mut T) -> EventResult + Send,
56+
F: 'static + FnMut(&mut T) -> EventResult + Send + Sync,
5757
{
5858
self.on_focus_lost = Box::new(f);
5959
}

cursive-core/src/views/stack_view.rs

+22-9
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use crate::{
1313
views::{BoxedView, CircularFocus, Layer, ShadowView},
1414
Printer, Vec2, With,
1515
};
16-
use std::cell;
1716
use std::ops::Deref;
1817

1918
/// Simple stack of views.
@@ -26,7 +25,7 @@ pub struct StackView {
2625
// and therefore need redrawing.
2726
// TODO: this is broken! Transparent views could change their content and lead to weirdness.
2827
// Instead, just rely on buffered backend.
29-
bg_dirty: cell::Cell<bool>,
28+
bg_dirty: std::sync::atomic::AtomicBool,
3029
}
3130

3231
// This is a poor man's optional parameter, or kinda builder pattern.
@@ -310,7 +309,7 @@ impl StackView {
310309
StackView {
311310
layers: Vec::new(),
312311
last_size: Vec2::zero(),
313-
bg_dirty: cell::Cell::new(true),
312+
bg_dirty: std::sync::atomic::AtomicBool::new(true),
314313
}
315314
}
316315

@@ -514,7 +513,7 @@ impl StackView {
514513
///
515514
/// If the given position is out of bounds.
516515
pub fn remove_layer(&mut self, position: LayerPosition) -> Box<dyn View> {
517-
self.bg_dirty.set(true);
516+
self.set_dirty();
518517
let i = self.get_index(position).unwrap();
519518
self.layers
520519
.remove(i)
@@ -526,9 +525,23 @@ impl StackView {
526525
.unwrap()
527526
}
528527

528+
fn set_dirty(&self) {
529+
self.bg_dirty
530+
.store(true, std::sync::atomic::Ordering::Relaxed);
531+
}
532+
533+
fn undirty(&self) {
534+
self.bg_dirty
535+
.store(false, std::sync::atomic::Ordering::Relaxed);
536+
}
537+
538+
fn is_dirty(&self) -> bool {
539+
self.bg_dirty.load(std::sync::atomic::Ordering::Relaxed)
540+
}
541+
529542
/// Remove the top-most layer.
530543
pub fn pop_layer(&mut self) -> Option<Box<dyn View>> {
531-
self.bg_dirty.set(true);
544+
self.set_dirty();
532545
self.layers
533546
.pop()
534547
.map(|child| child.view)
@@ -621,7 +634,7 @@ impl StackView {
621634
match child.placement {
622635
Placement::Floating(_) => {
623636
child.placement = Placement::Floating(position);
624-
self.bg_dirty.set(true);
637+
self.set_dirty();
625638
}
626639
Placement::Fullscreen => (),
627640
}
@@ -642,15 +655,15 @@ impl StackView {
642655
/// You probably just want to call draw()
643656
pub fn draw_bg(&self, printer: &Printer) {
644657
// If the background is dirty draw a new background
645-
if self.bg_dirty.get() {
658+
if self.is_dirty() {
646659
for y in 0..printer.size.y {
647660
printer.with_style(PaletteStyle::Background, |printer| {
648661
printer.print_hline((0, y), printer.size.x, " ");
649662
});
650663
}
651664

652665
// set background as clean, so we don't need to do this every frame
653-
self.bg_dirty.set(false);
666+
self.undirty();
654667
}
655668
}
656669

@@ -732,7 +745,7 @@ impl View for StackView {
732745

733746
fn on_event(&mut self, event: Event) -> EventResult {
734747
if event == Event::WindowResize {
735-
self.bg_dirty.set(true);
748+
self.set_dirty();
736749
}
737750

738751
// Use the stack position iterator to get the offset of the top layer.

cursive-core/src/views/tracked_view.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
use crate::view::{View, ViewWrapper};
22
use crate::Printer;
33
use crate::Vec2;
4-
use std::cell::Cell;
4+
use parking_lot::Mutex;
55

66
/// Wrapper around a view that remembers its position.
77
pub struct TrackedView<T> {
88
/// Wrapped view.
99
pub view: T,
1010
/// Last position the view was located.
11-
offset: Cell<Vec2>,
11+
offset: Mutex<Vec2>,
1212
}
1313

1414
new_default!(TrackedView<T: Default>);
1515

1616
impl<T> TrackedView<T> {
1717
/// Return the last offset at which the view was drawn.
1818
pub fn offset(&self) -> Vec2 {
19-
self.offset.get()
19+
*self.offset.lock()
2020
}
2121

2222
/// Creates a new `TrackedView` around `view`.
2323
pub fn new(view: T) -> Self {
2424
TrackedView {
2525
view,
26-
offset: Cell::new(Vec2::zero()),
26+
offset: Mutex::new(Vec2::zero()),
2727
}
2828
}
2929

@@ -34,7 +34,7 @@ impl<T: View> ViewWrapper for TrackedView<T> {
3434
wrap_impl!(self.view: T);
3535

3636
fn wrap_draw(&self, printer: &Printer) {
37-
self.offset.set(printer.offset);
37+
*self.offset.lock() = printer.offset;
3838
self.view.draw(printer);
3939
}
4040
}

0 commit comments

Comments
 (0)