Implement wxSlider ticks support in wxGTK

Tick marks were not available for wxSlider under GTK+ 2 or GTK+ 3
implementations of wxWidgets. However, tick marks have been available
for the GtkScale widget since GTK+ 2 version 2.16.

This change adds similar functionality in relation to tick marks
as was already available in wxMSW builds.

Closes https://github.com/wxWidgets/wxWidgets/pull/1355
This commit is contained in:
iwbnwif
2019-06-30 21:45:25 +01:00
committed by Vadim Zeitlin
parent e8991252ec
commit a7fe78eda8
3 changed files with 105 additions and 20 deletions

View File

@@ -56,6 +56,10 @@ public:
virtual void SetThumbLength(int lenPixels) wxOVERRIDE;
virtual int GetThumbLength() const wxOVERRIDE;
virtual void ClearTicks() wxOVERRIDE;
virtual void SetTick(int tickPos) wxOVERRIDE;
int GetTickFreq() const wxOVERRIDE;
static wxVisualAttributes
GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
@@ -73,11 +77,20 @@ protected:
GtkWidget *m_minLabel,*m_maxLabel;
bool m_blockScrollEvent;
// Note the following member is not used in GTK+2 < 2.16.
int m_tickFreq;
virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const wxOVERRIDE;
// set the slider value unconditionally
void GTKSetValue(int value);
// Platform-specific implementation of SetTickFreq
virtual void DoSetTickFreq(int freq) wxOVERRIDE;
private:
void Init();
wxDECLARE_DYNAMIC_CLASS(wxSlider);
};

View File

