panel layout

This commit is contained in:
Dongdong Zhou 2020-12-22 18:29:15 +00:00
parent 6a3953d7ad
commit 79c915a286
4 changed files with 303 additions and 18 deletions

View File

@ -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();

View File

@ -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<Arc<Mutex<dyn PanelProperty>>>,
window_id: WindowId,
tab_id: WidgetId,
pub panels: Vec<Arc<Mutex<Box<dyn PanelProperty>>>>,
pub shown: HashMap<PanelPosition, bool>,
}
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<dyn PanelProperty>));
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<PanelPosition, Option<(usize, Arc<Mutex<dyn PanelProperty>>)>> {
) -> HashMap<PanelPosition, Arc<Mutex<Box<dyn PanelProperty>>>> {
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<LapceUIState> 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) {}
}

View File

@ -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<Mutex<EditorSplitState>>,
pub container: Option<WidgetId>,
pub file_explorer: Arc<Mutex<FileExplorerState>>,
pub panel: Arc<Mutex<PanelState>>,
// pub plugins: Arc<Mutex<PluginCatalog>>,
// pub lsp: Arc<Mutex<LspCatalog>>,
pub ssh_session: Arc<Mutex<Option<SshSession>>>,
@ -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)),
};

View File

@ -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<LapceUIState, LapceSplit>,
status: WidgetPod<LapceUIState, LapceStatus>,
panels: HashMap<PanelPosition, WidgetPod<LapceUIState, LapcePanel>>,
}
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,
),
);