mirror of
https://gitlab.com/manzerbredes/cgeditor.git
synced 2025-04-05 17:46:28 +02:00
223 lines
No EOL
7.2 KiB
C++
223 lines
No EOL
7.2 KiB
C++
#include "Scrollbar.hpp"
|
|
#include <iostream>
|
|
namespace cgeditor {
|
|
Scrollbar::Scrollbar(Status *s, bool IsHorizontal) : Component(s) {
|
|
this->IsHorizontal = IsHorizontal;
|
|
|
|
bg.prop = Property::Rectangle | Property::Scrollbarbg;
|
|
bar.prop = Property::Rectangle | Property::Scrollbar;
|
|
|
|
if (IsHorizontal) {
|
|
bg.prop |= Property::Horizontal;
|
|
bar.x = 0;
|
|
} else {
|
|
bar.y = 0;
|
|
}
|
|
|
|
DragX = 0;
|
|
DragY = 0;
|
|
Trigger = false;
|
|
ShouldApplyFocus = false;
|
|
}
|
|
|
|
void Scrollbar::Refresh() {
|
|
if (IsHorizontal) {
|
|
bg.y = status->CanvasHeight - status->ScrollbarWidth;
|
|
bg.width = status->CanvasWidth - status->ScrollbarWidth;
|
|
bg.height = status->ScrollbarWidth;
|
|
bar.y = bg.y;
|
|
} else {
|
|
bg.x = status->CanvasWidth - status->ScrollbarWidth;
|
|
bg.width = status->CanvasWidth;
|
|
bg.height = status->CanvasHeight - status->ScrollbarWidth;
|
|
bar.x = bg.x;
|
|
}
|
|
// Init default width and height
|
|
bar.width = bg.width;
|
|
bar.height = bg.height;
|
|
|
|
// Compute move table canvas
|
|
double MTCanvasHeight = status->CanvasHeight - status->ScrollbarWidth;
|
|
double MTCanvasWidth = status->CanvasWidth - status->ScrollbarWidth;
|
|
|
|
// Configure scrollbar width and height and determined if a scroll must be applied:
|
|
bool shouldScroll = false;
|
|
if (!IsHorizontal && status->MoveTableMaxY > MTCanvasHeight) {
|
|
bar.height =
|
|
std::ceil(bg.height * (MTCanvasHeight / status->MoveTableMaxY));
|
|
shouldScroll = true;
|
|
}
|
|
|
|
if (IsHorizontal && status->MoveTableMaxX > MTCanvasWidth) {
|
|
bar.width = std::ceil(bg.width * (MTCanvasWidth / status->MoveTableMaxX));
|
|
shouldScroll = true;
|
|
}
|
|
|
|
// Ensure current scroll is valid (moves deletions, canvas resize etc...)
|
|
// If not, we correct it now
|
|
if(IsHorizontal){
|
|
// Check if we should not scroll but still an offset is applied to coordinates:
|
|
if(!shouldScroll && status->ScrollX>0){
|
|
status->ScrollX=0;
|
|
bar.x=bg.x;
|
|
}
|
|
// Else if we should scroll:
|
|
else if(shouldScroll){
|
|
double maxScroll=status->MoveTableMaxX-MTCanvasWidth;
|
|
// Check if we over scroll:
|
|
if((maxScroll+status->ScrollX)<0){
|
|
status->ScrollX=-maxScroll;
|
|
bar.x=bg.width-bar.width;
|
|
}
|
|
// If not sensure that scroll bar is at the correct location:
|
|
else {
|
|
// We add negative sign because ScrollY is negative:
|
|
double percent = (-status->ScrollX) / maxScroll;
|
|
bar.x=(bg.width - bar.width)*percent;
|
|
}
|
|
}
|
|
else {
|
|
status->ScrollX=0;
|
|
bar.x=0;
|
|
}
|
|
} else {
|
|
// Here same as previously but for vertical bar!
|
|
if(!shouldScroll && status->ScrollY>0){
|
|
status->ScrollY=0;
|
|
bar.y=bg.y;
|
|
}
|
|
else if(shouldScroll){
|
|
double maxScroll=status->MoveTableMaxY-MTCanvasHeight;
|
|
if((maxScroll+status->ScrollY)<0){
|
|
status->ScrollY=-maxScroll;
|
|
bar.y=bg.height-bar.height;
|
|
} else {
|
|
double percent = (-status->ScrollY) / maxScroll;
|
|
bar.y=(bg.height - bar.height)*percent;
|
|
}
|
|
} else {
|
|
status->ScrollY=0;
|
|
bar.y=0;
|
|
}
|
|
}
|
|
|
|
// Handle user scroll events:
|
|
if (shouldScroll) {
|
|
if(ShouldApplyFocus){
|
|
ApplyFocus();
|
|
}
|
|
else if (IsHorizontal && status->EventHScroll != 0) {
|
|
double percent = status->EventHScroll / status->MoveTableMaxX;
|
|
double maxScroll = bg.width - bar.width;
|
|
bar.x += maxScroll * percent;
|
|
bar.x = std::max(bg.x, bar.x);
|
|
bar.x = std::min(bg.x + maxScroll, bar.x);
|
|
double curScroll = bar.x - bg.x;
|
|
double scrollPercent = curScroll / maxScroll;
|
|
status->ScrollX =
|
|
-(status->MoveTableMaxX - MTCanvasWidth) * scrollPercent;
|
|
status->EventHScroll = 0;
|
|
} else if (status->EventVScroll != 0) {
|
|
double percent = status->EventVScroll / status->MoveTableMaxY;
|
|
double maxScroll = bg.height - bar.height;
|
|
bar.y += maxScroll * percent;
|
|
bar.y = std::max(bg.y, bar.y);
|
|
bar.y = std::min(bg.y + maxScroll, bar.y);
|
|
double curScroll = bar.y - bg.y;
|
|
double scrollPercent = curScroll / maxScroll;
|
|
status->ScrollY =
|
|
-(status->MoveTableMaxY - MTCanvasHeight) * scrollPercent;
|
|
status->EventVScroll = 0;
|
|
} else if (status->LeftClick &&
|
|
bar.IsOver(status->MouseX, status->MouseY)) {
|
|
DragX = bar.x;
|
|
DragY = bar.y;
|
|
Trigger = true;
|
|
} else if (Trigger && status->IsDrag) {
|
|
if (IsHorizontal) {
|
|
bar.x = DragX + (status->MouseX - status->LastMouseClicX);
|
|
bar.x = std::max(bg.x, bar.x);
|
|
double maxScroll = bg.width - bar.width;
|
|
bar.x = std::min(bg.x + maxScroll, bar.x);
|
|
double curScroll = bar.x - bg.x;
|
|
double scrollPercent = curScroll / maxScroll;
|
|
status->ScrollX =
|
|
-(status->MoveTableMaxX - MTCanvasWidth) * scrollPercent;
|
|
} else {
|
|
bar.y = DragY + (status->MouseY - status->LastMouseClicY);
|
|
bar.y = std::max(bg.y, bar.y);
|
|
double maxScroll = bg.height - bar.height;
|
|
bar.y = std::min(bg.y + maxScroll, bar.y);
|
|
double curScroll = bar.y - bg.y;
|
|
double scrollPercent = curScroll / maxScroll;
|
|
status->ScrollY =
|
|
-(status->MoveTableMaxY - MTCanvasHeight) * scrollPercent;
|
|
}
|
|
} else {
|
|
Trigger = false;
|
|
}
|
|
}
|
|
|
|
elements.clear();
|
|
elements.push_back(bg);
|
|
elements.push_back(bar);
|
|
// Update cache:
|
|
ShouldApplyFocus=false;
|
|
}
|
|
|
|
void Scrollbar::ApplyFocus(){
|
|
double MTCanvasHeight = status->CanvasHeight - status->ScrollbarWidth;
|
|
double MTCanvasWidth = status->CanvasWidth - status->ScrollbarWidth;
|
|
// Check horizontal or vertical and if should scroll
|
|
if(IsHorizontal && status->MoveTableMaxX > MTCanvasWidth){
|
|
// First normalize:
|
|
FocusX-=MTCanvasWidth; // Do not scroll on first page
|
|
FocusX=std::max(0.0,FocusX); // Ensure focus is greater than 0
|
|
FocusX=std::min(FocusX,(status->MoveTableMaxX-MTCanvasWidth)); // Ensure focus is than scroll max
|
|
// Then compute percent and apply scroll
|
|
double percent = FocusX / (status->MoveTableMaxX-MTCanvasWidth);
|
|
status->ScrollX =
|
|
-(status->MoveTableMaxX - MTCanvasWidth) * percent;
|
|
// Do not forget to update scrollbar:
|
|
double maxScroll = bg.width - bar.width;
|
|
bar.x = maxScroll * percent;
|
|
bar.x = std::max(bg.x, bar.x);
|
|
bar.x = std::min(bg.x + maxScroll, bar.x);
|
|
}
|
|
else if(status->MoveTableMaxY > MTCanvasHeight){
|
|
// First normalize:
|
|
FocusY-=MTCanvasHeight; // Do not scroll on first page
|
|
FocusY=std::max(0.0,FocusY); // Ensure focus is greater than 0
|
|
FocusY=std::min(FocusY,(status->MoveTableMaxY-MTCanvasHeight)); // Ensure focus is than scroll max
|
|
// Then compute percent and apply scroll
|
|
double percent = FocusY / (status->MoveTableMaxY-MTCanvasHeight);
|
|
status->ScrollY =
|
|
-(status->MoveTableMaxY - MTCanvasHeight) * percent;
|
|
// Do not forget to update scrollbar:
|
|
double maxScroll = bg.height - bar.height;
|
|
bar.y = maxScroll * percent;
|
|
bar.y = std::max(bg.y, bar.y);
|
|
bar.y = std::min(bg.y + maxScroll, bar.y);
|
|
}
|
|
}
|
|
|
|
void Scrollbar::Focus(double XorY){
|
|
if(IsHorizontal)
|
|
FocusX=XorY;
|
|
else
|
|
FocusY=XorY;
|
|
ShouldApplyFocus=true;
|
|
}
|
|
|
|
void Scrollbar::Reset(){
|
|
if(IsHorizontal){
|
|
status->ScrollX=0;
|
|
bar.x=bg.x;
|
|
}else{
|
|
status->ScrollY=0;
|
|
bar.y=bg.y;
|
|
}
|
|
}
|
|
|
|
|
|
} // namespace cgeditor
|