374 lines
14 KiB
C++
374 lines
14 KiB
C++
/**
|
|
* @author Edouard DUPIN
|
|
*
|
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
*
|
|
* @license APACHE v2.0 (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"
|
|
|
|
ewol::widget::Scroll::Scroll() :
|
|
propertyLimit(this, "limit",
|
|
vec2(0.15,0.5), vec2(0.0,0.0), vec2(1.0,1.0),
|
|
"Limit the scroll maximum position [0..1]% represent the free space in the scoll when arrive at the end",
|
|
&ewol::widget::Scroll::onChangePropertyLimit),
|
|
propertyShapeVert(this, "shape-vert",
|
|
"{ewol}THEME:GUI:WidgetScrolled.json",
|
|
"shape for the vertical display",
|
|
&ewol::widget::Scroll::onChangePropertyShapeVert),
|
|
propertyShapeHori(this, "shape-hori",
|
|
"{ewol}THEME:GUI:WidgetScrolled.json",
|
|
"shape for the horizonal display",
|
|
&ewol::widget::Scroll::onChangePropertyShapeHori),
|
|
m_pixelScrolling(20),
|
|
m_highSpeedStartPos(0,0),
|
|
m_highSpeedMode(speedModeDisable),
|
|
m_highSpeedButton(-1),
|
|
m_highSpeedType(gale::key::type_unknow) {
|
|
addObjectType("ewol::widget::Scroll");
|
|
}
|
|
|
|
void ewol::widget::Scroll::init() {
|
|
ewol::widget::Container::init();
|
|
propertyShapeVert.notifyChange();
|
|
propertyShapeHori.notifyChange();
|
|
}
|
|
|
|
|
|
ewol::widget::Scroll::~Scroll() {
|
|
|
|
}
|
|
|
|
#define SCROLL_BAR_SPACE (15)
|
|
|
|
void ewol::widget::Scroll::calculateMinMaxSize() {
|
|
// call main class !! and not containter class ...
|
|
ewol::Widget::calculateMinMaxSize();
|
|
// call sub classes
|
|
if (m_subWidget != nullptr) {
|
|
m_subWidget->calculateMinMaxSize();
|
|
}
|
|
}
|
|
|
|
void ewol::widget::Scroll::systemDraw(const ewol::DrawProperty& _displayProp) {
|
|
if (*propertyHide == true) {
|
|
return;
|
|
}
|
|
if (m_subWidget != nullptr) {
|
|
ewol::DrawProperty prop = _displayProp;
|
|
prop.limit(m_origin, m_size);
|
|
m_subWidget->systemDraw(prop);
|
|
}
|
|
ewol::Widget::systemDraw(_displayProp);
|
|
}
|
|
|
|
void ewol::widget::Scroll::onDraw() {
|
|
m_shaperH.draw();
|
|
m_shaperV.draw();
|
|
}
|
|
|
|
void ewol::widget::Scroll::onRegenerateDisplay() {
|
|
// call upper class
|
|
ewol::widget::Container::onRegenerateDisplay();
|
|
if (needRedraw() == false) {
|
|
return;
|
|
}
|
|
// clear all previous display
|
|
m_shaperH.clear();
|
|
m_shaperV.clear();
|
|
ewol::Padding paddingVert = m_shaperV.getPadding();
|
|
ewol::Padding paddingHori = m_shaperH.getPadding();
|
|
vec2 scrollOffset(0,0);
|
|
vec2 scrollSize(0,0);
|
|
if (m_subWidget != nullptr) {
|
|
scrollOffset = m_subWidget->getOffset();
|
|
scrollSize = m_subWidget->getSize();
|
|
}
|
|
if( m_size.y() < scrollSize.y()
|
|
|| scrollOffset.y()!=0) {
|
|
float lenScrollBar = m_size.y()*m_size.y() / scrollSize.y();
|
|
lenScrollBar = std::avg(10.0f, lenScrollBar, m_size.y());
|
|
float originScrollBar = scrollOffset.y() / (scrollSize.y()-m_size.y()*propertyLimit->y());
|
|
originScrollBar = std::avg(0.0f, originScrollBar, 1.0f);
|
|
originScrollBar *= (m_size.y()-lenScrollBar);
|
|
m_shaperV.setShape(vec2(m_size.x() - paddingVert.x(), 0),
|
|
vec2(paddingVert.x(), m_size.y()),
|
|
vec2(m_size.x() - paddingVert.xRight(), m_size.y() - originScrollBar - lenScrollBar),
|
|
vec2(0, lenScrollBar));
|
|
}
|
|
if( m_size.x() < scrollSize.x()
|
|
|| scrollOffset.x()!=0) {
|
|
float lenScrollBar = (m_size.x()-paddingHori.xLeft())*(m_size.x()-paddingVert.x()) / scrollSize.x();
|
|
lenScrollBar = std::avg(10.0f, lenScrollBar, (m_size.x()-paddingVert.x()));
|
|
float originScrollBar = scrollOffset.x() / (scrollSize.x()-m_size.x()*propertyLimit->x());
|
|
originScrollBar = std::avg(0.0f, originScrollBar, 1.0f);
|
|
originScrollBar *= (m_size.x()-paddingHori.xRight()-lenScrollBar);
|
|
m_shaperH.setShape(vec2(0, 0),
|
|
vec2(m_size.x()-paddingVert.x(), paddingHori.y()),
|
|
vec2(originScrollBar, paddingHori.yButtom()),
|
|
vec2(lenScrollBar, 0));
|
|
}
|
|
}
|
|
|
|
bool ewol::widget::Scroll::onEventInput(const ewol::event::Input& _event) {
|
|
//ewol::event::Input _event = event;
|
|
//_event.setType(gale::key::type_finger);
|
|
vec2 relativePos = relativePosition(_event.getPos());
|
|
vec2 scrollOffset(0,0);
|
|
vec2 scrollSize(0,0);
|
|
if (m_subWidget != nullptr) {
|
|
scrollOffset = m_subWidget->getOffset();
|
|
scrollSize = m_subWidget->getSize();
|
|
}
|
|
EWOL_VERBOSE("Get Event on scroll : " << _event);
|
|
relativePos.setY(m_size.y() - relativePos.y());
|
|
if( _event.getType() == gale::key::type_mouse
|
|
&& ( gale::key::type_unknow == m_highSpeedType
|
|
|| gale::key::type_mouse == m_highSpeedType ) ) {
|
|
if( _event.getId() == 1
|
|
&& _event.getStatus() == gale::key::status_down) {
|
|
// 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 = gale::key::type_mouse;
|
|
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(std::avg(0.0f, scrollOffset.y(), (scrollSize.y() - m_size.y()*propertyLimit->y())));
|
|
markToRedraw();
|
|
if (m_subWidget != nullptr) {
|
|
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 = gale::key::type_mouse;
|
|
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(std::avg(0.0f, scrollOffset.x(), (scrollSize.x() - m_size.x()*propertyLimit->x())));
|
|
markToRedraw();
|
|
if (m_subWidget != nullptr) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
} else if( _event.getId() == 4
|
|
&& _event.getStatus() == gale::key::status_up) {
|
|
if(m_size.y() < scrollSize.y()) {
|
|
scrollOffset.setY(scrollOffset.y()-m_pixelScrolling);
|
|
scrollOffset.setY(std::avg(0.0f, scrollOffset.y(), (scrollSize.y() - m_size.y()*propertyLimit->y())));
|
|
markToRedraw();
|
|
if (m_subWidget != nullptr) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
} else if( _event.getId() == 5
|
|
&& _event.getStatus() == gale::key::status_up) {
|
|
if(m_size.y() < scrollSize.y()) {
|
|
scrollOffset.setY(scrollOffset.y()+m_pixelScrolling);
|
|
scrollOffset.setY(std::avg(0.0f, scrollOffset.y(), (scrollSize.y() - m_size.y()*propertyLimit->y())));
|
|
markToRedraw();
|
|
if (m_subWidget != nullptr) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
}else if (_event.getId() == 2) {
|
|
if (_event.getStatus() == gale::key::status_down) {
|
|
m_highSpeedMode = speedModeInit;
|
|
m_highSpeedType = gale::key::type_mouse;
|
|
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() == gale::key::status_leave) {
|
|
m_highSpeedMode = speedModeDisable;
|
|
m_highSpeedType = gale::key::type_unknow;
|
|
markToRedraw();
|
|
return true;
|
|
}
|
|
if ( _event.getId() == m_highSpeedButton
|
|
&& m_highSpeedMode != speedModeDisable) {
|
|
if (_event.getStatus() == gale::key::status_up) {
|
|
if (m_highSpeedMode == speedModeInit) {
|
|
// TODO : generate back the down event ...
|
|
m_highSpeedMode = speedModeDisable;
|
|
m_highSpeedType = gale::key::type_unknow;
|
|
return false;
|
|
} else {
|
|
m_highSpeedMode = speedModeGrepEndEvent;
|
|
markToRedraw();
|
|
return true;
|
|
}
|
|
} else if (m_highSpeedMode == speedModeGrepEndEvent) {
|
|
if (_event.getStatus() == gale::key::status_single) {
|
|
m_highSpeedMode = speedModeDisable;
|
|
m_highSpeedType = gale::key::type_unknow;
|
|
m_highSpeedButton = -1;
|
|
markToRedraw();
|
|
}
|
|
return true;
|
|
} else if( m_highSpeedMode == speedModeInit
|
|
&& _event.getStatus() == gale::key::status_move) {
|
|
// wait that the cursor move more than 10 px to enable it :
|
|
if( std::abs(relativePos.x() - m_highSpeedStartPos.x()) > 10
|
|
|| std::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 (std::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(std::avg(0.0f, scrollOffset.y(), (scrollSize.y() - m_size.y()*propertyLimit->y())));
|
|
if (m_subWidget != nullptr) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
if( m_highSpeedMode == speedModeEnableHorizontal
|
|
&& _event.getStatus() == gale::key::status_move) {
|
|
scrollOffset.setX((int32_t)(scrollSize.x() * (relativePos.x()-SCROLL_BAR_SPACE) / (m_size.x()-SCROLL_BAR_SPACE*2)));
|
|
scrollOffset.setX(std::avg(0.0f, scrollOffset.x(), (scrollSize.x() - m_size.x()*propertyLimit->x() )));
|
|
markToRedraw();
|
|
if (m_subWidget != nullptr) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
if( m_highSpeedMode == speedModeEnableVertical
|
|
&& _event.getStatus() == gale::key::status_move) {
|
|
scrollOffset.setY((int32_t)(scrollSize.y() * (relativePos.y()-SCROLL_BAR_SPACE) / (m_size.y()-SCROLL_BAR_SPACE*2)));
|
|
scrollOffset.setY(std::avg(0.0f, scrollOffset.y(), (scrollSize.y() - m_size.y()*propertyLimit->x())));
|
|
markToRedraw();
|
|
if (m_subWidget != nullptr) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
} else if( gale::key::type_finger == _event.getType()
|
|
&& ( gale::key::type_unknow == m_highSpeedType
|
|
|| gale::key::type_finger == m_highSpeedType ) ) {
|
|
if (1 == _event.getId()) {
|
|
EWOL_VERBOSE("event: " << _event);
|
|
if (gale::key::status_down == _event.getStatus()) {
|
|
m_highSpeedMode = speedModeInit;
|
|
m_highSpeedType = gale::key::type_finger;
|
|
m_highSpeedStartPos.setValue(relativePos.x(), relativePos.y());
|
|
EWOL_VERBOSE("SCROOL == > INIT pos=" << m_highSpeedStartPos << " && curent scrollOffset=" << scrollOffset);
|
|
return true;
|
|
} else if (gale::key::status_upAfter == _event.getStatus()) {
|
|
m_highSpeedMode = speedModeDisable;
|
|
m_highSpeedType = gale::key::type_unknow;
|
|
EWOL_VERBOSE("SCROOL == > DISABLE");
|
|
markToRedraw();
|
|
return true;
|
|
} else if ( m_highSpeedMode == speedModeInit
|
|
&& gale::key::status_move == _event.getStatus()) {
|
|
// wait that the cursor move more than 10 px to enable it :
|
|
if( std::abs(relativePos.x() - m_highSpeedStartPos.x()) > 10
|
|
|| std::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
|
|
&& gale::key::status_move == _event.getStatus()) {
|
|
EWOL_VERBOSE("SCROOL == > INIT scrollOffset=" << scrollOffset.y() << " relativePos=" << relativePos.y() << " m_highSpeedStartPos=" << m_highSpeedStartPos.y());
|
|
//scrollOffset.x = (int32_t)(scrollSize.x * x / m_size.x);
|
|
if (propertyLimit->x() != 0.0f) {
|
|
scrollOffset.setX(scrollOffset.x() + (relativePos.x() - m_highSpeedStartPos.x()));
|
|
scrollOffset.setX(std::avg(0.0f, scrollOffset.x(), (scrollSize.x() - m_size.x()*propertyLimit->x())));
|
|
}
|
|
if (propertyLimit->y() != 0.0f) {
|
|
scrollOffset.setY(scrollOffset.y() - (relativePos.y() - m_highSpeedStartPos.y()));
|
|
scrollOffset.setY(std::avg(0.0f, scrollOffset.y(), (scrollSize.y() - m_size.y()*propertyLimit->y())));
|
|
}
|
|
// update current position:
|
|
m_highSpeedStartPos = relativePos;
|
|
EWOL_VERBOSE("SCROOL == > MOVE " << scrollOffset);
|
|
markToRedraw();
|
|
if (m_subWidget != nullptr) {
|
|
m_subWidget->setOffset(scrollOffset);
|
|
}
|
|
return true;
|
|
}
|
|
if (m_highSpeedMode == speedModeEnableFinger) {
|
|
return true;
|
|
}
|
|
} else if ( m_highSpeedMode != speedModeDisable
|
|
&& gale::key::status_leave == _event.getStatus()) {
|
|
m_highSpeedMode = speedModeDisable;
|
|
m_highSpeedType = gale::key::type_unknow;
|
|
EWOL_VERBOSE("SCROOL == > DISABLE");
|
|
markToRedraw();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
ewol::WidgetShared ewol::widget::Scroll::getWidgetAtPos(const vec2& _pos) {
|
|
ewol::WidgetShared tmpWidget = ewol::widget::Container::getWidgetAtPos(_pos);
|
|
if (tmpWidget != nullptr) {
|
|
return tmpWidget;
|
|
}
|
|
return std::dynamic_pointer_cast<ewol::Widget>(shared_from_this());;
|
|
}
|
|
|
|
void ewol::widget::Scroll::onChangePropertyLimit() {
|
|
markToRedraw();
|
|
}
|
|
|
|
void ewol::widget::Scroll::onChangePropertyShapeVert() {
|
|
m_shaperV.setSource(propertyShapeVert);
|
|
markToRedraw();
|
|
}
|
|
|
|
void ewol::widget::Scroll::onChangePropertyShapeHori() {
|
|
m_shaperH.setSource(propertyShapeHori);
|
|
markToRedraw();
|
|
}
|
|
|