Skip to content

Commit 47ec674

Browse files
authored
Merge pull request #88 from pop-os/vertical-time_jammy
fix(time): use autosized surface for correct sizing of time widget and add support for Left/Right anchors
2 parents e582a9f + a4ea05d commit 47ec674

File tree

1 file changed

+102
-22
lines changed

1 file changed

+102
-22
lines changed

cosmic-applet-time/src/main.rs

Lines changed: 102 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
1-
use cosmic::applet::CosmicAppletHelper;
1+
use cosmic::applet::{cosmic_panel_config::PanelAnchor, CosmicAppletHelper};
22
use cosmic::iced::wayland::{
33
popup::{destroy_popup, get_popup},
44
SurfaceIdWrapper,
55
};
66
use cosmic::iced::{
77
time,
8-
widget::{button, column, text},
9-
window, Alignment, Application, Color, Command, Length, Subscription,
8+
wayland::InitialSurface,
9+
widget::{button, column, text, vertical_space},
10+
window, Alignment, Application, Color, Command, Length, Rectangle, Subscription,
1011
};
12+
use cosmic::iced_sctk::layout::Limits;
1113
use cosmic::iced_style::application::{self, Appearance};
1214
use cosmic::theme;
13-
use cosmic::{Element, Theme};
15+
use cosmic::{
16+
widget::{icon, rectangle_tracker::*},
17+
Element, Theme,
18+
};
1419

1520
use chrono::{DateTime, Local, Timelike};
1621
use std::time::Duration;
1722

1823
pub fn main() -> cosmic::iced::Result {
19-
let mut helper = CosmicAppletHelper::default();
20-
helper.window_size(120, 16);
21-
Time::run(helper.window_settings())
24+
let helper = CosmicAppletHelper::default();
25+
let mut settings = helper.window_settings();
26+
match &mut settings.initial_surface {
27+
InitialSurface::XdgWindow(s) => {
28+
s.iced_settings.min_size = Some((1, 1));
29+
s.iced_settings.max_size = None;
30+
s.autosize = true;
31+
s.size_limits = Limits::NONE
32+
.min_height(1)
33+
.min_width(1);
34+
}
35+
_ => {}
36+
};
37+
Time::run(settings)
2238
}
2339

2440
struct Time {
@@ -29,6 +45,8 @@ struct Time {
2945
update_at: Every,
3046
now: DateTime<Local>,
3147
msg: String,
48+
rectangle_tracker: Option<RectangleTracker<u32>>,
49+
rectangle: Rectangle,
3250
}
3351

3452
impl Default for Time {
@@ -41,6 +59,8 @@ impl Default for Time {
4159
update_at: Every::Minute,
4260
now: Local::now(),
4361
msg: String::new(),
62+
rectangle_tracker: None,
63+
rectangle: Rectangle::default(),
4464
}
4565
}
4666
}
@@ -57,6 +77,7 @@ enum Message {
5777
TogglePopup,
5878
Tick,
5979
Ignore,
80+
Rectangle(RectangleUpdate<u32>),
6081
}
6182

6283
impl Application for Time {
@@ -103,10 +124,13 @@ impl Application for Time {
103124
.with_nanosecond(0)
104125
.expect("Setting nanoseconds to 0 should always be possible.");
105126
let wait = 1.max((next - now).num_milliseconds());
106-
time::every(Duration::from_millis(
107-
wait.try_into().unwrap_or(FALLBACK_DELAY),
108-
))
109-
.map(|_| Message::Tick)
127+
Subscription::batch(vec![
128+
rectangle_tracker_subscription(0).map(|(_, update)| Message::Rectangle(update)),
129+
time::every(Duration::from_millis(
130+
wait.try_into().unwrap_or(FALLBACK_DELAY),
131+
))
132+
.map(|_| Message::Tick),
133+
])
110134
}
111135

112136
fn update(&mut self, message: Message) -> Command<Message> {
@@ -133,13 +157,25 @@ impl Application for Time {
133157
let new_id = window::Id::new(self.id_ctr);
134158
self.popup.replace(new_id);
135159

136-
let popup_settings = self.applet_helper.get_popup_settings(
160+
let mut popup_settings = self.applet_helper.get_popup_settings(
137161
window::Id::new(0),
138162
new_id,
139163
None,
140-
Some(60),
164+
None,
141165
None,
142166
);
167+
let Rectangle {
168+
x,
169+
y,
170+
width,
171+
height,
172+
} = self.rectangle;
173+
popup_settings.positioner.anchor_rect = Rectangle::<i32> {
174+
x: x as i32,
175+
y: y as i32,
176+
width: width as i32,
177+
height: height as i32,
178+
};
143179
get_popup(popup_settings)
144180
}
145181
}
@@ -148,21 +184,65 @@ impl Application for Time {
148184
Command::none()
149185
}
150186
Message::Ignore => Command::none(),
187+
Message::Rectangle(u) => {
188+
match u {
189+
RectangleUpdate::Rectangle(r) => {
190+
self.rectangle = r.1;
191+
}
192+
RectangleUpdate::Init(tracker) => {
193+
self.rectangle_tracker = Some(tracker);
194+
}
195+
}
196+
Command::none()
197+
}
151198
}
152199
}
153200

154201
fn view(&self, id: SurfaceIdWrapper) -> Element<Message> {
155202
match id {
156203
SurfaceIdWrapper::LayerSurface(_) => unimplemented!(),
157-
SurfaceIdWrapper::Window(_) => button(
158-
column![text(self.now.format("%b %-d %-I:%M %p").to_string())]
159-
.width(Length::Fill)
160-
.align_items(Alignment::Center),
161-
)
162-
.on_press(Message::TogglePopup)
163-
.style(theme::Button::Text)
164-
.width(Length::Units(120))
165-
.into(),
204+
SurfaceIdWrapper::Window(_) => {
205+
let button = button(
206+
if matches!(
207+
self.applet_helper.anchor,
208+
PanelAnchor::Top | PanelAnchor::Bottom
209+
) {
210+
column![text(self.now.format("%b %-d %-I:%M %p").to_string())]
211+
} else {
212+
let mut date_time_col = column![
213+
icon(
214+
"emoji-recent-symbolic",
215+
self.applet_helper.suggested_size().0
216+
)
217+
.style(theme::Svg::Symbolic),
218+
text(self.now.format("%I").to_string()),
219+
text(self.now.format("%M").to_string()),
220+
text(self.now.format("%p").to_string()),
221+
vertical_space(Length::Units(4)),
222+
// TODO better calendar icon?
223+
icon(
224+
"calendar-go-today-symbolic",
225+
self.applet_helper.suggested_size().0
226+
)
227+
.style(theme::Svg::Symbolic),
228+
]
229+
.align_items(Alignment::Center)
230+
.spacing(4);
231+
for d in self.now.format("%x").to_string().split("/") {
232+
date_time_col = date_time_col.push(text(d.to_string()));
233+
}
234+
date_time_col
235+
},
236+
)
237+
.on_press(Message::TogglePopup)
238+
.style(theme::Button::Text);
239+
240+
if let Some(tracker) = self.rectangle_tracker.as_ref() {
241+
tracker.container(0, button).into()
242+
} else {
243+
button.into()
244+
}
245+
}
166246
SurfaceIdWrapper::Popup(_) => {
167247
let content = column![]
168248
.align_items(Alignment::Start)

0 commit comments

Comments
 (0)