2007-11-28 14:19:36 +00:00
|
|
|
/* ASE - Allegro Sprite Editor
|
2011-01-18 23:49:53 +00:00
|
|
|
* Copyright (C) 2001-2011 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"
|
|
|
|
|
2010-07-20 03:59:52 +00:00
|
|
|
#include <algorithm>
|
2010-09-26 18:59:32 +00:00
|
|
|
#include <allegro.h>
|
2010-07-20 03:59:52 +00:00
|
|
|
#include <cmath>
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-09-26 18:59:32 +00:00
|
|
|
#include "gui/jinete.h"
|
|
|
|
#include "gui/jintern.h"
|
2007-11-28 14:19:36 +00:00
|
|
|
#include "modules/gfx.h"
|
|
|
|
#include "modules/gui.h"
|
2011-01-21 20:29:45 +00:00
|
|
|
#include "skin_theme.h"
|
2007-11-28 14:19:36 +00:00
|
|
|
#include "widgets/tabs.h"
|
|
|
|
|
2010-03-20 15:55:25 +00:00
|
|
|
#define ARROW_W (12*jguiscale())
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-07-20 03:59:52 +00:00
|
|
|
#define ANI_ADDING_TAB_TICKS 5
|
|
|
|
#define ANI_REMOVING_TAB_TICKS 10
|
|
|
|
#define ANI_SMOOTH_SCROLL_TICKS 20
|
|
|
|
|
2011-01-21 21:54:47 +00:00
|
|
|
#define HAS_ARROWS(tabs) ((m_button_left->getParent() == (tabs)))
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
static bool tabs_button_msg_proc(JWidget widget, JMessage msg);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
static int tabs_type()
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
2010-06-13 20:51:22 +00:00
|
|
|
static int type = 0;
|
|
|
|
if (!type)
|
|
|
|
type = ji_register_widget_type();
|
|
|
|
return type;
|
|
|
|
}
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
Tabs::Tabs(ITabsHandler* handler)
|
|
|
|
: Widget(tabs_type())
|
|
|
|
, m_handler(handler)
|
|
|
|
{
|
|
|
|
m_hot = NULL;
|
|
|
|
m_selected = NULL;
|
2010-07-20 03:59:52 +00:00
|
|
|
m_timerId = jmanager_add_timer(this, 1000/60);
|
|
|
|
m_scrollX = 0;
|
|
|
|
m_ani = ANI_NONE;
|
2010-07-26 19:52:40 +00:00
|
|
|
m_removedTab = NULL;
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-08-23 20:41:19 +00:00
|
|
|
m_button_left = new Button(NULL);
|
|
|
|
m_button_right = new Button(NULL);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
setup_mini_look(m_button_left);
|
|
|
|
setup_mini_look(m_button_right);
|
2010-08-23 20:41:19 +00:00
|
|
|
setup_bevels(m_button_left, 2, 0, 2, 0);
|
|
|
|
setup_bevels(m_button_right, 0, 2, 0, 2);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
jwidget_focusrest(m_button_left, false);
|
|
|
|
jwidget_focusrest(m_button_right, false);
|
|
|
|
|
|
|
|
add_gfxicon_to_button(m_button_left, GFX_ARROW_LEFT, JI_CENTER | JI_MIDDLE);
|
|
|
|
add_gfxicon_to_button(m_button_right, GFX_ARROW_RIGHT, JI_CENTER | JI_MIDDLE);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
jwidget_add_hook(m_button_left, tabs_type(), tabs_button_msg_proc, (void *)-1);
|
|
|
|
jwidget_add_hook(m_button_right, tabs_type(), tabs_button_msg_proc, (void *)+1);
|
2010-03-25 01:08:22 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
jwidget_init_theme(this);
|
|
|
|
}
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
Tabs::~Tabs()
|
|
|
|
{
|
2010-07-26 19:52:40 +00:00
|
|
|
if (m_removedTab) {
|
|
|
|
delete m_removedTab;
|
|
|
|
m_removedTab = NULL;
|
|
|
|
}
|
|
|
|
|
2010-07-20 03:59:52 +00:00
|
|
|
// Stop animation
|
|
|
|
stopAni();
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-07-20 03:59:52 +00:00
|
|
|
// Remove all tabs
|
|
|
|
std::vector<Tab*>::iterator it, end = m_list_of_tabs.end();
|
2010-06-13 20:51:22 +00:00
|
|
|
for (it = m_list_of_tabs.begin(); it != end; ++it)
|
|
|
|
delete *it; // tab
|
|
|
|
m_list_of_tabs.clear();
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
delete m_button_left; // widget
|
|
|
|
delete m_button_right; // widget
|
2008-02-29 19:29:49 +00:00
|
|
|
|
2010-07-20 03:59:52 +00:00
|
|
|
jmanager_remove_timer(m_timerId);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
void Tabs::addTab(const char* text, void* data)
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
2009-11-21 20:02:31 +00:00
|
|
|
Tab *tab = new Tab(text, data);
|
2010-07-20 02:56:12 +00:00
|
|
|
tab->width = calcTabWidth(tab);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
m_list_of_tabs.push_back(tab);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
// Update scroll (in the same position if we can
|
2010-07-20 03:59:52 +00:00
|
|
|
setScrollX(m_scrollX);
|
|
|
|
|
|
|
|
startAni(ANI_ADDING_TAB);
|
|
|
|
//jwidget_dirty(this);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
void Tabs::removeTab(void* data)
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
2010-06-13 20:51:22 +00:00
|
|
|
Tab *tab = getTabByData(data);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
if (tab) {
|
2010-06-13 20:51:22 +00:00
|
|
|
if (m_hot == tab) m_hot = NULL;
|
|
|
|
if (m_selected == tab) m_selected = NULL;
|
2009-11-22 14:14:06 +00:00
|
|
|
|
2010-07-20 03:59:52 +00:00
|
|
|
std::vector<Tab*>::iterator it =
|
|
|
|
std::find(m_list_of_tabs.begin(), m_list_of_tabs.end(), tab);
|
|
|
|
|
2010-08-04 02:33:44 +00:00
|
|
|
ASSERT(it != m_list_of_tabs.end() && "Removing a tab that is not part of the Tabs widget");
|
2010-07-20 03:59:52 +00:00
|
|
|
|
|
|
|
it = m_list_of_tabs.erase(it);
|
|
|
|
|
|
|
|
// Width of the removed tab
|
2010-07-26 19:52:40 +00:00
|
|
|
if (m_removedTab) {
|
|
|
|
delete m_removedTab;
|
|
|
|
m_removedTab = NULL;
|
|
|
|
}
|
|
|
|
m_removedTab = tab;
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-07-20 03:59:52 +00:00
|
|
|
// Next tab in the list
|
|
|
|
if (it != m_list_of_tabs.end())
|
|
|
|
m_nextTabOfTheRemovedOne = *it;
|
|
|
|
else
|
|
|
|
m_nextTabOfTheRemovedOne = NULL;
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-07-20 03:59:52 +00:00
|
|
|
// Update scroll (in the same position if we can)
|
|
|
|
setScrollX(m_scrollX);
|
|
|
|
|
|
|
|
startAni(ANI_REMOVING_TAB);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
void Tabs::setTabText(const char* text, void* data)
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
2010-06-13 20:51:22 +00:00
|
|
|
Tab *tab = getTabByData(data);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
if (tab) {
|
2010-06-13 20:51:22 +00:00
|
|
|
// Change text of the tab
|
2009-11-21 20:02:31 +00:00
|
|
|
tab->text = text;
|
2010-07-20 02:56:12 +00:00
|
|
|
tab->width = calcTabWidth(tab);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
// Make it visible (if it's the selected)
|
|
|
|
if (m_selected == tab)
|
|
|
|
makeTabVisible(tab);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
jwidget_dirty(this);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
void Tabs::selectTab(void* data)
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
2010-06-13 20:51:22 +00:00
|
|
|
Tab *tab = getTabByData(data);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2008-02-29 19:29:49 +00:00
|
|
|
if (tab != NULL) {
|
2010-06-13 20:51:22 +00:00
|
|
|
m_selected = tab;
|
|
|
|
makeTabVisible(tab);
|
|
|
|
jwidget_dirty(this);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
void* Tabs::getSelectedTab()
|
2008-02-29 19:29:49 +00:00
|
|
|
{
|
2010-06-13 20:51:22 +00:00
|
|
|
if (m_selected != NULL)
|
|
|
|
return m_selected->data;
|
2008-02-29 19:29:49 +00:00
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-08-03 00:29:56 +00:00
|
|
|
bool Tabs::onProcessMessage(JMessage msg)
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
2011-01-21 21:08:25 +00:00
|
|
|
SkinTheme* theme = static_cast<SkinTheme*>(this->getTheme());
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
switch (msg->type) {
|
|
|
|
|
|
|
|
case JM_REQSIZE:
|
2009-11-21 20:02:31 +00:00
|
|
|
msg->reqsize.w = 0; // msg->reqsize.h = 4 + jwidget_get_text_height(widget) + 5;
|
|
|
|
msg->reqsize.h =
|
|
|
|
theme->get_part(PART_TAB_FILLER)->h +
|
|
|
|
theme->get_part(PART_TAB_BOTTOM_NORMAL)->h;
|
2010-01-30 16:43:13 +00:00
|
|
|
return true;
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
case JM_SETPOS:
|
2010-06-13 20:51:22 +00:00
|
|
|
jrect_copy(this->rc, &msg->setpos.rect);
|
2010-07-20 03:59:52 +00:00
|
|
|
setScrollX(m_scrollX);
|
2010-01-30 16:43:13 +00:00
|
|
|
return true;
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
case JM_DRAW: {
|
2010-07-26 19:52:40 +00:00
|
|
|
BITMAP *doublebuffer = create_bitmap(jrect_w(&msg->draw.rect),
|
|
|
|
jrect_h(&msg->draw.rect));
|
2010-06-13 20:51:22 +00:00
|
|
|
JRect rect = jwidget_get_rect(this);
|
2010-07-26 19:52:40 +00:00
|
|
|
jrect_displace(rect, -msg->draw.rect.x1, -msg->draw.rect.y1);
|
|
|
|
|
|
|
|
JRect box = jrect_new(rect->x1-m_scrollX,
|
|
|
|
rect->y1,
|
2010-07-20 03:59:52 +00:00
|
|
|
rect->x1-m_scrollX+2*jguiscale(),
|
2010-03-20 15:55:25 +00:00
|
|
|
rect->y1+theme->get_part(PART_TAB_FILLER)->h);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-07-26 19:52:40 +00:00
|
|
|
clear_to_color(doublebuffer, theme->get_window_face_color());
|
|
|
|
|
|
|
|
theme->draw_part_as_hline(doublebuffer, box->x1, box->y1, box->x2-1, box->y2-1, PART_TAB_FILLER);
|
|
|
|
theme->draw_part_as_hline(doublebuffer, box->x1, box->y2, box->x2-1, rect->y2-1, PART_TAB_BOTTOM_NORMAL);
|
2009-11-21 20:02:31 +00:00
|
|
|
|
|
|
|
box->x1 = box->x2;
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
// For each tab...
|
|
|
|
std::vector<Tab*>::iterator it, end = m_list_of_tabs.end();
|
|
|
|
|
|
|
|
for (it = m_list_of_tabs.begin(); it != end; ++it) {
|
|
|
|
Tab* tab = *it;
|
2010-07-26 19:52:40 +00:00
|
|
|
|
2007-11-28 14:19:36 +00:00
|
|
|
box->x2 = box->x1 + tab->width;
|
|
|
|
|
2010-07-20 03:59:52 +00:00
|
|
|
int x_delta = 0;
|
|
|
|
int y_delta = 0;
|
|
|
|
|
|
|
|
// Y-delta for animating tabs (intros and outros)
|
2010-07-26 19:52:40 +00:00
|
|
|
if (m_ani == ANI_ADDING_TAB && m_selected == tab) {
|
2010-07-20 03:59:52 +00:00
|
|
|
y_delta = (box->y2 - box->y1) * (ANI_ADDING_TAB_TICKS - m_ani_t) / ANI_ADDING_TAB_TICKS;
|
|
|
|
}
|
2010-07-26 19:52:40 +00:00
|
|
|
else if (m_ani == ANI_REMOVING_TAB && m_nextTabOfTheRemovedOne == tab) {
|
|
|
|
x_delta += m_removedTab->width - m_removedTab->width*(1.0-std::exp(-10.0 * m_ani_t / (double)ANI_REMOVING_TAB_TICKS));
|
|
|
|
x_delta = MID(0, x_delta, m_removedTab->width);
|
|
|
|
|
|
|
|
// Draw deleted tab
|
|
|
|
if (m_removedTab) {
|
|
|
|
JRect box2 = jrect_new(box->x1, box->y1, box->x1+x_delta, box->y2);
|
|
|
|
drawTab(doublebuffer, box2, m_removedTab, 0, false);
|
|
|
|
jrect_free(box2);
|
|
|
|
}
|
2010-07-20 03:59:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
box->x1 += x_delta;
|
|
|
|
box->x2 += x_delta;
|
2010-07-26 19:52:40 +00:00
|
|
|
|
|
|
|
drawTab(doublebuffer, box, tab, y_delta, (tab == m_selected));
|
2010-07-20 03:59:52 +00:00
|
|
|
|
2010-07-26 19:52:40 +00:00
|
|
|
box->x1 = box->x2;
|
|
|
|
}
|
2009-11-21 20:02:31 +00:00
|
|
|
|
2010-07-26 19:52:40 +00:00
|
|
|
if (m_ani == ANI_REMOVING_TAB && m_nextTabOfTheRemovedOne == NULL) {
|
|
|
|
// Draw deleted tab
|
|
|
|
if (m_removedTab) {
|
|
|
|
int x_delta = m_removedTab->width - m_removedTab->width*(1.0-std::exp(-10.0 * m_ani_t / (double)ANI_REMOVING_TAB_TICKS));
|
|
|
|
x_delta = MID(0, x_delta, m_removedTab->width);
|
2010-07-20 03:59:52 +00:00
|
|
|
|
2010-07-26 19:52:40 +00:00
|
|
|
JRect box2 = jrect_new(box->x1, box->y1, box->x1+x_delta, box->y2);
|
|
|
|
drawTab(doublebuffer, box2, m_removedTab, 0, false);
|
|
|
|
jrect_free(box2);
|
2010-07-20 02:56:12 +00:00
|
|
|
|
2010-07-26 19:52:40 +00:00
|
|
|
box->x1 += x_delta;
|
|
|
|
box->x2 = box->x1;
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fill the gap to the right-side */
|
|
|
|
if (box->x1 < rect->x2) {
|
2010-07-26 19:52:40 +00:00
|
|
|
theme->draw_part_as_hline(doublebuffer, box->x1, box->y1, rect->x2-1, box->y2-1, PART_TAB_FILLER);
|
|
|
|
theme->draw_part_as_hline(doublebuffer, box->x1, box->y2, rect->x2-1, rect->y2-1, PART_TAB_BOTTOM_NORMAL);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jrect_free(rect);
|
|
|
|
jrect_free(box);
|
2010-07-26 19:52:40 +00:00
|
|
|
|
|
|
|
blit(doublebuffer, ji_screen, 0, 0,
|
|
|
|
msg->draw.rect.x1,
|
|
|
|
msg->draw.rect.y1,
|
|
|
|
doublebuffer->w,
|
|
|
|
doublebuffer->h);
|
|
|
|
destroy_bitmap(doublebuffer);
|
2010-01-30 16:43:13 +00:00
|
|
|
return true;
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case JM_MOUSEENTER:
|
|
|
|
case JM_MOTION:
|
2010-06-13 20:51:22 +00:00
|
|
|
calculateHot();
|
2010-01-30 16:43:13 +00:00
|
|
|
return true;
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
case JM_MOUSELEAVE:
|
2010-06-13 20:51:22 +00:00
|
|
|
if (m_hot != NULL) {
|
|
|
|
m_hot = NULL;
|
|
|
|
jwidget_dirty(this);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
2010-01-30 16:43:13 +00:00
|
|
|
return true;
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
case JM_BUTTONPRESSED:
|
2010-06-13 20:51:22 +00:00
|
|
|
if (m_hot != NULL) {
|
|
|
|
if (m_selected != m_hot) {
|
|
|
|
m_selected = m_hot;
|
|
|
|
jwidget_dirty(this);
|
2009-11-22 14:14:06 +00:00
|
|
|
}
|
2008-10-16 02:19:00 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
if (m_selected && m_handler)
|
|
|
|
m_handler->clickTab(this,
|
|
|
|
m_selected->data,
|
|
|
|
msg->mouse.flags);
|
2009-11-22 14:14:06 +00:00
|
|
|
}
|
2010-01-30 16:43:13 +00:00
|
|
|
return true;
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
case JM_WHEEL: {
|
2010-06-13 20:51:22 +00:00
|
|
|
int dx = (jmouse_z(1) - jmouse_z(0)) * jrect_w(this->rc)/6;
|
2010-07-20 03:59:52 +00:00
|
|
|
// setScrollX(m_scrollX+dx);
|
|
|
|
|
|
|
|
m_begScrollX = m_scrollX;
|
|
|
|
if (m_ani != ANI_SMOOTH_SCROLL)
|
|
|
|
m_endScrollX = m_scrollX + dx;
|
|
|
|
else
|
|
|
|
m_endScrollX += dx;
|
|
|
|
|
|
|
|
// Limit endScrollX position (to improve animation ending to the correct position)
|
|
|
|
{
|
|
|
|
int max_x = getMaxScrollX();
|
|
|
|
m_endScrollX = MID(0, m_endScrollX, max_x);
|
|
|
|
}
|
|
|
|
|
|
|
|
startAni(ANI_SMOOTH_SCROLL);
|
2010-01-30 16:43:13 +00:00
|
|
|
return true;
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
|
2008-01-03 23:22:04 +00:00
|
|
|
case JM_TIMER: {
|
2010-07-20 03:59:52 +00:00
|
|
|
switch (m_ani) {
|
2010-08-12 02:42:03 +00:00
|
|
|
case ANI_NONE:
|
|
|
|
// Do nothing
|
|
|
|
break;
|
2010-07-20 03:59:52 +00:00
|
|
|
case ANI_SCROLL: {
|
|
|
|
int dir = jmanager_get_capture() == m_button_left ? -1: 1;
|
|
|
|
setScrollX(m_scrollX + dir*8*msg->timer.count);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ANI_SMOOTH_SCROLL: {
|
|
|
|
if (m_ani_t == ANI_SMOOTH_SCROLL_TICKS) {
|
|
|
|
stopAni();
|
|
|
|
setScrollX(m_endScrollX);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Lineal
|
|
|
|
//setScrollX(m_begScrollX + m_endScrollX - m_begScrollX) * m_ani_t / 10);
|
|
|
|
|
|
|
|
// Exponential
|
|
|
|
setScrollX(m_begScrollX +
|
|
|
|
(m_endScrollX - m_begScrollX) * (1.0-std::exp(-10.0 * m_ani_t / (double)ANI_SMOOTH_SCROLL_TICKS)));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ANI_ADDING_TAB: {
|
|
|
|
if (m_ani_t == ANI_ADDING_TAB_TICKS)
|
|
|
|
stopAni();
|
|
|
|
dirty();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ANI_REMOVING_TAB: {
|
|
|
|
if (m_ani_t == ANI_REMOVING_TAB_TICKS)
|
|
|
|
stopAni();
|
|
|
|
dirty();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++m_ani_t;
|
2008-01-03 23:22:04 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-02-29 19:29:49 +00:00
|
|
|
case JM_SIGNAL:
|
2010-07-31 16:08:13 +00:00
|
|
|
if (msg->signal.num == JI_SIGNAL_INIT_THEME) {
|
|
|
|
m_button_left->setBgColor(theme->get_tab_selected_face_color());
|
|
|
|
m_button_right->setBgColor(theme->get_tab_selected_face_color());
|
|
|
|
}
|
|
|
|
else if (msg->signal.num == JI_SIGNAL_SET_FONT) {
|
2010-06-13 20:51:22 +00:00
|
|
|
std::vector<Tab*>::iterator it, end = m_list_of_tabs.end();
|
2008-02-29 19:29:49 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
for (it = m_list_of_tabs.begin(); it != end; ++it) {
|
|
|
|
Tab* tab = *it;
|
2010-07-20 02:56:12 +00:00
|
|
|
tab->width = calcTabWidth(tab);
|
2008-02-29 19:29:49 +00:00
|
|
|
}
|
|
|
|
}
|
2008-03-22 18:43:56 +00:00
|
|
|
else if (msg->signal.num == JI_SIGNAL_INIT_THEME) {
|
|
|
|
/* setup the background color */
|
2010-06-13 20:51:22 +00:00
|
|
|
jwidget_set_bg_color(this, ji_color_face());
|
2008-03-22 18:43:56 +00:00
|
|
|
}
|
2008-02-29 19:29:49 +00:00
|
|
|
break;
|
|
|
|
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
|
2010-08-03 00:29:56 +00:00
|
|
|
return Widget::onProcessMessage(msg);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
|
2010-07-26 19:52:40 +00:00
|
|
|
void Tabs::drawTab(BITMAP* bmp, JRect box, Tab* tab, int y_delta, bool selected)
|
|
|
|
{
|
|
|
|
// Is the tab outside the bounds of the widget?
|
|
|
|
if (box->x1 >= this->rc->x2 || box->x2 <= this->rc->x1)
|
|
|
|
return;
|
|
|
|
|
2011-01-21 21:08:25 +00:00
|
|
|
SkinTheme* theme = static_cast<SkinTheme*>(this->getTheme());
|
2010-07-26 19:52:40 +00:00
|
|
|
int text_color;
|
|
|
|
int face_color;
|
|
|
|
|
|
|
|
// Selected
|
|
|
|
if (selected) {
|
|
|
|
text_color = theme->get_tab_selected_text_color();
|
|
|
|
face_color = theme->get_tab_selected_face_color();
|
|
|
|
}
|
|
|
|
// Non-selected
|
|
|
|
else {
|
|
|
|
text_color = theme->get_tab_normal_text_color();
|
|
|
|
face_color = theme->get_tab_normal_face_color();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (jrect_w(box) > 2) {
|
|
|
|
theme->draw_bounds_nw(bmp,
|
|
|
|
box->x1, box->y1+y_delta, box->x2-1, box->y2-1,
|
|
|
|
(selected) ? PART_TAB_SELECTED_NW:
|
|
|
|
PART_TAB_NORMAL_NW, face_color);
|
|
|
|
jdraw_text(bmp, this->getFont(), tab->text.c_str(),
|
|
|
|
box->x1+4*jguiscale(),
|
|
|
|
(box->y1+box->y2)/2-text_height(this->getFont())/2+1 + y_delta,
|
|
|
|
text_color, face_color, false, jguiscale());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selected) {
|
|
|
|
theme->draw_bounds_nw(bmp,
|
|
|
|
box->x1, box->y2, box->x2-1, this->rc->y2-1,
|
|
|
|
PART_TAB_BOTTOM_SELECTED_NW,
|
|
|
|
theme->get_tab_selected_face_color());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
theme->draw_part_as_hline(bmp,
|
|
|
|
box->x1, box->y2, box->x2-1, this->rc->y2-1,
|
|
|
|
PART_TAB_BOTTOM_NORMAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CLOSE_BUTTON_IN_EACH_TAB
|
|
|
|
BITMAP* close_icon = theme->get_part(PART_WINDOW_CLOSE_BUTTON_NORMAL);
|
|
|
|
set_alpha_blender();
|
|
|
|
draw_trans_sprite(doublebuffer, close_icon,
|
|
|
|
box->x2-4*jguiscale()-close_icon->w,
|
|
|
|
(box->y1+box->y2)/2-close_icon->h/2+1*jguiscale());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
Tabs::Tab* Tabs::getTabByData(void* data)
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
2010-06-13 20:51:22 +00:00
|
|
|
std::vector<Tab*>::iterator it, end = m_list_of_tabs.end();
|
2008-03-22 18:43:56 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
for (it = m_list_of_tabs.begin(); it != end; ++it) {
|
|
|
|
Tab* tab = *it;
|
2007-11-28 14:19:36 +00:00
|
|
|
if (tab->data == data)
|
|
|
|
return tab;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
int Tabs::getMaxScrollX()
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
2010-06-13 20:51:22 +00:00
|
|
|
std::vector<Tab*>::iterator it, end = m_list_of_tabs.end();
|
2007-11-28 14:19:36 +00:00
|
|
|
int x = 0;
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
for (it = m_list_of_tabs.begin(); it != end; ++it) {
|
|
|
|
Tab* tab = *it;
|
2007-11-28 14:19:36 +00:00
|
|
|
x += tab->width;
|
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
x -= jrect_w(this->rc);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
if (x < 0)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return x + ARROW_W*2;
|
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
void Tabs::makeTabVisible(Tab* make_visible_this_tab)
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
|
|
|
int x = 0;
|
2010-06-13 20:51:22 +00:00
|
|
|
int extra_x = getMaxScrollX() > 0 ? ARROW_W*2: 0;
|
|
|
|
std::vector<Tab*>::iterator it, end = m_list_of_tabs.end();
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
for (it = m_list_of_tabs.begin(); it != end; ++it) {
|
|
|
|
Tab* tab = *it;
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
if (tab == make_visible_this_tab) {
|
2010-07-20 03:59:52 +00:00
|
|
|
if (x - m_scrollX < 0) {
|
2010-06-13 20:51:22 +00:00
|
|
|
setScrollX(x);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
2010-07-20 03:59:52 +00:00
|
|
|
else if (x + tab->width - m_scrollX > jrect_w(this->rc) - extra_x) {
|
2010-06-13 20:51:22 +00:00
|
|
|
setScrollX(x + tab->width - jrect_w(this->rc) + extra_x);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
x += tab->width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
void Tabs::setScrollX(int scroll_x)
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
2010-06-13 20:51:22 +00:00
|
|
|
int max_x = getMaxScrollX();
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
scroll_x = MID(0, scroll_x, max_x);
|
2010-07-20 03:59:52 +00:00
|
|
|
if (m_scrollX != scroll_x) {
|
|
|
|
m_scrollX = scroll_x;
|
2010-06-13 20:51:22 +00:00
|
|
|
calculateHot();
|
|
|
|
jwidget_dirty(this);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
// We need scroll buttons?
|
2007-11-28 14:19:36 +00:00
|
|
|
if (max_x > 0) {
|
2010-06-13 20:51:22 +00:00
|
|
|
// Add childs
|
|
|
|
if (!HAS_ARROWS(this)) {
|
|
|
|
jwidget_add_child(this, m_button_left);
|
|
|
|
jwidget_add_child(this, m_button_right);
|
|
|
|
jwidget_dirty(this);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* disable/enable buttons */
|
2010-07-20 03:59:52 +00:00
|
|
|
m_button_left->setEnabled(m_scrollX > 0);
|
|
|
|
m_button_right->setEnabled(m_scrollX < max_x);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
/* setup the position of each button */
|
|
|
|
{
|
2010-06-13 20:51:22 +00:00
|
|
|
JRect rect = jwidget_get_rect(this);
|
2007-11-28 14:19:36 +00:00
|
|
|
JRect box = jrect_new(rect->x2-ARROW_W*2, rect->y1,
|
|
|
|
rect->x2-ARROW_W, rect->y2-2);
|
2010-06-13 20:51:22 +00:00
|
|
|
jwidget_set_rect(m_button_left, box);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
jrect_moveto(box, box->x1+ARROW_W, box->y1);
|
2010-06-13 20:51:22 +00:00
|
|
|
jwidget_set_rect(m_button_right, box);
|
2007-11-28 14:19:36 +00:00
|
|
|
|
|
|
|
jrect_free(box);
|
|
|
|
jrect_free(rect);
|
|
|
|
}
|
|
|
|
}
|
2010-06-13 20:51:22 +00:00
|
|
|
// Remove buttons
|
|
|
|
else if (HAS_ARROWS(this)) {
|
|
|
|
jwidget_remove_child(this, m_button_left);
|
|
|
|
jwidget_remove_child(this, m_button_right);
|
|
|
|
jwidget_dirty(this);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
void Tabs::calculateHot()
|
2007-11-28 14:19:36 +00:00
|
|
|
{
|
2010-06-13 20:51:22 +00:00
|
|
|
JRect rect = jwidget_get_rect(this);
|
2010-07-20 03:59:52 +00:00
|
|
|
JRect box = jrect_new(rect->x1-m_scrollX, rect->y1, 0, rect->y2-1);
|
2007-11-28 14:19:36 +00:00
|
|
|
Tab *hot = NULL;
|
2010-06-13 20:51:22 +00:00
|
|
|
std::vector<Tab*>::iterator it, end = m_list_of_tabs.end();
|
2007-11-28 14:19:36 +00:00
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
// For each tab
|
|
|
|
for (it = m_list_of_tabs.begin(); it != end; ++it) {
|
|
|
|
Tab* tab = *it;
|
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;
|
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
if (m_hot != hot) {
|
|
|
|
m_hot = hot;
|
|
|
|
|
|
|
|
if (m_handler)
|
|
|
|
m_handler->mouseOverTab(this, m_hot ? m_hot->data: NULL);
|
|
|
|
|
|
|
|
jwidget_dirty(this);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
2008-02-10 12:36:00 +00:00
|
|
|
|
|
|
|
jrect_free(rect);
|
|
|
|
jrect_free(box);
|
2007-11-28 14:19:36 +00:00
|
|
|
}
|
2010-06-13 20:51:22 +00:00
|
|
|
|
2010-07-20 02:56:12 +00:00
|
|
|
int Tabs::calcTabWidth(Tab* tab)
|
|
|
|
{
|
|
|
|
int border = 4*jguiscale();
|
|
|
|
#ifdef CLOSE_BUTTON_IN_EACH_TAB
|
2011-01-21 20:29:45 +00:00
|
|
|
SkinTheme* theme = static_cast<SkinTheme*>(this->theme);
|
2010-07-20 02:56:12 +00:00
|
|
|
int close_icon_w = theme->get_part(PART_WINDOW_CLOSE_BUTTON_NORMAL)->w;
|
|
|
|
return (border + text_length(getFont(), tab->text.c_str()) + border + close_icon_w + border);
|
|
|
|
#else
|
|
|
|
return (border + text_length(getFont(), tab->text.c_str()) + border);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-07-20 03:59:52 +00:00
|
|
|
void Tabs::startScrolling()
|
|
|
|
{
|
|
|
|
startAni(ANI_SCROLL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tabs::stopScrolling()
|
|
|
|
{
|
|
|
|
stopAni();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tabs::startAni(Ani ani)
|
|
|
|
{
|
|
|
|
// Stop previous animation
|
|
|
|
if (m_ani != ANI_NONE)
|
|
|
|
stopAni();
|
|
|
|
|
|
|
|
m_ani = ani;
|
|
|
|
m_ani_t = 0;
|
|
|
|
jmanager_start_timer(m_timerId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tabs::stopAni()
|
|
|
|
{
|
|
|
|
m_ani = ANI_NONE;
|
|
|
|
jmanager_stop_timer(m_timerId);
|
|
|
|
}
|
|
|
|
|
2010-06-13 20:51:22 +00:00
|
|
|
static bool tabs_button_msg_proc(JWidget widget, JMessage msg)
|
|
|
|
{
|
|
|
|
JWidget parent;
|
|
|
|
Tabs* tabs = NULL;
|
|
|
|
|
2011-01-21 21:54:47 +00:00
|
|
|
parent = widget->getParent();
|
2010-06-13 20:51:22 +00:00
|
|
|
if (parent)
|
|
|
|
tabs = dynamic_cast<Tabs*>(parent);
|
|
|
|
|
|
|
|
switch (msg->type) {
|
|
|
|
|
|
|
|
case JM_SIGNAL:
|
|
|
|
if (msg->signal.num == JI_SIGNAL_BUTTON_SELECT) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (msg->signal.num == JI_SIGNAL_DISABLE) {
|
2010-08-04 02:33:44 +00:00
|
|
|
ASSERT(tabs != NULL);
|
2010-06-13 20:51:22 +00:00
|
|
|
|
2010-07-03 18:03:26 +00:00
|
|
|
if (widget->isSelected()) {
|
2010-07-20 03:59:52 +00:00
|
|
|
tabs->stopScrolling();
|
2010-07-03 18:03:26 +00:00
|
|
|
widget->setSelected(false);
|
2010-06-13 20:51:22 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JM_BUTTONPRESSED:
|
2010-08-04 02:33:44 +00:00
|
|
|
ASSERT(tabs != NULL);
|
2010-07-20 03:59:52 +00:00
|
|
|
tabs->startScrolling();
|
2010-06-13 20:51:22 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case JM_BUTTONRELEASED:
|
2010-08-04 02:33:44 +00:00
|
|
|
ASSERT(tabs != NULL);
|
2010-07-20 03:59:52 +00:00
|
|
|
tabs->stopScrolling();
|
2010-06-13 20:51:22 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|