2D Grid Palette of Buttons: Virtual Elgato Stream Deck

KM_GridPalettes is a program that can take on the role of an Elgato Stream Deck by presenting a grid of buttons on the screen that the user can click on and activate Keyboard Maestro macros. If you have enough screen real estate you might be able to save some money and some space on your desk by using this program. This grid palette supplements the palettes that are built into Keyboard Maestro and is advantageous in some circumstances.

The program is available for free at my website. There is also a manual in PDF format. I would be interested in comments and suggestions from anyone interested in giving it a try.

Screen Shot 2021-02-23 at 8.30.11 AM

Website:
http://bearboat.net/KM_Palettes/KM_Palette.html

Short YouTube Video:
https://youtu.be/OvZSelaSsPQ

Longer, more convoluted YouTube Video:
https://youtu.be/swtQZkPAYgo

6 Likes

cool, will definitely try it with my iPad using the Duet app.
thanks @rlivingston

2 Likes

@rlivingston - Looks interesting but please help me figure out what makes this truly different than the native KM Palettes that can be inherently made to do the same thing. If it's about a grid of icons or a shortcut showing next to it, KM already does that. I admit, I performed only a cursory look, at the site, but I didn't convince myself that this was any different of what was available. Just curious. Sorry to be that guy, I would just like to understand. I've attached some native KM palettes below.

Screen Shot 2021-02-23 at 2.15.28 PM

KC

My knowledge of the native tools for building palettes in Keyboard Maestro is not as deep as it should be.

1 Like

Palettes are the main way I use Keyboard Maestro. Once you create one, you can manipulate the columns, rows, titles, show the hot keys, auto shrink it, use or not use icons etc. Reach out if you need help. I’m was hoping you didn’t code your creation when the developer has already done the work many moons ago... Sorry.

KC

Don't be sorry. I am just fine. I spent a couple hours learning more of the ins and outs of the KM Palettes. They are a very different animal than KM_GridPalettes.

Some things can be done with KM_GridPalettes that are kludgy but not impossible with the native tools. (Duplicating a macro only for the purpose of having two versions of the icon for example or having multiple Macro Groups only for the purpose of presenting a different Macro -- you can just have duplicates in each Group.) The native tools have their own set of advantages.

Some characteristics:

Native:

  1. The native palettes use a model that icons are associated with a specific macro.
  2. Things that appear on the Macro Group palette are members of a Macro Group that are enabled at the particular time
  3. The position of the buttons on a Grid are determined by alphabetical order with a native work-around that involves placing some characters to the left of a ")" which affects the position but does not appear on the palette. -- "01)Friendly Name"
  4. The text associated with a "button" on the grid is the name of the macro.
  5. If you include text, the size of the palette and the individual button is influenced by the length of the text. It is not hard to create a palette that does not fit on the screen.
  6. Native palettes come and go depending on the foremost app. You could consider that a feature or an annoyance.

KM_GridPalettes:

  1. The icons are associated with the palette and not the specific macro. So easy to have the same macro represented by a different looking button on two different palettes
  2. Members on the palette are controlled at the time the palette is designed. It could include all the macros in a group or not. And you could have two palettes, one with one subset and the other with another subset and simply switch back and forth.
  3. The position of the buttons on the Grid is determined by where you place them at the time of design not alphabetical order. You can have blank spaces anywhere you want in the grid rather than just the left over spaced at the end of the last row.
  4. The text associated with a button is handled very differently. They are called "Tips" in the app and only appear as a reminder when the cursor overlies the button. This greatly reduces clutter. That text can be anything you want; it does not have to be the official name of the macro. It also allows the size of the palette to be more controlled; you do not have to worry about some long macro name. There is actually a second piece of text that can be accessed associated with a given button. The amount of text this can contain is essentially unlimited if the purpose/function of a button requires a lengthy explanation.
  5. If you want to include an icon AND text, with the native palettes you can find yourself having a very small (less recognizable) icon just so you can fit on more buttons. KM_GridPalettes has stable sized buttons and any text associated with the palette is called up when the cursor overlies the button.
  6. It is easy to have many palettes in KM_GridPalettes. They are not associated with macro groups. You could have five palettes essentially acting on the parts one macro group if you want. And it could include macros from other groups. With the native control there is one macro group.
  7. Keyboard shortcuts within KM_GridPalettes a simple one character clicks. If it is the foremost application, this will just be handled. You do have to come up with some "complex" Control-Option-Command- W and then worry about that inadvertently being recognized as meaningful by some app outside of KM_GridPalettes. The shortcut that is being used can either be "always visible" (but very small in the corner of the icon) or only revealed when the cursor is over the button simply as a reminder. Again a space saver.

The native palettes are complex at some level. So many contingencies are addressed by the app. With various kludges, you could do many things that are not straight forward. It is very impressive.

Is this a criticism or praise? It is what it is.

Finally, what makes this all weird is that since KM_GridPalettes is just an app, Keyboard Maestro can control it and do anything inside the program (like choose another active palette or click on a button in that palette). It is designed to make that easy. Meanwhile since KM_GridPalettes has the ability to control Keyboard Maestro, it can reciprocate. It is quite possible to create a hybrid tool. You could have palettes from each app active on the screen at the same time.

KM already does that. I admit, I performed only a cursory look, at the site, but I didn't convince myself that this was any different of what was available.

I learned a lot by diving into Keyboard Maestro palettes. You could do the same by diving into KM_GridPalettes. Obviously, you needn't do that. It is up to you. But it, in fact, is quite different from what is available in native Keyboard Maestro.

But there is a lot of overlap as well, and many circumstances where either could effectively accomplish the "same thing."

4 Likes

try setting up one GM_Palette_Grid and you will know the differences.

I tried and IT IS different, thanks for your effort and sharing it, really appreciate it !
(the design or UI may looks a bit crude, but it works like breeze :+1:)

love it! :heart:

Hi @rlivingston, Thanks for developing this. It's handy.

I was wondering, instead of making a macro with a switch that has up to 100 cases, can you program it to execute one of the 100 macros (named 00~99) that is within a macro group named P00, P01 etc.?

I did a search on the forum and it looks like it is doable. See:

I have made some modification to the AS made by @gglick and tested it myself. I'm not familiar with AS at all. There is probably a better way to match an item in a list, but here is what it works:

set macroGroupName to "P00" as string
set macroNameInGroup to "00" as string

tell application "Keyboard Maestro"
	tell its macro group macroGroupName
		set MacroIdList to id of every macro
		set MacroNameList to name of every macro
	end tell
end tell

tell application "Keyboard Maestro Engine"
	repeat with i from 1 to (count of MacroNameList)
		if macroNameInGroup is equal to item i of MacroNameList as string then
			set MacroToRun to item i of MacroIdList
			do script MacroToRun
			return
		end if
	end repeat
end tell

OK. I think I find a way to do it myself.

Change the content of the file FirePalette.scpt in /Applications/KM_GridPalettes.app/Contents/Resources/ from

# thePalette is passed from Xojo (P00, P01, P02 etc.)
# theButton is passed from Xojo (00, 01, 02, 10, 11, 12 and such)
on run {thePalette, theButton}
	tell application "Keyboard Maestro Engine"
		# Keyboard Maestro is told to run the Macro: thePalette
		# Macro P00 regards all the things that P00 does (P00 is the first palette, P01 would be the second)
		# Macro P00 is told which button in the parameter theButton
		
		# if there is no Macro called thePalette, this will silently fail to do anything
		do script thePalette with parameter theButton
	end tell
end run

to

# thePalette is passed from Xojo (P00, P01, P02 etc.)
# theButton is passed from Xojo (00, 01, 02, 10, 11, 12 and such)
on run {thePalette, theButton}
	
	-- designate the Macro Group and the Macro to run
	set macroGroupName to thePalette as string
	set macroNameInGroup to theButton as string
	
	-- get a list of IDs and Names of all macros in the Macro Group
	tell application "Keyboard Maestro"
		tell its macro group macroGroupName
			set MacroIdList to id of every macro
			set MacroNameList to name of every macro
		end tell
	end tell
	
	-- execute the designated macro
	tell application "Keyboard Maestro Engine"
		repeat with i from 1 to (count of MacroNameList)
			if macroNameInGroup is equal to item i of MacroNameList as string then
				set MacroToRun to item i of MacroIdList
				do script MacroToRun
				return
			end if
		end repeat
	end tell
end run

