Skip to content

bt-gui

[module] bt-gui

Bintracker GUI abstractions.

Global Actions

[procedure] (update-window-title!)

update window title by looking at current file name and 'modified' property

[procedure] (do-proc-with-exit-dialogue DIALOGUE-STRING PROC)

If there are unsaved changes to the current module, ask user if they should be saved, then execute the procedure PROC unless the user cancelled the action. With no unsaved changes, simply execute PROC.

[procedure] (exit-bintracker)

Shut down the running application.

[variable] on-close-file-hooks

default:

(make-hooks
     `(delete-module-view . ,(lambda () (multibuffer-delete (ui) 'module-view)))
     `(show-welcome-buffer . ,(lambda () (multibuffer-show (ui) 'welcome)))
     `(update-window-title . ,update-window-title!))

[procedure] (close-file)

Close the currently opened module file.

[variable] after-load-file-hooks

default:

(make-hooks
     `(hide-welcome-buffer . ,(lambda args (multibuffer-hide (ui) 'welcome)))
     `(show-module
       . ,(lambda (mmod filename)
        (multibuffer-add (ui)
                 `(module-view #t 5 ,<ui-module-view>
                       mmod ,mmod filename ,filename)
                 before: 'repl)))
     `(focus-first-block
       . ,(lambda args
        (and-let* ((entry (find (lambda (entry)
                      (symbol-contains (car entry)
                               "block-view"))
                    (focus 'list))))
          (focus 'set (car entry))))))

[procedure] (load-file)

Prompt the user to load an MDAL module file.

[procedure] (create-new-module MDEF-NAME)

[variable] new-file-dialog

default:

(make <ui-dialog>
      'title "Select Engine"
      'children
      `((header ,<ui-wrapper> setup
        ((lbl1 label text: "Platform")
         (platform-selector combobox state: readonly)))
    (sf ,<ui-wrapper> setup
        ((mdef-selector treeview columns: (Name Version Platform)
                show: tree selectmode: browse))
        yscroll #t)
    (df ,<ui-wrapper> setup
        ((description text takefocus: 0 state: disabled bd: 0
              highlightthickness: 0 height: 10 wrap: word))
        yscroll #t))
      'traverse '(mdef-selector platform-selector)
      'initializers
      (make-hooks
       `(configure-text-style
     .
     ,(lambda ()
        ((ui-ref new-file-dialog 'description) 'configure
         bg: (colors 'background) fg: (colors 'text)
         font: (list family: (settings 'font-mono)
              size: (settings 'font-size)))))
       `(list-platforms
     .
     ,(lambda ()
        (let ((selected-pf (tk-var "selectedplatform")))
          ((ui-ref new-file-dialog 'platform-selector)
           'configure values: (cons "any" (btdb-list-platforms))
           textvariable: selected-pf)
          (tk-set-var! "selectedplatform" "any"))))
       `(list-mdefs
     .
     ,(lambda ()
        (for-each (lambda (mdef)
            ((ui-ref new-file-dialog 'mdef-selector)
             'insert '{} 'end text: (car mdef)
             values: (list (cadr mdef) (third mdef))))
              ;; TODO btdb-list-mdefs should always return a list!
              (btdb-list-mdefs))))
       `(do-bindings
     .
     ,(lambda ()
        (let* ((platform-selector (ui-ref new-file-dialog
                          'platform-selector))
           (mdef-selector (ui-ref new-file-dialog 'mdef-selector))
           (description-widget (ui-ref new-file-dialog 'description))
           (get-item-list (lambda ()
                    (string-split
                     (string-delete
                      (string->char-set "{}")
                      (->string
                       (mdef-selector 'children '{})))))))
          (tk/bind platform-selector
               (inverse-key-binding 'global 'where)
               (lambda () (say "platform selection")))
          (tk/bind platform-selector
               (inverse-key-binding 'global 'what)
               (lambda () (say (tk-get-var "selectedplatform"))))
          (tk/bind mdef-selector
               (inverse-key-binding 'global 'where)
               (lambda () (say "engine selection")))
          (tk/bind mdef-selector
               (inverse-key-binding 'global 'what)
               (lambda ()
             (let ((selected-engine
                     (mdef-selector
                      'item (mdef-selector 'selection) text:)))
               (say (string-append
                 selected-engine
                 " for "
                 (btdb-get-mdef-platform
                  (string->symbol selected-engine)))))))
          (tk/bind
           platform-selector
           '<<ComboboxSelected>>
           (lambda ()
         (let ((selected-platform
            (string->symbol (tk-get-var "selectedplatform"))))
           (mdef-selector 'delete (get-item-list))
           (for-each (lambda (mdef)
                   (mdef-selector 'insert '{} 'end
                          text: (car mdef)
                          values: (list (cadr mdef)
                                (third mdef))))
                 (btdb-list-mdefs selected-platform))
           (tk/update 'idletasks)
           (mdef-selector 'focus (car (get-item-list)))
           (mdef-selector 'selection 'set
                  (list (car (get-item-list)))))))
          (tk/bind
           mdef-selector
           '<<TreeviewSelect>>
           ;; TODO this fails when selection was set automatically,
           ;; because Tk delays execution of the selection too long.
           ;; Calling tk/update or tk/update 'idletasks hangs the app.
           ;; For now, use tk/after 100 as a (very brittle) work-around.
           ;; Update: Seems fairly stable now with forcing a tk/update
           ;; 'idletasks in the ComboboxSelect event above. Still fails
           ;; without a delay though.
           (lambda ()
             (tk/after
              20
              (lambda ()
                (let* ((selected-engine
                    (string->symbol
                     (mdef-selector
                      'item (mdef-selector 'selection) text:)))
                   (description (->string (btdb-get-mdef-description
                               selected-engine))))
                  (description-widget 'configure state: 'normal)
                  (description-widget 'delete "0.0" 'end)
                  (description-widget 'insert 'end description)
                  (description-widget 'configure state: 'disabled))))))))))
      'finalizers
      (make-hooks
       `(ex
     .
     ,(lambda a
        (and-let*
        ((mdef-selector (ui-ref new-file-dialog 'mdef-selector))
         (item-list (string-split
                 (string-delete
                  (string->char-set "{}")
                  (->string (mdef-selector 'children '{})))))
         (_ (not (null? item-list)))
         (selected-def (mdef-selector 'item (mdef-selector 'focus)
                          text:)))
          (create-new-module (if (string-null? selected-def)
                     (mdef-selector 'item (car item-list)
                            text:)
                     selected-def)))))))

[procedure] (new-file)

[variable] on-save-file-hooks

default:

(make-hooks
     `(write-file
       . ,(lambda ()
        (mmod->file (ui-metastate (current 'module-view) 'mmod)
            (ui-metastate (current 'module-view) 'filename))
        (ui-metastate (current 'module-view) 'modified #f)))
     `(update-window-title . ,update-window-title!))

[procedure] (save-file)

Save the current MDAL module. If no file name has been specified yet, promt the user for one.

[procedure] (save-file-as)

Save the current MDAL module under a new, different name.

[procedure] (export-asm)

[procedure] (export-bin)

[procedure] (undo)

Calls undo on (current 'module-view).

[procedure] (redo)

Calls redo on (current 'module-view).

[procedure] (launch-help)

Launch the online help in the user's default system web browser.

Playback

[procedure] (play-from-start)

[procedure] (play-pattern)

[procedure] (stop-playback)

GUI Elements

A collection of classes and methods that make up Bintracker's internal GUI structure. All UI classes are derived from <ui-element>. The OOP system used is coops.

[procedure] (ui-eval-layout-expression EXPR)

"Evaluate" a GUI layout expression (as used in config/config.scm) by replacing class names with class instances. Note that this procedure is not recursive, ie. you cannot use it to create nested layouts.

Auxilliary procedures used by various BT meta-widgets

[procedure] (value-display-size COMMAND-CONFIG)

Determine how many characters are needed to print values of a given command.

[procedure] (replace-digit VAL DIGIT-IDX KEYSYM)

Takes the Tk keypress symbol KEYSYM and interprets it as a digit taking the nth postion in the integer VAL, using a radix corresponding to the result of (settings 'number-base). DIGIT-IDX is the digit position index.

[procedure] (replace-modifier-digit VAL DIGIT-IDX KEYSYM)

Takes the Tk keypress symbol KEYSYM and interprets it as a digit taking the nth postion in the modifier command value VAL, using a radix corresponding to the result of (settings 'number-base) for the integer part. DIGIT-IDX is the digit position index (right to left) or -1 for the prefix part.

[procedure] (normalize-field-value VAL FIELD-ID MDEF)

Transform an ifield value from MDAL format to tracker display format. Replaces empty values with dots, changes numbers depending on number format setting, and turns everything into a string.

[procedure] (get-field-color-tag FIELD-ID MDEF)

Get the color tag asscociated with the field's command type.

[procedure] (get-field-color FIELD-ID MDEF)

Get the RGB color string associated with the field's command type.

[procedure] (keypress->note KEY BASE-OCTAVE)

Convert a keysym (as returned by a tk-event %K placeholder) to an MDAL note name.

[procedure] (get-command-type-tag FIELD-ID MDEF)

Get the appropriate command type tag to set the item color.

[procedure] (node-id-abbreviate ID LEN GROUP-ID)

Generate an abbrevation of LEN characters from the given MDAL inode identifier ID, where GROUP-ID is the parent group node identifier. Returns the abbrevation as a string. The string is padded to LEN characters if necessary.

Block View Field Configurations

[record] bv-field-config

[constructor] (make-bv-field-config #!key TYPE-TAG WIDTH CURSOR-WIDTH CURSOR-DIGITS)
[predicate] bv-field-config?
implementation: defstruct

field getter setter type
type-tag bv-field-config-type-tag bv-field-config-type-tag-set! symbol
width bv-field-config-width bv-field-config-width-set! fixnum
cursor-width bv-field-config-cursor-width bv-field-config-cursor-width-set! fixnum
cursor-digits bv-field-config-cursor-digits bv-field-config-cursor-digits-set! fixnum

A record type used internally by and its descendants.

[procedure] (field-id->cursor-size FIELD-ID MDEF)

Returns the number of characters that the blockview cursor should span for the given field-id.

[procedure] (field-id->cursor-digits FIELD-ID MDEF)

Returns the number of cursor positions for the the field node field-id. For fields that are based on note/key/ukey commands, the result will be one, otherwise it will be equal to the number of characters needed to represent the valid input range for the field's source command.

[procedure] (blockview-make-field-configs BLOCK-IDS FIELD-IDS MDEF)

Generate the alist of bv-field-configs.

Bintracker-specific UI Classes

[class] <ui-welcome-buffer>

inherits from: <ui-element>

slot initform
ui-zone (gensym 'welcome)
packing-args '(expand: 1 fill: both)
focus-controller focus
buttons '()
commands `(,new-file ,load-file ,launch-help)
where "welcome buffer"

A welcome screen with two buttons for creating and opening an MDAL module, respectively. Create instances with (make <ui-welcome-buffer>).

[method] (initialize-instance after: (BUF <ui-welcome-buffer>))

[method] (ui-show before: (BUF <ui-welcome-buffer>))

[method] (ui-hide after: (BUF <ui-welcome-buffer>))

[method] (ui-focus primary: (BUF <ui-welcome-buffer>))

[method] (ui-what primary: (BUF <ui-welcome-buffer>))

[class] <ui-repl>

inherits from: <ui-buffer>

slot initform accessor
ui-zone (gensym 'repl)
focus-controller focus
repl
yscroll #f
prompt "repl> "
history '() repl-history
history-pointer 0
where "read eval print loop"

A class representing a read-evaluate-print-loop prompt. 'setup shall be the initial text to display on the prompt. To register the widget as focussable in the Bintracker main UI, specify a ui-zone identifier as initform to 'ui-zone. The methods repl-clear, repl-insert, and repl-get are provided for interaction with the prompt.

[method] (initialize-instance after: (BUF <ui-repl>))

[method] (ui-show before: (BUF <ui-repl>))

[method] (ui-hide after: (BUF <ui-repl>))

[method] (ui-destroy before: (BUF <ui-repl>))

[method] (ui-collapse before: (BUF <ui-repl>))

[method] (ui-expand before: (BUF <ui-repl>))

[method] (repl-modify-default-events primary: (BUF <ui-repl>))
Protect the prompt string by applying various tweaks to the standard event handlers of Tk text widgets.

[method] (repl-insert primary: (BUF <ui-repl>) STR)
Insert STR at the end of the prompt of the <ui-repl> instance BUF.

[method] (repl-insert-prompt primary: (BUF <ui-repl>))

[method] (repl-clear primary: (BUF <ui-repl>))
Clear the prompt of the <ui-repl> instance BUF.

[method] (repl-get primary: (BUF <ui-repl>) #!rest ARGS)
Get the text contents of the <ui-repl> instance BUF. The remaining args are evaluated as arguments to Tk:Text 'get. See Tk manual page.

[method] (repl-insert-from-history primary: (BUF <ui-repl>) DIRECTION)

[method] (repl-eval primary: (BUF <ui-repl>))
Evaluate the latest command that the user entered into the repl prompt.

[method] (ui-focus primary: (BUF <ui-repl>))

Module View Widgets

The following classes are the components used to construct a graphical representation of an MDAL module (MMOD). The <ui-module-view> class defined at the end of this section combines these to create a display metabuffer of the module, and manage its state.

Given a class instance of any of these module view components (or an instance of the module view itself, you can interact with the (parent) module state through the ui-metastate method (see below).

You normally do not need to create instances of the child components yourself. If you do construct your own instances, then you must already have constructed a <ui-module-view>, and pass the value of its metastate-accessor slot to the constructor of the child component.

[class] <ui-group-field>

inherits from: <ui-element>

slot initform
label
entry
node-id (error '|make <ui-group-field>| "Missing 'node-id.")
parent-instance-path (error '|make <ui-group-field>| "Missing 'parent-instance-path.")
metastate-accessor (error '|make <ui-group-field>| "Missing 'metastate-accessor")
packing-args '(expand: 0 fill: x)

A widget representing an MDAL group field instance. Create instances of this class with

(make <ui-group-field>
      'node-id ID
      'parent-instance-path PATH
      'metastate-accessor ACCESSOR)

where ID is an MDAL field node identifier in the parent MMOD, and PATH is an MDAL node path string valid for (ACCESSOR 'mmod). where ID is an MDAL field node identifier, PATH is an MDAL node path string pointing to the parent group node instance, and ACCESSOR is a metastate accessor procedure as described in the` documentation below.

[method] (initialize-instance after: (BUF <ui-group-field>))

[method] (ui-group-field-perform-edit primary: (BUF <ui-group-field>) ACTION)

[method] (ui-group-field-update-value primary: (BUF <ui-group-field>))

[method] (edit primary: (BUF <ui-group-field>) WHAT #!optional VAL)

[method] (ui-metastate primary: (BUF <ui-group-field>) #!rest ARGS)
See <ui-module-view> below.

[method] (ui-focus primary: (BUF <ui-group-field>))

[method] (ui-unfocus primary: (BUF <ui-group-field>))

[class] <ui-group-fields>

inherits from: <ui-buffer>

slot initform
ui-zone (gensym 'group-fields)
focus-controller focus
group-id (error '|make <ui-group-fields>| "Missing 'group-id.")
parent-instance-path (error '|make <ui-group-fields>| "Missing 'parent-instance-path.")
metastate-accessor (error '|make <ui-group-fields>| "Missing 'metastate-accessor.")
active-index 0
packing-args '(expand: 0 fill: x)

A wrapper for the group field nodes of an MDAL group instance. Create instances of this class with

(make <ui-group-fields>
      'group-id ID
      'parent-instance-path PATH
      'metastate-accessor ACCESSOR)

where ID is the MDAL node identifier of the parent group node, PATH is an MDAL node path string pointing to the parent group node instance, and ACCESSOR is a metastate accessor procedure as described in the <ui-module-view> documentation below.

[method] (initialize-instance after: (BUF <ui-group-fields>))

[method] (ui-metastate primary: (BUF <ui-group-fields>) #!rest ARGS)

[method] (ui-get-focus-zones primary: (BUF <ui-group-fields>))

[method] (ui-show after: (BUF <ui-group-fields>))

[method] (ui-hide after: (BUF <ui-group-fields>))

[method] (ui-destroy before: (BUF <ui-group-fields>))

[method] (ui-focus primary: (BUF <ui-group-fields>))

[method] (ui-unfocus primary: (BUF <ui-group-fields>))

[method] (ui-update primary: (BUF <ui-group-fields>))

[class] <ui-basic-block-view>

inherits from: <ui-buffer><ui-selectable>

slot initform
ui-zone
focus-controller focus
group-id (error '|make <ui-basic-block-view>| "Missing 'group-id.")
parent-instance-path (error '|make <ui-basic-block-view>| "Missing 'parent-instance-path.")
metastate-accessor (error '|make <ui-basic-block-view>| "Missing 'metastate-accessor.")
field-ids
field-configs
hidden-fields '()
header-frame
content-frame
rownum-frame
rownum-header
rownums
block-frame
block-header
block-content
xscroll #f
yscroll #f
item-cache '()
collapsible #f
packing-args '(expand: 0 fill: both)

Abstract base class for <ui-block-view> and <ui-order-view>, implementing shared code for these two classes. You most likely do not need to construct an instance of this class directly. However, consider deriving from this class if you want to implement an alternative representation of the block node members of an MDAL group node.

[method] (initialize-instance after: (BUF <ui-basic-block-view>))

[method] (ui-show before: (BUF <ui-basic-block-view>))

[method] (ui-hide after: (BUF <ui-basic-block-view>))

[method] (ui-destroy before: (BUF <ui-basic-block-view>))

[method] (ui-what primary: (BUF <ui-basic-block-view>))

[method] (ui-metastate primary: (BUF <ui-basic-block-view>) #!rest ARGS)

[method] (ui-blockview-parent-instance primary: (BUF <ui-basic-block-view>))

[method] (ui-blockview-add-type-tags primary: (BUF <ui-basic-block-view>) ROW #!optional (TEXTGRID (slot-value buf 'block-content)))
Map type tags to the field columns of a textgrid. This can be used either on block-header, or on block-content slots.

[method] (ui-blockview-values->string primary: (BUF <ui-basic-block-view>) VALUES)
Convert the list of row VALUES into a string that can be inserted into the blockview's content-grid or header-grid. Each entry in VALUES must correspond to a field column in the blockview's content-grid.

[method] (ui-blockview-mark->position primary: (BUF <ui-basic-block-view>) MARK)
Returns the position of the Tk text widget MARK as a list containing the row in car, and the character position in cadr. Row position is adjusted to 0-based indexing.

[method] (ui-blockview-get-cursor-position primary: (BUF <ui-basic-block-view>))
Returns the current cursor position as a list containing the row in car, and the character position in cadr. Row position is adjusted to 0-based indexing.

[method] (ui-blockview-get-current-row primary: (BUF <ui-basic-block-view>))
Returns the current row, ie. the row that the cursor is currently on.

[method] (ui-blockview-get-current-field-id primary: (BUF <ui-basic-block-view>))
Returns the field ID that the cursor is currently on.

[method] (ui-blockview-get-current-block-id primary: (BUF <ui-basic-block-view>))
Returns the ID of the parent block node if the field that the cursor is currently on.

[method] (ui-blockview-get-current-field-config primary: (BUF <ui-basic-block-view>))
Returns the bv-field-configuration for the field that the cursor is currently on.

[method] (ui-blockview-get-current-digit-index primary: (BUF <ui-basic-block-view>))
Returns the index of the digit of the numeric block field that the cursor is currently on. Indices are 0-based, with the least significant digit assuming index 0.

[method] (ui-blockview-get-current-field-command primary: (BUF <ui-basic-block-view>))
Returns the MDAL command config for the field that the cursor is currently on.

[method] (ui-blockview-start+end-positions primary: (BUF <ui-basic-block-view>))
Determine the start and end positions of each item chunk in the blockview's item cache.

[method] (ui-blockview-get-total-length primary: (BUF <ui-basic-block-view>))
Get the total number of rows of the blockview's contents.

[method] (ui-blockview-get-active-zone primary: (BUF <ui-basic-block-view>) #!optional (ROW (ui-blockview-get-current-row buf)))
Returns the active blockview zone as a list containing the first and last row in car and cadr, respectively.

[method] (ui-blockview-get-current-field-instance primary: (BUF <ui-basic-block-view>))
Return the field instance ID currently under cursor.

[method] (ui-blockview-get-current-field-index primary: (BUF <ui-basic-block-view>))
Return the index of the the current field node ID in the blockview's list of field IDs. The result can be used to retrieve a field instance value from a chunk in the item cache.

[method] (ui-blockview-get-current-field-value primary: (BUF <ui-basic-block-view>))
Returns the (un-normalized) value of the field instance currently under cursor.

[method] (ui-blockview-update-row-highlights primary: (BUF <ui-basic-block-view>))
Update the row highlights of the blockview.

[method] (ui-blockview-update-content-grid primary: (BUF <ui-basic-block-view>))
Perform a full update of the blockview block-content.

[method] (ui-blockview-update-content-rows primary: (BUF <ui-basic-block-view>) NEW-ITEM-LIST)
Update the blockview content grid on a row by row basis. This compares the NEW-ITEM-LIST against the current item cache, and only updates rows that have changed. The list length of NEW-ITEM-LIST and the lengths of each of the subchunks must match the list of items in the current item cache. This operation does not update the blockview's item cache, which should be done manually after calling this procedure.

[method] (ui-blockview-cursor-x-positions primary: (BUF <ui-basic-block-view>))
Returns a list of character positions that the blockview's cursor may assume.

[method] (ui-blockview-column-x-positions primary: (BUF <ui-basic-block-view>))

[method] (ui-blockview-cursor-do primary: (BUF <ui-basic-block-view>) ACTION)
Show or hide the blockview's cursor. ACTION shall be 'add or 'remove.

[method] (ui-blockview-remove-cursor primary: (BUF <ui-basic-block-view>))
Hide the blockview's cursor.

[method] (ui-blockview-show-cursor primary: (BUF <ui-basic-block-view>))
Show the blockview's cursor.

[method] (ui-blockview-set-cursor primary: (BUF <ui-basic-block-view>) ROW CHAR)
Set the cursor to the given coordinates.

[method] (ui-blockview-move-cursor-common primary: (BUF <ui-basic-block-view>) DIRECTION STEP #!optional SELECTING)
Move the blockview's cursor in DIRECTION, which must be one of Up, Down, Home, End, Left or Right. If moving Down, STEP specifies specifies the number of rows to move, otherwise the argument is ignored. If SELECTING is #t, Left/Right movement will move in column increments, rather than cursor positions.

[method] (ui-blockview-set-cursor-from-mouse primary: (BUF <ui-basic-block-view>))
Set the blockview's cursor to the grid position currently closest to the mouse pointer.

[method] (ui-blockview-focus primary: (BUF <ui-basic-block-view>))
Set the input focus to the blockview BUF. In addition to setting the Tk focus, it also shows the cursor and updates the status bar info text.

[method] (ui-blockview-unfocus primary: (BUF <ui-basic-block-view>))
Unset focus from the blockview BUF.

[method] (ui-blockview-update-row-numbers-common primary: (BUF <ui-basic-block-view>) PADDING)
Update the blockview row numbers according to the current item cache.

[method] (ui-blockview-cut-current-cell primary: (BUF <ui-basic-block-view>))
Delete the field node instance that corresponds to the current cursor position, and insert an empty node at the end of the block instead.

[method] (ui-blockview-cut-previous-cell primary: (BUF <ui-basic-block-view>))
Delete the field node instance that corresponds to row directly above the current cursor position, and insert an empty node at the end of the block instead.

[method] (ui-blockview-insert-cell primary: (BUF <ui-basic-block-view>) #!optional (VALUE '()))
Insert an empty cell into the field column currently under cursor, shifting the following node instances down and dropping the last instance.

[method] (ui-blockview-make-cell-edit-action primary: (BUF <ui-basic-block-view>) NEW-VALUE FIELD-ID BLOCK-ROW PATH)
Helper function for ui-blockview-edit-cell. Creates an edit action for a blockview cell edit. Returns #f if NEW-VALUE does not validate, or if the edit is otherwise invalid (eg. deleting a label on row 0).

There is normally no reason to call this procedure directly.

[method] (dwim-adjust-edit-contents primary: (BUF <ui-basic-block-view>) CONTENTS START END)
Do-what-I-mean adjust normalized edit buffer values (as provided by normalize-edit-parameters so they better match the target fields. If the target field uses a key/ukey MDAL command, then incoming numeric values are converted to the closest matching key. If the target field uses a numeric command, then incoming key values are converted to the numeric equivalents, and incoming numeric values are adjusted so their range does not exceed that of the target command.

[method] (normalize-edit-parameters primary: (BUF <ui-basic-block-view>) WHERE WHAT CONTENTS)
Helper for edit.

[method] (ui-blockview-blockset primary: (BUF <ui-basic-block-view>) CONTENTS START END)
Low-level interface for edit. See ui-blockview-blockedit for details.

[method] (ui-blockview-blockinsert primary: (BUF <ui-basic-block-view>) CONTENTS START END)
Low-level interface for edit. See ui-blockview-blockedit for details.

[method] (ui-blockview-perform-edit primary: (BUF <ui-basic-block-view>) ACTION)
The low level interface to blockview editing. ACTION shall be an edit action specifier as described in the ui-metastate documentation.

[method] (edit primary: (BUF <ui-basic-block-view>) WHERE WHAT #!optional CONTENTS)
WHERE may be 'cursor, a (ROW FIELD-ID) list specifying the first cell that will be affected,'selection, or a list specifying a selected area of the blockview. The list must have the form(ROW1 FIELD1 ROW2 FIELD2)`, where ROWn is a row number and FIELDn is a field node identifier, describing the upper left and lower right corner of the selection.

edit will update the journal (undo/redo), and update the display.

[method] (ui-blockview-enter-note primary: (BUF <ui-basic-block-view>) KEYSYM)
Perform an edit action at cursor, assuming that the cursor points to a field that represents a note command.

[method] (ui-blockview-enter-boolean primary: (BUF <ui-basic-block-view>))
Perform an edit action at cursor, assuming that the cursor points to a field that represents a trigger or label command.

[method] (ui-blockview-enter-key primary: (BUF <ui-basic-block-view>) KEYSYM)
Perform an edit action at cursor, assuming that the cursor points to a field that represents a key/ukey command.

[method] (ui-blockview-repeat-last-set primary: (BUF <ui-basic-block-view>))

[method] (ui-blockview-keysym->field-value primary: (BUF <ui-basic-block-view>) KEYSYM IS-MODIFIER)
Helper method for ui-blockview-enter-numeric. Constructs a new block field value from the Tk key symbol KEYSYM, assuming that the cursor is currently positioned on the field digit being edited.

[method] (ui-blockview-enter-numeric primary: (BUF <ui-basic-block-view>) KEYSYM)
Perform an edit action at cursor, assuming that the cursor points to a field that represents a numeric (int/uint/reference) command.

[method] (ui-blockview-enter-modifier primary: (BUF <ui-basic-block-view>) KEYSYM)
Perform an edit action at cursor, assuming that the cursor points to a field that represents a modifier command.

[method] (ui-blockview-enter-string primary: (BUF <ui-basic-block-view>) KEYSYM)
Perform an edit action at cursor, assuming that the cursor points to a field that represents a string command.

[method] (ui-blockview-dispatch-entry-event primary: (BUF <ui-basic-block-view>) KEYSYM)
Dispatch entry events occuring on the blockview's content grid to the appropriate edit procedures, depending on field command type.

[method] (ui-blockview-tag-selection primary: (BUF <ui-basic-block-view>))
Update content tags so current selection is highlighted.

[method] (ui-blockview-selected-fields primary: (BUF <ui-basic-block-view>))
Returns the field node identifiers of the fields that are currently selected.

[method] (ui-select primary: (BUF <ui-basic-block-view>) KEYSYM)
Initialize or continue a selection process (ie, user selecting a section for copying/modifying/etc).

[method] (ui-cancel-selection primary: (BUF <ui-basic-block-view>))
Abort the current selection process and reset selection state.

[method] (ui-select-with-mouse primary: (BUF <ui-basic-block-view>) XPOS YPOS)
Initialize or continue a selection process with the mouse.

[method] (ui-selected-contents primary: (BUF <ui-basic-block-view>) #!optional (SELECTION (slot-value buf 'selection)))
Retrieve the contents (values) within the bounds of SELECTION, which must be a list of four elements denoting the top left and bottom right corners of the selection. Coordinates are given as row, field-id pairs, so SELECTION must have the format (ROW1 FIELD-ID1 ROW2 FIELD-ID2). Order does not matter when specifing the points. When SELECTION is not given, it defaults to the current user selection. If there is no active selection, the value of the field currently under cursor is returned.

[method] (ui-copy primary: (BUF <ui-basic-block-view>))
Copy data from the current selection to the global clipboard and cancel the selection. If nothing is selected, copy the field value currently under cursor.

[method] (ui-paste primary: (BUF <ui-basic-block-view>) #!optional (CONTENTS (clipboard)))

[method] (ui-porous-paste primary: (BUF <ui-basic-block-view>) #!optional (STACK-ORDER 'under) (CONTENTS (clipboard)))

[method] (ui-porous-paste-under primary: (BUF <ui-basic-block-view>) #!optional (CONTENTS (clipboard)))

[method] (ui-porous-paste-over primary: (BUF <ui-basic-block-view>) #!optional (CONTENTS (clipboard)))

[method] (ui-swap primary: (BUF <ui-basic-block-view>) #!optional (CONTENTS (clipboard)))
Swap the current selection with the clipboard contents

[method] (ui-normalized-selection primary: (BUF <ui-basic-block-view>))
Return the current selection normalized, so that start-row <= end-row and start-field <= end-field.

[method] (ui-randomize primary: (BUF <ui-basic-block-view>))
Randomize selected fields

[method] (ui-transpose primary: (BUF <ui-basic-block-view>) #!optional (OFFSET 1))
Transpose selected notes.

[method] (ui-shift primary: (BUF <ui-basic-block-view>) #!optional (DIRECTION 'up) (BY 1))

[method] (ui-reverse primary: (BUF <ui-basic-block-view>))
Reverse the current selection.

[method] (ui-shuffle primary: (BUF <ui-basic-block-view>) #!optional SYNCED)

[method] (ui-interpolate primary: (BUF <ui-basic-block-view>) #!optional (INTERPOLATION-TYPE 'linear))
Interpolate selected block field values.

[method] (ui-invert primary: (BUF <ui-basic-block-view>))
Invert selected numeric values

[method] (ui-scale primary: (BUF <ui-basic-block-view>) RMIN RMAX)

[method] (ui-make-scaling-dialog primary: (BUF <ui-basic-block-view>))

[method] (ui-blockview-bind-events primary: (BUF <ui-basic-block-view>))
Bind common event handlers for the blockview BUF.

[class] <ui-block-view>

inherits from: <ui-basic-block-view>

slot initform
ui-zone (gensym 'block-view)
block-ids

A class representing the display of an MDAL group node's blocks, minus the order block. Pattern display is implemented using this class.

(make <ui-order-view>
     'group-id ID
     'parent-instance-path PATH
     'metastate-accessor ACCESSOR)

where ID is the MDAL node identifier of the parent group node, PATH is an MDAL node path string pointing to the parent group node instance, and ACCESSOR is a metastate accessor procedure as described in the <ui-module-view> documentation below.

[method] (initialize-instance after: (BUF <ui-block-view>))

[method] (field-id->cursor-start primary: (BUF <ui-block-view>) ID)
Return the first cursor x-position for the field ID in the block-view buffer BUF. It is an error to call this on a hidden field.

[method] (ui-init-content-header primary: (BUF <ui-block-view>))
Set up the column and block header display.

[method] (ui-blockview-get-sibling primary: (BUF <ui-block-view>))
Retrieve the <ui-order-view> buffer that is linked to BUF.

[method] (ui-blockview-cursor-row->order-pos primary: (BUF <ui-block-view>) ROW)
Returns the order position that the vertical cursor position ROW belongs to.

[method] (ui-blockview-get-current-order-pos primary: (BUF <ui-block-view>))
Returns the corresponding group order position for the chunk currently under cursor.

[method] (ui-blockview-update-current-command-info primary: (BUF <ui-block-view>))
Update the command information in the status bar, based on the field that the cursor currently points to.

[method] (ui-blockview-get-item-list primary: (BUF <ui-block-view>))
Get the up-to-date list of items to display. The list is nested. The first nesting level corresponds to an order position. The second nesting level corresponds to a row of fields.

[method] (ui-blockview-get-current-chunk primary: (BUF <ui-block-view>))
Returns the chunk from the item cache that the cursor is currently on.

[method] (ui-blockview-get-current-block-instance primary: (BUF <ui-block-view>) #!optional (CURRENT-BLOCK-ID (ui-blockview-get-current-block-id buf)))
Return the block instance ID currently under cursor.

[method] (ui-blockview-get-current-block-instance-path primary: (BUF <ui-block-view>))
Return the MDAL node path string of the field currently under cursor.

[method] (ui-blockview-edit-cell primary: (BUF <ui-block-view>) NEW-VALUE #!key (FIELD-ID (ui-blockview-get-current-field-id buf)) (BLOCK-ROW (ui-blockview-get-current-field-instance buf)) (PATH (ui-blockview-get-current-block-instance-path buf)) (PLAY-ROW #f))
deprecated, use (edit BUF 'cursor VALUE) instead Set the field node instance that corresponds to the current cursor position to NEW-VALUE, and update the display and the undo/redo stacks accordingly.

[method] (ui-blockview-insert-row primary: (BUF <ui-block-view>))

[method] (ui-blockview-cut-row primary: (BUF <ui-block-view>))

[method] (ui-blockview-cut-previous-row primary: (BUF <ui-block-view>))
Provides inuitive behaviour for Ctrl+Backspace (cut row), by cutting the row above the cursor.

[method] (ui-blockview-blockedit primary: (BUF <ui-block-view>) CONTENTS START END ACTION-TYPE)
Low-level interface for edit. You most likely do not want to call this directly. CONTENTS must be a list of lists, where each sublist represents a block field node, and the contents of the sublist form the values that shall be set. START and END must be a row,field-id pair specifying the first and last affected cell, respectively.

This updates the journal and the display.

[method] (ui-blockview-blockcut primary: (BUF <ui-block-view>) CONTENTS START END)

[method] (ui-blockview-update-row-numbers primary: (BUF <ui-block-view>))
Update the blockview row numbers according to the current item cache.

[method] (ui-blockview-tag-active-zone primary: (BUF <ui-block-view>))
Apply type tags and the 'active tag to the current active zone of the blockview BUF.

[method] (ui-blockview-set-sibling-cursor primary: (BUF <ui-block-view>))
Set the cursor of the associated order view.

[method] (ui-blockview-move-cursor primary: (BUF <ui-block-view>) DIRECTION #!optional SELECTING)

[method] (ui-update primary: (BUF <ui-block-view>))
Update the blockview display. The procedure attempts to be "smart" about updating, ie. it tries to not perform unnecessary updates. This makes the procedure fast enough to be used after any change to the blockview's content, rather than manually updating the part of the content that has changed.

[method] (ui-show before: (BUF <ui-block-view>))

[method] (ui-where primary: (BUF <ui-block-view>))

[method] (ui-blockview-bind-events after: (BUF <ui-block-view>))

[procedure] (block-view-toolbar ARGS...)

Toolbar set for the block view toolbar. Callback procedures will be wrapped in a lambda, which calls the actual callback with the order view object as its first and only argument. So specifying a callback procedure foo will result in the effective callback (lambda () (foo BLOCK-BUF)).

[class] <ui-order-view>

inherits from: <ui-basic-block-view>

slot initform
ui-zone (gensym 'order-view)

A class representing the display of the order block of an MDAL group node instance.

(make <ui-order-view>
     'group-id ID
     'parent-instance-path PATH
     'metastate-accessor ACCESSOR)

where ID is the MDAL node identifier of the parent group node, PATH is an MDAL node path string pointing to the parent group node instance, and ACCESSOR is a metastate accessor procedure as described in the <ui-module-view> documentation below.

[method] (initialize-instance after: (BUF <ui-order-view>))

[method] (field-id->cursor-start primary: (BUF <ui-order-view>) ID)
Return the first cursor x-position for the field ID in the block-view buffer BUF.

[method] (ui-init-content-header primary: (BUF <ui-order-view>))
Set up the column and block header display.

[method] (ui-blockview-get-sibling primary: (BUF <ui-order-view>))
Retrieve the <ui-block-view> buffer that is linked to BUF.

[method] (ui-blockview-get-current-order-pos primary: (BUF <ui-order-view>))
Returns the corresponding group order position for the chunk currently under cursor. Alias for ui-blockview-get-current-row.

[method] (ui-blockview-update-current-command-info primary: (BUF <ui-order-view>))
Update the command information in the status bar, based on the field that the cursor currently points to.

[method] (ui-blockview-get-item-list primary: (BUF <ui-order-view>))
Get the up-to-date list of items to display. The list is nested. The first nesting level corresponds to an order position. The second nesting level corresponds to a row of fields. For order nodes, there is only one element at the first nesting level.

[method] (ui-blockview-get-current-chunk primary: (BUF <ui-order-view>))
Returns the chunk from the item cache that the cursor is currently on.

[method] (ui-blockview-update-row-numbers primary: (BUF <ui-order-view>))
Update the blockview row numbers according to the current item cache.

[method] (ui-blockview-tag-active-zone primary: (BUF <ui-order-view>))
Apply type tags and the 'active tag to the current active zone of the order view BUF.

[method] (ui-blockview-set-sibling-cursor primary: (BUF <ui-order-view>))
Set the cursor of the associated blockview.

[method] (ui-blockview-move-cursor primary: (BUF <ui-order-view>) DIRECTION #!optional SELECTING)

[method] (ui-blockview-get-current-block-instance-path primary: (BUF <ui-order-view>))
Return the MDAL node path string of the field currently under cursor.

[method] (ui-blockview-perform-edit after: (BUF <ui-order-view>) ACTION)
Update the sibling blockview after an edit to the order.

[method] (ui-blockview-edit-cell primary: (BUF <ui-order-view>) NEW-VALUE #!key (PATH #t) (FIELD-ID (ui-blockview-get-current-field-id buf)) (BLOCK-ROW (ui-blockview-get-current-field-instance buf)))
deprecated Set the field node instance that corresponds to the current cursor position to NEW-VALUE, and update the display and the undo/redo stacks accordingly.

[method] (ui-blockview-insert-row primary: (BUF <ui-order-view>) #!optional ROW (INSERT-POS (ui-blockview-get-current-row buf)))
Insert a new row at the current cursor position. If ROW is omitted, the current row is cloned, or an empty row is created if the cursor is on row 0. If ROW is given, it must be a list of row values, which may not contain empty nodes. INSERT-POS may be the index of the row to insert (defaults to the current cursor position if omitted).

[method] (ui-blockview-cut-row primary: (BUF <ui-order-view>) #!optional (POSITION (ui-blockview-get-current-row buf)))
Cut (remove) the row currently under cursor.

[method] (ui-blockview-cut-previous-row primary: (BUF <ui-order-view>))
Provides inuitive behaviour for Ctrl+Backspace (cut row), by cutting the row above the cursor.

[method] (ui-order-add-row primary: (BUF <ui-order-view>))
Increase order length.

[method] (ui-order-sub-row primary: (BUF <ui-order-view>))
Decrease order length.

[method] (ui-blockview-blockedit primary: (BUF <ui-order-view>) CONTENTS START END ACTION-TYPE)
Low-level interface for edit. You most likely do not want to call this directly. CONTENTS must be a list of lists, where each sublist represents a block field node, and the contents of the sublist form the values that shall be set. START and END must be a row,field-id pair specifying the first and last affected cell, respectively.

This updates the journal and the display.

[method] (ui-blockview-blockcut primary: (BUF <ui-order-view>) CONTENTS START END)

[method] (ui-update primary: (BUF <ui-order-view>))
Update the blockview display. The procedure attempts to be "smart" about updating, ie. it tries to not perform unnecessary updates. This makes the procedure fast enough to be used after any change to the blockview's content, rather than manually updating the part of the content that has changed.

[method] (ui-show before: (BUF <ui-order-view>))

[method] (ui-where primary: (BUF <ui-order-view>))

[method] (ui-blockview-bind-events after: (BUF <ui-order-view>))

[procedure] (order-view-toolbar ARGS...)

Toolbar set for the order view toolbar. Callback procedures will be wrapped in a lambda, which calls the actual callback with the order view object as its first and only argument. So specifying a callback procedure foo will result in the effective callback (lambda () (foo ORDER-BUF)).

[variable] order-view-minimal-toolbar

default:

(create-toolbar-set
     '((edit (add-row "Increase length" "add1.png" enabled)
         (sub-row "Decrease length" "sub1.png" enabled)))
     '((edit (add-row ui-order-add-row)
         (sub-row ui-order-sub-row))))

Like order-view-toolbar, but only contains buttons for add-row/sub-row. Used on non-editable orders.

[class] <ui-blocks>

inherits from: <ui-multibuffer>

slot initform
orient 'horizontal
group-id (error '|make <ui-blocks>| "Missing 'group-id.")
parent-instance-path (error '|make <ui-blocks>| "Missing 'parent-instance-path.")
metastate-accessor (error '|make <ui-blocks>| "Missing 'metastate-accessor.")

A widget class suitable for displaying an MDAL group node's block members. It is a wrapper around a and the associated . Create instances with

(make <ui-group-blocks>
     'group-id ID
     'parent-instance-path PATH
     'metastate-accessor ACCESSOR)

where ID is the MDAL node identifier of the parent group node, PATH is an MDAL node path string pointing to the parent group node instance, and ACCESSOR is a metastate accessor procedure as described in the <ui-module-view> documentation below.

[method] (initialize-instance after: (BUF <ui-blocks>))

[method] (ui-metastate primary: (BUF <ui-blocks>) #!rest ARGS)

[method] (ui-get-focus-zones primary: (BUF <ui-blocks>))

[class] <ui-subgroups>

inherits from: <ui-buffer>

slot initform
packing-args '(expand: 1 fill: both)
group-id (error '|make <ui-subgroups>| "Missing 'group-id.")
parent-instance-path (error '|make <ui-subgroups>| "Missing 'parent-instance-path.")
tabs
tab-ids #f
subgroups
metastate-accessor (error '|make <ui-subgroup>| "Missing 'metastate-accessor.")

A widget class suitable for displaying an MDAL group node's subgroups.

(make <ui-subgroups>
     'group-id ID
     'parent-instance-path PATH
     'metastate-accessor ACCESSOR)

where ID is the MDAL node identifier of the parent group node, PATH is an MDAL node path string pointing to the parent group node instance, and ACCESSOR is a metastate accessor procedure as described in the <ui-module-view> documentation below.

[method] (initialize-instance after: (BUF <ui-subgroups>))

[method] (ui-show before: (BUF <ui-subgroups>))

[method] (ui-destroy before: (BUF <ui-subgroups>))

[method] (ui-metastate primary: (BUF <ui-subgroups>) #!rest ARGS)

[method] (ui-get-focus-zones primary: (BUF <ui-subgroups>))

[method] (ui-set-focus primary: (BUF <ui-subgroups>) SUBGROUP-ID)

[method] (ui-get-selected-tab primary: (BUF <ui-subgroups>))
Get the Tk ID of the currently active subgroup tab.

[method] (ui-focus-next-tab primary: (BUF <ui-subgroups>))
Focus the next subgroup tab.

[method] (ui-focus-previous-tab primary: (BUF <ui-subgroups>))
Focus the next subgroup tab.

[class] <ui-group>

inherits from: <ui-multibuffer>

slot initform
group-id (error '|make <ui-group>| "Missing 'group-id.")
parent-instance-path (error '|make <ui-group>| "Missing 'parent-instance-path.")
current-instance 0
metastate-accessor (error '|make <ui-group>| "Missing 'metastate-accessor.")

A widget class suitable for displaying an MDAL group node.

(make <ui-group>
     'group-id ID
     'parent-instance-path PATH
     'metastate-accessor ACCESSOR)

where ID is the MDAL node identifier of the group node, PATH is an MDAL node path string pointing to the parent group node instance, and ACCESSOR is a metastate accessor procedure as described in the <ui-module-view> documentation below.

[method] (initialize-instance after: (BUF <ui-group>))

[method] (ui-metastate primary: (BUF <ui-group>) #!rest ARGS)

[method] (ui-get-focus-zones primary: (BUF <ui-group>))

[method] (ui-ref-by-zone-id primary: (BUF <ui-group>) ZONE-ID)

[class] <ui-module-view>

inherits from: <ui-multibuffer>

slot initform
mmod #f
metastate-accessor #f
filename #f
modified #f
journal (make-app-journal)
emulator #f

The top-level abstraction for MMOD displays. An manages the module state (including emulation), and contains the the display of the GLOBAL node.

You can instantiate a with either of the forms

(make <ui-module-view> 'mmod MMOD ['filename FILE])
(make <ui-module-view> 'filename FILE)

where MMOD is a MMOD structure as defined in md-types, and FILE is the fully qualified path to an .mmod FILE. When using the second form, the constructor will automatically construct the appropriate MMOD from the given .mmod FILE.

To interact with the module state, use the ui-metastate method. Note that ui-metastate can be called on any of the module-view's child elements as well, and doing so will act on the module state of the parent <ui-module-view>. See documentation for ui-metastate below.

[method] (make-module-view-toolbar primary: (BUF <ui-module-view>) #!optional SAVE-ENABLED)
Helper for <ui-module-view> constructor.

[method] (make-module-view-settings-bar primary: (BUF <ui-module-view>))
Helper for <ui-module-view> constructor.

[method] (module-view-push-undo primary: (BUF <ui-module-view>) ACTION)

[method] (module-view-pop-undo primary: (BUF <ui-module-view>))

[method] (module-view-push-redo primary: (BUF <ui-module-view>) ACTION)

[method] (module-view-pop-redo primary: (BUF <ui-module-view>))

[method] (module-view-clear-redo primary: (BUF <ui-module-view>))

[method] (module-view-undo primary: (BUF <ui-module-view>))

[method] (module-view-redo primary: (BUF <ui-module-view>))

[method] (make-metastate-accessor primary: (BUF <ui-module-view>))
Construct a module view metastate accessor procedure. Helper for <ui-module-view> constructor.

[method] (initialize-instance after: (BUF <ui-module-view>))

[method] (ui-module-view-current-zone primary: (BUF <ui-module-view>))

[method] (ui-ref-by-zone-id primary: (BUF <ui-module-view>) ZONE-ID)

[method] (ui-metastate primary: (BUF <ui-module-view>) #!rest ARGS)
Interact with the module-view module state. This method can be called on the module-view itself, or any of its child elements.

Given an <ui-module-view> MV, use as follows:

(ui-metastate MV 'mmod)

Returns the associated MDAL module structure.

(ui-metastate MV 'mdef)

Returns the associated MDAL engine definition.

(ui-metastate MV 'emulator ['play-row])

Returns the associated emulator. If the additional 'play-row tag is specified, plays the row of the block that the user is currently editing, if applicable. In this case, returns nothing.

(ui-metastate MV 'modified [NEW-VAL])

Returns the "modified" flag, ie. whether the associated module has changed since the last file save. When NEW-VAL is given and a boolean, sets the "modified" flag.

(ui-metastate MV 'filename [NEW-VAL])

Get the associated filename, or #f if the filename is not set. When NEW-VAL is given, sets the associated filename to it.

(ui-metastate MV 'apply-edit ACTION)

This command is used internally to apply the edit ACTION to the associated associated MDAL module. An edit action is a list that takes the form

(ACTION PARENT-INSTANCE-PATH NODE-ID INSTANCES)

where ACTION is one of the symbols set, insert, remove, block-row-insert, or block-row-remove. PARENT-INSTANCE-PATH is a fully qualified MDAL node path string denoting the parent node instance of the node that you want to edit (ie. a path starting at the global inode, see md-types/MMOD for details), NODE-ID is the ID of the node you want to edit, and INSTANCES is an alist where the keys are node instance ID numbers and the values are the values that you want to set. For block-row-insert/remove, INSTANCES must be an alist where the keys are block instance ids, and the values are in turn alists where the key is a row number (field instance), and the value is a list of field values as required by the block node.

Values for remove/block-row-remove actions are ignored, but you must still provide the argument so Bintracker can deduce the inverse of the action (which gets pushed to the journal).

As the respective names suggest, a set action sets one or more instances of the node NODE-ID at PARENT-INSTANCE-PATH to (a) new value(s), an insert action inserts one or more new instances into the node, and a remove action removes one or more instances from the node. Likewise, a block-row-insert inserts a new row into a given block node instance, and block-row-remove removes a row. It is an error to apply the latter to actions to any non-block node.

Alternatively, an edit action may take the form

(compound ACTIONS))

where ACTIONS is a list of edit actions. In this case, the edit actions are applied in the order provided. A compound action thus bundles one or more edit actions together.

When you use the 'apply-edit command in user code, it is your responsibility to ensure that the metastate's undo stack is updated accordingly by pushing the inverse of ACTION to it. Use the make-reverse-action procedure to derive the inverse from a given edit action.

(ui-metastate MV 'push-undo ACTION)

Push an edit action to the undo stack. ACTION shall be the inverse of an edit your applying (see above).

(ui-metastate MV 'undo)

Undo the most recent edit, if any.

(ui-metastate MV 'redo)

Redo the most recently undone edit.

(ui-metastate MV 'set-info STR)

Set the active command info in the modeline to STR.

`(ui-metastate MV 'group-ref ID)

Get the <ui-group> instance representing the MDAL group node named ID.

[method] (ui-show before: (BUF <ui-module-view>))

[method] (ui-destroy before: (BUF <ui-module-view>))

[variable] module-view-toolbar

default:

(create-toolbar-set
     '((file (new-file "New File" "new.png" enabled)
         (load-file "Load File..." "load.png" enabled)
         (save-file "Save File" "save.png"))
       (journal (undo "Undo last edit" "undo.png")
        (redo "Redo last edit" "redo.png"))
       (edit (copy "Copy Selection" "copy.png" enabled)
             (cut-selection "Cut Selection (delete with shift)" "cut.png"
                enabled)
             (clear "Clear Selection (delete, no shift)" "clear.png"
            enabled)
             (insert "Insert from Clipbard (with shift)" "insert.png"
             enabled)
             (paste "Paste from Clipboard (no shift)" "paste.png" enabled)
         (porous-paste-under "Porous paste under current data"
                 "porous-paste-under.png" enabled)
         (porous-paste-over "Porous paste over current data"
                "porous-paste-over.png" enabled)
             (swap "Swap Selection with Clipboard" "swap.png" enabled))
       (play (stop-playback "Stop Playback" "stop.png" enabled)
             (play-from-start "Play Track from Start"
                  "play-from-start.png" enabled)
             (play-from-here "Play Track from Current Position"
                 "play-from-here.png")
             (play-pattern "Play Pattern" "play-ptn.png" enabled)))
     `((file (new-file ,(lambda (buf) (new-file)))
         (load-file ,(lambda (buf) (load-file)))
         (save-file ,(lambda (buf) (save-file))))
       (edit (copy ,(lambda (buf)
              (and-let*
              ((current-zone (ui-module-view-current-zone buf)))
            (ui-copy current-zone))))
         (clear ,(lambda (buf)
               (and-let*
               ((current-zone (ui-module-view-current-zone buf)))
             (clipboard
              'put
                  (if (slot-value current-zone 'selection)
                      (ui-selected-contents current-zone)
                      (ui-blockview-get-current-field-value
                   current-zone)))
             (edit current-zone 'current 'clear)
             (ui-cancel-selection current-zone)
             ;; (ui-blockview-tag-selection current-zone)
             )))
         (cut-selection
          ,(lambda (buf)
         (and-let*
             ((current-zone (ui-module-view-current-zone buf))
              (_ (ui-selection current-zone)))
           (edit current-zone 'selection 'cut)
           (ui-cancel-selection current-zone))))
         (paste ,(lambda (buf)
               (and-let*
               ((current-zone (ui-module-view-current-zone buf)))
             (ui-paste current-zone))))
         (porous-paste-under
          ,(lambda (buf)
         (and-let* ((current-zone (ui-module-view-current-zone buf))
                (_ (or (symbol-contains
                    (slot-value current-zone 'ui-zone)
                    "block-view")
                   (symbol-contains
                    (slot-value current-zone 'ui-zone)
                    "order-view"))))
           (ui-porous-paste-under current-zone))))
         (porous-paste-over
          ,(lambda (buf)
         (and-let* ((current-zone (ui-module-view-current-zone buf))
                (_ (or (symbol-contains
                    (slot-value current-zone 'ui-zone)
                    "block-view")
                   (symbol-contains
                    (slot-value current-zone 'ui-zone)
                    "order-view"))))
           (ui-porous-paste-over current-zone))))
         (insert ,(lambda (buf)
            (and-let*
                ((contents (clipboard))
                 (current-zone (ui-module-view-current-zone buf)))
              (edit current-zone 'current 'insert contents))))
         (swap ,(lambda (buf)
              (and-let*
              ((current-zone (ui-module-view-current-zone buf))
               (_ (or (symbol-contains
                   (slot-value current-zone 'ui-zone)
                   "block-view")
                  (symbol-contains
                   (slot-value current-zone 'ui-zone)
                   "order-view"))))
            (ui-swap current-zone)))))
       (play (play-from-start ,(lambda (buf) (play-from-start)))
         (play-pattern ,(lambda (buf) (play-pattern)))
         (stop-playback ,(lambda (buf) (stop-playback))))
       (journal (undo ,(lambda (buf) (module-view-undo buf)))
        (redo ,(lambda (buf) (module-view-redo buf))))))

Auxiliary module UI accessor procedures

[procedure] (current WHAT)

This accessor can be used to retrieve various components of the module interface the user is currently interacting with. This is inevitably a brittle solution, so be careful when using these.

WHAT must be one of the following:

  • module-view: The current <ui-module-view> instance.
  • blockview: The current <ui-blockview> instance.
  • order-view: The current <ui-order-view> instance.
  • group-fields: The current <ui-group-fields> instance.
  • mmod: The current MDAL module.
  • mdef: The current MDAL engine definition.
  • emulator: The current emulator object.
  • buffer: The current focussed buffer.

Utility procedures

[procedure] (do-current WHAT . ARGS)

[procedure] (shift-current DIRECTION BY)

[procedure] (transpose-current OFFSET)

[procedure] (transpose-note-up)

[procedure] (transpose-note-down)

[procedure] (transpose-octave-up)

[procedure] (transpose-octave-down)

[procedure] (raise-current)

[procedure] (raise-by-unit-current)

[procedure] (lower-current)

[procedure] (lower-by-unit-current)

[procedure] (randomize-current)

[procedure] (invert-current)

[procedure] (reverse-current)

[procedure] (shuffle-current)

[procedure] (shuffle-synced-current)

[procedure] (interpolate-linear)

[procedure] (interpolate-cosine)

[procedure] (scale-current)

Screen Reader/Text-to-Speech API

[procedure] (say . ARGS)

An interface to the screen reader/text-to-speech tool. Use as follows:

(say STRING)

Say the string STRING (without sanitization).

(say 'sanitize STRING)

Say a sanitized version of STRING.

(say S-EXP)

Say a stringified, sanitized version of the symbolic expression S-EXP.

(say 'what)

Report the value currently under cursor.

(say 'where)

Report the location of the cursor. The results depend on the widget class type.

[procedure] (what)

Report the value currently under cursor through the screen reader, if any.

[procedure] (where)

Report the current cursor location on screen through the screen reader, if any.