Browse Source

Rename WINDOW_ macros to RACK_. Require rack:: namespace for APP macro.

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
2c9644d80d
14 changed files with 66 additions and 67 deletions
  1. +3
    -4
      include/app.hpp
  2. +8
    -8
      include/window.hpp
  3. +1
    -1
      src/Core/plugin.hpp
  4. +2
    -2
      src/app/Knob.cpp
  5. +16
    -16
      src/app/ModuleWidget.cpp
  6. +3
    -3
      src/app/ParamWidget.cpp
  7. +1
    -1
      src/app/PortWidget.cpp
  8. +4
    -4
      src/app/RackScrollWidget.cpp
  9. +1
    -1
      src/app/RackWidget.cpp
  10. +10
    -10
      src/app/Scene.cpp
  11. +7
    -7
      src/app/Toolbar.cpp
  12. +1
    -1
      src/ui/ScrollWidget.cpp
  13. +8
    -8
      src/ui/TextField.cpp
  14. +1
    -1
      src/window.cpp

+ 3
- 4
include/app.hpp View File

@@ -2,10 +2,6 @@
#include "common.hpp"


/** Accesses the global App pointer */
#define APP rack::appGet()


namespace rack {


@@ -52,5 +48,8 @@ void appDestroy();
/** Returns the global App pointer */
App *appGet();

/** Accesses the global App pointer */
#define APP appGet()


} // namespace rack

+ 8
- 8
include/window.hpp View File

@@ -18,21 +18,21 @@
Use this instead of GLFW_MOD_CONTROL, since Cmd should be used on Mac in place of Ctrl on Linux/Windows.
*/
#if defined ARCH_MAC
#define WINDOW_MOD_CTRL GLFW_MOD_SUPER
#define WINDOW_MOD_CTRL_NAME "Cmd"
#define RACK_MOD_CTRL GLFW_MOD_SUPER
#define RACK_MOD_CTRL_NAME "Cmd"
#else
#define WINDOW_MOD_CTRL GLFW_MOD_CONTROL
#define WINDOW_MOD_CTRL_NAME "Ctrl"
#define RACK_MOD_CTRL GLFW_MOD_CONTROL
#define RACK_MOD_CTRL_NAME "Ctrl"
#endif
#define WINDOW_MOD_SHIFT_NAME "Shift"
#define WINDOW_MOD_ALT_NAME "Alt"
#define RACK_MOD_SHIFT_NAME "Shift"
#define RACK_MOD_ALT_NAME "Alt"

/** Filters actual mod keys from the mod flags.
Use this if you don't care about GLFW_MOD_CAPS_LOCK and GLFW_MOD_NUM_LOCK.
Example usage:
if ((e.mod & WINDOW_MOD_MASK) == (WINDOW_MOD | GLFW_MOD_SHIFT)) ...
if ((e.mod & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) ...
*/
#define WINDOW_MOD_MASK (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER)
#define RACK_MOD_MASK (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER)


