Skip to content
Cecil Coupe edited this page May 22, 2016 · 9 revisions

This is a proposed design for a new widget that might appear in 3.3.2 (or later). It would look similar to a Shoes edit_box but it is more complicated and feature rich. This would not replace edit_box.

This is issue 144

When writing the show_console code for Shoes 3.2.24 and then rewriting it as Shoes.terminal in Shoes 3.3.2, I used Gtk Widgets and OSX facilities that Shoes does not have a mappings to some very rich capabilities and that's OK for the consoles. The console is just barely connected to Shoes. I was also struck by the common things I saw in the GtkTextView widget and NSTextView & friends. Could they merged into a new Shoes widget with it's own unique methods and simplified a bit (the native API's are huge)?

This is not a widget for beginners to use in place of edit_box and may not respond to all styles and methods for a edit_box. Backwards compatibly with edit_box is not a goal.

What would it do?

That Gtk link above gives you a good idea. There is an array of lines in a scrolled window. The buffer. You can delete lines and characters, insert and append lines and characters. That is very painful to do with edit_box (to be kind).

What problems does it fix? What would it be used for?

There are several open issues that might be solved with this widget.

The isp.rb script that I use for various examples that monitors pings would be much simpler. I'm aware of other folks that like to use Shoes to monitor processes or computations and have it appear in a edit_box like widget.

It could be used to write a much nicer IRB console for example. Think larger. One could write a simple text editor. One could eval the contents of the editor buffer (or a selection of it) with the proper App.context in selt. That would make Shoes an IDE doing REPL things. Byebug would still be a problem but there's probably a way to fix that since they are friendly folk. Yes, that's dreaming but it's not an impossible dream.

But first we need that widget and an API.

Proposed API - A work in progress.

Note, both GtkTextView and NSTextView have an MVC oriented api. Slight differently visions, to be expected. Shoes wasn't designed to expose that. In fact, it may be counter to Shoes. So we won't pretend it's going to be MVC, because it probably isn't.

We'll try to implement the Shoe common methods and styles for widgets of course where they make sense. We'll implement the current edit_box methods like focus() and text(), text= will work on the entire buffer. The string is suitable for writing to a file so it's got embedded new line characters in it. Just like it does now for edit_box.

text_mark, text_ranges and Selection

The buffer (M in MVC) is just one long Ruby string. Except, Shoes is displaying it and to modify it you need to use Shoes classes and methods. We don't count pixels inside edit_box or a text_edit_box. We can't manipulate characters in the buffer willy nilly with Ruby or Shoes won't know that the VC of MVC has something to do. Those characters on screen may not be in a utf8 buffer (cocoa uses utf16le). That's a detail we really don't want to think about. Abstract it away.

Cocoa NSTextStorage doesn't know lines and columns very well. It tends to use NSRange(Start,length) which is a run of text. Start is a 0 based index into the buffer characters. So NSRange is more like a selection. Unless one uses a length of 0 (we can).

GtkTextView has Marks and Iterators. Marks are best for this purpose because iterators are fleeting creatures - Unicorn sparkles. Two marks in a structure would be equivalent to an NSRange. Hopefully, this rough description can be matched up to the gui events for highlighting a block of chars with the mouse. See Beware notes.

Let's call them text_mark and text_range in this document. Assume they are new Shoes classes with some methods for creating new marks, perhaps changing the buffer position of a mark, shrinking or expanding a range or applying some visual change to the range (like bolding or a font change).

We'll have some predefined text_marks. Beginning of Buffer. End of Buffer. We need a mark that shows where the GUI cursor is in buffer. We'll need some methods to call to get those.

text_edit_box.first

returns text_mark for beginning of buffer.

text_edit_box.last

returns text_mark for current end of buffer. Might want to scroll to here.

text_edit_box.cursor

returns the text_mark of the cursor in the buffer. You could delete a character to the left of this mark or insert a new character to the right of this.

text_edit_box.insert(string, text_mark, {font_properties})

inserts the characters at the text_mark in the buffer and returns the text_mark after the last character(and line) inserted. If there is a hash in the optional third argument then its the Shoes font style hash with no guarantee of being completely cross platform).

text_edit_box.append (string, {font_properties])

Appends string at the end of the buffer. By default, this scrolls the view up so the cursor mark in at the end of the widget display.

text_edit_box.delete([text_range])

deletes characters from text_range. If no argument is given, text is deleted to the left of the cursor mark (think backspace key). Returns a text_mark usable for undo or replace.

text_edit_box.get(text_range)

returns the string for the text range.

text_edit_box.change {|self, keycode|}

This proc {} is different from Shoes edit_box.change{}. Its called with an arg that is the utf8 character before actually modifying the contents. Shoes will respond to the return of your proc {}. Returning true will insert the keycode where ever the cursor mark is. Return false or nil means Shoes won't insert the character. You might use this to implement your own definition of function keys behavior or only allowing numerals or...

text_edit_box.scroll_to_mark(text_mark)

moves the widget view so the given text_mark is visible. Does not change the cursor text_mark

text_edit_box.scroll_to_end

Like calling scroll_to_mark(text_edit_box.last())

Beware

Matching mouse movement/highlighting in a native widget to text_range in Shoes is critical to this proposal and while I think it can be done, it hasn't been done yet.

Edit History

2015-09-06 text_edit_box is the chosen name. Because that's how Shoes names things and I couldn't think of anything better. Not a permanent decision.

2015-09-09 Changed names for some methods. Some of that is embedded in C now so it going to be harder to change.

Note: Shoes has added append and scroll_to_end methods to the existing edit_box.

2016-05-21 More thoughts about selection and insertion points General rewrite of api

Clone this wiki locally