summaryrefslogtreecommitdiffstats
path: root/examples/multi_window
diff options
context:
space:
mode:
authorLibravatar Richard <richardsoncusto@gmail.com>2022-07-14 10:37:33 -0300
committerLibravatar bungoboingo <shankern@protonmail.com>2023-01-09 11:27:04 -0800
commit01bad4f89654d65b0d6a65a8df99c387cbadf7fe (patch)
tree95b5b4ac4f2a828179b2faec580d54120430e856 /examples/multi_window
parent8f53df560e1bde33e874977e5115cd0f9301640d (diff)
downloadiced-01bad4f89654d65b0d6a65a8df99c387cbadf7fe.tar.gz
iced-01bad4f89654d65b0d6a65a8df99c387cbadf7fe.tar.bz2
iced-01bad4f89654d65b0d6a65a8df99c387cbadf7fe.zip
duplicate `pane_grid` example to `multi_window`
Diffstat (limited to 'examples/multi_window')
-rw-r--r--examples/multi_window/Cargo.toml12
-rw-r--r--examples/multi_window/src/main.rs370
2 files changed, 355 insertions, 27 deletions
diff --git a/examples/multi_window/Cargo.toml b/examples/multi_window/Cargo.toml
new file mode 100644
index 00000000..9c3d0f21
--- /dev/null
+++ b/examples/multi_window/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "multi_window"
+version = "0.1.0"
+authors = ["Richard Custodio <richardsoncusto@gmail.com>"]
+edition = "2021"
+publish = false
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+iced = { path = "../..", features = ["debug", "multi_window"] }
+iced_native = { path = "../../native" }
+iced_lazy = { path = "../../lazy" } \ No newline at end of file
diff --git a/examples/multi_window/src/main.rs b/examples/multi_window/src/main.rs
index 0ba6a591..ae8fa22b 100644
--- a/examples/multi_window/src/main.rs
+++ b/examples/multi_window/src/main.rs
@@ -1,58 +1,374 @@
-use iced::multi_window::Application;
-use iced::pure::{button, column, text, Element};
-use iced::{window, Alignment, Command, Settings};
+use iced::alignment::{self, Alignment};
+use iced::executor;
+use iced::keyboard;
+use iced::theme::{self, Theme};
+use iced::widget::pane_grid::{self, PaneGrid};
+use iced::widget::{button, column, container, row, scrollable, text};
+use iced::{
+ Application, Color, Command, Element, Length, Settings, Size, Subscription,
+};
+use iced_lazy::responsive;
+use iced_native::{event, subscription, Event};
pub fn main() -> iced::Result {
- Counter::run(Settings::default())
+ Example::run(Settings::default())
}
-struct Counter {
- value: i32,
+struct Example {
+ panes: pane_grid::State<Pane>,
+ panes_created: usize,
+ focus: Option<pane_grid::Pane>,
}
#[derive(Debug, Clone, Copy)]
enum Message {
- IncrementPressed,
- DecrementPressed,
+ Split(pane_grid::Axis, pane_grid::Pane),
+ SplitFocused(pane_grid::Axis),
+ FocusAdjacent(pane_grid::Direction),
+ Clicked(pane_grid::Pane),
+ Dragged(pane_grid::DragEvent),
+ Resized(pane_grid::ResizeEvent),
+ TogglePin(pane_grid::Pane),
+ Close(pane_grid::Pane),
+ CloseFocused,
}
-impl Application for Counter {
- type Flags = ();
- type Executor = iced::executor::Default;
+impl Application for Example {
type Message = Message;
+ type Theme = Theme;
+ type Executor = executor::Default;
+ type Flags = ();
fn new(_flags: ()) -> (Self, Command<Message>) {
- (Self { value: 0 }, Command::none())
- }
+ let (panes, _) = pane_grid::State::new(Pane::new(0));
- fn title(&self) -> String {
- String::from("MultiWindow - Iced")
+ (
+ Example {
+ panes,
+ panes_created: 1,
+ focus: None,
+ },
+ Command::none(),
+ )
}
- fn windows(&self) -> Vec<(window::Id, iced::window::Settings)> {
- todo!()
+ fn title(&self) -> String {
+ String::from("Pane grid - Iced")
}
fn update(&mut self, message: Message) -> Command<Message> {
match message {
- Message::IncrementPressed => {
- self.value += 1;
+ Message::Split(axis, pane) => {
+ let result = self.panes.split(
+ axis,
+ &pane,
+ Pane::new(self.panes_created),
+ );
+
+ if let Some((pane, _)) = result {
+ self.focus = Some(pane);
+ }
+
+ self.panes_created += 1;
+ }
+ Message::SplitFocused(axis) => {
+ if let Some(pane) = self.focus {
+ let result = self.panes.split(
+ axis,
+ &pane,
+ Pane::new(self.panes_created),
+ );
+
+ if let Some((pane, _)) = result {
+ self.focus = Some(pane);
+ }
+
+ self.panes_created += 1;
+ }
+ }
+ Message::FocusAdjacent(direction) => {
+ if let Some(pane) = self.focus {
+ if let Some(adjacent) =
+ self.panes.adjacent(&pane, direction)
+ {
+ self.focus = Some(adjacent);
+ }
+ }
+ }
+ Message::Clicked(pane) => {
+ self.focus = Some(pane);
+ }
+ Message::Resized(pane_grid::ResizeEvent { split, ratio }) => {
+ self.panes.resize(&split, ratio);
+ }
+ Message::Dragged(pane_grid::DragEvent::Dropped {
+ pane,
+ target,
+ }) => {
+ self.panes.swap(&pane, &target);
}
- Message::DecrementPressed => {
- self.value -= 1;
+ Message::Dragged(_) => {}
+ Message::TogglePin(pane) => {
+ if let Some(Pane { is_pinned, .. }) = self.panes.get_mut(&pane)
+ {
+ *is_pinned = !*is_pinned;
+ }
+ }
+ Message::Close(pane) => {
+ if let Some((_, sibling)) = self.panes.close(&pane) {
+ self.focus = Some(sibling);
+ }
+ }
+ Message::CloseFocused => {
+ if let Some(pane) = self.focus {
+ if let Some(Pane { is_pinned, .. }) = self.panes.get(&pane)
+ {
+ if !is_pinned {
+ if let Some((_, sibling)) = self.panes.close(&pane)
+ {
+ self.focus = Some(sibling);
+ }
+ }
+ }
+ }
}
}
Command::none()
}
+ fn subscription(&self) -> Subscription<Message> {
+ subscription::events_with(|event, status| {
+ if let event::Status::Captured = status {
+ return None;
+ }
+
+ match event {
+ Event::Keyboard(keyboard::Event::KeyPressed {
+ modifiers,
+ key_code,
+ }) if modifiers.command() => handle_hotkey(key_code),
+ _ => None,
+ }
+ })
+ }
+
fn view(&self) -> Element<Message> {
- column()
- .padding(20)
- .align_items(Alignment::Center)
- .push(button("Increment").on_press(Message::IncrementPressed))
- .push(text(self.value.to_string()).size(50))
- .push(button("Decrement").on_press(Message::DecrementPressed))
+ let focus = self.focus;
+ let total_panes = self.panes.len();
+
+ let pane_grid = PaneGrid::new(&self.panes, |id, pane| {
+ let is_focused = focus == Some(id);
+
+ let pin_button = button(
+ text(if pane.is_pinned { "Unpin" } else { "Pin" }).size(14),
+ )
+ .on_press(Message::TogglePin(id))
+ .padding(3);
+
+ let title = row![
+ pin_button,
+ "Pane",
+ text(pane.id.to_string()).style(if is_focused {
+ PANE_ID_COLOR_FOCUSED
+ } else {
+ PANE_ID_COLOR_UNFOCUSED
+ }),
+ ]
+ .spacing(5);
+
+ let title_bar = pane_grid::TitleBar::new(title)
+ .controls(view_controls(id, total_panes, pane.is_pinned))
+ .padding(10)
+ .style(if is_focused {
+ style::title_bar_focused
+ } else {
+ style::title_bar_active
+ });
+
+ pane_grid::Content::new(responsive(move |size| {
+ view_content(id, total_panes, pane.is_pinned, size)
+ }))
+ .title_bar(title_bar)
+ .style(if is_focused {
+ style::pane_focused
+ } else {
+ style::pane_active
+ })
+ })
+ .width(Length::Fill)
+ .height(Length::Fill)
+ .spacing(10)
+ .on_click(Message::Clicked)
+ .on_drag(Message::Dragged)
+ .on_resize(10, Message::Resized);
+
+ container(pane_grid)
+ .width(Length::Fill)
+ .height(Length::Fill)
+ .padding(10)
.into()
}
}
+
+const PANE_ID_COLOR_UNFOCUSED: Color = Color::from_rgb(
+ 0xFF as f32 / 255.0,
+ 0xC7 as f32 / 255.0,
+ 0xC7 as f32 / 255.0,
+);
+const PANE_ID_COLOR_FOCUSED: Color = Color::from_rgb(
+ 0xFF as f32 / 255.0,
+ 0x47 as f32 / 255.0,
+ 0x47 as f32 / 255.0,
+);
+
+fn handle_hotkey(key_code: keyboard::KeyCode) -> Option<Message> {
+ use keyboard::KeyCode;
+ use pane_grid::{Axis, Direction};
+
+ let direction = match key_code {
+ KeyCode::Up => Some(Direction::Up),
+ KeyCode::Down => Some(Direction::Down),
+ KeyCode::Left => Some(Direction::Left),
+ KeyCode::Right => Some(Direction::Right),
+ _ => None,
+ };
+
+ match key_code {
+ KeyCode::V => Some(Message::SplitFocused(Axis::Vertical)),
+ KeyCode::H => Some(Message::SplitFocused(Axis::Horizontal)),
+ KeyCode::W => Some(Message::CloseFocused),
+ _ => direction.map(Message::FocusAdjacent),
+ }
+}
+
+struct Pane {
+ id: usize,
+ pub is_pinned: bool,
+}
+
+impl Pane {
+ fn new(id: usize) -> Self {
+ Self {
+ id,
+ is_pinned: false,
+ }
+ }
+}
+
+fn view_content<'a>(
+ pane: pane_grid::Pane,
+ total_panes: usize,
+ is_pinned: bool,
+ size: Size,
+) -> Element<'a, Message> {
+ let button = |label, message| {
+ button(
+ text(label)
+ .width(Length::Fill)
+ .horizontal_alignment(alignment::Horizontal::Center)
+ .size(16),
+ )
+ .width(Length::Fill)
+ .padding(8)
+ .on_press(message)
+ };
+
+ let mut controls = column![
+ button(
+ "Split horizontally",
+ Message::Split(pane_grid::Axis::Horizontal, pane),
+ ),
+ button(
+ "Split vertically",
+ Message::Split(pane_grid::Axis::Vertical, pane),
+ )
+ ]
+ .spacing(5)
+ .max_width(150);
+
+ if total_panes > 1 && !is_pinned {
+ controls = controls.push(
+ button("Close", Message::Close(pane))
+ .style(theme::Button::Destructive),
+ );
+ }
+
+ let content = column![
+ text(format!("{}x{}", size.width, size.height)).size(24),
+ controls,
+ ]
+ .width(Length::Fill)
+ .spacing(10)
+ .align_items(Alignment::Center);
+
+ container(scrollable(content))
+ .width(Length::Fill)
+ .height(Length::Fill)
+ .padding(5)
+ .center_y()
+ .into()
+}
+
+fn view_controls<'a>(
+ pane: pane_grid::Pane,
+ total_panes: usize,
+ is_pinned: bool,
+) -> Element<'a, Message> {
+ let mut button = button(text("Close").size(14))
+ .style(theme::Button::Destructive)
+ .padding(3);
+
+ if total_panes > 1 && !is_pinned {
+ button = button.on_press(Message::Close(pane));
+ }
+
+ button.into()
+}
+
+mod style {
+ use iced::widget::container;
+ use iced::Theme;
+
+ pub fn title_bar_active(theme: &Theme) -> container::Appearance {
+ let palette = theme.extended_palette();
+
+ container::Appearance {
+ text_color: Some(palette.background.strong.text),
+ background: Some(palette.background.strong.color.into()),
+ ..Default::default()
+ }
+ }
+
+ pub fn title_bar_focused(theme: &Theme) -> container::Appearance {
+ let palette = theme.extended_palette();
+
+ container::Appearance {
+ text_color: Some(palette.primary.strong.text),
+ background: Some(palette.primary.strong.color.into()),
+ ..Default::default()
+ }
+ }
+
+ pub fn pane_active(theme: &Theme) -> container::Appearance {
+ let palette = theme.extended_palette();
+
+ container::Appearance {
+ background: Some(palette.background.weak.color.into()),
+ border_width: 2.0,
+ border_color: palette.background.strong.color,
+ ..Default::default()
+ }
+ }
+
+ pub fn pane_focused(theme: &Theme) -> container::Appearance {
+ let palette = theme.extended_palette();
+
+ container::Appearance {
+ background: Some(palette.background.weak.color.into()),
+ border_width: 2.0,
+ border_color: palette.primary.strong.color,
+ ..Default::default()
+ }
+ }
+}