-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add centered view mode #3239
Add centered view mode #3239
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -405,6 +405,7 @@ impl MappableCommand { | |
wonly, "Close windows except current", | ||
select_register, "Select register", | ||
insert_register, "Insert register", | ||
toggle_centered_view, "Toggle centered view", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The naming seems confusing since the view isn't "centered" but is instead in a distraction free mode. Tmux also calls this "zoomed (in)" since the view is maximized and replaces the whole tree. |
||
align_view_middle, "Align view middle", | ||
align_view_top, "Align view top", | ||
align_view_center, "Align view center", | ||
|
@@ -4571,6 +4572,13 @@ fn insert_register(cx: &mut Context) { | |
}) | ||
} | ||
|
||
fn toggle_centered_view(cx: &mut Context) { | ||
let mut view = view_mut!(cx.editor); | ||
view.is_centered = !view.is_centered; | ||
|
||
cx.editor.tree.recalculate(); | ||
} | ||
|
||
fn align_view_top(cx: &mut Context) { | ||
let (view, doc) = current!(cx.editor); | ||
align_view(doc, view, Align::Top); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -274,6 +274,8 @@ pub struct Config { | |
/// Whether to color modes with different colors. Defaults to `false`. | ||
pub color_modes: bool, | ||
pub soft_wrap: SoftWrap, | ||
/// Whether to center views by default, Defaults to `false`. | ||
pub centered_views: bool, | ||
Comment on lines
+277
to
+278
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd remove the config option since it seems unlikely someone would want this always on. |
||
} | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] | ||
|
@@ -772,6 +774,7 @@ impl Default for Config { | |
indent_guides: IndentGuidesConfig::default(), | ||
color_modes: false, | ||
soft_wrap: SoftWrap::default(), | ||
centered_views: false, | ||
} | ||
} | ||
} | ||
|
@@ -1241,7 +1244,13 @@ impl Editor { | |
.try_get(self.tree.focus) | ||
.filter(|v| id == v.doc) // Different Document | ||
.cloned() | ||
.unwrap_or_else(|| View::new(id, self.config().gutters.clone())); | ||
.unwrap_or_else(|| { | ||
View::new( | ||
id, | ||
self.config().gutters.clone(), | ||
self.config().centered_views, | ||
) | ||
}); | ||
let view_id = self.tree.split( | ||
view, | ||
match action { | ||
|
@@ -1398,7 +1407,11 @@ impl Editor { | |
.map(|(&doc_id, _)| doc_id) | ||
.next() | ||
.unwrap_or_else(|| self.new_document(Document::default(self.config.clone()))); | ||
let view = View::new(doc_id, self.config().gutters.clone()); | ||
let view = View::new( | ||
doc_id, | ||
self.config().gutters.clone(), | ||
self.config().centered_views, | ||
); | ||
let view_id = self.tree.insert(view); | ||
let doc = doc_mut!(self, &doc_id); | ||
doc.ensure_view_init(view_id); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -342,16 +342,35 @@ impl Tree { | |
|
||
// take the area | ||
// fetch the node | ||
// a) node is view, give it whole area | ||
// a) node is view | ||
// 1) view is centered and the parent container is not a vertical layout or | ||
// with only 1 child (the current view), center the view | ||
// 2) give the whole area | ||
// b) node is container, calculate areas for each child and push them on the stack | ||
|
||
while let Some((key, area)) = self.stack.pop() { | ||
let node = &mut self.nodes[key]; | ||
let parent = self.nodes[key].parent; | ||
|
||
match &mut node.content { | ||
// Parent must always be a container | ||
let (parent_child_count, parent_layout) = match &self.nodes[parent].content { | ||
Content::Container(container) => (container.children.len(), container.layout), | ||
Content::View(_) => unreachable!(), | ||
}; | ||
|
||
match &mut self.nodes[key].content { | ||
Content::View(view) => { | ||
// debug!!("setting view area {:?}", area); | ||
view.area = area; | ||
if view.is_centered | ||
&& (parent_child_count <= 1 || parent_layout != Layout::Vertical) | ||
{ | ||
let width = std::cmp::min(std::cmp::max(area.width / 2, 120), area.width); | ||
let area = | ||
Rect::new(area.width / 2 - width / 2, area.y, width, area.height); | ||
|
||
view.area = area; | ||
} else { | ||
view.area = area; | ||
} | ||
Comment on lines
+363
to
+373
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This gives the view the entire area but doesn't affect any of the other views. This means that you're relying on view ordering (this view should be the last one rendered) otherwise other views might get rendered over it. We also pay the performance cost of rendering all other views even though they're not on screen. (Also what happens if I change focus to a different view but this one is still centered?) I'd rather see this done via a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi, thanks for the feedback, but... to be honest I made this PR 7 months ago, so I don't remember at all why I made things in this way, and I don't have sufficent spare time to invest in this PR anymore :/ if someone is motivated enough to take over my work (or redoing it from scratch ^^') it would be better |
||
} // TODO: call f() | ||
Content::Container(container) => { | ||
// debug!!("setting container area {:?}", area); | ||
|
@@ -712,22 +731,22 @@ mod test { | |
width: 180, | ||
height: 80, | ||
}); | ||
let mut view = View::new(DocumentId::default(), GutterConfig::default()); | ||
let mut view = View::new(DocumentId::default(), GutterConfig::default(), false); | ||
view.area = Rect::new(0, 0, 180, 80); | ||
tree.insert(view); | ||
|
||
let l0 = tree.focus; | ||
let view = View::new(DocumentId::default(), GutterConfig::default()); | ||
let view = View::new(DocumentId::default(), GutterConfig::default(), false); | ||
tree.split(view, Layout::Vertical); | ||
let r0 = tree.focus; | ||
|
||
tree.focus = l0; | ||
let view = View::new(DocumentId::default(), GutterConfig::default()); | ||
let view = View::new(DocumentId::default(), GutterConfig::default(), false); | ||
tree.split(view, Layout::Horizontal); | ||
let l1 = tree.focus; | ||
|
||
tree.focus = l0; | ||
let view = View::new(DocumentId::default(), GutterConfig::default()); | ||
let view = View::new(DocumentId::default(), GutterConfig::default(), false); | ||
tree.split(view, Layout::Vertical); | ||
let l2 = tree.focus; | ||
|
||
|
@@ -769,28 +788,28 @@ mod test { | |
}); | ||
|
||
let doc_l0 = DocumentId::default(); | ||
let mut view = View::new(doc_l0, GutterConfig::default()); | ||
let mut view = View::new(doc_l0, GutterConfig::default(), false); | ||
view.area = Rect::new(0, 0, 180, 80); | ||
tree.insert(view); | ||
|
||
let l0 = tree.focus; | ||
|
||
let doc_r0 = DocumentId::default(); | ||
let view = View::new(doc_r0, GutterConfig::default()); | ||
let view = View::new(doc_r0, GutterConfig::default(), false); | ||
tree.split(view, Layout::Vertical); | ||
let r0 = tree.focus; | ||
|
||
tree.focus = l0; | ||
|
||
let doc_l1 = DocumentId::default(); | ||
let view = View::new(doc_l1, GutterConfig::default()); | ||
let view = View::new(doc_l1, GutterConfig::default(), false); | ||
tree.split(view, Layout::Horizontal); | ||
let l1 = tree.focus; | ||
|
||
tree.focus = l0; | ||
|
||
let doc_l2 = DocumentId::default(); | ||
let view = View::new(doc_l2, GutterConfig::default()); | ||
let view = View::new(doc_l2, GutterConfig::default(), false); | ||
tree.split(view, Layout::Vertical); | ||
let l2 = tree.focus; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -107,6 +107,7 @@ pub struct View { | |
pub id: ViewId, | ||
pub offset: ViewPosition, | ||
pub area: Rect, | ||
pub is_centered: bool, | ||
pub doc: DocumentId, | ||
pub jumps: JumpList, | ||
// documents accessed from this view from the oldest one to last viewed one | ||
|
@@ -138,7 +139,7 @@ impl fmt::Debug for View { | |
} | ||
|
||
impl View { | ||
pub fn new(doc: DocumentId, gutters: GutterConfig) -> Self { | ||
pub fn new(doc: DocumentId, gutters: GutterConfig, is_centered: bool) -> Self { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default should be |
||
Self { | ||
id: ViewId::default(), | ||
doc, | ||
|
@@ -148,6 +149,7 @@ impl View { | |
vertical_offset: 0, | ||
}, | ||
area: Rect::default(), // will get calculated upon inserting into tree | ||
is_centered, | ||
jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel | ||
docs_access_history: Vec::new(), | ||
last_modified_docs: [None, None], | ||
|
@@ -597,7 +599,7 @@ mod tests { | |
|
||
#[test] | ||
fn test_text_pos_at_screen_coords() { | ||
let mut view = View::new(DocumentId::default(), GutterConfig::default()); | ||
let mut view = View::new(DocumentId::default(), GutterConfig::default(), false); | ||
view.area = Rect::new(40, 40, 40, 40); | ||
let rope = Rope::from_str("abc\n\tdef"); | ||
let doc = Document::from( | ||
|
@@ -771,6 +773,7 @@ mod tests { | |
layout: vec![GutterType::Diagnostics], | ||
line_numbers: GutterLineNumbersConfig::default(), | ||
}, | ||
false, | ||
); | ||
view.area = Rect::new(40, 40, 40, 40); | ||
let rope = Rope::from_str("abc\n\tdef"); | ||
|
@@ -800,6 +803,7 @@ mod tests { | |
layout: vec![], | ||
line_numbers: GutterLineNumbersConfig::default(), | ||
}, | ||
false, | ||
); | ||
view.area = Rect::new(40, 40, 40, 40); | ||
let rope = Rope::from_str("abc\n\tdef"); | ||
|
@@ -823,7 +827,7 @@ mod tests { | |
|
||
#[test] | ||
fn test_text_pos_at_screen_coords_cjk() { | ||
let mut view = View::new(DocumentId::default(), GutterConfig::default()); | ||
let mut view = View::new(DocumentId::default(), GutterConfig::default(), false); | ||
view.area = Rect::new(40, 40, 40, 40); | ||
let rope = Rope::from_str("Hi! こんにちは皆さん"); | ||
let doc = Document::from( | ||
|
@@ -906,7 +910,7 @@ mod tests { | |
|
||
#[test] | ||
fn test_text_pos_at_screen_coords_graphemes() { | ||
let mut view = View::new(DocumentId::default(), GutterConfig::default()); | ||
let mut view = View::new(DocumentId::default(), GutterConfig::default(), false); | ||
view.area = Rect::new(40, 40, 40, 40); | ||
let rope = Rope::from_str("Hèl̀l̀ò world!"); | ||
let doc = Document::from( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.