Skip to content

Commit 05e79c3

Browse files
committed
Slider: Add tick position property and tick offset theme item
Allow ticks to be placed at the top, bottom, or center with custom offset.
1 parent 9e02194 commit 05e79c3

File tree

6 files changed

+97
-4
lines changed

6 files changed

+97
-4
lines changed

doc/classes/Slider.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
<member name="ticks_on_borders" type="bool" setter="set_ticks_on_borders" getter="get_ticks_on_borders" default="false">
2424
If [code]true[/code], the slider will display ticks for minimum and maximum values.
2525
</member>
26+
<member name="ticks_position" type="int" setter="set_ticks_position" getter="get_ticks_position" enum="Slider.TickPosition" default="0">
27+
Sets the position of the ticks. See [enum TickPosition] for details.
28+
</member>
2629
</members>
2730
<signals>
2831
<signal name="drag_ended">
@@ -37,13 +40,30 @@
3740
</description>
3841
</signal>
3942
</signals>
43+
<constants>
44+
<constant name="BOTTOM_RIGHT" value="0" enum="TickPosition">
45+
Places the ticks at the bottom of the [HSlider], or right of the [VSlider].
46+
</constant>
47+
<constant name="TOP_LEFT" value="1" enum="TickPosition">
48+
Places the ticks at the top of the [HSlider], or left of the [VSlider].
49+
</constant>
50+
<constant name="BOTH" value="2" enum="TickPosition">
51+
Places the ticks at the both sides of the slider.
52+
</constant>
53+
<constant name="CENTER" value="3" enum="TickPosition">
54+
Places the ticks at the center of the slider.
55+
</constant>
56+
</constants>
4057
<theme_items>
4158
<theme_item name="center_grabber" data_type="constant" type="int" default="0">
4259
Boolean constant. If [code]1[/code], the grabber texture size will be ignored and it will fit within slider's bounds based only on its center position.
4360
</theme_item>
4461
<theme_item name="grabber_offset" data_type="constant" type="int" default="0">
4562
Vertical or horizontal offset of the grabber.
4663
</theme_item>
64+
<theme_item name="tick_offset" data_type="constant" type="int" default="0">
65+
Vertical or horizontal offset of the ticks. The offset is reversed for top or left ticks.
66+
</theme_item>
4767
<theme_item name="grabber" data_type="icon" type="Texture2D">
4868
The texture for the grabber (the draggable element).
4969
</theme_item>

scene/gui/slider.cpp

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,19 @@ void Slider::_notification(int p_what) {
308308
continue;
309309
}
310310
int ofs = (i * areasize / (ticks - 1)) + grabber_offset - grabber_shift;
311-
tick->draw(ci, Point2i((size.width - widget_width) / 2, ofs));
311+
312+
if (ticks_position == BOTTOM_RIGHT || ticks_position == BOTH) {
313+
tick->draw(ci, Point2i(widget_width + (size.width - widget_width) / 2 + theme_cache.tick_offset, ofs));
314+
}
315+
316+
if (ticks_position == TOP_LEFT || ticks_position == BOTH) {
317+
Point2i pos = Point2i((size.width - widget_width) / 2 - tick->get_width() - theme_cache.tick_offset, ofs);
318+
tick->draw_rect(ci, Rect2i(pos, Size2i(-tick->get_width(), tick->get_height())));
319+
}
320+
321+
if (ticks_position == CENTER) {
322+
tick->draw(ci, Point2i((size.width - tick->get_width()) / 2 + theme_cache.tick_offset, ofs));
323+
}
312324
}
313325
}
314326
grabber->draw(ci, Point2i(size.width / 2 - grabber->get_width() / 2 + theme_cache.grabber_offset, size.height - ratio * areasize - grabber->get_height() + grabber_shift));
@@ -333,7 +345,19 @@ void Slider::_notification(int p_what) {
333345
continue;
334346
}
335347
int ofs = (i * areasize / (ticks - 1)) + grabber_offset + grabber_shift;
336-
tick->draw(ci, Point2i(ofs, (size.height - widget_height) / 2));
348+
349+
if (ticks_position == BOTTOM_RIGHT || ticks_position == BOTH) {
350+
tick->draw(ci, Point2i(ofs, widget_height + (size.height - widget_height) / 2 + theme_cache.tick_offset));
351+
}
352+
353+
if (ticks_position == TOP_LEFT || ticks_position == BOTH) {
354+
Point2i pos = Point2i(ofs, (size.height - widget_height) / 2 - tick->get_height() - theme_cache.tick_offset);
355+
tick->draw_rect(ci, Rect2i(pos, Size2i(tick->get_width(), -tick->get_height())));
356+
}
357+
358+
if (ticks_position == CENTER) {
359+
tick->draw(ci, Point2i(ofs, (size.height - tick->get_height()) / 2 + theme_cache.tick_offset));
360+
}
337361
}
338362
}
339363
grabber->draw(ci, Point2i((rtl ? 1 - ratio : ratio) * areasize + grabber_shift, size.height / 2 - grabber->get_height() / 2 + theme_cache.grabber_offset));
@@ -342,6 +366,12 @@ void Slider::_notification(int p_what) {
342366
}
343367
}
344368

369+
void Slider::_validate_property(PropertyInfo &p_property) const {
370+
if (p_property.name == "ticks_position") {
371+
p_property.hint_string = orientation == VERTICAL ? "Right,Left,Both,Center" : "Bottom,Top,Both,Center";
372+
}
373+
}
374+
345375
void Slider::set_custom_step(double p_custom_step) {
346376
custom_step = p_custom_step;
347377
}
@@ -367,6 +397,10 @@ bool Slider::get_ticks_on_borders() const {
367397
return ticks_on_borders;
368398
}
369399

400+
Slider::TickPosition Slider::get_ticks_position() const {
401+
return ticks_position;
402+
}
403+
370404
void Slider::set_ticks_on_borders(bool _tob) {
371405
if (ticks_on_borders == _tob) {
372406
return;
@@ -376,6 +410,15 @@ void Slider::set_ticks_on_borders(bool _tob) {
376410
queue_redraw();
377411
}
378412

413+
void Slider::set_ticks_position(TickPosition p_ticks_position) {
414+
if (ticks_position == p_ticks_position) {
415+
return;
416+
}
417+
418+
ticks_position = p_ticks_position;
419+
queue_redraw();
420+
}
421+
379422
void Slider::set_editable(bool p_editable) {
380423
if (editable == p_editable) {
381424
return;
@@ -405,6 +448,9 @@ void Slider::_bind_methods() {
405448
ClassDB::bind_method(D_METHOD("get_ticks_on_borders"), &Slider::get_ticks_on_borders);
406449
ClassDB::bind_method(D_METHOD("set_ticks_on_borders", "ticks_on_border"), &Slider::set_ticks_on_borders);
407450

451+
ClassDB::bind_method(D_METHOD("get_ticks_position"), &Slider::get_ticks_position);
452+
ClassDB::bind_method(D_METHOD("set_ticks_position", "ticks_on_border"), &Slider::set_ticks_position);
453+
408454
ClassDB::bind_method(D_METHOD("set_editable", "editable"), &Slider::set_editable);
409455
ClassDB::bind_method(D_METHOD("is_editable"), &Slider::is_editable);
410456
ClassDB::bind_method(D_METHOD("set_scrollable", "scrollable"), &Slider::set_scrollable);
@@ -417,6 +463,12 @@ void Slider::_bind_methods() {
417463
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrollable"), "set_scrollable", "is_scrollable");
418464
ADD_PROPERTY(PropertyInfo(Variant::INT, "tick_count", PROPERTY_HINT_RANGE, "0,4096,1"), "set_ticks", "get_ticks");
419465
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ticks_on_borders"), "set_ticks_on_borders", "get_ticks_on_borders");
466+
ADD_PROPERTY(PropertyInfo(Variant::INT, "ticks_position", PROPERTY_HINT_ENUM), "set_ticks_position", "get_ticks_position");
467+
468+
BIND_ENUM_CONSTANT(BOTTOM_RIGHT);
469+
BIND_ENUM_CONSTANT(TOP_LEFT);
470+
BIND_ENUM_CONSTANT(BOTH);
471+
BIND_ENUM_CONSTANT(CENTER);
420472

421473
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Slider, slider_style, "slider");
422474
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Slider, grabber_area_style, "grabber_area");
@@ -429,6 +481,7 @@ void Slider::_bind_methods() {
429481

430482
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Slider, center_grabber);
431483
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Slider, grabber_offset);
484+
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Slider, tick_offset);
432485
}
433486

434487
Slider::Slider(Orientation p_orientation) {

scene/gui/slider.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@
3535
class Slider : public Range {
3636
GDCLASS(Slider, Range);
3737

38+
public:
39+
enum TickPosition {
40+
BOTTOM_RIGHT,
41+
TOP_LEFT,
42+
BOTH,
43+
CENTER,
44+
};
45+
46+
private:
3847
struct Grab {
3948
int pos = 0;
4049
double uvalue = 0.0; // Value at `pos`.
@@ -43,6 +52,8 @@ class Slider : public Range {
4352
} grab;
4453

4554
int ticks = 0;
55+
TickPosition ticks_position = BOTTOM_RIGHT;
56+
4657
bool mouse_inside = false;
4758
Orientation orientation;
4859
double custom_step = -1.0;
@@ -65,13 +76,15 @@ class Slider : public Range {
6576

6677
bool center_grabber = false;
6778
int grabber_offset = 0;
79+
int tick_offset = 0;
6880
} theme_cache;
6981

7082
protected:
7183
bool ticks_on_borders = false;
7284

7385
virtual void gui_input(const Ref<InputEvent> &p_event) override;
7486
void _notification(int p_what);
87+
void _validate_property(PropertyInfo &p_property) const;
7588
static void _bind_methods();
7689

7790
public:
@@ -86,6 +99,9 @@ class Slider : public Range {
8699
void set_ticks_on_borders(bool);
87100
bool get_ticks_on_borders() const;
88101

102+
void set_ticks_position(TickPosition p_ticks_position);
103+
TickPosition get_ticks_position() const;
104+
89105
void set_editable(bool p_editable);
90106
bool is_editable() const;
91107

@@ -95,6 +111,8 @@ class Slider : public Range {
95111
Slider(Orientation p_orientation = VERTICAL);
96112
};
97113

114+
VARIANT_ENUM_CAST(Slider::TickPosition);
115+
98116
class HSlider : public Slider {
99117
GDCLASS(HSlider, Slider);
100118

scene/theme/default_theme.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
588588

589589
theme->set_constant("center_grabber", "HSlider", 0);
590590
theme->set_constant("grabber_offset", "HSlider", 0);
591+
theme->set_constant("tick_offset", "HSlider", 0);
591592

592593
// VSlider
593594

@@ -602,6 +603,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
602603

603604
theme->set_constant("center_grabber", "VSlider", 0);
604605
theme->set_constant("grabber_offset", "VSlider", 0);
606+
theme->set_constant("tick_offset", "VSlider", 0);
605607

606608
// SpinBox
607609

scene/theme/icons/hslider_tick.svg

Lines changed: 1 addition & 1 deletion
Loading

scene/theme/icons/vslider_tick.svg

Lines changed: 1 addition & 1 deletion
Loading

0 commit comments

Comments
 (0)