Restore hotkeys in `pane_grid` example
- Implement `subscription::events_with` - Remove `pane_grid::KeyPressEvent` - Return closest sibling in `pane_grid::State::close`
This commit is contained in:
parent
c53022e8df
commit
d6d5cf0294
|
@ -7,3 +7,4 @@ publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
iced = { path = "../..", features = ["debug"] }
|
iced = { path = "../..", features = ["debug"] }
|
||||||
|
iced_native = { path = "../../native" }
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use iced::{
|
use iced::{
|
||||||
button, keyboard, pane_grid, scrollable, Align, Button, Column, Container,
|
button, executor, keyboard, pane_grid, scrollable, Align, Application,
|
||||||
Element, HorizontalAlignment, Length, PaneGrid, Sandbox, Scrollable,
|
Button, Column, Command, Container, Element, HorizontalAlignment, Length,
|
||||||
Settings, Text,
|
PaneGrid, Scrollable, Settings, Subscription, Text,
|
||||||
};
|
};
|
||||||
|
use iced_native::{subscription, Event};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Example::run(Settings::default())
|
Example::run(Settings::default())
|
||||||
|
@ -26,24 +27,29 @@ enum Message {
|
||||||
CloseFocused,
|
CloseFocused,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sandbox for Example {
|
impl Application for Example {
|
||||||
type Message = Message;
|
type Message = Message;
|
||||||
|
type Executor = executor::Default;
|
||||||
|
type Flags = ();
|
||||||
|
|
||||||
fn new() -> Self {
|
fn new(_flags: ()) -> (Self, Command<Message>) {
|
||||||
let (panes, _) = pane_grid::State::new(Content::new(0));
|
let (panes, _) = pane_grid::State::new(Content::new(0));
|
||||||
|
|
||||||
Example {
|
(
|
||||||
panes,
|
Example {
|
||||||
panes_created: 1,
|
panes,
|
||||||
focus: None,
|
panes_created: 1,
|
||||||
}
|
focus: None,
|
||||||
|
},
|
||||||
|
Command::none(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self) -> String {
|
fn title(&self) -> String {
|
||||||
String::from("Pane grid - Iced")
|
String::from("Pane grid - Iced")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
match message {
|
match message {
|
||||||
Message::Split(axis, pane) => {
|
Message::Split(axis, pane) => {
|
||||||
let result = self.panes.split(
|
let result = self.panes.split(
|
||||||
|
@ -96,14 +102,30 @@ impl Sandbox for Example {
|
||||||
}
|
}
|
||||||
Message::Dragged(_) => {}
|
Message::Dragged(_) => {}
|
||||||
Message::Close(pane) => {
|
Message::Close(pane) => {
|
||||||
let _ = self.panes.close(&pane);
|
if let Some((_, sibling)) = self.panes.close(&pane) {
|
||||||
|
self.focus = Some(sibling);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Message::CloseFocused => {
|
Message::CloseFocused => {
|
||||||
if let Some(pane) = self.focus {
|
if let Some(pane) = self.focus {
|
||||||
let _ = self.panes.close(&pane);
|
if let Some((_, sibling)) = self.panes.close(&pane) {
|
||||||
|
self.focus = Some(sibling);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Command::none()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
|
subscription::events_with(|event| match event {
|
||||||
|
Event::Keyboard(keyboard::Event::KeyPressed {
|
||||||
|
modifiers,
|
||||||
|
key_code,
|
||||||
|
}) if modifiers.control => handle_hotkey(key_code),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&mut self) -> Element<Message> {
|
fn view(&mut self) -> Element<Message> {
|
||||||
|
@ -137,11 +159,11 @@ impl Sandbox for Example {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_hotkey(event: pane_grid::KeyPressEvent) -> Option<Message> {
|
fn handle_hotkey(key_code: keyboard::KeyCode) -> Option<Message> {
|
||||||
use keyboard::KeyCode;
|
use keyboard::KeyCode;
|
||||||
use pane_grid::{Axis, Direction};
|
use pane_grid::{Axis, Direction};
|
||||||
|
|
||||||
let direction = match event.key_code {
|
let direction = match key_code {
|
||||||
KeyCode::Up => Some(Direction::Up),
|
KeyCode::Up => Some(Direction::Up),
|
||||||
KeyCode::Down => Some(Direction::Down),
|
KeyCode::Down => Some(Direction::Down),
|
||||||
KeyCode::Left => Some(Direction::Left),
|
KeyCode::Left => Some(Direction::Left),
|
||||||
|
@ -149,7 +171,7 @@ fn handle_hotkey(event: pane_grid::KeyPressEvent) -> Option<Message> {
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
match event.key_code {
|
match key_code {
|
||||||
KeyCode::V => Some(Message::SplitFocused(Axis::Vertical)),
|
KeyCode::V => Some(Message::SplitFocused(Axis::Vertical)),
|
||||||
KeyCode::H => Some(Message::SplitFocused(Axis::Horizontal)),
|
KeyCode::H => Some(Message::SplitFocused(Axis::Horizontal)),
|
||||||
KeyCode::W => Some(Message::CloseFocused),
|
KeyCode::W => Some(Message::CloseFocused),
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
use crate::Renderer;
|
use crate::Renderer;
|
||||||
|
|
||||||
pub use iced_native::pane_grid::{
|
pub use iced_native::pane_grid::{
|
||||||
Axis, Configuration, Direction, DragEvent, Focus, KeyPressEvent, Node,
|
Axis, Configuration, Direction, DragEvent, Focus, Node, Pane, ResizeEvent,
|
||||||
Pane, ResizeEvent, Split, State,
|
Split, State,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A collection of panes distributed using either vertical or horizontal splits
|
/// A collection of panes distributed using either vertical or horizontal splits
|
||||||
|
|
|
@ -20,8 +20,8 @@ use iced_native::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use iced_native::pane_grid::{
|
pub use iced_native::pane_grid::{
|
||||||
Axis, Configuration, Content, Direction, DragEvent, Focus, KeyPressEvent,
|
Axis, Configuration, Content, Direction, DragEvent, Focus, Pane,
|
||||||
Pane, ResizeEvent, Split, State, TitleBar,
|
ResizeEvent, Split, State, TitleBar,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A collection of panes distributed using either vertical or horizontal splits
|
/// A collection of panes distributed using either vertical or horizontal splits
|
||||||
|
|
|
@ -43,5 +43,25 @@ use events::Events;
|
||||||
/// [`Subscription`]: type.Subscription.html
|
/// [`Subscription`]: type.Subscription.html
|
||||||
/// [`Event`]: ../enum.Event.html
|
/// [`Event`]: ../enum.Event.html
|
||||||
pub fn events() -> Subscription<Event> {
|
pub fn events() -> Subscription<Event> {
|
||||||
Subscription::from_recipe(Events)
|
Subscription::from_recipe(Events { f: Some })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a [`Subscription`] that filters all the runtime events with the
|
||||||
|
/// provided function, producing messages accordingly.
|
||||||
|
///
|
||||||
|
/// This subscription will call the provided function for every [`Event`]
|
||||||
|
/// handled by the runtime. If the function:
|
||||||
|
///
|
||||||
|
/// - Returns `None`, the [`Event`] will be discarded.
|
||||||
|
/// - Returns `Some` message, the `Message` will be produced.
|
||||||
|
///
|
||||||
|
/// [`Subscription`]: type.Subscription.html
|
||||||
|
/// [`Event`]: ../enum.Event.html
|
||||||
|
pub fn events_with<Message>(
|
||||||
|
f: fn(Event) -> Option<Message>,
|
||||||
|
) -> Subscription<Message>
|
||||||
|
where
|
||||||
|
Message: 'static + Send,
|
||||||
|
{
|
||||||
|
Subscription::from_recipe(Events { f })
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,26 @@ use crate::{
|
||||||
subscription::{EventStream, Recipe},
|
subscription::{EventStream, Recipe},
|
||||||
Event, Hasher,
|
Event, Hasher,
|
||||||
};
|
};
|
||||||
|
use iced_futures::futures::future;
|
||||||
|
use iced_futures::futures::StreamExt;
|
||||||
use iced_futures::BoxStream;
|
use iced_futures::BoxStream;
|
||||||
|
|
||||||
pub struct Events;
|
pub struct Events<Message> {
|
||||||
|
pub(super) f: fn(Event) -> Option<Message>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Recipe<Hasher, Event> for Events {
|
impl<Message> Recipe<Hasher, Event> for Events<Message>
|
||||||
type Output = Event;
|
where
|
||||||
|
Message: 'static + Send,
|
||||||
|
{
|
||||||
|
type Output = Message;
|
||||||
|
|
||||||
fn hash(&self, state: &mut Hasher) {
|
fn hash(&self, state: &mut Hasher) {
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
std::any::TypeId::of::<Self>().hash(state);
|
struct Marker;
|
||||||
|
std::any::TypeId::of::<Marker>().hash(state);
|
||||||
|
self.f.hash(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream(
|
fn stream(
|
||||||
|
@ -20,5 +29,7 @@ impl Recipe<Hasher, Event> for Events {
|
||||||
event_stream: EventStream,
|
event_stream: EventStream,
|
||||||
) -> BoxStream<Self::Output> {
|
) -> BoxStream<Self::Output> {
|
||||||
event_stream
|
event_stream
|
||||||
|
.filter_map(move |event| future::ready((self.f)(event)))
|
||||||
|
.boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,8 @@ pub use state::{Focus, State};
|
||||||
pub use title_bar::TitleBar;
|
pub use title_bar::TitleBar;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
container, keyboard, layout, mouse, overlay, row, text, Clipboard, Element,
|
container, layout, mouse, overlay, row, text, Clipboard, Element, Event,
|
||||||
Event, Hasher, Layout, Length, Point, Rectangle, Size, Vector, Widget,
|
Hasher, Layout, Length, Point, Rectangle, Size, Vector, Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A collection of panes distributed using either vertical or horizontal splits
|
/// A collection of panes distributed using either vertical or horizontal splits
|
||||||
|
@ -336,18 +336,6 @@ pub struct ResizeEvent {
|
||||||
pub ratio: f32,
|
pub ratio: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An event produced during a key press interaction of a [`PaneGrid`].
|
|
||||||
///
|
|
||||||
/// [`PaneGrid`]: struct.PaneGrid.html
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct KeyPressEvent {
|
|
||||||
/// The key that was pressed.
|
|
||||||
pub key_code: keyboard::KeyCode,
|
|
||||||
|
|
||||||
/// The state of the modifier keys when the key was pressed.
|
|
||||||
pub modifiers: keyboard::ModifiersState,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, Message, Renderer> Widget<Message, Renderer>
|
impl<'a, Message, Renderer> Widget<Message, Renderer>
|
||||||
for PaneGrid<'a, Message, Renderer>
|
for PaneGrid<'a, Message, Renderer>
|
||||||
where
|
where
|
||||||
|
|
|
@ -227,12 +227,13 @@ impl<T> State<T> {
|
||||||
let _ = self.internal.layout.resize(split, ratio);
|
let _ = self.internal.layout.resize(split, ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Closes the given [`Pane`] and returns its internal state, if it exists.
|
/// Closes the given [`Pane`] and returns its internal state and its closest
|
||||||
|
/// sibling, if it exists.
|
||||||
///
|
///
|
||||||
/// [`Pane`]: struct.Pane.html
|
/// [`Pane`]: struct.Pane.html
|
||||||
pub fn close(&mut self, pane: &Pane) -> Option<T> {
|
pub fn close(&mut self, pane: &Pane) -> Option<(T, Pane)> {
|
||||||
if let Some(_) = self.internal.layout.remove(pane) {
|
if let Some(sibling) = self.internal.layout.remove(pane) {
|
||||||
self.panes.remove(pane)
|
self.panes.remove(pane).map(|state| (state, sibling))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
use crate::Renderer;
|
use crate::Renderer;
|
||||||
|
|
||||||
pub use iced_native::pane_grid::{
|
pub use iced_native::pane_grid::{
|
||||||
Axis, Configuration, Direction, DragEvent, Focus, KeyPressEvent, Node,
|
Axis, Configuration, Direction, DragEvent, Focus, Node, Pane, ResizeEvent,
|
||||||
Pane, ResizeEvent, Split, State,
|
Split, State,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A collection of panes distributed using either vertical or horizontal splits
|
/// A collection of panes distributed using either vertical or horizontal splits
|
||||||
|
|
Loading…
Reference in New Issue