/* jinete - a GUI library * Copyright (C) 2003-2005 by David A. Capello * * Jinete is gift-ware. */ #include #include "jinete.h" typedef struct ComboBox { JWidget entry; JWidget button; JWidget window; JList items; int selected; bool editable : 1; bool clickopen : 1; bool casesensitive : 1; } ComboBox; #define COMBOBOX(widget) ((ComboBox *)jwidget_get_data(widget, JI_COMBOBOX)) #define IS_VALID_ITEM(widget, index) \ (index >= 0 && index < jlist_length(COMBOBOX(widget)->items)) static bool combobox_msg_proc(JWidget widget, JMessage msg); static bool combobox_entry_msg_proc(JWidget widget, JMessage msg); static bool combobox_listbox_msg_proc(JWidget widget, JMessage msg); static void combobox_button_cmd(JWidget widget, void *data); static void combobox_open_window(JWidget widget); static void combobox_close_window(JWidget widget); static void combobox_switch_window(JWidget widget); static JRect combobox_get_windowpos(ComboBox *combobox); JWidget jcombobox_new (void) { JWidget widget = jbox_new (JI_HORIZONTAL); ComboBox *combobox = jnew (ComboBox, 1); combobox->entry = jentry_new (256, ""); combobox->button = jbutton_new ("^"); combobox->window = NULL; combobox->items = jlist_new(); combobox->selected = 0; combobox->editable = FALSE; combobox->clickopen = TRUE; combobox->casesensitive = TRUE; combobox->entry->user_data[0] = widget; combobox->button->user_data[0] = widget; /* XXXX */ /* widget->child_spacing = 0; */ jwidget_focusrest (widget, TRUE); jwidget_add_hook (widget, JI_COMBOBOX, combobox_msg_proc, combobox); jwidget_add_hook (combobox->entry, JI_WIDGET, combobox_entry_msg_proc, NULL); jwidget_expansive (combobox->entry, TRUE); jbutton_set_bevel (combobox->button, 0, 2, 0, 2); jbutton_add_command_data (combobox->button, combobox_button_cmd, widget); jwidget_add_child (widget, combobox->entry); jwidget_add_child (widget, combobox->button); jcombobox_editable (widget, combobox->editable); return widget; } void jcombobox_editable (JWidget widget, bool state) { ComboBox *combobox = jwidget_get_data (widget, JI_COMBOBOX); combobox->editable = state; if (state) { jentry_readonly (combobox->entry, FALSE); jentry_show_cursor (combobox->entry); } else { jentry_readonly (combobox->entry, TRUE); jentry_hide_cursor (combobox->entry); } } void jcombobox_clickopen (JWidget widget, bool state) { ComboBox *combobox = jwidget_get_data (widget, JI_COMBOBOX); combobox->clickopen = state; } void jcombobox_casesensitive (JWidget widget, bool state) { ComboBox *combobox = jwidget_get_data (widget, JI_COMBOBOX); combobox->casesensitive = state; } bool jcombobox_is_editable (JWidget widget) { ComboBox *combobox = jwidget_get_data (widget, JI_COMBOBOX); return combobox->editable; } bool jcombobox_is_clickopen (JWidget widget) { ComboBox *combobox = jwidget_get_data (widget, JI_COMBOBOX); return combobox->clickopen; } bool jcombobox_is_casesensitive (JWidget widget) { ComboBox *combobox = jwidget_get_data (widget, JI_COMBOBOX); return combobox->casesensitive; } void jcombobox_add_string(JWidget widget, const char *string) { ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); bool sel_first = jlist_empty(combobox->items); jlist_append(combobox->items, jstrdup(string)); if (sel_first) jcombobox_select_index(widget, 0); } void jcombobox_del_string(JWidget widget, const char *string) { jcombobox_del_index (widget, jcombobox_get_index (widget, string)); } void jcombobox_del_index (JWidget widget, int index) { ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); jlist_remove (combobox->items, jlist_nth_data (combobox->items, index)); } void jcombobox_select_index (JWidget widget, int index) { ComboBox *combobox = jwidget_get_data (widget, JI_COMBOBOX); JLink link = jlist_nth_link (combobox->items, index); if (link != combobox->items->end) { combobox->selected = index; jwidget_set_text (combobox->entry, link->data); } } void jcombobox_select_string(JWidget widget, const char *string) { jcombobox_select_index(widget, jcombobox_get_index(widget, string)); } int jcombobox_get_selected_index(JWidget widget) { ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); return combobox->items ? combobox->selected: -1; } const char *jcombobox_get_selected_string(JWidget widget) { ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); return jlist_nth_data(combobox->items, combobox->selected); } const char *jcombobox_get_string(JWidget widget, int index) { ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); if (index >= 0 && index < jlist_length(combobox->items)) return jlist_nth_link(combobox->items, index)->data; else return NULL; } int jcombobox_get_index(JWidget widget, const char *string) { ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); int index = 0; JLink link; JI_LIST_FOR_EACH(combobox->items, link) { if ((combobox->casesensitive && ustrcmp(link->data, string) == 0) || (!combobox->casesensitive && ustricmp(link->data, string) == 0)) return index; index++; } return -1; } int jcombobox_get_count(JWidget widget) { ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); return jlist_length(combobox->items); } JWidget jcombobox_get_entry_widget(JWidget widget) { ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); return combobox->entry; } static bool combobox_msg_proc(JWidget widget, JMessage msg) { switch (msg->type) { case JM_CLOSE: combobox_close_window(widget); break; case JM_DESTROY: { ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); JLink link; JI_LIST_FOR_EACH(combobox->items, link) jfree(link->data); jlist_free(combobox->items); jfree(combobox); } break; case JM_WINMOVE: { ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); if (combobox->window) { JRect rc = combobox_get_windowpos(combobox); jwindow_move(combobox->window, rc); jrect_free(rc); } } break; } return FALSE; } static bool combobox_entry_msg_proc (JWidget widget, JMessage msg) { switch (msg->type) { case JM_CHAR: if (jwidget_has_focus (widget)) { if (!jcombobox_is_editable (widget->user_data[0])) { if (msg->key.scancode == KEY_SPACE || msg->key.scancode == KEY_ENTER || msg->key.scancode == KEY_ENTER_PAD) { combobox_switch_window (widget->user_data[0]); return TRUE; } } else { if (msg->key.scancode == KEY_ENTER || msg->key.scancode == KEY_ENTER_PAD) { combobox_switch_window (widget->user_data[0]); return TRUE; } } } break; case JM_BUTTONPRESSED: if (jcombobox_is_clickopen (widget->user_data[0])) combobox_open_window (widget->user_data[0]); if (jcombobox_is_editable (widget->user_data[0])) { jmanager_set_focus (widget); } else return TRUE; break; } return FALSE; } static bool combobox_listbox_msg_proc (JWidget widget, JMessage msg) { switch (msg->type) { case JM_SIGNAL: if (msg->signal.num == JI_SIGNAL_LISTBOX_CHANGE) { int index = jlistbox_get_selected_index(widget); if (IS_VALID_ITEM(widget->user_data[0], index)) { jcombobox_select_index(widget->user_data[0], index); jwidget_emit_signal(widget->user_data[0], JI_SIGNAL_COMBOBOX_CHANGE); } } break; case JM_BUTTONRELEASED: { int index = jcombobox_get_selected_index(widget->user_data[0]); if (IS_VALID_ITEM(widget->user_data[0], index)) jwidget_emit_signal(widget->user_data[0], JI_SIGNAL_COMBOBOX_SELECT); combobox_close_window(widget->user_data[0]); } return TRUE; case JM_CHAR: if (jwidget_has_focus (widget)) { if (msg->key.scancode == KEY_SPACE || msg->key.scancode == KEY_ENTER || msg->key.scancode == KEY_ENTER_PAD) { combobox_close_window (widget->user_data[0]); return TRUE; } } break; } return FALSE; } static void combobox_button_cmd (JWidget widget, void *data) { combobox_switch_window ((JWidget)data); } static void combobox_open_window (JWidget widget) { ComboBox *combobox = jwidget_get_data (widget, JI_COMBOBOX); if (!combobox->window) { JWidget view, listbox; JLink link; int size; JRect rc; combobox->window = jwindow_new (NULL); view = jview_new (); listbox = jlistbox_new (); listbox->user_data[0] = widget; jwidget_add_hook (listbox, JI_WIDGET, combobox_listbox_msg_proc, NULL); JI_LIST_FOR_EACH(combobox->items, link) jwidget_add_child (listbox, jlistitem_new(link->data)); jwindow_ontop (combobox->window, TRUE); jwidget_noborders (combobox->window); size = jlist_length (combobox->items); jwidget_set_static_size (view, jrect_w(combobox->entry->rc), 2+(2+jwidget_get_text_height (listbox))*MID(1, size, 10)+2); jwidget_add_child (combobox->window, view); jview_attach (view, listbox); jwidget_signal_off (listbox); jlistbox_select_index (listbox, combobox->selected); jwidget_signal_on (listbox); jwindow_remap (combobox->window); rc = combobox_get_windowpos(combobox); jwindow_position(combobox->window, rc->x1, rc->y1); jrect_free(rc); jwindow_open_bg (combobox->window); jmanager_set_focus (listbox); } } static void combobox_close_window (JWidget widget) { ComboBox *combobox = jwidget_get_data (widget, JI_COMBOBOX); if (combobox->window) { jwindow_close (combobox->window, widget); combobox->window = NULL; jmanager_set_focus (combobox->entry); } } static void combobox_switch_window (JWidget widget) { ComboBox *combobox = jwidget_get_data (widget, JI_COMBOBOX); if (!combobox->window) combobox_open_window (widget); else combobox_close_window (widget); } static JRect combobox_get_windowpos(ComboBox *combobox) { JRect rc = jrect_new(combobox->entry->rc->x1, combobox->entry->rc->y2, combobox->entry->rc->x2, combobox->entry->rc->y2+ jrect_h(combobox->window->rc)); if (rc->y2 > JI_SCREEN_H) jrect_displace (rc, 0, -(jrect_h(rc)+jrect_h(combobox->entry->rc))); return rc; }