From 98a0bcb2d7aa201733f1da6eb80f1043fb1dca4c Mon Sep 17 00:00:00 2001
From: mezz <tehgeek@gmail.com>
Date: Tue, 29 Dec 2020 19:56:02 -1000
Subject: [PATCH 1/6] Add palette option to save as preset

This works the same as saving a palette normally, but opens the file dialogue to the default palette preset directory.
---
 data/gui.xml                          |  3 +++
 data/strings/en.ini                   |  1 +
 src/app/commands/cmd_save_palette.cpp |  5 ++++-
 src/app/modules/palettes.cpp          | 19 +++++++++++++------
 src/app/modules/palettes.h            |  1 +
 5 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/data/gui.xml b/data/gui.xml
index 06a9f0f01..fd5496e6a 100644
--- a/data/gui.xml
+++ b/data/gui.xml
@@ -1080,6 +1080,9 @@
       <separator />
       <item command="LoadPalette" text="@.load_palette" />
       <item command="SavePalette" text="@.save_palette" />
+      <item command="SavePalette" text="@.save_palette_as_preset">
+        <param name="save_as_preset" value="true" />
+      </item>
       <item command="LoadPalette" text="@.load_default_palette">
         <param name="preset" value="default" />
       </item>
diff --git a/data/strings/en.ini b/data/strings/en.ini
index 2f82ed1a3..4c6183aad 100644
--- a/data/strings/en.ini
+++ b/data/strings/en.ini
@@ -1318,6 +1318,7 @@ ryb_color_wheel = RYB Color Wheel
 normal_map_color_wheel = Normal Map Color Wheel
 load_palette = L&oad Palette
 save_palette = S&ave Palette
+save_palette_as_preset = Save Palette as Preset
 load_default_palette = Load Default Palette
 save_as_default_palette = Save as Default Palette
 create_palette_from_current_sprite = Create Palette from Current Sprite
diff --git a/src/app/commands/cmd_save_palette.cpp b/src/app/commands/cmd_save_palette.cpp
index 429599162..1d05b0f4d 100644
--- a/src/app/commands/cmd_save_palette.cpp
+++ b/src/app/commands/cmd_save_palette.cpp
@@ -35,6 +35,7 @@ protected:
 
 private:
   std::string m_preset;
+  bool m_save_as_preset;
 };
 
 SavePaletteCommand::SavePaletteCommand()
@@ -45,6 +46,7 @@ SavePaletteCommand::SavePaletteCommand()
 void SavePaletteCommand::onLoadParams(const Params& params)
 {
   m_preset = params.get("preset");
+  m_save_as_preset = params.get("save_as_preset") == "true";
 }
 
 void SavePaletteCommand::onExecute(Context* context)
@@ -58,8 +60,9 @@ void SavePaletteCommand::onExecute(Context* context)
   else {
     base::paths exts = get_writable_palette_extensions();
     base::paths selFilename;
+    std::string initialPath = m_save_as_preset ? get_preset_palettes_dir() : "";
     if (!app::show_file_selector(
-          "Save Palette", "", exts,
+          "Save Palette", initialPath, exts,
           FileSelectorType::Save, selFilename))
       return;
 
diff --git a/src/app/modules/palettes.cpp b/src/app/modules/palettes.cpp
index f6d515851..cd79a3a1c 100644
--- a/src/app/modules/palettes.cpp
+++ b/src/app/modules/palettes.cpp
@@ -161,12 +161,7 @@ bool set_current_palette(const Palette *_palette, bool forced)
 std::string get_preset_palette_filename(const std::string& preset,
                                         const std::string& dot_extension)
 {
-  ResourceFinder rf;
-  rf.includeUserDir(base::join_path("palettes", ".").c_str());
-  std::string palettesDir = rf.getFirstOrCreateDefault();
-
-  if (!base::is_directory(palettesDir))
-    base::make_directory(palettesDir);
+  std::string palettesDir = get_preset_palettes_dir();
 
   return base::join_path(palettesDir, preset + dot_extension);
 }
@@ -176,4 +171,16 @@ std::string get_default_palette_preset_name()
   return "default";
 }
 
+std::string get_preset_palettes_dir()
+{
+  ResourceFinder rf;
+  rf.includeUserDir(base::join_path("palettes", ".").c_str());
+  std::string palettesDir = rf.getFirstOrCreateDefault();
+
+  if (!base::is_directory(palettesDir))
+    base::make_directory(palettesDir);
+
+  return palettesDir;
+}
+
 } // namespace app
diff --git a/src/app/modules/palettes.h b/src/app/modules/palettes.h
index 551b4bedf..52f953766 100644
--- a/src/app/modules/palettes.h
+++ b/src/app/modules/palettes.h
@@ -33,6 +33,7 @@ namespace app {
   std::string get_preset_palette_filename(const std::string& preset,
                                           const std::string& dot_extension);
   std::string get_default_palette_preset_name();
+  std::string get_preset_palettes_dir();
 
 } // namespace app
 

From be48c40dc5ffe84cc34fad3372671974238d3b3d Mon Sep 17 00:00:00 2001
From: mezz <tehgeek@gmail.com>
Date: Tue, 29 Dec 2020 20:45:37 -1000
Subject: [PATCH 2/6] Reload palette popup and refresh search results when
 saving a new preset

---
 src/app/commands/cmd_save_palette.cpp | 5 +++++
 src/app/extensions.cpp                | 2 +-
 src/app/extensions.h                  | 2 +-
 src/app/ui/palette_popup.cpp          | 1 +
 src/app/ui/resources_listbox.cpp      | 1 +
 5 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/app/commands/cmd_save_palette.cpp b/src/app/commands/cmd_save_palette.cpp
index 1d05b0f4d..82f5d2ba0 100644
--- a/src/app/commands/cmd_save_palette.cpp
+++ b/src/app/commands/cmd_save_palette.cpp
@@ -8,10 +8,12 @@
 #include "config.h"
 #endif
 
+#include "app/app.h"
 #include "app/commands/cmd_set_palette.h"
 #include "app/commands/commands.h"
 #include "app/commands/params.h"
 #include "app/context.h"
+#include "app/extensions.h"
 #include "app/file/palette_file.h"
 #include "app/file_selector.h"
 #include "app/i18n/strings.h"
@@ -77,6 +79,9 @@ void SavePaletteCommand::onExecute(Context* context)
     if (!context->activeDocument())
       set_current_palette(palette, false);
   }
+  if (m_save_as_preset) {
+      App::instance()->extensions().PalettesChange();
+  }
 }
 
 Command* CommandFactory::createSavePaletteCommand()
