⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gtkdlg.c

📁 putty
💻 C
📖 第 1 页 / 共 5 页
字号:
            gtk_container_focus(GTK_CONTAINER(uc->list), GTK_DIR_TAB_FORWARD);
        }
        break;
    }
}

/*
 * During event processing, you might well want to give an error
 * indication to the user. dlg_beep() is a quick and easy generic
 * error; dlg_error() puts up a message-box or equivalent.
 */
void dlg_beep(void *dlg)
{
    gdk_beep();
}

static void errmsg_button_clicked(GtkButton *button, gpointer data)
{
    gtk_widget_destroy(GTK_WIDGET(data));
}

static void set_transient_window_pos(GtkWidget *parent, GtkWidget *child)
{
    gint x, y, w, h, dx, dy;
    GtkRequisition req;
    gtk_window_set_position(GTK_WINDOW(child), GTK_WIN_POS_NONE);
    gtk_widget_size_request(GTK_WIDGET(child), &req);

    gdk_window_get_origin(GTK_WIDGET(parent)->window, &x, &y);
    gdk_window_get_size(GTK_WIDGET(parent)->window, &w, &h);

    /*
     * One corner of the transient will be offset inwards, by 1/4
     * of the parent window's size, from the corresponding corner
     * of the parent window. The corner will be chosen so as to
     * place the transient closer to the centre of the screen; this
     * should avoid transients going off the edge of the screen on
     * a regular basis.
     */
    if (x + w/2 < gdk_screen_width() / 2)
        dx = x + w/4;                  /* work from left edges */
    else
        dx = x + 3*w/4 - req.width;    /* work from right edges */
    if (y + h/2 < gdk_screen_height() / 2)
        dy = y + h/4;                  /* work from top edges */
    else
        dy = y + 3*h/4 - req.height;   /* work from bottom edges */
    gtk_widget_set_uposition(GTK_WIDGET(child), dx, dy);
}

void dlg_error_msg(void *dlg, char *msg)
{
    struct dlgparam *dp = (struct dlgparam *)dlg;
    GtkWidget *window, *hbox, *text, *ok;

    window = gtk_dialog_new();
    text = gtk_label_new(msg);
    gtk_misc_set_alignment(GTK_MISC(text), 0.0, 0.0);
    hbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), text, FALSE, FALSE, 20);
    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox),
                       hbox, FALSE, FALSE, 20);
    gtk_widget_show(text);
    gtk_widget_show(hbox);
    gtk_window_set_title(GTK_WINDOW(window), "Error");
    gtk_label_set_line_wrap(GTK_LABEL(text), TRUE);
    ok = gtk_button_new_with_label("OK");
    gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->action_area),
                     ok, FALSE, FALSE, 0);
    gtk_widget_show(ok);
    GTK_WIDGET_SET_FLAGS(ok, GTK_CAN_DEFAULT);
    gtk_window_set_default(GTK_WINDOW(window), ok);
    gtk_signal_connect(GTK_OBJECT(ok), "clicked",
                       GTK_SIGNAL_FUNC(errmsg_button_clicked), window);
    gtk_signal_connect(GTK_OBJECT(window), "destroy",
                       GTK_SIGNAL_FUNC(window_destroy), NULL);
    gtk_window_set_modal(GTK_WINDOW(window), TRUE);
    gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(dp->window));
    set_transient_window_pos(dp->window, window);
    gtk_widget_show(window);
    gtk_main();
}

/*
 * 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_press(GtkWidget *item, GdkEventButton *event,
			         gpointer data)
{
    struct dlgparam *dp = (struct dlgparam *)data;
    struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(item));
    switch (event->type) {
    default:
    case GDK_BUTTON_PRESS: uc->nclicks = 1; break;
    case GDK_2BUTTON_PRESS: uc->nclicks = 2; break;
    case GDK_3BUTTON_PRESS: uc->nclicks = 3; break;
    }
    return FALSE;
}

static int listitem_button_release(GtkWidget *item, GdkEventButton *event,
                                   gpointer data)
{
    struct dlgparam *dp = (struct dlgparam *)data;
    struct uctrl *uc = dlg_find_bywidget(dp, GTK_WIDGET(item));
    if (uc->nclicks>1) {
	uc->ctrl->generic.handler(uc->ctrl, dp, dp->data, EVENT_ACTION);
        return TRUE;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -