diff --git a/lapce-data/src/data.rs b/lapce-data/src/data.rs index 0d19add0..791aab6b 100644 --- a/lapce-data/src/data.rs +++ b/lapce-data/src/data.rs @@ -1015,10 +1015,9 @@ pub fn run_workbench_command( } LapceWorkbenchCommand::OpenLogFile => { if let Some(path) = Config::log_file() { - let editor_view_id = self.main_split.active.clone(); self.main_split.jump_to_location( ctx, - *editor_view_id, + None, EditorLocationNew { path, position: None, @@ -1030,20 +1029,20 @@ pub fn run_workbench_command( } } LapceWorkbenchCommand::OpenSettings => { - let settings = Arc::make_mut(&mut self.settings); - settings.shown = true; - ctx.submit_command(Command::new( - LAPCE_UI_COMMAND, - LapceUICommand::ShowSettings, - Target::Widget(self.settings.panel_widget_id), - )); + self.main_split.open_settings(ctx); + // let settings = Arc::make_mut(&mut self.settings); + // settings.shown = true; + // ctx.submit_command(Command::new( + // LAPCE_UI_COMMAND, + // LapceUICommand::ShowSettings, + // Target::Widget(self.settings.panel_widget_id), + // )); } LapceWorkbenchCommand::OpenSettingsFile => { if let Some(path) = Config::settings_file() { - let editor_view_id = self.main_split.active.clone(); self.main_split.jump_to_location( ctx, - *editor_view_id, + None, EditorLocationNew { path, position: None, @@ -1055,8 +1054,6 @@ pub fn run_workbench_command( } } LapceWorkbenchCommand::OpenKeyboardShortcuts => { - let settings = Arc::make_mut(&mut self.settings); - settings.shown = true; ctx.submit_command(Command::new( LAPCE_UI_COMMAND, LapceUICommand::ShowKeybindings, @@ -1065,10 +1062,9 @@ pub fn run_workbench_command( } LapceWorkbenchCommand::OpenKeyboardShortcutsFile => { if let Some(path) = KeyPressData::file() { - let editor_view_id = self.main_split.active.clone(); self.main_split.jump_to_location( ctx, - *editor_view_id, + None, EditorLocationNew { path, position: None, @@ -1176,7 +1172,7 @@ pub fn run_workbench_command( } } LapceWorkbenchCommand::FocusEditor => { - if let Some(active) = *self.main_split.active { + if let Some(active) = *self.main_split.active_tab { ctx.submit_command(Command::new( LAPCE_UI_COMMAND, LapceUICommand::Focus, @@ -1443,7 +1439,7 @@ fn hide_panel(&mut self, ctx: &mut EventCtx, kind: PanelKind) { break; } } - if let Some(active) = *self.main_split.active { + if let Some(active) = *self.main_split.active_tab { ctx.submit_command(Command::new( LAPCE_UI_COMMAND, LapceUICommand::Focus, @@ -1977,6 +1973,170 @@ pub fn get_active_tab_mut( ) } + fn new_editor_tab( + &mut self, + ctx: &mut EventCtx, + split_id: WidgetId, + ) -> WidgetId { + let split = self.splits.get_mut(&split_id).unwrap(); + let split = Arc::make_mut(split); + + let editor_tab_id = WidgetId::next(); + let editor_tab = LapceEditorTabData { + widget_id: editor_tab_id, + split: *self.split_id, + active: 0, + children: vec![], + layout_rect: Rc::new(RefCell::new(Rect::ZERO)), + content_is_hot: Rc::new(RefCell::new(false)), + }; + ctx.submit_command(Command::new( + LAPCE_UI_COMMAND, + LapceUICommand::SplitAdd( + 0, + SplitContent::EditorTab(editor_tab.widget_id), + true, + ), + Target::Widget(*self.split_id), + )); + self.active_tab = Arc::new(Some(editor_tab.widget_id)); + split + .children + .push(SplitContent::EditorTab(editor_tab.widget_id)); + self.editor_tabs.insert(editor_tab_id, Arc::new(editor_tab)); + editor_tab_id + } + + fn editor_tab_new_settings( + &mut self, + ctx: &mut EventCtx, + editor_tab_id: WidgetId, + ) { + let editor_tab = self.editor_tabs.get_mut(&editor_tab_id).unwrap(); + let editor_tab = Arc::make_mut(editor_tab); + let child = EditorTabChild::Settings(WidgetId::next(), editor_tab_id); + editor_tab.children.push(child.clone()); + ctx.submit_command(Command::new( + LAPCE_UI_COMMAND, + LapceUICommand::EditorTabAdd(0, child), + Target::Widget(editor_tab.widget_id), + )); + } + + fn editor_tab_new_editor( + &mut self, + ctx: &mut EventCtx, + editor_tab_id: WidgetId, + config: &Config, + ) -> WidgetId { + let editor_tab = self.editor_tabs.get_mut(&editor_tab_id).unwrap(); + let editor_tab = Arc::make_mut(editor_tab); + let editor = Arc::new(LapceEditorData::new( + None, + None, + Some(editor_tab.widget_id), + BufferContent::Local(LocalBufferKind::Empty), + config, + )); + editor_tab.children.push(EditorTabChild::Editor( + editor.view_id, + editor.editor_id, + editor.find_view_id, + )); + ctx.submit_command(Command::new( + LAPCE_UI_COMMAND, + LapceUICommand::EditorTabAdd( + 0, + EditorTabChild::Editor( + editor.view_id, + editor.editor_id, + editor.find_view_id, + ), + ), + Target::Widget(editor_tab.widget_id), + )); + self.insert_editor(editor.clone(), config); + editor.view_id + } + + fn get_editor_from_tab( + &mut self, + ctx: &mut EventCtx, + editor_tab_id: WidgetId, + path: Option, + _scratch: bool, + config: &Config, + ) -> &mut LapceEditorData { + let editor_tab = + Arc::make_mut(self.editor_tabs.get_mut(&editor_tab_id).unwrap()); + + if !config.editor.show_tab { + if let EditorTabChild::Editor(id, _, _) = editor_tab.active_child() { + return Arc::make_mut(self.editors.get_mut(id).unwrap()); + } + } + + let mut editor_size = Size::ZERO; + for (i, child) in editor_tab.children.iter().enumerate() { + if let EditorTabChild::Editor(id, _, _) = child { + let editor = self.editors.get(id).unwrap(); + let current_size = *editor.size.borrow(); + if current_size.height > 0.0 { + editor_size = current_size; + } + if let Some(path) = path.as_ref() { + if editor.content == BufferContent::File(path.clone()) { + editor_tab.active = i; + ctx.submit_command(Command::new( + LAPCE_UI_COMMAND, + LapceUICommand::Focus, + Target::Widget(*id), + )); + return Arc::make_mut(self.editors.get_mut(id).unwrap()); + } + } + } + } + + let new_editor = Arc::new(LapceEditorData::new( + None, + None, + Some(editor_tab.widget_id), + BufferContent::Local(LocalBufferKind::Empty), + config, + )); + *new_editor.size.borrow_mut() = editor_size; + editor_tab.children.insert( + editor_tab.active + 1, + EditorTabChild::Editor( + new_editor.view_id, + new_editor.editor_id, + new_editor.find_view_id, + ), + ); + ctx.submit_command(Command::new( + LAPCE_UI_COMMAND, + LapceUICommand::EditorTabAdd( + editor_tab.active + 1, + EditorTabChild::Editor( + new_editor.view_id, + new_editor.editor_id, + new_editor.find_view_id, + ), + ), + Target::Widget(editor_tab.widget_id), + )); + editor_tab.active += 1; + ctx.submit_command(Command::new( + LAPCE_UI_COMMAND, + LapceUICommand::Focus, + Target::Widget(new_editor.view_id), + )); + self.insert_editor(new_editor.clone(), config); + + return Arc::make_mut(self.editors.get_mut(&new_editor.view_id).unwrap()); + } + fn get_editor_or_new( &mut self, ctx: &mut EventCtx, @@ -1989,159 +2149,13 @@ fn get_editor_or_new( Some(view_id) => Arc::make_mut(self.editors.get_mut(&view_id).unwrap()), None => match *self.active_tab { Some(active) => { - let editor_tab = - Arc::make_mut(self.editor_tabs.get_mut(&active).unwrap()); - match &editor_tab.children[editor_tab.active] { - EditorTabChild::Editor(id, _, _) => { - if config.editor.show_tab { - if path.is_some() || scratch { - let mut editor_size = Size::ZERO; - for (i, child) in - editor_tab.children.iter().enumerate() - { - match child { - EditorTabChild::Editor(id, _, _) => { - let editor = - self.editors.get(id).unwrap(); - let current_size = - *editor.size.borrow(); - if current_size.height > 0.0 { - editor_size = current_size; - } - if let Some(path) = path.as_ref() { - if editor.content - == BufferContent::File( - path.clone(), - ) - { - editor_tab.active = i; - ctx.submit_command( - Command::new( - LAPCE_UI_COMMAND, - LapceUICommand::Focus, - Target::Widget(*id), - ), - ); - return Arc::make_mut( - self.editors - .get_mut(id) - .unwrap(), - ); - } - } - } - } - } - - let new_editor = Arc::new(LapceEditorData::new( - None, - None, - Some(editor_tab.widget_id), - BufferContent::Local(LocalBufferKind::Empty), - config, - )); - *new_editor.size.borrow_mut() = editor_size; - editor_tab.children.insert( - editor_tab.active + 1, - EditorTabChild::Editor( - new_editor.view_id, - new_editor.editor_id, - new_editor.find_view_id, - ), - ); - ctx.submit_command(Command::new( - LAPCE_UI_COMMAND, - LapceUICommand::EditorTabAdd( - editor_tab.active + 1, - EditorTabChild::Editor( - new_editor.view_id, - new_editor.editor_id, - new_editor.find_view_id, - ), - ), - Target::Widget(editor_tab.widget_id), - )); - editor_tab.active += 1; - ctx.submit_command(Command::new( - LAPCE_UI_COMMAND, - LapceUICommand::Focus, - Target::Widget(new_editor.view_id), - )); - self.insert_editor(new_editor.clone(), config); - - return Arc::make_mut( - self.editors - .get_mut(&new_editor.view_id) - .unwrap(), - ); - } - Arc::make_mut(self.editors.get_mut(id).unwrap()) - } else { - Arc::make_mut(self.editors.get_mut(id).unwrap()) - } - } - } + self.get_editor_from_tab(ctx, active, path, scratch, config) } None => { - let split = self.splits.get_mut(&self.split_id).unwrap(); - let split = Arc::make_mut(split); - - let mut editor_tab = LapceEditorTabData { - widget_id: WidgetId::next(), - split: *self.split_id, - active: 0, - children: vec![], - layout_rect: Rc::new(RefCell::new(Rect::ZERO)), - content_is_hot: Rc::new(RefCell::new(false)), - }; - - let editor = Arc::new(LapceEditorData::new( - None, - None, - Some(editor_tab.widget_id), - BufferContent::Local(LocalBufferKind::Empty), - config, - )); - - editor_tab.children.push(EditorTabChild::Editor( - editor.view_id, - editor.editor_id, - editor.find_view_id, - )); - - self.active = Arc::new(Some(editor.view_id)); - self.active_tab = Arc::new(Some(editor_tab.widget_id)); - - ctx.submit_command(Command::new( - LAPCE_UI_COMMAND, - LapceUICommand::EditorTabAdd( - 0, - EditorTabChild::Editor( - editor.view_id, - editor.editor_id, - editor.find_view_id, - ), - ), - Target::Widget(editor_tab.widget_id), - )); - ctx.submit_command(Command::new( - LAPCE_UI_COMMAND, - LapceUICommand::SplitAdd( - 0, - SplitContent::EditorTab(editor_tab.widget_id), - true, - ), - Target::Widget(*self.split_id), - )); - split - .children - .push(SplitContent::EditorTab(editor_tab.widget_id)); - - self.insert_editor(editor.clone(), config); - self.editor_tabs - .insert(editor_tab.widget_id, Arc::new(editor_tab)); - - Arc::make_mut(self.editors.get_mut(&editor.view_id).unwrap()) + let editor_tab_id = self.new_editor_tab(ctx, *self.split_id); + let view_id = + self.editor_tab_new_editor(ctx, editor_tab_id, config); + Arc::make_mut(self.editors.get_mut(&view_id).unwrap()) } }, } @@ -2167,6 +2181,37 @@ pub fn jump_to_position( } } + pub fn open_settings(&mut self, ctx: &mut EventCtx) { + match *self.active_tab { + Some(active) => { + let editor_tab = + Arc::make_mut(self.editor_tabs.get_mut(&active).unwrap()); + for (i, child) in editor_tab.children.iter().enumerate() { + if let EditorTabChild::Settings(_, _) = child { + editor_tab.active = i; + return; + } + } + + let child = + EditorTabChild::Settings(WidgetId::next(), editor_tab.widget_id); + editor_tab + .children + .insert(editor_tab.active + 1, child.clone()); + ctx.submit_command(Command::new( + LAPCE_UI_COMMAND, + LapceUICommand::EditorTabAdd(editor_tab.active + 1, child), + Target::Widget(editor_tab.widget_id), + )); + editor_tab.active += 1; + } + None => { + let editor_tab_id = self.new_editor_tab(ctx, *self.split_id); + self.editor_tab_new_settings(ctx, editor_tab_id); + } + } + } + pub fn jump_to_location( &mut self, ctx: &mut EventCtx, @@ -2611,6 +2656,26 @@ pub fn save_as( } } + pub fn settings_close( + &mut self, + ctx: &mut EventCtx, + widget_id: WidgetId, + editor_tab_id: WidgetId, + ) { + let editor_tab = self.editor_tabs.get(&editor_tab_id).unwrap(); + let mut index = 0; + for (i, child) in editor_tab.children.iter().enumerate() { + if child.widget_id() == widget_id { + index = i; + } + } + ctx.submit_command(Command::new( + LAPCE_UI_COMMAND, + LapceUICommand::EditorTabRemove(index, true, true), + Target::Widget(editor_tab_id), + )); + } + pub fn editor_close( &mut self, ctx: &mut EventCtx, @@ -2852,6 +2917,48 @@ pub fn split_move( } } + pub fn split_settings( + &mut self, + ctx: &mut EventCtx, + editor_tab_id: WidgetId, + direction: SplitDirection, + ) { + let editor_tab = self.editor_tabs.get(&editor_tab_id).unwrap(); + let split_id = editor_tab.split; + + let new_editor_tab_id = WidgetId::next(); + let mut new_editor_tab = LapceEditorTabData { + widget_id: new_editor_tab_id, + split: split_id, + active: 0, + children: vec![EditorTabChild::Settings( + WidgetId::next(), + new_editor_tab_id, + )], + layout_rect: Rc::new(RefCell::new(Rect::ZERO)), + content_is_hot: Rc::new(RefCell::new(false)), + }; + + let new_split_id = self.split( + ctx, + split_id, + SplitContent::EditorTab(editor_tab_id), + SplitContent::EditorTab(new_editor_tab.widget_id), + direction, + false, + false, + ); + + new_editor_tab.split = new_split_id; + if split_id != new_split_id { + let editor_tab = self.editor_tabs.get_mut(&editor_tab_id).unwrap(); + let editor_tab = Arc::make_mut(editor_tab); + editor_tab.split = new_split_id; + } + self.editor_tabs + .insert(new_editor_tab.widget_id, Arc::new(new_editor_tab)); + } + pub fn split_editor( &mut self, ctx: &mut EventCtx, @@ -2916,14 +3023,14 @@ pub enum InlineFindDirection { #[derive(Clone, Debug, PartialEq)] pub enum EditorTabChild { Editor(WidgetId, WidgetId, Option<(WidgetId, WidgetId)>), - // Settings(WidgetId), + Settings(WidgetId, WidgetId), } impl EditorTabChild { pub fn widget_id(&self) -> WidgetId { match &self { EditorTabChild::Editor(widget_id, _, _) => *widget_id, - // EditorTabChild::Settings(_) => todo!(), + EditorTabChild::Settings(widget_id, _) => *widget_id, } } @@ -2932,17 +3039,25 @@ pub fn child_info(&self, data: &LapceTabData) -> EditorTabChildInfo { EditorTabChild::Editor(view_id, _, _) => { let editor_data = data.main_split.editors.get(view_id).unwrap(); EditorTabChildInfo::Editor(editor_data.editor_info(data)) - } // EditorTabChild::Settings(_) => todo!(), + } + EditorTabChild::Settings(_, _) => EditorTabChildInfo::Settings, } } - pub fn set_editor_tab(&self, data: &mut LapceTabData, editor_tab_id: WidgetId) { - match &self { + pub fn set_editor_tab( + &mut self, + data: &mut LapceTabData, + editor_tab_id: WidgetId, + ) { + match self { EditorTabChild::Editor(view_id, _, _) => { let editor_data = data.main_split.editors.get_mut(view_id).unwrap(); let editor_data = Arc::make_mut(editor_data); editor_data.tab_id = Some(editor_tab_id); - } // EditorTabChild::Settings(_) => todo!(), + } + EditorTabChild::Settings(_, current_editor_tab_id) => { + *current_editor_tab_id = editor_tab_id; + } } } } @@ -2970,6 +3085,10 @@ pub fn tab_info(&self, data: &LapceTabData) -> EditorTabInfo { }; info } + + pub fn active_child(&self) -> &EditorTabChild { + &self.children[self.active] + } } #[derive(Clone, Debug)] diff --git a/lapce-data/src/db.rs b/lapce-data/src/db.rs index 7228e40d..1f981331 100644 --- a/lapce-data/src/db.rs +++ b/lapce-data/src/db.rs @@ -135,6 +135,7 @@ pub fn to_data( #[derive(Clone, Serialize, Deserialize)] pub enum EditorTabChildInfo { Editor(EditorInfo), + Settings, } impl EditorTabChildInfo { @@ -163,6 +164,9 @@ pub fn to_data( editor_data.find_view_id, ) } + EditorTabChildInfo::Settings => { + EditorTabChild::Settings(WidgetId::next(), editor_tab_id) + } } } } diff --git a/lapce-data/src/palette.rs b/lapce-data/src/palette.rs index 09e23637..94cbfe62 100644 --- a/lapce-data/src/palette.rs +++ b/lapce-data/src/palette.rs @@ -447,7 +447,7 @@ pub fn cancel(&mut self, ctx: &mut EventCtx) { palette.palette_type = PaletteType::File; palette.items.clear(); palette.filtered_items.clear(); - if let Some(active) = *self.main_split.active { + if let Some(active) = *self.main_split.active_tab { ctx.submit_command(Command::new( LAPCE_UI_COMMAND, LapceUICommand::Focus, diff --git a/lapce-data/src/settings.rs b/lapce-data/src/settings.rs index 6b5af937..cd2ea377 100644 --- a/lapce-data/src/settings.rs +++ b/lapce-data/src/settings.rs @@ -6,7 +6,9 @@ use crate::{ command::{CommandExecuted, CommandKind, LapceUICommand, LAPCE_UI_COMMAND}, + data::LapceMainSplitData, keypress::KeyPressFocus, + split::SplitDirection, }; pub enum LapceSettingsKind { @@ -16,7 +18,6 @@ pub enum LapceSettingsKind { #[derive(Clone)] pub struct LapceSettingsPanelData { - pub shown: bool, pub panel_widget_id: WidgetId, pub keymap_widget_id: WidgetId, @@ -67,7 +68,6 @@ fn run_command( impl LapceSettingsPanelData { pub fn new() -> Self { Self { - shown: false, panel_widget_id: WidgetId::next(), keymap_widget_id: WidgetId::next(), keymap_view_id: WidgetId::next(), @@ -85,6 +85,56 @@ fn default() -> Self { } } +#[derive(Clone)] +pub struct LapceSettingsFocusData { + pub widget_id: WidgetId, + pub editor_tab_id: WidgetId, + pub main_split: LapceMainSplitData, +} + +impl KeyPressFocus for LapceSettingsFocusData { + fn get_mode(&self) -> Mode { + Mode::Insert + } + + fn check_condition(&self, _condition: &str) -> bool { + false + } + + fn run_command( + &mut self, + ctx: &mut EventCtx, + command: &crate::command::LapceCommand, + _count: Option, + _mods: Modifiers, + _env: &Env, + ) -> CommandExecuted { + match &command.kind { + CommandKind::Focus(cmd) => match cmd { + FocusCommand::SplitVertical => { + self.main_split.split_settings( + ctx, + self.editor_tab_id, + SplitDirection::Vertical, + ); + } + FocusCommand::SplitClose => { + self.main_split.settings_close( + ctx, + self.widget_id, + self.editor_tab_id, + ); + } + _ => return CommandExecuted::No, + }, + _ => return CommandExecuted::No, + } + CommandExecuted::Yes + } + + fn receive_char(&mut self, _ctx: &mut EventCtx, _c: &str) {} +} + pub enum SettingsValue { Bool(bool), } diff --git a/lapce-ui/src/editor/tab.rs b/lapce-ui/src/editor/tab.rs index 392fa8cc..c41c6819 100644 --- a/lapce-ui/src/editor/tab.rs +++ b/lapce-ui/src/editor/tab.rs @@ -56,6 +56,7 @@ fn clear_child(&mut self, ctx: &mut EventCtx, data: &mut LapceTabData) { EditorTabChild::Editor(view_id, _, _) => { data.main_split.editors.remove(view_id); } + EditorTabChild::Settings(_, _) => {} } } ctx.submit_command(Command::new( @@ -124,6 +125,7 @@ pub fn remove_child( EditorTabChild::Editor(view_id, _, _) => { data.main_split.editors.remove(&view_id); } + EditorTabChild::Settings(_, _) => {} } } } @@ -193,6 +195,7 @@ fn mouse_up( layout_rect: Rc::new(RefCell::new(Rect::ZERO)), content_is_hot: Rc::new(RefCell::new(false)), }; + let mut child = child.clone(); child.set_editor_tab(data, new_editor_tab.widget_id); let new_split_id = data.main_split.split( @@ -240,6 +243,7 @@ fn mouse_up( if from_id == &self.widget_id { return; } + let mut child = child.clone(); child.set_editor_tab(data, self.widget_id); let editor_tab = data .main_split @@ -307,7 +311,7 @@ fn event( LapceUICommand::EditorTabAdd(index, content) => { self.children.insert( *index, - WidgetPod::new(editor_tab_child_widget(content)), + WidgetPod::new(editor_tab_child_widget(content, data)), ); ctx.children_changed(); return; @@ -354,29 +358,33 @@ fn event( data.main_split.editor_tabs.get(&self.widget_id) { let active = &tab.children[tab.active]; - let EditorTabChildInfo::Editor(info) = - active.child_info(data); - - if info.content - == BufferContent::Local(LocalBufferKind::Empty) - { - // File has not yet been loaded, most likely. - return; - } - - ctx.submit_command(Command::new( - LAPCE_UI_COMMAND, - LapceUICommand::ActiveFileChanged { - path: if let BufferContent::File(path) = - info.content + match active.child_info(data) { + EditorTabChildInfo::Editor(info) => { + if info.content + == BufferContent::Local( + LocalBufferKind::Empty, + ) { - Some(path) - } else { - None - }, - }, - Target::Widget(data.file_explorer.widget_id), - )); + // File has not yet been loaded, most likely. + return; + } + + ctx.submit_command(Command::new( + LAPCE_UI_COMMAND, + LapceUICommand::ActiveFileChanged { + path: if let BufferContent::File(path) = + info.content + { + Some(path) + } else { + None + }, + }, + Target::Widget(data.file_explorer.widget_id), + )); + } + EditorTabChildInfo::Settings => {} + } return; } } @@ -601,6 +609,7 @@ fn paint( let doc = data.main_split.editor_doc(*editor_id); doc.buffer().is_pristine() } + EditorTabChild::Settings(_, _) => true, }; if !is_pristine { diff --git a/lapce-ui/src/editor/tab_header_content.rs b/lapce-ui/src/editor/tab_header_content.rs index 01254dba..3ef91249 100644 --- a/lapce-ui/src/editor/tab_header_content.rs +++ b/lapce-ui/src/editor/tab_header_content.rs @@ -218,6 +218,7 @@ fn handle_drag( return; } + let mut child = child.clone(); child.set_editor_tab(data, editor_tab.widget_id); let editor_tab = data .main_split @@ -363,6 +364,9 @@ fn layout( text = editor.content.file_name().to_string(); } } + EditorTabChild::Settings(_, _) => { + text = "Settings".to_string(); + } } let text_layout = ctx .text() diff --git a/lapce-ui/src/editor/view.rs b/lapce-ui/src/editor/view.rs index 8d921d1e..bf51aae0 100644 --- a/lapce-ui/src/editor/view.rs +++ b/lapce-ui/src/editor/view.rs @@ -26,6 +26,7 @@ container::LapceEditorContainer, header::LapceEditorHeader, LapceEditor, }, find::FindBox, + settings::LapceSettingsPanel, }; pub struct LapceEditorView { @@ -37,11 +38,15 @@ pub struct LapceEditorView { pub fn editor_tab_child_widget( child: &EditorTabChild, + data: &LapceTabData, ) -> Box> { match child { EditorTabChild::Editor(view_id, editor_id, find_view_id) => { LapceEditorView::new(*view_id, *editor_id, *find_view_id).boxed() } + EditorTabChild::Settings(widget_id, editor_tab_id) => { + LapceSettingsPanel::new(data, *widget_id, *editor_tab_id).boxed() + } } } diff --git a/lapce-ui/src/settings.rs b/lapce-ui/src/settings.rs index 9e339a4a..e01e5172 100644 --- a/lapce-ui/src/settings.rs +++ b/lapce-ui/src/settings.rs @@ -7,8 +7,8 @@ }, BoxConstraints, Command, Env, Event, EventCtx, ExtEventSink, FontWeight, LayoutCtx, LifeCycle, LifeCycleCtx, Modifiers, MouseEvent, PaintCtx, Point, - Rect, RenderContext, Size, Target, TimerToken, UpdateCtx, Vec2, Widget, - WidgetExt, WidgetId, WidgetPod, + Rect, RenderContext, Size, Target, TimerToken, UpdateCtx, Widget, WidgetExt, + WidgetId, WidgetPod, }; use inflector::Inflector; use lapce_core::{ @@ -24,7 +24,7 @@ data::{LapceEditorData, LapceTabData}, document::{BufferContent, Document}, keypress::KeyPressFocus, - proxy::VERSION, + settings::LapceSettingsFocusData, }; use xi_rope::Rope; @@ -33,7 +33,6 @@ keymap::LapceKeymap, scroll::{LapcePadding, LapceScrollNew}, split::LapceSplitNew, - svg::get_svg, }; enum LapceSettingsKind { @@ -43,54 +42,22 @@ enum LapceSettingsKind { Terminal, } -#[derive(Clone)] -pub struct LapceSettingsPanelData { - pub shown: bool, - pub panel_widget_id: WidgetId, - - pub keymap_widget_id: WidgetId, - pub keymap_view_id: WidgetId, - pub keymap_split_id: WidgetId, - - pub settings_widget_id: WidgetId, - pub settings_view_id: WidgetId, - pub settings_split_id: WidgetId, -} - -impl LapceSettingsPanelData { - pub fn new() -> Self { - Self { - shown: false, - panel_widget_id: WidgetId::next(), - keymap_widget_id: WidgetId::next(), - keymap_view_id: WidgetId::next(), - keymap_split_id: WidgetId::next(), - settings_widget_id: WidgetId::next(), - settings_view_id: WidgetId::next(), - settings_split_id: WidgetId::next(), - } - } -} - -impl Default for LapceSettingsPanelData { - fn default() -> Self { - Self::new() - } -} - pub struct LapceSettingsPanel { widget_id: WidgetId, + editor_tab_id: WidgetId, active: usize, content_rect: Rect, - header_rect: Rect, switcher_rect: Rect, switcher_line_height: f64, - close_rect: Rect, children: Vec>, } impl LapceSettingsPanel { - pub fn new(data: &LapceTabData) -> Self { + pub fn new( + data: &LapceTabData, + widget_id: WidgetId, + editor_tab_id: WidgetId, + ) -> Self { let children = vec![ WidgetPod::new(LapceSettings::new_split(LapceSettingsKind::Core, data)), WidgetPod::new(LapceSettings::new_split(LapceSettingsKind::UI, data)), @@ -105,11 +72,10 @@ pub fn new(data: &LapceTabData) -> Self { WidgetPod::new(LapceKeymap::new_split(data)), ]; Self { - widget_id: data.settings.panel_widget_id, + widget_id, + editor_tab_id, active: 0, - header_rect: Rect::ZERO, content_rect: Rect::ZERO, - close_rect: Rect::ZERO, switcher_rect: Rect::ZERO, switcher_line_height: 40.0, children, @@ -120,15 +86,8 @@ fn mouse_down( &mut self, ctx: &mut EventCtx, mouse_event: &MouseEvent, - data: &mut LapceTabData, + _data: &mut LapceTabData, ) { - if self.icon_hit_test(mouse_event) || !self.panel_hit_test(mouse_event) { - let settings = Arc::make_mut(&mut data.settings); - settings.shown = false; - ctx.clear_cursor(); - return; - } - ctx.set_handled(); ctx.request_focus(); if self.switcher_rect.contains(mouse_event.pos) { @@ -141,14 +100,6 @@ fn mouse_down( } } } - - fn icon_hit_test(&self, mouse_event: &MouseEvent) -> bool { - self.close_rect.contains(mouse_event.pos) - } - - fn panel_hit_test(&self, mouse_event: &MouseEvent) -> bool { - self.content_rect.contains(mouse_event.pos) - } } impl Widget for LapceSettingsPanel { @@ -163,43 +114,29 @@ fn event( data: &mut LapceTabData, env: &Env, ) { - if !data.settings.shown && !event.should_propagate_to_hidden() { - return; - } - match event { - Event::Command(cmd) if cmd.is(LAPCE_UI_COMMAND) => {} - Event::Command(cmd) if cmd.is(LAPCE_COMMAND) => {} - _ => { - self.children[self.active].event(ctx, event, data, env); - } - } + self.children[self.active].event(ctx, event, data, env); if ctx.is_handled() { return; } match event { Event::KeyDown(key_event) => { let mut keypress = data.keypress.clone(); + let mut focus = LapceSettingsFocusData { + widget_id: self.widget_id, + editor_tab_id: self.editor_tab_id, + main_split: data.main_split.clone(), + }; let mut_keypress = Arc::make_mut(&mut keypress); - let performed_action = mut_keypress.key_down( - ctx, - key_event, - Arc::make_mut(&mut data.settings), - env, - ); + let performed_action = + mut_keypress.key_down(ctx, key_event, &mut focus, env); data.keypress = keypress; + data.main_split = focus.main_split; if performed_action { ctx.set_handled(); } } - Event::MouseMove(mouse_event) => { + Event::MouseMove(_mouse_event) => { ctx.set_handled(); - if self.icon_hit_test(mouse_event) { - ctx.set_cursor(&druid::Cursor::Pointer); - ctx.request_paint(); - } else { - ctx.clear_cursor(); - ctx.request_paint(); - } } Event::MouseDown(mouse_event) => { self.mouse_down(ctx, mouse_event, data); @@ -207,6 +144,17 @@ fn event( Event::MouseUp(_mouse_event) => { ctx.set_handled(); } + Event::Command(cmd) if cmd.is(LAPCE_COMMAND) => { + let cmd = cmd.get_unchecked(LAPCE_COMMAND); + let mut focus = LapceSettingsFocusData { + widget_id: self.widget_id, + editor_tab_id: self.editor_tab_id, + main_split: data.main_split.clone(), + }; + focus.run_command(ctx, cmd, None, Modifiers::empty(), env); + data.main_split = focus.main_split; + println!("run cmd {cmd:?}"); + } Event::Command(cmd) if cmd.is(LAPCE_UI_COMMAND) => { let command = cmd.get_unchecked(LAPCE_UI_COMMAND); match command { @@ -219,7 +167,6 @@ fn event( self.active = 4; } LapceUICommand::Hide => { - Arc::make_mut(&mut data.settings).shown = false; if let Some(active) = *data.main_split.active { ctx.submit_command(Command::new( LAPCE_UI_COMMAND, @@ -242,9 +189,6 @@ fn lifecycle( data: &LapceTabData, env: &Env, ) { - if !data.settings.shown && !event.should_propagate_to_hidden() { - return; - } for child in self.children.iter_mut() { child.lifecycle(ctx, event, data, env); } @@ -257,8 +201,8 @@ fn update( data: &LapceTabData, env: &Env, ) { - if data.settings.shown { - self.children[self.active].update(ctx, data, env); + for child in self.children.iter_mut() { + child.update(ctx, data, env); } } @@ -269,136 +213,61 @@ fn layout( data: &LapceTabData, env: &Env, ) -> Size { - let tab_size = bc.max(); - - let self_size = Size::new( - (tab_size.width * 0.8).min(900.0), - (tab_size.height * 0.8).min(700.0), - ); - let origin = Point::new( - tab_size.width / 2.0 - self_size.width / 2.0, - (tab_size.height / 2.0 - self_size.height / 2.0) / 2.0, - ) - .round(); + let self_size = bc.max(); + let origin = Point::ZERO; self.content_rect = self_size.to_rect().with_origin(origin).round(); - self.header_rect = Size::new(self_size.width, 50.0) - .to_rect() - .with_origin(origin) - .round(); - let close_size = 26.0; - self.close_rect = Size::new(close_size, close_size) + self.switcher_rect = Size::new(150.0, self_size.height) .to_rect() - .with_origin( - origin - + ( - self.header_rect.width() - - (self.header_rect.height() / 2.0 - close_size / 2.0) - - close_size, - self.header_rect.height() / 2.0 - close_size / 2.0, - ), - ) + .with_origin(Point::ZERO) .round(); - self.switcher_rect = - Size::new(150.0, self_size.height - self.header_rect.height()) - .to_rect() - .with_origin(origin + (0.0, self.header_rect.height())) - .round(); - let content_size = Size::new( - self_size.width - self.switcher_rect.width() - 40.0, - self_size.height - self.header_rect.height(), + self_size.width - self.switcher_rect.width() - 20.0, + self_size.height, ); - let content_origin = origin - + ( - self_size.width - content_size.width - 20.0, - self_size.height - content_size.height, - ); + let content_origin = Point::new(self.switcher_rect.width() + 20.0, 0.0); let content_bc = BoxConstraints::tight(content_size); let child = &mut self.children[self.active]; child.layout(ctx, &content_bc, data, env); child.set_origin(ctx, data, env, content_origin); - tab_size + self_size } fn paint(&mut self, ctx: &mut PaintCtx, data: &LapceTabData, env: &Env) { - if data.settings.shown { - let rect = ctx.size().to_rect(); - ctx.fill( - rect, - &data - .config - .get_color_unchecked(LapceTheme::LAPCE_DROPDOWN_SHADOW) - .clone() - .with_alpha(0.5), - ); - ctx.fill( - self.content_rect, - data.config - .get_color_unchecked(LapceTheme::PANEL_BACKGROUND), - ); + ctx.fill( + self.content_rect, + data.config + .get_color_unchecked(LapceTheme::EDITOR_BACKGROUND), + ); - ctx.fill( - Size::new(self.switcher_rect.width(), self.switcher_line_height) - .to_rect() - .with_origin( - self.switcher_rect.origin() - + (0.0, self.active as f64 * self.switcher_line_height), - ), - data.config - .get_color_unchecked(LapceTheme::EDITOR_BACKGROUND), - ); - - const SETTINGS_SECTIONS: [&str; 5] = [ - "Core Settings", - "UI Settings", - "Editor Settings", - "Terminal Settings", - "Keybindings", - ]; - - for (i, text) in SETTINGS_SECTIONS.into_iter().enumerate() { - let text_layout = ctx - .text() - .new_text_layout(text) - .font( - data.config.ui.font_family(), - (data.config.ui.font_size() + 1) as f64, - ) - .text_color( - data.config - .get_color_unchecked(LapceTheme::EDITOR_FOREGROUND) - .clone(), - ) - .build() - .unwrap(); - let text_size = text_layout.size(); - ctx.draw_text( - &text_layout, + ctx.fill( + Size::new(self.switcher_rect.width(), self.switcher_line_height) + .to_rect() + .with_origin( self.switcher_rect.origin() - + ( - 20.0, - i as f64 * self.switcher_line_height - + (self.switcher_line_height / 2.0 - - text_size.height / 2.0), - ), - ); - } + + (0.0, self.active as f64 * self.switcher_line_height), + ), + data.config + .get_color_unchecked(LapceTheme::EDITOR_CURRENT_LINE), + ); + const SETTINGS_SECTIONS: [&str; 5] = [ + "Core Settings", + "UI Settings", + "Editor Settings", + "Terminal Settings", + "Keybindings", + ]; + + for (i, text) in SETTINGS_SECTIONS.into_iter().enumerate() { let text_layout = ctx .text() - .new_text_layout(format!("Settings v{VERSION}")) + .new_text_layout(text) .font( data.config.ui.font_family(), - ((data.config.ui.font_size() as f64) * 1.2).round(), - ) - .range_attribute( - 9..9 + VERSION.len() + 1, - TextAttribute::FontSize( - ((data.config.ui.font_size() as f64) * 0.8).round(), - ), + (data.config.ui.font_size() + 1) as f64, ) .text_color( data.config @@ -408,84 +277,28 @@ fn paint(&mut self, ctx: &mut PaintCtx, data: &LapceTabData, env: &Env) { .build() .unwrap(); let text_size = text_layout.size(); - let x = self.header_rect.height() / 2.0 - text_size.height / 2.0; - let y = self.header_rect.height() / 2.0 - text_size.height / 2.0; - ctx.draw_text(&text_layout, self.header_rect.origin() + (x, y)); - - let svg = get_svg("close.svg").unwrap(); - let icon_padding = 4.0; - ctx.draw_svg( - &svg, - self.close_rect.inflate(-icon_padding, -icon_padding), - Some( - data.config - .get_color_unchecked(LapceTheme::EDITOR_FOREGROUND), - ), + ctx.draw_text( + &text_layout, + self.switcher_rect.origin() + + ( + 20.0, + i as f64 * self.switcher_line_height + + (self.switcher_line_height / 2.0 + - text_size.height / 2.0), + ), ); - - self.children[self.active].paint(ctx, data, env); - - let shadow_width = 5.0; - if data.config.ui.drop_shadow() { - ctx.blurred_rect( - self.content_rect, - shadow_width, - data.config - .get_color_unchecked(LapceTheme::LAPCE_DROPDOWN_SHADOW), - ); - } - - if data.config.ui.drop_shadow() { - ctx.with_save(|ctx| { - ctx.clip( - self.switcher_rect.inflate(50.0, 0.0) + Vec2::new(50.0, 0.0), - ); - ctx.blurred_rect( - self.switcher_rect, - shadow_width, - data.config - .get_color_unchecked(LapceTheme::LAPCE_DROPDOWN_SHADOW), - ); - }); - } else { - ctx.stroke( - Line::new( - Point::new( - self.switcher_rect.x1 + 0.5, - self.switcher_rect.y0, - ), - Point::new( - self.switcher_rect.x1 + 0.5, - self.switcher_rect.y1, - ), - ), - data.config.get_color_unchecked(LapceTheme::LAPCE_BORDER), - 1.0, - ); - } - if data.config.ui.drop_shadow() { - ctx.with_save(|ctx| { - ctx.clip( - self.header_rect.inflate(0.0, 50.0) + Vec2::new(0.0, 50.0), - ); - ctx.blurred_rect( - self.header_rect, - shadow_width, - data.config - .get_color_unchecked(LapceTheme::LAPCE_DROPDOWN_SHADOW), - ); - }); - } else { - ctx.stroke( - Line::new( - Point::new(self.header_rect.x0, self.header_rect.y1 - 0.5), - Point::new(self.header_rect.x1, self.header_rect.y1 - 0.5), - ), - data.config.get_color_unchecked(LapceTheme::LAPCE_BORDER), - 1.0, - ); - } } + + self.children[self.active].paint(ctx, data, env); + + ctx.stroke( + Line::new( + Point::new(self.switcher_rect.x1 + 0.5, self.switcher_rect.y0), + Point::new(self.switcher_rect.x1 + 0.5, self.switcher_rect.y1), + ), + data.config.get_color_unchecked(LapceTheme::LAPCE_BORDER), + 1.0, + ); } } @@ -513,7 +326,7 @@ pub fn new_split(kind: LapceSettingsKind, data: &LapceTabData) -> LapceSplitNew ) .hide_header() .hide_gutter() - .padding((15.0, 15.0)); + .padding((15.0, 15.0, 0.0, 15.0)); let split = LapceSplitNew::new(data.settings.settings_split_id) .horizontal() @@ -789,7 +602,8 @@ pub fn name( .clone(), ) .default_attribute(TextAttribute::Weight(FontWeight::BOLD)) - .max_width(self.width) + .max_width(self.width - 30.0) + .set_line_height(1.5) .build() .unwrap(); self.name_text = Some(text_layout); @@ -820,7 +634,8 @@ pub fn desc( .get_color_unchecked(LapceTheme::EDITOR_FOREGROUND) .clone(), ) - .max_width(max_width) + .max_width(max_width - 30.0) + .set_line_height(1.5) .build() .unwrap(); self.desc_text = Some(text_layout); @@ -867,6 +682,12 @@ pub fn value( fn get_key(&self) -> String { format!("{}.{}", self.kind, self.name.to_kebab_case()) } + + fn clear_text_layout_cache(&mut self) { + self.name_text = None; + self.desc_text = None; + self.value_text = None; + } } impl KeyPressFocus for LapceSettingsItemKeypress { @@ -977,7 +798,8 @@ fn event( .with_origin(Point::new( 0.0, self.name(ctx.text(), data).size().height - + self.padding * 2.0, + + self.padding * 2.0 + + 4.0, )); if rect.contains(mouse_event.pos) { self.value = serde_json::json!(!checked); @@ -1049,9 +871,7 @@ fn update( _env: &Env, ) { if data.config.id != old_data.config.id { - self.name_text = None; - self.desc_text = None; - self.value_text = None; + self.clear_text_layout_cache(); } if let Some(view_id) = self.input_view_id.as_ref() { let editor = data.main_split.editors.get(view_id).unwrap(); @@ -1093,7 +913,11 @@ fn layout( data: &LapceTabData, env: &Env, ) -> Size { - self.width = bc.max().width; + let width = bc.max().width; + if width != self.width { + self.width = width; + self.clear_text_layout_cache(); + } let text = ctx.text(); let name = self.name(text, data).size(); let desc = self.desc(text, data).size(); @@ -1142,7 +966,7 @@ fn paint(&mut self, ctx: &mut PaintCtx, data: &LapceTabData, env: &Env) { let x = if let serde_json::Value::Bool(checked) = self.value { let width = 13.0; let height = 13.0; - let origin = Point::new(0.0, y); + let origin = Point::new(0.0, y + 4.0); let rect = Size::new(width, height).to_rect().with_origin(origin); ctx.stroke( rect, diff --git a/lapce-ui/src/split.rs b/lapce-ui/src/split.rs index 7a9e6a3d..b0b21f18 100644 --- a/lapce-ui/src/split.rs +++ b/lapce-ui/src/split.rs @@ -1,5 +1,6 @@ use crate::{ editor::{tab::LapceEditorTab, view::LapceEditorView}, + settings::LapceSettingsPanel, terminal::LapceTerminalView, }; use std::sync::Arc; @@ -68,6 +69,15 @@ pub fn split_content_widget( .boxed(); editor_tab = editor_tab.with_child(editor); } + EditorTabChild::Settings(widget_id, editor_tab_id) => { + let settings = LapceSettingsPanel::new( + data, + *widget_id, + *editor_tab_id, + ) + .boxed(); + editor_tab = editor_tab.with_child(settings); + } } } editor_tab.boxed() @@ -528,7 +538,7 @@ pub fn split_terminal_close( Arc::make_mut(panel).shown = false; } } - if let Some(active) = *data.main_split.active { + if let Some(active) = *data.main_split.active_tab { ctx.submit_command(Command::new( LAPCE_UI_COMMAND, LapceUICommand::Focus, diff --git a/lapce-ui/src/tab.rs b/lapce-ui/src/tab.rs index c2292b84..642a2478 100644 --- a/lapce-ui/src/tab.rs +++ b/lapce-ui/src/tab.rs @@ -118,7 +118,8 @@ pub fn new(data: &LapceTabData) -> Self { let picker = FilePicker::new(data); - let settings = LapceSettingsPanel::new(data); + let settings = + LapceSettingsPanel::new(data, WidgetId::next(), WidgetId::next()); let alert = AlertBox::new(data); @@ -1027,7 +1028,7 @@ fn handle_event( ctx.set_handled(); } LapceUICommand::FocusEditor => { - if let Some(active) = *data.main_split.active { + if let Some(active) = *data.main_split.active_tab { ctx.submit_command(Command::new( LAPCE_UI_COMMAND, LapceUICommand::Focus, @@ -1119,9 +1120,6 @@ fn event( if data.alert.active || event.should_propagate_to_hidden() { self.alert.event(ctx, event, data, env); } - if data.settings.shown || event.should_propagate_to_hidden() { - self.settings.event(ctx, event, data, env); - } if data.picker.active || event.should_propagate_to_hidden() { self.picker.event(ctx, event, data, env); } @@ -1247,10 +1245,6 @@ fn update( ctx.request_layout(); } - if old_data.settings.shown != data.settings.shown { - ctx.request_layout(); - } - if old_data.picker.active != data.picker.active { ctx.request_layout(); } @@ -1555,11 +1549,6 @@ fn layout( ); } - if data.settings.shown { - self.settings.layout(ctx, bc, data, env); - self.settings.set_origin(ctx, data, env, Point::ZERO); - } - if data.alert.active { self.alert.layout(ctx, bc, data, env); self.alert.set_origin(ctx, data, env, Point::ZERO);