Browse DevX
Sign up for e-mail newsletters from DevX


Nano-Sheets: A Small but Mighty Spreadsheet Engine in REBOL, Part 2 : Page 2

Building on Part 1 of this article, not only can you create a working spreadsheet in just a few bytes using REBOL, but you can extend it to support printing, standard keyboard navigation, macros containing code, and even make it shareable and dynamically updatable—while still using only a few bytes of code.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Adding Keyboard Navigation
Although the basic engine has mouse controls, and the tab key moves between cells, it's worth adding some extra keyboard navigation; the up and down arrow keys are very helpful if you expect to do much editing. To avoid adding code to every cell to handle keyboard events, you can use a nice feature in REBOL/View: insert-event-func.

The insert-event-func word lets you specify a callback function that the main parent calls whenever it "sees" an event. Using this feature, you can filter and act on events in one central location. First, define a callback function:

event-func: func [face event /local f] [ ; The face we get passed is *not* the cell, it's ; the main layout. ; We use system/view/focal-face to get the cell ; being edited. ; The ALL function is a shortcut for ANDing ; clauses together, e.g. ; if (('key = event/type) and (in-cell?)) if all ['key = event/type in-cell?] [ switch event/key [ F2 [if in-cell? [show-formula system/view/focal-face]] up [move up] down [move down] ; left/right conflict with edit ' navigation, need a more ; complex system to track edit mode if we ' want to do this. Use Tab/Shift+Tab to ; move L/R in the meantime. ;left [move left] ;right [move right] ] ] event ]

Then you install the completed callback function in the event chain using insert-event-func.

insert-event-func :event-func

Note that the code also handles an F2 key press, so you can edit the formula for a cell as you would in a traditional spreadsheet. The function that actually moves the focus is called move. If you're new to REBOL, it may not be clear how move works, so here's some commented code that should help explain it.

move: func ['way /local pos] [ ; Find the location of the current cell in the ; list of cells pos: find cells cur-cell ; "enter cur-cell" triggers the recalc; the tab ; key does that automatically, arrow keys don't if find [up down] way [enter cur-cell] ; left right ; Now we shift the position in the list of cells, ; relative to the current cell, based on the ; direction they're moving, and pick the cell at ; that location so we can move to it. ; Left and Right arrows conflict with in-cell ; editing, and need more code to support changing ; between navigation and edit modes. cell: pick switch way [ up [skip pos negate sheet-size/x * 2] down [skip pos sheet-size/x * 2] ;left [back pos] ;right [next pos] ] 1 ; Keep from falling off the top of the list due to ; a negative skip. if not object? cell [cell: none] ; Set the current cell if cell [focus cell] ]

The move code illustrates one other advanced trick—the use of a lit-word! (notice the tick-mark/apostrophe in the word way in the first line of preceding code) as a parameter. That tells REBOL not to evaluate the argument it gets. In this case way is going to be a word! value, something like up or down. Normally you would have to use a lit-word! when making the call, for example:

move 'up move 'down

That's not terrible, but it's not quite as nice as this.

move up move down

The goal here is to make the higher-level logic look less like "code," and is an important concept when you think in terms of REBOL dialects. The use of a lit-word! as a parameter shows how much control REBOL gives you over when evaluation occurs. That's important because, in REBOL, there is no code, there is only data that gets evaluated (it takes a while for that concept to sink in, especially if you're an experienced programmer used to other languages).

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date