• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Return-To-The-Roots / s25client / 18801966163

25 Oct 2025 10:37AM UTC coverage: 50.497% (+0.006%) from 50.491%
18801966163

Pull #1811

github

web-flow
Merge deb629d2a into 2d6849772
Pull Request #1811: Convert `MouseCoord` to plain struct

26 of 73 new or added lines in 20 files covered. (35.62%)

22514 of 44585 relevant lines covered (50.5%)

34778.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

44.35
/libs/s25main/controls/ctrlScrollBar.cpp
1
// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org)
2
//
3
// SPDX-License-Identifier: GPL-2.0-or-later
4

5
#include "ctrlScrollBar.h"
6
#include "CollisionDetection.h"
7
#include "Loader.h"
8
#include "ctrlButton.h"
9
#include "driver/MouseCoords.h"
10

11
ctrlScrollBar::ctrlScrollBar(Window* parent, unsigned id, const DrawPoint& pos, const Extent& size,
74✔
12
                             unsigned short button_height, TextureColor tc, unsigned short pagesize)
74✔
13
    : Window(parent, id, pos, size), button_height(button_height), tc(tc), pagesize(pagesize), scroll_range(0),
14
      scroll_pos(0), scroll_height(0), sliderHeight(0), sliderPos(0), isMouseScrolling(false), last_y(0)
74✔
15
{
16
    SetVisible(false);
74✔
17

18
    AddImageButton(0, DrawPoint(0, 0), Extent(size.x, button_height), tc, LOADER.GetImageN("io", 33));
148✔
19
    AddImageButton(1, DrawPoint(0, (size.y > button_height) ? size.y - button_height : 1),
296✔
20
                   Extent(size.x, button_height), tc, LOADER.GetImageN("io", 34));
222✔
21

22
    Resize(size);
74✔
23
}
74✔
24

25
void ctrlScrollBar::Scroll(int distance)
×
26
{
27
    if(distance == 0 || scroll_range == 0)
×
28
        return;
×
29
    // Calc new scroll pos
30
    int newScrollPos = scroll_pos + distance;
×
31
    // But beware of over and underflows. Final value must be >= 0
32
    if(newScrollPos + pagesize > scroll_range)
×
33
        newScrollPos = static_cast<int>(scroll_range) - pagesize;
×
34
    if(newScrollPos < 0)
×
35
        newScrollPos = 0;
×
36
    if(scroll_pos != static_cast<unsigned short>(newScrollPos))
×
37
    {
38
        scroll_pos = static_cast<unsigned short>(newScrollPos);
×
39
        UpdateSliderFromPos();
×
40
        GetParent()->Msg_ScrollChange(GetID(), scroll_pos);
×
41
    }
42
}
43

44
bool ctrlScrollBar::Msg_LeftUp(const MouseCoords& mc)
×
45
{
46
    isMouseScrolling = false;
×
47

48
    // ButtonMessages weiterleiten
49
    return RelayMouseMessage(&Window::Msg_LeftUp, mc);
×
50
}
51

52
bool ctrlScrollBar::Msg_LeftDown(const MouseCoords& mc)
×
53
{
NEW
54
    if(IsPointInRect(mc.pos,
×
55
                     Rect(GetDrawPos().x, GetDrawPos().y + button_height + sliderPos, GetSize().x, sliderHeight)))
×
56
    {
57
        // Maus auf dem Scrollbutton
58
        isMouseScrolling = true;
×
59
        return true;
×
NEW
60
    } else if(IsPointInRect(mc.pos, Rect(GetDrawPos().x, GetDrawPos().y + button_height, GetSize().x, sliderPos)))
×
61
    {
62
        // Clicked above slider -> Move half a slider height up
63
        if(sliderPos < sliderHeight / 2)
×
64
            sliderPos = 0;
×
65
        else
66
            sliderPos -= sliderHeight / 2;
×
67

68
        UpdatePosFromSlider();
×
69
        return true;
×
70
    } else
71
    {
72
        unsigned short bottomSliderPos = button_height + sliderPos + sliderHeight;
×
73

NEW
74
        if(IsPointInRect(mc.pos, Rect(GetDrawPos().x, GetDrawPos().y + bottomSliderPos, GetSize().x,
×
NEW
75
                                      GetSize().y - (bottomSliderPos + button_height))))
×
76
        {
77
            // Clicked below slider -> Move half a slider height down
78
            sliderPos += sliderHeight / 2;
×
79

80
            if(sliderPos + sliderHeight > scroll_height)
×
81
            {
82
                RTTR_Assert(scroll_height > sliderHeight); // Otherwise the scrollbar should be hidden
×
83
                sliderPos = scroll_height - sliderHeight;
×
84
            }
85

86
            UpdatePosFromSlider();
×
87
            return true;
×
88
        }
89
    }
90

91
    return RelayMouseMessage(&Window::Msg_LeftDown, mc);
×
92
}
93

94
bool ctrlScrollBar::Msg_MouseMove(const MouseCoords& mc)
1✔
95
{
96
    if(isMouseScrolling)
1✔
97
    {
98
        const int moveDist = mc.pos.y - last_y;
×
99
        sliderPos += moveDist;
×
100
        if(sliderPos + sliderHeight > scroll_height)
×
101
            sliderPos = moveDist < 0 ? 0 : (scroll_height - sliderHeight);
×
102

103
        UpdatePosFromSlider();
×
104
    }
105
    last_y = mc.pos.y;
1✔
106

107
    // ButtonMessages weiterleiten
108
    return RelayMouseMessage(&Window::Msg_MouseMove, mc);
1✔
109
}
110

