mirror of https://github.com/lapce/lapce.git
panel layout
This commit is contained in:
parent
6a3953d7ad
commit
79c915a286
|
@ -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();
|
||||
|
|
|
@ -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) {}
|
||||
}
|
||||
|
|
|
@ -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)),
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue