2007-11-28 14:19:36 +00:00
|
|
|
/* ASE - Allegro Sprite Editor
|
2009-01-24 00:41:01 +00:00
|
|
|
* Copyright (C) 2001-2009 David Capello
|
2007-11-28 14:19:36 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <allegro.h>
|
2008-03-22 18:43:56 +00:00
|
|
|
#include <assert.h>
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2007-12-05 01:30:50 +00:00
|
|
|
#include "jinete/jinete.h"
|
|
|
|
#include "jinete/jintern.h"
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
#include "modules/gfx.h"
|
|
|
|
#include "modules/gui.h"
|
|
|
|
#include "widgets/tabs.h"
|
|
|
|
|
|
|
|
#define CALC_TAB_WIDTH(widget, tab) \
|
2009-05-30 21:22:52 +00:00
|
|
|
(4 + text_length(widget->font(), tab->text) + 4)
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
#define ARROW_W 12
|
|
|
|
|
|
|
|
#define HAS_ARROWS ((jwidget_get_parent(tabs->button_left) == widget))
|
|
|
|
|
|
|
|
typedef struct Tab
|
|
|
|
{
|
|
|
|
char *text;
|
|
|
|
void *data;
|
|
|
|
int width;
|
|
|
|
} Tab;
|
|
|
|
|
|
|
|
typedef struct Tabs
|
|
|
|
{
|
|
|
|
JList list_of_tabs;
|
|
|
|
Tab *hot;
|
|
|
|
Tab *selected;
|
2008-10-16 02:19:00 +00:00
|
|
|
void (*select_callback)(JWidget tabs, void *data, int button);
|
2008-01-03 23:22:04 +00:00
|
|
|
int timer_id;
|
2007-11-28 14:19:36 +00:00
|
|
|
int scroll_x;
|
|
|
|
/* int hot_arrow; */
|
|
|
|
JWidget button_left;
|
|
|
|
JWidget button_right;
|
|
|
|
} Tabs;
|
|
|
|
|
2008-10-01 01:27:51 +00:00
|
|
|
static int tabs_type();
|
2007-11-28 14:19:36 +00:00
|
|
|
static bool tabs_msg_proc(JWidget widget, JMessage msg);
|
|
|
|
static bool tabs_button_msg_proc(JWidget widget, JMessage msg);
|
|
|
|
|
|
|
|
static Tab *get_tab_by_data(JWidget widget, void *data);
|
|
|
|
static int get_max_scroll_x(JWidget widget);
|
|
|
|
static void make_tab_visible(JWidget widget, Tab *tab);
|
|
|
|
static void set_scroll_x(JWidget widget, int scroll_x);
|
|
|
|
static void calculate_hot(JWidget widget);
|
|
|
|
static void draw_bevel_box(JRect box, int c1, int c2, int bottom);
|
|
|
|
|
|
|
|
static Tab *tab_new(const char *text, void *data);
|
|
|
|
static void tab_free(Tab *tab);
|
|
|
|
|
|
|
|
/**************************************************************/
|
|
|
|
/* Tabs */
|
|
|
|
/**************************************************************/
|
|
|
|
|
2008-10-16 02:19:00 +00:00
|
|
|
JWidget tabs_new(void (*select_callback)(JWidget tabs, void *data, int button))
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
|
|
|
JWidget widget = jwidget_new(tabs_type());
|
|
|
|
Tabs *tabs = jnew0(Tabs, 1);
|
|
|
|
|
|
|
|
tabs->list_of_tabs = jlist_new();
|
|
|
|
tabs->hot = NULL;
|
|
|
|
tabs->selected = NULL;
|
|
|
|
tabs->select_callback = select_callback;
|
2008-01-03 23:22:04 +00:00
|
|
|
tabs->timer_id = jmanager_add_timer(widget, 1000/60);
|
2007-11-28 14:19:36 +00:00
|
|
|
tabs->scroll_x = 0;
|
|
|
|
/* tabs->hot_arrow = 0; */
|
|
|
|
|
|
|
|
tabs->button_left = jbutton_new(NULL);
|
|
|
|
tabs->button_right = jbutton_new(NULL);
|
|
|
|
|
|
|
|
jbutton_set_bevel(tabs->button_left, 0, 0, 0, 0);
|
|
|
|
jbutton_set_bevel(tabs->button_right, 0, 0, 0, 0);
|
|
|
|
|
|
|
|
jwidget_focusrest(tabs->button_left, FALSE);
|
|
|
|
jwidget_focusrest(tabs->button_right, FALSE);
|
|
|
|
|
|
|
|
add_gfxicon_to_button(tabs->button_left, GFX_ARROW_LEFT, JI_CENTER | JI_MIDDLE);
|
|
|
|
add_gfxicon_to_button(tabs->button_right, GFX_ARROW_RIGHT, JI_CENTER | JI_MIDDLE);
|
|
|
|
|
|
|
|
jwidget_add_hook(widget, tabs_type(), tabs_msg_proc, tabs);
|
|
|
|
jwidget_add_hook(tabs->button_left, tabs_type(), tabs_button_msg_proc, (void *)-1);
|
|
|
|
jwidget_add_hook(tabs->button_right, tabs_type(), tabs_button_msg_proc, (void *)+1);
|
|
|
|
|
2008-03-22 18:43:56 +00:00
|
|
|
jwidget_init_theme(widget);
|
2008-02-29 19:29:49 +00:00
|
|
|
|
2007-11-28 14:19:36 +00:00
|
|
|
return widget;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tabs_append_tab(JWidget widget, const char *text, void *data)
|
|
|
|
{
|
2008-09-30 21:01:54 +00:00
|
|
|
Tabs* tabs = reinterpret_cast<Tabs*>(jwidget_get_data(widget, tabs_type()));
|
2007-11-28 14:19:36 +00:00
|
|
|
Tab *tab = tab_new(text, data);
|
|
|
|
tab->width = CALC_TAB_WIDTH(widget, tab);
|
|
|
|
|
|
|
|
jlist_append(tabs->list_of_tabs, tab);
|
|
|
|
|
|
|
|
/* update scroll (in the same position if we can */
|
|
|
|
set_scroll_x(widget, tabs->scroll_x);
|
|
|
|
|
|
|
|
jwidget_dirty(widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tabs_remove_tab(JWidget widget, void *data)
|
|
|
|
{
|
2008-09-30 21:01:54 +00:00
|
|
|
Tabs* tabs = reinterpret_cast<Tabs*>(jwidget_get_data(widget, tabs_type()));
|
2007-11-28 14:19:36 +00:00
|
|
|
Tab *tab = get_tab_by_data(widget, data);
|
|
|
|
|
|
|
|
if (tab) {
|
|
|
|
jlist_remove(tabs->list_of_tabs, tab);
|
|
|
|
tab_free(tab);
|
|
|
|
|
|
|
|
/* update scroll (in the same position if we can */
|
|
|
|
set_scroll_x(widget, tabs->scroll_x);
|
|
|
|
|
|
|
|
jwidget_dirty(widget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tabs_set_text_for_tab(JWidget widget, const char *text, void *data)
|
|
|
|
{
|
2008-09-30 21:01:54 +00:00
|
|
|
Tabs* tabs = reinterpret_cast<Tabs*>(jwidget_get_data(widget, tabs_type()));
|
2007-11-28 14:19:36 +00:00
|
|
|
Tab *tab = get_tab_by_data(widget, data);
|
|
|
|
|
|
|
|
if (tab) {
|
|
|
|
/* free old text */
|
|
|
|
if (tab->text)
|
|
|
|
jfree(tab->text);
|
|
|
|
|
|
|
|
/* change text of the tab */
|
|
|
|
tab->text = jstrdup(text);
|
|
|
|
tab->width = CALC_TAB_WIDTH(widget, tab);
|
|
|
|
|
|
|
|
/* make it visible (if it's the selected) */
|
|
|
|
if (tabs->selected == tab)
|
|
|
|
make_tab_visible(widget, tab);
|
|
|
|
|
|
|
|
jwidget_dirty(widget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tabs_select_tab(JWidget widget, void *data)
|
|
|
|
{
|
2008-09-30 21:01:54 +00:00
|
|
|
Tabs* tabs = reinterpret_cast<Tabs*>(jwidget_get_data(widget, tabs_type()));
|
2007-11-28 14:19:36 +00:00
|
|
|
Tab *tab = get_tab_by_data(widget, data);
|
|
|
|
|
2008-02-29 19:29:49 +00:00
|
|
|
if (tab != NULL) {
|
2007-11-28 14:19:36 +00:00
|
|
|
tabs->selected = tab;
|
|
|
|
make_tab_visible(widget, tab);
|
|
|
|
jwidget_dirty(widget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-30 21:01:54 +00:00
|
|
|
void* tabs_get_selected_tab(JWidget widget)
|
2008-02-29 19:29:49 +00:00
|
|
|
{
|
2008-09-30 21:01:54 +00:00
|
|
|
Tabs* tabs = reinterpret_cast<Tabs*>(jwidget_get_data(widget, tabs_type()));
|
2008-02-29 19:29:49 +00:00
|
|
|
|
|
|
|
if (tabs->selected != NULL)
|
|
|
|
return tabs->selected->data;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-10-01 01:27:51 +00:00
|
|
|
static int tabs_type()
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
|
|
|
static int type = 0;
|
|
|
|
if (!type)
|
|
|
|
type = ji_register_widget_type();
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool tabs_msg_proc(JWidget widget, JMessage msg)
|
|
|
|
{
|
2008-09-30 21:01:54 +00:00
|
|
|
Tabs* tabs = reinterpret_cast<Tabs*>(jwidget_get_data(widget, tabs_type()));
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
switch (msg->type) {
|
|
|
|
|
|
|
|
case JM_DESTROY: {
|
|
|
|
JLink link;
|
|
|
|
|
|
|
|
JI_LIST_FOR_EACH(tabs->list_of_tabs, link)
|
2008-09-30 21:01:54 +00:00
|
|
|
tab_free(reinterpret_cast<Tab*>(link->data));
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
jwidget_free(tabs->button_left);
|
|
|
|
jwidget_free(tabs->button_right);
|
|
|
|
|
|
|
|
jlist_free(tabs->list_of_tabs);
|
2008-01-03 23:22:04 +00:00
|
|
|
|
|
|
|
jmanager_remove_timer(tabs->timer_id);
|
2007-11-28 14:19:36 +00:00
|
|
|
jfree(tabs);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case JM_REQSIZE:
|
|
|
|
msg->reqsize.w =
|
|
|
|
msg->reqsize.h = 4 + jwidget_get_text_height(widget) + 5;
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case JM_SETPOS:
|
|
|
|
jrect_copy(widget->rc, &msg->setpos.rect);
|
|
|
|
set_scroll_x(widget, tabs->scroll_x);
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case JM_DRAW: {
|
|
|
|
JRect rect = jwidget_get_rect(widget);
|
|
|
|
JRect box = jrect_new(rect->x1-tabs->scroll_x, rect->y1, 0, rect->y2-1);
|
|
|
|
JLink link;
|
|
|
|
|
|
|
|
/* for each tab */
|
|
|
|
JI_LIST_FOR_EACH(tabs->list_of_tabs, link) {
|
2008-09-30 21:01:54 +00:00
|
|
|
Tab* tab = reinterpret_cast<Tab*>(link->data);
|
2007-11-28 14:19:36 +00:00
|
|
|
int fg, face, bottom;
|
|
|
|
|
|
|
|
box->x2 = box->x1 + tab->width;
|
|
|
|
|
|
|
|
/* is the tab inside the bounds of the widget? */
|
|
|
|
if (box->x1 < rect->x2 && box->x2 > rect->x1) {
|
|
|
|
/* selected */
|
|
|
|
if (tabs->selected == tab) {
|
|
|
|
fg = ji_color_background();
|
|
|
|
face = ji_color_selected();
|
|
|
|
bottom = face;
|
|
|
|
}
|
|
|
|
/* non-selected */
|
|
|
|
else {
|
|
|
|
fg = ji_color_foreground();
|
|
|
|
face = tabs->hot == tab ? ji_color_hotface():
|
|
|
|
ji_color_face();
|
|
|
|
bottom = ji_color_facelight();
|
|
|
|
}
|
|
|
|
|
2009-05-30 21:22:52 +00:00
|
|
|
hline(ji_screen, box->x1, box->y1, box->x2-1, widget->bg_color());
|
2007-11-28 14:19:36 +00:00
|
|
|
rectfill(ji_screen, box->x1+1, box->y1+1, box->x2-2, box->y2-1, face);
|
|
|
|
hline(ji_screen, box->x1, rect->y2-1, box->x2-1, ji_color_selected());
|
|
|
|
|
|
|
|
draw_bevel_box(box,
|
|
|
|
ji_color_facelight(),
|
|
|
|
ji_color_faceshadow(),
|
|
|
|
bottom);
|
|
|
|
|
2009-05-30 21:22:52 +00:00
|
|
|
jdraw_text(widget->font(), tab->text,
|
2007-11-28 14:19:36 +00:00
|
|
|
box->x1+4,
|
2009-05-30 21:22:52 +00:00
|
|
|
(box->y1+box->y2)/2-text_height(widget->font())/2,
|
2007-11-28 14:19:36 +00:00
|
|
|
fg, face, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
box->x1 = box->x2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fill the gap to the right-side */
|
|
|
|
if (box->x1 < rect->x2) {
|
|
|
|
rectfill(ji_screen, box->x1, rect->y1, rect->x2-1, rect->y2-3,
|
2009-05-30 21:22:52 +00:00
|
|
|
widget->bg_color());
|
2007-11-28 14:19:36 +00:00
|
|
|
hline(ji_screen, box->x1, rect->y2-2, rect->x2-1, ji_color_facelight());
|
|
|
|
hline(ji_screen, box->x1, rect->y2-1, rect->x2-1, ji_color_selected());
|
|
|
|
}
|
|
|
|
|
|
|
|
/* draw bottom lines below the arrow-buttons */
|
|
|
|
if (HAS_ARROWS) {
|
|
|
|
hline(ji_screen, box->x1, rect->y2-2, rect->x2-1, ji_color_facelight());
|
|
|
|
hline(ji_screen, box->x1, rect->y2-1, rect->x2-1, ji_color_selected());
|
|
|
|
}
|
|
|
|
|
|
|
|
jrect_free(rect);
|
|
|
|
jrect_free(box);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
case JM_MOUSEENTER:
|
|
|
|
case JM_MOTION:
|
|
|
|
calculate_hot(widget);
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case JM_MOUSELEAVE:
|
|
|
|
if (tabs->hot != NULL) {
|
|
|
|
tabs->hot = NULL;
|
|
|
|
jwidget_dirty(widget);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case JM_BUTTONPRESSED:
|
2008-01-03 23:22:04 +00:00
|
|
|
if (tabs->selected != tabs->hot && tabs->hot != NULL) {
|
2007-11-28 14:19:36 +00:00
|
|
|
tabs->selected = tabs->hot;
|
|
|
|
jwidget_dirty(widget);
|
|
|
|
}
|
2008-10-16 02:19:00 +00:00
|
|
|
|
|
|
|
if (tabs->selected && tabs->select_callback)
|
|
|
|
(*tabs->select_callback)(widget,
|
|
|
|
tabs->selected->data,
|
|
|
|
msg->mouse.flags);
|
2007-11-28 14:19:36 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case JM_WHEEL: {
|
|
|
|
int dx = (jmouse_z(1) - jmouse_z(0)) * jrect_w(widget->rc)/6;
|
|
|
|
set_scroll_x(widget, tabs->scroll_x+dx);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-01-03 23:22:04 +00:00
|
|
|
case JM_TIMER: {
|
|
|
|
int dir = jmanager_get_capture() == tabs->button_left ? -1: 1;
|
2008-02-04 02:37:26 +00:00
|
|
|
set_scroll_x(widget, tabs->scroll_x + dir*8*msg->timer.count);
|
2008-01-03 23:22:04 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-02-29 19:29:49 +00:00
|
|
|
case JM_SIGNAL:
|
|
|
|
if (msg->signal.num == JI_SIGNAL_SET_FONT) {
|
|
|
|
JLink link;
|
|
|
|
|
|
|
|
JI_LIST_FOR_EACH(tabs->list_of_tabs, link) {
|
2008-09-30 21:01:54 +00:00
|
|
|
Tab* tab = reinterpret_cast<Tab*>(link->data);
|
2008-02-29 19:29:49 +00:00
|
|
|
tab->width = CALC_TAB_WIDTH(widget, tab);
|
|
|
|
}
|
|
|
|
}
|
2008-03-22 18:43:56 +00:00
|
|
|
else if (msg->signal.num == JI_SIGNAL_INIT_THEME) {
|
|
|
|
/* setup the background color */
|
|
|
|
jwidget_set_bg_color(widget, ji_color_face());
|
|
|
|
}
|
2008-02-29 19:29:49 +00:00
|
|
|
break;
|
|
|
|
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool tabs_button_msg_proc(JWidget widget, JMessage msg)
|
|
|
|
{
|
2008-01-03 23:22:04 +00:00
|
|
|
JWidget parent;
|
2008-03-22 18:43:56 +00:00
|
|
|
Tabs *tabs = NULL;
|
2008-01-03 23:22:04 +00:00
|
|
|
|
|
|
|
parent = jwidget_get_parent(widget);
|
|
|
|
if (parent)
|
2008-09-30 21:01:54 +00:00
|
|
|
tabs = reinterpret_cast<Tabs*>(jwidget_get_data(parent, tabs_type()));
|
2008-01-03 23:22:04 +00:00
|
|
|
|
2007-11-28 14:19:36 +00:00
|
|
|
switch (msg->type) {
|
|
|
|
|
|
|
|
case JM_SIGNAL:
|
2008-01-03 23:22:04 +00:00
|
|
|
if (msg->signal.num == JI_SIGNAL_BUTTON_SELECT) {
|
2007-11-28 14:19:36 +00:00
|
|
|
return TRUE;
|
2008-01-03 23:22:04 +00:00
|
|
|
}
|
2007-11-28 14:19:36 +00:00
|
|
|
else if (msg->signal.num == JI_SIGNAL_DISABLE) {
|
2008-03-22 18:43:56 +00:00
|
|
|
assert(tabs != NULL);
|
|
|
|
|
2008-01-03 23:22:04 +00:00
|
|
|
if (jwidget_is_selected(widget)) {
|
|
|
|
jmanager_stop_timer(tabs->timer_id);
|
2007-11-28 14:19:36 +00:00
|
|
|
jwidget_deselect(widget);
|
2008-01-03 23:22:04 +00:00
|
|
|
}
|
2007-11-28 14:19:36 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-01-03 23:22:04 +00:00
|
|
|
case JM_BUTTONPRESSED:
|
2008-03-22 18:43:56 +00:00
|
|
|
assert(tabs != NULL);
|
2008-01-03 23:22:04 +00:00
|
|
|
jmanager_start_timer(tabs->timer_id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JM_BUTTONRELEASED:
|
2008-03-22 18:43:56 +00:00
|
|
|
assert(tabs != NULL);
|
2008-01-03 23:22:04 +00:00
|
|
|
jmanager_stop_timer(tabs->timer_id);
|
2007-11-28 14:19:36 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Tab *get_tab_by_data(JWidget widget, void *data)
|
|
|
|
{
|
2008-09-30 21:01:54 +00:00
|
|
|
Tabs* tabs = reinterpret_cast<Tabs*>(jwidget_get_data(widget, tabs_type()));
|
2007-11-28 14:19:36 +00:00
|
|
|
JLink link;
|
|
|
|
|
|
|
|
JI_LIST_FOR_EACH(tabs->list_of_tabs, link) {
|
2008-09-30 21:01:54 +00:00
|
|
|
Tab* tab = reinterpret_cast<Tab*>(link->data);
|
2007-11-28 14:19:36 +00:00
|
|
|
if (tab->data == data)
|
|
|
|
return tab;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int get_max_scroll_x(JWidget widget)
|
|
|
|
{
|
2008-09-30 21:01:54 +00:00
|
|
|
Tabs* tabs = reinterpret_cast<Tabs*>(jwidget_get_data(widget, tabs_type()));
|
2007-11-28 14:19:36 +00:00
|
|
|
JLink link;
|
|
|
|
int x = 0;
|
|
|
|
|
|
|
|
JI_LIST_FOR_EACH(tabs->list_of_tabs, link) {
|
2008-09-30 21:01:54 +00:00
|
|
|
Tab* tab = reinterpret_cast<Tab*>(link->data);
|
2007-11-28 14:19:36 +00:00
|
|
|
x += tab->width;
|
|
|
|
}
|
|
|
|
|
|
|
|
x -= jrect_w(widget->rc);
|
|
|
|
|
|
|
|
if (x < 0)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return x + ARROW_W*2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void make_tab_visible(JWidget widget, Tab *make_visible_this_tab)
|
|
|
|
{
|
2008-09-30 21:01:54 +00:00
|
|
|
Tabs* tabs = reinterpret_cast<Tabs*>(jwidget_get_data(widget, tabs_type()));
|
2007-11-28 14:19:36 +00:00
|
|
|
JLink link;
|
|
|
|
int x = 0;
|
|
|
|
int extra_x = get_max_scroll_x(widget) > 0 ? ARROW_W*2: 0;
|
|
|
|
|
|
|
|
JI_LIST_FOR_EACH(tabs->list_of_tabs, link) {
|
2008-09-30 21:01:54 +00:00
|
|
|
Tab* tab = reinterpret_cast<Tab*>(link->data);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
if (tab == make_visible_this_tab) {
|
|
|
|
if (x - tabs->scroll_x < 0) {
|
|
|
|
set_scroll_x(widget, x);
|
|
|
|
}
|
|
|
|
else if (x + tab->width - tabs->scroll_x > jrect_w(widget->rc) - extra_x) {
|
|
|
|
set_scroll_x(widget, x + tab->width - jrect_w(widget->rc) + extra_x);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
x += tab->width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void set_scroll_x(JWidget widget, int scroll_x)
|
|
|
|
{
|
2008-09-30 21:01:54 +00:00
|
|
|
Tabs* tabs = reinterpret_cast<Tabs*>(jwidget_get_data(widget, tabs_type()));
|
2007-11-28 14:19:36 +00:00
|
|
|
int max_x = get_max_scroll_x(widget);
|
|
|
|
|
|
|
|
scroll_x = MID(0, scroll_x, max_x);
|
|
|
|
if (tabs->scroll_x != scroll_x) {
|
|
|
|
tabs->scroll_x = scroll_x;
|
|
|
|
calculate_hot(widget);
|
|
|
|
jwidget_dirty(widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we need scroll buttons? */
|
|
|
|
if (max_x > 0) {
|
|
|
|
/* add childs */
|
|
|
|
if (!HAS_ARROWS) {
|
|
|
|
jwidget_add_child(widget, tabs->button_left);
|
|
|
|
jwidget_add_child(widget, tabs->button_right);
|
|
|
|
jwidget_dirty(widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* disable/enable buttons */
|
|
|
|
if (tabs->scroll_x > 0)
|
|
|
|
jwidget_enable(tabs->button_left);
|
|
|
|
else
|
|
|
|
jwidget_disable(tabs->button_left);
|
|
|
|
|
|
|
|
if (tabs->scroll_x < max_x)
|
|
|
|
jwidget_enable(tabs->button_right);
|
|
|
|
else
|
|
|
|
jwidget_disable(tabs->button_right);
|
|
|
|
|
|
|
|
/* setup the position of each button */
|
|
|
|
{
|
|
|
|
JRect rect = jwidget_get_rect(widget);
|
|
|
|
JRect box = jrect_new(rect->x2-ARROW_W*2, rect->y1,
|
|
|
|
rect->x2-ARROW_W, rect->y2-2);
|
|
|
|
jwidget_set_rect(tabs->button_left, box);
|
|
|
|
|
|
|
|
jrect_moveto(box, box->x1+ARROW_W, box->y1);
|
|
|
|
jwidget_set_rect(tabs->button_right, box);
|
|
|
|
|
|
|
|
jrect_free(box);
|
|
|
|
jrect_free(rect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* remove buttons */
|
|
|
|
else if (HAS_ARROWS) {
|
|
|
|
jwidget_remove_child(widget, tabs->button_left);
|
|
|
|
jwidget_remove_child(widget, tabs->button_right);
|
|
|
|
jwidget_dirty(widget);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void calculate_hot(JWidget widget)
|
|
|
|
{
|
2008-09-30 21:01:54 +00:00
|
|
|
Tabs* tabs = reinterpret_cast<Tabs*>(jwidget_get_data(widget, tabs_type()));
|
2007-11-28 14:19:36 +00:00
|
|
|
JRect rect = jwidget_get_rect(widget);
|
|
|
|
JRect box = jrect_new(rect->x1-tabs->scroll_x, rect->y1, 0, rect->y2-1);
|
|
|
|
JLink link;
|
|
|
|
Tab *hot = NULL;
|
|
|
|
|
|
|
|
/* for each tab */
|
|
|
|
JI_LIST_FOR_EACH(tabs->list_of_tabs, link) {
|
2008-09-30 21:01:54 +00:00
|
|
|
Tab* tab = reinterpret_cast<Tab*>(link->data);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
box->x2 = box->x1 + tab->width;
|
|
|
|
|
|
|
|
if (jrect_point_in(box, jmouse_x(0), jmouse_y(0))) {
|
|
|
|
hot = tab;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
box->x1 = box->x2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tabs->hot != hot) {
|
|
|
|
tabs->hot = hot;
|
|
|
|
jwidget_dirty(widget);
|
|
|
|
}
|
2008-02-10 12:36:00 +00:00
|
|
|
|
|
|
|
jrect_free(rect);
|
|
|
|
jrect_free(box);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_bevel_box(JRect box, int c1, int c2, int bottom)
|
|
|
|
{
|
|
|
|
hline(ji_screen, box->x1+1, box->y1, box->x2-2, c1); /* top */
|
|
|
|
hline(ji_screen, box->x1, box->y2-1, box->x2-1, bottom); /* bottom */
|
|
|
|
vline(ji_screen, box->x1, box->y1+1, box->y2-2, c1); /* left */
|
|
|
|
vline(ji_screen, box->x2-1, box->y1+1, box->y2-2, c2); /* right */
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************/
|
|
|
|
/* Tab */
|
|
|
|
/**************************************************************/
|
|
|
|
|
|
|
|
static Tab *tab_new(const char *text, void *data)
|
|
|
|
{
|
|
|
|
Tab *tab = jnew0(Tab, 1);
|
|
|
|
if (!tab)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
tab->text = jstrdup(text);
|
|
|
|
tab->data = data;
|
|
|
|
tab->width = 0;
|
|
|
|
|
|
|
|
return tab;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tab_free(Tab *tab)
|
|
|
|
{
|
|
|
|
if (tab->text)
|
|
|
|
jfree(tab->text);
|
|
|
|
jfree(tab);
|
|
|
|
}
|