diff --git a/src/app/extensions.cpp b/src/app/extensions.cpp
index cde81cd99..2a247d82e 100644
--- a/src/app/extensions.cpp
+++ b/src/app/extensions.cpp
@@ -1132,7 +1132,7 @@ void Extensions::generateExtensionSignals(Extension* extension)
 {
   if (extension->hasLanguages()) LanguagesChange(extension);
   if (extension->hasThemes()) ThemesChange(extension);
-  if (extension->hasPalettes()) PalettesChange(extension);
+  if (extension->hasPalettes()) PalettesChange();
   if (extension->hasDitheringMatrices()) DitheringMatricesChange(extension);
 #ifdef ENABLE_SCRIPTING
   if (extension->hasScripts()) ScriptsChange(extension);
diff --git a/src/app/extensions.h b/src/app/extensions.h
index ab2e7492b..898ab6ae7 100644
--- a/src/app/extensions.h
+++ b/src/app/extensions.h
@@ -182,7 +182,7 @@ namespace app {
     obs::signal<void(Extension*)> NewExtension;
     obs::signal<void(Extension*)> LanguagesChange;
     obs::signal<void(Extension*)> ThemesChange;
-    obs::signal<void(Extension*)> PalettesChange;
+    obs::signal<void()> PalettesChange;
     obs::signal<void(Extension*)> DitheringMatricesChange;
     obs::signal<void(Extension*)> ScriptsChange;
 
diff --git a/src/app/ui/palette_popup.cpp b/src/app/ui/palette_popup.cpp
index 31e6bb032..716ff6ad5 100644
--- a/src/app/ui/palette_popup.cpp
+++ b/src/app/ui/palette_popup.cpp
@@ -42,6 +42,7 @@ PalettePopup::PalettePopup()
   addChild(m_popup);
 
   m_paletteListBox.DoubleClickItem.connect(base::Bind<void>(&PalettePopup::onLoadPal, this));
+  m_paletteListBox.Change.connect(base::Bind<void>(&PalettePopup::onSearchChange, this));
   m_popup->search()->Change.connect(base::Bind<void>(&PalettePopup::onSearchChange, this));
   m_popup->loadPal()->Click.connect(base::Bind<void>(&PalettePopup::onLoadPal, this));
   m_popup->openFolder()->Click.connect(base::Bind<void>(&PalettePopup::onOpenFolder, this));
diff --git a/src/app/ui/resources_listbox.cpp b/src/app/ui/resources_listbox.cpp
index 2c8e23d46..b7cbe9f25 100644
--- a/src/app/ui/resources_listbox.cpp
+++ b/src/app/ui/resources_listbox.cpp
@@ -210,6 +210,7 @@ void ResourcesListBox::onTick()
     resource.release();
     listItem.release();
   }
+  Change();
 
   if (m_resourcesLoader->isDone())
     stop();

From 3211831da3d3730e1924c6b89b6b8010e4592bc8 Mon Sep 17 00:00:00 2001
From: mezz <tehgeek@gmail.com>
Date: Mon, 4 Jan 2021 09:38:43 -1000
Subject: [PATCH 3/6] Create and use new signal: PalettePresetsChange

---
 src/app/app.h                         | 1 +
 src/app/commands/cmd_save_palette.cpp | 3 +--
 src/app/extensions.cpp                | 2 +-
 src/app/extensions.h                  | 2 +-
 src/app/ui/palettes_listbox.cpp       | 3 +++
 src/app/ui/palettes_listbox.h         | 1 +
 6 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/app/app.h b/src/app/app.h
index f255fae2a..e178ee519 100644
--- a/src/app/app.h
+++ b/src/app/app.h
@@ -124,6 +124,7 @@ namespace app {
     obs::signal<void()> Exit;
     obs::signal<void()> PaletteChange;
     obs::signal<void()> ColorSpaceChange;
+    obs::signal<void()> PalettePresetsChange;
 
   private:
     class CoreModules;
diff --git a/src/app/commands/cmd_save_palette.cpp b/src/app/commands/cmd_save_palette.cpp
index 82f5d2ba0..9e53dc9d4 100644
--- a/src/app/commands/cmd_save_palette.cpp
+++ b/src/app/commands/cmd_save_palette.cpp
@@ -13,7 +13,6 @@
 #include "app/commands/commands.h"
 #include "app/commands/params.h"
 #include "app/context.h"
-#include "app/extensions.h"
 #include "app/file/palette_file.h"
 #include "app/file_selector.h"
 #include "app/i18n/strings.h"
@@ -80,7 +79,7 @@ void SavePaletteCommand::onExecute(Context* context)
       set_current_palette(palette, false);
   }
   if (m_save_as_preset) {
-      App::instance()->extensions().PalettesChange();
+      App::instance()->PalettePresetsChange();
   }
 }
 
diff --git a/src/app/extensions.cpp b/src/app/extensions.cpp
index 2a247d82e..cde81cd99 100644
--- a/src/app/extensions.cpp
+++ b/src/app/extensions.cpp
@@ -1132,7 +1132,7 @@ void Extensions::generateExtensionSignals(Extension* extension)
 {
   if (extension->hasLanguages()) LanguagesChange(extension);
   if (extension->hasThemes()) ThemesChange(extension);
-  if (extension->hasPalettes()) PalettesChange();
+  if (extension->hasPalettes()) PalettesChange(extension);
   if (extension->hasDitheringMatrices()) DitheringMatricesChange(extension);
 #ifdef ENABLE_SCRIPTING
   if (extension->hasScripts()) ScriptsChange(extension);
diff --git a/src/app/extensions.h b/src/app/extensions.h
index 898ab6ae7..ab2e7492b 100644
--- a/src/app/extensions.h
+++ b/src/app/extensions.h
@@ -182,7 +182,7 @@ namespace app {
     obs::signal<void(Extension*)> NewExtension;
     obs::signal<void(Extension*)> LanguagesChange;
     obs::signal<void(Extension*)> ThemesChange;
-    obs::signal<void()> PalettesChange;
+    obs::signal<void(Extension*)> PalettesChange;
     obs::signal<void(Extension*)> DitheringMatricesChange;
     obs::signal<void(Extension*)> ScriptsChange;
 
diff --git a/src/app/ui/palettes_listbox.cpp b/src/app/ui/palettes_listbox.cpp
index e23896d82..8cbe66b01 100644
--- a/src/app/ui/palettes_listbox.cpp
+++ b/src/app/ui/palettes_listbox.cpp
@@ -124,6 +124,9 @@ PalettesListBox::PalettesListBox()
   m_extPaletteChanges =
     App::instance()->extensions().PalettesChange.connect(
       base::Bind<void>(&PalettesListBox::reload, this));
+  m_extPresetsChanges =
+    App::instance()->PalettePresetsChange.connect(
+      base::Bind<void>(&PalettesListBox::reload, this));
 }
 
 doc::Palette* PalettesListBox::selectedPalette()
diff --git a/src/app/ui/palettes_listbox.h b/src/app/ui/palettes_listbox.h
index 57af50fa5..26247148b 100644
--- a/src/app/ui/palettes_listbox.h
+++ b/src/app/ui/palettes_listbox.h
@@ -34,6 +34,7 @@ namespace app {
 
     ui::TooltipManager m_tooltips;
     obs::scoped_connection m_extPaletteChanges;
+    obs::scoped_connection m_extPresetsChanges;
   };
 
 } // namespace app