111
void ctrlScrollBar::Msg_ButtonClick(const unsigned ctrl_id)
×
112
{
113
    switch(ctrl_id)
×
114
    {
115
        case 0: // Upwards
×
116
            Scroll(-1);
×
117
            break;
×
118
        case 1: // Downwards
×
119
            Scroll(+1);
×
120
            break;
×
121
    }
122
}
×
123

124
/**
125
 *  setzt die Scroll-Position.
126
 */
127
void ctrlScrollBar::SetScrollPos(unsigned short scroll_pos)
2✔
128
{
129
    if(this->scroll_pos != scroll_pos)
2✔
130
    {
131
        this->scroll_pos = scroll_pos;
×
132
        UpdateSliderFromPos();
×
133
    }
134
}
2✔
135

136
/**
137
 *  setzt die Scroll-Höhe.
138
 */
139
void ctrlScrollBar::SetRange(unsigned short scroll_range)
310✔
140
{
141
    if(this->scroll_range != scroll_range)
310✔
142
    {
143
        this->scroll_range = scroll_range;
304✔
144
        RecalculateSizes();
304✔
145
    }
146
}
310✔
147

148
/**
149
 *  setzt die Seiten-Höhe.
150
 */
151
void ctrlScrollBar::SetPageSize(unsigned short pagesize)
348✔
152
{
153
    if(this->pagesize != pagesize)
348✔
154
    {
155
        this->pagesize = pagesize;
265✔
156
        RecalculateSizes();
265✔
157
    }
158
}
348✔
159

160
void ctrlScrollBar::Resize(const Extent& newSize)
420✔
161
{
162
    Window::Resize(newSize);
420✔
163

164
    // Up button
165
    Extent btSize = Extent(newSize.x, button_height);
420✔
166
    GetCtrl<ctrlButton>(0)->Resize(btSize);
420✔
167
    // Down button
168
    auto* downButton = GetCtrl<ctrlButton>(1);
420✔
169
    downButton->Resize(btSize);
420✔
170

171
    if(newSize.y >= button_height)
420✔
172
    {
173
        downButton->SetVisible(true);
230✔
174
        downButton->SetPos(DrawPoint(0, newSize.y - button_height));
230✔
175
    } else
176
        downButton->SetVisible(false);
190✔
177

178
    RecalculateSizes();
420✔
179
}
420✔
180

181
/**
182
 *  Zeichenmethode.
183
 *
184
 *  @return @p true bei Erfolg, @p false bei Fehler
185
 */
186
void ctrlScrollBar::Draw_()
×
187
{
188
    RTTR_Assert(scroll_range > pagesize); // Don't show unneccessary scrollbars, otherwise invariants might be violated.
×
189
    if(scroll_height == 0)
×
190
        return;
×
191
    DrawPoint pos = GetDrawPos();
×
192
    // Leiste
193
    Draw3D(Rect(pos + DrawPoint(0, button_height - 2), GetSize().x, GetSize().y - button_height * 2 + 4), tc, false);
×
194

195
    // Buttons
196
    Window::Draw_();
×
197

198
    // Scrollbar
199
    Draw3D(Rect(pos + DrawPoint(0, button_height + sliderPos), GetSize().x, sliderHeight), tc, true);
×
200
}
201

202
void ctrlScrollBar::UpdatePosFromSlider()
×
203
{
204
    RTTR_Assert(sliderPos + sliderHeight <= scroll_height); // Slider must be inside bar
×
205
    unsigned short newScrollPos = (sliderPos * scroll_range) / scroll_height;
×
206
    if(scroll_pos != newScrollPos)
×
207
    {
208
        RTTR_Assert(newScrollPos + pagesize <= scroll_range); // Probably slider to small?
×
209
        scroll_pos = newScrollPos;
×
210
        GetParent()->Msg_ScrollChange(GetID(), scroll_pos);
×
211
    }
212
}
×
213

214
void ctrlScrollBar::UpdateSliderFromPos()
545✔
215
{
216
    if(scroll_pos + pagesize >= scroll_range)
545✔
217
        sliderPos = scroll_height - sliderHeight;
×
218
    else
219
        sliderPos = (scroll_height * scroll_pos) / scroll_range;
545✔
220
}
545✔
221

222
/**
223
 *  berechnet die Werte für die Scrollbar.
224
 */
225
void ctrlScrollBar::RecalculateSizes()
989✔
226
{
227
    scroll_height = ((GetSize().y > 2u * button_height) ? GetSize().y - 2u * button_height : 0);
989✔
228

229
    if(scroll_range > pagesize)
989✔
230
    {
231
        sliderHeight = (scroll_height * pagesize) / scroll_range;
545✔
232

233
        UpdateSliderFromPos();
545✔
234

235
        if(!IsVisible())
545✔
236
        {
237
            SetVisible(true);
254✔
238
            GetParent()->Msg_ScrollShow(GetID(), IsVisible());
254✔
239
        }
240
    } else
241
    {
242
        scroll_pos = 0;
444✔
243

244
        // nicht nötig, Scrollleiste kann weg
245
        if(IsVisible())
444✔
246
        {
247
            SetVisible(false);
240✔
248
            GetParent()->Msg_ScrollShow(GetID(), IsVisible());
240✔
249
        }
250
    }
251
}
989✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc