366 lines
13 KiB
C++
366 lines
13 KiB
C++
/**
|
|
* @author Edouard DUPIN
|
|
*
|
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
*
|
|
* @license BSD v3 (see license file)
|
|
*/
|
|
|
|
#include <ewol/widget/Scroll.h>
|
|
#include <ewol/ewol.h>
|
|
#include <ewol/widget/Manager.h>
|
|
#include <ewol/debug.h>
|
|
|
|
#undef __class__
|
|
#define __class__ "Scroll"
|
|
|
|
static ewol::Widget* create(void) {
|
|
return new ewol::widget::Scroll();
|
|
}
|
|
|
|
void ewol::widget::Scroll::init(ewol::widget::Manager& _widgetManager) {
|
|
_widgetManager.addWidgetCreator(__class__,&create);
|
|
}
|
|
|
|
const char* const ewol::widget::Scroll::configLimit = "limit";
|
|
|
|
ewol::widget::Scroll::Scroll(void) :
|
|
m_limit(0.15,0.5),
|
|
m_pixelScrolling(20),
|
|
m_highSpeedStartPos(0,0),
|
|
m_highSpeedMode(speedModeDisable),
|
|
m_highSpeedButton(-1),
|
|
m_highSpeedType(ewol::key::typeUnknow) {
|
|
addObjectType("ewol::widget::Scroll");
|
|
registerConfig(configLimit, "vec2", NULL, "Limit the scroll maximum position [0..1]% represent the free space in the scoll when arrive at the end");
|
|
}
|
|
|
|
ewol::widget::Scroll::~Scroll(void) {
|
|
|
|
}
|
|
|
|
void ewol::widget::Scroll::setLimit(const vec2& _limit) {
|
|
m_limit = _limit;
|
|
markToRedraw();
|
|
}
|
|
|
|
#define SCROLL_BAR_SPACE (15)
|
|
|
|
void ewol::widget::Scroll::calculateMinMaxSize(void) {
|
|
// call main class !! and not containter class ...
|
|
ewol::Widget::calculateMinMaxSize();
|
|
// call sub classes
|
|
if (NULL!=m_subWidget) {
|
|
m_subWidget->calculateMinMaxSize();
|
|
}
|
|
}
|
|
|
|
void ewol::widget::Scroll::systemDraw(const ewol::DrawProperty& _displayProp) {
|
|
if (m_hide == true) {
|
|
return;
|
|
}
|
|
if (NULL!=m_subWidget) {
|
|
ewol::DrawProperty prop = _displayProp;
|
|
prop.limit(m_origin, m_size);
|
|
m_subWidget->systemDraw(prop);
|
|
}
|
|
ewol::Widget::systemDraw(_displayProp);
|
|
}
|
|
|
|
void ewol::widget::Scroll::onDraw(void) {
|
|
m_draw.draw();
|
|
}
|
|
|
|
void ewol::widget::Scroll::onRegenerateDisplay(void) {
|
|
// call upper class
|
|
ewol::widget::Container::onRegenerateDisplay();
|
|
if (true == needRedraw()) {
|
|
// clear all previous display
|
|
m_draw.clear();
|
|
|
|
m_draw.setColor(0xFF00007F);
|
|
|
|
vec2 scrollOffset(0,0);
|
|
vec2 scrollSize(0,0);
|
|
if (NULL!=m_subWidget) {
|
|
scrollOffset = m_subWidget->getOffset();
|
|
scrollSize = m_subWidget->getSize();
|
|
}
|
|
m_draw.setThickness(1);
|
|
if( m_size.y() < scrollSize.y()
|
|
|| scrollOffset.y()!=0) {
|
|
//EWOL_DEBUG("plop : " << vec2(m_size.x()-(SCROLL_BAR_SPACE/2), 0) << " " << vec2(m_size.x()-(SCROLL_BAR_SPACE/2), m_size.y()));
|
|
m_draw.setPos(vec2(m_size.x()-(SCROLL_BAR_SPACE/2), 0) );
|
|
m_draw.lineTo(vec2(m_size.x()-(SCROLL_BAR_SPACE/2), m_size.y()) );
|
|
float lenScrollBar = m_size.y()*m_size.y() / scrollSize.y();
|
|
lenScrollBar = etk_avg(10, lenScrollBar, m_size.y());
|
|
float originScrollBar = scrollOffset.y() / (scrollSize.y()-m_size.y()*m_limit.y());
|
|
originScrollBar = etk_avg(0.0, originScrollBar, 1.0);
|
|
originScrollBar *= (m_size.y()-lenScrollBar);
|
|
m_draw.setPos(vec2(m_size.x()-SCROLL_BAR_SPACE, m_size.y() - originScrollBar - lenScrollBar) );
|
|
m_draw.rectangleWidth(vec2(SCROLL_BAR_SPACE, lenScrollBar));
|
|
}
|
|
if( m_size.x() < scrollSize.x()
|
|
|| scrollOffset.x()!=0) {
|
|
m_draw.setPos(vec2(0, (SCROLL_BAR_SPACE/2)) );
|
|
m_draw.lineTo(vec2(m_size.x()-SCROLL_BAR_SPACE, (SCROLL_BAR_SPACE/2)) );
|
|
float lenScrollBar = m_size.x()*(m_size.x()-SCROLL_BAR_SPACE) / scrollSize.x();
|
|
lenScrollBar = etk_avg(10, lenScrollBar, (m_size.x()-SCROLL_BAR_SPACE));
|
|
float originScrollBar = scrollOffset.x() / (scrollSize.x()-m_size.x()*m_limit.x());
|
|
originScrollBar = etk_avg(0.0, originScrollBar, 1.0);
|
|
originScrollBar *= (m_size.x()-SCROLL_BAR_SPACE-lenScrollBar);
|
|
m_draw.setPos(vec2(originScrollBar, 0) );
|
|
m_draw.rectangle(vec2(lenScrollBar, SCROLL_BAR_SPACE) );
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ewol::widget::Scroll::onEventInput(const ewol::event::Input& _event) {
|
|
vec2 relativePos = relativePosition(_event.getPos());
|
|
vec2 scrollOffset(0,0);
|
|
vec2 scrollSize(0,0);
|
|
if (NULL!=m_subWidget) {
|
|
scrollOffset = m_subWidget->getOffset();
|
|
scrollSize = m_subWidget->getSize();
|
|
}
|
|
relativePos.setY(m_size.y() - relativePos.y());
|
|
if( _event.getType() == ewol::key::typeMouse
|
|
&& ( ewol::key::typeUnknow == m_highSpeedType
|
|
|| ewol::key::typeMouse == m_highSpeedType ) ) {
|
|
if( _event.getId() == 1
|
|
&& _event.getStatus() == ewol::key::statusDown) {
|
|
// check if selected the scrolling position whth the scrolling bar ...
|
|
if (relativePos.x() >= (m_size.x()-SCROLL_BAR_SPACE)) {
|
|
if( m_size.y() < scrollSize.y()
|
|
|| scrollOffset.y() != 0) {
|
|
m_highSpeedMode = speedModeEnableVertical;
|
|
m_highSpeedType = ewol::key::typeMouse;
|
|
m_highSpeedStartPos.setX(relativePos.x());
|
|
m_highSpeedStartPos.setY(scrollOffset.y() / scrollSize.y() * (m_size.y()-SCROLL_BAR_SPACE*2));
|
|
m_highSpeedButton = 1;
|
|
// force direct scrolling in this case
|
|
scrollOffset.setY((int32_t)(scrollSize.y() * (relativePos.y()-SCROLL_BAR_SPACE) / (m_size.y()-SCROLL_BAR_SPACE*2)));
|
|
scrollOffset.setY(etk_avg(0, scrollOffset.y(), (scrollSize.y() - m_size.y()*m_limit.y())));
|
|
markToRedraw();
|
|
if (NULL!=m_subWidget) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
} else if (relativePos.y() >= (m_size.y()-SCROLL_BAR_SPACE)) {
|
|
if( m_size.x() < scrollSize.x()
|
|
|| scrollOffset.x()!=0) {
|
|
m_highSpeedMode = speedModeEnableHorizontal;
|
|
m_highSpeedType = ewol::key::typeMouse;
|
|
m_highSpeedStartPos.setX(scrollOffset.x() / scrollSize.x() * (m_size.x()-SCROLL_BAR_SPACE*2));
|
|
m_highSpeedStartPos.setY(relativePos.y());
|
|
m_highSpeedButton = 1;
|
|
// force direct scrolling in this case
|
|
scrollOffset.setX((int32_t)(scrollSize.x() * (relativePos.x()-SCROLL_BAR_SPACE) / (m_size.x()-SCROLL_BAR_SPACE*2)));
|
|
scrollOffset.setY(etk_avg(0, scrollOffset.x(), (scrollSize.x() - m_size.x()*m_limit.x())));
|
|
markToRedraw();
|
|
if (NULL!=m_subWidget) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
} else if( _event.getId() == 4
|
|
&& _event.getStatus() == ewol::key::statusUp) {
|
|
if(m_size.y() < scrollSize.y()) {
|
|
scrollOffset.setY(scrollOffset.y()-m_pixelScrolling);
|
|
scrollOffset.setY(etk_avg(0, scrollOffset.y(), (scrollSize.y() - m_size.y()*m_limit.y())));
|
|
markToRedraw();
|
|
if (NULL!=m_subWidget) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
} else if( _event.getId() == 5
|
|
&& _event.getStatus() == ewol::key::statusUp) {
|
|
if(m_size.y() < scrollSize.y()) {
|
|
scrollOffset.setY(scrollOffset.y()+m_pixelScrolling);
|
|
scrollOffset.setY(etk_avg(0, scrollOffset.y(), (scrollSize.y() - m_size.y()*m_limit.y())));
|
|
markToRedraw();
|
|
if (NULL!=m_subWidget) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
}else if (_event.getId() == 2) {
|
|
if (_event.getStatus() == ewol::key::statusDown) {
|
|
m_highSpeedMode = speedModeInit;
|
|
m_highSpeedType = ewol::key::typeMouse;
|
|
m_highSpeedStartPos.setValue(relativePos.x(), relativePos.y());
|
|
m_highSpeedButton = 2;
|
|
// not really use... == > just keep some informations
|
|
return false;
|
|
}
|
|
} else if( m_highSpeedMode != speedModeDisable
|
|
&& _event.getStatus() == ewol::key::statusLeave) {
|
|
m_highSpeedMode = speedModeDisable;
|
|
m_highSpeedType = ewol::key::typeUnknow;
|
|
markToRedraw();
|
|
return true;
|
|
}
|
|
if ( _event.getId() == m_highSpeedButton
|
|
&& m_highSpeedMode != speedModeDisable) {
|
|
if (_event.getStatus() == ewol::key::statusUp) {
|
|
if (m_highSpeedMode == speedModeInit) {
|
|
// TODO : generate back the down event ...
|
|
m_highSpeedMode = speedModeDisable;
|
|
m_highSpeedType = ewol::key::typeUnknow;
|
|
return false;
|
|
} else {
|
|
m_highSpeedMode = speedModeGrepEndEvent;
|
|
markToRedraw();
|
|
return true;
|
|
}
|
|
} else if (m_highSpeedMode == speedModeGrepEndEvent) {
|
|
if (_event.getStatus() == ewol::key::statusSingle) {
|
|
m_highSpeedMode = speedModeDisable;
|
|
m_highSpeedType = ewol::key::typeUnknow;
|
|
m_highSpeedButton = -1;
|
|
markToRedraw();
|
|
}
|
|
return true;
|
|
} else if( m_highSpeedMode == speedModeInit
|
|
&& _event.getStatus() == ewol::key::statusMove) {
|
|
// wait that the cursor move more than 10 px to enable it :
|
|
if( abs(relativePos.x() - m_highSpeedStartPos.x()) > 10
|
|
|| abs(relativePos.y() - m_highSpeedStartPos.y()) > 10 ) {
|
|
// the scrooling can start :
|
|
// select the direction :
|
|
if (relativePos.x() == m_highSpeedStartPos.x()) {
|
|
m_highSpeedMode = speedModeEnableVertical;
|
|
} else if (relativePos.y() == m_highSpeedStartPos.y()) {
|
|
m_highSpeedMode = speedModeEnableHorizontal;
|
|
} else {
|
|
float coef = (relativePos.y() - m_highSpeedStartPos.y()) / (relativePos.x() - m_highSpeedStartPos.x());
|
|
if (abs(coef) <= 1 ) {
|
|
m_highSpeedMode = speedModeEnableHorizontal;
|
|
} else {
|
|
m_highSpeedMode = speedModeEnableVertical;
|
|
}
|
|
}
|
|
if (m_highSpeedMode == speedModeEnableHorizontal) {
|
|
m_highSpeedStartPos.setX(scrollOffset.x() / scrollSize.x() * (m_size.x()-SCROLL_BAR_SPACE*2));
|
|
} else {
|
|
m_highSpeedStartPos.setY(scrollOffset.y() / scrollSize.y() * (m_size.y()-SCROLL_BAR_SPACE*2));
|
|
}
|
|
markToRedraw();
|
|
}
|
|
scrollOffset.setY(etk_avg(0, scrollOffset.y(), (scrollSize.y() - m_size.y()*m_limit.y())));
|
|
if (NULL!=m_subWidget) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
if( m_highSpeedMode == speedModeEnableHorizontal
|
|
&& _event.getStatus() == ewol::key::statusMove) {
|
|
scrollOffset.setX((int32_t)(scrollSize.x() * (relativePos.x()-SCROLL_BAR_SPACE) / (m_size.x()-SCROLL_BAR_SPACE*2)));
|
|
scrollOffset.setX(etk_avg(0, scrollOffset.x(), (scrollSize.x() - m_size.x()*m_limit.x() )));
|
|
markToRedraw();
|
|
if (NULL!=m_subWidget) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
if( m_highSpeedMode == speedModeEnableVertical
|
|
&& _event.getStatus() == ewol::key::statusMove) {
|
|
scrollOffset.setY((int32_t)(scrollSize.y() * (relativePos.y()-SCROLL_BAR_SPACE) / (m_size.y()-SCROLL_BAR_SPACE*2)));
|
|
scrollOffset.setY(etk_avg(0, scrollOffset.y(), (scrollSize.y() - m_size.y()*m_limit.x())));
|
|
markToRedraw();
|
|
if (NULL!=m_subWidget) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
} else if( ewol::key::typeFinger == _event.getType()
|
|
&& ( ewol::key::typeUnknow == m_highSpeedType
|
|
|| ewol::key::typeFinger == m_highSpeedType ) ) {
|
|
if (1 == _event.getId()) {
|
|
//EWOL_VERBOSE("event 1 << " << (int32_t)typeEvent << "(" << x << "," << y << ")");
|
|
if (ewol::key::statusDown == _event.getStatus()) {
|
|
m_highSpeedMode = speedModeInit;
|
|
m_highSpeedType = ewol::key::typeFinger;
|
|
m_highSpeedStartPos.setValue(relativePos.x(), relativePos.y());
|
|
EWOL_VERBOSE("SCROOL == > INIT");
|
|
return true;
|
|
} else if (ewol::key::statusUp == _event.getStatus()) {
|
|
m_highSpeedMode = speedModeDisable;
|
|
m_highSpeedType = ewol::key::typeUnknow;
|
|
EWOL_VERBOSE("SCROOL == > DISABLE");
|
|
markToRedraw();
|
|
return true;
|
|
} else if ( m_highSpeedMode == speedModeInit
|
|
&& ewol::key::statusMove == _event.getStatus()) {
|
|
// wait that the cursor move more than 10 px to enable it :
|
|
if( abs(relativePos.x() - m_highSpeedStartPos.x()) > 10
|
|
|| abs(relativePos.y() - m_highSpeedStartPos.y()) > 10 ) {
|
|
// the scrooling can start :
|
|
// select the direction :
|
|
m_highSpeedMode = speedModeEnableFinger;
|
|
EWOL_VERBOSE("SCROOL == > ENABLE");
|
|
markToRedraw();
|
|
}
|
|
return true;
|
|
}
|
|
if ( m_highSpeedMode == speedModeEnableFinger
|
|
&& ewol::key::statusMove == _event.getStatus()) {
|
|
//scrollOffset.x = (int32_t)(scrollSize.x * x / m_size.x);
|
|
scrollOffset.setX(scrollOffset.x() - relativePos.x() - m_highSpeedStartPos.x());
|
|
scrollOffset.setY(scrollOffset.y() - relativePos.y() - m_highSpeedStartPos.y());
|
|
scrollOffset.setX(etk_avg(0, scrollOffset.x(), (scrollSize.x() - m_size.x()*m_limit.x())));
|
|
scrollOffset.setY(etk_avg(0, scrollOffset.y(), (scrollSize.y() - m_size.y()*m_limit.y())));
|
|
m_highSpeedStartPos.setValue(relativePos.x(), relativePos.y());
|
|
EWOL_VERBOSE("SCROOL == > MOVE (" << scrollOffset.x() << "," << scrollOffset.y() << ")");
|
|
markToRedraw();
|
|
return true;
|
|
}
|
|
} else if ( m_highSpeedMode != speedModeDisable
|
|
&& ewol::key::statusLeave == _event.getStatus()) {
|
|
m_highSpeedMode = speedModeDisable;
|
|
m_highSpeedType = ewol::key::typeUnknow;
|
|
EWOL_VERBOSE("SCROOL == > DISABLE");
|
|
markToRedraw();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
ewol::Widget* ewol::widget::Scroll::getWidgetAtPos(const vec2& _pos) {
|
|
ewol::Widget* tmpWidget = ewol::widget::Container::getWidgetAtPos(_pos);
|
|
if (NULL != tmpWidget) {
|
|
return tmpWidget;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
bool ewol::widget::Scroll::onSetConfig(const ewol::object::Config& _conf) {
|
|
if (true == ewol::widget::Container::onSetConfig(_conf)) {
|
|
return true;
|
|
}
|
|
if (_conf.getConfig() == configLimit) {
|
|
setLimit(_conf.getData());
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ewol::widget::Scroll::onGetConfig(const char* _config, std::string& _result) const {
|
|
if (true == ewol::widget::Container::onGetConfig(_config, _result)) {
|
|
return true;
|
|
}
|
|
if (_config == configLimit) {
|
|
_result = getLimit();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|