Support opacity
This commit is contained in:
parent
c93032ab9d
commit
72c97fd5fc
4 changed files with 86 additions and 24 deletions
|
|
@ -22,6 +22,7 @@ light = Light
|
|||
syntax-dark = Color scheme dark
|
||||
syntax-light = Color scheme light
|
||||
default-zoom-step = Zoom steps
|
||||
opacity = Background opacity
|
||||
|
||||
### Font
|
||||
font = Font
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ pub struct Config {
|
|||
pub bold_font_weight: u16,
|
||||
pub font_stretch: u16,
|
||||
pub font_size_zoom_step_mul_100: u16,
|
||||
pub opacity: u8,
|
||||
pub profiles: BTreeMap<ProfileId, Profile>,
|
||||
pub show_headerbar: bool,
|
||||
pub use_bright_bold: bool,
|
||||
|
|
@ -90,6 +91,7 @@ impl Default for Config {
|
|||
font_size_zoom_step_mul_100: 100,
|
||||
font_stretch: Stretch::Normal.to_number(),
|
||||
font_weight: Weight::NORMAL.0,
|
||||
opacity: 100,
|
||||
profiles: BTreeMap::new(),
|
||||
show_headerbar: true,
|
||||
syntax_theme_dark: "COSMIC Dark".to_string(),
|
||||
|
|
@ -114,6 +116,10 @@ impl Config {
|
|||
Metrics::new(font_size, line_height)
|
||||
}
|
||||
|
||||
pub fn opacity_ratio(&self) -> f32 {
|
||||
(self.opacity as f32) / 100.0
|
||||
}
|
||||
|
||||
// Get a sorted and adjusted for duplicates list of profiles names and ids
|
||||
pub fn profile_names(&self) -> Vec<(String, ProfileId)> {
|
||||
let mut profile_names = Vec::<(String, ProfileId)>::with_capacity(self.profiles.len());
|
||||
|
|
|
|||
62
src/main.rs
62
src/main.rs
|
|
@ -23,6 +23,7 @@ use cosmic::{
|
|||
use cosmic_text::{fontdb::FaceInfo, Family, Stretch, Weight};
|
||||
use std::{
|
||||
any::TypeId,
|
||||
cmp,
|
||||
collections::{BTreeMap, BTreeSet, HashMap},
|
||||
env, process,
|
||||
sync::{atomic::Ordering, Mutex},
|
||||
|
|
@ -266,6 +267,7 @@ pub enum Message {
|
|||
PaneResized(pane_grid::ResizeEvent),
|
||||
Modifiers(Modifiers),
|
||||
MouseEnter(pane_grid::Pane),
|
||||
Opacity(u8),
|
||||
Paste(Option<segmented_button::Entity>),
|
||||
PasteValue(Option<segmented_button::Entity>, String),
|
||||
ProfileCollapse(ProfileId),
|
||||
|
|
@ -728,8 +730,14 @@ impl App {
|
|||
Message::DefaultZoomStep(index)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.add(
|
||||
widget::settings::item::builder(fl!("opacity"))
|
||||
.description(format!("{}%", self.config.opacity))
|
||||
.control(widget::slider(0..=100, self.config.opacity, |opacity| {
|
||||
Message::Opacity(opacity)
|
||||
})),
|
||||
);
|
||||
//TODO: background opacity
|
||||
|
||||
let mut font_section = widget::settings::view_section(fl!("font"))
|
||||
.add(
|
||||
|
|
@ -934,6 +942,7 @@ impl Application for App {
|
|||
|
||||
/// Creates the application, and optionally emits command on initialize.
|
||||
fn init(mut core: Core, flags: Self::Flags) -> (Self, Command<Self::Message>) {
|
||||
core.window.content_container = false;
|
||||
core.window.show_headerbar = flags.config.show_headerbar;
|
||||
|
||||
// Update font name from config
|
||||
|
|
@ -1106,6 +1115,33 @@ impl Application for App {
|
|||
|
||||
/// Handle application events here.
|
||||
fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
|
||||
// Helper for updating config values efficiently
|
||||
macro_rules! config_set {
|
||||
($name: ident, $value: expr) => {
|
||||
match &self.config_handler {
|
||||
Some(config_handler) => {
|
||||
match paste::paste! { self.config.[<set_ $name>](config_handler, $value) } {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
log::warn!(
|
||||
"failed to save config {:?}: {}",
|
||||
stringify!($name),
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
self.config.$name = $value;
|
||||
log::warn!(
|
||||
"failed to save config {:?}: no config handler",
|
||||
stringify!($name)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
match message {
|
||||
Message::AppTheme(app_theme) => {
|
||||
self.config.app_theme = app_theme;
|
||||
|
|
@ -1291,6 +1327,9 @@ impl Application for App {
|
|||
self.pane_model.focus = pane;
|
||||
return self.update_focus();
|
||||
}
|
||||
Message::Opacity(opacity) => {
|
||||
config_set!(opacity, cmp::min(100, opacity));
|
||||
}
|
||||
Message::PaneClicked(pane) => {
|
||||
self.pane_model.focus = pane;
|
||||
return self.update_title(Some(pane));
|
||||
|
|
@ -1443,10 +1482,7 @@ impl Application for App {
|
|||
}
|
||||
}
|
||||
Message::FocusFollowMouse(focus_follow_mouse) => {
|
||||
if focus_follow_mouse != self.config.focus_follow_mouse {
|
||||
self.config.focus_follow_mouse = focus_follow_mouse;
|
||||
return self.save_config();
|
||||
}
|
||||
config_set!(focus_follow_mouse, focus_follow_mouse);
|
||||
}
|
||||
Message::SystemThemeChange => {
|
||||
return self.update_config();
|
||||
|
|
@ -1751,10 +1787,11 @@ impl Application for App {
|
|||
fn view(&self) -> Element<Self::Message> {
|
||||
let cosmic_theme = self.core().system_theme().cosmic();
|
||||
let cosmic_theme::Spacing { space_xxs, .. } = cosmic_theme.spacing;
|
||||
|
||||
{
|
||||
// Update terminal window color
|
||||
//TODO: do this only when theme changes?
|
||||
let color = Color::from(cosmic_theme.bg_color());
|
||||
let color = Color::from(cosmic_theme.background.base);
|
||||
let bytes = color.into_rgba8();
|
||||
let data = (bytes[2] as u32)
|
||||
| ((bytes[1] as u32) << 8)
|
||||
|
|
@ -1773,6 +1810,7 @@ impl Application for App {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
let pane_grid = PaneGrid::new(&self.pane_model.panes, |pane, tab_model, _is_maximized| {
|
||||
let mut tab_column = widget::column::with_capacity(1);
|
||||
|
||||
|
|
@ -1798,9 +1836,13 @@ impl Application for App {
|
|||
.unwrap_or_else(widget::Id::unique);
|
||||
match tab_model.data::<Mutex<Terminal>>(entity) {
|
||||
Some(terminal) => {
|
||||
let mut terminal_box = terminal_box(terminal).id(terminal_id).on_context_menu(
|
||||
move |position_opt| Message::TabContextMenu(pane, position_opt),
|
||||
);
|
||||
let mut terminal_box = terminal_box(terminal)
|
||||
.id(terminal_id)
|
||||
.on_context_menu(move |position_opt| {
|
||||
Message::TabContextMenu(pane, position_opt)
|
||||
})
|
||||
.opacity(self.config.opacity_ratio())
|
||||
.padding(space_xxs);
|
||||
|
||||
if self.config.focus_follow_mouse {
|
||||
terminal_box =
|
||||
|
|
@ -1891,11 +1933,11 @@ impl Application for App {
|
|||
})
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.spacing(space_xxs)
|
||||
.on_click(Message::PaneClicked)
|
||||
.on_resize(space_xxs, Message::PaneResized)
|
||||
.on_drag(Message::PaneDragged);
|
||||
|
||||
//TODO: apply window border radius xs at bottom of window
|
||||
pane_grid.into()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,11 +44,13 @@ use crate::{terminal::Metadata, Terminal, TerminalScroll};
|
|||
pub struct TerminalBox<'a, Message> {
|
||||
terminal: &'a Mutex<Terminal>,
|
||||
id: Option<Id>,
|
||||
border: Border,
|
||||
padding: Padding,
|
||||
click_timing: Duration,
|
||||
context_menu: Option<Point>,
|
||||
on_context_menu: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
on_mouse_enter: Option<Box<dyn Fn() -> Message + 'a>>,
|
||||
opacity: Option<f32>,
|
||||
mouse_inside_boundary: Option<bool>,
|
||||
}
|
||||
|
||||
|
|
@ -60,11 +62,13 @@ where
|
|||
Self {
|
||||
terminal,
|
||||
id: None,
|
||||
border: Border::default(),
|
||||
padding: Padding::new(0.0),
|
||||
click_timing: Duration::from_millis(500),
|
||||
context_menu: None,
|
||||
on_context_menu: None,
|
||||
on_mouse_enter: None,
|
||||
opacity: None,
|
||||
mouse_inside_boundary: None,
|
||||
}
|
||||
}
|
||||
|
|
@ -74,6 +78,11 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
pub fn border<B: Into<Border>>(mut self, border: B) -> Self {
|
||||
self.border = border.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
|
||||
self.padding = padding.into();
|
||||
self
|
||||
|
|
@ -101,6 +110,11 @@ where
|
|||
self.on_mouse_enter = Some(Box::new(on_mouse_enter));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn opacity(mut self, opacity: f32) -> Self {
|
||||
self.opacity = Some(opacity);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn terminal_box<Message>(terminal: &Mutex<Terminal>) -> TerminalBox<'_, Message>
|
||||
|
|
@ -248,17 +262,18 @@ where
|
|||
|
||||
renderer.fill_quad(
|
||||
Quad {
|
||||
bounds: Rectangle::new(
|
||||
view_position,
|
||||
Size::new(view_w as f32 + scrollbar_w, view_h as f32),
|
||||
),
|
||||
bounds: layout.bounds(),
|
||||
border: self.border,
|
||||
..Default::default()
|
||||
},
|
||||
Color::new(
|
||||
background_color.r() as f32 / 255.0,
|
||||
background_color.g() as f32 / 255.0,
|
||||
background_color.b() as f32 / 255.0,
|
||||
background_color.a() as f32 / 255.0,
|
||||
match self.opacity {
|
||||
Some(opacity) => opacity,
|
||||
None => background_color.a() as f32 / 255.0,
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -301,10 +316,6 @@ where
|
|||
renderer: &mut Renderer,
|
||||
is_focused: bool,
|
||||
) {
|
||||
if self.metadata == self.default_metadata {
|
||||
return;
|
||||
}
|
||||
|
||||
let cosmic_text_to_iced_color = |color: cosmic_text::Color| {
|
||||
Color::new(
|
||||
color.r() as f32 / 255.0,
|
||||
|
|
@ -339,11 +350,13 @@ where
|
|||
}
|
||||
|
||||
let metadata = &self.metadata_set[self.metadata];
|
||||
let color = shade(metadata.bg, is_focused);
|
||||
renderer.fill_quad(
|
||||
mk_quad!(mk_pos_offset!(0.0, self.line_height), self.line_height),
|
||||
cosmic_text_to_iced_color(color),
|
||||
);
|
||||
if metadata.bg != self.metadata_set[self.default_metadata].bg {
|
||||
let color = shade(metadata.bg, is_focused);
|
||||
renderer.fill_quad(
|
||||
mk_quad!(mk_pos_offset!(0.0, self.line_height), self.line_height),
|
||||
cosmic_text_to_iced_color(color),
|
||||
);
|
||||
}
|
||||
|
||||
if !metadata.flags.is_empty() {
|
||||
let style_line_height =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue