317 lines
7.7 KiB
ActionScript
317 lines
7.7 KiB
ActionScript
import elements.BaseGuiElement;
|
|
import elements.GuiButton;
|
|
|
|
export ScrollOrientation, GuiScrollbar;
|
|
|
|
enum ScrollOrientation {
|
|
SO_Vertical,
|
|
SO_Horizontal,
|
|
};
|
|
|
|
class GuiScrollbar : BaseGuiElement {
|
|
bool Focused;
|
|
bool Dragging;
|
|
int Orientation;
|
|
vec2i DragFrom;
|
|
|
|
GuiButton@ up;
|
|
GuiButton@ down;
|
|
|
|
SkinStyle style;
|
|
SkinStyle handleStyle;
|
|
|
|
double start;
|
|
double end;
|
|
|
|
double page;
|
|
double scroll;
|
|
double pos;
|
|
double bar;
|
|
|
|
GuiScrollbar(IGuiElement@ ParentElement, const recti& Rectangle) {
|
|
super(ParentElement, Rectangle);
|
|
|
|
start = 0.0;
|
|
end = 1.0;
|
|
page = 0.0;
|
|
bar = 0.2;
|
|
|
|
pos = 0.5;
|
|
scroll = 40.0;
|
|
|
|
Focused = false;
|
|
Dragging = false;
|
|
|
|
@up = GuiButton(this, recti());
|
|
@down = GuiButton(this, recti());
|
|
|
|
Orientation = SO_Vertical;
|
|
updateAbsolutePosition();
|
|
}
|
|
|
|
void set_orientation(int orient) {
|
|
Orientation = orient;
|
|
|
|
if(orient == SO_Vertical) {
|
|
up.alignment.top.set(AS_Top, 0.0, 0);
|
|
up.alignment.left.set(AS_Left, 0.0, 0);
|
|
up.alignment.right.set(AS_Right, 0.0, 0);
|
|
up.alignment.bottom.set(AS_Top, 0.0, AbsolutePosition.width);
|
|
|
|
down.alignment.top.set(AS_Bottom, 0.0, AbsolutePosition.width);
|
|
down.alignment.left.set(AS_Left, 0.0, 0);
|
|
down.alignment.right.set(AS_Right, 0.0, 0);
|
|
down.alignment.bottom.set(AS_Bottom, 0.0, 0);
|
|
|
|
up.style = SS_ScrollUp;
|
|
down.style = SS_ScrollDown;
|
|
|
|
style = SS_ScrollVert;
|
|
handleStyle = SS_ScrollVertHandle;
|
|
}
|
|
else {
|
|
up.alignment.top.set(AS_Top, 0.0, 0);
|
|
up.alignment.left.set(AS_Left, 0.0, 0);
|
|
up.alignment.right.set(AS_Left, 0.0, AbsolutePosition.height);
|
|
up.alignment.bottom.set(AS_Bottom, 0.0, 0);
|
|
|
|
down.alignment.top.set(AS_Top, 0.0, 0);
|
|
down.alignment.left.set(AS_Right, 0.0, AbsolutePosition.height);
|
|
down.alignment.right.set(AS_Right, 0.0, 0);
|
|
down.alignment.bottom.set(AS_Bottom, 0.0, 0);
|
|
|
|
up.style = SS_ScrollLeft;
|
|
down.style = SS_ScrollRight;
|
|
|
|
style = SS_ScrollHoriz;
|
|
handleStyle = SS_ScrollHorizHandle;
|
|
}
|
|
|
|
up.updateAbsolutePosition();
|
|
down.updateAbsolutePosition();
|
|
}
|
|
|
|
int get_orientation() {
|
|
return Orientation;
|
|
}
|
|
|
|
void emitChange() {
|
|
GuiEvent evt;
|
|
evt.type = GUI_Changed;
|
|
@evt.caller = this;
|
|
onGuiEvent(evt);
|
|
}
|
|
|
|
bool onGuiEvent(const GuiEvent& event) {
|
|
if(event.caller is this) {
|
|
switch(event.type) {
|
|
case GUI_Focused:
|
|
Focused = true;
|
|
break;
|
|
case GUI_Focus_Lost:
|
|
Focused = false;
|
|
Dragging = false;
|
|
break;
|
|
}
|
|
}
|
|
else if(event.type == GUI_Clicked) {
|
|
if(event.caller is up) {
|
|
if(shiftKey)
|
|
pos = max(start, pos - page);
|
|
else
|
|
pos = max(start, pos - scroll);
|
|
emitChange();
|
|
}
|
|
else if(event.caller is down) {
|
|
if(shiftKey)
|
|
pos = min(end - page, pos + page);
|
|
else
|
|
pos = min(end - page, pos + scroll);
|
|
emitChange();
|
|
}
|
|
}
|
|
return BaseGuiElement::onGuiEvent(event);
|
|
}
|
|
|
|
bool onMouseEvent(const MouseEvent& event, IGuiElement@ source) {
|
|
if(source is this) {
|
|
vec2i mouse = vec2i(event.x, event.y);
|
|
|
|
switch(event.type) {
|
|
case MET_Button_Down: {
|
|
recti handlePos = getBarPosition();
|
|
vec2i offset = mouse - AbsolutePosition.topLeft;
|
|
Dragging = true;
|
|
DragFrom = mouse;
|
|
if(!handlePos.isWithin(offset)) {
|
|
pos = min(end - page, max(start, getOffsetPosition(offset)));
|
|
emitChange();
|
|
}
|
|
} return true;
|
|
case MET_Moved: {
|
|
if(Dragging) {
|
|
vec2i diff = mouse - DragFrom;
|
|
|
|
if(Orientation == SO_Vertical) {
|
|
int barSize = getBarPosition().height;
|
|
pos += double(diff.y) * (end - start - page) / double(AbsolutePosition.height - barSize - 2 * AbsolutePosition.width);
|
|
}
|
|
else {
|
|
int barSize = getBarPosition().width;
|
|
pos += double(diff.x) * (end - start - page) / double(AbsolutePosition.width - barSize - 2 * AbsolutePosition.height);
|
|
}
|
|
|
|
if(pos < start)
|
|
pos = start;
|
|
else if(pos > end)
|
|
pos = end;
|
|
|
|
DragFrom = vec2i(clamp(mouse.x, AbsolutePosition.topLeft.x+size.height, AbsolutePosition.botRight.x-size.height),
|
|
clamp(mouse.y, AbsolutePosition.topLeft.y+size.width, AbsolutePosition.botRight.y-size.width));
|
|
emitChange();
|
|
return true;
|
|
}
|
|
} break;
|
|
case MET_Button_Up:
|
|
if(Focused) {
|
|
Dragging = false;
|
|
return true;
|
|
}
|
|
break;
|
|
case MET_Scrolled:
|
|
pos = min(max(end - page, start), max(start, pos + double(-event.y) * scroll));
|
|
emitChange();
|
|
return true;
|
|
}
|
|
}
|
|
return BaseGuiElement::onMouseEvent(event, source);
|
|
}
|
|
|
|
bool onKeyEvent(const KeyboardEvent& event, IGuiElement@ source) {
|
|
switch(event.type) {
|
|
case KET_Key_Down:
|
|
switch(event.key) {
|
|
case KEY_LEFT:
|
|
case KEY_UP:
|
|
pos = max(start, pos - scroll);
|
|
emitChange();
|
|
break;
|
|
case KEY_RIGHT:
|
|
case KEY_DOWN:
|
|
pos = min(end - page, pos + scroll);
|
|
emitChange();
|
|
break;
|
|
case KEY_PAGEUP:
|
|
pos = max(start, pos - page);
|
|
emitChange();
|
|
break;
|
|
case KEY_PAGEDOWN:
|
|
pos = min(end - page, pos + page);
|
|
emitChange();
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return BaseGuiElement::onKeyEvent(event, source);
|
|
}
|
|
|
|
void updateAbsolutePosition() {
|
|
BaseGuiElement::updateAbsolutePosition();
|
|
orientation = Orientation;
|
|
}
|
|
|
|
double getOffsetPosition(vec2i offset) {
|
|
double range = end - start;
|
|
|
|
if(range < page || range <= 0.0)
|
|
return start;
|
|
|
|
if(Orientation == SO_Vertical) {
|
|
int buttonsize = AbsolutePosition.width;
|
|
int space = AbsolutePosition.height - buttonsize * 2;
|
|
int barsize = max(int(space * (bar / range)), 16);
|
|
|
|
return (double(offset.y - barsize - buttonsize) / double(space - barsize)) * range + start;
|
|
}
|
|
else {
|
|
int buttonsize = AbsolutePosition.height;
|
|
int space = AbsolutePosition.width - buttonsize * 2;
|
|
int barsize = max(int(space * (bar / range)), 16);
|
|
|
|
return (double(offset.x - barsize - buttonsize) / double(space - barsize)) * range + start;
|
|
}
|
|
}
|
|
|
|
recti getBarPosition() {
|
|
//Initial scrollbar space
|
|
double range = end - start;
|
|
|
|
if(range <= page || range <= 0.0)
|
|
return recti();
|
|
|
|
if(Orientation == SO_Vertical) {
|
|
int buttonsize = AbsolutePosition.width;
|
|
int space = AbsolutePosition.height - buttonsize * 2;
|
|
|
|
//Remove space for bar
|
|
int barsize = max(int(space * (bar / range)), 16);
|
|
space -= barsize;
|
|
|
|
//Draw bar at correct position
|
|
int barpos = ((pos - start) / (range - page)) * space;
|
|
vec2i barcoord = vec2i(0, barpos + buttonsize);
|
|
|
|
return recti(barcoord, barcoord + vec2i(AbsolutePosition.width, barsize));
|
|
}
|
|
else {
|
|
int buttonsize = AbsolutePosition.height;
|
|
int space = AbsolutePosition.width - buttonsize * 2;
|
|
|
|
//Remove space for bar
|
|
int barsize = max(int(space * (bar / range)), 16);
|
|
space -= barsize;
|
|
|
|
//Draw bar at correct position
|
|
int barpos = ((pos - start) / (range - page)) * space;
|
|
vec2i barcoord = vec2i(barpos + buttonsize, 0);
|
|
|
|
return recti(barcoord, barcoord + vec2i(barsize, AbsolutePosition.height));
|
|
}
|
|
}
|
|
|
|
void draw() {
|
|
recti barPos = getBarPosition() + AbsolutePosition.topLeft;
|
|
recti bgPos;
|
|
|
|
bool enabled = (end - start > page);
|
|
|
|
uint handleFlags = SF_Normal;
|
|
uint flags = SF_Normal;
|
|
|
|
if(!enabled)
|
|
flags |= SF_Disabled;
|
|
if(Dragging)
|
|
handleFlags |= SF_Active;
|
|
if(barPos.isWithin(mousePos))
|
|
handleFlags |= SF_Hovered;
|
|
|
|
if(Orientation == SO_Vertical) {
|
|
bgPos = recti(AbsolutePosition.topLeft + vec2i(0, AbsolutePosition.width),
|
|
AbsolutePosition.botRight - vec2i(0, AbsolutePosition.width));
|
|
}
|
|
else {
|
|
bgPos = recti(AbsolutePosition.topLeft + vec2i(AbsolutePosition.height, 0),
|
|
AbsolutePosition.botRight - vec2i(AbsolutePosition.height, 0));
|
|
}
|
|
|
|
skin.draw(style, flags, bgPos);
|
|
|
|
if(enabled)
|
|
skin.draw(handleStyle, handleFlags, barPos);
|
|
up.disabled = !enabled;
|
|
down.disabled = !enabled;
|
|
|
|
BaseGuiElement::draw();
|
|
}
|
|
};
|