Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions iced/src/figure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ where
}

/// Set the scale of the [`Figure`]
pub fn scale(mut self, scale: impl Into<f32>) -> Self {
self.scale = scale.into();
pub fn scale(mut self, scale: f32) -> Self {
self.scale = scale;
self
}

Expand Down Expand Up @@ -372,6 +372,7 @@ pub fn map_style(theme: &iced::Theme) -> plotive::Style {
iced::Theme::CatppuccinMacchiato => plotive::Style::catppuccin_macchiato(),
iced::Theme::CatppuccinFrappe => plotive::Style::catppuccin_frappe(),
iced::Theme::CatppuccinLatte => plotive::Style::catppuccin_latte(),
iced::Theme::Dracula => plotive::Style::dracula(),
_ => {
let theme = map_theme(theme);
let palette = if theme.is_dark() {
Expand Down
147 changes: 128 additions & 19 deletions iced/src/show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ pub struct Params {
pub style: Option<plotive::Style>,
pub fontdb: Option<Arc<fontdb::Database>>,
pub commands: Commands,
pub title: Option<String>,
}

impl Default for Params {
Expand All @@ -143,6 +144,7 @@ impl Default for Params {
style: None,
fontdb: None,
commands: Commands::all(),
title: None,
}
}
}
Expand All @@ -168,7 +170,7 @@ impl Show for des::Figure {
.prepare(&*data_source, Some(&*fontdb))
.expect("Failed to prepare figure");

show_app(fig, data_source, fontdb, params.style)
show_app(fig, data_source, fontdb, params.style, params.title)
}
}

Expand All @@ -181,15 +183,63 @@ impl Show for drawing::PreparedFigure {
.fontdb
.unwrap_or_else(|| Arc::new(plotive::bundled_font_db()));

show_app(self, data_source, fontdb, params.style)
show_app(self, data_source, fontdb, params.style, params.title)
}
}

fn color_to_iced(color: &plotive::Rgba8) -> iced::Color {
iced::Color::from_rgba(
color.r() as f32 / 255.0,
color.g() as f32 / 255.0,
color.b() as f32 / 255.0,
color.a() as f32 / 255.0,
)
}

fn theme_plotive_to_iced(pv_style: &plotive::Style) -> iced::Theme {
if pv_style == &plotive::Style::dracula() {
iced::Theme::Dracula
} else if pv_style == &plotive::Style::catppuccin_mocha() {
iced::Theme::CatppuccinMocha
} else if pv_style == &plotive::Style::catppuccin_latte() {
iced::Theme::CatppuccinLatte
} else if pv_style == &plotive::Style::catppuccin_frappe() {
iced::Theme::CatppuccinFrappe
} else if pv_style == &plotive::Style::catppuccin_macchiato() {
iced::Theme::CatppuccinMacchiato
} else {
let palette = iced::theme::Palette {
background: color_to_iced(&pv_style.theme().background()),
text: color_to_iced(&pv_style.theme().foreground()),
primary: color_to_iced(
&pv_style
.palette()
.get(plotive::style::series::IndexColor(0)),
),
success: iced::theme::Palette::LIGHT.success,
warning: iced::theme::Palette::LIGHT.warning,
danger: iced::theme::Palette::LIGHT.danger,
};
iced::Theme::custom("plotive", palette)
}
}

fn theme_from_show<D>(show: &FigureShow<D>) -> iced::Theme
where
D: data::Source + ?Sized + 'static,
{
show.style
.as_ref()
.map(theme_plotive_to_iced)
.unwrap_or(iced::Theme::Light)
}

fn show_app<D>(
fig: drawing::PreparedFigure,
data_source: Arc<D>,
fontdb: Arc<fontdb::Database>,
style: Option<plotive::Style>,
title: Option<String>,
) -> iced::Result
where
D: data::Source + ?Sized + 'static,
Expand All @@ -203,11 +253,14 @@ where
let mut show = FigureShow::new(fontdb, Commands::all(), None);
show.set_figure(fig, data_source.clone());
show.set_style(style.clone());
show.set_title(title.clone());
(show, iced::Task::none())
},
FigureShow::update,
FigureShow::view,
)
.theme(theme_from_show::<D>)
.title(FigureShow::title)
// subscribe to key events
.subscription(FigureShow::subscription)
.run()
Expand Down Expand Up @@ -274,6 +327,7 @@ pub struct FigureShow<D: data::Source + ?Sized + 'static> {
fontdb: Arc<fontdb::Database>,
style: Option<plotive::Style>,
commands: Commands,
title: Option<String>,
at_home: bool,
over_plot: bool,
tb_status: Option<(String, String)>,
Expand Down Expand Up @@ -304,6 +358,7 @@ where
at_home: true,
over_plot: false,
tb_status: None,
title: None,
interaction: Interaction::None,
middle_but_drag: None,
fig_scale: 1.0,
Expand Down Expand Up @@ -335,6 +390,28 @@ where
self.style = style;
}

pub fn theme(&self) -> iced::Theme {
self.style
.as_ref()
.map(theme_plotive_to_iced)
.unwrap_or(iced::Theme::Light)
}

pub fn set_title(&mut self, title: Option<String>) {
self.title = title;
}

