From 79c915a286cc6286518762b572e18741c24012d6 Mon Sep 17 00:00:00 2001 From: Dongdong Zhou Date: Tue, 22 Dec 2020 18:29:15 +0000 Subject: [PATCH] panel layout --- core/src/explorer.rs | 19 ++++- core/src/panel.rs | 113 +++++++++++++++++++++++--- core/src/state.rs | 3 + core/src/window.rs | 186 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 303 insertions(+), 18 deletions(-) diff --git a/core/src/explorer.rs b/core/src/explorer.rs index ef1a9361..0b864b63 100644 --- a/core/src/explorer.rs +++ b/core/src/explorer.rs @@ -12,8 +12,9 @@ use crate::{ command::LapceCommand, command::LapceUICommand, command::LAPCE_UI_COMMAND, editor::EditorSplitState, movement::LinePosition, movement::Movement, - palette::file_svg, palette::svg_tree_size, state::LapceFocus, - state::LapceUIState, state::LAPCE_APP_STATE, theme::LapceTheme, + palette::file_svg, palette::svg_tree_size, panel::PanelPosition, + panel::PanelProperty, state::LapceFocus, state::LapceUIState, + state::LAPCE_APP_STATE, theme::LapceTheme, }; pub const ICONS_DIR: Dir = include_dir!("../icons"); @@ -29,6 +30,20 @@ pub struct FileExplorerState { count: usize, } +impl PanelProperty for FileExplorerState { + fn position(&self) -> &PanelPosition { + &PanelPosition::LeftTop + } + + fn active(&self) -> usize { + 0 + } + + fn size(&self) -> (f64, f64) { + (300.0, 0.5) + } +} + impl FileExplorerState { pub fn new(window_id: WindowId, tab_id: WidgetId) -> FileExplorerState { let items = Vec::new(); diff --git a/core/src/panel.rs b/core/src/panel.rs index a464e9a5..43068bd9 100644 --- a/core/src/panel.rs +++ b/core/src/panel.rs @@ -1,7 +1,13 @@ use std::{collections::HashMap, sync::Arc}; +use druid::{ + BoxConstraints, Env, Event, EventCtx, LayoutCtx, LifeCycle, LifeCycleCtx, + PaintCtx, Size, Widget, WidgetId, WindowId, +}; use parking_lot::Mutex; +use crate::{explorer::FileExplorerState, state::LapceUIState}; + #[derive(Eq, PartialEq, Hash, Clone)] pub enum PanelPosition { LeftTop, @@ -12,23 +18,41 @@ pub enum PanelPosition { RightBottom, } -pub trait PanelProperty { +pub trait PanelProperty: Send { fn position(&self) -> &PanelPosition; fn active(&self) -> usize; - fn size(&self) -> (usize, f64); + fn size(&self) -> (f64, f64); } pub struct PanelState { - pub panels: Vec>>, + window_id: WindowId, + tab_id: WidgetId, + pub panels: Vec>>>, pub shown: HashMap, } impl PanelState { + pub fn new(window_id: WindowId, tab_id: WidgetId) -> Self { + let file_exploer = Arc::new(Mutex::new(Box::new(FileExplorerState::new( + window_id, tab_id, + )) + as Box)); + let mut panels = Vec::new(); + panels.push(file_exploer); + let mut shown = HashMap::new(); + shown.insert(PanelPosition::LeftTop, true); + Self { + window_id, + tab_id, + panels, + shown, + } + } pub fn is_shown(&self, position: &PanelPosition) -> bool { *self.shown.get(position).unwrap_or(&false) } - pub fn size(&self, position: &PanelPosition) -> Option<(usize, f64)> { + pub fn size(&self, position: &PanelPosition) -> Option<(f64, f64)> { let mut active_panel = None; let mut active = 0; for panel in self.panels.iter() { @@ -47,7 +71,7 @@ pub fn size(&self, position: &PanelPosition) -> Option<(usize, f64)> { pub fn shown_panels( &self, - ) -> HashMap>)>> { + ) -> HashMap>>> { let mut shown_panels = HashMap::new(); for (postion, shown) in self.shown.iter() { if *shown { @@ -57,19 +81,86 @@ pub fn shown_panels( for panel in self.panels.iter() { let local_panel = panel.clone(); - let panel = panel.lock(); - let position = panel.position(); - let active = panel.active(); + let (position, active) = { + let panel = panel.lock(); + let position = panel.position().clone(); + let active = panel.active(); + (position, active) + }; if let Some(p) = shown_panels.get_mut(&position) { if p.is_none() { - *p = Some((active, local_panel)); + *p = Some(local_panel); } else { - if active > p.as_ref().unwrap().0 { - *p = Some((active, local_panel)) + if active > p.as_ref().unwrap().lock().active() { + *p = Some(local_panel) } } } } shown_panels + .iter() + .filter_map(|(p, panel)| Some((p.clone(), panel.clone()?))) + .collect() } } + +pub struct LapcePanel { + window_id: WindowId, + tab_id: WidgetId, + position: PanelPosition, +} + +impl LapcePanel { + pub fn new( + window_id: WindowId, + tab_id: WidgetId, + position: PanelPosition, + ) -> Self { + Self { + window_id, + tab_id, + position, + } + } +} + +impl Widget for LapcePanel { + fn event( + &mut self, + ctx: &mut EventCtx, + event: &Event, + data: &mut LapceUIState, + env: &Env, + ) { + } + + fn lifecycle( + &mut self, + ctx: &mut LifeCycleCtx, + event: &LifeCycle, + data: &LapceUIState, + env: &Env, + ) { + } + + fn update( + &mut self, + ctx: &mut druid::UpdateCtx, + old_data: &LapceUIState, + data: &LapceUIState, + env: &druid::Env, + ) { + } + + fn layout( + &mut self, + ctx: &mut LayoutCtx, + bc: &BoxConstraints, + data: &LapceUIState, + env: &Env, + ) -> Size { + bc.max() + } + + fn paint(&mut self, ctx: &mut PaintCtx, data: &LapceUIState, env: &Env) {} +} diff --git a/core/src/state.rs b/core/src/state.rs index 53b0f3ed..b77a5930 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -15,6 +15,7 @@ lsp::LspCatalog, palette::PaletteState, palette::PaletteType, + panel::PanelState, plugin::PluginCatalog, proxy::start_proxy_process, proxy::LapceProxy, @@ -303,6 +304,7 @@ pub struct LapceTabState { pub editor_split: Arc>, pub container: Option, pub file_explorer: Arc>, + pub panel: Arc>, // pub plugins: Arc>, // pub lsp: Arc>, pub ssh_session: Arc>>, @@ -349,6 +351,7 @@ pub fn new(window_id: WindowId) -> LapceTabState { // window_id.clone(), // tab_id.clone(), // ))), + panel: Arc::new(Mutex::new(PanelState::new(window_id, tab_id))), ssh_session: Arc::new(Mutex::new(None)), proxy: Arc::new(Mutex::new(None)), }; diff --git a/core/src/window.rs b/core/src/window.rs index c774c7c8..ade6b4fe 100644 --- a/core/src/window.rs +++ b/core/src/window.rs @@ -4,6 +4,7 @@ container::LapceContainer, editor::EditorUIState, explorer::FileExplorer, + panel::{LapcePanel, PanelPosition, PanelProperty}, split::LapceSplit, state::{ LapceTabState, LapceUIState, LapceWindowState, LapceWorkspaceType, @@ -25,6 +26,7 @@ pub struct LapceTab { tab_id: WidgetId, main_split: WidgetPod, status: WidgetPod, + panels: HashMap>, } impl LapceTab { @@ -45,11 +47,61 @@ pub fn new(window_id: WindowId, tab_id: WidgetId) -> LapceTab { ) .with_flex_child(container, 1.0); let status = LapceStatus::new(window_id.clone(), tab_id.clone()); + let mut panels = HashMap::new(); + panels.insert( + PanelPosition::LeftTop, + WidgetPod::new(LapcePanel::new( + window_id, + tab_id, + PanelPosition::LeftTop, + )), + ); + panels.insert( + PanelPosition::LeftBottom, + WidgetPod::new(LapcePanel::new( + window_id, + tab_id, + PanelPosition::LeftBottom, + )), + ); + panels.insert( + PanelPosition::BottomLeft, + WidgetPod::new(LapcePanel::new( + window_id, + tab_id, + PanelPosition::BottomLeft, + )), + ); + panels.insert( + PanelPosition::BottomRight, + WidgetPod::new(LapcePanel::new( + window_id, + tab_id, + PanelPosition::BottomRight, + )), + ); + panels.insert( + PanelPosition::RightTop, + WidgetPod::new(LapcePanel::new( + window_id, + tab_id, + PanelPosition::RightTop, + )), + ); + panels.insert( + PanelPosition::RightBottom, + WidgetPod::new(LapcePanel::new( + window_id, + tab_id, + PanelPosition::RightBottom, + )), + ); LapceTab { window_id, tab_id, main_split: WidgetPod::new(main_split), status: WidgetPod::new(status), + panels, } } } @@ -147,18 +199,142 @@ fn layout( let self_size = bc.max(); let status_size = self.status.layout(ctx, bc, data, env); - let main_split_size = - Size::new(self_size.width, self_size.height - status_size.height); + let state = LAPCE_APP_STATE.get_tab_state(&self.window_id, &self.tab_id); + let panel_state = state.panel.lock(); + let shown_panels = panel_state.shown_panels(); + let mut left = None; + let mut right = None; + let mut bottom = None; + for (p, panel) in shown_panels.iter() { + match p { + PanelPosition::LeftTop => { + let (size, ratio) = panel.lock().size(); + if left.is_none() { + left = Some(size); + } else { + if size > left.unwrap() { + left = Some(size); + } + } + } + PanelPosition::LeftBottom => { + let (size, ratio) = panel.lock().size(); + if left.is_none() { + left = Some(size); + } else { + if size > left.unwrap() { + left = Some(size); + } + } + } + PanelPosition::RightTop => { + let (size, ratio) = panel.lock().size(); + if right.is_none() { + right = Some(size); + } else { + if size > right.unwrap() { + right = Some(size); + } + } + } + PanelPosition::RightBottom => { + let (size, ratio) = panel.lock().size(); + if right.is_none() { + right = Some(size); + } else { + if size > right.unwrap() { + right = Some(size); + } + } + } + PanelPosition::BottomLeft => { + let (size, ratio) = panel.lock().size(); + if bottom.is_none() { + right = Some(size); + } else { + if size > bottom.unwrap() { + bottom = Some(size); + } + } + } + PanelPosition::BottomRight => { + let (size, ratio) = panel.lock().size(); + if bottom.is_none() { + right = Some(size); + } else { + if size > bottom.unwrap() { + bottom = Some(size); + } + } + } + } + } + // for panel in + + let mut main_split_width = self_size.width; + if let Some(left) = left { + main_split_width -= left; + self.panels + .get_mut(&PanelPosition::LeftTop) + .unwrap() + .set_layout_rect( + ctx, + data, + env, + Size::new(left, self_size.height - status_size.height).to_rect(), + ); + } + if let Some(right) = right { + main_split_width -= right; + self.panels + .get_mut(&PanelPosition::RightTop) + .unwrap() + .set_layout_rect( + ctx, + data, + env, + Size::new(right, self_size.height - status_size.height) + .to_rect() + .with_origin(Point::new(self_size.width - right, 0.0)), + ); + } + + let mut main_split_origin = Point::ZERO; + if let Some(left) = left { + main_split_origin = Point::new(left, 0.0); + } + + let mut main_split_height = self_size.height - status_size.height; + if let Some(bottom) = bottom { + main_split_height -= bottom; + self.panels + .get_mut(&PanelPosition::RightTop) + .unwrap() + .set_layout_rect( + ctx, + data, + env, + Size::new(main_split_width, bottom) + .to_rect() + .with_origin(main_split_origin + (0.0, main_split_height)), + ); + } + + let main_split_size = Size::new(main_split_width, main_split_height); let main_split_bc = BoxConstraints::new(Size::ZERO, main_split_size); self.main_split.layout(ctx, &main_split_bc, data, env); - self.main_split - .set_layout_rect(ctx, data, env, main_split_size.to_rect()); + self.main_split.set_layout_rect( + ctx, + data, + env, + main_split_size.to_rect().with_origin(main_split_origin), + ); self.status.set_layout_rect( ctx, data, env, Rect::from_origin_size( - Point::new(0.0, main_split_size.height), + Point::new(0.0, self_size.height - status_size.height), status_size, ), );