📄 gtkdlg.c
字号:
gtk_container_add(GTK_CONTAINER(uc->menu), menuitem);
gtk_widget_show(menuitem);
gtk_object_set_data(GTK_OBJECT(menuitem), "user-data",
GINT_TO_POINTER(id));
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(menuitem_activate), dp);
} else if (!uc->entry) {
/*
* List item in a non-combo-box list box. We make all of
* these Columns containing GtkLabels. This allows us to do
* the nasty force_left hack irrespective of whether there
* are tabs in the thing.
*/
GtkWidget *listitem = gtk_list_item_new();
GtkWidget *cols = columns_new(10);
gint *percents;
int i, ncols;
/* Count the tabs in the text, and hence determine # of columns. */
ncols = 1;
for (i = 0; text[i]; i++)
if (text[i] == '\t')
ncols++;
assert(ncols <=
(uc->ctrl->listbox.ncols ? uc->ctrl->listbox.ncols : 1));
percents = snewn(ncols, gint);
percents[ncols-1] = 100;
for (i = 0; i < ncols-1; i++) {
percents[i] = uc->ctrl->listbox.percentages[i];
percents[ncols-1] -= percents[i];
}
columns_set_cols(COLUMNS(cols), ncols, percents);
sfree(percents);
for (i = 0; i < ncols; i++) {
int len = strcspn(text, "\t");
char *dup = dupprintf("%.*s", len, text);
GtkWidget *label;
text += len;
if (*text) text++;
label = gtk_label_new(dup);
sfree(dup);
columns_add(COLUMNS(cols), label, i, 1);
columns_force_left_align(COLUMNS(cols), label);
gtk_widget_show(label);
}
gtk_container_add(GTK_CONTAINER(listitem), cols);
gtk_widget_show(cols);
gtk_container_add(GTK_CONTAINER(uc->list), listitem);
gtk_widget_show(listitem);
if (ctrl->listbox.multisel) {
gtk_signal_connect(GTK_OBJECT(listitem), "key_press_event",
GTK_SIGNAL_FUNC(listitem_multi_key), uc->adj);
} else {
gtk_signal_connect(GTK_OBJECT(listitem), "key_press_event",
GTK_SIGNAL_FUNC(listitem_single_key), uc->adj);
}
gtk_signal_connect(GTK_OBJECT(listitem), "focus_in_event",
GTK_SIGNAL_FUNC(widget_focus), dp);
gtk_signal_connect(GTK_OBJECT(listitem), "button_press_event",
GTK_SIGNAL_FUNC(listitem_button), dp);
gtk_object_set_data(GTK_OBJECT(listitem), "user-data",
GINT_TO_POINTER(id));
} else {
/*
* List item in a combo-box list, which means the sensible
* thing to do is make it a perfectly normal label. Hence
* tabs are disregarded.
*/
GtkWidget *listitem = gtk_list_item_new_with_label(text);
gtk_container_add(GTK_CONTAINER(uc->list), listitem);
gtk_widget_show(listitem);
gtk_object_set_data(GTK_OBJECT(listitem), "user-data",
GINT_TO_POINTER(id));
}
dp->flags &= ~FLAG_UPDATING_COMBO_LIST;
}
int dlg_listbox_getid(union control *ctrl, void *dlg, int index)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
GList *children;
GtkObject *item;
assert(uc->ctrl->generic.type == CTRL_EDITBOX ||
uc->ctrl->generic.type == CTRL_LISTBOX);
assert(uc->menu != NULL || uc->list != NULL);
children = gtk_container_children(GTK_CONTAINER(uc->menu ? uc->menu :
uc->list));
item = GTK_OBJECT(g_list_nth_data(children, index));
g_list_free(children);
return GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(item), "user-data"));
}
/* dlg_listbox_index returns <0 if no single element is selected. */
int dlg_listbox_index(union control *ctrl, void *dlg)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
GList *children;
GtkWidget *item, *activeitem;
int i;
int selected = -1;
assert(uc->ctrl->generic.type == CTRL_EDITBOX ||
uc->ctrl->generic.type == CTRL_LISTBOX);
assert(uc->menu != NULL || uc->list != NULL);
if (uc->menu)
activeitem = gtk_menu_get_active(GTK_MENU(uc->menu));
else
activeitem = NULL; /* unnecessarily placate gcc */
children = gtk_container_children(GTK_CONTAINER(uc->menu ? uc->menu :
uc->list));
for (i = 0; children!=NULL && (item = GTK_WIDGET(children->data))!=NULL;
i++, children = children->next) {
if (uc->menu ? activeitem == item :
GTK_WIDGET_STATE(item) == GTK_STATE_SELECTED) {
if (selected == -1)
selected = i;
else
selected = -2;
}
}
g_list_free(children);
return selected < 0 ? -1 : selected;
}
int dlg_listbox_issel(union control *ctrl, void *dlg, int index)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
GList *children;
GtkWidget *item, *activeitem;
assert(uc->ctrl->generic.type == CTRL_EDITBOX ||
uc->ctrl->generic.type == CTRL_LISTBOX);
assert(uc->menu != NULL || uc->list != NULL);
children = gtk_container_children(GTK_CONTAINER(uc->menu ? uc->menu :
uc->list));
item = GTK_WIDGET(g_list_nth_data(children, index));
g_list_free(children);
if (uc->menu) {
activeitem = gtk_menu_get_active(GTK_MENU(uc->menu));
return item == activeitem;
} else {
return GTK_WIDGET_STATE(item) == GTK_STATE_SELECTED;
}
}
void dlg_listbox_select(union control *ctrl, void *dlg, int index)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
assert(uc->ctrl->generic.type == CTRL_EDITBOX ||
uc->ctrl->generic.type == CTRL_LISTBOX);
assert(uc->optmenu != NULL || uc->list != NULL);
if (uc->optmenu) {
gtk_option_menu_set_history(GTK_OPTION_MENU(uc->optmenu), index);
} else {
gtk_list_select_item(GTK_LIST(uc->list), index);
}
}
void dlg_text_set(union control *ctrl, void *dlg, char const *text)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
assert(uc->ctrl->generic.type == CTRL_TEXT);
assert(uc->text != NULL);
gtk_label_set_text(GTK_LABEL(uc->text), text);
}
void dlg_filesel_set(union control *ctrl, void *dlg, Filename fn)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
assert(uc->ctrl->generic.type == CTRL_FILESELECT);
assert(uc->entry != NULL);
gtk_entry_set_text(GTK_ENTRY(uc->entry), fn.path);
}
void dlg_filesel_get(union control *ctrl, void *dlg, Filename *fn)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
assert(uc->ctrl->generic.type == CTRL_FILESELECT);
assert(uc->entry != NULL);
strncpy(fn->path, gtk_entry_get_text(GTK_ENTRY(uc->entry)),
lenof(fn->path));
fn->path[lenof(fn->path)-1] = '\0';
}
void dlg_fontsel_set(union control *ctrl, void *dlg, FontSpec fs)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
assert(uc->ctrl->generic.type == CTRL_FONTSELECT);
assert(uc->entry != NULL);
gtk_entry_set_text(GTK_ENTRY(uc->entry), fs.name);
}
void dlg_fontsel_get(union control *ctrl, void *dlg, FontSpec *fs)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
assert(uc->ctrl->generic.type == CTRL_FONTSELECT);
assert(uc->entry != NULL);
strncpy(fs->name, gtk_entry_get_text(GTK_ENTRY(uc->entry)),
lenof(fs->name));
fs->name[lenof(fs->name)-1] = '\0';
}
/*
* Bracketing a large set of updates in these two functions will
* cause the front end (if possible) to delay updating the screen
* until it's all complete, thus avoiding flicker.
*/
void dlg_update_start(union control *ctrl, void *dlg)
{
/*
* Apparently we can't do this at all in GTK. GtkCList supports
* freeze and thaw, but not GtkList. Bah.
*/
}
void dlg_update_done(union control *ctrl, void *dlg)
{
/*
* Apparently we can't do this at all in GTK. GtkCList supports
* freeze and thaw, but not GtkList. Bah.
*/
}
void dlg_set_focus(union control *ctrl, void *dlg)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct uctrl *uc = dlg_find_byctrl(dp, ctrl);
switch (ctrl->generic.type) {
case CTRL_CHECKBOX:
case CTRL_BUTTON:
/* Check boxes and buttons get the focus _and_ get toggled. */
gtk_widget_grab_focus(uc->toplevel);
break;
case CTRL_FILESELECT:
case CTRL_FONTSELECT:
case CTRL_EDITBOX:
/* Anything containing an edit box gets that focused. */
gtk_widget_grab_focus(uc->entry);
break;
case CTRL_RADIO:
/*
* Radio buttons: we find the currently selected button and
* focus it.
*/
{
int i;
for (i = 0; i < ctrl->radio.nbuttons; i++)
if (gtk_toggle_button_get_active
(GTK_TOGGLE_BUTTON(uc->buttons[i]))) {
gtk_widget_grab_focus(uc->buttons[i]);
}
}
break;
case CTRL_LISTBOX:
/*
* If the list is really an option menu, we focus it.
* Otherwise we tell it to focus one of its children, which
* appears to do the Right Thing.
*/
if (uc->optmenu) {
gtk_widget_grab_focus(uc->optmenu);
} else {
assert(uc->list != NULL);
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();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -