Viewport controller

A MVC-like design was imported in ReoGrid to implement the rendering of presentation layer. According to Excel, there are at least two different layouts needed to be presented to the end-user.

Two layouts in Excel are:
  • Normal Layout
  • Page Layout
One important thing is what different layout has different behaviors, like scrolling behavior and page header editing.

Normal Layout


Page Layout


Implementations in ReoGrid

The first thing to do is to separate the entire display region of control to a few small views, and each view is designed only to render the content of itself.

Since the header of rows, header of columns have different scrolling directions, to separate the views by scrolling direction seems more better.

How to scroll

The GDI+ graphics object provides the method TranslateTransform, it can be used to change the origin of drawing context, it will be useful to implement the scrolling. No need to change each position of cells in spreadsheet, just use this method to change the start position of rendering context by specifying a offset value.

Interface definitions

Some views are not necessary to scroll, decrease times of performing TranslateTransform will help to save the time of rendering, there is a different sets of interface was designed in ReoGrid, the views without scrolling:
interface View {                     // called 'IPart' in source code
  void Draw();                       // draw content without scrolling
  Rectangle Bounds { get; set; }     // view boundaries 

And the views with scrolling:
interface ScrollView : View {        // called 'IViewPart' in source code
  void Draw();                       // draw content without scrolling,
                                        and perform TranslateTranform by ViewStart
  void DrawView();                   // draw content with scrolling
  void Scroll(int x, int y);         // perform scrolling, apply offset to ViewStart
  Point ViewStart { get; set; }      // offset value in horizontal and vertical direction

Visible region

Always to render the visible region which is part of entire spreadsheet will improving rendering performance. Maintains the visible region to each views after view has been scrolled, draw the content which is only contained or intersected by a visible region.

The freeze implementation

once a view such as header of row which is used to render the header of rows will be implemented, just by making a clone of the view, disabling it's scrolling ability or changing its scrolling direction, will implement the freeze with an easier way.

Difference scrolling effect between Excel and ReoGrid

ReoGrid uses pixel-based scrolling calculating, but seems like Excel uses cell-based scrolling calculating. I think there are different pros and cons to each method.
  • Excel
    • Scrolling starting position: cell's top-left
    • Scrolled by number of cells
    • pros - Since scrolled by number of cells, once the value of scroll-bar changed, it is possible to find the position of cell to be displayed very quickly. And when the freeze, outline collapsed or any rows or columns hiding, even in the spitted window rendering, it still work quickly.
    • cons - Cannot force the scrolling start at the middle of row. When the row has large of height, scrolling starts at either top of the row, or bottom of the row, this is a little bit bad on user experience.
  • ReoGrid
    • Scrolling starting position: any pixels
    • Scrolled by pixels of screen
    • pros - improving user experience, make scrolling more smoothly
    • cons - since scrolled by pixels of screen, when the value of scroll-bar changed, it needed to decide the spreadsheet start to render at which row and column, it needed to convert the pixels to cells index, it will also spend more time during scrolling. I had considered and tried to solve this, make it faster by binary search.

Improving: Convert from pixel position to cell index by binary search

All of headers of both row and column have the top position in pixel, and the width or height are saved in memory together. Since headers always be sorted by both index and pixels, it is possible to convert the pixels to cell index by using binary search quickly.
The implementation of binary search in ReoGrid is ArrayHelper class.

Last edited Jan 14, 2014 at 8:08 AM by unvell, version 22