@@ -30,6 +30,8 @@
On Windows, the track bar control is used.
On GTK+, tick marks are only available for version 2.16 and later.
Slider generates the same events as wxScrollBar but in practice the most
convenient way to process wxSlider updates is by handling the
slider-specific @c wxEVT_SLIDER event which carries wxCommandEvent
@@ -41,7 +43,7 @@
@style{wxSL_VERTICAL}
Displays the slider vertically.
@style{wxSL_AUTOTICKS}
Displays tick marks. Windows only.
Displays tick marks (Windows, GTK+ 2.16 and later).
@style{wxSL_MIN_MAX_LABELS}
Displays minimum, maximum labels (new since wxWidgets 2.9.1).
@style{wxSL_VALUE_LABEL}
@@ -50,11 +52,11 @@
Displays minimum, maximum and value labels (same as wxSL_VALUE_LABEL
and wxSL_MIN_MAX_LABELS together).
@style{wxSL_LEFT}
Displays ticks on the left and forces the slider to be vertical.
Displays ticks on the left and forces the slider to be vertical (Windows and GTK+ 3 only).
@style{wxSL_RIGHT}
Displays ticks on the right and forces the slider to be vertical.
@style{wxSL_TOP}
Displays ticks on the top.
Displays ticks on the top (Windows and GTK+ 3 only).
@style{wxSL_BOTTOM}
Displays ticks on the bottom (this is the default).
@style{wxSL_BOTH}
@@ -67,11 +69,11 @@
@endStyleTable
Notice that @c wxSL_LEFT, @c wxSL_TOP, @c wxSL_RIGHT and @c wxSL_BOTTOM
specify the position of the slider ticks in MSW implementation and that the
slider labels, if any, are positioned on the opposite side. So, to have a
label on the left side of a vertical slider, @b wxSL_RIGHT must be used (or
none of these styles at all should be specified as left and top are default
positions for the vertical and horizontal sliders respectively).
specify the position of the slider ticks and that the slider labels, if any,
are positioned on the opposite side. So, to have a label on the left side of
a vertical slider, @b wxSL_RIGHT must be used (or none of these styles at all
should be specified as left and top are default positions for the vertical
and horizontal sliders respectively).
@beginEventEmissionTable{wxScrollEvent}
You can use EVT_COMMAND_SCROLL... macros with window IDs for when intercepting
@@ -206,7 +208,7 @@ public:
/**
Clears the ticks.
@onlyfor{wxmsw}
@onlyfor{wxmsw,wxgtk}
*/
virtual void ClearTicks();
@@ -278,7 +280,7 @@ public:
/**
Returns the tick frequency.
@onlyfor{wxmsw}
@onlyfor{wxmsw,wxgtk}
@see SetTickFreq()
*/
@@ -372,7 +374,7 @@ public:
@param tickPos
The tick position.
@onlyfor{wxmsw}
@onlyfor{wxmsw,wxgtk}
@see SetTickFreq()
*/
@@ -385,11 +387,11 @@ public:
Frequency. For example, if the frequency is set to two, a tick mark is
displayed for every other increment in the slider's range.
@onlyfor{wxmsw}
@onlyfor{wxmsw,wxgtk}
@see GetTickFreq()
*/
virtual void SetTickFreq(int n);
virtual void SetTickFreq(int freq);
/**
Sets the slider position.

View File

@@ -273,7 +273,7 @@ static gchar* gtk_format_value(GtkScale*, double value, void*)
wxSlider::wxSlider()
{
m_scale = NULL;
Init();
}
wxSlider::~wxSlider()
@@ -282,6 +282,15 @@ wxSlider::~wxSlider()
GTKDisconnect(m_scale);
}
void wxSlider::Init()
{
m_scrollEventType = GTK_SCROLL_NONE;
m_needThumbRelease = false;
m_blockScrollEvent = false;
m_tickFreq = 0;
m_scale = NULL;
}
bool wxSlider::Create(wxWindow *parent,
wxWindowID id,
int value,
@@ -293,10 +302,8 @@ bool wxSlider::Create(wxWindow *parent,
const wxValidator& validator,
const wxString& name)
{
Init();
m_pos = value;
m_scrollEventType = GTK_SCROLL_NONE;
m_needThumbRelease = false;
m_blockScrollEvent = false;
if (!PreCreation( parent, pos, size ) ||
!CreateBase( parent, id, pos, size, style, validator, name ))
@@ -344,9 +351,9 @@ bool wxSlider::Create(wxWindow *parent,
gtk_scale_set_draw_value(GTK_SCALE (m_scale), showValueLabel );
if ( showValueLabel )
{
// position the label appropriately: notice that wxSL_DIRECTION flags
// specify the position of the ticks, not label, under MSW and so the
// label is on the opposite side
// Position the label appropriately: notice that wxSL_DIRECTION flags
// specify the position of the ticks, not label, and so the
// label is on the opposite side.
GtkPositionType posLabel;
if ( style & wxSL_VERTICAL )
{
@@ -501,6 +508,69 @@ int wxSlider::GetLineSize() const
return int(gtk_adjustment_get_step_increment(adj));
}
void wxSlider::ClearTicks()
{
#if GTK_CHECK_VERSION(2,16,0)
if (wx_is_at_least_gtk2(16))
gtk_scale_clear_marks(GTK_SCALE (m_scale));
#endif
}
void wxSlider::SetTick(int tickPos)
{
#if GTK_CHECK_VERSION(2,16,0)
if ( wx_is_at_least_gtk2(16) )
{
GtkPositionType posTicks;
long style = GetWindowStyle();
if ( style & wxSL_VERTICAL )
{
if ( style & wxSL_LEFT )
posTicks = GTK_POS_LEFT;
else
posTicks = GTK_POS_RIGHT;
}
else // horizontal slider
{
if ( style & wxSL_TOP )
posTicks = GTK_POS_TOP;
else
posTicks = GTK_POS_BOTTOM;
}
gtk_scale_add_mark(GTK_SCALE (m_scale), (double)tickPos, posTicks, NULL);
}
#else
wxUnusedVar(tickPos);
#endif
}
void wxSlider::DoSetTickFreq(int freq)
{
#if GTK_CHECK_VERSION(2,16,0)
if ( wx_is_at_least_gtk2(16) )
{
m_tickFreq = freq;
gtk_scale_clear_marks(GTK_SCALE (m_scale));
for (int i = GetMin() + freq; i < GetMax(); i += freq)
SetTick(i);
}
#else
wxUnusedVar(freq);
#endif
}
int wxSlider::GetTickFreq() const
{
#if GTK_CHECK_VERSION(2,16,0)
return wx_is_at_least_gtk2(16) ? m_tickFreq : -1;
#else
return -1;
#endif
}
GdkWindow *wxSlider::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
{
#ifdef __WXGTK3__