Skip to content

Commit

Permalink
feat(ux): change themes at runtime (zellij-org#3559)
Browse files Browse the repository at this point in the history
  • Loading branch information
imsnif authored and Tomcat-42 committed Nov 9, 2024
1 parent 516a9f6 commit 4fe6041
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 31 deletions.
4 changes: 2 additions & 2 deletions zellij-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ pub fn start_client(
config.env.set_vars();

let palette = config
.theme_config(&config_options)
.theme_config(config_options.theme.as_ref())
.unwrap_or_else(|| os_input.load_palette());

let full_screen_ws = os_input.get_terminal_size_using_fd(0);
Expand Down Expand Up @@ -624,7 +624,7 @@ pub fn start_server_detached(
config.env.set_vars();

let palette = config
.theme_config(&config_options)
.theme_config(config_options.theme.as_ref())
.unwrap_or_else(|| os_input.load_palette());

let client_attributes = ClientAttributes {
Expand Down
4 changes: 4 additions & 0 deletions zellij-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ use zellij_utils::{
plugins::PluginAliases,
},
ipc::{ClientAttributes, ExitReason, ServerToClientMsg},
shared::default_palette,
};

pub type ClientId = u16;
Expand Down Expand Up @@ -267,6 +268,9 @@ impl SessionMetaData {
client_id,
keybinds: Some(new_config.keybinds.clone()),
default_mode: new_config.options.default_mode,
theme: new_config
.theme_config(new_config.options.theme.as_ref())
.or_else(|| Some(default_palette())),
})
.unwrap();
self.senders
Expand Down
8 changes: 7 additions & 1 deletion zellij-server/src/panes/floating_panes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use std::collections::{BTreeMap, HashMap, HashSet};
use std::rc::Rc;
use std::time::Instant;
use zellij_utils::{
data::{ModeInfo, Style},
data::{ModeInfo, Palette, Style},
errors::prelude::*,
input::command::RunCommand,
input::layout::{FloatingPaneLayout, Run, RunPluginOrAlias},
Expand Down Expand Up @@ -913,4 +913,10 @@ impl FloatingPanes {
},
}
}
pub fn update_pane_themes(&mut self, theme: Palette) {
self.style.colors = theme;
for pane in self.panes.values_mut() {
pane.update_theme(theme);
}
}
}
3 changes: 3 additions & 0 deletions zellij-server/src/panes/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2155,6 +2155,9 @@ impl Grid {
pub fn unlock_renders(&mut self) {
self.lock_renders = false;
}
pub fn update_theme(&mut self, theme: Palette) {
self.style.colors = theme.clone();
}
}

impl Perform for Grid {
Expand Down
6 changes: 6 additions & 0 deletions zellij-server/src/panes/plugin_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,12 @@ impl Pane for PluginPane {
self.pane_name = String::from_utf8_lossy(&buf).to_string();
self.set_should_render(true);
}
fn update_theme(&mut self, theme: Palette) {
self.style.colors = theme.clone();
for grid in self.grids.values_mut() {
grid.update_theme(theme.clone());
}
}
}

impl PluginPane {
Expand Down
8 changes: 8 additions & 0 deletions zellij-server/src/panes/terminal_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,14 @@ impl Pane for TerminalPane {
run_command.clone()
})
}
fn update_theme(&mut self, theme: Palette) {
self.style.colors = theme.clone();
self.grid.update_theme(theme);
if self.banner.is_some() {
// we do this so that the banner will be updated with the new theme colors
self.render_first_run_banner();
}
}
}

