Class SMDialog
Powerful user interface.
Table of contents
Introduction
Hi devs!
When you create a floatting window or interface composer, MyrScript allows you to use DialogItem such as button, static text, radio, checkbox, text editor, note head/duration selector...
These items are very useful but you may bump into their limit,
for example create a small square button is impossible, it has minimal width.
An example of script made of "native" DialogItems is Target Editor.
Danièl's scripts
are very inspirating.
Danièl's approch is to graphically create buttons with background of palettes' buttons (Graph.DrawPaletteButton(...)
),
display a text, and handle in Idle()
and Draw()
functions, what to do for each button while you move mouse pointer or click.
The result is really more like a palette than a "dialog", and there is no such limitations as DialogItem have:
- like in palettes, color change when mouse pointer is over a button
- like some palette button, you can display 2 states: active, inactive
- No minimal size restriction
- You can insert text (caption), image or draw a polygon
A simple example of what Danièl scripts look like: Active layers
(but I'm sure you already installed and enjoyed all his wonderful scripts!)
If you have a look to the source code, you'll see a lot of variables for each button B1G, B1H, B1D, B1B
(gauche, haut, droite, bas) which stands for "button #1" left, top, right and bottom.
You'll see also two large Idle()
and Draw()
functions.
So I was looking for a way to simplify the code, and makie it more human readable...
After this long introduction, let's go discovering my powerful componants and code!
Skeleton?
SMDialog is part of SMCore library, bundled with Harmony Assistant.
In case of update between two releases of Harmony Assistant, the following lines will download automatically latest SMCore version.
Last update version is announced on the forum.
In a new floatting or Composer window, remove the pre-defined functions, and copy/past this skeleton.
function Init(dialog) -- download/update library Include "SMCore-Updater" SMCoreRequireVersion(20250501) Include "SMDialog" smDialog = SMDialog:new(dialog) -- Uncomment for Composer window (modal dialog) -- smDialog.ListenMidiEvents = true -- Uncomment for more messages in Console in Run mode -- LOG_LEVEL = LOG_LEVEL_DEBUG -- LOG_LEVEL_TRACE -- Uncomment for less messages in Console in Debug mode -- LOG_LEVEL = LOG_LEVEL_INFO -- dialog.AreaWidth, dialog.AreaHeight = x, x -- dialog.AreaLeft, dialog.AreaTop = x, x -- Add components -- smDialog:addButton, :addSlider, :addKnob, :addGrid... end -- /Init function KeyDown(dialog, dummy, key) -- KeyDown : called each time a key is pressed local continueProcessing, keyAsString, ctrl, shift = smDialog:handleKeyDown(dummy, key) if continueProcessing == true then -- No component handled the pressed key, perform dialog-level processing -- print(keyAsString, ctrl, shift) end -- Return true if the key will be processed normaly return continueProcessing end -- /KeyDown function OnMouseWheel(dialog, score, amount) smDialog:handleMouseWheel(score, amount) end function Idle(dialog) -- Idle : called when nothing happens to the dialog box smDialog:handleIdle() end function Draw(dialog) -- Draw : called each time the dialog need to be redrawn -- default font size and face -- size is a number, face is a constant from MSDefine -- 11 and FACE_NONE should do the job. smDialog:handleDraw(11, FACE_NONE) end function Exit(dialog) -- Exit : called just before the dialog is closed -- close resources, may print some debug messages smDialog:handleExit() end
Concepts
DialogItems
MyrScript native items are DialogItems, called "items" in this documentation.
Components
All elements used by SMDialog are called "component".
Most of them are drawn with a background Graph.DrawPaletteButton()
.
The basic ones are button, label (without background). More complex ones have been created: slider, spinner, grid....
Panels
SMDialog introduces the concept of "panel" grouping components and items, which can be hidden or shown, like a contextual menu (overlapping other items and components), or panels of a tab bar.
You can add items in your window and attach them to a panel in their own function Init(dialog, item)
, in one line:
item.UserTable.Panel="MyPanelName"
Components and panels are tables
Components and panels are tables with variables like Left, Top, Right, Bottom, Caption, Help... Table elements can be functions, and this is massively used by components.
Relative positionning
Components position are relative to their parent panel.
By default there is a "main" panel and positions are from the left top corner of the window,
but in case of contextual menu, you'll see that relative positions is very handy.
Events
Components have "event" functions: OnClick, OnclickRelease, OnMouseWheel, OnMouseEnter, OnMouseLeave, OnInit, OnChange, OnMidiController...
Provided component (Slider, Grid, Knob...) have their own event handler functions, it's up to you to implement the OnChange
Simplest Component (buttons and labels) have no event handler implemented.
Keyboard navigation and focus
Mouse related events are sent to the component under the mouse pointer,
but you can navigate throught components using Tab or Shift+Tab.
Then, the focus is changed, and the focused component will receive keyboard event: OnKeyDown.
Some components, such as Slider, Switchable, Knob and Grid have pre-defined behavior when pressing keystrokes.
MIDI controllers
If you enable the Midi event listener, you can assign CC# [+ channel] shortcuts to components.
This is not recommanded for a distributed script, because CC# are very hardware dependant: MIDI-master keyboards
have plenty of knobs, switches, cursors (sliders) while simpler keyboard only have pitch bend and modulation wheels.
Run the script Midi > Midi input monitor to discover channel and CC# of your Midi device.
If only one component has OnMidiNoteOn or OnMidiNoteOff or OnMidiPitchBend functions, they will receive respectively all 'Note On', 'Note Off' and 'Pitch Bend' messages and be focused.
By default, once Midi listener is enabled, focused or under mouse pointer component will behave the following way:
- pitch bend wheel scrolls the Grids
- pitch bend wheel turns Knobs and move Sliders,
- sustain pedal produce a click, or Space stroke,
- all other controllers selects/change value of grids, sliders and knobs.
- Last, if nothing above happened (the dialog only contain simple buttons), pitch bend wheel and controllers move the focus across buttons in the dialog.
Given the above behaviors and considerations, it's very safe to enable the Midi event listener for Composer window (modal dialogs), not recommanded for floatting windows as they may conflict with Midi recording, unless you really know what you are doing, for your personal use, not for distributed script.
Dialog.UserTable
Inside these event functions, you don't have direct reference to smDialog object created in Dialog.Init()
, so there are some shortcuts in dialog.UserTable
to interact with SMDialog
(e.g. hide a panel, get a button to change it's properties...). See Dialog.UserTable for list of functions and properties.
Components creation in Dialog.Init()
All components, visible or hidden, in main panel or another, *MUST* be created function Init(dialog)
.
See SMDialog:addButton(...).
-- B1 is a button in dialog top left corner without contextual help local B1 = smDialog:addButton("B1", 0, 0, 180, 25, "My button caption") -- B2 is a button wide as the dialog with contextual help local B2 = smDialog:addButton("B2", 0, 25, nil, 50, "A wide button", "The wide button help") -- bigger and bold caption, button in near bottom right corner -- Default font size is set to 11 in Dialog.Draw -> smDialog:handleDraw(...) local btnHelp = smDialog:addButton("help", -35, -35, -10, -10, "?", "Click to open help, right click to make coffee", 16, FACE_BOLD)
All these buttons are in the "main" panel = the window. We will focus on panels later.
Run the script, the buttons are drawn, but nothing happen on click. Stop the script.
Let's define the OnClick
events.
Event functions
See Component for full list.
- Resource allocation, init and exit:
B1.OnInit(dialog, compo)
Fired only once, after the Dialog initialization. Can allocate resources that should be closed by OnExit() event.B1.OnExit(dialog, compo)
Fired only once, before dialog exit. Free resources that have been allocated byOnInit
event.
- Mouse event:
B1.OnClick(dialog, compo, x, y, click)
fired when mouse button is pressed inside the component's area.B1.OnClickRelease(dialog, compo, x, y, click)
fired when mouse button is released inside the component's area.B1.OnMouseEnter(dialog, compo)
fired when mouse pointer enter the component's area.B1.OnMouseLeave(dialog, compo)
fired when mouse pointer exit the component's area.B1.OnMouseMove(dialog, compo, x, y, click)
fired each time mouse pointer move within the component's area.
This is less common event, but can be used for a Slider (cursor) while a mouse button is pressed.B1.OnMouseOver(dialog, compo, x, y, click)
fired each time the dialog is idle and mouse pointer is in component's area, even not moving.
uncommon but why not? It can scroll a long caption or play a little animation.B1.OnMouseWheel(dialog, score, amount, compo)
fired when mouse wheel is scrolling while mouse pointer is in component's area.
Note that in debug mode, mouse wheel is not fired.
- Computer keyboard:
B1.OnKeyDown(dialog, dummy, key, compo, ctrl, shift, keyAsString)
fired to the focused component when a key is pressed.
- Midi device (or other sources, see
MidiAllowedSources
):B1.OnMidiNoteOn(dialog, compo, channel, pitch, velocity
When Midi source plays a note while component is focused or under mouse pointer, e.g. a key of a Midi keyboard is pressed. Only if MidiAllowNoteOn is true.B1.OnMidiNoteOff(dialog, compo, channel, pitch, velocity
When Midi source stop play a note while component is focused or under mouse pointer, e.g. a key of a Midi keyboard is released. Only if MidiAllowNoteOff is true.B1.OnMidiController(dialog, compo, channel, controller, value)
When Midi hardware send a CC message (modulation wheel, pedals, switches, knobs, cursors) while component is focused or under mouse pointer. Enabled by default, MidiAllowCC is set to true.B1.OnMidiPitchBend(dialog, compo, channel, value)
When Midi hardware send a pitch bend message from the pitch wheel while component is focused or under mouse pointer. Enabled by default, MidiAllowPitchBend is set to true.
IfOnMidiPitchBend
is not implemented, the pitch bend send mouse wheel event.B1.OnMidiEvent(dialog, compo, event, channel, pitch, velocity, timeMs, timePos, source
:
When a midi event is received while component is focused or under mouse pointer, note on/off, controller, program change, pitch bend, aftertouch...
Only if MidiAllowOthers is set to tru.
OnChange(dialog, compo, ...)
:
Some component fire OnChange event you have to implement after mouse, keyboard or Midi input, e.g. a knob is rotated, selected row of a Grid has changed...
Refer to each component for list of arguments.B1.OnDraw(dialog, compo)
called each time the button is drawn, after drawing the bacgkground palette button and the caption.
This allow to add picture, polygons, and is massively used by other components.B1.OnExit(dialog, compo)
Called at Dialog.Exit, to free open resources.
Attach event to button
- Still in the
function Init(dialog)
, get the result of SMDialog:addButton in a local variable, this is a Component:local B1 = smDialog:addButton("B1", 0, 0, 180, 25, "My button caption")
- Then, for each event required, write
B1.<Event> = function(...) <body> end
:B1.OnMouseEnter = function(dialog, button) print("Hello little button. How are you?") end B1.OnClick = function(dialog, button, x, y, click) print("OK, you clicked me!") end -- one-line format works as well: B1.OnMouseLeave = function(dialog, button) print("Good bye little button...") end
- If the bodies of the functions are short, you can write them as the above example.
But if you have the same body for several buttons, or a more complex code, you'd better write it in a separate function in your Dialog this way:function Init(dialog) --... B1.OnClick = function(dialog, button, x, y, click) dialog.MyComplexFunction(dialog, button, x, y, click, "anotherArgument") end end --... and at the bottom of your script: function MyComplexFunction(dialog, button, x, y, click, anotherArgument) if button.Name=="B1" and click=LEFT_CLICK then print("Left click on B1") elseif button.Name=="B2" and click==LEFT_CLICK then print("Left click on B2") elseif button.Name=="help" and click==RIGHT_CLICK then dialog.MakeCoffee() -- else ... end end
This way will lighten a bit thefunction Init(dialog)
, and can be used by several buttons for complex tasks.
Button properties
As for events, once you have the button variable, you can read/change its properties.
See Component for complete list of properties.
local B1 = smDialog:addButton("B1", 0, 0, 180, 25, "My button caption") B1.CaptionHorizontalAlign = ALIGN_LEFT B1.IsSelected = true -- ...
Note: do NOT change Name, Left, Top, Right, Bottom and Panel after creation.
To change a set of button positions you can group them in a panel and move the panel (see further).
Panels
What is a panel?
Panel is a convenient way to group components and items: hide, show or move them in one function call,
A panel can be seen as a layer in the case you want to overlap ptjer components and items (e.g. a context menu that pops up at the x,y location of the right click).
It's also the way used by tabbed user interface:
- first tab show first panel, and hide all others
- second tab show second panel, and hide all others...

Create panels, in function Init(dialog)
Before adding button to a panel with the last argument of SMDialog:addButton, you must create it.
See SMDialog:addPanel(...).
default, all components are in "main" panel which is automatically created.
The returne table Panel describe panel's properties:
Name
, Left
, Top
, Right
, Bottom
that should not be modified.
AutoClose
and BackgroundColor
can be modified after creation, but there should not be a lot of case.
See Panel for full list of properties.
Show and hide panels
There are three functions:
This will force a redraw of the window, in debug mode, this can create a short blink, but this was not perceptible in normal mode (run from the Scripts menu).
Move panel
In the case you want a panel appear at the click position, or some other strange cases,
do not change Left and Top properties!
Call SMDialog:movePanel(...). This will move all its content (components and items).
Note: use movePanel as "one shot", not for frequente moves like a sliding effect or a falling Tetris brick ;)
This would consume more CPU and need more graphical refreshs.
Add an item in a panel
For button, you know, it's the last argument of SMDialog:addButton(...)
. Other components (see below) have also a panel argument.
For item (knob, list, note head/length selector, text box...), just click on each item and add a line in their Init function:
function Init(dialog,item) item.UserTable.Panel="MyPanel" end
If you also set item.AreaLeft=x
and item.AreaTop=y
,
these are absolute positions from left/top corner of the window.
This will be converted into relative position to the left/top of the panel so the item will follow the panel's moves. :)
Dialog.UserTable
smDialog is a variable (a SMDialog object) created in your dialog's Init function.
It is only visible by other dialog's function (Draw, Idle) where we call smDialog:handleDraw()
, smDialog.handleIdle()
...
But, in all events such as button click, you may need to access smDialog, to show/hide/move panels,
to get a component and change its properties... and there, smDialog variable is not visible.
In events, the native MyrScript Dialog is visible, given as dialog argument.
Dialog.UserTable is the bridge
A Lua table can contain functions.
Due to technical limitations, it was not possible to add directly function to the native Dialog object,
so I used Dialog.UserTable. See it for list of properties and functions.
Dialog.UserTable functions require dialog as first argument, else they
will raise an error. This is also a Lua standard.
For Java devs, these are static function, while object:doSomething() calls a method of an object).
Example: dialog.UserTable.HidePanel(dialog, name)
calls smDialog:hidePanel(name)
.
Dialog.DrawContent()
The Dialog.DrawContent()
in MyrScript manual, say it redraw completely the window.
But it doesn't know SMDialog at all.
SMDialog optimizes drawing, only needed buttons are redrawn instead of the whole window (it's around 3 times faster).
Don't call Dialog.DrawContent()
, buttons will disappear!
Call dialog.UserTable.DrawContent(dialog)
instead.
It forces SMDialog:handleDraw(...) to redraw all components.
Component zoo
MinX=-50, MaxX=50, MinY=-30, MaxY=30, OrientationY=ORIENTATION_SOUTH
Summary
Field | Type | Summary |
---|---|---|
A11yTitle | string | Alternative title for screen reader. |
ListenMidiEvents | boolean | Listen Midi events that can interact with components. |
MidiAllowAftertouch | boolean | Listen for aftertouch Midi events? |
MidiAllowCC | boolean | Listen for Controller Change (CC) midi events? |
MidiAllowNoteOff | boolean | Listen for "Note Off" Midi events? |
MidiAllowNoteOn | boolean | Listen for "Note On" Midi events? |
MidiAllowOthers | boolean | Allow other (unknown) Midi events? |
MidiAllowPitchBend | boolean | Listen for Pitch Bend wheel midi events? |
MidiAllowProgramChange | boolean | Listen for Program Change (instrument change) Midi events? |
MidiDelay | int | Delay to filter repetitive calls of component refresh or component Midi event handler functions. |
UpAndDownArrowsLikeTabs | boolean | Use Up and Down keyboard arrows like Tab to focus previous/next component? |
Return type | Function and summary |
---|---|
SMDialog | new(Dialog dlg, boolean debugBoundaries, string preferencesDirectory) SMDialog constructor. |
Component | addButton(string name, number left, number top, number right, number bottom, string caption, string help, number captionSize, number captionFace, string panel) Creates a button in the dialog. |
Grid | addGrid(string name, number left, number top, number right, number bottom, string help, number captionSize, number captionFace, string panel) Adds a Grid to the dialog. |
Knob | addKnob(string name, number left, number top, number right, number bottom, string caption, string help, number captionSize, number captionFace, string panel, number minValue, number maxValue, number defaultValue, number currentValue, number step) Add a knob. |
Component | addLabel(string name, number left, number top, number right, number bottom, string caption, string help, number captionSize, number captionFace, string panel) Add a label. |
Panel | addPanel(string name, number left, number top, number right, number bottom, boolean visible, boolean autoClose, string backgroundColor, boolean shrink) Creates a panel which will contain Components and DialogItems. |
Slider | addSlider(string name, number left, number top, number right, number bottom, string help, number captionSize, number captionFace, string panel, number minValue, number maxValue, number defaultValue, number currentValue, number step) Add a slider. |
Spinner | addSpinner(string name, number left, number top, number right, number bottom, string help, number captionSize, number captionFace, string panel, table valuesList, string defaultValue, boolean isVertical, string arrowsLocation) Add a spinner. |
Switchable | addSwitchable(string name, number left, number top, number right, number bottom, string caption, string help, number captionSize, number captionFace, string panel, string switchType, int switchAlign, boolean switchState) Add a switchable element: checkbox or switch. |
XYSlider | addXYSlider(string name, number left, number top, number right, number bottom, string help, number captionSize, number captionFace, string panel, number minX, number maxX, number defaultX, number currentX, number stepX, number minY, number maxY, number defaultY, number currentY, number stepY) Add a 2D slider to pick a couple of x,y values within bounds. |
string | focus(btn) Set the focus, if possible, to a Component or a DialogItem. |
Component | getComponent(string name) Retrive a Component by its name, which is unique identifier. |
Component | getComponentUnderMouse() Get the Component under mouse pointer |
string | getPreferencesDirectory() If set as 3rd argument at SMDialog:new , return the full preferences directory. |
handleDraw(number defaultCaptionSize, number defaultCaptionFace) Draw all Components of SMDialog. | |
handleExit() Called at Dialog exit. | |
handleIdle() During what MyrScript consider as "idle", clicks and mouse moves may happen; this handles them, and more. | |
boolean | handleKeyDown(dummy, int key, string keyAsString) Handles key strokes, send them to the focused button or component, or navigate throught them. |
handleMouseWheel(Score score, number amount) Handles mouse wheel events, send them to the Component or component under mouse pointer. | |
hideAllPanels() Hide all panels, don't forget to all SMDialog:showPanel(...) after else you'll get an empty window. | |
hidePanel(string name) Hide the given panel. | |
movePanel(string name, number x, number y, boolean avoidOutside, boolean allowSymetry) Moves a panel and its content to a new x,y position. | |
saveDialogArea() Save the Dialog area, call it in the Exit function. | |
setDialogArea(int left, int top, int width, int height) Set the Dialog area. | |
showPanel(string name) Show the given panel. |
Fields
string SMDialog:A11yTitle
Alternative title for screen reader.
boolean SMDialog:UpAndDownArrowsLikeTabs
Use Up and Down keyboard arrows like Tab to focus previous/next component?
Don't use it if your dialog contains Grid, Slider, XYSlider, or Spinner.
boolean SMDialog:ListenMidiEvents
Listen Midi events that can interact with components.
Not recommanded for floating window script, unless you really know what you are doing. Once set to true
, set all MidiAllow* and MidiDelay settings.
boolean SMDialog:MidiAllowNoteOn
Listen for "Note On" Midi events?
boolean SMDialog:MidiAllowNoteOff
Listen for "Note Off" Midi events?
boolean SMDialog:MidiAllowCC
Listen for Controller Change (CC) midi events?
Controller Change may fire a lot of events. If you use them only to interact with knobs and sliders, set the MidiDelay value to something like 100 milliseconds, else it will call many times the refresh of components.
boolean SMDialog:MidiAllowProgramChange
Listen for Program Change (instrument change) Midi events?
Program Change event are not used to interact with SMDialog components, so it's turned false
by default.
boolean SMDialog:MidiAllowAftertouch
Listen for aftertouch Midi events?
Aftertouch events are very numerous and not used to interact with SMDialog components, so it's turned false
by default.
boolean SMDialog:MidiAllowPitchBend
Listen for Pitch Bend wheel midi events?
Pitch bend may fire a lot of events. If you use them only to interact with knobs and sliders, set the MidiDelay value to something like 100 milliseconds, else it will call many times the refresh of components.
boolean SMDialog:MidiAllowOthers
Allow other (unknown) Midi events?
int SMDialog:MidiDelay
Delay to filter repetitive calls of component refresh or component Midi event handler functions.
Methods
SMDialog:new(Dialog dlg, boolean debugBoundaries, string preferencesDirectory)
SMDialog constructor.
This creates a SMDialog object and adds methods in Dialog.UserTable.
Parameter | Type | Default | Description |
---|---|---|---|
dlg | Dialog | The MyrScript Dialog object | |
debugBoundaries | boolean | false | Add frames around all panels and components, only when script is run in debug mode. |
preferencesDirectory | string | nil | Sub-directory of GetPreferencesPathName() where are stored dialog area and other preferences. If nil or "", saving and loading preferences are inhibited. By convention, to avoid collision between script, you should prefix the directory name with the 5 first chars of your licence key. |
- Return
- SMDialog: SMDialog
- Error
- If dialog is
nil
SMDialog:setDialogArea(int left, int top, int width, int height)
Set the Dialog area.
If position was previously saved by SMDialog:saveDialogArea()
, it is restaured.
If loaded or argument left/top are out of screen boundaries, they are not applied.
Position is stored in dialog.cfg in preferences directory (if given at SMDialog constructor).
Parameter | Type | Default | Description |
---|---|---|---|
left | int | left | |
top | int | top | |
width | int | width | |
height | int | height |
SMDialog:saveDialogArea()
Save the Dialog area, call it in the Exit
function.
Position is stored in dialog.cfg in preferences directory (if given at SMDialog constructor).
SMDialog:getPreferencesDirectory()
If set as 3rd argument at SMDialog:new
, return the full preferences directory.
The directory is automatically created in GetPreferencesPathName()
- Return
- string:
GetPreferencesPathName() .. preferencesDirectory
if set and exists, elsenil
.
SMDialog:addPanel(string name, number left, number top, number right, number bottom, boolean visible, boolean autoClose, string backgroundColor, boolean shrink)
Creates a panel which will contain Components and DialogItems.
Hiding or showing a panel will hide or show all its components and items.
Panels can be used as multi-page covering the whole dialog area, as tabbed-panels, as submenus.
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Identifier of the panel, "" not allowed | |
left | number | 0 | Left position of the panel. if >= 0 then left is relative to dialog's left border, if < 0 then left is relative to dialog's right border (AreaWidth) |
top | number | 0 | Top position of the pane. if >= 0 then top is relative to dialog's top border, if < 0 then top is relative to dialog's bottom border (AreaHeight) |
right | number | dialog.AreaWidth | Right position of the panel. if >= 0 then right is relative to dialog's left border, if < 0 then right is relative to dialog's right border (AreaWidth) |
bottom | number | dialog.AreaHeight | Bottom position of the panel. if >= 0 then bottom is relative to dialog's top border, if < 0 then bottom is relative to dialog's bottom border (AreaHeight) |
visible | boolean | false | Initial visibility |
autoClose | boolean | false | Close the panel on click outside it? |
backgroundColor | string | nil | Background color in RRGGBB[AA] format, nil for transparent. |
shrink | boolean | false | Panel boundaries will be adjusted to contain DialogItems and Components that can be outside of original boundaries. Will it shrink (true ) or only extand (false )? |
- Return
- Panel: A table containing panel properties: Name, Top, Left, Right, Bottom...
- Errors
- if name is missing or empty
- if right < left or bottom < top
- if panel already exists
SMDialog:hidePanel(string name)
Hide the given panel.
You can call it by dialog.UserTable.HidePanel(dialog, name)
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Name of the panel to hide |
- Errors
- if panel doesn't exist
- if called within
function Init(dialog)
, use 'visible' argument ofSMDialog:addPanel
instead.
SMDialog:hideAllPanels()
Hide all panels, don't forget to all SMDialog:showPanel(...)
after else you'll get an empty window.
You can call it by dialog.UserTable.HideAllPanels(dialog)
- Error
- if called within
function Init(dialog)
, use 'visible' argument ofSMDialog:addPanel
instead.
SMDialog:showPanel(string name)
Show the given panel.
You can call it by dialog.UserTable.ShowPanel(dialog, name)
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Name of the panel to show |
- Errors
- if panel doesn't exist
- if called within
function Init(dialog)
, use 'visible' argument ofSMDialog:addPanel
instead.
SMDialog:movePanel(string name, number x, number y, boolean avoidOutside, boolean allowSymetry)
Moves a panel and its content to a new x,y position.
You can call it by dialog.UserTable.MovePanel(dialog, name, x, y)
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Name of the panel to move | |
x | number | New horizontal position of the left/top corner of the panel | |
y | number | New vertical position of the left/top corner of the panel | |
avoidOutside | boolean | false | Do you accept to move the panel partially or fully outside of the window? If not, the extremes points of items of the panel will be used to calculate a new position inside window. |
allowSymetry | boolean | false | Useful for contextual/popup menu, if true and if there is not enoguh space between x,y and right/bottom edges of the window, this will try to place the right/top or right/bottom corner of the panel at x,y. |
- Error
- if panel doesn't exist or x,y are not valid parmeters
SMDialog:focus(btn)
Set the focus, if possible, to a Component or a DialogItem.
Parameter | Type | Default | Description |
---|---|---|---|
btn | nil | Component or DialogItem object or name (string). If nil , focus will not change. |
- Return
- string: The focused Component or DialogItem's name, or
nil
if no focus.
SMDialog:addButton(string name, number left, number top, number right, number bottom, string caption, string help, number captionSize, number captionFace, string panel)
Creates a button in the dialog.
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Identifier of the button. "outside" and "inside" are reserved names. | |
left | number | 0 | Left position of the button's frame.
|
top | number | 0 | Top position of the button's frame.
|
right | number | panel's right | Right position of the button's frame.
|
bottom | number | panel's bottom | Bottom position of the button's frame.
|
caption | string | nil | Caption text of the button. nil or "" for no text |
help | string | nil | Contextual help message |
captionSize | number | nil | Font size |
captionFace | number | nil | Font face, use sum of constants from MSDefine such as FACE_BOLD |
panel | string | "main" | Name of the Panel that will contain the button |
- Return
- Component: A table where you can customize more the button and add events. See Component.
- Errors
- if name is missing, reserved or already used
- if right < left or bottom < top
- if panel doesn't exist. Panel named
"main"
is automatically created, other panels need a call ofSMDialog:addPanel(...)
.
SMDialog:addLabel(string name, number left, number top, number right, number bottom, string caption, string help, number captionSize, number captionFace, string panel)
Add a label.
It calls SMDialog:addButton(...)
, removes the frame (background palette button), and horizontal align it to left.
You can still change these settings. This function is just a shortcut ;)
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Identifier of the label. "outside" and "inside" are reserved names. | |
left | number | 0 | Left position of the label's edge.
|
top | number | 0 | Top position of the label's edge.
|
right | number | panel's right | Right position of the label's edge.
|
bottom | number | panel's bottom | Bottom position of the label's edge.
|
caption | string | nil | Caption text of the label. nil or "" for no text |
help | string | nil | Contextual help message |
captionSize | number | nil | Font size |
captionFace | number | nil | Font face, use sum of constants from MSDefine such as FACE_BOLD |
panel | string | "main" | Name of the Panel that will contain the label |
- Return
- Component: A table where you can customize more the label and add events.
- Errors
- if name is missing, reserved or already used
- if right < left or bottom < top
- if panel doesn't exist. Panel named
"main"
is automatically created, other panels need a call ofSMDialog:addPanel(...)
.
SMDialog:addSwitchable(string name, number left, number top, number right, number bottom, string caption, string help, number captionSize, number captionFace, string panel, string switchType, int switchAlign, boolean switchState)
Add a switchable element: checkbox or switch.
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Identifier of the component. "outside" and "inside" are reserved names. | |
left | number | 0 | Left position of the component's edge.
|
top | number | 0 | Top position of the component's edge.
|
right | number | panel's right | Right position of the component's edge.
|
bottom | number | panel's bottom | Bottom position of the component's edge.
|
caption | string | nil | Caption text of the switchable component. nil or "" for no text |
help | string | nil | Contextual help message |
captionSize | number | nil | Font size |
captionFace | number | nil | Font face, use sum of constants from MSDefine such as FACE_BOLD |
panel | string | "main" | Name of the Panel that will contain the label |
switchType | string | "checkbox" | Type of the switch: "checkbox", "radio", "horizontal switch" |
switchAlign | int | depends on switchType | Checkbox/switch alignment, ALIGN_LEFT or ALIGN_RIGHT ALIGN_CENTER is also allowed if CaptionVerticalAlign is set to one of VERTICAL_ALIGN_TOP, VERTICAL_ALIGN_BOTTOM . By default, checkbox is on the left, horizontal switch on the right. |
switchState | boolean | false | true tick the checkbox, false untick it it, nil means unknown state. |
- Return
- Switchable: A Component, with click and space key handled, where you can add a
OnChange(...)
event. - Errors
- if name is missing, reserved or already used
- if right < left or bottom < top
- if panel doesn't exist. Panel named
"main"
is automatically created, other panels need a call ofSMDialog:addPanel(...)
.
SMDialog:addGrid(string name, number left, number top, number right, number bottom, string help, number captionSize, number captionFace, string panel)
Adds a Grid to the dialog.
A grid has columns with headers and ID that are Excel-like letters "A", "B", ... "Z", "AA"... and rows from 1 to N.
Download this script to fully test Grid features.
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Identifier of the grid. "outside" and "inside" are reserved names. | |
left | number | 0 | Left position of the grid.
|
top | number | 0 | Top position of the grid.
|
right | number | panel's right | Right position of the grid.
|
bottom | number | panel's bottom | Bottom position of the grid.
|
help | string | nil | Contextual help message |
captionSize | number | 8 | Font size |
captionFace | number | FACE_NONE | Font face, use sum of constants from MSDefine such as FACE_BOLD |
panel | string | "main" | Name of the Panel that will contain the grid |
- Return
- Grid: A table with all Component properties and Grid special properties and event implementations.
- Errors
- if name is missing, reserved or already used
- if right < left or bottom < top
- if panel doesn't exist. Panel named
"main"
is automatically created, other panels need a call ofSMDialog:addPanel(...)
.
SMDialog:addSlider(string name, number left, number top, number right, number bottom, string help, number captionSize, number captionFace, string panel, number minValue, number maxValue, number defaultValue, number currentValue, number step)
Add a slider.
This is a Component with vertical or horizontal drawbar, handled events, min, max and value labels, custom steps... things that Harmony's native scroll and slider don't have.
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Identifier of the component. "outside" and "inside" are reserved names. | |
left | number | 0 | Left position of the slider's frame.
|
top | number | 0 | Top position of the slider's frame.
|
right | number | panel's right | Right position of the slider's frame.
|
bottom | number | panel's bottom | Bottom position of the slider's frame.
|
help | string | nil | Contextual help message. If nil, a contextual help is generated, explaining how to change value with mouse wheel and keyboard. |
captionSize | number | nil | Font size |
captionFace | number | nil | Font face, use sum of constants from MSDefine such as FACE_BOLD |
panel | string | "main" | Name of the Panel that will contain the slider |
minValue | number | 0 | Minimal value |
maxValue | number | 0 | Maximal value |
defaultValue | number | currentValue | Default (factory) value, a dual click on the slider goes back to this value |
currentValue | number | defaultValue | Current displayed value |
step | number | 1 | Step between two consecutive possible values. e.g. 1 for a value from 0 to 127, 0.01 for fine adjustement of object position in the score... The bigger the faster mouse wheel and keyboard will change the value. |
- Return
- Slider: A table with all Component properties and Slider special properties and event implementations.
- Errors
- if name is missing, reserved or already used
- if right < left or bottom < top
- if panel doesn't exist. Panel named
"main"
is automatically created, other panels need a call ofSMDialog:addPanel(...)
. - if minValue >= maxValue
- if defaultValue or currentValue are outside of [minValue:maxValue] range
- if defaultValue and currentValue are
nil
.
SMDialog:addKnob(string name, number left, number top, number right, number bottom, string caption, string help, number captionSize, number captionFace, string panel, number minValue, number maxValue, number defaultValue, number currentValue, number step)
Add a knob.
This is a Component with circular drawing, handled events, min, max and value labels, custom steps... things that Harmony's native knob don't have.
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Identifier of the component. "outside" and "inside" are reserved names. | |
left | number | 0 | Left position of the knob's frame.
|
top | number | 0 | Top position of the knob's frame.
|
right | number | panel's right | Right position of the knob's frame.
|
bottom | number | panel's bottom | Bottom position of the knob's frame.
|
caption | string | nil | Caption displayed below the knob. |
help | string | nil | Contextual help message. If nil, a contextual help is generated, explaining how to change value with mouse wheel and keyboard. |
captionSize | number | nil | Font size |
captionFace | number | nil | Font face, use sum of constants from MSDefine such as FACE_BOLD |
panel | string | "main" | Name of the Panel that will contain the slider |
minValue | number | 0 | Minimal value |
maxValue | number | 0 | Maximal value |
defaultValue | number | currentValue | Default (factory) value, a dual click on the slider goes back to this value |
currentValue | number | defaultValue | Current displayed value |
step | number | 1 | Step between two consecutive possible values. e.g. 1 for a value from 0 to 127, 0.01 for fine adjustement of object position in the score... The bigger the faster mouse wheel and keyboard will change the value. |
- Return
- Knob: A table with all Component properties and Knob special properties and event implementations.
- Errors
- if name is missing, reserved or already used
- if right < left or bottom < top
- if panel doesn't exist. Panel named
"main"
is automatically created, other panels need a call ofSMDialog:addPanel(...)
. - if minValue >= maxValue
- if defaultValue or currentValue are outside of [minValue:maxValue] range
- if defaultValue and currentValue are
nil
.
SMDialog:addXYSlider(string name, number left, number top, number right, number bottom, string help, number captionSize, number captionFace, string panel, number minX, number maxX, number defaultX, number currentX, number stepX, number minY, number maxY, number defaultY, number currentY, number stepY)
Add a 2D slider to pick a couple of x,y values within bounds.
This is a Component with custom drawing, handled events, additional properties.
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Identifier of the XYSlider. "outside" and "inside" are reserved names. | |
left | number | 0 | Left position of the XYSlider's frame.
|
top | number | 0 | Top position of the XYSlider's frame.
|
right | number | panel's right | Right position of the XYSlider's frame.
|
bottom | number | panel's bottom | Bottom position of the XYSlider's frame.
|
help | string | nil | Contextual help message. If nil, a contextual help is generated, explaining how to change value with mouse wheel and keyboard. |
captionSize | number | nil | Font size |
captionFace | number | nil | Font face, use sum of constants from MSDefine such as FACE_BOLD |
panel | string | "main" | Name of the Panel that will contain the button |
minX | number | 0 | Minimal value for X |
maxX | number | 0 | Maximal value for X |
defaultX | number | currentX | Default (factory) value for X, a dual click on the slider goes back to this value |
currentX | number | defaultX | Current displayed X value |
stepX | number | 1 | Step between two consecutive X possible values. e.g. 1 for a value from 0 to 127, 0.01 for fine adjustement of object position in the score... The bigger the faster mouse wheel and keyboard will change the value. |
minY | number | 0 | Minimal value for Y |
maxY | number | 0 | Maximal value for Y |
defaultY | number | currentY | Default (factory) value for Y, a dual click on the slider goes back to this value |
currentY | number | defaultY | Current displayed Y value |
stepY | number | 1 | Step between two consecutive Y possible values. e.g. 1 for a value from 0 to 127, 0.01 for fine adjustement of object position in the score... The bigger the faster mouse wheel and keyboard will change the value. |
- Return
- XYSlider: A table with all Component properties and XYSlider special properties and event implementations.
- Errors
- if name is missing, reserved or already used
- if right < left or bottom < top
- if panel doesn't exist. Panel named
"main"
is automatically created, other panels need a call ofSMDialog:addPanel(...)
. - if minX >= maxX or minY >= maxY
- if defaultX or currentX are outside of [minX:maxX] range
- if defaultY or currentY are outside of [minY:maxY] range
- if defaultX and currentX, or defaultY and currentY are
nil
.
SMDialog:addSpinner(string name, number left, number top, number right, number bottom, string help, number captionSize, number captionFace, string panel, table valuesList, string defaultValue, boolean isVertical, string arrowsLocation)
Add a spinner.
This is a Component that allow user to cycle through values. The spinner allows the user to select a value from a defined list using mouse wheel or click on arrow buttons. This is kind of menu with more mouse interactions and now popup menu that are sometimes too large.
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Identifier of the spinner. "outside" and "inside" are reserved names. | |
left | number | 0 | Left position of the spinner's edge.
|
top | number | 0 | Top position of the spinner's edge.
|
right | number | panel's right | Right position of the spinner's edge.
|
bottom | number | panel's bottom | Bottom position of the spinner's edge.
|
help | string | nil | Contextual help message. If nil, a contextual help is generated, explaining how to change value with mouse wheel and keyboard. |
captionSize | number | nil | Font size |
captionFace | number | nil | Font face, use sum of constants from MSDefine such as FACE_BOLD |
panel | string | "main" | Name of the Panel that will contain the button |
valuesList | table |
| |
defaultValue | string | nil | Default value from the list. If nil first value from the list is selected. |
isVertical | boolean | true | false for Horizontal (left/right), true for vertical (up/down on the right) arrows |
arrowsLocation | string | nil | Location of the arrows around the spinner.
|
- Return
- Spinner: A table with all Component properties and Spinner special properties and event implementations.
- Errors
- if name is missing, reserved or already used
- if right < left or bottom < top
- if panel doesn't exist. Panel named
"main"
is automatically created, other panels need a call ofSMDialog:addPanel(...)
.
SMDialog:getComponentUnderMouse()
Get the Component under mouse pointer
- Return
- Component:
nil
if no component under mouse pointer
SMDialog:getComponent(string name)
Retrive a Component by its name, which is unique identifier.
Parameter | Type | Default | Description |
---|---|---|---|
name | string | Wanted component's name |
- Return
- Component:
nil
if not found
SMDialog:handleKeyDown(dummy, int key, string keyAsString)
Handles key strokes, send them to the focused button or component, or navigate throught them.
In your Dialog's KeyDown function, just call: smDialog:handleKeyDown(dummy,key)
Parameter | Type | Default | Description |
---|---|---|---|
dummy | I really don't know what this may contains | ||
key | int | This may be nil in case of usage of F1 to F12 keys. | |
keyAsString | string | nil | Internal use, set it to nil. |
- Return
- boolean:
true
if the key continue to be processed (e.g. send to the FrontScore()),false
otherwise. The return value is given by button's OnKeyDown function - See
- Component.OnKeyDown
SMDialog:handleMouseWheel(Score score, number amount)
Handles mouse wheel events, send them to the Component or component under mouse pointer.
In your Dialog's MouseWheel(dialog, score, amount)
just call: smDialog:handleMouseWheel(score, amount)
Parameter | Type | Default | Description |
---|---|---|---|
score | Score | The FrontScore() ?? | |
amount | number | The amount of the scroll on mouse wheel |
SMDialog:handleIdle()
During what MyrScript consider as "idle", clicks and mouse moves may happen; this handles them, and more.
In your Dialog's Idle function, just call:
smDialog:handleIdle()
It will:
- update user interface according to mouse coordinates
- change cursor shape
- fire the following events: OnClick, OnClickRelease, OnMouseEnter, OnMouseLeave, OnMouseMove, OnMouseOver, OnMidi* and OnIdle
SMDialog:handleDraw(number defaultCaptionSize, number defaultCaptionFace)
Draw all Components of SMDialog.
In your Dialog's Draw function, just call: smDialog:handleDraw(...)
Parameter | Type | Default | Description |
---|---|---|---|
defaultCaptionSize | number | 11 | Default caption font size if not specified in SMDialog:addButton(...) |
defaultCaptionFace | number | FACE_NONE | Default caption font face, sum of constants from MSDefine |
SMDialog:handleExit()
Called at Dialog exit.
In your Dialog's Exit function, just call:
smDialog:handleExit()
It will fire the OnExit event of the components.