aboutsummaryrefslogtreecommitdiff
path: root/src/Scrollbar.cpp
blob: c1a06b2d945cbeab3808967dc73912d7716cc761 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "../include/Scrollbar.hpp"
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Window/Mouse.hpp>
#include <cmath>

namespace dchat
{
    const float MIN_HEIGHT = 30.0f;
    
    Scrollbar::Scrollbar() : 
        width(0.0f),
        maxHeight(0.0),
        scroll(0.0),
        maxScroll(0.0),
        scrollRelative(0.0),
        grabbing(false),
        followMouse(false)
    {
        
    }
        
    // TODO: Add scroll by clicking on scrollbar background and smoothly move scrollbar to mouse
    void Scrollbar::draw(sf::RenderWindow &window)
    {
        sf::RectangleShape backgroundRect(sf::Vector2f(floor(width), floor(maxHeight)));
        backgroundRect.setPosition(floor(position.x), floor(position.y));
        backgroundRect.setFillColor(backgroundColor);
        window.draw(backgroundRect);
        
        float minHeight = fmin(MIN_HEIGHT, maxHeight);
        float scrollHeight = maxHeight * (maxHeight / maxScroll);
        if(scrollHeight >= maxHeight)
            return;
        scrollHeight = floor(std::max(scrollHeight, minHeight));
        
        scrollRelative = scroll / (maxScroll - maxHeight);
        float possibleScrollRange = maxHeight - scrollHeight;
        sf::Vector2f scrollSize(floor(width), scrollHeight);
        sf::Vector2f scrollPosition(floor(position.x), floor(position.y + scrollRelative * possibleScrollRange));
        sf::RectangleShape scrollRect(scrollSize);
        
        bool grabbingThisFrame = false;
        if(sf::Mouse::isButtonPressed(sf::Mouse::Button::Left))
        {
            if(!grabbing)
                grabbingThisFrame = true;
            grabbing = true;
        }
        else
        {
            grabbing = false;
            followMouse = false;
        }
        
        auto mousePos = sf::Mouse::getPosition(window);
        if(followMouse)
        {
            float grabOffsetTopY = scrollSize.y * 0.5f + grabOffset.y;
            scrollPosition.y = fmax(mousePos.y - grabOffsetTopY, position.y);
            scrollPosition.y = fmin(scrollPosition.y, position.y + maxHeight - scrollHeight);
            scrollPosition.y = floor(scrollPosition.y);
            scrollRelative = (scrollPosition.y - position.y) / possibleScrollRange;
        }
        
        scrollRect.setPosition(scrollPosition);
        scrollRect.setFillColor(scrollColor);
        window.draw(scrollRect);
        
        if(!grabbingThisFrame) return;
        
        sf::Vector2f scrollbarCenter(scrollPosition.x + scrollSize.x * 0.5f, scrollPosition.y + scrollSize.y * 0.5f);
        sf::Vector2f mouseScrollbarOffset(mousePos.x - scrollbarCenter.x, mousePos.y - scrollbarCenter.y);
        if(fabs(mouseScrollbarOffset.x) <= scrollSize.x * 0.5f && fabs(mouseScrollbarOffset.y) <= scrollSize.y * 0.5f)
        {
            grabOffset = mouseScrollbarOffset;
            followMouse = true;
        }
    }
    
    float Scrollbar::getScrollingForContent() const
    {
        return -(scrollRelative * (maxScroll - maxHeight));
    }
}