From 78fc63c3f89108dddd901f7b751122078692f5da Mon Sep 17 00:00:00 2001
From: mezz <tehgeek@gmail.com>
Date: Mon, 4 Jan 2021 09:51:16 -1000
Subject: [PATCH 4/6] Organize the palette load/save menu

---
 data/gui.xml        | 9 ++++-----
 data/strings/en.ini | 4 ++--
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/data/gui.xml b/data/gui.xml
index fd5496e6a..ea8039fff 100644
--- a/data/gui.xml
+++ b/data/gui.xml
@@ -1078,19 +1078,18 @@
         <param name="type" value="normal-map-wheel" />
       </item>
       <separator />
+      <item command="ColorQuantization" text="@.create_palette_from_current_sprite" group="palette_generation" />
       <item command="LoadPalette" text="@.load_palette" />
+      <item command="LoadPalette" text="@.load_default_palette">
+        <param name="preset" value="default" />
+      </item>
       <item command="SavePalette" text="@.save_palette" />
       <item command="SavePalette" text="@.save_palette_as_preset">
         <param name="save_as_preset" value="true" />
       </item>
-      <item command="LoadPalette" text="@.load_default_palette">
-        <param name="preset" value="default" />
-      </item>
       <item command="SavePalette" text="@.save_as_default_palette" group="palette_files">
         <param name="preset" value="default" />
       </item>
-      <separator />
-      <item command="ColorQuantization" text="@.create_palette_from_current_sprite" group="palette_generation" />
     </menu>
 
     <menu id="ink_popup_menu">
diff --git a/data/strings/en.ini b/data/strings/en.ini
index 4c6183aad..c0819c6fe 100644
--- a/data/strings/en.ini
+++ b/data/strings/en.ini
@@ -1320,8 +1320,8 @@ load_palette = L&oad Palette
 save_palette = S&ave Palette
 save_palette_as_preset = Save Palette as Preset
 load_default_palette = Load Default Palette
-save_as_default_palette = Save as Default Palette
-create_palette_from_current_sprite = Create Palette from Current Sprite
+save_as_default_palette = Save Palette as Default
+create_palette_from_current_sprite = New Palette from Sprite
 
 [palette_size]
 title = Palette Size

From de22d69678e42638202cb0079ba8f16500a9b805 Mon Sep 17 00:00:00 2001
From: David Capello <david@igarastudio.com>
Date: Tue, 5 Jan 2021 11:03:29 -0300
Subject: [PATCH 5/6] Add FinishLoading signal to ResourcesListBox to detect
 when the resources were loaded

In this way we avoid using ui::ListBox::Change signal as a
workaround (which is a signal that should be fired only from
ui::ListBox::onChange()).
---
 src/app/ui/palette_popup.cpp     | 2 +-
 src/app/ui/resources_listbox.cpp | 5 +++--
 src/app/ui/resources_listbox.h   | 3 +++
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/app/ui/palette_popup.cpp b/src/app/ui/palette_popup.cpp
index 716ff6ad5..6179203d4 100644
--- a/src/app/ui/palette_popup.cpp
+++ b/src/app/ui/palette_popup.cpp
@@ -42,7 +42,7 @@ PalettePopup::PalettePopup()
   addChild(m_popup);
 
   m_paletteListBox.DoubleClickItem.connect(base::Bind<void>(&PalettePopup::onLoadPal, this));
-  m_paletteListBox.Change.connect(base::Bind<void>(&PalettePopup::onSearchChange, this));
+  m_paletteListBox.FinishLoading.connect(base::Bind<void>(&PalettePopup::onSearchChange, this));
   m_popup->search()->Change.connect(base::Bind<void>(&PalettePopup::onSearchChange, this));
   m_popup->loadPal()->Click.connect(base::Bind<void>(&PalettePopup::onLoadPal, this));
   m_popup->openFolder()->Click.connect(base::Bind<void>(&PalettePopup::onOpenFolder, this));
diff --git a/src/app/ui/resources_listbox.cpp b/src/app/ui/resources_listbox.cpp
index b7cbe9f25..1b95ac44c 100644
--- a/src/app/ui/resources_listbox.cpp
+++ b/src/app/ui/resources_listbox.cpp
@@ -210,10 +210,11 @@ void ResourcesListBox::onTick()
     resource.release();
     listItem.release();
   }
-  Change();
 
-  if (m_resourcesLoader->isDone())
+  if (m_resourcesLoader->isDone()) {
+    FinishLoading();
     stop();
+  }
 }
 
 void ResourcesListBox::stop()
diff --git a/src/app/ui/resources_listbox.h b/src/app/ui/resources_listbox.h
index aa8a38d61..418e705ca 100644
--- a/src/app/ui/resources_listbox.h
+++ b/src/app/ui/resources_listbox.h
@@ -9,6 +9,7 @@
 #pragma once
 
 #include "app/res/resources_loader.h"
+#include "obs/signal.h"
 #include "ui/listbox.h"
 #include "ui/listitem.h"
 #include "ui/timer.h"
@@ -43,6 +44,8 @@ class ResourceListItem : public ui::ListItem {
 
     void reload();
 
+    obs::signal<void()> FinishLoading;
+
   protected:
     virtual bool onProcessMessage(ui::Message* msg) override;
     virtual void onChange() override;

From d3f38588597b79d282a85c06c0557601839e5d97 Mon Sep 17 00:00:00 2001
From: David Capello <david@igarastudio.com>
Date: Tue, 5 Jan 2021 11:05:40 -0300
Subject: [PATCH 6/6] Minor change "save_as_preset" -> "saveAsPreset"

This new camelCase style is prefered since the introduction of the Lua
scripting API.
---
 data/gui.xml                          | 2 +-
 src/app/commands/cmd_save_palette.cpp | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/data/gui.xml b/data/gui.xml
index ea8039fff..50d05a93f 100644
--- a/data/gui.xml
+++ b/data/gui.xml
@@ -1085,7 +1085,7 @@
       </item>
       <item command="SavePalette" text="@.save_palette" />
       <item command="SavePalette" text="@.save_palette_as_preset">
-        <param name="save_as_preset" value="true" />
+        <param name="saveAsPreset" value="true" />
       </item>
       <item command="SavePalette" text="@.save_as_default_palette" group="palette_files">
         <param name="preset" value="default" />
diff --git a/src/app/commands/cmd_save_palette.cpp b/src/app/commands/cmd_save_palette.cpp
index 9e53dc9d4..05be7186d 100644
--- a/src/app/commands/cmd_save_palette.cpp
+++ b/src/app/commands/cmd_save_palette.cpp
@@ -36,7 +36,7 @@ protected:
 
 private:
   std::string m_preset;
-  bool m_save_as_preset;
+  bool m_saveAsPreset = false;
 };
 
 SavePaletteCommand::SavePaletteCommand()
@@ -47,7 +47,7 @@ SavePaletteCommand::SavePaletteCommand()
 void SavePaletteCommand::onLoadParams(const Params& params)
 {
   m_preset = params.get("preset");
-  m_save_as_preset = params.get("save_as_preset") == "true";
+  m_saveAsPreset = (params.get("saveAsPreset") == "true");
 }
 
 void SavePaletteCommand::onExecute(Context* context)
@@ -61,7 +61,7 @@ void SavePaletteCommand::onExecute(Context* context)
   else {
     base::paths exts = get_writable_palette_extensions();
     base::paths selFilename;
-    std::string initialPath = m_save_as_preset ? get_preset_palettes_dir() : "";
+    std::string initialPath = (m_saveAsPreset ? get_preset_palettes_dir(): "");
     if (!app::show_file_selector(
           "Save Palette", initialPath, exts,
           FileSelectorType::Save, selFilename))
@@ -78,7 +78,7 @@ void SavePaletteCommand::onExecute(Context* context)
     if (!context->activeDocument())
       set_current_palette(palette, false);
   }
-  if (m_save_as_preset) {
+  if (m_saveAsPreset) {
       App::instance()->PalettePresetsChange();
   }
 }