mirror of https://github.com/lapce/lapce.git
fix: rework titlebar (#990)
This commit is contained in:
parent
bd8ad59e2a
commit
46f9fca0fa
|
@ -2,6 +2,7 @@
|
|||
modal = false
|
||||
color-theme = "Lapce Dark"
|
||||
icon-theme = ""
|
||||
custom-titlebar = true
|
||||
|
||||
[editor]
|
||||
font-family = "Cascadia Code"
|
||||
|
@ -39,7 +40,6 @@ tab-min-width = 100
|
|||
scroll-width = 10
|
||||
drop-shadow-width = 0
|
||||
preview-editor-width = 0
|
||||
custom-titlebar = false
|
||||
hover-font-family = ""
|
||||
hover-font-size = 0
|
||||
|
||||
|
|
|
@ -150,6 +150,10 @@ pub struct LapceConfig {
|
|||
pub modal: bool,
|
||||
#[field_names(desc = "Set the color theme of Lapce")]
|
||||
pub color_theme: String,
|
||||
#[field_names(
|
||||
desc = "Enable customised titlebar and disable OS native one (Linux, BSD, Windows)"
|
||||
)]
|
||||
pub custom_titlebar: bool,
|
||||
}
|
||||
|
||||
#[derive(FieldNames, Debug, Clone, Deserialize, Serialize, Default)]
|
||||
|
|
|
@ -121,18 +121,23 @@ fn new_window_desc<W, T: druid::Data>(
|
|||
size: Size,
|
||||
pos: Point,
|
||||
maximised: bool,
|
||||
_config: &Arc<Config>,
|
||||
config: &Arc<Config>,
|
||||
) -> WindowDesc<T>
|
||||
where
|
||||
W: Widget<T> + 'static,
|
||||
{
|
||||
let mut desc = WindowDesc::new_with_id(window_id, root)
|
||||
.show_titlebar(false)
|
||||
.title(LocalizedString::new("Lapce").with_placeholder("Lapce"))
|
||||
.with_min_size(Size::new(384.0, 384.0))
|
||||
.window_size(size)
|
||||
.set_position(pos);
|
||||
|
||||
if cfg!(not(target_os = "macos")) {
|
||||
desc = desc.show_titlebar(!config.lapce.custom_titlebar);
|
||||
} else {
|
||||
desc = desc.show_titlebar(false);
|
||||
}
|
||||
|
||||
if maximised {
|
||||
desc = desc.set_window_state(WindowState::Maximized);
|
||||
}
|
||||
|
|
|
@ -2176,12 +2176,14 @@ pub struct LapceTabHeader {
|
|||
pub drag_start: Option<(Point, Point)>,
|
||||
pub mouse_pos: Point,
|
||||
close_icon_rect: Rect,
|
||||
holding_click_rect: Option<Rect>,
|
||||
}
|
||||
|
||||
impl LapceTabHeader {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
close_icon_rect: Rect::ZERO,
|
||||
holding_click_rect: None,
|
||||
drag_start: None,
|
||||
mouse_pos: Point::ZERO,
|
||||
}
|
||||
|
@ -2218,11 +2220,7 @@ fn event(
|
|||
}
|
||||
Event::MouseDown(mouse_event) => {
|
||||
if self.close_icon_rect.contains(mouse_event.pos) {
|
||||
ctx.submit_command(Command::new(
|
||||
LAPCE_UI_COMMAND,
|
||||
LapceUICommand::CloseTabId(data.id),
|
||||
Target::Auto,
|
||||
));
|
||||
self.holding_click_rect = Some(self.close_icon_rect);
|
||||
} else {
|
||||
self.drag_start =
|
||||
Some((ctx.to_window(mouse_event.pos), ctx.window_origin()));
|
||||
|
@ -2235,7 +2233,17 @@ fn event(
|
|||
));
|
||||
}
|
||||
}
|
||||
Event::MouseUp(_mouse_event) => {
|
||||
Event::MouseUp(mouse_event) => {
|
||||
if self.close_icon_rect.contains(mouse_event.pos)
|
||||
&& self.holding_click_rect.eq(&Some(self.close_icon_rect))
|
||||
{
|
||||
ctx.submit_command(Command::new(
|
||||
LAPCE_UI_COMMAND,
|
||||
LapceUICommand::CloseTabId(data.id),
|
||||
Target::Auto,
|
||||
));
|
||||
}
|
||||
self.holding_click_rect = None;
|
||||
ctx.set_active(false);
|
||||
self.drag_start = None;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#[cfg(not(target_os = "macos"))]
|
||||
use crate::window::window_controls;
|
||||
use crate::{palette::Palette, svg::get_svg};
|
||||
use druid::kurbo::Circle;
|
||||
use druid::WindowConfig;
|
||||
use druid::{kurbo::Circle, InternalEvent};
|
||||
use druid::{
|
||||
kurbo::Line,
|
||||
piet::{PietText, PietTextLayout, Svg, Text, TextLayout, TextLayoutBuilder},
|
||||
|
@ -28,8 +28,10 @@
|
|||
|
||||
pub struct Title {
|
||||
mouse_pos: Point,
|
||||
commands: Vec<(Rect, Command)>,
|
||||
svgs: Vec<(Svg, Rect, Option<Color>)>,
|
||||
menus: Vec<(Rect, Command)>,
|
||||
window_controls: Vec<(Rect, Command)>,
|
||||
holding_click_rect: Option<Rect>,
|
||||
svgs: Vec<(Svg, Rect, Option<Color>, Option<Color>)>,
|
||||
text_layouts: Vec<(PietTextLayout, Point)>,
|
||||
borders: Vec<Line>,
|
||||
rects: Vec<(Rect, Color)>,
|
||||
|
@ -43,7 +45,9 @@ pub fn new(data: &LapceTabData) -> Self {
|
|||
let palette = Palette::new(data);
|
||||
Self {
|
||||
mouse_pos: Point::ZERO,
|
||||
commands: Vec::new(),
|
||||
menus: Vec::new(),
|
||||
window_controls: Vec::new(),
|
||||
holding_click_rect: None,
|
||||
svgs: Vec::new(),
|
||||
text_layouts: Vec::new(),
|
||||
borders: Vec::new(),
|
||||
|
@ -63,7 +67,8 @@ fn update_content(
|
|||
piet_text: &mut PietText,
|
||||
size: Size,
|
||||
) -> Rect {
|
||||
self.commands.clear();
|
||||
self.menus.clear();
|
||||
self.window_controls.clear();
|
||||
self.svgs.clear();
|
||||
self.text_layouts.clear();
|
||||
self.borders.clear();
|
||||
|
@ -95,12 +100,13 @@ fn update_content(
|
|||
.clone()
|
||||
.with_alpha(0.5),
|
||||
),
|
||||
None,
|
||||
));
|
||||
x += size.height;
|
||||
}
|
||||
|
||||
let padding = 15.0;
|
||||
x = self.update_remote(data, piet_text, size, padding, x);
|
||||
x = self.update_remote(data, size, padding, x);
|
||||
x = self.update_source_control(data, piet_text, size, padding, x);
|
||||
|
||||
let mut region = Region::EMPTY;
|
||||
|
@ -137,7 +143,6 @@ fn update_content(
|
|||
fn update_remote(
|
||||
&mut self,
|
||||
data: &LapceTabData,
|
||||
_piet_text: &mut PietText,
|
||||
size: Size,
|
||||
_padding: f64,
|
||||
x: f64,
|
||||
|
@ -164,12 +169,13 @@ fn update_remote(
|
|||
Size::new(size.height, size.height)
|
||||
.to_rect()
|
||||
.with_origin(Point::new(x + 5.0, 0.0))
|
||||
.inflate(-8.0, -8.0),
|
||||
.inflate(-6.0, -6.0),
|
||||
Some(
|
||||
data.config
|
||||
.get_color_unchecked(LapceTheme::EDITOR_BACKGROUND)
|
||||
.clone(),
|
||||
),
|
||||
None,
|
||||
));
|
||||
let x = x + remote_rect.width();
|
||||
let command_rect =
|
||||
|
@ -184,7 +190,8 @@ fn update_remote(
|
|||
enabled: true,
|
||||
})];
|
||||
|
||||
if cfg!(target_os = "windows") {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
menu_items.push(MenuKind::Item(MenuItem {
|
||||
desc: None,
|
||||
command: LapceCommand {
|
||||
|
@ -208,7 +215,7 @@ fn update_remote(
|
|||
}));
|
||||
}
|
||||
|
||||
self.commands.push((
|
||||
self.menus.push((
|
||||
command_rect,
|
||||
Command::new(
|
||||
LAPCE_UI_COMMAND,
|
||||
|
@ -244,12 +251,13 @@ fn update_source_control(
|
|||
.with_origin(Point::new(x, 0.0));
|
||||
self.svgs.push((
|
||||
folder_svg,
|
||||
folder_rect.inflate(-10.5, -10.5),
|
||||
folder_rect.inflate(-8.5, -8.5),
|
||||
Some(
|
||||
data.config
|
||||
.get_color_unchecked(LapceTheme::EDITOR_FOREGROUND)
|
||||
.clone(),
|
||||
),
|
||||
None,
|
||||
));
|
||||
x += size.height;
|
||||
|
||||
|
@ -294,7 +302,7 @@ fn update_source_control(
|
|||
})
|
||||
})
|
||||
.collect();
|
||||
self.commands.push((
|
||||
self.menus.push((
|
||||
command_rect,
|
||||
Command::new(
|
||||
LAPCE_UI_COMMAND,
|
||||
|
@ -331,7 +339,10 @@ fn update_settings(
|
|||
x: f64,
|
||||
) -> f64 {
|
||||
let mut x = x;
|
||||
if cfg!(target_os = "macos") || data.multiple_tab {
|
||||
if cfg!(target_os = "macos")
|
||||
|| data.multiple_tab
|
||||
|| !data.config.lapce.custom_titlebar
|
||||
{
|
||||
x -= size.height;
|
||||
} else {
|
||||
x = size.width - (size.height * 4.0);
|
||||
|
@ -339,6 +350,30 @@ fn update_settings(
|
|||
|
||||
let offset = x;
|
||||
|
||||
let hover_color = {
|
||||
let (r, g, b, a) = data
|
||||
.config
|
||||
.get_color_unchecked(LapceTheme::PANEL_BACKGROUND)
|
||||
.to_owned()
|
||||
.as_rgba8();
|
||||
// TODO: hacky way to detect "lightness" of colour, should be fixed once we have dark/light themes
|
||||
if r < 128 || g < 128 || b < 128 {
|
||||
Color::rgba8(
|
||||
r.saturating_add(25),
|
||||
g.saturating_add(25),
|
||||
b.saturating_add(25),
|
||||
a,
|
||||
)
|
||||
} else {
|
||||
Color::rgba8(
|
||||
r.saturating_sub(30),
|
||||
g.saturating_sub(30),
|
||||
b.saturating_sub(30),
|
||||
a,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let settings_rect = Size::new(size.height, size.height)
|
||||
.to_rect()
|
||||
.with_origin(Point::new(x, 0.0));
|
||||
|
@ -351,6 +386,7 @@ fn update_settings(
|
|||
.get_color_unchecked(LapceTheme::EDITOR_FOREGROUND)
|
||||
.clone(),
|
||||
),
|
||||
Some(hover_color),
|
||||
));
|
||||
let latest_version = data
|
||||
.latest_release
|
||||
|
@ -433,7 +469,7 @@ fn update_settings(
|
|||
));
|
||||
self.text_layouts.push((text_layout, point));
|
||||
}
|
||||
self.commands.push((
|
||||
self.menus.push((
|
||||
settings_rect,
|
||||
Command::new(
|
||||
LAPCE_UI_COMMAND,
|
||||
|
@ -450,22 +486,21 @@ fn update_settings(
|
|||
));
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
if !data.multiple_tab {
|
||||
if !data.multiple_tab && data.config.lapce.custom_titlebar {
|
||||
x += size.height;
|
||||
let (commands, svgs, text_layouts) = window_controls(
|
||||
let (window_controls, svgs) = window_controls(
|
||||
data.window_id,
|
||||
window_state,
|
||||
piet_text,
|
||||
x,
|
||||
size.height,
|
||||
&data.config,
|
||||
);
|
||||
|
||||
for command in commands {
|
||||
self.commands.push(command);
|
||||
for command in window_controls {
|
||||
self.window_controls.push(command);
|
||||
}
|
||||
|
||||
for (svg, rect) in svgs {
|
||||
for (svg, rect, color) in svgs {
|
||||
self.svgs.push((
|
||||
svg,
|
||||
rect,
|
||||
|
@ -474,12 +509,9 @@ fn update_settings(
|
|||
.get_color_unchecked(LapceTheme::EDITOR_FOREGROUND)
|
||||
.clone(),
|
||||
),
|
||||
Some(color),
|
||||
));
|
||||
}
|
||||
|
||||
for text_layout in text_layouts {
|
||||
self.text_layouts.push(text_layout);
|
||||
}
|
||||
}
|
||||
|
||||
offset
|
||||
|
@ -549,6 +581,7 @@ fn update_folder(
|
|||
.get_color_unchecked(LapceTheme::EDITOR_FOREGROUND)
|
||||
.clone(),
|
||||
),
|
||||
None,
|
||||
));
|
||||
let menu_items = vec![
|
||||
MenuKind::Item(MenuItem {
|
||||
|
@ -581,8 +614,9 @@ fn update_folder(
|
|||
.get_color_unchecked(LapceTheme::EDITOR_FOREGROUND)
|
||||
.clone(),
|
||||
),
|
||||
None,
|
||||
));
|
||||
self.commands.push((
|
||||
self.menus.push((
|
||||
command_rect,
|
||||
Command::new(
|
||||
LAPCE_UI_COMMAND,
|
||||
|
@ -599,7 +633,12 @@ fn update_folder(
|
|||
}
|
||||
|
||||
fn icon_hit_test(&self, mouse_event: &MouseEvent) -> bool {
|
||||
for (rect, _) in self.commands.iter() {
|
||||
for (rect, _) in self.menus.iter() {
|
||||
if rect.contains(mouse_event.pos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (rect, _) in self.window_controls.iter() {
|
||||
if rect.contains(mouse_event.pos) {
|
||||
return true;
|
||||
}
|
||||
|
@ -607,9 +646,29 @@ fn icon_hit_test(&self, mouse_event: &MouseEvent) -> bool {
|
|||
false
|
||||
}
|
||||
|
||||
fn mouse_down(&self, ctx: &mut EventCtx, mouse_event: &MouseEvent) {
|
||||
for (rect, command) in self.commands.iter() {
|
||||
fn mouse_down(&mut self, ctx: &mut EventCtx, mouse_event: &MouseEvent) {
|
||||
for (rect, command) in self.menus.iter() {
|
||||
if rect.contains(mouse_event.pos) {
|
||||
self.holding_click_rect = Some(*rect);
|
||||
ctx.submit_command(command.clone());
|
||||
ctx.set_handled();
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (rect, _command) in self.window_controls.iter() {
|
||||
if rect.contains(mouse_event.pos) {
|
||||
self.holding_click_rect = Some(*rect);
|
||||
ctx.set_handled();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mouse_up(&self, ctx: &mut EventCtx, mouse_event: &MouseEvent) {
|
||||
for (rect, command) in self.window_controls.iter() {
|
||||
if rect.contains(mouse_event.pos)
|
||||
&& self.holding_click_rect.eq(&Some(*rect))
|
||||
{
|
||||
ctx.submit_command(command.clone());
|
||||
ctx.set_handled();
|
||||
return;
|
||||
|
@ -627,6 +686,10 @@ fn event(
|
|||
env: &Env,
|
||||
) {
|
||||
match event {
|
||||
Event::Internal(InternalEvent::MouseLeave) => {
|
||||
self.mouse_pos = Point::ZERO;
|
||||
ctx.request_paint();
|
||||
}
|
||||
Event::MouseMove(mouse_event) => {
|
||||
self.mouse_pos = mouse_event.pos;
|
||||
if self.icon_hit_test(mouse_event) {
|
||||
|
@ -651,7 +714,9 @@ fn event(
|
|||
}
|
||||
}
|
||||
Event::MouseDown(mouse_event) => {
|
||||
self.mouse_down(ctx, mouse_event);
|
||||
if mouse_event.button.is_left() {
|
||||
self.mouse_down(ctx, mouse_event);
|
||||
}
|
||||
}
|
||||
Event::MouseUp(mouse_event) => {
|
||||
if !data.multiple_tab
|
||||
|
@ -673,7 +738,14 @@ fn event(
|
|||
.with(WindowConfig::default().set_window_state(state))
|
||||
.to(Target::Window(data.window_id)),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if mouse_event.button.is_left() {
|
||||
self.mouse_up(ctx, mouse_event);
|
||||
}
|
||||
|
||||
self.holding_click_rect = None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -782,8 +854,25 @@ fn paint(&mut self, ctx: &mut PaintCtx, data: &LapceTabData, env: &Env) {
|
|||
ctx.fill(rect, color);
|
||||
}
|
||||
|
||||
for (svg, rect, color) in self.svgs.iter() {
|
||||
ctx.draw_svg(svg, *rect, color.as_ref());
|
||||
for (svg, rect, color, bg_color) in self.svgs.iter() {
|
||||
let hover_rect = rect.inflate(10.0, 10.0);
|
||||
if hover_rect.contains(self.mouse_pos)
|
||||
&& bg_color.is_some()
|
||||
&& (self.holding_click_rect.is_none()
|
||||
|| self.holding_click_rect.unwrap().contains(self.mouse_pos))
|
||||
{
|
||||
let bg_color = bg_color.to_owned().unwrap();
|
||||
ctx.fill(hover_rect, &bg_color);
|
||||
|
||||
// TODO: hacky way to detect close button, should be fixed once we have dark/light themes
|
||||
if bg_color.as_rgba8() == (210, 16, 33, 255) {
|
||||
ctx.draw_svg(svg, *rect, Some(&Color::WHITE));
|
||||
} else {
|
||||
ctx.draw_svg(svg, *rect, color.as_ref());
|
||||
}
|
||||
} else {
|
||||
ctx.draw_svg(svg, *rect, color.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
for (circle, color) in self.circles.iter() {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use druid::{
|
||||
kurbo::Line,
|
||||
piet::{PietText, PietTextLayout, Svg, Text, TextLayout, TextLayoutBuilder},
|
||||
widget::{LensWrap, WidgetExt},
|
||||
BoxConstraints, Command, Data, Env, Event, EventCtx, LayoutCtx, LifeCycle,
|
||||
LifeCycleCtx, PaintCtx, Point, Rect, Region, RenderContext, Size, Target,
|
||||
Widget, WidgetId, WidgetPod, WindowConfig, WindowId, WindowState,
|
||||
BoxConstraints, Command, Data, Env, Event, EventCtx, InternalEvent, LayoutCtx,
|
||||
LifeCycle, LifeCycleCtx, PaintCtx, Point, Rect, Region, RenderContext, Size,
|
||||
Target, Widget, WidgetId, WidgetPod, WindowConfig, WindowState,
|
||||
};
|
||||
use lapce_data::{
|
||||
command::{LapceUICommand, LAPCE_UI_COMMAND},
|
||||
|
@ -14,12 +13,10 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
svg::get_svg,
|
||||
tab::{LapceTab, LapceTabHeader},
|
||||
};
|
||||
use crate::tab::{LapceTab, LapceTabHeader};
|
||||
|
||||
pub struct LapceWindow {
|
||||
mouse_pos: Point,
|
||||
// pub title: WidgetPod<LapceWindowData, Box<dyn Widget<LapceWindowData>>>,
|
||||
pub tabs: Vec<WidgetPod<LapceWindowData, Box<dyn Widget<LapceWindowData>>>>,
|
||||
tab_headers: Vec<
|
||||
|
@ -31,6 +28,8 @@ pub struct LapceWindow {
|
|||
dragable_area: Region,
|
||||
tab_header_cmds: Vec<(Rect, Command)>,
|
||||
mouse_down_cmd: Option<(Rect, Command)>,
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
holding_click_rect: Option<Rect>,
|
||||
}
|
||||
|
||||
impl LapceWindow {
|
||||
|
@ -54,11 +53,14 @@ pub fn new(data: &mut LapceWindowData) -> Self {
|
|||
})
|
||||
.collect();
|
||||
Self {
|
||||
mouse_pos: Point::ZERO,
|
||||
dragable_area: Region::EMPTY,
|
||||
tabs,
|
||||
tab_headers,
|
||||
tab_header_cmds: Vec::new(),
|
||||
mouse_down_cmd: None,
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
holding_click_rect: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,12 +204,20 @@ fn event(
|
|||
Target::Widget(data.active_id),
|
||||
));
|
||||
}
|
||||
Event::Internal(InternalEvent::MouseLeave) => {
|
||||
self.mouse_pos = Point::ZERO;
|
||||
ctx.request_paint();
|
||||
}
|
||||
Event::MouseMove(mouse_event) => {
|
||||
ctx.clear_cursor();
|
||||
if data.tabs.len() > 1 && cfg!(not(target_os = "macos")) {
|
||||
self.mouse_pos = mouse_event.pos;
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
if data.tabs.len() > 1 && mouse_event.count < 2 {
|
||||
for (rect, _) in self.tab_header_cmds.iter() {
|
||||
if rect.contains(mouse_event.pos) {
|
||||
ctx.set_cursor(&druid::Cursor::Pointer);
|
||||
ctx.request_paint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -224,15 +234,16 @@ fn event(
|
|||
ctx.window().handle_titlebar(true);
|
||||
}
|
||||
}
|
||||
Event::MouseDown(mouse_event) => {
|
||||
Event::MouseDown(_mouse_event) => {
|
||||
self.mouse_down_cmd = None;
|
||||
if data.tabs.len() > 1
|
||||
&& mouse_event.count == 1
|
||||
&& cfg!(not(target_os = "macos"))
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
if (data.tabs.len() > 1 && _mouse_event.count == 1)
|
||||
|| data.config.lapce.custom_titlebar
|
||||
{
|
||||
for (rect, cmd) in self.tab_header_cmds.iter() {
|
||||
if rect.contains(mouse_event.pos) {
|
||||
if rect.contains(_mouse_event.pos) {
|
||||
self.mouse_down_cmd = Some((*rect, cmd.clone()));
|
||||
self.holding_click_rect = Some(*rect);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -258,15 +269,29 @@ fn event(
|
|||
.to(Target::Window(data.window_id)),
|
||||
)
|
||||
}
|
||||
if data.tabs.len() > 1
|
||||
&& mouse_event.count < 2
|
||||
&& cfg!(not(target_os = "macos"))
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
if (data.tabs.len() > 1 && mouse_event.count < 2)
|
||||
|| data.config.lapce.custom_titlebar
|
||||
{
|
||||
if let Some((rect, cmd)) = self.mouse_down_cmd.as_ref() {
|
||||
if rect.contains(mouse_event.pos) {
|
||||
ctx.submit_command(cmd.clone());
|
||||
}
|
||||
}
|
||||
|
||||
for (rect, cmd) in self.tab_header_cmds.iter() {
|
||||
if let Some(click_rect) = self.holding_click_rect {
|
||||
if rect.contains(mouse_event.pos)
|
||||
&& click_rect.contains(mouse_event.pos)
|
||||
{
|
||||
ctx.submit_command(cmd.clone());
|
||||
ctx.set_handled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.holding_click_rect = None;
|
||||
}
|
||||
}
|
||||
Event::Command(cmd) if cmd.is(LAPCE_UI_COMMAND) => {
|
||||
|
@ -471,6 +496,12 @@ fn update(
|
|||
if old_data.active != data.active {
|
||||
ctx.request_layout();
|
||||
}
|
||||
#[cfg(not(platform_os = "macos"))]
|
||||
if data.config.lapce.custom_titlebar != old_data.config.lapce.custom_titlebar
|
||||
{
|
||||
ctx.window()
|
||||
.show_titlebar(!data.config.lapce.custom_titlebar);
|
||||
}
|
||||
let old_tab = old_data.tabs.get(&old_data.active_id).unwrap();
|
||||
let tab = data.tabs.get(&data.active_id).unwrap();
|
||||
if old_tab.workspace != tab.workspace {
|
||||
|
@ -506,7 +537,9 @@ fn layout(
|
|||
#[cfg(not(target_os = "macos"))]
|
||||
let left_padding = 0.0;
|
||||
#[cfg(target_os = "macos")]
|
||||
let left_padding = if ctx.window().is_fullscreen() {
|
||||
let left_padding = if ctx.window().is_fullscreen()
|
||||
|| !data.config.lapce.custom_titlebar
|
||||
{
|
||||
0.0
|
||||
} else {
|
||||
78.0
|
||||
|
@ -664,18 +697,38 @@ fn paint(&mut self, ctx: &mut PaintCtx, data: &LapceWindowData, env: &Env) {
|
|||
);
|
||||
|
||||
self.tab_header_cmds.clear();
|
||||
if cfg!(not(target_os = "macos")) {
|
||||
let (cmds, svgs, text_layouts) = window_controls(
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
if data.config.lapce.custom_titlebar {
|
||||
let (cmds, svgs) = window_controls(
|
||||
data.window_id,
|
||||
&ctx.window().get_window_state(),
|
||||
ctx.text(),
|
||||
size.width - 36.0 * 3.0,
|
||||
36.0,
|
||||
&data.config,
|
||||
);
|
||||
self.tab_header_cmds = cmds;
|
||||
|
||||
for (svg, rect) in svgs {
|
||||
for (svg, rect, color) in svgs {
|
||||
let hover_rect = rect.inflate(10.0, 10.0);
|
||||
if hover_rect.contains(self.mouse_pos)
|
||||
&& (self.holding_click_rect.is_none()
|
||||
|| self
|
||||
.holding_click_rect
|
||||
.unwrap()
|
||||
.contains(self.mouse_pos))
|
||||
{
|
||||
ctx.fill(hover_rect, &color);
|
||||
ctx.stroke(
|
||||
Line::new(
|
||||
Point::new(hover_rect.x0, hover_rect.y1),
|
||||
Point::new(hover_rect.x1, hover_rect.y1),
|
||||
),
|
||||
data.config
|
||||
.get_color_unchecked(LapceTheme::LAPCE_BORDER),
|
||||
1.0,
|
||||
);
|
||||
}
|
||||
|
||||
ctx.draw_svg(
|
||||
&svg,
|
||||
rect,
|
||||
|
@ -685,28 +738,26 @@ fn paint(&mut self, ctx: &mut PaintCtx, data: &LapceWindowData, env: &Env) {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
for (text_layout, point) in text_layouts {
|
||||
ctx.draw_text(&text_layout, point);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub fn window_controls(
|
||||
window_id: WindowId,
|
||||
window_id: druid::WindowId,
|
||||
window_state: &WindowState,
|
||||
piet_text: &mut PietText,
|
||||
x: f64,
|
||||
width: f64,
|
||||
config: &Config,
|
||||
) -> (
|
||||
Vec<(Rect, Command)>,
|
||||
Vec<(Svg, Rect)>,
|
||||
Vec<(PietTextLayout, Point)>,
|
||||
Vec<(druid::piet::Svg, Rect, druid::Color)>,
|
||||
) {
|
||||
use crate::svg::get_svg;
|
||||
use druid::Color;
|
||||
|
||||
let mut commands = Vec::new();
|
||||
|
||||
let minimise_rect = Size::new(width, width)
|
||||
|
@ -748,72 +799,61 @@ pub fn window_controls(
|
|||
Command::new(druid::commands::QUIT_APP, (), Target::Global),
|
||||
));
|
||||
|
||||
let mut svgs = Vec::new();
|
||||
if cfg!(target_os = "linux")
|
||||
|| cfg!(target_os = "freebsd")
|
||||
|| cfg!(target_os = "openbsd")
|
||||
{
|
||||
let minimize_rect = Size::new(width, width)
|
||||
.to_rect()
|
||||
.with_origin(Point::new(x, 0.0))
|
||||
.inflate(-12.0, -12.0);
|
||||
svgs.push((get_svg("chrome-minimize.svg").unwrap(), minimize_rect));
|
||||
|
||||
let max_res_rect = Size::new(width, width)
|
||||
.to_rect()
|
||||
.with_origin(Point::new(x + width, 0.0))
|
||||
.inflate(-10.0, -10.0);
|
||||
let max_res_svg = if window_state == &WindowState::Restored {
|
||||
get_svg("chrome-maximize.svg").unwrap()
|
||||
let hover_color = {
|
||||
let (r, g, b, a) = config
|
||||
.get_color_unchecked(LapceTheme::PANEL_BACKGROUND)
|
||||
.to_owned()
|
||||
.as_rgba8();
|
||||
// TODO: hacky way to detect "lightness" of colour, should be fixed once we have dark/light themes
|
||||
if r < 128 || g < 128 || b < 128 {
|
||||
Color::rgba8(
|
||||
r.saturating_add(25),
|
||||
g.saturating_add(25),
|
||||
b.saturating_add(25),
|
||||
a,
|
||||
)
|
||||
} else {
|
||||
get_svg("chrome-restore.svg").unwrap()
|
||||
};
|
||||
svgs.push((max_res_svg, max_res_rect));
|
||||
|
||||
let close_rect = Size::new(width, width)
|
||||
.to_rect()
|
||||
.with_origin(Point::new(x + 2.0 * width, 0.0))
|
||||
.inflate(-10.0, -10.0);
|
||||
svgs.push((get_svg("chrome-close.svg").unwrap(), close_rect));
|
||||
}
|
||||
|
||||
let mut text_layouts = Vec::new();
|
||||
if cfg!(target_os = "windows") {
|
||||
let texts = vec![
|
||||
"\u{E949}",
|
||||
if window_state == &WindowState::Restored {
|
||||
"\u{E739}"
|
||||
} else {
|
||||
"\u{E923}"
|
||||
},
|
||||
"\u{E106}",
|
||||
];
|
||||
let font_size = 10.0;
|
||||
let font_family = "Segoe MDL2 Assets";
|
||||
for (i, text_layout) in texts
|
||||
.iter()
|
||||
.map(|text| {
|
||||
piet_text
|
||||
.new_text_layout(text.to_string())
|
||||
.font(piet_text.font_family(font_family).unwrap(), font_size)
|
||||
.text_color(
|
||||
config
|
||||
.get_color_unchecked(LapceTheme::EDITOR_FOREGROUND)
|
||||
.clone(),
|
||||
)
|
||||
.build()
|
||||
.unwrap()
|
||||
})
|
||||
.enumerate()
|
||||
{
|
||||
let text_size = text_layout.size();
|
||||
let point = Point::new(
|
||||
x + i as f64 * width + ((text_size.width + 5.0) / 2.0),
|
||||
(36.0 - text_size.height) / 2.0,
|
||||
);
|
||||
text_layouts.push((text_layout, point));
|
||||
Color::rgba8(
|
||||
r.saturating_sub(30),
|
||||
g.saturating_sub(30),
|
||||
b.saturating_sub(30),
|
||||
a,
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
(commands, svgs, text_layouts)
|
||||
let mut svgs = Vec::new();
|
||||
|
||||
let minimize_rect = Size::new(width, width)
|
||||
.to_rect()
|
||||
.with_origin(Point::new(x, 0.0))
|
||||
.inflate(-10.0, -10.0);
|
||||
svgs.push((
|
||||
get_svg("chrome-minimize.svg").unwrap(),
|
||||
minimize_rect,
|
||||
hover_color.clone(),
|
||||
));
|
||||
|
||||
let max_res_rect = Size::new(width, width)
|
||||
.to_rect()
|
||||
.with_origin(Point::new(x + width, 0.0))
|
||||
.inflate(-10.0, -10.0);
|
||||
let max_res_svg = if window_state == &WindowState::Restored {
|
||||
get_svg("chrome-maximize.svg").unwrap()
|
||||
} else {
|
||||
get_svg("chrome-restore.svg").unwrap()
|
||||
};
|
||||
svgs.push((max_res_svg, max_res_rect, hover_color));
|
||||
|
||||
let close_rect = Size::new(width, width)
|
||||
.to_rect()
|
||||
.with_origin(Point::new(x + 2.0 * width, 0.0))
|
||||
.inflate(-10.0, -10.0);
|
||||
svgs.push((
|
||||
get_svg("chrome-close.svg").unwrap(),
|
||||
close_rect,
|
||||
Color::rgb8(210, 16, 33),
|
||||
));
|
||||
|
||||
(commands, svgs)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue