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 void SetThumbLength(int lenPixels) wxOVERRIDE;
virtual int GetThumbLength() const wxOVERRIDE; virtual int GetThumbLength() const wxOVERRIDE;
virtual void ClearTicks() wxOVERRIDE;
virtual void SetTick(int tickPos) wxOVERRIDE;
int GetTickFreq() const wxOVERRIDE;
static wxVisualAttributes static wxVisualAttributes
GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL); GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
@@ -73,11 +77,20 @@ protected:
GtkWidget *m_minLabel,*m_maxLabel; GtkWidget *m_minLabel,*m_maxLabel;
bool m_blockScrollEvent; 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; virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const wxOVERRIDE;
// set the slider value unconditionally // set the slider value unconditionally
void GTKSetValue(int value); void GTKSetValue(int value);
// Platform-specific implementation of SetTickFreq
virtual void DoSetTickFreq(int freq) wxOVERRIDE;
private:
void Init();
wxDECLARE_DYNAMIC_CLASS(wxSlider); wxDECLARE_DYNAMIC_CLASS(wxSlider);
}; };

View File

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

View File

@@ -273,7 +273,7 @@ static gchar* gtk_format_value(GtkScale*, double value, void*)
wxSlider::wxSlider() wxSlider::wxSlider()
{ {
m_scale = NULL; Init();
} }
wxSlider::~wxSlider() wxSlider::~wxSlider()
@@ -282,6 +282,15 @@ wxSlider::~wxSlider()
GTKDisconnect(m_scale); 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, bool wxSlider::Create(wxWindow *parent,
wxWindowID id, wxWindowID id,
int value, int value,
@@ -293,10 +302,8 @@ bool wxSlider::Create(wxWindow *parent,
const wxValidator& validator, const wxValidator& validator,
const wxString& name) const wxString& name)
{ {
Init();
m_pos = value; m_pos = value;
m_scrollEventType = GTK_SCROLL_NONE;
m_needThumbRelease = false;
m_blockScrollEvent = false;
if (!PreCreation( parent, pos, size ) || if (!PreCreation( parent, pos, size ) ||
!CreateBase( parent, id, pos, size, style, validator, name )) !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 ); gtk_scale_set_draw_value(GTK_SCALE (m_scale), showValueLabel );
if ( showValueLabel ) if ( showValueLabel )
{ {
// position the label appropriately: notice that wxSL_DIRECTION flags // Position the label appropriately: notice that wxSL_DIRECTION flags
// specify the position of the ticks, not label, under MSW and so the // specify the position of the ticks, not label, and so the
// label is on the opposite side // label is on the opposite side.
GtkPositionType posLabel; GtkPositionType posLabel;
if ( style & wxSL_VERTICAL ) if ( style & wxSL_VERTICAL )
{ {
@@ -501,6 +508,69 @@ int wxSlider::GetLineSize() const
return int(gtk_adjustment_get_step_increment(adj)); 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 GdkWindow *wxSlider::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
{ {
#ifdef __WXGTK3__ #ifdef __WXGTK3__