/* * Widgets for the GNOME edition of the Midnight Commander * * Copyright (C) 1997 The Free Software Foundation * * Author: Miguel de Icaza (miguel@gnu.org) * */ #include #include #include #include #include #include "x.h" #include "gwidget.h" #include "dlg.h" GtkWidget * get_gtk_widget (Widget_Item *p) { GtkWidget *w; g_return_val_if_fail(p, NULL); g_return_val_if_fail(p->widget, NULL); w = GTK_WIDGET (p->widget->wdata); if (GNOME_IS_ENTRY (w)) return (gnome_entry_gtk_entry ((GnomeEntry *)(w))); else return (GTK_WIDGET (p->widget->wdata)); } void x_dialog_stop (Dlg_head *h) { if (h->grided & DLG_GNOME_APP) return; gtk_main_quit (); } void x_focus_widget (Widget_Item *p) { GtkWidget *w = get_gtk_widget (p); gtk_widget_grab_focus (w); } void x_unfocus_widget (Widget_Item *p) { GtkWidget *w = get_gtk_widget (p); GtkWidget *toplevel = gtk_widget_get_toplevel (w); /* Only happens if the widget is not yet added to its container */ /* I am not yet sure why this happens */ if (GTK_IS_WINDOW (toplevel)) gtk_window_set_focus (GTK_WINDOW (gtk_widget_get_toplevel (w)), NULL); } void x_destroy_cmd (void *w) { Widget *widget = (Widget *) w; if (!widget->wdata) return; gtk_widget_destroy (GTK_WIDGET(widget->wdata)); } /* Buttons */ static void gbutton_callback (GtkWidget *w, void *data) { WButton *b = data; Dlg_head *h = (Dlg_head *) b->widget.parent; int stop = 0; if (b->callback) stop = (*b->callback)(b->action, b->callback_data); if (!b->callback || stop){ h->ret_value = b->action; dlg_stop (h); } } char * stock_from_text (char *text) { char *stock; if ( g_strcasecmp (text, _("ok")) == 0) stock = GNOME_STOCK_BUTTON_OK; else if ( g_strcasecmp (text, _("cancel")) == 0) stock = GNOME_STOCK_BUTTON_CANCEL; else if ( g_strcasecmp (text, _("help")) == 0) stock = GNOME_STOCK_BUTTON_HELP; else if ( g_strcasecmp (text, _("yes")) == 0) stock = GNOME_STOCK_BUTTON_YES; else if ( g_strcasecmp (text, _("no")) == 0) stock = GNOME_STOCK_BUTTON_NO; else if ( g_strcasecmp (text, _("exit")) == 0) stock = GNOME_STOCK_BUTTON_CLOSE; else if ( g_strcasecmp (text, _("abort")) == 0) stock = GNOME_STOCK_BUTTON_CANCEL; else stock = 0; return stock; } int x_create_button (Dlg_head *h, widget_data parent, WButton *b) { GtkWidget *button; char *stock; int tag; stock = stock_from_text (b->text); if (stock){ button = gnome_stock_button (stock); } else button = gtk_button_new_with_label (b->text); if (b->flags == DEFPUSH_BUTTON){ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); gtk_widget_grab_default (button); } gtk_widget_show (button); tag = gtk_signal_connect (GTK_OBJECT(button), "clicked", (GtkSignalFunc) gbutton_callback, b); gtk_object_set_data (GTK_OBJECT (button), "click-signal-tag", (void *) tag); b->widget.wdata = (widget_data) button; return 1; } static void x_set_text (GtkWidget *w, gpointer data) { if (!GTK_IS_LABEL (w)) return; gtk_label_set (GTK_LABEL(w), data); } void x_button_set (WButton *b, char *text) { GtkWidget *button = GTK_WIDGET (b->widget.wdata); gtk_container_foreach (GTK_CONTAINER (button), x_set_text, text); } /* Radio buttons */ void x_radio_focus_item (WRadio *radio) { GList *children = GTK_BOX (radio->widget.wdata)->children; int i; for (i = 0; i < radio->count; i++){ if (i == radio->pos){ GtkBoxChild *bc = (GtkBoxChild *) children->data; gtk_widget_grab_focus (GTK_WIDGET (bc->widget)); break; } children = children->next; } } void x_radio_toggle (WRadio *radio) { GList *children = GTK_BOX (radio->widget.wdata)->children; int i; for (i = 0; i < radio->count; i++){ GtkBoxChild *bc = (GtkBoxChild *) children->data; gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bc->widget), (i == radio->sel) ? 1 : 0); children = children->next; } } static void radio_toggle (GtkObject *object, WRadio *r) { int idx = (int) gtk_object_get_data (object, "index"); if (!GTK_TOGGLE_BUTTON (object)->active) return; g_return_if_fail (idx != 0); idx--; r->sel = idx; } static char * remove_hotkey (char *text) { char *t = g_strdup (text); char *p = strchr (t,'&'); if (p) strcpy (p, p+1); return t; } int x_create_radio (Dlg_head *h, widget_data parent, WRadio *r) { GtkWidget *w, *vbox; int i; vbox = gtk_vbox_new (0, 0); for (i = 0; i < r->count; i++){ char *text = remove_hotkey (_(r->texts [i])); if (i == 0){ w = gtk_radio_button_new_with_label (NULL, text); r->first_gtk_radio = w; } else w = gtk_radio_button_new_with_label_from_widget (r->first_gtk_radio, text); g_free (text); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), (i == r->sel)); gtk_signal_connect (GTK_OBJECT (w), "toggled", GTK_SIGNAL_FUNC (radio_toggle), r); gtk_object_set_data (GTK_OBJECT (w), "index", (void *) (i+1)); gtk_box_pack_start_defaults (GTK_BOX (vbox), w); } gtk_widget_show_all (vbox); r->widget.wdata = (widget_data) vbox; return 1; } static void x_check_changed (GtkToggleButton *t, WCheck *c) { c->state ^= C_BOOL; c->state ^= C_CHANGE; } /* Check buttons */ int x_create_check (Dlg_head *h, widget_data parent, WCheck *c) { GtkWidget *w; w = gtk_check_button_new_with_label (c->text); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), (c->state & C_BOOL)); gtk_signal_connect (GTK_OBJECT (w), "toggled", GTK_SIGNAL_FUNC (x_check_changed), c); gtk_widget_show (w); c->widget.wdata = (widget_data) w; return 1; } /* Input lines */ static void entry_click (GtkWidget *widget, GdkEvent *event, WInput *in) { dlg_select_widget (in->widget.parent, in); in->first = 0; } static void entry_release (GtkEditable *entry, GdkEvent *event, WInput *in) { in->point = entry->current_pos; in->mark = (entry->current_pos == entry->selection_start_pos) ? entry->selection_end_pos : entry->selection_start_pos; if (in->point != in->mark) in->first = 1; } static void wentry_changed (GtkEditable *editable, WInput *in) { char *text = gtk_entry_get_text (GTK_ENTRY (editable)); assign_text (in, text); input_set_point (in, editable->current_pos); } int x_create_input (Dlg_head *h, widget_data parent, WInput *in) { GtkWidget *gnome_entry; GtkEntry *entry; /* The widget might have been initialized manually. * Look in gscreen.c for an example */ if (in->widget.wdata) return 1; #ifdef USE_GNOME_ENTRY gnome_entry = gnome_entry_new (in->widget.tkname); #else entry = GTK_ENTRY (gnome_entry = gtk_entry_new ()); gtk_entry_set_visibility (entry, !in->is_password); #endif gtk_widget_show (gnome_entry); in->widget.wdata = (widget_data) gnome_entry; #ifdef USE_GNOME_ENTRY entry = GTK_ENTRY (gnome_entry_gtk_entry (GNOME_ENTRY (gnome_entry))); #endif gtk_entry_set_text (entry, in->buffer); gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); gtk_entry_set_position (entry, in->point); gtk_signal_connect (GTK_OBJECT (entry), "button_press_event", GTK_SIGNAL_FUNC (entry_click), in); gtk_signal_connect (GTK_OBJECT (entry), "button_release_event", GTK_SIGNAL_FUNC (entry_release), in); gtk_signal_connect (GTK_OBJECT (entry), "changed", GTK_SIGNAL_FUNC (wentry_changed), in); return 1; } void x_update_input (WInput *in) { #ifdef USE_GNOME_ENTRY GnomeEntry *gnome_entry; #endif GtkEntry *entry; char *text; int draw = 0; /* If the widget has not been initialized yet (done by WIDGET_INIT) */ if (!in->widget.wdata) return; #ifdef USE_GNOME_ENTRY gnome_entry = GNOME_ENTRY (in->widget.wdata); entry = GTK_ENTRY (gnome_entry_gtk_entry (gnome_entry)); #else entry = GTK_ENTRY (in->widget.wdata); #endif /* Block the signal handler */ gtk_signal_handler_block_by_func ( GTK_OBJECT (entry), GTK_SIGNAL_FUNC(wentry_changed), in); /* Do the actual work */ if (in->first == -1){ gtk_editable_select_region (GTK_EDITABLE (entry), 0, 0); in->first = 0; } text = gtk_entry_get_text (GTK_ENTRY (entry)); if (text && strcmp (text, in->buffer)){ gtk_entry_set_text (entry, in->buffer); draw = 1; } if (GTK_EDITABLE (entry)->current_pos != in->point){ gtk_entry_set_position (entry, in->point); draw = 1; } if (draw){ #ifdef USE_GNOME_ENTRY gtk_widget_draw (GTK_WIDGET (gnome_entry), NULL); #else gtk_widget_draw (GTK_WIDGET (entry), NULL); #endif gtk_editable_changed (GTK_EDITABLE (entry)); gtk_widget_queue_draw (GTK_WIDGET (entry)); } /* Unblock the signal handler */ gtk_signal_handler_unblock_by_func ( GTK_OBJECT (entry), GTK_SIGNAL_FUNC(wentry_changed), in); } /* Listboxes */ static GtkWidget * listbox_pull (widget_data data) { return GTK_BIN (data)->child; } void x_listbox_select_nth (WListbox *l, int nth) { static int inside; GtkCList *clist; if (inside) return; if (!l->widget.wdata) return; inside = 1; clist = GTK_CLIST (listbox_pull (l->widget.wdata)); gtk_clist_select_row (clist, nth, 0); if (gtk_clist_row_is_visible (clist, nth) != GTK_VISIBILITY_FULL) gtk_clist_moveto (clist, nth, 0, 0.5, 0.0); inside = 0; } void x_listbox_delete_nth (WListbox *l, int nth) { gtk_clist_remove (GTK_CLIST (listbox_pull (l->widget.wdata)), nth); } static void listbox_select (GtkWidget *widget, int row, int column, GdkEvent *event, WListbox *l) { Dlg_head *h = l->widget.parent; static int inside; if (inside) return; inside = 1; listbox_select_by_number (l, row); if (!event){ inside = 0; return; } if (event->type == GDK_2BUTTON_PRESS){ switch (l->action){ case listbox_nothing: break; case listbox_finish: h->running = 0; h->ret_value = B_ENTER; gtk_main_quit (); return; case listbox_cback: if ((*l->cback)(l) == listbox_finish){ gtk_main_quit (); return; } } } /* Send an artificial DLG_POST_KEY */ if (event->type == GDK_BUTTON_PRESS) (*l->widget.parent->callback)(l->widget.parent, 0, DLG_POST_KEY); inside = 0; } int x_create_listbox (Dlg_head *h, widget_data parent, WListbox *l) { GtkWidget *listbox, *sw; GtkRequisition req; WLEntry *p; int i; listbox = gtk_clist_new (1); sw = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (sw), listbox); gtk_clist_set_selection_mode (GTK_CLIST (listbox), GTK_SELECTION_BROWSE); gtk_widget_size_request (listbox, &req); gtk_widget_set_usize (listbox, req.width, req.height + 20*8); gtk_signal_connect (GTK_OBJECT (listbox), "select_row", GTK_SIGNAL_FUNC (listbox_select), l); l->widget.wdata = (widget_data) sw; gtk_widget_show (listbox); g_warning ("FIXME: actually compute the real size of the listbox"); l->height = 8; for (p = l->list, i = 0; i < l->count; i++, p = p->next){ char *text [1]; text [0] = p->text; gtk_clist_append (GTK_CLIST (listbox), text); } x_listbox_select_nth (l, l->pos); return 1; } void x_list_insert (WListbox *l, WLEntry *p, WLEntry *e) { int pos = 0, i; char *text [1]; if (!l->widget.wdata) return; for (i = 0; i < l->count; i++){ if (p == e) break; p = p->next; pos++; } if (p != e){ printf ("x_list_insert: should not happen!\n"); return; } text [0] = e->text; gtk_clist_append (GTK_CLIST (listbox_pull (l->widget.wdata)), text); } /* Labels */ int x_create_label (Dlg_head *g, widget_data parent, WLabel *l) { GtkWidget *label; /* Tempo-hack */ if (*l->text == 0){ if (0) label = gtk_label_new (l->widget.tkname); else label = gtk_label_new (""); } else label = gtk_label_new (l->text); gtk_widget_show (label); l->widget.wdata = (widget_data) label; return 1; } void x_label_set_text (WLabel *label, char *text) { if (label->widget.wdata) gtk_label_set (GTK_LABEL (label->widget.wdata), text); } #if 0 /* Buttonbar */ static void buttonbar_clicked (GtkWidget *widget, WButtonBar *bb) { GtkBox *box = GTK_BOX (widget->parent); GList *children = box->children; int i; /* Find out which button we are (number) */ for (i = 0; children; children = children->next, i++){ if (((GtkBoxChild *)children->data)->widget == widget){ if (bb->labels [i].function) (*bb->labels [i].function)(bb->labels [i].data); return; } } printf ("Mhm, should not happen or The Cow is out\n"); } #endif int x_create_buttonbar (Dlg_head *h, widget_data parent, WButtonBar *bb) { GtkWidget *hbox; #if 0 int i; #endif hbox = gtk_hbox_new (0, 0); #if 0 for (i = 0; i < 10; i++){ char buffer [40]; GtkButton *b; g_snprintf (buffer, sizeof (buffer), "F%d %s", i+1, bb->labels [i].text ? bb->labels [i].text : " "); b = (GtkButton *) gtk_button_new_with_label (buffer); gtk_signal_connect (GTK_OBJECT (b), "clicked", GTK_SIGNAL_FUNC (buttonbar_clicked), bb); gtk_widget_show (GTK_WIDGET (b)); gtk_box_pack_start_defaults (GTK_BOX (hbox), (GtkWidget *)b); } gtk_widget_show (hbox); #endif bb->widget.wdata = (widget_data) hbox; return 1; } void x_redefine_label (WButtonBar *bb, int idx) { #if 0 GtkBox *box = GTK_BOX (bb->widget.wdata); GtkBoxChild *bc = (GtkBoxChild *)g_list_nth (box->children, idx)->data; GtkButton *button = GTK_BUTTON (bc->widget); GtkWidget *label = gtk_label_new (bb->labels [idx].text); gtk_widget_show (label); gtk_container_remove (GTK_CONTAINER (button), button->child); gtk_container_add (GTK_CONTAINER (button), label); #endif } /* Gauges */ int x_create_gauge (Dlg_head *h, widget_data parent, WGauge *g) { GtkWidget *pbar; pbar = gtk_progress_bar_new (); gtk_widget_show (pbar); g->widget.wdata = (widget_data) pbar; return 1; } void x_gauge_show (WGauge *g) { gtk_widget_show (GTK_WIDGET (g->widget.wdata)); } void x_gauge_set_value (WGauge *g, int max, int current) { gtk_progress_bar_update (GTK_PROGRESS_BAR (g->widget.wdata), ((gfloat) current / (gfloat) max)); }