Thursday, January 21, 2021

Hybrid Menubar and Toolbar Tabber

The customary method of organizing application menubars and toolbars is in a vertical sequence. To save space, sometimes multiple tool sets can be embedded into a single bar. This is fine but what usually results is a duplication if the functionality offered in a pull-down menu and some toolbar button. This can cause a lot of clutter, not only on screen, but in the coding where the duplication is a occurring.

For a user the on-screen clutter can be obtrusive as it begins to eat away at the screen space used by an application in both the horizontal and vertical dimensions. Too many on screen toolbars reduces the size of user work zones and tool many items per bar can result in windows whose resizing becomes constrained.  

Multiple toolbars can be toggled on or off, but then a menu item, nested somewhere in menu in the toolbar needs to be created, the result more clutter. Complex GUI elements are not only demanding in terms of coding, but offputting to any new user who has grown shy of 'bloated apps'. Users become menu weary. 

The solution? Why not switch between toolbars as needed, and leave those not so often used options such as would be found in the File, Settings and Help menu in the menubar.

Switching between toolbars is easily sorted, place them in the pages of a notebook. But, one might ask, will this take up three rows on screen, with one each for the menubar, notebook tabs and the toolbars. Well no, not really. The solution lies in embedding the menubar into the notebook tab bar using the -startWiget option. And, for those who prefer the Help menu tucked on the right hand side of the menu bar, its even possible to embed this separately using the -endWidget option. The result, a clean and simple solution with a modern feel to it.

Here's a screen shot, showing this at work in a proof of concept script.


#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

if { [catch { package present Gnocl } ] } { package require Gnocl }
    
set frame [gnocl::vBox]
set nb [gnocl::notebook]
$frame add $nb
set menuBar [gnocl::menuBar]
$nb configure -startWidget $menuBar
set container [gnocl::vBox]
    
$frame add $container -fill 1 -expand 1
gnocl::window -child $frame -setSize 0.3 -onDelete exit

set menu(file) [gnocl::menu ]
set menu(help) [gnocl::menu ]

