📄 sgtk-find-dialog.c
字号:
/* * Copyright (c) 2004 Jean-Yves Lefort * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include <glib/gi18n.h>#include "sg-util.h"#include "sgtk-find-dialog.h"#include "sgtk-util.h"#include "sgtk-stock.h"#include "sgtk-hig.h"/*** cpp *********************************************************************/#define ENTRY(dialog) (GTK_BIN((dialog)->priv->combo_entry)->child)/*** type definitions ********************************************************/enum { PROP_0, PROP_TOKEN, PROP_HISTORY, PROP_CASE_SENSITIVE, PROP_WRAP_AROUND}; enum { COLUMN_TOKEN, N_COLUMNS}; struct _sGtkFindDialogPrivate{ GtkWidget *combo_entry; GtkWidget *case_sensitive; GtkWidget *wrap_around; GtkListStore *history_store;};/*** variable declarations ***************************************************/static GObjectClass *parent_class = NULL;/*** function declarations ***************************************************/static void sgtk_find_dialog_class_init (sGtkFindDialogClass *class);static void sgtk_find_dialog_init (sGtkFindDialog *dialog);static void sgtk_find_dialog_finalize (GObject *object);static void sgtk_find_dialog_entry_changed_h (GtkEditable *editable, gpointer user_data);static void sgtk_find_dialog_case_sensitive_toggled_h (GtkToggleButton *togglebutton, gpointer user_data);static void sgtk_find_dialog_wrap_around_toggled_h (GtkToggleButton *togglebutton, gpointer user_data);static void sgtk_find_dialog_response_h (GtkDialog *dialog, int response, gpointer data);static void sgtk_find_dialog_set_property (GObject *object, unsigned int prop_id, const GValue *value, GParamSpec *pspec);static void sgtk_find_dialog_get_property (GObject *object, unsigned int prop_id, GValue *value, GParamSpec *pspec);/*** implementation **********************************************************/GTypesgtk_find_dialog_get_type (void){ static GType find_dialog_type = 0; if (! find_dialog_type) { static const GTypeInfo find_dialog_info = { sizeof(sGtkFindDialogClass), NULL, NULL, (GClassInitFunc) sgtk_find_dialog_class_init, NULL, NULL, sizeof(sGtkFindDialog), 0, (GInstanceInitFunc) sgtk_find_dialog_init, }; find_dialog_type = g_type_register_static(SGTK_TYPE_DIALOG, "sGtkFindDialog", &find_dialog_info, 0); } return find_dialog_type;}static voidsgtk_find_dialog_class_init (sGtkFindDialogClass *class){ GObjectClass *object_class = G_OBJECT_CLASS(class); parent_class = g_type_class_peek_parent(class); g_type_class_add_private(class, sizeof(sGtkFindDialogPrivate)); object_class->finalize = sgtk_find_dialog_finalize; object_class->set_property = sgtk_find_dialog_set_property; object_class->get_property = sgtk_find_dialog_get_property; g_object_class_install_property(object_class, PROP_TOKEN, g_param_spec_string("token", _("Token"), _("The current token"), NULL, G_PARAM_WRITABLE | G_PARAM_READABLE)); g_object_class_install_property(object_class, PROP_HISTORY, g_param_spec_pointer("history", _("History"), _("The tokens history list"), G_PARAM_WRITABLE | G_PARAM_READABLE)); g_object_class_install_property(object_class, PROP_CASE_SENSITIVE, g_param_spec_boolean("case-sensitive", _("Case sensitive"), _("The state of the case sensitive knob"), FALSE, G_PARAM_WRITABLE | G_PARAM_READABLE)); g_object_class_install_property(object_class, PROP_WRAP_AROUND, g_param_spec_boolean("wrap-around", _("Wrap around"), _("The state of the wrap around knob"), FALSE, G_PARAM_WRITABLE | G_PARAM_READABLE));}static voidsgtk_find_dialog_init (sGtkFindDialog *dialog){ GtkWidget *vbox; GtkWidget *hbox; GtkWidget *label; dialog->priv = G_TYPE_INSTANCE_GET_PRIVATE(dialog, SGTK_TYPE_FIND_DIALOG, sGtkFindDialogPrivate); gtk_window_set_title(GTK_WINDOW(dialog), _("Find")); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); gtk_dialog_add_buttons(GTK_DIALOG(dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, SGTK_STOCK_PREVIOUS, SGTK_RESPONSE_PREVIOUS, SGTK_STOCK_NEXT, SGTK_RESPONSE_NEXT, NULL); gtk_dialog_set_default_response(GTK_DIALOG(dialog), SGTK_RESPONSE_NEXT); vbox = gtk_vbox_new(FALSE, SGTK_HIG_CONTROL_SPACING); hbox = gtk_hbox_new(FALSE, SGTK_HIG_CONTROL_LABEL_SPACING); label = gtk_label_new_with_mnemonic(_("_Find:")); dialog->priv->combo_entry = gtk_combo_box_entry_new(); gtk_label_set_mnemonic_widget(GTK_LABEL(label), dialog->priv->combo_entry); dialog->priv->history_store = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING); gtk_combo_box_set_model(GTK_COMBO_BOX(dialog->priv->combo_entry), GTK_TREE_MODEL(dialog->priv->history_store)); gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(dialog->priv->combo_entry), COLUMN_TOKEN); gtk_entry_set_activates_default(GTK_ENTRY(ENTRY(dialog)), TRUE); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), dialog->priv->combo_entry, TRUE, TRUE, 0); dialog->priv->case_sensitive = gtk_check_button_new_with_mnemonic(_("C_ase sensitive")); dialog->priv->wrap_around = gtk_check_button_new_with_mnemonic(_("_Wrap around")); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), dialog->priv->case_sensitive, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), dialog->priv->wrap_around, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(SGTK_DIALOG(dialog)->contents), vbox); gtk_widget_show_all(vbox); g_signal_connect(ENTRY(dialog), "changed", G_CALLBACK(sgtk_find_dialog_entry_changed_h), dialog); g_signal_connect(dialog->priv->case_sensitive, "toggled", G_CALLBACK(sgtk_find_dialog_case_sensitive_toggled_h), dialog); g_signal_connect(dialog->priv->wrap_around, "toggled", G_CALLBACK(sgtk_find_dialog_wrap_around_toggled_h), dialog); g_signal_connect(dialog, "response", G_CALLBACK(sgtk_find_dialog_response_h), NULL);}static voidsgtk_find_dialog_finalize (GObject *object){ sGtkFindDialog *dialog = SGTK_FIND_DIALOG(object); g_object_unref(dialog->priv->history_store); parent_class->finalize(object);}static voidsgtk_find_dialog_entry_changed_h (GtkEditable *editable, gpointer user_data){ sGtkFindDialog *dialog = user_data; g_object_notify(G_OBJECT(dialog), "token");}static voidsgtk_find_dialog_case_sensitive_toggled_h (GtkToggleButton *togglebutton, gpointer user_data){ sGtkFindDialog *dialog = user_data; g_object_notify(G_OBJECT(dialog), "case-sensitive");}static voidsgtk_find_dialog_wrap_around_toggled_h (GtkToggleButton *togglebutton, gpointer user_data){ sGtkFindDialog *dialog = user_data; g_object_notify(G_OBJECT(dialog), "wrap-around");}static voidsgtk_find_dialog_response_h (GtkDialog *dialog, int response, gpointer data){ sGtkFindDialog *find_dialog = SGTK_FIND_DIALOG(dialog); switch (response) { case SGTK_RESPONSE_PREVIOUS: case SGTK_RESPONSE_NEXT: { const char *token = gtk_entry_get_text(GTK_ENTRY(ENTRY(find_dialog))); gboolean valid; gboolean already_exists = FALSE; GtkTreeIter iter; valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(find_dialog->priv->history_store), &iter); while (valid) { char *this_token; gtk_tree_model_get(GTK_TREE_MODEL(find_dialog->priv->history_store), &iter, COLUMN_TOKEN, &this_token, -1); already_exists = ! sg_utf8_strcmp(token, this_token); g_free(this_token); if (already_exists) break; valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(find_dialog->priv->history_store), &iter); } if (already_exists) gtk_list_store_move_after(find_dialog->priv->history_store, &iter, NULL); else { gtk_list_store_prepend(find_dialog->priv->history_store, &iter); gtk_list_store_set(find_dialog->priv->history_store, &iter, COLUMN_TOKEN, gtk_entry_get_text(GTK_ENTRY(ENTRY(find_dialog))), -1); } g_object_notify(G_OBJECT(dialog), "history"); } break; }}static voidsgtk_find_dialog_set_property (GObject *object, unsigned int prop_id, const GValue *value, GParamSpec *pspec){ sGtkFindDialog *dialog = SGTK_FIND_DIALOG(object); switch (prop_id) { case PROP_TOKEN: gtk_entry_set_text(GTK_ENTRY(ENTRY(dialog)), g_value_get_string(value)); break; case PROP_HISTORY: { GSList *history = g_value_get_pointer(value); GSList *l; gtk_list_store_clear(dialog->priv->history_store); SG_LIST_FOREACH(l, history) { GtkTreeIter iter; gtk_list_store_append(dialog->priv->history_store, &iter); gtk_list_store_set(dialog->priv->history_store, &iter, COLUMN_TOKEN, l->data, -1); } } break; case PROP_CASE_SENSITIVE: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->priv->case_sensitive), g_value_get_boolean(value)); break; case PROP_WRAP_AROUND: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->priv->wrap_around), g_value_get_boolean(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; }}voidsgtk_find_dialog_set_token (sGtkFindDialog *dialog, const char *token){ g_return_if_fail(SGTK_IS_FIND_DIALOG(dialog)); g_object_set(G_OBJECT(dialog), "token", token, NULL);}voidsgtk_find_dialog_set_history (sGtkFindDialog *dialog, GSList *history){ g_return_if_fail(SGTK_IS_FIND_DIALOG(dialog)); g_object_set(G_OBJECT(dialog), "history", history, NULL);}voidsgtk_find_dialog_set_case_sensitive (sGtkFindDialog *dialog, gboolean case_sensitive){ g_return_if_fail(SGTK_IS_FIND_DIALOG(dialog)); g_object_set(G_OBJECT(dialog), "case-sensitive", case_sensitive, NULL);}voidsgtk_find_dialog_set_wrap_around (sGtkFindDialog *dialog, gboolean wrap_around){ g_return_if_fail(SGTK_IS_FIND_DIALOG(dialog)); g_object_set(G_OBJECT(dialog), "wrap-around", wrap_around, NULL);}static voidsgtk_find_dialog_get_property (GObject *object, unsigned int prop_id, GValue *value, GParamSpec *pspec){ sGtkFindDialog *dialog = SGTK_FIND_DIALOG(object); switch (prop_id) { case PROP_TOKEN: g_value_set_string(value, sgtk_find_dialog_get_token(dialog)); break; case PROP_HISTORY: g_value_set_pointer(value, sgtk_find_dialog_get_history(dialog)); break; case PROP_CASE_SENSITIVE: g_value_set_boolean(value, sgtk_find_dialog_get_case_sensitive(dialog)); break; case PROP_WRAP_AROUND: g_value_set_boolean(value, sgtk_find_dialog_get_wrap_around(dialog)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; }}const char *sgtk_find_dialog_get_token (sGtkFindDialog *dialog){ g_return_val_if_fail(SGTK_IS_FIND_DIALOG(dialog), NULL); return gtk_entry_get_text(GTK_ENTRY(ENTRY(dialog)));}GSList *sgtk_find_dialog_get_history (sGtkFindDialog *dialog){ GSList *history = NULL; gboolean valid; GtkTreeIter iter; g_return_val_if_fail(SGTK_IS_FIND_DIALOG(dialog), NULL); valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dialog->priv->history_store), &iter); while (valid) { char *token; gtk_tree_model_get(GTK_TREE_MODEL(dialog->priv->history_store), &iter, COLUMN_TOKEN, &token, -1); history = g_slist_append(history, token); valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(dialog->priv->history_store), &iter); } return history;}gbooleansgtk_find_dialog_get_case_sensitive (sGtkFindDialog *dialog){ g_return_val_if_fail(SGTK_IS_FIND_DIALOG(dialog), FALSE); return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->priv->case_sensitive));}gbooleansgtk_find_dialog_get_wrap_around (sGtkFindDialog *dialog){ g_return_val_if_fail(SGTK_IS_FIND_DIALOG(dialog), FALSE); return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->priv->wrap_around));}GtkWidget *sgtk_find_dialog_new (GtkWindow *parent){ GtkWidget *dialog; dialog = g_object_new(SGTK_TYPE_FIND_DIALOG, NULL); if (parent) gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); return dialog;}voidsgtk_find_dialog_set_previous_sensitive (sGtkFindDialog *dialog, gboolean sensitive){ g_return_if_fail(SGTK_IS_FIND_DIALOG(dialog)); gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), SGTK_RESPONSE_PREVIOUS, sensitive);}voidsgtk_find_dialog_set_next_sensitive (sGtkFindDialog *dialog, gboolean sensitive){ g_return_if_fail(SGTK_IS_FIND_DIALOG(dialog)); gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), SGTK_RESPONSE_NEXT, sensitive);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -