@@ -137,11 +137,14 @@ impl<'a, T: Numeric> DoubleSlider<'a, T> {
137
137
/// Default is false.
138
138
#[ inline]
139
139
pub fn logarithmic ( mut self , logarithmic : bool ) -> Self {
140
- let range_f64 = self . range_f64 ( ) ;
141
- assert ! (
142
- * range_f64. start( ) > 0.0 && range_f64. end( ) . is_finite( ) ,
143
- "Logarithmic scale can only be used with finite, strictly positive values"
144
- ) ;
140
+ if logarithmic {
141
+ let range_f64 = self . range_f64 ( ) ;
142
+ assert ! (
143
+ * range_f64. start( ) > 0.0 && range_f64. start( ) . is_finite( ) &&
144
+ * range_f64. end( ) > 0.0 && range_f64. end( ) . is_finite( ) ,
145
+ "Logarithmic scale can only be used with a range of finite, strictly positive values (both start and end)"
146
+ ) ;
147
+ }
145
148
self . logarithmic = logarithmic;
146
149
self
147
150
}
@@ -156,31 +159,86 @@ impl<'a, T: Numeric> DoubleSlider<'a, T> {
156
159
157
160
fn val_to_x ( & self , val : T ) -> f32 {
158
161
let offset = self . control_point_radius + OFFSET ;
159
- let slider_width = self . width - 2.0 * offset;
160
- let mut range_f64 = self . range_f64 ( ) ;
161
- let mut val = val. to_f64 ( ) ;
162
+ // Calculate usable visual width of the slider track, ensuring it's not negative
163
+ let visual_slider_width = ( self . width - 2.0 * offset) . max ( 0.0 ) ;
164
+
165
+ let mut current_val_f64 = val. to_f64 ( ) ;
166
+ let mut range_min_f64 = self . range . start ( ) . to_f64 ( ) ;
167
+ let mut range_max_f64 = self . range . end ( ) . to_f64 ( ) ;
168
+
162
169
if self . logarithmic {
163
- range_f64 = range_f64. start ( ) . log10 ( ) ..=range_f64. end ( ) . log10 ( ) ;
164
- val = val. log10 ( ) ;
170
+ // Values are asserted to be > 0 in the logarithmic() setter.
171
+ // If range_min_f64 or range_max_f64 were <=0, log10 would produce NaN or Inf.
172
+ // current_val_f64 should also be > 0.
173
+ if current_val_f64 <= 0.0 || range_min_f64 <= 0.0 || range_max_f64 <= 0.0 {
174
+ // This case should ideally be prevented by assertions or clamping
175
+ // For safety, if inputs are invalid for log, default to a non-NaN behavior
176
+ // though this indicates a deeper issue if reached.
177
+ // Given the problem context (1..=1), this branch isn't the primary issue.
178
+ return offset; // Fallback to avoid NaN from log
179
+ }
180
+ current_val_f64 = current_val_f64. log10 ( ) ;
181
+ range_min_f64 = range_min_f64. log10 ( ) ;
182
+ range_max_f64 = range_max_f64. log10 ( ) ;
165
183
}
166
- let ratio = ( ( val - range_f64. start ( ) ) / ( range_f64. end ( ) - range_f64. start ( ) ) ) as f32 ;
167
184
168
- ratio * slider_width + offset
185
+ let range_span_f64 = range_max_f64 - range_min_f64;
186
+
187
+ let ratio = if range_span_f64 == 0.0 {
188
+ // If the range is a single point (e.g., 1..=1, or log(1)..=log(1)),
189
+ // the value is conceptually at that point.
190
+ // Map this to the start (0.0) of the visual slider part.
191
+ 0.0
192
+ } else {
193
+ // Normalize current_val_f64 to a [0, 1] ratio within the range.
194
+ let normalized_val = ( current_val_f64 - range_min_f64) / range_span_f64;
195
+ normalized_val. clamp ( 0.0 , 1.0 ) // Clamp to handle potential floating point inaccuracies.
196
+ } ;
197
+
198
+ // Map the ratio to the screen coordinate.
199
+ ( ratio as f32 * visual_slider_width) + offset
169
200
}
170
201
171
- fn x_to_val ( & self , x : f32 ) -> T {
202
+ fn x_to_val ( & self , x_in_widget : f32 ) -> T {
172
203
let offset = self . control_point_radius + OFFSET ;
173
- let slider_width = ( self . width - 2.0 * offset) as f64 ;
174
- let ratio = ( x - offset) as f64 / slider_width;
175
- let range_f64 = self . range_f64 ( ) ;
176
- let val = if self . logarithmic {
177
- let ( start, end) = ( range_f64. start ( ) . log10 ( ) , range_f64. end ( ) . log10 ( ) ) ;
178
- 10.0f64 . powf ( start + ( end - start) * ratio)
204
+ // Calculate usable visual width of the slider track, ensuring it's not negative
205
+ let visual_slider_width = ( self . width - 2.0 * offset) . max ( 0.0 ) as f64 ;
206
+
207
+ let range_min_f64 = self . range . start ( ) . to_f64 ( ) ;
208
+ let range_max_f64 = self . range . end ( ) . to_f64 ( ) ;
209
+
210
+ let value_f64 = if range_min_f64 == range_max_f64 {
211
+ // If the range is a single point, any x position maps to this single value.
212
+ range_min_f64
179
213
} else {
180
- range_f64. start ( ) + ( * range_f64. end ( ) - * range_f64. start ( ) ) * ratio
214
+ // Position of x relative to the start of the slider track
215
+ let x_on_track = ( x_in_widget - offset) as f64 ;
216
+
217
+ let ratio = if visual_slider_width == 0.0 {
218
+ // If visual width is zero (e.g. self.width is too small),
219
+ // effectively all points map to the start of the range.
220
+ 0.0
221
+ } else {
222
+ ( x_on_track / visual_slider_width) . clamp ( 0.0 , 1.0 )
223
+ } ;
224
+
225
+ if self . logarithmic {
226
+ // Values are asserted to be > 0 in the logarithmic() setter.
227
+ if range_min_f64 <= 0.0 || range_max_f64 <= 0.0 {
228
+ // Fallback, though assertions should prevent this.
229
+ return self . f64_to_val ( self . range . start ( ) . to_f64 ( ) ) ;
230
+ }
231
+ let log_min = range_min_f64. log10 ( ) ;
232
+ let log_max = range_max_f64. log10 ( ) ;
233
+ // This path is taken only if range_min_f64 != range_max_f64.
234
+ // If they are different and positive, their logs will also be different.
235
+ 10.0f64 . powf ( log_min + ( log_max - log_min) * ratio)
236
+ } else {
237
+ range_min_f64 + ( range_max_f64 - range_min_f64) * ratio
238
+ }
181
239
} ;
182
240
183
- self . f64_to_val ( val )
241
+ self . f64_to_val ( value_f64 )
184
242
}
185
243
186
244
fn left_slider_f64 ( & self ) -> f64 {
0 commit comments