-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce a layer of indirection between `Terminal` and `CharGrid`, using the `Screen` type, which allows a `Terminal` to contain multiple `CharGrids` in different sections of the visible screen. Prior to this commit, a single `Terminal` contained a stack of `CharGrid`s, which each filled the entire size of the `Terminal` window. Now, a single `Terminal` contains a single `Screen`, which is divided into `ScreenSection`s. Each `ScreenSection` is a rectangular section of the screen. They are formed by splitting an existing section into two along a horizontal or vertical axis. This means that the relationship between sections that exist is always a binary tree. Each `ScreenSection` has an unsigned 64-bit tag. One section is identified as the 'active section' - commands that apply to the `CharGrid` are applied to the grid contained in this section. Each section contains a non-empty stack of `Panel`s. A `Panel` can take one of two forms: either it contains a `CharGrid`, or it is split into two parts, each of which contains a `ScreenSection`. As a result, there is a mutually recursive relationship between the definition of `ScreenSection` and `Panel`, which allows for considerable flexibility in adjusting the layout screen, while still maintaining a certain level of restraint. This commit and its associated commit to notty-encoding add or modify several commands to the notty protocol: * __PUSH BUFFER__ is now __PUSH PANEL__, and takes as an argument the tag of the screen section being pushed to. If no argument is passed, a panel is pushed to the active section. The panel that is pushed always contains a single character grid. It also takes a boolean argument, which determines whether or not the grid retains offscreen data as it scrolls. * __POP BUFFER__ is now __POP PANEL__, and also takes as an argument the tag of screen section to pop from. If no argument is passed, the top panel of the active section is popped. A stack with 1 member cannot be popped from. * __SPLIT PANEL__ describes splitting a panel into two. It takes arguments defining the axis and position of the split, which panel the contents should be saved to, how resizing of child sections should be handled, and whether or not the grid in the new panel should retain offscreen data as it scrolls. Panels which are already split *can* be split again; the existing split sections are resized into the identified saved sections. * __UNSPLIT PANEL__ describes removing the split from a panel. It takes an argument identifying which of the two sections in this panel should be saved. The stack of the saved section will be pushed to the top of the section this panel is on top of; the stack of the unsaved section will be destroyed. * __ADJUST PANEL SPLIT__ allows an existing split panel's split to be moved or adjusted. It takes arguments defining the axis and position of the split, and how resizing of the child sections should be handled. It performs no action it the section's top is a unsplit panel. * __ROTATE SECTION DOWN__ rotates down the stack, putting the top of the stack on the bottom. * __ROTATE SECTION UP__ rotates up the stack, putting the bottom of the stack on the top. * __SWITCH ACTIVE SECTION__ switches which section is active. It will only perform a switch if the top panel of the target section is a single character grid.
- Loading branch information
1 parent
e94b8a9
commit 431b7a9
Showing
18 changed files
with
1,542 additions
and
112 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
# Subdividing the screen in notty | ||
|
||
notty supports subdividing a screen into multiple sections, each of which can | ||
contain independent grids. Each of these grids can retain off-screen state, | ||
scroll independently, be resized independently, and so on. There are several | ||
commands which manipulate this feature, but what's most important is | ||
understanding the underlying layout model that notty uses. Here are the | ||
rules that notty's model uses to make screen subdivision easier: | ||
|
||
1. The screen is subdivided into nested, rectangular sections. | ||
2. Each section of the screen contains a stack of panels. | ||
3. Each panel is either a single character grid, or is split into two smaller | ||
sections, each of which contain a stack of panels. | ||
|
||
# For example | ||
|
||
Consider this 6x6 screen: | ||
|
||
``` | ||
0 1 2 3 4 5 | ||
+-----+-----+ | ||
0| | | | ||
1| | | | ||
2| | | | ||
3| | | | ||
+-----+-----+ | ||
4| | | ||
5| | | ||
+-----+-----+ | ||
``` | ||
|
||
Though this screen contains only 3 grids, it actually contains 5 sections: | ||
|
||
1. The base section, which contains the entire 6x6 grid. The panel in this | ||
section is split horizontally between rows 3 and 4. | ||
2. The top portion of the base section, filling the area from 0,0 to 5,3 | ||
(inclusive). The panel in this section is split vertically between columns 2 | ||
and 3. | ||
3. The left portion of the previous section, from 0,0 to 2,3 (inclusive). The | ||
panel here contains a character grid. | ||
4. The right portion of that section, from 3,0 to 5,3 (inclusive). The panel | ||
here contains a character grid as well. | ||
5. The lower portion of the base section, from 0,4 to 5,5 (inclusive). The | ||
panel here also contains a character grid. | ||
|
||
# Commands that can be applied to any section | ||
|
||
In the implementation, each of these sections of the screen has an identifying | ||
tag, so that different commands can be applied to each section. These actions | ||
can all be performed on any section of the screen, whether it contains a grid | ||
or a split: | ||
|
||
## Pushing a Panel | ||
|
||
Sections don't just contain one Panel, they contain a stack of Panels. You can | ||
push a new Panel, which contains an empty grid, over any section on the screen. | ||
|
||
This includes sections which contain split panels, and also includes the 'base | ||
section' of the entire screen. This means, for example, a new grid could be | ||
pushed over the entire screen in the above example, or over the top half of | ||
the screen that contains the vertical split. | ||
|
||
## Popping a Panel | ||
|
||
The top panel of a section can be popped off, deleting whatever it contained. | ||
This is only true if a section contains more than one panel - a section with a | ||
stack with only one member will not change when the pop command is applied. | ||
|
||
The tag of each section is assigned when that section is created, but the tag | ||
of the base section is always 0. If two sections are given the same tag, the | ||
behavior of notty commands applied to that tag is implementation defined, and | ||
you should not create sections with the same tag. | ||
|
||
## Rotating the Panel Stack | ||
|
||
The stack in each section can also be rotated up and down, switching which | ||
panel is on top (and therefore visible) without deleting any panels. The stack | ||
cannot be arbitrarily reordered, it can only be rotated in either direction. | ||
|
||
## Splitting a Section | ||
|
||
Any section can be split into two sections, the split command takes arguments | ||
which handle how it should be split, including which side of the split the | ||
current content of the top panel should be saved to. | ||
|
||
Splits can be either horizontal or vertical, and can occur between any two | ||
columns/rows within that section. | ||
|
||
Only the top panel of a section is split, if that panel is popped off, whatever | ||
was underneath it will unchanged by the split. | ||
|
||
A panel containing a split can be split: the current split will be saved to | ||
one of the subsections created. This includes the base panel of the entire | ||
screen. | ||
|
||
# Commands that can be applied to split sections | ||
|
||
These commands can be applied to sections which are split. Applying them to | ||
sections which are not split produces no change. | ||
|
||
## Unsplitting a Section | ||
|
||
A split section can be unsplit. The unsplit command takes an argument | ||
identifying which half of the split should be saved. The stack from the saved | ||
section will be pushed on top of the stack in the section that is being | ||
unsplit. | ||
|
||
## Adjusting a Section Split | ||
|
||
The division within a split section can be adjusted, changing how that section | ||
is split. This adjustment can change both the position and axis of the split, | ||
so that a horizontal split could become a vertical split, for example. The | ||
contents of the two subsections of the split will be resized to fit the new | ||
areas of the subsections. | ||
|
||
# The 'active' section | ||
|
||
At any given time, exactly one section of the screen is marked the active | ||
section. This top panel of this section must be a character grid. | ||
|
||
All commands which apply to character grids - writing characters, setting | ||
styles, moving the cursor, and so on - are applied to the grid which is | ||
currently active. | ||
|
||
A command exists to switch which section is active at a given time. An attempt | ||
to switch the active section to a section which does not have a character grid | ||
as its top panel will result in no change. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
use command::prelude::*; | ||
use datatypes::{SaveGrid, ResizeRule}; | ||
|
||
use notty_encoding::cmds::{ | ||
PushPanel, PopPanel, | ||
SplitPanel, UnsplitPanel, AdjustPanelSplit, | ||
RotateSectionDown, RotateSectionUp, | ||
SwitchActiveSection, | ||
}; | ||
|
||
impl Command for PushPanel { | ||
fn apply(&self, terminal: &mut Terminal) -> io::Result<()> { | ||
terminal.push(self.0, self.1.unwrap_or(true)); | ||
Ok(()) | ||
} | ||
fn repr(&self) -> String { | ||
String::from("PUSH BUFFER") | ||
} | ||
} | ||
|
||
impl Command for PopPanel { | ||
fn apply(&self, terminal: &mut Terminal) -> io::Result<()> { | ||
terminal.pop(self.0); | ||
Ok(()) | ||
} | ||
fn repr(&self) -> String { | ||
String::from("POP BUFFER") | ||
} | ||
} | ||
|
||
impl Command for SplitPanel { | ||
fn apply(&self, terminal: &mut Terminal) -> io::Result<()> { | ||
let save = self.save.unwrap_or(SaveGrid::Left); | ||
let rule = self.rule.unwrap_or(ResizeRule::Percentage); | ||
terminal.split(save, self.kind, rule, self.split_tag, self.l_tag, self.r_tag, | ||
self.retain_offscreen_state.unwrap_or(true)); | ||
Ok(()) | ||
} | ||
fn repr(&self) -> String { | ||
String::from("SPLIT BUFFER") | ||
} | ||
} | ||
|
||
impl Command for UnsplitPanel { | ||
fn apply(&self, terminal: &mut Terminal) -> io::Result<()> { | ||
terminal.unsplit(self.save, self.unsplit_tag); | ||
Ok(()) | ||
} | ||
fn repr(&self) -> String { | ||
String::from("UNSPLIT BUFFER") | ||
} | ||
} | ||
|
||
impl Command for AdjustPanelSplit { | ||
fn apply(&self, terminal: &mut Terminal) -> io::Result<()> { | ||
terminal.adjust_split(self.adjust_tag, self.kind, self.rule); | ||
Ok(()) | ||
} | ||
fn repr(&self) -> String { | ||
String::from("ADJUST PANEL SPLIT") | ||
} | ||
} | ||
|
||
impl Command for RotateSectionDown { | ||
fn apply(&self, terminal: &mut Terminal) -> io::Result<()> { | ||
terminal.rotate_down(self.0); | ||
Ok(()) | ||
} | ||
fn repr(&self) -> String { | ||
String::from("ROTATE DOWN") | ||
} | ||
} | ||
|
||
impl Command for RotateSectionUp { | ||
fn apply(&self, terminal: &mut Terminal) -> io::Result<()> { | ||
terminal.rotate_up(self.0); | ||
Ok(()) | ||
} | ||
fn repr(&self) -> String { | ||
String::from("ROTATE UP") | ||
} | ||
} | ||
|
||
impl Command for SwitchActiveSection { | ||
fn apply(&self, terminal: &mut Terminal) -> io::Result<()> { | ||
terminal.switch(self.0); | ||
Ok(()) | ||
} | ||
fn repr(&self) -> String { | ||
format!("SWITCH TO PANEL {}", self.0) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.