1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
//! Various styles for the [`Knob`] widget
//!
//! [`Knob`]: ../native/knob/struct.Knob.html

use iced_native::Color;
//use iced_native::image;

pub use iced_graphics::widget::canvas::{Canvas, LineCap};

use crate::style::{default_colors, text_marks, tick_marks};
use crate::KnobAngleRange;

/// The appearance of a [`Knob`],
///
/// [`Knob`]: ../../native/knob/struct.Knob.html
#[derive(Debug, Clone)]
pub enum Appearance {
    //Texture(TextureStyle),
    /// A classic circular style
    Circle(CircleAppearance),
    /// A modern arc style
    Arc(ArcAppearance),
    /// A modern arc style with. It can display different colors
    /// for left, right, and center positions.
    ArcBipolar(ArcBipolarAppearance),
}

/*
/// An [`Appearance`] for a [`Knob`] that uses an image texture for the knob
///
/// [`Appearance`]: enum.Appearance.html
/// [`Knob`]: ../../native/knob/struct.Knob.html
/// [`Handle`]: https://docs.rs/iced/0.1.1/iced/widget/image/struct.Handle.html
#[derive(Debug, Clone)]
pub struct TextureStyle {
    /// the [`Handle`] to the image texture
    pub texture: image::Handle,
    /// the width of the knob, not including padding
    pub knob_width: u16,
    /// the height of the knob, not including padding
    pub knob_height: u16,
    /// the texture padding around the knob bounding
    /// rectangle. This is useful when the texture is of a glowing handle or has
    /// a drop shadow, etc.
    pub texture_padding: Option<TexturePadding>,
}
*/

/// A length in a [`Knob`] stylesheet
///
/// [`Knob`]: ../../native/knob/struct.Knob.html
#[derive(Debug, Clone)]
pub enum StyleLength {
    /// The diameter of the knob scaled to this value
    Scaled(f32),
    /// Absolute length in pixels
    Fixed(f32),
}

impl StyleLength {
    /// Returns the length based on the given knob diameter
    #[inline]
    pub fn from_knob_diameter(&self, knob_diameter: f32) -> f32 {
        match self {
            StyleLength::Scaled(scale) => knob_diameter * *scale,
            StyleLength::Fixed(units) => *units,
        }
    }
}

/// Circle notch
#[derive(Debug, Clone)]
pub struct CircleNotch {
    /// The color of the circle
    pub color: Color,
    /// The width of the border
    pub border_width: f32,
    /// The color of the border
    pub border_color: Color,
    /// The diameter of the circle
    pub diameter: StyleLength,
    /// The offset from the edge of the knob to the center of the notch.
    pub offset: StyleLength,
}

/// Line notch
#[derive(Debug, Clone)]
pub struct LineNotch {
    /// The color of the line
    pub color: Color,
    /// The width (thickness) of the line
    pub width: StyleLength,
    /// The length of the line
    pub length: StyleLength,
    /// The cap at the ends of the line
    pub cap: LineCap,
    /// The offset from the edge of the knob to the center of the notch.
    pub offset: StyleLength,
}

/// The shape of the notch
#[derive(Debug, Clone)]
pub enum NotchShape {
    /// No notch
    None,
    /// Circle notch
    Circle(CircleNotch),
    /// Line notch
    Line(LineNotch),
}

/// A classic circular [`Appearance`] of a [`Knob`]
///
/// [`Appearance`]: enum.Appearance.html
/// [`Knob`]: ../../native/knob/struct.Knob.html
#[derive(Debug, Clone)]
pub struct CircleAppearance {
    /// The color of the knob
    pub color: Color,
    /// The width of the border around the knob
    pub border_width: f32,
    /// The color of the border around the knob
    pub border_color: Color,
    /// The shape of the notch
    pub notch: NotchShape,
}

impl Default for CircleAppearance {
    fn default() -> Self {
        CircleAppearance {
            color: default_colors::LIGHT_BACK,
            border_width: 1.0,
            border_color: default_colors::BORDER,
            notch: NotchShape::Circle(CircleNotch {
                color: default_colors::BORDER,
                border_width: 0.0,
                border_color: Color::TRANSPARENT,
                diameter: StyleLength::Scaled(0.17),
                offset: StyleLength::Scaled(0.15),
            }),
        }
    }
}

