Closed
Description
Original design
plot.xts()
is based on quantmod::chart_Series()
. The internal structures have a lot of implicit assumptions and some duplicated code, which makes the code harder to reason about and change. For example:
- There are no explicit "panels", i.e. what is added when
addSeries()
is called withon = NA
. Instead, there is one list of "frames" that contains header and series frames. The odd numbered list elements are the header frames and the even numbered elements are the series frames.- Target: store the header and series frames in a panel object.
- Everything that gets rendered is in one list of "actions". Where the action is rendered is stored in the "frame" attribute of the action.
- Target: frames should contain actions that are rendered in the the frame.
- There are separate lists for the ylim and x/y aspect ratio for each frame.
- Target: frames should contain their ylim and x/y aspect ratio.
- There are 5 separate code blocks to add y-axis grid lines and labels.
- Target: the panel should control the y-axis settings.
- Some functions are always called, even though they're only necessary in certain situations. For example,
get_ylim()
is always called but only needed whenmulti.panel = TRUE
. - The x-axis action is part of the first series frame.
- Target: the x-axis is the same for the entire plot, so it should be part of the plot object.
The main purpose for this refactor is to make it easier to implement y-axis log scaling (#103).
Refactor target design
The target design attempts to organize the plot components into their respective parts: the plot window, the window panels, and the panel data/actions.
-
The plot object contains the plot title/header (and optional timespan), the x-axis labels and tick marks, and a list of 'panel' objects. The main plot object contains:
Env
: an environment to hold all the plot informationadd_main_header()
: add the main plot headeradd_main_xaxis()
: add the x-axis labels and ticks to the main plotnew_panel()
: create a new panel and add it to the plotget_xcoords()
: get the x-coordinate values for the plotget_panel()
: get a specific panelget_last_action_panel()
: get the panel that had the last rendered actionnew_environment()
: create a new environment withEnv
as its parent- Functions that aren't intended to be called externally:
update_panels()
: re-calculate the x-axis and y-axis valuesrender_panels()
: render all the plot panelsx_grid_lines()
: plot the x-axis grid linescreate_ylim()
: create y-axis max/min, to handle whenmax(x) == min(x)
.
-
The panel object contains:
id
: the numeric index of the panel in the plot's list of panelsasp
: the x/y aspect ratio for the panel (relative vertical size)ylim
: the ylim of the panel when it was createdylim_render
: the ylim of the panel to use when renderinguse_fixed_ylim
: whenTRUE
, do not update the panel ylim based on all panel seriesheader
: the panel titleactions
: a list of expressions used to render the paneladd_action()
: add an action to the actions listyaxis_expr
the expression to render the y-axis min/max values, labels, and grid lines/ticks. It also contains the x-axis grid expression because we need the y-axis min/max values to know where to draw the x-axis grid lines on the panel.