#include "Scrollbar.hpp" 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; CanvasWidth = 0; CanvasHeight = 0; Trigger = 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; } bar.width = bg.width; bar.height = bg.height; // Check if resize, in this case, reset everything (avoid bugs). // Not that this will be executed during first draw also but it is fine: if((CanvasWidth != status->CanvasWidth) || (CanvasWidth != status->CanvasWidth)){ status->ScrollX=0; status->ScrollY=0; bar.x=bg.x; bar.y=bg.y; } // Compute move table canvas double MTCanvasHeight = status->CanvasHeight - status->ScrollbarWidth; double MTCanvasWidth = status->CanvasWidth - status->ScrollbarWidth; 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; } if (shouldScroll) { 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: CanvasWidth = status->CanvasWidth; CanvasHeight = status->CanvasHeight; } void Scrollbar::Focus(double XorY){ 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: XorY-=MTCanvasWidth; // Do not scroll on first page XorY=std::max(0.0,XorY); // Ensure focus is greater than 0 XorY=std::min(XorY,(status->MoveTableMaxX-MTCanvasWidth)); // Ensure focus is than scroll max // Then compute percent and apply scroll double percent = XorY / (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: XorY-=MTCanvasHeight; // Do not scroll on first page XorY=std::max(0.0,XorY); // Ensure focus is greater than 0 XorY=std::min(XorY,(status->MoveTableMaxY-MTCanvasHeight)); // Ensure focus is than scroll max // Then compute percent and apply scroll double percent = XorY / (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); } } } // namespace cgeditor