📄 gtkdlg.c
字号:
} else {
w = gtk_entry_new();
if (ctrl->editbox.password)
gtk_entry_set_visibility(GTK_ENTRY(w), FALSE);
uc->entry = w;
}
gtk_signal_connect(GTK_OBJECT(uc->entry), "changed",
GTK_SIGNAL_FUNC(editbox_changed), dp);
gtk_signal_connect(GTK_OBJECT(uc->entry), "key_press_event",
GTK_SIGNAL_FUNC(editbox_key), dp);
gtk_signal_connect(GTK_OBJECT(uc->entry), "focus_in_event",
GTK_SIGNAL_FUNC(widget_focus), dp);
/*
* Edit boxes, for some strange reason, have a minimum
* width of 150 in GTK 1.2. We don't want this - we'd
* rather the edit boxes acquired their natural width
* from the column layout of the rest of the box.
*
* Also, while we're here, we'll squirrel away the
* edit box height so we can use that to centre its
* label vertically beside it.
*/
gtk_widget_size_request(w, &req);
gtk_widget_set_usize(w, 10, req.height);
if (ctrl->generic.label) {
GtkWidget *label, *container;
label = gtk_label_new(ctrl->generic.label);
shortcut_add(scs, label, ctrl->editbox.shortcut,
SHORTCUT_FOCUS, uc->entry);
container = columns_new(4);
if (ctrl->editbox.percentwidth == 100) {
columns_add(COLUMNS(container), label, 0, 1);
columns_force_left_align(COLUMNS(container), label);
columns_add(COLUMNS(container), w, 0, 1);
} else {
gint percentages[2];
percentages[1] = ctrl->editbox.percentwidth;
percentages[0] = 100 - ctrl->editbox.percentwidth;
columns_set_cols(COLUMNS(container), 2, percentages);
columns_add(COLUMNS(container), label, 0, 1);
columns_force_left_align(COLUMNS(container), label);
columns_add(COLUMNS(container), w, 1, 1);
/* Centre the label vertically. */
gtk_widget_set_usize(label, -1, req.height);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
}
gtk_widget_show(label);
gtk_widget_show(w);
w = container;
uc->label = label;
}
gtk_signal_connect(GTK_OBJECT(uc->entry), "focus_out_event",
GTK_SIGNAL_FUNC(editbox_lostfocus), dp);
}
break;
case CTRL_FILESELECT:
case CTRL_FONTSELECT:
{
GtkWidget *ww;
GtkRequisition req;
char *browsebtn =
(ctrl->generic.type == CTRL_FILESELECT ?
"Browse..." : "Change...");
gint percentages[] = { 75, 25 };
w = columns_new(4);
columns_set_cols(COLUMNS(w), 2, percentages);
if (ctrl->generic.label) {
ww = gtk_label_new(ctrl->generic.label);
columns_add(COLUMNS(w), ww, 0, 2);
columns_force_left_align(COLUMNS(w), ww);
gtk_widget_show(ww);
shortcut_add(scs, ww,
(ctrl->generic.type == CTRL_FILESELECT ?
ctrl->fileselect.shortcut :
ctrl->fontselect.shortcut),
SHORTCUT_UCTRL, uc);
uc->label = ww;
}
uc->entry = ww = gtk_entry_new();
gtk_widget_size_request(ww, &req);
gtk_widget_set_usize(ww, 10, req.height);
columns_add(COLUMNS(w), ww, 0, 1);
gtk_widget_show(ww);
uc->button = ww = gtk_button_new_with_label(browsebtn);
columns_add(COLUMNS(w), ww, 1, 1);
gtk_widget_show(ww);
gtk_signal_connect(GTK_OBJECT(uc->entry), "key_press_event",
GTK_SIGNAL_FUNC(editbox_key), dp);
gtk_signal_connect(GTK_OBJECT(uc->entry), "changed",
GTK_SIGNAL_FUNC(editbox_changed), dp);
gtk_signal_connect(GTK_OBJECT(uc->entry), "focus_in_event",
GTK_SIGNAL_FUNC(widget_focus), dp);
gtk_signal_connect(GTK_OBJECT(uc->button), "focus_in_event",
GTK_SIGNAL_FUNC(widget_focus), dp);
gtk_signal_connect(GTK_OBJECT(ww), "clicked",
GTK_SIGNAL_FUNC(filefont_clicked), dp);
}
break;
case CTRL_LISTBOX:
if (ctrl->listbox.height == 0) {
uc->optmenu = w = gtk_option_menu_new();
uc->menu = gtk_menu_new();
gtk_option_menu_set_menu(GTK_OPTION_MENU(w), uc->menu);
gtk_object_set_data(GTK_OBJECT(uc->menu), "user-data",
(gpointer)uc->optmenu);
gtk_signal_connect(GTK_OBJECT(uc->optmenu), "focus_in_event",
GTK_SIGNAL_FUNC(widget_focus), dp);
} else {
uc->list = gtk_list_new();
if (ctrl->listbox.multisel == 2) {
gtk_list_set_selection_mode(GTK_LIST(uc->list),
GTK_SELECTION_EXTENDED);
} else if (ctrl->listbox.multisel == 1) {
gtk_list_set_selection_mode(GTK_LIST(uc->list),
GTK_SELECTION_MULTIPLE);
} else {
gtk_list_set_selection_mode(GTK_LIST(uc->list),
GTK_SELECTION_SINGLE);
}
w = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(w),
uc->list);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(w),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
uc->adj = gtk_scrolled_window_get_vadjustment
(GTK_SCROLLED_WINDOW(w));
gtk_widget_show(uc->list);
gtk_signal_connect(GTK_OBJECT(uc->list), "selection-changed",
GTK_SIGNAL_FUNC(list_selchange), dp);
gtk_signal_connect(GTK_OBJECT(uc->list), "focus_in_event",
GTK_SIGNAL_FUNC(widget_focus), dp);
/*
* Adjust the height of the scrolled window to the
* minimum given by the height parameter.
*
* This piece of guesswork is a horrid hack based
* on looking inside the GTK 1.2 sources
* (specifically gtkviewport.c, which appears to be
* the widget which provides the border around the
* scrolling area). Anyone lets me know how I can
* do this in a way which isn't at risk from GTK
* upgrades, I'd be grateful.
*/
{
int edge = GTK_WIDGET(uc->list)->style->klass->ythickness;
gtk_widget_set_usize(w, 10,
2*edge + (ctrl->listbox.height *
listitemheight));
}
if (ctrl->listbox.draglist) {
/*
* GTK doesn't appear to make it easy to
* implement a proper draggable list; so
* instead I'm just going to have to put an Up
* and a Down button to the right of the actual
* list box. Ah well.
*/
GtkWidget *cols, *button;
static const gint percentages[2] = { 80, 20 };
cols = columns_new(4);
columns_set_cols(COLUMNS(cols), 2, percentages);
columns_add(COLUMNS(cols), w, 0, 1);
gtk_widget_show(w);
button = gtk_button_new_with_label("Up");
columns_add(COLUMNS(cols), button, 1, 1);
gtk_widget_show(button);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(draglist_up), dp);
gtk_signal_connect(GTK_OBJECT(button), "focus_in_event",
GTK_SIGNAL_FUNC(widget_focus), dp);
button = gtk_button_new_with_label("Down");
columns_add(COLUMNS(cols), button, 1, 1);
gtk_widget_show(button);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(draglist_down), dp);
gtk_signal_connect(GTK_OBJECT(button), "focus_in_event",
GTK_SIGNAL_FUNC(widget_focus), dp);
w = cols;
}
}
if (ctrl->generic.label) {
GtkWidget *label, *container;
label = gtk_label_new(ctrl->generic.label);
container = columns_new(4);
if (ctrl->listbox.percentwidth == 100) {
columns_add(COLUMNS(container), label, 0, 1);
columns_force_left_align(COLUMNS(container), label);
columns_add(COLUMNS(container), w, 0, 1);
} else {
gint percentages[2];
percentages[1] = ctrl->listbox.percentwidth;
percentages[0] = 100 - ctrl->listbox.percentwidth;
columns_set_cols(COLUMNS(container), 2, percentages);
columns_add(COLUMNS(container), label, 0, 1);
columns_force_left_align(COLUMNS(container), label);
columns_add(COLUMNS(container), w, 1, 1);
}
gtk_widget_show(label);
gtk_widget_show(w);
shortcut_add(scs, label, ctrl->listbox.shortcut,
SHORTCUT_UCTRL, uc);
w = container;
uc->label = label;
}
break;
case CTRL_TEXT:
/*
* Wrapping text widgets don't sit well with the GTK
* layout model, in which widgets state a minimum size
* and the whole window then adjusts to the smallest
* size it can sensibly take given its contents. A
* wrapping text widget _has_ no clear minimum size;
* instead it has a range of possibilities. It can be
* one line deep but 2000 wide, or two lines deep and
* 1000 pixels, or three by 867, or four by 500 and so
* on. It can be as short as you like provided you
* don't mind it being wide, or as narrow as you like
* provided you don't mind it being tall.
*
* Therefore, it fits very badly into the layout model.
* Hence the only thing to do is pick a width and let
* it choose its own number of lines. To do this I'm
* going to cheat a little. All new wrapping text
* widgets will be created with a minimal text content
* "X"; then, after the rest of the dialog box is set
* up and its size calculated, the text widgets will be
* told their width and given their real text, which
* will cause the size to be recomputed in the y
* direction (because many of them will expand to more
* than one line).
*/
uc->text = w = gtk_label_new("X");
gtk_misc_set_alignment(GTK_MISC(w), 0.0, 0.0);
gtk_label_set_line_wrap(GTK_LABEL(w), TRUE);
uc->textsig =
gtk_signal_connect(GTK_OBJECT(w), "size-allocate",
GTK_SIGNAL_FUNC(label_sizealloc), dp);
break;
}
assert(w != NULL);
columns_add(cols, w,
COLUMN_START(ctrl->generic.column),
COLUMN_SPAN(ctrl->generic.column));
if (left)
columns_force_left_align(cols, w);
gtk_widget_show(w);
uc->toplevel = w;
dlg_add_uctrl(dp, uc);
}
return ret;
}
struct selparam {
struct dlgparam *dp;
GtkNotebook *panels;
GtkWidget *panel, *treeitem;
struct Shortcuts shortcuts;
};
static void treeitem_sel(GtkItem *item, gpointer data)
{
struct selparam *sp = (struct selparam *)data;
gint page_num;
page_num = gtk_notebook_page_num(sp->panels, sp->panel);
gtk_notebook_set_page(sp->panels, page_num);
dlg_refresh(NULL, sp->dp);
sp->dp->shortcuts = &sp->shortcuts;
sp->dp->currtreeitem = sp->treeitem;
}
static void window_destroy(GtkWidget *widget, gpointer data)
{
gtk_main_quit();
}
static int tree_grab_focus(struct dlgparam *dp)
{
int i, f;
/*
* See if any of the treeitems has the focus.
*/
f = -1;
for (i = 0; i < dp->ntreeitems; i++)
if (GTK_WIDGET_HAS_FOCUS(dp->treeitems[i])) {
f = i;
break;
}
if (f >= 0)
return FALSE;
else {
gtk_widget_grab_focus(dp->currtreeitem);
return TRUE;
}
}
gint tree_focus(GtkContainer *container, GtkDirectionType direction,
gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
gtk_signal_emit_stop_by_name(GTK_OBJECT(container), "focus");
/*
* If there's a focused treeitem, we return FALSE to cause the
* focus to move on to some totally other control. If not, we
* focus the selected one.
*/
return tree_grab_focus(dp);
}
int win_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
struct dlgparam *dp = (struct dlgparam *)data;
if (event->keyval == GDK_Escape && dp->cancelbutton) {
gtk_signal_emit_by_name(GTK_OBJECT(dp->cancelbutton), "clicked");
return TRUE;
}
if ((event->state & GDK_MOD1_MASK) &&
(unsigned char)event->string[0] > 0 &&
(unsigned char)event->string[0] <= 127) {
int schr = (unsigned char)event->string[0];
struct Shortcut *sc = &dp->shortcuts->sc[schr];
switch (sc->action) {
case SHORTCUT_TREE:
tree_grab_focus(dp);
break;
case SHORTCUT_FOCUS:
gtk_widget_grab_focus(sc->widget);
break;
case SHORTCUT_UCTRL:
/*
* We must do something sensible with a uctrl.
* Precisely what this is depends on the type of
* control.
*/
switch (sc->uc->ctrl->generic.type) {
case CTRL_CHECKBOX:
case CTRL_BUTTON:
/* Check boxes and buttons get the focus _and_ get toggled. */
gtk_widget_grab_focus(sc->uc->toplev
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -