Skip to content

Commit

Permalink
- added customizable keyboard shortcut system (File -> Edit shortcuts)
Browse files Browse the repository at this point in the history
  • Loading branch information
christoph-hart committed Jul 18, 2022
1 parent e5ae615 commit 6dbe3e3
Show file tree
Hide file tree
Showing 20 changed files with 506 additions and 39 deletions.
80 changes: 80 additions & 0 deletions hi_backend/backend/BackendApplicationCommandWindows.cpp
Expand Up @@ -1123,6 +1123,86 @@ class CyclicReferenceChecker: public DialogWindowWithBackgroundThread
BackendProcessorEditor* bpe;
};



struct ShortcutEditor : public QuasiModalComponent,
public Component,
public PathFactory
{
ShortcutEditor(BackendRootWindow* t) :
QuasiModalComponent(),
editor(t->getKeyPressMappingSet(), true),
closeButton("close", nullptr, *this)
{
addAndMakeVisible(editor);
setName("Edit Shortcuts");
setSize(600, 700);

editor.setLookAndFeel(&alaf);
editor.setColours(Colours::transparentBlack, alaf.bright);
setLookAndFeel(&alaf);
addAndMakeVisible(closeButton);

closeButton.onClick = [&]()
{
destroy();
};
};

Path createPath(const String&) const override
{
Path p;
p.loadPathFromData(HiBinaryData::ProcessorEditorHeaderIcons::closeIcon, sizeof(HiBinaryData::ProcessorEditorHeaderIcons::closeIcon));
return p;
}

void resized() override
{
auto b = getLocalBounds();
b.removeFromTop(32);

closeButton.setBounds(getLocalBounds().removeFromTop(37).removeFromRight(37).reduced(6));
editor.setBounds(b.reduced(10));
}

void mouseDown(const MouseEvent& e)
{
dragger.startDraggingComponent(this, e);
}

void mouseDrag(const MouseEvent& e)
{
dragger.dragComponent(this, e, nullptr);
}

juce::ComponentDragger dragger;

void paint(Graphics& g) override
{
ColourGradient grad(alaf.dark.withMultipliedBrightness(1.4f), 0.0f, 0.0f,
alaf.dark, 0.0f, (float)getHeight(), false);

auto a = getLocalBounds().removeFromTop(37).toFloat();

g.setFont(GLOBAL_BOLD_FONT().withHeight(17.0f));
g.setGradientFill(grad);
g.fillAll();
g.setColour(Colours::white.withAlpha(0.1f));
g.fillRect(a);
g.setColour(alaf.bright);

g.drawRect(getLocalBounds().toFloat());

g.drawText("Edit Shortcuts", a, Justification::centred);


}

HiseShapeButton closeButton;
AlertWindowLookAndFeel alaf;
juce::KeyMappingEditorComponent editor;
};

class SampleMapPropertySaverWithBackup : public DialogWindowWithBackgroundThread,
public ControlledObject
{
Expand Down
17 changes: 16 additions & 1 deletion hi_backend/backend/BackendApplicationCommands.cpp
Expand Up @@ -132,7 +132,7 @@ void BackendCommandTarget::getAllCommands(Array<CommandID>& commands)
MenuEditCloseAllChains,
MenuEditPlotModulator,
MenuViewShowSelectedProcessorInPopup,

MenuToolsEditShortcuts,
MenuToolsRecompile,
MenuToolsCreateInterface,
MenuToolsClearConsole,
Expand Down Expand Up @@ -373,6 +373,7 @@ void BackendCommandTarget::getCommandInfo(CommandID commandID, ApplicationComman
case MenuFileQuit:
setCommandTarget(result, "Quit", true, false, 'X', false);
result.categoryName = "File";
break;
case MenuEditUndo:
setCommandTarget(result, "Undo: " + bpe->owner->getControlUndoManager()->getUndoDescription(), bpe->owner->getControlUndoManager()->canUndo(), false, 'Z', true, ModifierKeys::commandModifier);
result.categoryName = "Edit";
Expand All @@ -394,6 +395,10 @@ void BackendCommandTarget::getCommandInfo(CommandID commandID, ApplicationComman
result.categoryName = "Edit";
result.addDefaultKeypress(KeyPress::upKey, ModifierKeys::ctrlModifier);
break;
case MenuToolsEditShortcuts:
setCommandTarget(result, "Edit Shortcuts", true, false, 'x', false);
result.categoryName = "Tools";
break;
case MenuEditMoveDown:
setCommandTarget(result, "Move down", currentCopyPasteTarget.get() != nullptr, false, 'X', false);
result.categoryName = "Edit";
Expand Down Expand Up @@ -727,6 +732,7 @@ bool BackendCommandTarget::perform(const InvocationInfo &info)
case MenuToolsEnableDebugLogging: bpe->owner->getDebugLogger().toggleLogging(); updateCommands(); return true;
case MenuToolsApplySampleMapProperties: Actions::applySampleMapProperties(bpe); return true;
case MenuToolsConvertSVGToPathData: Actions::convertSVGToPathData(bpe); return true;
case MenuToolsEditShortcuts: Actions::editShortcuts(bpe); return true;
case MenuViewFullscreen: Actions::toggleFullscreen(bpe); updateCommands(); return true;
case MenuViewReset: bpe->resetInterface(); updateCommands(); return true;
case MenuViewRotate:
Expand Down Expand Up @@ -895,6 +901,7 @@ PopupMenu BackendCommandTarget::getMenuForIndex(int topLevelMenuIndex, const Str
p.addSeparator();

ADD_ALL_PLATFORMS(MenuFileSettingsProject);
ADD_DESKTOP_ONLY(MenuToolsEditShortcuts);

p.addSeparator();
ADD_ALL_PLATFORMS(MenuFileQuit);
Expand Down Expand Up @@ -952,6 +959,7 @@ PopupMenu BackendCommandTarget::getMenuForIndex(int topLevelMenuIndex, const Str
ADD_DESKTOP_ONLY(MenuToolsValidateUserPresets);
ADD_DESKTOP_ONLY(MenuToolsConvertSVGToPathData);


p.addSeparator();

PopupMenu sub;
Expand Down Expand Up @@ -1229,6 +1237,13 @@ void BackendCommandTarget::menuItemSelected(int menuItemID, int topLevelMenuInde



void BackendCommandTarget::Actions::editShortcuts(BackendRootWindow* bpe)
{
auto s = new ShortcutEditor(bpe);

s->setModalBaseWindowComponent(bpe);
}

bool BackendCommandTarget::Actions::hasProcessorInClipboard()
{
if (auto xml = XmlDocument::parse(SystemClipboard::getTextFromClipboard()))
Expand Down
6 changes: 5 additions & 1 deletion hi_backend/backend/BackendApplicationCommands.h
Expand Up @@ -109,6 +109,7 @@ class BackendCommandTarget: public ApplicationCommandTarget,
MenuFileSettingCheckSanity,
MenuFileSettingsCleanBuildDirectory,
MenuFileCreateThirdPartyNode,
MenuFileQuit,
MenuReplaceWithClipboardContent,
MenuExportFileAsPlugin,
MenuExportFileAsEffectPlugin,
Expand All @@ -119,7 +120,7 @@ class BackendCommandTarget: public ApplicationCommandTarget,
MenuExportSampleDataForInstaller,
MenuExportCompileFilesInPool,
MenuExportCompileNetworksAsDll,
MenuFileQuit,

MenuEditOffset = 0x30000,
MenuEditUndo,
MenuEditRedo,
Expand Down Expand Up @@ -156,6 +157,7 @@ class BackendCommandTarget: public ApplicationCommandTarget,
MenuToolsCreateInterface,
MenuToolsSanityCheck,
MenuToolsClearConsole,
MenuToolsEditShortcuts,
MenuToolsSetCompileTimeOut,
MenuToolsUseBackgroundThreadForCompile,
MenuToolsRecompileScriptsOnReload,
Expand Down Expand Up @@ -190,6 +192,7 @@ class BackendCommandTarget: public ApplicationCommandTarget,
MenuToolsRecordOneSecond,
MenuToolsShowDspNetworkDllInfo,
MenuToolsDeviceSimulatorOffset,

MenuHelpShowAboutPage = 0x70000,
MenuHelpShowDocumentation,
MenuHelpShowHelpForComponents,
Expand Down Expand Up @@ -270,6 +273,7 @@ class BackendCommandTarget: public ApplicationCommandTarget,
{
public:

static void editShortcuts(BackendRootWindow* bpe);
static bool hasProcessorInClipboard();
static bool hasSnippetInClipboard();
static void openFile(BackendRootWindow *bpe);
Expand Down
84 changes: 83 additions & 1 deletion hi_backend/backend/BackendRootWindow.cpp
Expand Up @@ -35,8 +35,10 @@ namespace hise { using namespace juce;
BackendRootWindow::BackendRootWindow(AudioProcessor *ownerProcessor, var editorState) :
AudioProcessorEditor(ownerProcessor),
BackendCommandTarget(static_cast<BackendProcessor*>(ownerProcessor)),
owner(static_cast<BackendProcessor*>(ownerProcessor))
owner(static_cast<BackendProcessor*>(ownerProcessor)),
drawer(*this)
{

PresetHandler::buildProcessorDataBase(owner->getMainSynthChain());

Desktop::getInstance().setDefaultLookAndFeel(&globalLookAndFeel);
Expand All @@ -45,6 +47,8 @@ BackendRootWindow::BackendRootWindow(AudioProcessor *ownerProcessor, var editorS

getMainController()->getLockFreeDispatcher().addPresetLoadListener(this);

loadKeyPressMap();

if (GET_HISE_SETTING(owner->getMainSynthChain(), HiseSettings::Other::GlassEffect))
{
if(!CompileExporter::isExportingFromCommandLine())
Expand Down Expand Up @@ -258,6 +262,7 @@ BackendRootWindow::BackendRootWindow(AudioProcessor *ownerProcessor, var editorS

BackendRootWindow::~BackendRootWindow()
{
saveKeyPressMap();
saveInterfaceData();

popoutWindows.clear();
Expand Down Expand Up @@ -313,6 +318,32 @@ bool BackendRootWindow::isFullScreenMode() const
#endif
}

void BackendRootWindow::initialiseAllKeyPresses()
{
// Workspace Shortcuts

addShortcut(this, "Workspaces", FloatingTileKeyPressIds::fold_browser, "Fold Browser Tab", KeyPress(KeyPress::F2Key, ModifierKeys::shiftModifier, 0));
addShortcut(this, "Workspaces", FloatingTileKeyPressIds::fold_editor, "Fold Code Editor", KeyPress(KeyPress::F3Key, ModifierKeys::shiftModifier, 0));
addShortcut(this, "Workspaces", FloatingTileKeyPressIds::fold_interface, "Fold Interface Designer", KeyPress(KeyPress::F4Key, ModifierKeys::shiftModifier, 0));

addShortcut(this, "Workspaces", FloatingTileKeyPressIds::fold_watch, "Fold Script Variable Watch Table", KeyPress('q', ModifierKeys::commandModifier, 'q'));

addShortcut(this, "Workspaces", FloatingTileKeyPressIds::fold_list, "Fold Component / Node List", KeyPress('w', ModifierKeys::commandModifier, 'w'));

addShortcut(this, "Workspaces", FloatingTileKeyPressIds::fold_console, "Fold [K]onsole", KeyPress('k', ModifierKeys::commandModifier, 'k'));

addShortcut(this, "Workspaces", FloatingTileKeyPressIds::fold_properties, "Fold Component / Node Properties", KeyPress('e', ModifierKeys::commandModifier, 'e'));

addShortcut(this, "Workspaces", FloatingTileKeyPressIds::focus_browser, "Focus Browser Tab", KeyPress(KeyPress::F2Key));
addShortcut(this, "Workspaces", FloatingTileKeyPressIds::focus_editor, "Focus Code Editor", KeyPress(KeyPress::F3Key));
addShortcut(this, "Workspaces", FloatingTileKeyPressIds::focus_interface, "Focus Interface Designer", KeyPress(KeyPress::F4Key));

addShortcut(this, "Workspaces", FloatingTileKeyPressIds::cycle_browser, "Cycle Browser Tabs", KeyPress(KeyPress::F2Key, ModifierKeys::commandModifier, 0));
addShortcut(this, "Workspaces", FloatingTileKeyPressIds::cycle_editor, "Cycle Code Editor Tabs", KeyPress(KeyPress::F3Key, ModifierKeys::commandModifier, 0));

mcl::FullEditor::initKeyPresses(this);
}

void BackendRootWindow::setScriptProcessorForWorkspace(JavascriptProcessor* jsp)
{
sendRootContainerRebuildMessage(true);
Expand Down Expand Up @@ -601,6 +632,8 @@ MarkdownPreview* BackendRootWindow::createOrShowDocWindow(const MarkdownLink& li

void BackendRootWindow::paintOverChildren(Graphics& g)
{
drawer.draw(g);

if (learnMode)
{
RectangleList<float> areas;
Expand Down Expand Up @@ -778,4 +811,53 @@ void PeriodicScreenshotter::run()
}
}

void BackendRootWindow::FocusDrawer::globalFocusChanged(Component* focusedComponent)
{
if(focusedComponent != nullptr)
focusedComponent = focusedComponent->findParentComponentOfClass<FloatingTile>();

if (lastFocusComponent != focusedComponent)
{
lastFocusComponent = focusedComponent;

if (lastFocusComponent != nullptr)
{
focusArea = parent.getLocalArea(lastFocusComponent, lastFocusComponent->getLocalBounds());
startTimer(30);
alpha = 1.0f;
parent.repaint();
}
}
}

void BackendRootWindow::FocusDrawer::timerCallback()
{
alpha -= 0.08f;

if (lastFocusComponent != nullptr)
{
focusArea = parent.getLocalArea(lastFocusComponent, lastFocusComponent->getLocalBounds());
}



parent.repaint();

if (alpha <= 0.0f)
{
alpha = 0.0f;
stopTimer();
}

}

void BackendRootWindow::FocusDrawer::draw(Graphics& g)
{
if (alpha != 0.0f)
{
g.setColour(Colour(SIGNAL_COLOUR).withAlpha(jlimit(0.0f, 1.0f, alpha * 0.4f)));
g.drawRect(focusArea, 1.0f);
}
}

} // namespace hise
41 changes: 40 additions & 1 deletion hi_backend/backend/BackendRootWindow.h
Expand Up @@ -49,7 +49,10 @@ class BackendProcessorEditor;





class BackendRootWindow : public TopLevelWindowWithOptionalOpenGL,
public TopLevelWindowWithKeyMappings,
public AudioProcessorEditor,
public BackendCommandTarget,
public snex::ui::WorkbenchManager::WorkbenchChangeListener,
Expand All @@ -70,6 +73,13 @@ class BackendRootWindow : public TopLevelWindowWithOptionalOpenGL,

bool isFullScreenMode() const;

File getKeyPressSettingFile() const override
{
return ProjectHandler::getAppDataDirectory().getChildFile("KeyPressMapping.xml");
}

void initialiseAllKeyPresses() override;

void paint(Graphics& g) override
{
g.fillAll(HiseColourScheme::getColour(HiseColourScheme::ColourIds::EditorBackgroundColourIdBright));
Expand Down Expand Up @@ -209,11 +219,40 @@ class BackendRootWindow : public TopLevelWindowWithOptionalOpenGL,

void paintOverChildren(Graphics& g) override;



private:

struct FocusDrawer : public FocusChangeListener,
public Timer
{
FocusDrawer(BackendRootWindow& p) :
parent(p)
{
Desktop::getInstance().addFocusChangeListener(this);
};

~FocusDrawer()
{
Desktop::getInstance().removeFocusChangeListener(this);
}

void globalFocusChanged(Component* focusedComponent) override;

void timerCallback() override;

void draw(Graphics& g);

Component* lastFocusComponent = nullptr;

Rectangle<int> focusArea;
float alpha = 0.0f;
BackendRootWindow& parent;
} drawer;

bool learnMode = false;

LookAndFeel_V3 globalLookAndFeel;
GlobalHiseLookAndFeel globalLookAndFeel;

OwnedArray<FloatingTileDocumentWindow> popoutWindows;

Expand Down
2 changes: 1 addition & 1 deletion hi_backend/backend/debug_components/FileBrowser.cpp
Expand Up @@ -211,7 +211,7 @@ FileBrowser::FileBrowser(BackendRootWindow* rootWindow_) :

addKeyListener(browserCommandManager->getKeyMappings());

setWantsKeyboardFocus(true);
setWantsKeyboardFocus(false);

browseUndoManager = new UndoManager();

Expand Down

2 comments on commit 6dbe3e3

@davidhealey
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent!

@christoph-hart
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have any suggestions of which key presses you want to customize, let me know. The system is setup so that this is pretty easy to do...

Please sign in to comment.