|
wxMaxima
|
The layout/recalculation engine of a worksheet. More...
#include <WorksheetLayout.h>
Data Structures | |
| struct | ScrollAnchor |
| The point of the worksheet the cursor sits at, for ArmScrollCompensation(). More... | |
Public Member Functions | |
| WorksheetLayout (Configuration *config, WorksheetView &view, std::function< GroupCell *()> getTree, std::function< GroupCell *()> getLastCell) | |
| Construct the engine. | |
| WorksheetLayout (const WorksheetLayout &)=delete | |
| WorksheetLayout & | operator= (const WorksheetLayout &)=delete |
| void | RequestRecalculation (Cell *start) |
| Schedule a recalculation of the worksheet starting with the cell start. | |
| void | RequestFullRecalculation () |
| Schedule a recalculation of the whole worksheet. | |
| bool | RecalculateIfNeeded (bool timeout=false, long timeSliceMs=50) |
| Perform the scheduled recalculation, if one is pending. | |
| void | AdjustSize () |
| Adjust the virtual size and scrollbars to the document's extent. | |
| void | GetMaxPoint (int *width, int *height) |
| Get the coordinates of the bottom right point of the worksheet. | |
| void | UpdateConfigurationClientSize () |
| Inform the configuration about the view's current client size. | |
| int | GroupCellWidthWithMargins (int cellWidth) const |
| The horizontal space a group cell of the given width occupies. | |
| int | GetScrollUnit () const |
| The scroll granularity (device px per scroll unit) AdjustSize() last applied. | |
| void | RequestAdjustSize () |
| Flag the virtual (scroll) size as needing re-adjustment. | |
| void | CancelPendingRecalculation () |
| Drop any pending recalculation (e.g. when the document is cleared). | |
| void | SetScrollAnchorCallback (std::function< ScrollAnchor()> callback) |
| Tells the engine where the cursor currently is. | |
| void | ArmScrollCompensation () |
| Keep the cursor still on screen across the next layout pass. | |
| bool | ScrollCompensationArmed () const |
| Is a scroll compensation waiting for the next layout pass to finish? | |
| int | GetLastCellsVisited () const |
| GroupCells walked by the most recent RecalculateIfNeeded() pass (visited includes cheap reposition-only cells; recalculated counts only the cells that actually needed the expensive re-layout). Exposed for tests and diagnostics: a localized change should recalculate very few cells, so a large count on a small edit signals an over-broad recalculation. | |
| int | GetLastCellsRecalculated () const |
The layout/recalculation engine of a worksheet.
Talks to the cell tree via the callbacks handed to the constructor, to the window via a WorksheetView and to the Configuration for metrics and the canvas size. Worksheet holds one instance and forwards its layout entry points here; the headless unit test drives an instance without any window.
| WorksheetLayout::WorksheetLayout | ( | Configuration * | config, |
| WorksheetView & | view, | ||
| std::function< GroupCell *()> | getTree, | ||
| std::function< GroupCell *()> | getLastCell | ||
| ) |
Construct the engine.
| config | The Configuration supplying metrics, the canvas size and the recalculation drawing context. |
| view | The window surface (real Worksheet or a test mock). Held by reference: must outlive this object. |
| getTree | Returns the first GroupCell of the worksheet (or null). |
| getLastCell | Returns the last GroupCell of the worksheet (or null). |
| void WorksheetLayout::AdjustSize | ( | ) |
Adjust the virtual size and scrollbars to the document's extent.
Defers (via RequestAdjustSize()) while a recalculation is still pending, since the cell positions it reads would be stale - see the implementation comment for the full story.
| void WorksheetLayout::ArmScrollCompensation | ( | ) |
Keep the cursor still on screen across the next layout pass.
Called just before output is appended to a cell: the cells below it are about to move down, the cursor with them if it sits below the changed cell. This remembers where the cursor's cell is now; once the pass has laid everything out, the view is scrolled by however far that cell moved - to the pixel, see ComputeScrollCompensation() - so the cursor, and everything around it, stays where the user was looking.
Only ever arms once per pass: a second append before the pass has run would measure positions that aren't on screen yet. The caller is expected to only arm if the cursor is visible - scrolling to keep an invisible point still would move the part of the worksheet the user actually is looking at.
| void WorksheetLayout::GetMaxPoint | ( | int * | width, |
| int * | height | ||
| ) |
Get the coordinates of the bottom right point of the worksheet.
Only valid once no recalculation is pending; asserts on that.
|
inline |
The scroll granularity (device px per scroll unit) AdjustSize() last applied.
Worksheet's scroll handlers read it to convert scroll positions to pixels.
| int WorksheetLayout::GroupCellWidthWithMargins | ( | int | cellWidth | ) | const |
The horizontal space a group cell of the given width occupies.
That is the cell's own width plus the equal left and right margins the worksheet reserves around every group cell. Used both when measuring the document width (GetMaxPoint) and while walking the recalculation.
| bool WorksheetLayout::RecalculateIfNeeded | ( | bool | timeout = false, |
| long | timeSliceMs = 50 |
||
| ) |
Perform the scheduled recalculation, if one is pending.
One walk from the scheduled start point drives both modes: with timeout set the pass is time-sliced (yields after timeSliceMs, resuming on the next call); otherwise the whole scheduled range is laid out in one go. Ends by adjusting the virtual size once the cell positions are valid.
|
inline |
Flag the virtual (scroll) size as needing re-adjustment.
Set when a cell changed height (via the callback Worksheet registers on the Configuration, so cells can flag it without depending on the view) or when layout is scheduled; consumed by RecalculateIfNeeded(), which calls AdjustSize() once the cell positions are valid.
| void WorksheetLayout::RequestFullRecalculation | ( | ) |
Schedule a recalculation of the whole worksheet.
For changes that potentially dirty cells at arbitrary positions (zoom, font or configuration changes, window resizes): the dirty range becomes "the first cell to the end of the document", so the next layout pass may not stop early. An operation that changes one known cell should call RequestRecalculation(cell) instead.
| void WorksheetLayout::RequestRecalculation | ( | Cell * | start | ) |
Schedule a recalculation of the worksheet starting with the cell start.
This only records where the next layout pass has to start (it marks the group dirty and extends the pending dirty range [m_recalculateStart, m_recalculateEnd]); it does not size or position any cell. The actual work - and, crucially, AdjustSize() once the cell positions are correct - happens in RecalculateIfNeeded(). Calling AdjustSize() (or otherwise reading cell geometry) right after this, without a RecalculateIfNeeded() in between, reads stale positions.
|
inline |
Tells the engine where the cursor currently is.
Queried by ArmScrollCompensation() and again once the layout pass has run, so a compensation is dropped if the cursor moved in between: the point to keep still is then a different one. Worksheet sets this; without it (the headless tests) no compensation is ever armed.