Now the button "00", "01", etc. in Palette "P00", "P01", etc. of KM_GridPalettes will fire: the macro named "00", "01", etc. in the Macro Group named "P00", "P01", etc. in KM. :grinning:
(Why I did mod.: I can easily manage a macro group with 100 macros, but it's difficult to manage a macro with 100 switch cases).

1 Like

It is an interesting idea. And it is very clever that you seem to have been able to do this on your own without actually changing the code of KM_GridPalettes. You simply have gone into the Resources folder of the app and found and modified the AppleScript stored there. Who would have thought it?

When I first was trying to implement KM_GridPalettes, I wondered just how Keyboard Maestro should be organized so as to respond to the requests. The most straight-forward way would be as you suggest: essentially every button of the KM_GridPalettes should be linked in a one-to-one relationship to a macro in Keyboard Maestro. So I conceived a system in my mind that every macro would have a unique name corresponding to a button. That would have been of the form: P02_05. The name would convey the palette and the button: Palette - P02 and Button - 05.

I veered away from this because I thought it would be unwieldy A huge pile of macros all in one group with this naming structure. I did not think of the structure that you came up with: each palette would be its own Group filled with macros corresponding to its buttons - At most 100 macros in one Group.

I settled on the system of having each palette correspond with a single macro and that macro determining the actions depending on the button that was clicked. Within that macro, you could have a switch that determined the action of a particular button. A natural arrangement would have each switch statement invoke a specific macro (Execute Macro) but that would not be absolutely necessary. If your intent was just to perform a couple of actions you could put them right there in the switch without bothering to actually create a corresponding macro. Even if just invoking macros (Execute Macro) you would not have to use some rigid naming structure like P02_05. You could use some more human-friendly name. And you could access macros that you had already written and assigned whatever name you did in the past and they might exist anywhere.

It is not a big deal in the sense that it is easy enough to rename or duplicate and rename an existing macro P02_05 and if you want to put in an explanatory comment, it ends up being pretty clear. As palettes get larger (more buttons), there is more that is attractive about a more "rigid" approach. Many of the palettes that I use have only about 8-20 buttons and creating and handling the switch macro is not too difficult.

There is a lot to like, however, about the scheme that you prefer, and I wonder if I would have drifted there if I had been sophisticated enough with AppleScript to implement it.

At this point, I am very curious about how things work out for you. Whether you find it agreeable and workable over time. I could probably offer a preference in the app itself or on a palette-by-palette basis to call Keyboard Maestro one way or the other. The biggest problem for me might be trying to explain the two approaches in the documentation and what the benefits of each were. I will keep rolling this idea over in my mind.

If I were you, I would probably modify the AppleScript so that the individual macros in the group did not end up with the names 00, 01, 02, 03, etc. but rather the totally unique names P02_00, P02_01, P02_02, P02_03. It just seems to me "safer" to assign them totally unique names should your needs or approaches change in the future. You have figured out how to address the macro 01 in Group P02 distinguishing it from the macro 01 in Group P03. But it seems to me that there would be no cost and possibly a future benefit for the macros in the Group P02 to be assigned P02_00, P02_01, P02_02, etc.

I very much appreciate your chiming in. If you run into some problem that requires some modification of the code of KM_GridPalettes itself, at least tell me and possibly something could be done.

1 Like

Hi @rlivingston,
Thanks for taking the time to explain so much.

I actually prefer this method. I, then, don't need to iterate through the names all macros in a macro group. So I just edited my AppleScript to trigger macro whose name is structured as P02_05. It works great.

This makes perfect sense to me. For me, I do not want to use switch/case to manage too many cases. As more cases are added, the macro becomes longer and longer (of course, too many is subjective). Now, even using the name structured as P02_05, we could still move the macros into different macro groups when there are too many macros in a certain group.

I did not expect to be able to do that either. But as I was looking into the files, I just found out the two key strings for firing the macro: Palette name and Button name. I realized that I only need to play with these two variables.
Here is my new code:

on run {thePalette, theButton}
	-- set the name of the macro to run
	set macroName to thePalette & "_" & theButton
	
	-- execute the macro
	tell application "Keyboard Maestro Engine"
		do script macroName
	end tell
end run

If we don't want to use the numbers structured as P02_05, I guess we can further edit the AppleScript, adding an object variable, such as {"P02_05": "My KM Macro Names"}, then we will be able to retrieve the user-defined macro name for execution. But this requires us to constantly edit the AppleScript when a button is added, not feasible for mass distribution.

This idea is less intuitive, but I'll put here anyway. Since the button number is from 00 to 99, I think we could use the two digits for different purposes:
The tens digits from 0~9 can be used to identify the macro names, e.g., "P00_0", "P00_1", the single digits from 0~9 can be used for switch/cases in that macro. As a result, we will have only up to 10 macros for one Palette, and up to 10 switch/cases for each macro.

@martin your AppleScript has become cleaner, and the whole thing is easier to explain to a potential user. I will continue to mull over the idea of providing the user a choice if it is not too hard to code on the KM_GridPalettes end.

1 Like

Hi @rlivingston,

After some tests and thinking, I think your app is already pretty good.
If the macro is too long, I can easily solve this in the switch/case in KM.
Here is an example:

%TriggerValue% starts with 0 is row zero.
%TriggerValue% ends with 0 is column zero.
If there are too many rows and columns, I can make a separate macro for one row with up to 10 cases for the columns and put an "execute a macro" action in the main macro.
image

I only wish I have is to be able to suffix other descriptions to the name, something like: "P00_MyCustomMacroName". But since the AppleScript in the app triggers the macro by name. We don't have this freedom.

I've thought about some solutions and made some attempts, but the best possible solution I can think of is to offer a place in the app for users to put the UUID for each palette. Something like:

Palette Number UUID Comment
Palette00 paste UUID here Description for the macro
Palette01 paste UUID here Description for the macro

You offer 10 palettes in the app, so we only need to create 10 macros and point each palette to the UUID. Then we will have the freedom to change the macro names. But this is not a must-have. "P00", "01" are pretty straightforward. So it could be provided as an option. If users are ok with the macro names such as "P00", "P01", they don't need to do anything. If they want to change macro names, they can provide the UUIDs.
In AppleScript, add a condition.
If a UUID is provided, trigger by UUID, else, trigger by name ("P00", "P01" etc.).

I'm just offering my thoughts to see if they can help you improve your already-very-nice app. Hope you don't mind.

BTW, you may also add a help menu item that leads us to the instructions on your website.

To be clear, you can have up to 100 palettes in the app. P25 is a valid palette. P99 is a valid palette. So if you maxed out with 100 palettes and if each palette had 100 buttons, then you could have links to 10,000 macros. :woozy_face:

I am considering various ideas for my next version. It is very likely that there will be an intrinsic Help function.

If you settle on the AppleScript that comes with the program, then there are some other options for "organizing" Keyboard Maestro macros that are linked to particular buttons. Assume that you personally settle on the scheme of usually invoking specific macros with a unique name (P03_15 or actually any unique name in a switch action). You could create Groups with names that matched the names of the corresponding palette. This need not have any functional significance, it could just be a way of "organizing" your corresponding macros.

Currently, the program has the ability to give any palette a human-friendly name, what is called name/alias in the program. It enforces a rule that these name/aliases are unique. Therefore P03 also has a name/alias that you could assign something like Window Management. That might be a sensible name for a Group where you put all the macros that relate to that palette. It needn't actually be an exact match or any match at all, but Window Management might be a sensible choice for a Group name.

Thanks. I forgot we could create new palettes. (10,000 is a huge number! Currently, I have about 10% of that. And I think it's already a bit number. Can't imagine myself using about 1,000 macros! :grin:)

The names only show up as the window title, correct?
Like "KM Palette" below:
image

Is there a way to make them show up on the menu? Otherwise, we don't know what the palette is for until we switch to it and then look at the window title.
image

They are actually something different than the Window Title. Window Titles can be anything and need not be unique. Currently, the only use of the Name/Alias in the program is in the Palette List (Switch Palette under the Palette menu). There the Name/Alias is listed with the Name/ID. In this example the Window Title is MacSparky and the Name/Alias is OriginalFrog and the Name/ID is P00.

You can also change the Name/Alias in the Palette Rename/Create/Delete area under the Configure Menu.

The whole Palette Rename/Create/Delete needs to be redone. There are three largely unrelated functions crammed into this single window which is just bad design. But you can see the current Name/Alias in the Change Name area.

The next version will offer more visibility to this property. Still working this over in my mind.

Thanks, @rlivingston. I see what you mean.
The name shows in the Switch Panel window. I was hoping that they also show in the menu as part of the menu item names. Here:
image

NOT just here:
image

I have a new version out. http://bearboat.net/KM_Palettes/KM_Palette.html The basic functionality remains, but the UI involved in setting up personalized grids of buttons has been cleaned up.

Example: The new version of the palette menu.

PaletteMenu

2 Likes