impl TerminalPane {
Expand Down
8 changes: 7 additions & 1 deletion zellij-server/src/panes/tiled_panes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{
};
use stacked_panes::StackedPanes;
use zellij_utils::{
data::{Direction, ModeInfo, PaneInfo, ResizeStrategy, Style},
data::{Direction, ModeInfo, Palette, PaneInfo, ResizeStrategy, Style},
errors::prelude::*,
input::{
command::RunCommand,
Expand Down Expand Up @@ -1766,6 +1766,12 @@ impl TiledPanes {
}
pane_infos
}
pub fn update_pane_themes(&mut self, theme: Palette) {
self.style.colors = theme;
for pane in self.panes.values_mut() {
pane.update_theme(theme);
}
}
}

#[allow(clippy::borrowed_box)]
Expand Down
17 changes: 0 additions & 17 deletions zellij-server/src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,23 +93,6 @@ pub(crate) fn route_action(
},
Action::SwitchToMode(mode) => {
let attrs = &client_attributes;
// TODO: use the palette from the client and remove it from the server os api
// this is left here as a stop gap measure until we shift some code around
// to allow for this
// TODO: Need access to `ClientAttributes` here
senders
.send_to_plugin(PluginInstruction::Update(vec![(
None,
Some(client_id),
Event::ModeUpdate(get_mode_info(
mode,
attrs,
capabilities,
&client_keybinds,
Some(default_mode),
)),
)]))
.with_context(err_context)?;
senders
.send_to_server(ServerInstruction::ChangeMode(client_id, mode))
.with_context(err_context)?;
Expand Down
38 changes: 30 additions & 8 deletions zellij-server/src/screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ pub enum ScreenInstruction {
client_id: ClientId,
keybinds: Option<Keybinds>,
default_mode: Option<InputMode>,
theme: Option<Palette>,
},
RerunCommandPane(u32), // u32 - terminal pane id
}
Expand Down Expand Up @@ -1735,11 +1736,13 @@ impl Screen {
if mode_info.session_name.as_ref() != Some(&self.session_name) {
mode_info.session_name = Some(self.session_name.clone());
}
let previous_mode = self

let previous_mode_info = self
.mode_info
.get(&client_id)
.unwrap_or(&self.default_mode_info)
.mode;
.unwrap_or(&self.default_mode_info);
let previous_mode = previous_mode_info.mode;
mode_info.style = previous_mode_info.style;

let err_context = || {
format!(
Expand Down Expand Up @@ -2183,10 +2186,22 @@ impl Screen {
&mut self,
new_keybinds: Option<Keybinds>,
new_default_mode: Option<InputMode>,
theme: Option<Palette>,
client_id: ClientId,
) -> Result<()> {
let should_update_mode_info =
new_keybinds.is_some() || new_default_mode.is_some() || theme.is_some();

// themes are currently global and not per-client
if let Some(theme) = theme {
self.default_mode_info.update_theme(theme);
for tab in self.tabs.values_mut() {
tab.update_theme(theme);
}
}

// client specific configuration
if self.connected_clients_contains(&client_id) {
let should_update_mode_info = new_keybinds.is_some() || new_default_mode.is_some();
let mode_info = self
.mode_info
.entry(client_id)
Expand All @@ -2197,15 +2212,21 @@ impl Screen {
if let Some(new_default_mode) = new_default_mode {
mode_info.update_default_mode(new_default_mode);
}
if let Some(theme) = theme {
mode_info.update_theme(theme);
}
if should_update_mode_info {
for tab in self.tabs.values_mut() {
tab.change_mode_info(mode_info.clone(), client_id);
tab.mark_active_pane_for_rerender(client_id);
tab.update_input_modes()?;
}
}
} else {
log::error!("Could not find client_id {client_id} to rebind keys");
}

if should_update_mode_info {
for tab in self.tabs.values_mut() {
tab.update_input_modes()?;
}
}
Ok(())
}
Expand Down Expand Up @@ -4082,9 +4103,10 @@ pub(crate) fn screen_thread_main(
client_id,
keybinds,
default_mode,
theme,
} => {
screen
.reconfigure_mode_info(keybinds, default_mode, client_id)
.reconfigure_mode_info(keybinds, default_mode, theme, client_id)
.non_fatal();
},
ScreenInstruction::RerunCommandPane(terminal_pane_id) => {
Expand Down
9 changes: 9 additions & 0 deletions zellij-server/src/tab/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ pub trait Pane {
fn rerun(&mut self) -> Option<RunCommand> {
None
} // only relevant to terminal panes
fn update_theme(&mut self, _theme: Palette) {}
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -3951,6 +3952,14 @@ impl Tab {
},
}
}
pub fn update_theme(&mut self, theme: Palette) {
self.style.colors = theme;
self.floating_panes.update_pane_themes(theme);
self.tiled_panes.update_pane_themes(theme);
for (_, pane) in self.suppressed_panes.values_mut() {
pane.update_theme(theme);
}
}
}

pub fn pane_info_for_pane(pane_id: &PaneId, pane: &Box<dyn Pane>) -> PaneInfo {
Expand Down
3 changes: 3 additions & 0 deletions zellij-utils/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,9 @@ impl ModeInfo {
pub fn update_default_mode(&mut self, new_default_mode: InputMode) {
self.base_mode = Some(new_default_mode);
}
pub fn update_theme(&mut self, theme: Palette) {
self.style.colors = theme;
}
}

#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)]
Expand Down
4 changes: 2 additions & 2 deletions zellij-utils/src/input/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ impl TryFrom<&CliArgs> for Config {
}

impl Config {
pub fn theme_config(&self, opts: &Options) -> Option<Palette> {
match &opts.theme {
pub fn theme_config(&self, theme_name: Option<&String>) -> Option<Palette> {
match &theme_name {
Some(theme_name) => self.themes.get_theme(theme_name).map(|theme| theme.palette),
None => self.themes.get_theme("default").map(|theme| theme.palette),
}
Expand Down

0 comments on commit 4fe6041

Please # to comment.