aseprite/src/jinete/jcombox.c

460 lines
12 KiB
C
Raw Normal View History

2007-09-23 20:13:58 +00:00
/* Jinete - a GUI library
* Copyright (C) 2003, 2004, 2005, 2007, 2008 David A. Capello.
2007-09-23 20:13:58 +00:00
* All rights reserved.
2007-09-18 23:57:02 +00:00
*
2007-09-23 20:13:58 +00:00
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the Jinete nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2007-09-18 23:57:02 +00:00
*/
#include <allegro.h>
#include "jinete/jinete.h"
2007-09-18 23:57:02 +00:00
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);
2007-09-18 23:57:02 +00:00
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;
/* TODO this separation should be from the JTheme */
widget->child_spacing = 0;
2007-09-18 23:57:02 +00:00
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);
2007-09-18 23:57:02 +00:00
jwidget_expansive(combobox->entry, TRUE);
jbutton_set_bevel(combobox->button, 0, 2, 0, 2);
jbutton_add_command_data(combobox->button, combobox_button_cmd, widget);
2007-09-18 23:57:02 +00:00
jwidget_add_child(widget, combobox->entry);
jwidget_add_child(widget, combobox->button);
2007-09-18 23:57:02 +00:00
jcombobox_editable(widget, combobox->editable);
2007-09-18 23:57:02 +00:00
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)
2007-09-18 23:57:02 +00:00
{
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
jlist_remove(combobox->items, jlist_nth_data (combobox->items, index));
2007-09-18 23:57:02 +00:00
}
void jcombobox_select_index(JWidget widget, int index)
2007-09-18 23:57:02 +00:00
{
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)
2007-09-18 23:57:02 +00:00
{
2007-12-04 21:50:31 +00:00
JWidget combo_widget = widget->user_data[0];
2007-09-18 23:57:02 +00:00
switch (msg->type) {
case JM_CHAR:
2007-12-04 21:50:31 +00:00
if (jwidget_has_focus(widget)) {
if (!jcombobox_is_editable(combo_widget)) {
2007-09-18 23:57:02 +00:00
if (msg->key.scancode == KEY_SPACE ||
msg->key.scancode == KEY_ENTER ||
msg->key.scancode == KEY_ENTER_PAD) {
2007-12-04 21:50:31 +00:00
combobox_switch_window(combo_widget);
2007-09-18 23:57:02 +00:00
return TRUE;
}
}
else {
if (msg->key.scancode == KEY_ENTER ||
msg->key.scancode == KEY_ENTER_PAD) {
2007-12-04 21:50:31 +00:00
combobox_switch_window(combo_widget);
2007-09-18 23:57:02 +00:00
return TRUE;
}
}
}
break;
case JM_BUTTONPRESSED:
2007-12-04 21:50:31 +00:00
if (jcombobox_is_clickopen(combo_widget)) {
combobox_switch_window(combo_widget);
/* combobox_open_window(combo_widget); */
}
2007-09-18 23:57:02 +00:00
2007-12-04 21:50:31 +00:00
if (jcombobox_is_editable(combo_widget)) {
jmanager_set_focus(widget);
2007-09-18 23:57:02 +00:00
}
else
return TRUE;
break;
}
return FALSE;
}
static bool combobox_listbox_msg_proc(JWidget widget, JMessage msg)
2007-09-18 23:57:02 +00:00
{
2007-12-04 21:50:31 +00:00
JWidget combo_widget = widget->user_data[0];
2007-09-18 23:57:02 +00:00
switch (msg->type) {
case JM_SIGNAL:
if (msg->signal.num == JI_SIGNAL_LISTBOX_CHANGE) {
int index = jlistbox_get_selected_index(widget);
2007-12-04 21:50:31 +00:00
if (IS_VALID_ITEM(combo_widget, index)) {
jcombobox_select_index(combo_widget, index);
2007-09-18 23:57:02 +00:00
2007-12-04 21:50:31 +00:00
jwidget_emit_signal(combo_widget, JI_SIGNAL_COMBOBOX_CHANGE);
2007-09-18 23:57:02 +00:00
}
}
break;
case JM_BUTTONRELEASED:
{
2007-12-04 21:50:31 +00:00
int index = jcombobox_get_selected_index(combo_widget);
2007-09-18 23:57:02 +00:00
2007-12-04 21:50:31 +00:00
if (IS_VALID_ITEM(combo_widget, index))
jwidget_emit_signal(combo_widget, JI_SIGNAL_COMBOBOX_SELECT);
2007-09-18 23:57:02 +00:00
2007-12-04 21:50:31 +00:00
combobox_close_window(combo_widget);
2007-09-18 23:57:02 +00:00
}
return TRUE;
2007-12-04 21:50:31 +00:00
/* case JM_IDLE: { */
/* /\* if the user clicks outside the listbox *\/ */
/* if (!jmouse_b(1) && jmouse_b(0) && !jwidget_has_mouse(widget)) { */
/* ComboBox *combobox = jwidget_get_data(combo_widget, JI_COMBOBOX); */
/* if (combobox->entry && !jwidget_has_mouse(combobox->entry) && */
/* combobox->button && !jwidget_has_mouse(combobox->button) && */
/* combobox->window && !jwidget_has_mouse(combobox->window)) { */
/* combobox_close_window(combo_widget); */
/* return TRUE; */
/* } */
/* } */
/* break; */
/* } */
2007-09-18 23:57:02 +00:00
case JM_CHAR:
2007-12-04 21:50:31 +00:00
if (jwidget_has_focus(widget)) {
2007-09-18 23:57:02 +00:00
if (msg->key.scancode == KEY_SPACE ||
msg->key.scancode == KEY_ENTER ||
msg->key.scancode == KEY_ENTER_PAD) {
2007-12-04 21:50:31 +00:00
combobox_close_window(combo_widget);
2007-09-18 23:57:02 +00:00
return TRUE;
}
}
break;
}
return FALSE;
}
static void combobox_button_cmd(JWidget widget, void *data)
2007-09-18 23:57:02 +00:00
{
2007-12-04 21:50:31 +00:00
combobox_switch_window((JWidget)data);
2007-09-18 23:57:02 +00:00
}
static void combobox_open_window(JWidget widget)
2007-09-18 23:57:02 +00:00
{
2007-12-04 21:50:31 +00:00
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
2007-09-18 23:57:02 +00:00
if (!combobox->window) {
JWidget view, listbox;
JLink link;
int size;
JRect rc;
2007-12-04 21:50:31 +00:00
combobox->window = jwindow_new(NULL);
view = jview_new();
listbox = jlistbox_new();
2007-09-18 23:57:02 +00:00
listbox->user_data[0] = widget;
2007-12-04 21:50:31 +00:00
jwidget_add_hook(listbox, JI_WIDGET, combobox_listbox_msg_proc, NULL);
2007-09-18 23:57:02 +00:00
JI_LIST_FOR_EACH(combobox->items, link)
2007-12-04 21:50:31 +00:00
jwidget_add_child(listbox, jlistitem_new(link->data));
2007-09-18 23:57:02 +00:00
2007-12-04 21:50:31 +00:00
jwindow_ontop(combobox->window, TRUE);
jwidget_noborders(combobox->window);
2007-09-18 23:57:02 +00:00
2007-12-04 21:50:31 +00:00
size = jlist_length(combobox->items);
jwidget_set_min_size
2007-09-18 23:57:02 +00:00
(view,
jrect_w(combobox->entry->rc),
2007-12-04 21:50:31 +00:00
2+(2+jwidget_get_text_height(listbox))*MID(1, size, 10)+2);
2007-09-18 23:57:02 +00:00
2007-12-04 21:50:31 +00:00
jwidget_add_child(combobox->window, view);
jview_attach(view, listbox);
2007-09-18 23:57:02 +00:00
2007-12-04 21:50:31 +00:00
jwidget_signal_off(listbox);
jlistbox_select_index(listbox, combobox->selected);
jwidget_signal_on(listbox);
2007-09-18 23:57:02 +00:00
2007-12-04 21:50:31 +00:00
jwindow_remap(combobox->window);
2007-09-18 23:57:02 +00:00
rc = combobox_get_windowpos(combobox);
jwindow_position(combobox->window, rc->x1, rc->y1);
jrect_free(rc);
2007-12-04 21:50:31 +00:00
jwindow_open_bg(combobox->window);
jmanager_set_focus(listbox);
2007-09-18 23:57:02 +00:00
}
}
static void combobox_close_window(JWidget widget)
2007-09-18 23:57:02 +00:00
{
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
2007-09-18 23:57:02 +00:00
if (combobox->window) {
2007-12-04 21:50:31 +00:00
jwindow_close(combobox->window, widget);
2007-09-18 23:57:02 +00:00
combobox->window = NULL;
jmanager_set_focus(combobox->entry);
2007-09-18 23:57:02 +00:00
}
}
static void combobox_switch_window(JWidget widget)
2007-09-18 23:57:02 +00:00
{
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
2007-09-18 23:57:02 +00:00
if (!combobox->window)
combobox_open_window(widget);
2007-09-18 23:57:02 +00:00
else
combobox_close_window(widget);
2007-09-18 23:57:02 +00:00
}
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));
2007-09-18 23:57:02 +00:00
if (rc->y2 > JI_SCREEN_H)
jrect_displace(rc, 0, -(jrect_h(rc)+jrect_h(combobox->entry->rc)));
2007-09-18 23:57:02 +00:00
return rc;
}