/// A modern arc [`Appearance`] of a [`Knob`]
///
/// [`Appearance`]: enum.Appearance.html
/// [`Knob`]: ../../native/knob/struct.Knob.html
#[derive(Debug, Clone)]
pub struct ArcAppearance {
    /// The width (thickness) of the arc
    pub width: StyleLength,
    /// The color of an empty portion of the arc
    pub empty_color: Color,
    /// The color of the filled portion of the arc
    pub filled_color: Color,
    /// The shape of the notch
    pub notch: NotchShape,
    /// The cap at the ends of the arc
    pub cap: LineCap,
}

/// A modern arc [`Appearance`] of a [`Knob`].
/// It can display different colors for left, right, and center positions. The filled arc
/// color draws from the center position.
///
/// [`Appearance`]: enum.Appearance.html
/// [`Knob`]: ../../native/knob/struct.Knob.html
#[derive(Debug, Clone)]
pub struct ArcBipolarAppearance {
    /// The width (thickness) of the arc
    pub width: StyleLength,
    /// The color of the empty background portion of the arc
    pub empty_color: Color,
    /// The color of the filled portion to the left of the center
    pub left_filled_color: Color,
    /// The color of the filled portion to the right of the center
    pub right_filled_color: Color,
    /// The shape of the notch when in the center position
    pub notch_center: NotchShape,
    /// The shape of the notch when it is to the left and right of the
    /// center. Set this to `None` to only use `notch_center`.
    pub notch_left_right: Option<(NotchShape, NotchShape)>,
    /// The cap at the ends of the arc
    pub cap: LineCap,
}

/// A style for a value arc around a [`Knob`]
///
/// [`Knob`]: ../../native/knob/struct.Knob.html
#[derive(Debug, Copy, Clone)]
pub struct ValueArcAppearance {
    /// The width (thickness) of the arc
    pub width: f32,
    /// The offset from the edge of the `Knob` in pixels
    pub offset: f32,
    /// The color of the empty background portion in the arc. Set this to
    /// `None` for no background arc.
    pub empty_color: Option<Color>,
    /// The color of a filled portion of the ring. If `right_filled_color` is
    /// `Some`, then this will only apply to the left side of the ring.
    pub left_filled_color: Color,
    /// The color of a filled portion on the right side of the ring.
    /// Set this to `None` for unipolar mode.
    pub right_filled_color: Option<Color>,
    /// The cap at the ends of the arc
    pub cap: LineCap,
}

/// A style for a [`ModulationRange`] arc around a [`Knob`]
///
/// [`ModulationRange`]: ../../core/struct.ModulationRange.html
/// [`Knob`]: ../../native/knob/struct.Knob.html
#[derive(Debug, Copy, Clone)]
pub struct ModRangeArcAppearance {
    /// The width (thickness) of the arc
    pub width: f32,
    /// The offset from the edge of the `Knob` in pixels
    pub offset: f32,
    /// The color of an empty background portion in the arc. Set this to
    /// `None` for no background arc.
    pub empty_color: Option<Color>,
    /// The color of a filled portion of the arc
    pub filled_color: Color,
    /// The color of a filled portion of the arc when `end` is less than
    /// `start`
    pub filled_inverse_color: Color,
    /// The cap at the ends of the arc
    pub cap: LineCap,
}

/// Style of tick marks for a [`Knob`].
///
/// [`Knob`]: ../../native/knob/struct.Knob.html
#[derive(Debug, Clone)]
pub struct TickMarksAppearance {
    /// The style of the tick marks
    pub style: tick_marks::Appearance,
    /// The offset from the edge of the knob in pixels
    pub offset: f32,
}

