styles: working on making it look just right
This commit is contained in:
@@ -1,29 +1,59 @@
|
|||||||
use iced::{Element, Length, widget::{container, pick_list, row}};
|
use iced::{
|
||||||
|
Background, Element, Length, Padding, Theme,
|
||||||
|
widget::{container, pick_list, row},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::message::{FileAction, Message, ViewAction};
|
use crate::message::{FileAction, Message, ViewAction};
|
||||||
|
|
||||||
pub fn view(
|
pub fn view(
|
||||||
selected_file_action: Option<FileAction>,
|
selected_file_action: Option<FileAction>,
|
||||||
selected_view_action: Option<ViewAction>,
|
selected_view_action: Option<ViewAction>,
|
||||||
) -> Element<'static, Message> {
|
) -> Element<'static, Message> {
|
||||||
|
let pick_list_padding = Padding {
|
||||||
|
left: 4.0,
|
||||||
|
right: 4.0,
|
||||||
|
top: 2.0,
|
||||||
|
bottom: 2.0,
|
||||||
|
};
|
||||||
|
|
||||||
let file_menu = pick_list(
|
let file_menu = pick_list(
|
||||||
FileAction::ALL,
|
FileAction::ALL,
|
||||||
selected_file_action,
|
selected_file_action,
|
||||||
Message::FileActionSelected,
|
Message::FileActionSelected,
|
||||||
)
|
)
|
||||||
.placeholder("File");
|
.padding(pick_list_padding)
|
||||||
|
.style(pick_list_style)
|
||||||
|
.placeholder("File");
|
||||||
|
|
||||||
let view_menu = pick_list(
|
let view_menu = pick_list(
|
||||||
ViewAction::ALL,
|
ViewAction::ALL,
|
||||||
selected_view_action,
|
selected_view_action,
|
||||||
Message::ViewActionSelected,
|
Message::ViewActionSelected,
|
||||||
)
|
)
|
||||||
.placeholder("View");
|
.padding(pick_list_padding)
|
||||||
|
.style(pick_list_style)
|
||||||
|
.placeholder("View");
|
||||||
|
|
||||||
container(
|
container(row![file_menu, view_menu].spacing(10))
|
||||||
row![file_menu, view_menu].spacing(10)
|
.style(|theme: &Theme| {
|
||||||
)
|
let base = container::Style::default();
|
||||||
|
|
||||||
|
container::Style {
|
||||||
|
background: container::primary(theme).background,
|
||||||
|
..base
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.padding(5)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pick_list_style(theme: &Theme, status: pick_list::Status) -> pick_list::Style {
|
||||||
|
let base = pick_list::default(theme, status);
|
||||||
|
|
||||||
|
pick_list::Style {
|
||||||
|
placeholder_color: base.text_color,
|
||||||
|
background: Background::Color(theme.palette().primary),
|
||||||
|
..base
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use iced::{
|
use iced::{
|
||||||
Element, Length, Theme, highlighter,
|
Element, Length, Theme, border, highlighter,
|
||||||
widget::{container, markdown, row, text_editor},
|
widget::{container, markdown, row, text_editor},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -9,9 +9,24 @@ pub fn view<'a>(file: &'a File, mode: Mode, font_size: u32) -> Element<'a, Messa
|
|||||||
match mode {
|
match mode {
|
||||||
Mode::Edit => {
|
Mode::Edit => {
|
||||||
let editor = text_editor(file.content())
|
let editor = text_editor(file.content())
|
||||||
.highlight(file.extension().unwrap_or("txt"), highlighter::Theme::Base16Ocean)
|
.highlight(
|
||||||
|
file.extension().unwrap_or("txt"),
|
||||||
|
highlighter::Theme::Base16Ocean,
|
||||||
|
)
|
||||||
|
.padding(10)
|
||||||
.size(font_size)
|
.size(font_size)
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
|
.style(|theme: &Theme, status: text_editor::Status| {
|
||||||
|
let base = text_editor::default(theme, status);
|
||||||
|
|
||||||
|
text_editor::Style {
|
||||||
|
border: border::Border {
|
||||||
|
width: 0.0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..base
|
||||||
|
}
|
||||||
|
})
|
||||||
.on_action(Message::Edit);
|
.on_action(Message::Edit);
|
||||||
|
|
||||||
container(row![editor]).height(Length::Fill).into()
|
container(row![editor]).height(Length::Fill).into()
|
||||||
|
|||||||
@@ -1,16 +1,26 @@
|
|||||||
use iced::widget::{container, row, text};
|
|
||||||
use iced::{Element, Length};
|
|
||||||
use crate::file::File;
|
use crate::file::File;
|
||||||
|
use iced::widget::{container, row, text};
|
||||||
|
use iced::{Element, Length, Padding, Theme};
|
||||||
|
|
||||||
pub fn view(file: &File) -> Element<'_, crate::Message> {
|
pub fn view(file: &File) -> Element<'_, crate::Message> {
|
||||||
let path_text = text(file.path_summary());
|
let path_text = text(file.path_summary()).size(12);
|
||||||
let cursor_text = text(file.position_summary());
|
let cursor_text = text(file.position_summary()).size(12);
|
||||||
|
|
||||||
container(
|
container(row![cursor_text, path_text].spacing(20))
|
||||||
row![cursor_text, path_text]
|
.style(|theme: &Theme| {
|
||||||
.spacing(20)
|
let base = container::Style::default();
|
||||||
)
|
|
||||||
|
container::Style {
|
||||||
|
background: container::primary(theme).background,
|
||||||
|
..base
|
||||||
|
}
|
||||||
|
})
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.padding(5)
|
.padding(Padding {
|
||||||
|
left: 20.0,
|
||||||
|
right: 20.0,
|
||||||
|
top: 5.0,
|
||||||
|
bottom: 5.0,
|
||||||
|
})
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|||||||
+62
-30
@@ -1,41 +1,73 @@
|
|||||||
use crate::file::File;
|
use crate::file::File;
|
||||||
use crate::message::{FileAction, Message};
|
use crate::message::{FileAction, Message};
|
||||||
use iced::{Background, Border, Theme, border};
|
use iced::{Background, Border, Padding, Theme, border};
|
||||||
use iced::{
|
use iced::{
|
||||||
Element,
|
Element,
|
||||||
widget::{button, container, row, scrollable, text},
|
widget::{button, container, row, scrollable, text},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn view<'a>(files: &'a [File], active_index: usize) -> Element<'a, Message> {
|
pub fn view<'a>(files: &'a [File], active_index: usize) -> Element<'a, Message> {
|
||||||
let tabs = files.iter().enumerate().map(|(index, file)| {
|
let tabs = files.iter().enumerate().map(|(index, file)| {
|
||||||
let is_focused = index == active_index;
|
let is_focused = index == active_index;
|
||||||
|
|
||||||
let label = text(file.display_name());
|
let label = text(file.display_name());
|
||||||
let close_btn =
|
let close_btn =
|
||||||
button(text("x")).on_press(Message::FileActionSelected(FileAction::Close(Some(index))));
|
button(text("x")).padding(1).on_press(Message::FileActionSelected(FileAction::Close(Some(index))));
|
||||||
|
|
||||||
button(row![label, close_btn].spacing(5))
|
button(
|
||||||
.on_press(Message::SwitchTab(index))
|
row![label, close_btn]
|
||||||
.padding(5)
|
.spacing(5)
|
||||||
.style(move |theme: &Theme, status| {
|
.align_y(iced::Alignment::Center),
|
||||||
let base = button::primary(theme, status);
|
)
|
||||||
let button_background = if is_focused {
|
.on_press(Message::SwitchTab(index))
|
||||||
base.background
|
.padding(Padding {
|
||||||
} else {
|
top: 5.0,
|
||||||
Some(Background::Color(theme.palette().background))
|
bottom: 5.0,
|
||||||
};
|
left: 10.0,
|
||||||
|
right: 10.0,
|
||||||
|
})
|
||||||
|
.style(move |theme: &Theme, status: button::Status| {
|
||||||
|
let base = button::primary(theme, status);
|
||||||
|
|
||||||
button::Style {
|
let button_background = if is_focused {
|
||||||
background: button_background,
|
Some(Background::Color(theme.palette().primary))
|
||||||
border: Border {
|
} else {
|
||||||
radius: border::radius(0).top_left(10).top_right(10),
|
Some(Background::Color(theme.palette().background))
|
||||||
..base.border
|
};
|
||||||
},
|
|
||||||
..base
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into()
|
|
||||||
});
|
|
||||||
|
|
||||||
scrollable(container(row(tabs).spacing(2))).into()
|
let button_style = button::Style {
|
||||||
|
background: button_background,
|
||||||
|
border: Border {
|
||||||
|
radius: border::radius(0).top_left(10).top_right(10),
|
||||||
|
..base.border
|
||||||
|
},
|
||||||
|
..base
|
||||||
|
};
|
||||||
|
|
||||||
|
match status {
|
||||||
|
button::Status::Hovered => button::Style {
|
||||||
|
background: Some(Background::Color(theme.palette().primary)),
|
||||||
|
..button_style
|
||||||
|
},
|
||||||
|
_ => button_style,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.into()
|
||||||
|
});
|
||||||
|
|
||||||
|
scrollable(container(row(tabs)).padding(Padding {
|
||||||
|
top: 5.0,
|
||||||
|
left: 5.0,
|
||||||
|
right: 5.0,
|
||||||
|
bottom: 0.0,
|
||||||
|
}))
|
||||||
|
.direction(scrollable::Direction::Horizontal(
|
||||||
|
scrollable::Scrollbar::new().spacing(1)
|
||||||
|
))
|
||||||
|
.style(|theme: &Theme, status: scrollable::Status| {
|
||||||
|
let mut style = scrollable::default(theme, status);
|
||||||
|
style.horizontal_rail.background = Some(Background::Color(theme.palette().primary));
|
||||||
|
style
|
||||||
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|||||||
+57
-49
@@ -7,9 +7,10 @@ mod key_bindings;
|
|||||||
mod message;
|
mod message;
|
||||||
mod state;
|
mod state;
|
||||||
|
|
||||||
use iced::Theme;
|
use iced::theme::Palette;
|
||||||
use iced::widget::column;
|
use iced::widget::column;
|
||||||
use iced::window::icon;
|
use iced::window::icon;
|
||||||
|
use iced::{Color, Theme};
|
||||||
use iced::{Element, Subscription, Task, event};
|
use iced::{Element, Subscription, Task, event};
|
||||||
use iced::{keyboard, window};
|
use iced::{keyboard, window};
|
||||||
|
|
||||||
@@ -17,69 +18,76 @@ use crate::message::Message;
|
|||||||
use crate::state::State;
|
use crate::state::State;
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
iced::application(boot, update, view)
|
iced::application(boot, update, view)
|
||||||
.subscription(subscription)
|
.subscription(subscription)
|
||||||
.font(constants::CUSTOM_FONT_BYTES)
|
.font(constants::CUSTOM_FONT_BYTES)
|
||||||
.theme(theme)
|
.theme(theme)
|
||||||
.settings(iced::Settings {
|
.settings(iced::Settings {
|
||||||
default_font: constants::CUSTOM_FONT,
|
default_font: constants::CUSTOM_FONT,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.window(window::Settings {
|
.window(window::Settings {
|
||||||
icon: Some(
|
icon: Some(icon::from_file_data(constants::ICON_BYTES, None).expect("Failed to load icon")),
|
||||||
icon::from_file_data(constants::ICON_BYTES, None).expect("Failed to load icon"),
|
..window::Settings::default()
|
||||||
),
|
})
|
||||||
..window::Settings::default()
|
.run()
|
||||||
})
|
|
||||||
.run()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn boot() -> State {
|
fn boot() -> State {
|
||||||
state::State::new()
|
state::State::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(state: &mut State, message: Message) -> Task<Message> {
|
fn update(state: &mut State, message: Message) -> Task<Message> {
|
||||||
match message {
|
match message {
|
||||||
Message::Edit(action) => handler::edit(state, action),
|
Message::Edit(action) => handler::edit(state, action),
|
||||||
Message::SwitchTab(index) => handler::switch_tab(state, index),
|
Message::SwitchTab(index) => handler::switch_tab(state, index),
|
||||||
Message::LinkClicked(url) => handler::link_clicked(url),
|
Message::LinkClicked(url) => handler::link_clicked(url),
|
||||||
Message::FileActionSelected(action) => handler::file_action(state, action),
|
Message::FileActionSelected(action) => handler::file_action(state, action),
|
||||||
Message::ViewActionSelected(action) => handler::view_action(state, action),
|
Message::ViewActionSelected(action) => handler::view_action(state, action),
|
||||||
Message::FileOpened(result) => handler::opened_file(state, result),
|
Message::FileOpened(result) => handler::opened_file(state, result),
|
||||||
Message::FileSaved(result) => handler::saved_file(state, result),
|
Message::FileSaved(result) => handler::saved_file(state, result),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(state: &State) -> Element<'_, Message> {
|
fn view(state: &State) -> Element<'_, Message> {
|
||||||
let current_file = state.active_file();
|
let current_file = state.active_file();
|
||||||
|
|
||||||
column![
|
column![
|
||||||
components::tabs::view(state.files(), state.current_file_index()),
|
components::tabs::view(state.files(), state.current_file_index()),
|
||||||
components::action_bar::view(state.selected_file_action(), state.selected_view_action()),
|
components::action_bar::view(state.selected_file_action(), state.selected_view_action()),
|
||||||
components::editor::view(current_file, state.mode(), state.font_size()),
|
components::editor::view(current_file, state.mode(), state.font_size()),
|
||||||
components::status_bar::view(current_file),
|
components::status_bar::view(current_file),
|
||||||
]
|
]
|
||||||
.padding(10)
|
.into()
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(_state: &State) -> Subscription<Message> {
|
fn subscription(_state: &State) -> Subscription<Message> {
|
||||||
event::listen_with(|e, _status, _win| -> Option<Message> {
|
event::listen_with(|e, _status, _win| -> Option<Message> {
|
||||||
match e {
|
match e {
|
||||||
iced::Event::Keyboard(keyboard::Event::KeyPressed { key, modifiers, .. }) => {
|
iced::Event::Keyboard(keyboard::Event::KeyPressed { key, modifiers, .. }) => {
|
||||||
for vb in key_bindings::ALL {
|
for vb in key_bindings::ALL {
|
||||||
if vb.should_handle(&key, &modifiers) {
|
if vb.should_handle(&key, &modifiers) {
|
||||||
return Some(vb.message());
|
return Some(vb.message());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn theme(_state: &State) -> Theme {
|
fn theme(_state: &State) -> Theme {
|
||||||
Theme::Dark
|
Theme::custom(
|
||||||
|
"Win11 Dark",
|
||||||
|
Palette {
|
||||||
|
background: Color::from_rgb8(0x20, 0x20, 0x20),
|
||||||
|
text: Color::from_rgb8(0xF2, 0xF2, 0xF2),
|
||||||
|
primary: Color::from_rgb8(0x2C, 0x2C, 0x2C),
|
||||||
|
success: Color::from_rgb8(0x4C, 0xC3, 0x8A),
|
||||||
|
warning: Color::from_rgb8(0xF5, 0xC8, 0x4B),
|
||||||
|
danger: Color::from_rgb8(0xE8, 0x6A, 0x6A),
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user