pub fn title(&self) -> String {
if let Some(title) = self.fig.as_ref().and_then(|f| f.fig.title()) {
if let Some(fst_line) = title.lines().next() {
return fst_line.to_string();
}
}
self.title
.clone()
.unwrap_or_else(|| "Plotive Figure".to_string())
}

pub fn figure(&self) -> Option<&drawing::PreparedFigure> {
self.fig.as_ref().map(|f| &f.fig)
}
Expand All @@ -343,7 +420,7 @@ where
self.fig.as_ref().map(|f| &f.data_source)
}

pub fn style(&self) -> Option<&plotive::Style> {
pub fn plotive_style(&self) -> Option<&plotive::Style> {
self.style.as_ref()
}

Expand Down Expand Up @@ -686,6 +763,19 @@ where
/// Create a view for the toolbar
pub fn toolbar_view(&self) -> iced::Element<'_, Message> {
let has_fig = self.fig.is_some();
let theme = self.theme();
let icon_color = |style: fn(&iced::Theme, button::Status) -> button::Style,
enabled: bool| {
style(
&theme,
if enabled {
button::Status::Active
} else {
button::Status::Disabled
},
)
.text_color
};

let mut toolbar = row![];

Expand All @@ -704,17 +794,29 @@ where
const FA_ZOOM: &str = "expand";
const FA_PAN: &str = "arrows-up-down-left-right";

let home_button = button(fa_icon_solid(FA_HOME).size(ICON_SZ))
.on_press_maybe((has_fig && !self.at_home).then_some(Message::GoHome));
let zoom_button = button(fa_icon_solid(FA_ZOOM).size(ICON_SZ))
.on_press_maybe(has_fig.then_some(Message::EnableZoom));
let home_button = button(
fa_icon_solid(FA_HOME)
.size(ICON_SZ)
.color(icon_color(button::primary, has_fig && !self.at_home)),
)
.on_press_maybe((has_fig && !self.at_home).then_some(Message::GoHome));
let zoom_button = button(
fa_icon_solid(FA_ZOOM)
.size(ICON_SZ)
.color(icon_color(button::primary, has_fig)),
)
.on_press_maybe(has_fig.then_some(Message::EnableZoom));
let zoom_button = if zooming {
zoom_button.style(button::secondary)
} else {
zoom_button.style(button::primary)
};
let pan_button = button(fa_icon_solid(FA_PAN).size(ICON_SZ))
.on_press_maybe(has_fig.then_some(Message::EnablePan));
let pan_button = button(
fa_icon_solid(FA_PAN)
.size(ICON_SZ)
.color(icon_color(button::primary, has_fig)),
)
.on_press_maybe(has_fig.then_some(Message::EnablePan));
let pan_button = if panning {
pan_button.style(button::secondary)
} else {
Expand All @@ -738,19 +840,25 @@ where

if self.commands.has_export_png() {
let convert_png = button(
row![fa_icon_solid("file-image"), text("PNG").size(TEXT_SZ)]
.align_y(Alignment::Center)
.spacing(5),
row![
fa_icon_solid("file-image").color(icon_color(button::primary, has_fig)),
text("PNG").size(TEXT_SZ)
]
.align_y(Alignment::Center)
.spacing(5),
)
.on_press_maybe(has_fig.then_some(Message::ExportPng));
toolbar = toolbar.push(convert_png);
}

if self.commands.has_export_svg() {
let convert_svg = button(
row![fa_icon_solid("file-image"), text("SVG").size(TEXT_SZ)]
.align_y(Alignment::Center)
.spacing(5),
row![
fa_icon_solid("file-image").color(icon_color(button::primary, has_fig)),
text("SVG").size(TEXT_SZ)
]
.align_y(Alignment::Center)
.spacing(5),
)
.on_press_maybe(has_fig.then_some(Message::ExportSvg));
toolbar = toolbar.push(convert_svg);
Expand All @@ -759,9 +867,9 @@ where
#[cfg(feature = "clipboard")]
if self.commands.has_export_clipboard() {
let icon = if self.ack_clipboard {
fa_icon_solid("check")
fa_icon_solid("check").color(icon_color(button::primary, has_fig))
} else {
fa_icon("clipboard")
fa_icon("clipboard").color(icon_color(button::primary, has_fig))
};

let convert_clipboard =
Expand All @@ -771,8 +879,9 @@ where

#[cfg(feature = "data-csv")]
if self.commands.has_export_csv() {
let convert_csv = button(fa_icon_solid("file-csv"))
.on_press_maybe(has_fig.then_some(Message::ExportCsv));
let convert_csv =
button(fa_icon_solid("file-csv").color(icon_color(button::primary, has_fig)))
.on_press_maybe(has_fig.then_some(Message::ExportCsv));
toolbar = toolbar.push(convert_csv);
}

Expand Down
5 changes: 5 additions & 0 deletions src/drawing/figure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ impl PreparedFigure {
self.size
}

/// Get the text of the figure title, if any.
pub fn title(&self) -> Option<&str> {
self.title.as_ref().map(|(_, text)| text.text.as_str())
}

///
pub fn plot_indices(&self) -> impl Iterator<Item = des::PlotIdx> + '_ {
self.plots.iter_indices()
Expand Down
Loading