Skip to content

Commit

Permalink
Allow search in palette by partial color code or name.
Browse files Browse the repository at this point in the history
Disable search on preview palettes.

Issue #207.
  • Loading branch information
thezbyg committed Jun 28, 2022
1 parent f9f6156 commit c6bb676
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 9 deletions.
5 changes: 2 additions & 3 deletions source/IContainerUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef GPICK_ICONTAINER_UI_H_
#define GPICK_ICONTAINER_UI_H_
#pragma once
#include <vector>
struct ColorObject;
struct IContainerUI {
virtual bool isContainer() = 0;
virtual void addColors(const std::vector<ColorObject> &colorObjects) = 0;
virtual void removeColors(bool selected) = 0;
virtual void editColors() = 0;
virtual void find() = 0;
};
#endif /* GPICK_ICONTAINER_UI_H_ */
8 changes: 8 additions & 0 deletions source/StandardMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,12 @@ static void onEditableColorRemoveAll(GtkWidget *widget, IReadonlyColorUI *readon
containerUI->removeColors(false);
}
}
static void onEditableColorFind(GtkWidget *widget, IReadonlyColorUI *readonlyColorUI) {
auto *containerUI = dynamic_cast<IContainerUI *>(readonlyColorUI);
if (containerUI && containerUI->isContainer()) {
containerUI->find();
}
}
static void onEditableColorEdit(GtkWidget *widget, IReadonlyColorUI *readonlyColorUI) {
auto *colorObject = reinterpret_cast<ColorObject *>(g_object_get_data(G_OBJECT(gtk_widget_get_parent(widget)), "color"));
auto &gs = *reinterpret_cast<GlobalState *>(g_object_get_data(G_OBJECT(gtk_widget_get_parent(widget)), "gs"));
Expand Down Expand Up @@ -358,6 +364,7 @@ void StandardMenu::contextForColorObject(ColorObject *colorObject, GlobalState *
appender.appendItem(_("_Edit..."), GTK_STOCK_EDIT, GDK_KEY_e, GdkModifierType(0), G_CALLBACK(onEditableColorEdit), hasSelection && currentlyEditable);
appender.appendItem(_("_Paste"), GTK_STOCK_PASTE, GDK_KEY_v, GdkModifierType(GDK_CONTROL_MASK), G_CALLBACK(onEditableColorPaste), (isContainer || hasSelection) && currentlyEditable && clipboard::colorObjectAvailable());
if (isContainer) {
appender.appendItem(_("_Find..."), GTK_STOCK_FIND, GDK_KEY_f, GdkModifierType(GDK_CONTROL_MASK), G_CALLBACK(onEditableColorFind), hasColor);
appender.appendSeparator();
appender.appendItem(_("_Remove"), GTK_STOCK_REMOVE, GDK_KEY_Delete, GdkModifierType(0), G_CALLBACK(onEditableColorRemove), hasSelection && currentlyEditable);
appender.appendItem(_("Remove _All"), GTK_STOCK_REMOVE, GDK_KEY_Delete, GdkModifierType(GDK_CONTROL_MASK), G_CALLBACK(onEditableColorRemoveAll), hasColor && currentlyEditable);
Expand Down Expand Up @@ -393,6 +400,7 @@ void StandardMenu::forInterface(GlobalState *gs, GdkEventButton *event, Interfac
appender.appendItem(_("_Edit..."), GTK_STOCK_EDIT, GDK_KEY_e, GdkModifierType(0), G_CALLBACK(onEditableColorEdit), hasSelection && currentlyEditable);
appender.appendItem(_("_Paste"), GTK_STOCK_PASTE, GDK_KEY_v, GdkModifierType(GDK_CONTROL_MASK), G_CALLBACK(onEditableColorPaste), (hasSelection || isContainer) && currentlyEditable && clipboard::colorObjectAvailable());
if (isContainer) {
appender.appendItem(_("_Find..."), GTK_STOCK_FIND, GDK_KEY_f, GdkModifierType(GDK_CONTROL_MASK), G_CALLBACK(onEditableColorFind), hasColor);
appender.appendSeparator();
appender.appendItem(_("_Remove"), GTK_STOCK_REMOVE, GDK_KEY_Delete, GdkModifierType(0), G_CALLBACK(onEditableColorRemove), hasSelection && currentlyEditable);
appender.appendItem(_("Remove _All"), GTK_STOCK_REMOVE, GDK_KEY_Delete, GdkModifierType(GDK_CONTROL_MASK), G_CALLBACK(onEditableColorRemoveAll), hasColor && currentlyEditable);
Expand Down
14 changes: 14 additions & 0 deletions source/uiApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,15 @@ static void palette_popup_menu_generate(GtkWidget *widget, AppArgs *args) {
static void palette_popup_menu_equalize(GtkWidget *widget, AppArgs *args) {
dialog_equalize_show(GTK_WINDOW(args->window), args->paletteWidget, *args->gs);
}
static gboolean startInteractiveSearch(AppArgs *args) {
gtk_widget_grab_focus(args->paletteWidget);
gboolean result;
g_signal_emit_by_name(args->paletteWidget, "start-interactive-search", &result);
return false;
}
static void palette_popup_menu_find(GtkWidget *widget, AppArgs *args) {
g_idle_add(reinterpret_cast<GSourceFunc>(startInteractiveSearch), args);
}
static gboolean palette_popup_menu_show(GtkWidget *widget, GdkEventButton *event, AppArgs *args) {
auto menu = gtk_menu_new();
GtkAccelGroup *accel_group = gtk_accel_group_new();
Expand Down Expand Up @@ -1238,6 +1247,11 @@ static gboolean palette_popup_menu_show(GtkWidget *widget, GdkEventButton *event
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(palette_popup_menu_paste), args);
gtk_widget_set_sensitive(item, clipboard::colorObjectAvailable());
item = newMenuItem(_("_Find..."), GTK_STOCK_FIND);
gtk_widget_add_accelerator(item, "activate", accel_group, GDK_KEY_f, GdkModifierType(GDK_CONTROL_MASK), GTK_ACCEL_VISIBLE);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(palette_popup_menu_find), args);
gtk_widget_set_sensitive(item, total_count > 0);

gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
item = newMenuItem (_("_Mix Colors..."), GTK_STOCK_CONVERT);
Expand Down
31 changes: 25 additions & 6 deletions source/uiListPalette.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@
#include "IDroppableColorUI.h"
#include "IContainerUI.h"
#include "IPalette.h"
#include <boost/algorithm/string/find.hpp>
#include <unordered_set>
#include <sstream>
#include <iomanip>
#include <string_view>
using namespace math;
namespace {
enum struct Type {
Expand Down Expand Up @@ -131,11 +133,10 @@ struct ListPaletteArgs : public IEditableColorsUI, public IContainerUI, public I
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), col);
g_object_set(renderer, "editable", TRUE, nullptr);
g_signal_connect(renderer, "edited", G_CALLBACK(onCellEdited), store);

gtk_tree_view_set_enable_search(GTK_TREE_VIEW(treeview), false);
gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(store));
g_object_unref(GTK_TREE_MODEL(store));

gtk_tree_view_set_enable_search(GTK_TREE_VIEW(treeview), false);
gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(treeview), onSearchEqual, nullptr, nullptr);
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
g_signal_connect(G_OBJECT(treeview), "row-activated", G_CALLBACK(onRowActivated), this);
Expand Down Expand Up @@ -168,11 +169,10 @@ struct ListPaletteArgs : public IEditableColorsUI, public IContainerUI, public I
gtk_tree_view_column_pack_start(col, renderer, true);
gtk_tree_view_column_add_attribute(col, renderer, "color", 0);
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), col);

gtk_tree_view_set_enable_search(GTK_TREE_VIEW(treeview), false);
gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(store));
g_object_unref(GTK_TREE_MODEL(store));

gtk_tree_view_set_enable_search(GTK_TREE_VIEW(treeview), false);
gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview), -1);
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
g_signal_connect(G_OBJECT(treeview), "button-press-event", G_CALLBACK(onPreviewButtonPress), this);
Expand Down Expand Up @@ -258,6 +258,15 @@ struct ListPaletteArgs : public IEditableColorsUI, public IContainerUI, public I
colorList.removeAll();
}
}
static gboolean startInteractiveSearch(ListPaletteArgs *args) {
gtk_widget_grab_focus(args->treeview);
gboolean result;
g_signal_emit_by_name(args->treeview, "start-interactive-search", &result);
return false;
}
virtual void find() override {
g_idle_add(reinterpret_cast<GSourceFunc>(startInteractiveSearch), this);
}
virtual void setColor(const ColorObject &colorObject) override {
foreachSelectedItem(GTK_TREE_VIEW(treeview), [&colorObject](ColorObject *old) {
old->setName(colorObject.getName());
Expand Down Expand Up @@ -677,6 +686,16 @@ struct ListPaletteArgs : public IEditableColorsUI, public IContainerUI, public I
args->updateCounts();
return false;
}
static bool contains(std::string_view value, std::string_view start) {
if (start.length() > value.length())
return false;
return boost::ifind_first(value, start);
}
static gboolean onSearchEqual(GtkTreeModel *model, gint, const gchar *key, GtkTreeIter *iter, gpointer) {
gchar *code, *name;
gtk_tree_model_get(model, iter, 1, &code, 2, &name, -1);
return !(contains(code, key) || contains(name, key));
}
ColorObject colorObject;
};
static void set(GtkListStore *store, GtkTreeIter *iter, ColorObject *colorObject, ListPaletteArgs *args) {
Expand Down

0 comments on commit c6bb676

Please sign in to comment.