New alternate scrollbar style, used by default in dialogs
This commit is contained in:
@@ -153,6 +153,14 @@ rectangle_size_delegate rectangle::height() {
|
||||
return rectangle_size_delegate(*this, &rectangle::top, &rectangle::bottom);
|
||||
}
|
||||
|
||||
const rectangle_size_delegate rectangle::width() const {
|
||||
return rectangle_size_delegate(*const_cast<rectangle*>(this), &rectangle::left, &rectangle::right);
|
||||
}
|
||||
|
||||
const rectangle_size_delegate rectangle::height() const {
|
||||
return rectangle_size_delegate(*const_cast<rectangle*>(this), &rectangle::top, &rectangle::bottom);
|
||||
}
|
||||
|
||||
location rectangle::centre() {
|
||||
return location((left + right) / 2, (top + bottom) / 2);
|
||||
}
|
||||
|
@@ -67,6 +67,8 @@ struct rectangle {
|
||||
rectangle(sf::Vector2<T> size) : rectangle(0, 0, size.y, size.x) {}
|
||||
rectangle_size_delegate width();
|
||||
rectangle_size_delegate height();
|
||||
const rectangle_size_delegate width() const;
|
||||
const rectangle_size_delegate height() const;
|
||||
location centre();
|
||||
location topLeft();
|
||||
location topRight();
|
||||
|
@@ -11,14 +11,15 @@
|
||||
#include "graphtool.hpp"
|
||||
#include "mathutil.hpp"
|
||||
|
||||
sf::Texture cScrollbar::scroll_gw;
|
||||
sf::Texture cScrollbar::scroll_gw[NUM_STYLES];
|
||||
|
||||
cScrollbar::cScrollbar(cDialog& parent) : cControl(CTRL_SCROLL, parent), pos(0), max(0), pgsz(10) {}
|
||||
|
||||
cScrollbar::cScrollbar(sf::RenderWindow& parent) : cControl(CTRL_SCROLL, parent), pos(0), max(0), pgsz(10) {}
|
||||
|
||||
void cScrollbar::init() {
|
||||
scroll_gw.loadFromImage(*ResMgr::get<ImageRsrc>("dlogscroll"));
|
||||
scroll_gw[0].loadFromImage(*ResMgr::get<ImageRsrc>("dlogscrollwh"));
|
||||
scroll_gw[1].loadFromImage(*ResMgr::get<ImageRsrc>("dlogscrollled"));
|
||||
}
|
||||
|
||||
bool cScrollbar::isClickable(){
|
||||
@@ -46,6 +47,10 @@ void cScrollbar::setLink(std::string l) {
|
||||
link = l;
|
||||
}
|
||||
|
||||
void cScrollbar::setStyle(eScrollStyle newStyle) {
|
||||
style = newStyle;
|
||||
}
|
||||
|
||||
long cScrollbar::getPosition() {
|
||||
return pos;
|
||||
}
|
||||
@@ -66,6 +71,10 @@ std::string cScrollbar::getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
eScrollStyle cScrollbar::getStyle() {
|
||||
return style;
|
||||
}
|
||||
|
||||
void cScrollbar::attachClickHandler(click_callback_t f) throw(xHandlerNotSupported) {
|
||||
onClick = f;
|
||||
}
|
||||
@@ -85,7 +94,7 @@ bool cScrollbar::handleClick(location where) {
|
||||
sf::Event e;
|
||||
bool done = false, clicked = false;
|
||||
depressed = true;
|
||||
int btn_size = 16;
|
||||
int btn_size = vert ? up_rect[style][VERT].height() : up_rect[style][HORZ].width();
|
||||
int total_bar_size = vert ? frame.height() : frame.width();
|
||||
int bar_start = vert ? frame.top : frame.left;
|
||||
int bar_end = vert ? frame.bottom : frame.right;
|
||||
@@ -171,42 +180,41 @@ sf::Color cScrollbar::getColour() throw(xUnsupportedProp) {
|
||||
return sf::Color();
|
||||
}
|
||||
|
||||
// Constants to index the rect arrays
|
||||
enum {
|
||||
VERT, VERT_PRESSED, HORZ, HORZ_PRESSED
|
||||
const rectangle cScrollbar::up_rect[NUM_STYLES][4] = {
|
||||
{{0,0,16,16}, {16,0,32,16}, {32,0,48,16}, {48,0,64,16}},
|
||||
{{0,0,10,14}, {10,0,20,14}, {20,0,34,10}, {34,0,48,10}},
|
||||
};
|
||||
|
||||
const rectangle cScrollbar::up_rect[4] = {
|
||||
{0,0,16,16}, {16,0,32,16}, {32,0,48,16}, {48,0,64,16}
|
||||
const rectangle cScrollbar::down_rect[NUM_STYLES][4] = {
|
||||
{{0,16,16,32}, {16,16,32,32}, {32,16,48,32}, {48,16,64,32}},
|
||||
{{0,14,10,28}, {10,14,20,28}, {20,10,34,20}, {34,10,48,20}},
|
||||
};
|
||||
const rectangle cScrollbar::down_rect[4] = {
|
||||
{0,16,16,32}, {16,16,32,32}, {32,16,48,32}, {48,16,64,32}
|
||||
const rectangle cScrollbar::thumb_rect[NUM_STYLES][4] = {
|
||||
{{0,32,16,48}, {16,32,32,48}, {32,32,48,48}, {48,32,64,48}},
|
||||
{{0,28,10,42}, {10,28,20,42}, {20,20,34,30}, {34,20,48,30}},
|
||||
};
|
||||
const rectangle cScrollbar::thumb_rect[4] = {
|
||||
{0,32,16,48}, {16,32,32,48}, {32,32,48,48}, {48,32,64,48}
|
||||
};
|
||||
const rectangle cScrollbar::bar_rect[4] = {
|
||||
{0,48,16,64}, {16,48,32,64}, {32,48,48,64}, {48,48,64,64}
|
||||
const rectangle cScrollbar::bar_rect[NUM_STYLES][4] = {
|
||||
{{0,48,16,64}, {16,48,32,64}, {32,48,48,64}, {48,48,64,64}},
|
||||
{{0,42,10,56}, {10,42,20,56}, {20,30,34,40}, {34,30,48,40}},
|
||||
};
|
||||
|
||||
void cScrollbar::draw_horizontal() {
|
||||
int btn_size = 16;
|
||||
int btn_size = up_rect[style][HORZ].width();
|
||||
int bar_width = frame.width() - btn_size * 2;
|
||||
inWindow->setActive();
|
||||
rectangle draw_rect = frame, from_rect = up_rect[HORZ];
|
||||
rectangle draw_rect = frame, from_rect = up_rect[style][HORZ];
|
||||
draw_rect.width() = btn_size;
|
||||
if(depressed && pressedPart == PART_UP)
|
||||
from_rect = up_rect[HORZ_PRESSED];
|
||||
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
||||
from_rect = up_rect[style][HORZ_PRESSED];
|
||||
rect_draw_some_item(scroll_gw[style], from_rect, *inWindow, draw_rect);
|
||||
if(pos > 0) {
|
||||
from_rect = bar_rect[HORZ];
|
||||
from_rect = bar_rect[style][HORZ];
|
||||
int left = draw_rect.right, width = pos * (bar_width - btn_size) / max;
|
||||
if(depressed && pressedPart == PART_PGUP)
|
||||
from_rect = bar_rect[HORZ_PRESSED];
|
||||
from_rect = bar_rect[style][HORZ_PRESSED];
|
||||
draw_rect.left = left;
|
||||
while(draw_rect.left - left < width) {
|
||||
draw_rect.right = draw_rect.left + btn_size;
|
||||
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
||||
rect_draw_some_item(scroll_gw[style], from_rect, *inWindow, draw_rect);
|
||||
draw_rect.left = draw_rect.right;
|
||||
}
|
||||
draw_rect.right = left + width;
|
||||
@@ -214,50 +222,50 @@ void cScrollbar::draw_horizontal() {
|
||||
if(max > 0) {
|
||||
draw_rect.left = draw_rect.right;
|
||||
draw_rect.width() = btn_size;
|
||||
from_rect = thumb_rect[HORZ];
|
||||
from_rect = thumb_rect[style][HORZ];
|
||||
if(depressed && pressedPart == PART_THUMB)
|
||||
from_rect = thumb_rect[HORZ_PRESSED];
|
||||
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
||||
from_rect = thumb_rect[style][HORZ_PRESSED];
|
||||
rect_draw_some_item(scroll_gw[style], from_rect, *inWindow, draw_rect);
|
||||
}
|
||||
if(pos < max || max == 0) {
|
||||
from_rect = bar_rect[HORZ];
|
||||
from_rect = bar_rect[style][HORZ];
|
||||
int left = draw_rect.right, right = frame.right - btn_size;
|
||||
if(depressed && pressedPart == PART_PGDN)
|
||||
from_rect = bar_rect[HORZ_PRESSED];
|
||||
from_rect = bar_rect[style][HORZ_PRESSED];
|
||||
draw_rect.left = left;
|
||||
while(draw_rect.left < right) {
|
||||
draw_rect.right = draw_rect.left + btn_size;
|
||||
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
||||
rect_draw_some_item(scroll_gw[style], from_rect, *inWindow, draw_rect);
|
||||
draw_rect.left = draw_rect.right;
|
||||
}
|
||||
draw_rect.right = right;
|
||||
}
|
||||
draw_rect = frame;
|
||||
draw_rect.left = draw_rect.right - btn_size;
|
||||
from_rect = down_rect[HORZ];
|
||||
from_rect = down_rect[style][HORZ];
|
||||
if(depressed && pressedPart == PART_DOWN)
|
||||
from_rect = down_rect[HORZ_PRESSED];
|
||||
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
||||
from_rect = down_rect[style][HORZ_PRESSED];
|
||||
rect_draw_some_item(scroll_gw[style], from_rect, *inWindow, draw_rect);
|
||||
}
|
||||
|
||||
void cScrollbar::draw_vertical() {
|
||||
int btn_size = 16;
|
||||
int btn_size = up_rect[style][VERT].height();
|
||||
int bar_height = frame.height() - btn_size * 2;
|
||||
inWindow->setActive();
|
||||
rectangle draw_rect = frame, from_rect = up_rect[VERT];
|
||||
rectangle draw_rect = frame, from_rect = up_rect[style][VERT];
|
||||
draw_rect.height() = btn_size;
|
||||
if(depressed && pressedPart == PART_UP)
|
||||
from_rect = up_rect[VERT_PRESSED];
|
||||
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
||||
from_rect = up_rect[style][VERT_PRESSED];
|
||||
rect_draw_some_item(scroll_gw[style], from_rect, *inWindow, draw_rect);
|
||||
if(pos > 0) {
|
||||
from_rect = bar_rect[VERT];
|
||||
from_rect = bar_rect[style][VERT];
|
||||
int top = draw_rect.bottom, height = pos * (bar_height - btn_size) / max;
|
||||
if(depressed && pressedPart == PART_PGUP)
|
||||
from_rect = bar_rect[VERT_PRESSED];
|
||||
from_rect = bar_rect[style][VERT_PRESSED];
|
||||
draw_rect.top = top;
|
||||
while(draw_rect.top - top < height) {
|
||||
draw_rect.bottom = draw_rect.top + btn_size;
|
||||
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
||||
rect_draw_some_item(scroll_gw[style], from_rect, *inWindow, draw_rect);
|
||||
draw_rect.top = draw_rect.bottom;
|
||||
}
|
||||
draw_rect.bottom = top + height;
|
||||
@@ -265,30 +273,30 @@ void cScrollbar::draw_vertical() {
|
||||
if(max > 0) {
|
||||
draw_rect.top = draw_rect.bottom;
|
||||
draw_rect.height() = btn_size;
|
||||
from_rect = thumb_rect[VERT];
|
||||
from_rect = thumb_rect[style][VERT];
|
||||
if(depressed && pressedPart == PART_THUMB)
|
||||
from_rect = thumb_rect[VERT_PRESSED];
|
||||
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
||||
from_rect = thumb_rect[style][VERT_PRESSED];
|
||||
rect_draw_some_item(scroll_gw[style], from_rect, *inWindow, draw_rect);
|
||||
}
|
||||
if(pos < max || max == 0) {
|
||||
from_rect = bar_rect[VERT];
|
||||
from_rect = bar_rect[style][VERT];
|
||||
int top = draw_rect.bottom, bottom = frame.bottom - btn_size;
|
||||
if(depressed && pressedPart == PART_PGDN)
|
||||
from_rect = bar_rect[VERT_PRESSED];
|
||||
from_rect = bar_rect[style][VERT_PRESSED];
|
||||
draw_rect.top = top;
|
||||
while(draw_rect.top < bottom) {
|
||||
draw_rect.bottom = draw_rect.top + btn_size;
|
||||
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
||||
rect_draw_some_item(scroll_gw[style], from_rect, *inWindow, draw_rect);
|
||||
draw_rect.top = draw_rect.bottom;
|
||||
}
|
||||
draw_rect.bottom = bottom;
|
||||
}
|
||||
draw_rect = frame;
|
||||
draw_rect.top = draw_rect.bottom - btn_size;
|
||||
from_rect = down_rect[VERT];
|
||||
from_rect = down_rect[style][VERT];
|
||||
if(depressed && pressedPart == PART_DOWN)
|
||||
from_rect = down_rect[VERT_PRESSED];
|
||||
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
||||
from_rect = down_rect[style][VERT_PRESSED];
|
||||
rect_draw_some_item(scroll_gw[style], from_rect, *inWindow, draw_rect);
|
||||
}
|
||||
|
||||
void cScrollbar::draw() {
|
||||
@@ -305,6 +313,7 @@ std::string cScrollbar::parse(ticpp::Element& who, std::string fname) {
|
||||
bool foundVertical = false;
|
||||
rectangle frame;
|
||||
int width = 0, height = 0;
|
||||
style = SCROLL_LED; // Dialog scrollbars have a different default.
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
@@ -315,6 +324,12 @@ std::string cScrollbar::parse(ticpp::Element& who, std::string fname) {
|
||||
if(val == "true") vert = true;
|
||||
else vert = false;
|
||||
foundVertical = true;
|
||||
}else if(name == "style"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "white") style = SCROLL_WHITE;
|
||||
else if(val == "led") style = SCROLL_LED;
|
||||
else throw xBadVal("slider", name, val, attr->Row(), attr->Column(), fname);
|
||||
}else if(name == "link"){
|
||||
attr->GetValue(&link);
|
||||
}else if(name == "initial"){
|
||||
@@ -338,7 +353,7 @@ std::string cScrollbar::parse(ticpp::Element& who, std::string fname) {
|
||||
if(!foundTop) throw xMissingAttr("slider","top",who.Row(),who.Column(),fname);
|
||||
if(!foundLeft) throw xMissingAttr("slider","left",who.Row(),who.Column(),fname);
|
||||
if(pos > max) throw xBadAttr("slider","initial",who.Row(),who.Column(),fname);
|
||||
int thickness = 16;
|
||||
int thickness = vert ? up_rect[style][VERT].width() : up_rect[style][HORZ].height();
|
||||
if(width > 0) {
|
||||
frame.right = frame.left + width;
|
||||
if(height == 0 && !foundVertical)
|
||||
|
@@ -15,6 +15,12 @@
|
||||
#include "control.hpp"
|
||||
#include "graphtool.hpp"
|
||||
|
||||
/// Specifies the style of a scrollbar.
|
||||
enum eScrollStyle {
|
||||
SCROLL_WHITE, ///< The white scrollbar, matching the help and PC buttons.
|
||||
SCROLL_LED, ///< A dark scrollbar matching the LEDs and dialog buttons
|
||||
};
|
||||
|
||||
/// A simple vertical scrollbar.
|
||||
/// This has no coupling with scrollable data; that must be handled externally by
|
||||
/// using the methods to get the scrollbar's position.
|
||||
@@ -22,6 +28,12 @@
|
||||
class cScrollbar : public cControl {
|
||||
int pos, max, pgsz;
|
||||
std::string link;
|
||||
// Make sure this is equal to the number of constants in eScrollStyle
|
||||
static const int NUM_STYLES = 2;
|
||||
// Constants to index the rect arrays
|
||||
enum {
|
||||
VERT, VERT_PRESSED, HORZ, HORZ_PRESSED
|
||||
};
|
||||
// Note: For horizontal scrollbars, up is left and down is right.
|
||||
enum {
|
||||
PART_UP,
|
||||
@@ -30,10 +42,11 @@ class cScrollbar : public cControl {
|
||||
PART_PGDN,
|
||||
PART_DOWN,
|
||||
} pressedPart;
|
||||
eScrollStyle style = SCROLL_WHITE;
|
||||
bool vert = true;
|
||||
click_callback_t onClick;
|
||||
static sf::Texture scroll_gw;
|
||||
static const rectangle up_rect[4], down_rect[4], bar_rect[4], thumb_rect[4];
|
||||
static sf::Texture scroll_gw[NUM_STYLES];
|
||||
static const rectangle up_rect[NUM_STYLES][4], down_rect[NUM_STYLES][4], bar_rect[NUM_STYLES][4], thumb_rect[NUM_STYLES][4];
|
||||
void draw_vertical(), draw_horizontal();
|
||||
public:
|
||||
/// @copydoc cDialog::init()
|
||||
@@ -77,6 +90,9 @@ public:
|
||||
/// value as its text.
|
||||
/// @return The ID of the linked control, or an empty string if none.
|
||||
std::string getLink();
|
||||
/// Get the scrollbar style.
|
||||
/// @return The style
|
||||
eScrollStyle getStyle();
|
||||
/// Set the scrollbar thumb's current position.
|
||||
/// @param to The new position.
|
||||
void setPosition(long to);
|
||||
@@ -98,6 +114,9 @@ public:
|
||||
/// value as its text.
|
||||
/// @param l The ID of the linked control, or an empty string if none.
|
||||
void setLink(std::string l);
|
||||
/// Set the scrollbar style.
|
||||
/// @param newStyle The new style.
|
||||
void setStyle(eScrollStyle newStyle);
|
||||
void draw();
|
||||
cScrollbar& operator=(cScrollbar& other) = delete;
|
||||
cScrollbar(cScrollbar& other) = delete;
|
||||
|
@@ -126,6 +126,14 @@ void cScrollPane::setPosition(long to) {
|
||||
scroll.setPosition(to);
|
||||
}
|
||||
|
||||
eScrollStyle cScrollPane::getStyle() {
|
||||
return scroll.getStyle();
|
||||
}
|
||||
|
||||
void cScrollPane::setStyle(eScrollStyle style) {
|
||||
scroll.setStyle(style);
|
||||
}
|
||||
|
||||
bool cScrollPane::hasChild(std::string id) {
|
||||
return contents.find(id) != contents.end();
|
||||
}
|
||||
@@ -166,6 +174,7 @@ std::string cScrollPane::parse(ticpp::Element& who, std::string fname) {
|
||||
rectangle frame;
|
||||
int width = 0, height = 0;
|
||||
bool foundTop = false, foundLeft = false;
|
||||
scroll.setStyle(SCROLL_LED);
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++) {
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
@@ -183,6 +192,12 @@ std::string cScrollPane::parse(ticpp::Element& who, std::string fname) {
|
||||
attr->GetValue(&val);
|
||||
if(val == "true") setFormat(TXT_FRAME, true);
|
||||
else setFormat(TXT_FRAME, false);
|
||||
}else if(name == "style"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "white") setStyle(SCROLL_WHITE);
|
||||
else if(val == "led") setStyle(SCROLL_LED);
|
||||
else throw xBadVal("slider", name, val, attr->Row(), attr->Column(), fname);
|
||||
} else throw xBadAttr("pane",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
if(!foundTop) throw xMissingAttr("pane","top",who.Row(),who.Column(),fname);
|
||||
|
@@ -54,6 +54,12 @@ public:
|
||||
/// Set the pane's current scroll position.
|
||||
/// @param to The new position.
|
||||
void setPosition(long to);
|
||||
/// Get the scrollbar style.
|
||||
/// @return The style
|
||||
eScrollStyle getStyle();
|
||||
/// Set the scrollbar style.
|
||||
/// @param newStyle The new style.
|
||||
void setStyle(eScrollStyle newStyle);
|
||||
void draw();
|
||||
cScrollPane& operator=(cScrollPane& other) = delete;
|
||||
cScrollPane(cScrollPane& other) = delete;
|
||||
|
@@ -212,6 +212,8 @@ The `<slider>` tag defines a slider control (presented with a scrollbar).
|
||||
|
||||
The `<slider>` tag accepts the following attributes:
|
||||
|
||||
* `style` - Specifies the slider style. Can be either `white` or `led`;
|
||||
defaults to `led`.
|
||||
* `vertical` - Specifies whether the slider should be shown horizontally
|
||||
or vertically. Usually defaults to true, but if `width` is provided and
|
||||
`height` is not, then it will default to false.
|
||||
@@ -245,6 +247,7 @@ The `<pane>` tag accepts the following attributes:
|
||||
|
||||
* `framed` - Specifies whether a frame is drawn around the pane. Can
|
||||
be either `true` or `false`; defaults to `true`.
|
||||
* `style` - Same as for `<slider>`, see above. Applies to the pane's scrollbar.
|
||||
|
||||
Keyboard Shortcuts
|
||||
------------------
|
||||
|
Reference in New Issue
Block a user