added new and experimental doc-strings + minor fixes and cleanup...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2017-01-18 00:56:08 +03:00
parent b2044eb7a1
commit b58b583995
3 changed files with 202 additions and 135 deletions

View File

@ -349,11 +349,61 @@ module.Util = ImageGridFeatures.Feature({
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Introspection... // Introspection...
// Normalize doc strings...
//
// This will remove indent padding from all lines in a doc string.
//
// This is useful for documenting actions using ES6 template/multi-line
// strings and keep them sane in terms of indent...
//
// Example:
// someAction: ['Test/Some action title',
// doc`This is an example...
// mult-iline...
// ...doc string that will be normalized and look the same but`
// without the indent...`,
// function(){ ... }]
//
// NOTE: this will ignore the first line's indent so it can be started
// right at the string start.
var doc =
module.doc =
function(strings, ...values){
var lines = strings
.map(function(s, i){ return s + (values[i] || '') })
.join('')
.split(/\n/g)
// get the common whitespae offset...
var l = -1
lines.forEach(function(line, i){
if(line.trim().length == 0){
return
}
// get the indent...
var a = line.length - line.trimLeft().length
// if line 0 is not indented, ignore it...
if(i == 0 && a == 0){
return
}
l = l < 0 ? a : Math.min(l, a)
})
return lines
.map(function(line, i){ return i == 0 ? line : line.slice(l) })
.join('\n')
}
// Indicate that an action is not intended for direct use... // Indicate that an action is not intended for direct use...
// //
// NOTE: this will not do anything but mark the action. // NOTE: this will not do anything but mark the action.
var notUserCallable = var notUserCallable =
module.notUserCallable = function(func){ module.notUserCallable =
function(func){
func.__not_user_callable__ = true func.__not_user_callable__ = true
return func return func
} }
@ -368,10 +418,9 @@ var IntrospectionActions = actions.Actions({
// check if action is callable by user... // check if action is callable by user...
isUserCallable: ['- System/', isUserCallable: ['- System/',
doc`Test if an action is used callable.`,
actions.doWithRootAction(function(action){ actions.doWithRootAction(function(action){
return action.__not_user_callable__ != true })], return action.__not_user_callable__ != true })],
}) })

View File

@ -393,6 +393,8 @@ module.GLOBAL_KEYBOARD2 = {
/*********************************************************************/ /*********************************************************************/
// XXX add loading/storing of kb bindings... // XXX add loading/storing of kb bindings...
// XXX experimenting with new style of doc strings, usable from the
// system... (for details see: core.doc)
var KeyboardActions = actions.Actions({ var KeyboardActions = actions.Actions({
config: { config: {
@ -429,9 +431,8 @@ var KeyboardActions = actions.Actions({
get keyboard(){ get keyboard(){
return this.__keyboard_object }, return this.__keyboard_object },
// Self-test action...
testKeyboardDoc: ['- Interface/', testKeyboardDoc: ['- Interface/',
core.doc`Self-test action...`,
{self_test: true}, {self_test: true},
function(){ function(){
var that = this var that = this
@ -471,12 +472,10 @@ var KeyboardActions = actions.Actions({
// Key bindings --------------------------------------------------- // Key bindings ---------------------------------------------------
// XXX need a clean deep copy to restore... // XXX need a clean deep copy to restore...
resetKeyBindings: ['Interface/Restore default key bindings', resetKeyBindings: ['Interface/Restore default key bindings',
function(){ function(){
thiis.__keyboard_config = GLOBAL_KEYBOARD }], thiis.__keyboard_config = GLOBAL_KEYBOARD }],
keyHandler: ['- Interface/Get or set key handler', keyHandler: ['- Interface/Get or set key handler',
function(mode, key, action){ function(mode, key, action){
var res = this.keyboard.handler(mode, key, action) var res = this.keyboard.handler(mode, key, action)
@ -485,24 +484,24 @@ var KeyboardActions = actions.Actions({
return res return res
} }
}], }],
// Get normalized, flat set of actions and keys that trigger them...
//
// Format:
// {
// <action>: [
// <key>,
// ...
// ],
// ...
// }
//
// NOTE: this does not check overloading between modes i.e. if two
// actions in two different modes are bound to the same key
// only one is shown...
// XXX is this a bug???
// ...at this point can't find when this produces inconsistencies...
getKeysForAction: ['- Interface/', getKeysForAction: ['- Interface/',
core.doc`Get normalized, flat set of actions and keys that trigger them...
Format:
{
<action>: [
<key>,
...
],
...
}
NOTE: this does not check overloading between modes i.e. if two
actions in two different modes are bound to the same key
only one is shown...
XXX is this a bug???
...at this point can't find when this produces inconsistencies...
`,
function(actions, modes){ function(actions, modes){
var that = this var that = this
var res = {} var res = {}
@ -560,25 +559,25 @@ var KeyboardActions = actions.Actions({
// keyboard handling ---------------------------------------------- // keyboard handling ----------------------------------------------
// Handle key / keyboard event...
//
// Handle key...
// .keyPress(<key>)
//
// Handle key and call func if key is not bound...
// .keyPress(<key>, <func>)
//
// Handle key event...
// .keyPress(<event>)
//
// Handle key and call func if key is not bound...
// .keyPress(<event>, <func>)
//
//
// NOTE: care must be taken when using or binding to this (especially
// the .pre stage) as this may introduce a lag into user input.
keyPress: ['- Interface/Handle key or keyboard event', keyPress: ['- Interface/Handle key or keyboard event',
core.doc`Handle key / keyboard event...
Handle key...
.keyPress(<key>)
Handle key and call func if key is not bound...
.keyPress(<key>, <func>)
Handle key event...
.keyPress(<event>)
Handle key and call func if key is not bound...
.keyPress(<event>, <func>)
NOTE: care must be taken when using or binding to this (especially
the .pre stage) as this may introduce a lag into user input.
`,
{ keepDialogTitle: true }, { keepDialogTitle: true },
function(key, no_match){ function(key, no_match){
var that = this var that = this
@ -634,7 +633,6 @@ var KeyboardActions = actions.Actions({
// XXX not sure if this is the right way to go... // XXX not sure if this is the right way to go...
return res return res
}], }],
toggleKeyboardHandling: ['- Interface/Keyboard handling', toggleKeyboardHandling: ['- Interface/Keyboard handling',
toggler.Toggler(null, function(_, state){ toggler.Toggler(null, function(_, state){
var that = this var that = this
@ -724,87 +722,85 @@ var KeyboardActions = actions.Actions({
} }
}, },
['on', 'off'])], ['on', 'off'])],
pauseKeyboardRepeat: ['- Interface/Drop keys until none are pressed for a timout',
core.doc`Drop keys until non are pressed for a timeout...
// Drop keys until non are pressed for a timeout... This is useful for stopping repeating (held down) keys after some
// event.`,
// This is useful for stopping repeating (held down) keys after some
// event.
pauseKeyboardRepeat: ['- Interface/',
function(){ this.__keyboard_repeat_paused = true }], function(){ this.__keyboard_repeat_paused = true }],
// Interface stuff ------------------------------------------------ // Interface stuff ------------------------------------------------
// Keyboard bindings viewer...
//
// options format:
// {
// // Classes to add to the dialog...
// cls: 'edit',
//
// // If true, show non-actions in the list...
// // This would include:
// // - aliases
// // - special handlers (like: DROP, NEXT, ...)
// // - actions of features not loaded or not available
// show_non_actions: false,
//
// // If true will show the placeholder text in sections that
// // contain no mappings...
// //
// // This can also be a string, which will be shown as empty
// // section text.
// empty_section_text: true,
//
// // Function used to get/generate text to represent an action
// // in the list.
// //
// // If not defined or false action doc will be used if
// // available.
// get_key_text: <function>,
//
//
// // Button structures for different sections...
// //
// // All of these must confirm to the lib/widget/browse buttons
// // format:
// // {
// // [<html>: <func>],
// // ...
// // }
// //
// // (see: browse.Browser.update(..) doc for more info)
// //
// // Mode section title...
// mode_buttons: <buttons>,
//
// // Mode actions...
// //
// // If false or undefined the element will not be shown.
// //
// // NOTE: these are shown at the end of a section.
// mode_actions: <buttons>,
//
// // Key binding buttons...
// key_buttons: <buttons>,
//
// // Dropped key list buttons...
// drop_buttons: <buttons>,
// }
//
// NOTE: this is designed to be a viewer by default but provide enough
// configurability to support editing without actually including
// any editing mechanics.
// This should separate the editing mechanics from the actual
// view layout while at the same time keeping it consistent.
// The main drawback could be that this will complicate the
// layout development until (if) it stabilizes.
//
// XXX path parameter is not used...
// XXX BUG sections with doc do not show up in title... // XXX BUG sections with doc do not show up in title...
// XXX slow on update... // XXX slow on update...
// XXX sub-group by path (???) // XXX sub-group by path (???)
browseKeyboardBindings: ['Interface|Help/Keyboard bindings...', browseKeyboardBindings: ['Interface|Help/Keyboard bindings...',
core.doc`Keyboard bindings viewer...
options format:
{
// Classes to add to the dialog...
cls: 'edit',
// If true, show non-actions in the list...
// This would include:
// - aliases
// - special handlers (like: DROP, NEXT, ...)
// - actions of features not loaded or not available
show_non_actions: false,
// If true will show the placeholder text in sections that
// contain no mappings...
//
// This can also be a string, which will be shown as empty
// section text.
empty_section_text: true,
// Function used to get/generate text to represent an action
// in the list.
//
// If not defined or false action doc will be used if
// available.
get_key_text: <function>,
// Button structures for different sections...
//
// All of these must confirm to the lib/widget/browse buttons
// format:
// {
// [<html>: <func>],
// ...
// }
//
// (see: browse.Browser.update(..) doc for more info)
//
// Mode section title...
mode_buttons: <buttons>,
// Mode actions...
//
// If false or undefined the element will not be shown.
//
// NOTE: these are shown at the end of a section.
mode_actions: <buttons>,
// Key binding buttons...
key_buttons: <buttons>,
// Dropped key list buttons...
drop_buttons: <buttons>,
}
NOTE: this is designed to be a viewer by default but provide enough
configurability to support editing without actually including
any editing mechanics.
This should separate the editing mechanics from the actual
view layout while at the same time keeping it consistent.
The main drawback could be that this will complicate the
layout development until (if) it stabilizes.
`,
widgets.makeUIDialog(function(path, options){ widgets.makeUIDialog(function(path, options){
options = options || {} options = options || {}
@ -812,19 +808,20 @@ var KeyboardActions = actions.Actions({
var keybindings = this.keybindings var keybindings = this.keybindings
var kb = this.keyboard var kb = this.keyboard
var keys = kb.keys('*')
// get doc... // get doc...
var getKeyText = options.get_key_text var getKeyText = options.get_key_text === undefined ?
|| function(action){ function(action){
var doc = action.doc ? action.doc var doc = action.doc ? action.doc
: action.action in this ? this.getDocTitle(action.action) : action.action in this ? this.getDocTitle(action.action)
: action.action : action.action
return doc.length == 0 ? action.action : doc return doc.length == 0 ? action.action : doc
} }
: options.get_key_text
var dialog = browse.makeLister(null, var dialog = browse.makeLister(null,
function(path, make){ function(path, make){
var keys = kb.keys('*')
Object.keys(keybindings) Object.keys(keybindings)
.forEach(function(mode){ .forEach(function(mode){
var dropped = keybindings[mode].drop || [] var dropped = keybindings[mode].drop || []
@ -996,6 +993,9 @@ var KeyboardActions = actions.Actions({
// keyboard??? // keyboard???
// XXX BUG: for some reason modes are unclickable... // XXX BUG: for some reason modes are unclickable...
editKeyboardBindings: ['Interface/Keyboard bindings editor...', editKeyboardBindings: ['Interface/Keyboard bindings editor...',
core.doc`Similar to .browseKeyboardBindings(..) but adds editing functionality...
For more details see: .browseKeyboardBindings(..)`,
widgets.uiDialog(function(path){ widgets.uiDialog(function(path){
var that = this var that = this
var bindings = this.keybindings var bindings = this.keybindings
@ -1021,6 +1021,7 @@ var KeyboardActions = actions.Actions({
cls: 'edit', cls: 'edit',
show_non_actions: true, show_non_actions: true,
empty_section_text: false, empty_section_text: false,
get_key_text: false,
// mode... // mode...
mode_buttons: [ mode_buttons: [
@ -1116,17 +1117,10 @@ var KeyboardActions = actions.Actions({
sub_dialog sub_dialog
&& sub_dialog && sub_dialog
// XXX for some magical reason this is triggered BEFORE .close(function(){ dialog.update() })
// the base event handler...
// ...seems that there's an async something hidden
// in the middle, need to check this! (XXX)
//.close(function(){ dialog.update() })
.close(function(){
setTimeout(function(){ dialog.update() }, 0) })
}) })
return dialog return dialog
})], })],
// XXX need a way to abort edits... // XXX need a way to abort edits...
editKeyBinding: ['- Interface/Key mapping...', editKeyBinding: ['- Interface/Key mapping...',
widgets.makeUIDialog(function(mode, code){ widgets.makeUIDialog(function(mode, code){
@ -1137,6 +1131,7 @@ var KeyboardActions = actions.Actions({
keys = mode in keys ? keys = mode in keys ?
(keys[mode][code] || []) (keys[mode][code] || [])
: [] : []
var orig_keys = keys.slice()
var dialog = browse.makeLister(null, var dialog = browse.makeLister(null,
function(path, make){ function(path, make){
@ -1147,8 +1142,6 @@ var KeyboardActions = actions.Actions({
make('---') make('---')
var to_remove = []
make.EditableList(keys) make.EditableList(keys)
make('---') make('---')
@ -1162,8 +1155,22 @@ var KeyboardActions = actions.Actions({
cls: 'metadata-view', cls: 'metadata-view',
}) })
// save the keys... // save the keys...
// XXX at this point this does not account for changes
// in mode or code...
.on('close', function(){ .on('close', function(){
// XXX // remove keys...
orig_keys
.filter(function(k){ return keys.indexOf(k) < 0 })
.forEach(function(k){
that.keyHandler(mode, k, '')
})
// add keys...
keys
.filter(function(k){ return orig_keys.indexOf(k) < 0 })
.forEach(function(k){
that.keyHandler(mode, k, code)
})
}) })
return dialog return dialog
@ -1199,7 +1206,7 @@ var KeyboardActions = actions.Actions({
return dialog return dialog
})], })],
// XXX revise... // XXX revise:
// - '*' toggle // - '*' toggle
// - done/cancel // - done/cancel
editKeyboardModeDroppedKeys: ['- Interface/Dropped keys...', editKeyboardModeDroppedKeys: ['- Interface/Dropped keys...',
@ -1327,9 +1334,11 @@ module.Keyboard = core.ImageGridFeatures.Feature({
} }
}], }],
/*
['keyHandler', ['keyHandler',
function(res, mode, key, action){ function(res, mode, key, action){
action && this.checkKeyboardDoc() }], action && this.testKeyboardDoc() }],
//*/
], ],
}) })

View File

@ -127,20 +127,27 @@ function(text, options){
// XXX // XXX
Items.Selectable = Items.Selectable =
function(text, options){ function(text, options){
// XXX
} }
// make Editable on select element... // make Editable on select element...
// //
// options format: // options format:
// { // {
// // show as action (via. .Action(..))
// action: <bool>,
//
// // If true, clear text when item is selected...
// clear_on_edit: true, // clear_on_edit: true,
// //
// editaborted: // // Called when editing is abrted...
// editdone: // editaborted: <func>,
// //
// action: <bool>, // // Called when editing is done...
// editdone: <func>,
//
// ...
// } // }
// XXX
Items.Editable = Items.Editable =
function(text, options){ function(text, options){
options = options || {} options = options || {}
@ -171,11 +178,13 @@ function(text, options){
// XXX // XXX
Items.SelectableField = Items.SelectableField =
function(text, options){ function(text, options){
// XXX
} }
// XXX // XXX
Items.EditableField = Items.EditableField =
function(text, options){ function(text, options){
// XXX
} }