/// Style of text marks for a [`Knob`].
///
/// [`Knob`]: ../../native/knob/struct.Knob.html
#[derive(Debug, Clone)]
pub struct TextMarksAppearance {
    /// The style of the text marks
    pub style: text_marks::Appearance,
    /// The offset from the edge of the knob in pixels
    pub offset: f32,
    /// Extra horizontal offset in pixels for each additional character
    /// in the text label. This is used to keep longer labels on the sides
    /// of the knob from being too close to the knob.
    ///
    /// The default is `3.0`.
    pub h_char_offset: f32,
    /// The vertical offset in pixels.
    ///
    /// The default is `-0.75`.
    pub v_offset: f32,
}

impl std::default::Default for TextMarksAppearance {
    fn default() -> Self {
        Self {
            style: text_marks::Appearance::default(),
            offset: 15.0,
            h_char_offset: 3.0,
            v_offset: -0.75,
        }
    }
}

/// A set of rules that dictate the style of a [`Knob`].
///
/// [`Knob`]: ../../native/knob/struct.Knob.html
pub trait StyleSheet {
    /// The supported style of the [`StyleSheet`].
    type Style: Default;

    /// Produces the style of an active [`Knob`].
    ///
    /// [`Knob`]: ../../native/knob/struct.Knob.html
    fn active(&self, style: &Self::Style) -> Appearance;

    /// Produces the style of a hovered [`Knob`].
    ///
    /// [`Knob`]: ../../native/knob/struct.Knob.html
    fn hovered(&self, style: &Self::Style) -> Appearance;

    /// Produces the style of a [`Knob`] that is being dragged.
    ///
    /// [`Knob`]: ../../native/knob/struct.Knob.html
    fn dragging(&self, style: &Self::Style) -> Appearance;

    /// a [`KnobAngleRange`] that defines the minimum and maximum angle that the
    /// knob rotates
    ///
    /// [`KnobAngleRange`]: struct.KnobAngleRange.html
    fn angle_range(&self, _style: &Self::Style) -> KnobAngleRange {
        KnobAngleRange::default()
    }

    /// The style of tick marks around a [`Knob`]
    ///
    /// For no tick marks, don't override this or set this to return `None`.
    ///
    /// [`TickMarkGroup`]: ../../core/tick_marks/struct.TickMarkGroup.html
    /// [`Knob`]: ../../native/knob/struct.Knob.html
    fn tick_marks_appearance(
        &self,
        _style: &Self::Style,
    ) -> Option<TickMarksAppearance> {
        None
    }

    /// The style of a value arc around a [`Knob`]
    ///
    /// For no value arc, don't override this or set this to return `None`.
    ///
    /// [`Knob`]: ../../native/knob/struct.Knob.html
    fn value_arc_appearance(
        &self,
        _style: &Self::Style,
    ) -> Option<ValueArcAppearance> {
        None
    }

    /// The style of a [`ModulationRange`] arc around a [`Knob`]
    ///
    /// For no modulation range arc, don't override this or set this to return `None`.
    ///
    /// [`ModulationRange`]: ../../core/struct.ModulationRange.html
    /// [`Knob`]: ../../native/knob/struct.Knob.html
    fn mod_range_arc_appearance(
        &self,
        _style: &Self::Style,
    ) -> Option<ModRangeArcAppearance> {
        None
    }

    /// The style of a second [`ModulationRange`] arc around a [`Knob`]
    ///
    /// For no second modulation range arc, don't override this or set this to return `None`.
    ///
    /// [`ModulationRange`]: ../../core/struct.ModulationRange.html
    /// [`Knob`]: ../../native/knob/struct.Knob.html
    fn mod_range_arc_appearance_2(
        &self,
        _style: &Self::Style,
    ) -> Option<ModRangeArcAppearance> {
        None
    }

    /// The style of text marks around a [`Knob`]
    ///
    /// For no text marks, don't override this or set this to return `None`.
    ///
    /// [`TextMarkGroup`]: ../../core/text_marks/struct.TextMarkGroup.html
    /// [`Knob`]: ../../native/knob/struct.Knob.html
    fn text_marks_appearance(
        &self,
        _style: &Self::Style,
    ) -> Option<TextMarksAppearance> {
        None
    }
}