Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop menu tree changes #808

Draft
wants to merge 17 commits into
base: master
Choose a base branch
from
Draft
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,14 @@ tokio = [
# Wayland window support
wayland = [
"ashpd?/wayland",
"autosize",
"iced_runtime/wayland",
"iced/wayland",
"iced_winit/wayland",
"cctk",
"surface-message",
]
surface-message = []
# multi-window support
multi-window = ["iced/multi-window"]
# Render with wgpu
Expand Down Expand Up @@ -104,7 +107,9 @@ libc = { version = "0.2.155", optional = true }
license = { version = "3.5.1", optional = true }
mime = { version = "0.3.17", optional = true }
palette = "0.7.3"
rfd = { version = "0.14.0", default-features = false, features = ["xdg-portal"], optional = true }
rfd = { version = "0.14.0", default-features = false, features = [
"xdg-portal",
], optional = true }
rustix = { version = "0.38.34", features = [
"pipe",
"process",
Expand Down
246 changes: 198 additions & 48 deletions examples/applet/src/window.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,82 @@
use cosmic::app::Core;
use cosmic::iced::application;
use cosmic::iced::platform_specific::shell::commands::popup::{destroy_popup, get_popup};
use cosmic::cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Gravity;
use cosmic::iced::event::listen_with;
use cosmic::iced::window::Id;
use cosmic::iced::{Length, Limits, Task};
use cosmic::iced::{self, Length, Limits, Task};
use cosmic::iced_runtime::core::window;
use cosmic::theme::iced;
use cosmic::widget::{list_column, settings, toggler};
use cosmic::{Element, Theme};
use cosmic::iced_runtime::platform_specific::wayland::popup::SctkPopupSettings;
use cosmic::iced_runtime::platform_specific::wayland::subsurface;
use cosmic::surface_message::{MessageWrapper, SurfaceMessage};
use cosmic::widget::dropdown::DropdownView;
use cosmic::widget::{autosize, dropdown, layer_container, list_column, settings, toggler};
use cosmic::{iced_core, Element};
use once_cell::sync::Lazy;

const ID: &str = "com.system76.CosmicAppletExample";

#[derive(Default)]
static SUBSURFACE_ID: Lazy<cosmic::widget::Id> =
Lazy::new(|| cosmic::widget::Id::new("subsurface"));

pub struct Window {
core: Core,
popup: Option<Id>,
example_row: bool,
selected: Option<usize>,
subsurface_id: Id,
dropdown_id: Id,
}

impl Default for Window {
fn default() -> Self {
Self {
core: Core::default(),
popup: None,
example_row: false,
selected: None,
subsurface_id: Id::unique(),
dropdown_id: Id::unique(),
}
}
}

#[derive(Clone, Debug)]
#[derive(Clone)]
pub enum Message {
TogglePopup,
PopupClosed(Id),
PopupCloseRequested(Id),
ToggleExampleRow(bool),
Selected(usize),
Surface(SurfaceMessage),
OpenDropdown(SctkPopupSettings, DropdownView<Message>),
}

impl std::fmt::Debug for Message {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::PopupClosed(arg0) => f.debug_tuple("PopupClosed").field(arg0).finish(),
Self::PopupCloseRequested(arg0) => {
f.debug_tuple("PopupCloseRequested").field(arg0).finish()
}
Self::ToggleExampleRow(arg0) => f.debug_tuple("ToggleExampleRow").field(arg0).finish(),
Self::Selected(arg0) => f.debug_tuple("Selected").field(arg0).finish(),
Self::Surface(arg0) => f.debug_tuple("Surface").field(arg0).finish(),
Self::OpenDropdown(arg0, _) => f.debug_tuple("OpenDropdown").field(arg0).finish(),
}
}
}

impl From<Message> for MessageWrapper<Message> {
fn from(value: Message) -> Self {
match value {
Message::Surface(s) => MessageWrapper::Surface(s),
m => MessageWrapper::Message(m),
}
}
}

impl From<SurfaceMessage> for Message {
fn from(value: SurfaceMessage) -> Self {
Message::Surface(value)
}
}

impl cosmic::Application for Window {
Expand Down Expand Up @@ -52,61 +107,156 @@ impl cosmic::Application for Window {

fn update(&mut self, message: Self::Message) -> Task<cosmic::app::Message<Self::Message>> {
match message {
Message::TogglePopup => {
return if let Some(p) = self.popup.take() {
destroy_popup(p)
} else {
let new_id = Id::unique();
self.popup.replace(new_id);
let mut popup_settings = self.core.applet.get_popup_settings(
self.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
popup_settings.positioner.size_limits = Limits::NONE
.max_width(372.0)
.min_width(300.0)
.min_height(200.0)
.max_height(1080.0)
.height(500)
.width(500);
popup_settings.positioner.size = Some((500, 500));
get_popup(popup_settings)
};
}
Message::PopupClosed(id) => {
if self.popup.as_ref() == Some(&id) {
self.popup = None;
}
}
Message::ToggleExampleRow(toggled) => self.example_row = toggled,
Message::ToggleExampleRow(toggled) => {
self.example_row = toggled;
}

Message::Surface(_) => {}
Message::Selected(i) => {
self.selected = Some(i);
return cosmic::task::message(cosmic::app::message::destroy_popup::<Window>(
self.dropdown_id,
));
}
Message::OpenDropdown(sctk_popup_settings, view) => {
self.dropdown_id = sctk_popup_settings.id;
return cosmic::task::message(cosmic::app::message::app_popup::<Window>(
move |_: &mut Window| sctk_popup_settings.clone(),
Some(Box::new(
move |_: &Window| -> cosmic::Element<'_, cosmic::app::Message<Message>> {
view().map(cosmic::app::Message::App)
},
)),
));
}
Message::PopupCloseRequested(id) => {
return cosmic::task::message(cosmic::app::message::destroy_popup::<Window>(id));
}
}
Task::none()
}

fn view(&self) -> Element<Self::Message> {
self.core
.applet
.icon_button("display-symbolic")
.on_press(Message::TogglePopup)
.into()
cosmic::widget::wayland::tooltip::widget::Tooltip::new(
self.core.applet.icon_button("display-symbolic").on_press(
if let Some(id) = self.popup {
cosmic::app::message::destroy_popup::<Window>(id)
} else {
cosmic::app::message::app_popup::<Window>(
|state: &mut Window| {
let new_id = Id::unique();
state.popup = Some(new_id);
let mut popup_settings = state.core.applet.get_popup_settings(
state.core.main_window_id().unwrap(),
new_id,
None,
None,
None,
);
popup_settings.positioner.size_limits = Limits::NONE
.max_width(372.0)
.min_width(300.0)
.min_height(200.0)
.max_height(1080.0)
.height(500)
.width(500);
popup_settings.positioner.size = Some((500, 500));
popup_settings
},
Some(
Box::new(
move |state: &Window| -> cosmic::Element<
'_,
cosmic::app::Message<Message>,
> {
{
let content_list = list_column()
.padding(5)
.spacing(0)
.add(settings::item(
"Example row",
cosmic::widget::container(
toggler(state.example_row).on_toggle(|value| {
Message::ToggleExampleRow(value)
}),
)
.height(Length::Fixed(50.)),
))
.add(
dropdown(
&["1", "asdf", "hello", "test"],
state.selected,
Message::Selected,
)
.with_popup(
state.popup.unwrap_or(Id::NONE),
Message::OpenDropdown,
)
.on_close_popup(Message::PopupCloseRequested),
);
Element::from(
state.core.applet.popup_container(content_list),
)
.map(cosmic::app::Message::App)
}
},
),
),
)
},
),
|layout| {
let bounds = layout.bounds();
let pos = bounds.position();
let size = bounds.size();

cosmic::app::message::subsurface(
move |app: &mut Window| subsurface::SctkSubsurfaceSettings {
parent: window::Id::RESERVED,
id: app.subsurface_id,
loc: iced::Point {
x: bounds.width / 2.,
y: bounds.height,
},
size: None,
z: 1,
steal_keyboard_focus: false,
offset: (0, 0),
gravity: Gravity::Bottom,
},
Some(Box::new(|_: &'_ Window| {
Element::from(autosize::autosize(
layer_container(cosmic::widget::text("hello"))
.layer(cosmic::cosmic_theme::Layer::Background),
SUBSURFACE_ID.clone(),
))
})),
)
},
cosmic::app::message::destroy_subsurface::<Window>(self.subsurface_id),
)
.into()
}

fn view_window(&self, _id: Id) -> Element<Self::Message> {
let content_list = list_column().padding(5).spacing(0).add(settings::item(
"Example row",
cosmic::widget::container(
toggler(self.example_row).on_toggle(|value| Message::ToggleExampleRow(value)),
)
.height(Length::Fixed(50.)),
));

self.core.applet.popup_container(content_list).into()
"oops".into()
}

fn style(&self) -> Option<cosmic::iced_runtime::Appearance> {
Some(cosmic::applet::style())
}

fn subscription(&self) -> cosmic::iced::Subscription<Self::Message> {
listen_with(|e, status, id| {
if matches!(e, iced::event::Event::Keyboard(_)) {
dbg!(e, id);
}
None
})
}
}
5 changes: 4 additions & 1 deletion examples/application/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ name = "application"
version = "0.1.0"
edition = "2021"

[features]
default = ["wayland"]
wayland = ["libcosmic/wayland"]

[dependencies]
tracing = "0.1.37"
tracing-subscriber = "0.3.17"
Expand All @@ -18,7 +22,6 @@ features = [
"xdg-portal",
"dbus-config",
"a11y",
"wayland",
"wgpu",
"single-instance",
"multi-window",
Expand Down
Loading