namespace rack {


+ 1
- 1
src/Core/plugin.hpp View File

@@ -127,7 +127,7 @@ struct CcChoice : LedDisplayChoice {
}

void onSelectKey(const event::SelectKey &e) override {
if ((e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER) && e.action == GLFW_PRESS && (e.mods & WINDOW_MOD_MASK) == 0) {
if ((e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER) && e.action == GLFW_PRESS && (e.mods & RACK_MOD_MASK) == 0) {
event::Deselect eDeselect;
onDeselect(eDeselect);
APP->event->selectedWidget = NULL;


+ 2
- 2
src/app/Knob.cpp View File

@@ -82,11 +82,11 @@ void Knob::onDragMove(const event::DragMove &e) {

// Drag slower if mod is held
int mods = APP->window->getMods();
if ((mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
delta /= 16.f;
}
// Drag even slower if mod+shift is held
if ((mods & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL | GLFW_MOD_SHIFT)) {
if ((mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) {
delta /= 256.f;
}



+ 16
- 16
src/app/ModuleWidget.cpp View File

@@ -178,13 +178,13 @@ struct ModulePresetItem : ui::MenuItem {

ModuleCopyItem *copyItem = new ModuleCopyItem;
copyItem->text = "Copy";
copyItem->rightText = WINDOW_MOD_CTRL_NAME "+C";
copyItem->rightText = RACK_MOD_CTRL_NAME "+C";
copyItem->moduleWidget = moduleWidget;
menu->addChild(copyItem);

ModulePasteItem *pasteItem = new ModulePasteItem;
pasteItem->text = "Paste";
pasteItem->rightText = WINDOW_MOD_CTRL_NAME "+V";
pasteItem->rightText = RACK_MOD_CTRL_NAME "+V";
pasteItem->moduleWidget = moduleWidget;
menu->addChild(pasteItem);

@@ -308,7 +308,7 @@ void ModuleWidget::onHover(const event::Hover &e) {
// Instead of checking key-down events, delete the module even if key-repeat hasn't fired yet and the cursor is hovering over the widget.
if ((glfwGetKey(APP->window->win, GLFW_KEY_DELETE) == GLFW_PRESS
|| glfwGetKey(APP->window->win, GLFW_KEY_BACKSPACE) == GLFW_PRESS)
&& (APP->window->getMods() & WINDOW_MOD_MASK) == 0) {
&& (APP->window->getMods() & RACK_MOD_MASK) == 0) {
removeAction();
e.consume(NULL);
return;
@@ -336,43 +336,43 @@ void ModuleWidget::onHoverKey(const event::HoverKey &e) {
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
switch (e.key) {
case GLFW_KEY_I: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
resetAction();
e.consume(this);
}
} break;
case GLFW_KEY_R: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
randomizeAction();
e.consume(this);
}
} break;
case GLFW_KEY_C: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
copyClipboard();
e.consume(this);
}
} break;
case GLFW_KEY_V: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
pasteClipboardAction();
e.consume(this);
}
} break;
case GLFW_KEY_D: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
cloneAction();
e.consume(this);
}
} break;
case GLFW_KEY_U: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
disconnectAction();
e.consume(this);
}
} break;
case GLFW_KEY_E: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
bypassAction();
e.consume(this);
}
@@ -403,7 +403,7 @@ void ModuleWidget::onDragEnd(const event::DragEnd &e) {
void ModuleWidget::onDragMove(const event::DragMove &e) {
if (!settings::lockModules) {
math::Vec pos = APP->scene->rack->mousePos.minus(dragPos);
if ((APP->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL)
if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL)
APP->scene->rack->setModulePosForce(this, pos);
else
APP->scene->rack->setModulePosNearest(this, pos);
@@ -822,31 +822,31 @@ void ModuleWidget::createContextMenu() {

ModuleResetItem *resetItem = new ModuleResetItem;
resetItem->text = "Initialize";
resetItem->rightText = WINDOW_MOD_CTRL_NAME "+I";
resetItem->rightText = RACK_MOD_CTRL_NAME "+I";
resetItem->moduleWidget = this;
menu->addChild(resetItem);

ModuleRandomizeItem *randomizeItem = new ModuleRandomizeItem;
randomizeItem->text = "Randomize";
randomizeItem->rightText = WINDOW_MOD_CTRL_NAME "+R";
randomizeItem->rightText = RACK_MOD_CTRL_NAME "+R";
randomizeItem->moduleWidget = this;
menu->addChild(randomizeItem);

ModuleDisconnectItem *disconnectItem = new ModuleDisconnectItem;
disconnectItem->text = "Disconnect cables";
disconnectItem->rightText = WINDOW_MOD_CTRL_NAME "+U";
disconnectItem->rightText = RACK_MOD_CTRL_NAME "+U";
disconnectItem->moduleWidget = this;
menu->addChild(disconnectItem);

ModuleCloneItem *cloneItem = new ModuleCloneItem;
cloneItem->text = "Duplicate";
cloneItem->rightText = WINDOW_MOD_CTRL_NAME "+D";
cloneItem->rightText = RACK_MOD_CTRL_NAME "+D";
cloneItem->moduleWidget = this;
menu->addChild(cloneItem);

ModuleBypassItem *bypassItem = new ModuleBypassItem;
bypassItem->text = "Disable";
bypassItem->rightText = WINDOW_MOD_CTRL_NAME "+E";
bypassItem->rightText = RACK_MOD_CTRL_NAME "+E";
if (module && module->bypass)
bypassItem->rightText = CHECKMARK_STRING " " + bypassItem->rightText;
bypassItem->moduleWidget = this;


+ 3
- 3
src/app/ParamWidget.cpp View File

@@ -143,7 +143,7 @@ void ParamWidget::onButton(const event::Button &e) {
OpaqueWidget::onButton(e);

// Touch parameter
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && (e.mods & WINDOW_MOD_MASK) == 0) {
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && (e.mods & RACK_MOD_MASK) == 0) {
if (paramQuantity) {
APP->scene->rack->touchedParam = this;
}
@@ -151,7 +151,7 @@ void ParamWidget::onButton(const event::Button &e) {
}

// Right click to open context menu
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT && (e.mods & WINDOW_MOD_MASK) == 0) {
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT && (e.mods & RACK_MOD_MASK) == 0) {
createContextMenu();
e.consume(this);
}
@@ -206,7 +206,7 @@ void ParamWidget::createContextMenu() {

// ParamFineItem *fineItem = new ParamFineItem;
// fineItem->text = "Fine adjust";
// fineItem->rightText = WINDOW_MOD_CTRL_NAME "+drag";
// fineItem->rightText = RACK_MOD_CTRL_NAME "+drag";
// fineItem->disabled = true;
// menu->addChild(fineItem);



+ 1
- 1
src/app/PortWidget.cpp View File

@@ -91,7 +91,7 @@ void PortWidget::onDragStart(const event::DragStart &e) {
return;

CableWidget *cw = NULL;
if ((APP->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL) {
if (type == OUTPUT) {
// Keep cable NULL. Will be created below
}


+ 4
- 4
src/app/RackScrollWidget.cpp View File

@@ -77,11 +77,11 @@ void RackScrollWidget::draw(const DrawArgs &args) {
void RackScrollWidget::onHover(const event::Hover &e) {
// Scroll with arrow keys
float arrowSpeed = 30.0;
if ((APP->window->getMods() & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL |GLFW_MOD_SHIFT))
if ((APP->window->getMods() & RACK_MOD_MASK) == (RACK_MOD_CTRL |GLFW_MOD_SHIFT))
arrowSpeed /= 16.0;
else if ((APP->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL)
else if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL)
arrowSpeed *= 4.0;
else if ((APP->window->getMods() & WINDOW_MOD_MASK) == GLFW_MOD_SHIFT)
else if ((APP->window->getMods() & RACK_MOD_MASK) == GLFW_MOD_SHIFT)
arrowSpeed /= 4.0;

if (glfwGetKey(APP->window->win, GLFW_KEY_LEFT) == GLFW_PRESS)
@@ -97,7 +97,7 @@ void RackScrollWidget::onHover(const event::Hover &e) {
}

void RackScrollWidget::onHoverScroll(const event::HoverScroll &e) {
if ((APP->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL) {
// Increase zoom
float zoomDelta = e.scrollDelta.y / 50 / 4;
if (settings::invertZoom)


+ 1
- 1
src/app/RackWidget.cpp View File

@@ -131,7 +131,7 @@ void RackWidget::onHoverKey(const event::HoverKey &e) {
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
switch (e.key) {
case GLFW_KEY_V: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
pastePresetClipboardAction();
e.consume(this);
}


+ 10
- 10
src/app/Scene.cpp View File

@@ -79,49 +79,49 @@ void Scene::onHoverKey(const event::HoverKey &e) {
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
switch (e.key) {
case GLFW_KEY_N: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
APP->patch->resetDialog();
e.consume(this);
}
} break;
case GLFW_KEY_Q: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
APP->window->close();
e.consume(this);
}
} break;
case GLFW_KEY_O: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
APP->patch->loadDialog();
e.consume(this);
}
if ((e.mods & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL | GLFW_MOD_SHIFT)) {
if ((e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) {
APP->patch->revertDialog();
e.consume(this);
}
} break;
case GLFW_KEY_S: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
APP->patch->saveDialog();
e.consume(this);
}
if ((e.mods & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL | GLFW_MOD_SHIFT)) {
if ((e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) {
APP->patch->saveAsDialog();
e.consume(this);
}
} break;
case GLFW_KEY_Z: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
APP->history->undo();
e.consume(this);
}
if ((e.mods & WINDOW_MOD_MASK) == (WINDOW_MOD_CTRL | GLFW_MOD_SHIFT)) {
if ((e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) {
APP->history->redo();
e.consume(this);
}
} break;
case GLFW_KEY_MINUS: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
float z = std::log2(settings::zoom);
z *= 2;
z = std::ceil(z - 0.01) - 1;
@@ -131,7 +131,7 @@ void Scene::onHoverKey(const event::HoverKey &e) {
}
} break;
case GLFW_KEY_EQUAL: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
float z = std::log2(settings::zoom);
z *= 2;
z = std::floor(z + 0.01) + 1;


+ 7
- 7
src/app/Toolbar.cpp View File

@@ -97,22 +97,22 @@ struct FileButton : MenuButton {

NewItem *newItem = new NewItem;
newItem->text = "New";
newItem->rightText = WINDOW_MOD_CTRL_NAME "+N";
newItem->rightText = RACK_MOD_CTRL_NAME "+N";
menu->addChild(newItem);

OpenItem *openItem = new OpenItem;
openItem->text = "Open";
openItem->rightText = WINDOW_MOD_CTRL_NAME "+O";
openItem->rightText = RACK_MOD_CTRL_NAME "+O";
menu->addChild(openItem);

SaveItem *saveItem = new SaveItem;
saveItem->text = "Save";
saveItem->rightText = WINDOW_MOD_CTRL_NAME "+S";
saveItem->rightText = RACK_MOD_CTRL_NAME "+S";
menu->addChild(saveItem);

SaveAsItem *saveAsItem = new SaveAsItem;
saveAsItem->text = "Save as";
saveAsItem->rightText = WINDOW_MOD_CTRL_NAME "+Shift+S";
saveAsItem->rightText = RACK_MOD_CTRL_NAME "+Shift+S";
menu->addChild(saveAsItem);

SaveTemplateItem *saveTemplateItem = new SaveTemplateItem;
@@ -129,7 +129,7 @@ struct FileButton : MenuButton {

QuitItem *quitItem = new QuitItem;
quitItem->text = "Quit";
quitItem->rightText = WINDOW_MOD_CTRL_NAME "+Q";
quitItem->rightText = RACK_MOD_CTRL_NAME "+Q";
menu->addChild(quitItem);
}
};
@@ -157,13 +157,13 @@ struct EditButton : MenuButton {

UndoItem *undoItem = new UndoItem;
undoItem->text = "Undo " + APP->history->getUndoName();
undoItem->rightText = WINDOW_MOD_CTRL_NAME "+Z";
undoItem->rightText = RACK_MOD_CTRL_NAME "+Z";
undoItem->disabled = !APP->history->canUndo();
menu->addChild(undoItem);

RedoItem *redoItem = new RedoItem;
redoItem->text = "Redo " + APP->history->getRedoName();
redoItem->rightText = WINDOW_MOD_CTRL_NAME "+" WINDOW_MOD_SHIFT_NAME "+Z";
redoItem->rightText = RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+Z";
redoItem->disabled = !APP->history->canRedo();
menu->addChild(redoItem);
}


+ 1
- 1
src/ui/ScrollWidget.cpp View File

@@ -102,7 +102,7 @@ void ScrollWidget::onHoverScroll(const event::HoverScroll &e) {

math::Vec scrollDelta = e.scrollDelta;
// Flip coordinates if shift is held
if ((APP->window->getMods() & WINDOW_MOD_MASK) == GLFW_MOD_SHIFT)
if ((APP->window->getMods() & RACK_MOD_MASK) == GLFW_MOD_SHIFT)
scrollDelta = scrollDelta.flip();

offset = offset.minus(scrollDelta);


+ 8
- 8
src/ui/TextField.cpp View File

@@ -93,7 +93,7 @@ void TextField::onSelectKey(const event::SelectKey &e) {
}
} break;
case GLFW_KEY_LEFT: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
while (--cursor > 0) {
if (text[cursor] == ' ')
break;
@@ -102,12 +102,12 @@ void TextField::onSelectKey(const event::SelectKey &e) {
else {
cursor--;
}
if ((e.mods & WINDOW_MOD_MASK) == 0) {
if ((e.mods & RACK_MOD_MASK) == 0) {
selection = cursor;
}
} break;
case GLFW_KEY_RIGHT: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
while (++cursor < (int) text.size()) {
if (text[cursor] == ' ')
break;
@@ -116,7 +116,7 @@ void TextField::onSelectKey(const event::SelectKey &e) {
else {
cursor++;
}
if ((e.mods & WINDOW_MOD_MASK) == 0) {
if ((e.mods & RACK_MOD_MASK) == 0) {
selection = cursor;
}
} break;
@@ -127,14 +127,14 @@ void TextField::onSelectKey(const event::SelectKey &e) {
selection = cursor = text.size();
} break;
case GLFW_KEY_V: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
const char *newText = glfwGetClipboardString(APP->window->win);
if (newText)
insertText(newText);
}
} break;
case GLFW_KEY_X: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
if (cursor != selection) {
int begin = std::min(cursor, selection);
std::string selectedText = text.substr(begin, std::abs(selection - cursor));
@@ -144,7 +144,7 @@ void TextField::onSelectKey(const event::SelectKey &e) {
}
} break;
case GLFW_KEY_C: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
if (cursor != selection) {
int begin = std::min(cursor, selection);
std::string selectedText = text.substr(begin, std::abs(selection - cursor));
@@ -153,7 +153,7 @@ void TextField::onSelectKey(const event::SelectKey &e) {
}
} break;
case GLFW_KEY_A: {
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
selectAll();
}
} break;


+ 1
- 1
src/window.cpp View File

@@ -159,7 +159,7 @@ static void keyCallback(GLFWwindow *win, int key, int scancode, int action, int
return;

// Keyboard MIDI driver
if ((mods & WINDOW_MOD_MASK) == 0) {
if ((mods & RACK_MOD_MASK) == 0) {
if (action == GLFW_PRESS) {
keyboard::press(key);
}


Loading…
Cancel
Save