📄 gtkdlg.c
字号:
/*
* This function signals to the front end that the dialog's
* processing is completed, and passes an integer value (typically
* a success status).
*/
void dlg_end(void *dlg, int value)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
dp->retval = value;
gtk_widget_destroy(dp->window);
}
void dlg_refresh(union control *ctrl, void *dlg)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc;
if (ctrl) {
if (ctrl->generic.handler != NULL)
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_REFRESH);
} else {
int i;
for (i = 0; (uc = index234(dp->byctrl, i)) != NULL; i++) {
assert(uc->ctrl != NULL);
if (uc->ctrl->generic.handler != NULL)
uc->ctrl->generic.handler(uc->ctrl, dp,
dp->data, EVENT_REFRESH);
}
}
}
void dlg_coloursel_start(union control *ctrl, void *dlg, int r, int g, int b)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
gdouble cvals[4];
GtkWidget *coloursel =
gtk_color_selection_dialog_new("Select a colour");
GtkColorSelectionDialog *ccs = GTK_COLOR_SELECTION_DIALOG(coloursel);
dp->coloursel_result.ok = FALSE;
gtk_window_set_modal(GTK_WINDOW(coloursel), TRUE);
gtk_color_selection_set_opacity(GTK_COLOR_SELECTION(ccs->colorsel), FALSE);
cvals[0] = r / 255.0;
cvals[1] = g / 255.0;
cvals[2] = b / 255.0;
cvals[3] = 1.0; /* fully opaque! */
gtk_color_selection_set_color(GTK_COLOR_SELECTION(ccs->colorsel), cvals);
gtk_object_set_data(GTK_OBJECT(ccs->ok_button), "user-data",
(gpointer)coloursel);
gtk_object_set_data(GTK_OBJECT(ccs->cancel_button), "user-data",
(gpointer)coloursel);
gtk_object_set_data(GTK_OBJECT(coloursel), "user-data", (gpointer)uc);
gtk_signal_connect(GTK_OBJECT(ccs->ok_button), "clicked",
GTK_SIGNAL_FUNC(coloursel_ok), (gpointer)dp);
gtk_signal_connect(GTK_OBJECT(ccs->cancel_button), "clicked",
GTK_SIGNAL_FUNC(coloursel_cancel), (gpointer)dp);
gtk_signal_connect_object(GTK_OBJECT(ccs->ok_button), "clicked",
GTK_SIGNAL_FUNC(gtk_widget_destroy),
(gpointer)coloursel);
gtk_signal_connect_object(GTK_OBJECT(ccs->cancel_button), "clicked",
GTK_SIGNAL_FUNC(gtk_widget_destroy),
(gpointer)coloursel);
gtk_widget_show(coloursel);
}
int dlg_coloursel_results(union control *ctrl, void *dlg,
int *r, int *g, int *b)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
if (dp->coloursel_result.ok) {
*r = dp->coloursel_result.r;
*g = dp->coloursel_result.g;
*b = dp->coloursel_result.b;
return 1;
} else
return 0;
}
/* ----------------------------------------------------------------------
* Signal handlers while the dialog box is active.
*/
static gboolean widget_focus(GtkWidget *widget, GdkEventFocus *event,
gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
struct uctrl *uc = dlg_find_bywidget(dp, widget);
union control *focus;
if (uc && uc->ctrl)
focus = uc->ctrl;
else
focus = NULL;
if (focus != dp->currfocus) {
dp->lastfocus = dp->currfocus;
dp->currfocus = focus;
}
return FALSE;
}
static void button_clicked(GtkButton *button, gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(button));
uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_ACTION);
}
static void button_toggled(GtkToggleButton *tb, gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(tb));
uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_VALCHANGE);
}
static int editbox_key(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
/*
* GtkEntry has a nasty habit of eating the Return key, which
* is unhelpful since it doesn't actually _do_ anything with it
* (it calls gtk_widget_activate, but our edit boxes never need
* activating). So I catch Return before GtkEntry sees it, and
* pass it straight on to the parent widget. Effect: hitting
* Return in an edit box will now activate the default button
* in the dialog just like it will everywhere else.
*/
if (event->keyval == GDK_Return && widget->parent != NULL) {
gint return_val;
gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event");
gtk_signal_emit_by_name(GTK_OBJECT(widget->parent), "key_press_event",
event, &return_val);
return return_val;
}
return FALSE;
}
static void editbox_changed(GtkEditable *ed, gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
if (!(dp->flags & FLAG_UPDATING_COMBO_LIST)) {
struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(ed));
uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_VALCHANGE);
}
}
static void editbox_lostfocus(GtkWidget *ed, GdkEventFocus *event,
gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(ed));
uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_REFRESH);
}
static int listitem_key(GtkWidget *item, GdkEventKey *event, gpointer data,
int multiple)
{
GtkAdjustment *adj = GTK_ADJUSTMENT(data);
if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up ||
event->keyval == GDK_Down || event->keyval == GDK_KP_Down ||
event->keyval == GDK_Page_Up || event->keyval == GDK_KP_Page_Up ||
event->keyval == GDK_Page_Down || event->keyval == GDK_KP_Page_Down) {
/*
* Up, Down, PgUp or PgDn have been pressed on a ListItem
* in a list box. So, if the list box is single-selection:
*
* - if the list item in question isn't already selected,
* we simply select it.
* - otherwise, we find the next one (or next
* however-far-away) in whichever direction we're going,
* and select that.
* + in this case, we must also fiddle with the
* scrollbar to ensure the newly selected item is
* actually visible.
*
* If it's multiple-selection, we do all of the above
* except actually selecting anything, so we move the focus
* and fiddle the scrollbar to follow it.
*/
GtkWidget *list = item->parent;
gtk_signal_emit_stop_by_name(GTK_OBJECT(item), "key_press_event");
if (!multiple &&
GTK_WIDGET_STATE(item) != GTK_STATE_SELECTED) {
gtk_list_select_child(GTK_LIST(list), item);
} else {
int direction =
(event->keyval==GDK_Up || event->keyval==GDK_KP_Up ||
event->keyval==GDK_Page_Up || event->keyval==GDK_KP_Page_Up)
? -1 : +1;
int step =
(event->keyval==GDK_Page_Down ||
event->keyval==GDK_KP_Page_Down ||
event->keyval==GDK_Page_Up || event->keyval==GDK_KP_Page_Up)
? 2 : 1;
int i, n;
GList *children, *chead;
chead = children = gtk_container_children(GTK_CONTAINER(list));
n = g_list_length(children);
if (step == 2) {
/*
* Figure out how many list items to a screenful,
* and adjust the step appropriately.
*/
step = 0.5 + adj->page_size * n / (adj->upper - adj->lower);
step--; /* go by one less than that */
}
i = 0;
while (children != NULL) {
if (item == children->data)
break;
children = children->next;
i++;
}
while (step > 0) {
if (direction < 0 && i > 0)
children = children->prev, i--;
else if (direction > 0 && i < n-1)
children = children->next, i++;
step--;
}
if (children && children->data) {
if (!multiple)
gtk_list_select_child(GTK_LIST(list),
GTK_WIDGET(children->data));
gtk_widget_grab_focus(GTK_WIDGET(children->data));
gtk_adjustment_clamp_page
(adj,
adj->lower + (adj->upper-adj->lower) * i / n,
adj->lower + (adj->upper-adj->lower) * (i+1) / n);
}
g_list_free(chead);
}
return TRUE;
}
return FALSE;
}
static int listitem_single_key(GtkWidget *item, GdkEventKey *event,
gpointer data)
{
return listitem_key(item, event, data, FALSE);
}
static int listitem_multi_key(GtkWidget *item, GdkEventKey *event,
gpointer data)
{
return listitem_key(item, event, data, TRUE);
}
static int listitem_button(GtkWidget *item, GdkEventButton *event,
gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
if (event->type == GDK_2BUTTON_PRESS ||
event->type == GDK_3BUTTON_PRESS) {
struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(item));
uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_ACTION);
return TRUE;
}
return FALSE;
}
static void list_selchange(GtkList *list, gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(list));
if (!uc) return;
uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_SELCHANGE);
}
static void menuitem_activate(GtkMenuItem *item, gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
GtkWidget *menushell = GTK_WIDGET(item)->parent;
gpointer optmenu = gtk_object_get_data(GTK_OBJECT(menushell), "user-data");
struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(optmenu));
uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_SELCHANGE);
}
static void draglist_move(struct dlgparam *dp, struct uctrl *uc, int direction)
{
int index = dlg_listbox_index(uc->ctrl, dp);
GList *children = gtk_container_children(GTK_CONTAINER(uc->list));
GtkWidget *child;
if ((index < 0) ||
(index == 0 && direction < 0) ||
(index == g_list_length(children)-1 && direction > 0)) {
gdk_beep();
return;
}
child = g_list_nth_data(children, index);
gtk_widget_ref(child);
gtk_list_clear_items(GTK_LIST(uc->list), index, index+1);
g_list_free(children);
children = NULL;
children = g_list_append(children, child);
gtk_list_insert_items(GTK_LIST(uc->list), children, index + direction);
gtk_list_select_item(GTK_LIST(uc->list), index + direction);
uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_VALCHANGE);
}
static void draglist_up(GtkButton *button, gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(button));
draglist_move(dp, uc, -1);
}
static void draglist_down(GtkButton *button, gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(button));
draglist_move(dp, uc, +1);
}
static void filesel_ok(GtkButton *button, gpointer data)
{
/* struct dlgparam *dp = (struct dlgparam *)data; */
gpointer filesel = gtk_object_get_data(GTK_OBJECT(button), "user-data");
struct uctrl *uc = gtk_object_get_data(GTK_OBJECT(filesel), "user-data");
char *name = gtk_file_selection_get_filename(GTK_FILE_SELECTION(filesel));
gtk_entry_set_text(GTK_ENTRY(uc->entry), name);
}
static void fontsel_ok(GtkButton *button, gpointer data)
{
/* struct dlgparam *dp = (struct dlgparam *)data; */
gpointer fontsel = gtk_object_get_data(GTK_OBJECT(button), "user-data");
struct uctrl *uc = gtk_object_get_data(GTK_OBJECT(fontsel), "user-data");
char *name = gtk_font_selection_dialog_get_font_name
(GTK_FONT_SELECTION_DIALOG(fontsel));
gtk_entry_set_text(GTK_ENTRY(uc->entry), name);
}
static void coloursel_ok(GtkButton *button, gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
gpointer coloursel = gtk_object_get_data(GTK_OBJECT(button), "user-data");
struct uctrl *uc = gtk_object_get_data(GTK_OBJECT(coloursel), "user-data");
gdouble cvals[4];
gtk_color_selection_get_color
(GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(coloursel)->colorsel),
cvals);
dp->coloursel_result.r = (int) (255 * cvals[0]);
dp->coloursel_result.g = (int) (255 * cvals[1]);
dp->coloursel_result.b = (int) (255 * cvals[2]);
dp->coloursel_result.ok = TRUE;
uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_CALLBACK);
}
static void coloursel_cancel(GtkButton *button, gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
gpointer coloursel = gtk_object_get_data(GTK_OBJECT(button), "user-data");
struct uctrl *uc = gtk_object_get_data(GTK_OBJECT(coloursel), "user-data");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -