Add StackView::remove_layer

This commit is contained in:
Alexandre Bury 2019-02-12 17:24:34 -08:00
parent 6171930649
commit 027038db6f

View File

@ -20,8 +20,12 @@ pub struct StackView {
bg_dirty: cell::Cell<bool>, bg_dirty: cell::Cell<bool>,
} }
/// Where should the view be on the screen (per dimension).
enum Placement { enum Placement {
/// View is floating at a specific position.
Floating(Position), Floating(Position),
/// View is full-screen; it should not have a 1-cell border.
Fullscreen, Fullscreen,
} }
@ -52,7 +56,7 @@ impl Placement {
} }
} }
// A child view can be wrapped in multiple ways. /// A child view can be wrapped in multiple ways.
enum ChildWrapper<T: View> { enum ChildWrapper<T: View> {
// Some views include a shadow around. // Some views include a shadow around.
Shadow(ShadowView<Layer<CircularFocus<T>>>), Shadow(ShadowView<Layer<CircularFocus<T>>>),
@ -209,6 +213,22 @@ impl StackView {
} }
} }
/// Returns the number of layers in this `StackView`.
pub fn len(&self) -> usize {
self.layers.len()
}
/// Returns `true` if `position` points to a valid layer.
///
/// Returns `false` if it exceeds the bounds.
pub fn fits(&self, position: LayerPosition) -> bool {
let i = match position {
LayerPosition::FromBack(i) | LayerPosition::FromFront(i) => i,
};
i < self.len()
}
/// Adds a new full-screen layer on top of the stack. /// Adds a new full-screen layer on top of the stack.
/// ///
/// Fullscreen layers have no shadow. /// Fullscreen layers have no shadow.
@ -247,16 +267,18 @@ impl StackView {
/// Returns a reference to the layer at the given position. /// Returns a reference to the layer at the given position.
pub fn get(&self, pos: LayerPosition) -> Option<&View> { pub fn get(&self, pos: LayerPosition) -> Option<&View> {
let i = self.get_index(pos); self.get_index(pos).and_then(|i| {
self.layers.get(i).map(|child| &**child.view.get_inner()) self.layers.get(i).map(|child| &**child.view.get_inner())
})
} }
/// Returns a mutable reference to the layer at the given position. /// Returns a mutable reference to the layer at the given position.
pub fn get_mut(&mut self, pos: LayerPosition) -> Option<&mut View> { pub fn get_mut(&mut self, pos: LayerPosition) -> Option<&mut View> {
let i = self.get_index(pos); self.get_index(pos).and_then(move |i| {
self.layers self.layers
.get_mut(i) .get_mut(i)
.map(|child| &mut **child.view.get_inner_mut()) .map(|child| &mut **child.view.get_inner_mut())
})
} }
/// Looks for the layer containing a view with the given ID. /// Looks for the layer containing a view with the given ID.
@ -266,6 +288,9 @@ impl StackView {
/// ///
/// Returns `None` if the given ID is not found. /// Returns `None` if the given ID is not found.
/// ///
/// Note that the returned position may be invalidated if some layers are
/// removed from the view.
///
/// # Examples /// # Examples
/// ///
/// ```rust /// ```rust
@ -357,7 +382,7 @@ impl StackView {
}); });
} }
/// Adds a view on top of the stack. /// Adds a view on top of the stack at the given position.
/// ///
/// Chainable variant. /// Chainable variant.
pub fn layer_at<T>(self, position: Position, view: T) -> Self pub fn layer_at<T>(self, position: Position, view: T) -> Self
@ -367,6 +392,16 @@ impl StackView {
self.with(|s| s.add_layer_at(position, view)) self.with(|s| s.add_layer_at(position, view))
} }
/// Remove a layer from this `StackView`.
///
/// # Panics
///
/// If the given position is out of bounds.
pub fn remove_layer(&mut self, position: LayerPosition) -> Box<View> {
let i = self.get_index(position).unwrap();
self.layers.remove(i).view.unwrap().unwrap()
}
/// Remove the top-most layer. /// Remove the top-most layer.
pub fn pop_layer(&mut self) -> Option<Box<View>> { pub fn pop_layer(&mut self) -> Option<Box<View>> {
self.bg_dirty.set(true); self.bg_dirty.set(true);
@ -396,10 +431,12 @@ impl StackView {
self.layers.iter().map(|layer| layer.size).collect() self.layers.iter().map(|layer| layer.size).collect()
} }
fn get_index(&self, pos: LayerPosition) -> usize { fn get_index(&self, pos: LayerPosition) -> Option<usize> {
match pos { match pos {
LayerPosition::FromBack(i) => i, LayerPosition::FromBack(i) => Some(i),
LayerPosition::FromFront(i) => self.layers.len() - i - 1, LayerPosition::FromFront(i) => {
self.layers.len().checked_sub(i + 1)
}
} }
} }
@ -407,38 +444,47 @@ impl StackView {
/// ///
/// This only affects the elevation of a layer (whether it is drawn over /// This only affects the elevation of a layer (whether it is drawn over
/// or under other views). /// or under other views).
///
/// # Panics
///
/// If either `from` or `to` is out of bounds.
pub fn move_layer(&mut self, from: LayerPosition, to: LayerPosition) { pub fn move_layer(&mut self, from: LayerPosition, to: LayerPosition) {
// Convert relative positions to indices in the array // Convert relative positions to indices in the array
let from_i = self.get_index(from); let from = self.get_index(from).unwrap();
let to_i = self.get_index(to); let to = self.get_index(to).unwrap();
let removed = self.layers.remove(from_i); let removed = self.layers.remove(from);
self.layers.insert(to, removed);
self.layers.insert(to_i, removed);
} }
/// Brings the given view to the front of the stack. /// Brings the given view to the front of the stack.
///
/// # Panics
///
/// If `layer` is out of bounds.
pub fn move_to_front(&mut self, layer: LayerPosition) { pub fn move_to_front(&mut self, layer: LayerPosition) {
self.move_layer(layer, LayerPosition::FromFront(0)); self.move_layer(layer, LayerPosition::FromFront(0));
} }
/// Pushes the given view to the back of the stack. /// Pushes the given view to the back of the stack.
///
/// # Panics
///
/// If `layer` is out of bounds.
pub fn move_to_back(&mut self, layer: LayerPosition) { pub fn move_to_back(&mut self, layer: LayerPosition) {
self.move_layer(layer, LayerPosition::FromBack(0)); self.move_layer(layer, LayerPosition::FromBack(0));
} }
/// Moves a layer to a new position on the screen. /// Moves a layer to a new position on the screen.
/// ///
/// Has no effect on fullscreen layers /// # Panics
/// Has no effect if layer is not found ///
/// If `layer` is out of bounds.
pub fn reposition_layer( pub fn reposition_layer(
&mut self, layer: LayerPosition, position: Position, &mut self, layer: LayerPosition, position: Position,
) { ) {
let i = self.get_index(layer); let i = self.get_index(layer).unwrap();
let child = match self.layers.get_mut(i) { let child = &mut self.layers[i];
Some(i) => i,
None => return,
};
match child.placement { match child.placement {
Placement::Floating(_) => { Placement::Floating(_) => {
child.placement = Placement::Floating(position); child.placement = Placement::Floating(position);
@ -451,7 +497,8 @@ impl StackView {
/// Background drawing /// Background drawing
/// ///
/// Drawing functions are split into forground and background to /// Drawing functions are split into forground and background to
/// ease inserting layers under the stackview but above it's background /// ease inserting layers under the stackview but above its background.
///
/// you probably just want to call draw() /// you probably just want to call draw()
pub fn draw_bg(&self, printer: &Printer) { pub fn draw_bg(&self, printer: &Printer) {
// If the background is dirty draw a new background // If the background is dirty draw a new background
@ -470,8 +517,9 @@ impl StackView {
/// Forground drawing /// Forground drawing
/// ///
/// Drawing functions are split into forground and background to /// Drawing functions are split into forground and background to
/// ease inserting layers under the stackview but above it's background /// ease inserting layers under the stackview but above its background.
/// you probably just want to call draw() ///
/// You probably just want to call draw()
pub fn draw_fg(&self, printer: &Printer) { pub fn draw_fg(&self, printer: &Printer) {
let last = self.layers.len(); let last = self.layers.len();
printer.with_color(ColorStyle::primary(), |printer| { printer.with_color(ColorStyle::primary(), |printer| {
@ -490,14 +538,17 @@ impl StackView {
} }
} }
struct StackPositionIterator<R: Deref<Target = Child>, I: Iterator<Item = R>> { /// Iterates on the layers and compute the position of each.
struct StackPositionIterator<I> {
inner: I, inner: I,
previous: Vec2, previous: Vec2,
total_size: Vec2, total_size: Vec2,
} }
impl<R: Deref<Target = Child>, I: Iterator<Item = R>> impl<I> StackPositionIterator<I>
StackPositionIterator<R, I> where
I: Iterator,
I::Item: Deref<Target = Child>,
{ {
/// Returns a new StackPositionIterator /// Returns a new StackPositionIterator
pub fn new(inner: I, total_size: Vec2) -> Self { pub fn new(inner: I, total_size: Vec2) -> Self {
@ -510,12 +561,14 @@ impl<R: Deref<Target = Child>, I: Iterator<Item = R>>
} }
} }
impl<R: Deref<Target = Child>, I: Iterator<Item = R>> Iterator impl<I> Iterator for StackPositionIterator<I>
for StackPositionIterator<R, I> where
I: Iterator,
I::Item: Deref<Target = Child>,
{ {
type Item = (R, Vec2); type Item = (I::Item, Vec2);
fn next(&mut self) -> Option<(R, Vec2)> { fn next(&mut self) -> Option<(I::Item, Vec2)> {
self.inner.next().map(|v| { self.inner.next().map(|v| {
let offset = v.placement.compute_offset( let offset = v.placement.compute_offset(
v.size, v.size,