$menu(file) add [gnocl::menuItem -text "%#New" -onClicked {puts "That's new"}]
$menu(file) add [gnocl::menuItem -text "%#Open" -onClicked {puts "That's new"}]
$menu(file) add [gnocl::menuItem -text "%#Save" -onClicked {puts "That's new"}]
$menu(file) add [gnocl::menuSeparator]
$menu(file) add [gnocl::menuItem -text "%#Quit" -onClicked exit ]
set item(help) [gnocl::menuItem -icon %#Help -text "%__Help" -onClicked { gnocl::dialog -text HELP!}]
set item(about) [gnocl::menuItem -icon %#About -text "%__About" -onClicked { gnocl::aboutDialog }]

$menu(help) add $item(help)
$menu(help) add $item(about)

set file [gnocl::menuItem -text "%__File" -submenu $menu(file)]
set help [gnocl::menuItem -text "%__Help" -submenu $menu(help) ]

$menuBar configure -children [list $file $help]


$nb addPage [gnocl::richTextToolBar  -iconSize small] %__Markup

set tb1 [gnocl::toolBar -style icons -iconSize small]
$nb addPage $tb1 %__Edit

set tb2 [gnocl::toolBar -style icons  -iconSize small]
$nb addPage $tb2 %__Tools

    
$tb1 add item -icon %#Cut   
$tb1 add item -icon %#Copy
$tb1 add item -icon %#Paste
$tb1 add item -icon %#Delete
$tb1 add item -icon %#Undo
$tb1 add item -icon %#Redo

$tb2 add item -icon %#GoBack   
$tb2 add item -icon %#GoDown
$tb2 add item -icon %#GoForward
$tb2 add item -icon %#GoUp
$tb2 add item -icon %#GotoFirst
$tb2 add item -icon %#GotoLast


$container add [gnocl::text -name txt -margins {4} -useMarkup 1] -fill 1 -expand 1

set stat [gnocl::statusBar]
$container add $stat -fill 1
    
txt lorem ;# using widget alias automatically created using the gnocl::text -name option
    
$stat push ready...


Other enhancement that could be implemented included a tearoff capability for the toolbar notebook tabs and the use of menu ribbons outlined in a previous blogpost (clear here to read).


Sunday, January 10, 2021

{{{} {}}} What!

This level of nested braces may appear to be something from a programming quiz but, actually, this is meaningful when adding new, empty rows to a gnocl::list widget.

Suppose an instance of a list widget is created with 2 columns containing plain text.

set lv(s) [gnocl::list \
    
-types [list string string] \
    -titles {Keys Mapping}]

Appending new rows to the table is achieved using the widget subcommand add.  

$lv(s) add ...
 

So, adding an empty row can be achieved using

$lv(s) add {{{} {}}}

The widget code expects a list of rows, with each member of this list itself being a list whose items correspond to the column entries. Sounds kind of confusing and complicated. Well, it is. Especially when empty rows are being added.

Lets work our way our way through it, from the inside out.

The list has two columns, and lets take the following as our staring point. We will write these items to the cells to be appended.

col-1 col-2

A list of two items. This needs to be converted to a list for the row, simply done with braces.

{col-1 col-2}

And, as only one row it to be added, this list forms a single entry if the list of rows.

{{col-1 col-2}}

If the data entries contains white space, then these would need to be surrounded by braces or quotes. So,

{{{col 1}  {col 2}}}

Is the same as:

{{"col 1" "col 2"}}

Just to prove the point, lets add two rows.

{ {{r1c1} {r1c2}} {{r2c1} {r2c2}}}


All this single line bracing, especially with empty fields,  has just been something to capture the imagination. The previous line could also have been written much more clearly as:

{
{ {r1c1} {r1c2} }
{ {r2c1} {r2c2} }
}

So, we can now see, that 

{{{} {}}}

Is nothing other than:

{

{{} {}}

}

The addition of empty cells into 1 row, with 2 columns.




Autocorrection, string swapping and balancing quotations in gnocl::text widgets.

Although the basic GtkTextView is a lightweight plain vanilla text editing widget, it can be spiced up to do more interesting things, operations that would normally be expected in a word processing application. It is possible to embed such larger editors into a Gtk window, and the legacy binding to the Abiwidget is an example of that. Using such objects comes with the caveat that the widget is effectively an app within an app, rather than a component.

The gnocl::text object has three options, -balanceQuotes, -swap and -corrections which pushes the uses of the widget towards creative writing rather than just editing a simple text file. 

All three options work in connection with the widget's 'key-release-event' signal to analyse the text buffer contents adjacent to the insert cursor. Setting the -balanceQuotes option to 1 will result in the any " or ' becoming modified to single or double open quotes dependent upon leading or trailing characters. It also enables the correct insertion of apostrophe's in the creation of English possessives.

The -swap option accepts an even list of char mappings resulting in substitution taking place at the point of insertion. Although IBUS allows switching between input methods, and character map applications allow specific glyphs to be inserted, these can be cumbersome or inconvenient. Character mapping allows convenient changes to be made by the user, during runtime.

At a more targeted way -corrections options allows whole words to be swap whist typing. This is useful to ensure the correct application of cumbersome to remember diacritics or where an acronym or abbreviation can be fully expanded.

For example:

$txt configure -balanceQuotes 1

$txt configure -swap {
        aa ā
        ii ī
        ^o ô
        ;s ś
        .h ḥ }
 

$txt configure -corrections {
        maha māha
        mudra mūdra
        Avalokiteshvara Avalôkiteśvara
        prajna prajñā
        AAPP {astasahasrika prajanparamita sutra}
        SDPS {sadharma pundarika sutra}
        }

Other uses for this functionality includes user-defined active spelling checking.


 

Saturday, January 02, 2021

January 2021 Update

From the coding point of view December was a very busy month. Lots of updates in terms of fixes and the introduction of extra functionality. See the notes below. Another useful change was the ability to download stable versions of gnocl directly from the main website.

What, however, will the new year bring? I've already begun the process of integrating support for the canvas into main core, it makes sense, especially if the creation of graphics is needed. Once done, I'll take a look at integrating some the functionality from the other legacy modules. With that done, perhaps its time for a version increment, perhaps to 1.0 at long last!

'Why, hasn't it happened already?' one might ask. In short, all the additional work needed to update the online documentation and creating a comprehensive demonstration application. This is largely done now, especially with the internal help functionality added to the core.

Just to show that the gnocl::canvas is now up and running, here's that old familiar screenshot on 0.9.96.

 
 

   gnocl::selection
      o new command, retrieve currently selected text on display.
    gnocl::button, gnocl::toolbar button
      o -onClicked has new substitution string, %s, the currently selected text.
    gnocl::text
      o some minor bug fixes.
    gnocl::dialog
      o new option -showHelp, tidied up code.
    gnocl::colorSelectionDialog
      o -title now works (can override locale settings)
      o new option -showHelp, show help button,
        OK - returns colours values: R,G,B,a. range 0-65535.
        Cancel - empty string
        Help - returns "HELP"
    Legacy support for deprecated Gtk+ widgets now removed.
    The following have been removed completely from the Gnocl C-sources.
        gnocl::curve
        gnocl::gammaCurve
        gnocl::ruler
    Whereas the following commands will treated as synonymns
        gnocl::about - gnocl::aboutDialog
        gnocl::fileSelection - gnocl::fileChooserDialog
        gnocl::optionMenu - gnocl::comboBox
        gnocl::combo - gnocl::comboEntry
    gnocl::fileSelection
      o options -parent and -icon.
    gnocl::scale
      o -data option now works correctly.
    gnocl::inventory
      o crash fixed.
    gnocl::fileChooserButton
      o -onFileSet %F substitution string changed to %u.
    gnocl::folderChooserButton
      o -onFolderSet now works, responds to "selection-changed" signal.
    gnocl::fontButton
      o new option -borderwidth
    gnocl::colorButton
      o new option -borderwidth