Skip to main content

egui_charts/config/drawing_tool/
display.rs

1//! Display, parsing, and identification methods for [`DrawingToolType`].
2//!
3//! Implements [`Display`](std::fmt::Display) and [`FromStr`](std::str::FromStr)
4//! for human-readable names and flexible case-insensitive parsing, plus methods
5//! for data-name identifiers (for protocol/storage compatibility) and SVG icon
6//! paths (for toolbar rendering).
7
8use std::fmt;
9use std::str::FromStr;
10
11use super::DrawingToolType;
12
13impl fmt::Display for DrawingToolType {
14    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15        write!(f, "{}", self.as_str())
16    }
17}
18
19/// The error [`DrawingToolType`]'s [`FromStr`] returns for a name that is not a
20/// drawing tool.
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct ParseToolTypeError {
23    /// The name that did not parse, as given.
24    pub input: String,
25}
26
27impl fmt::Display for ParseToolTypeError {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        write!(f, "unknown drawing tool {:?}", self.input)
30    }
31}
32
33impl std::error::Error for ParseToolTypeError {}
34
35impl FromStr for DrawingToolType {
36    type Err = ParseToolTypeError;
37
38    fn from_str(s: &str) -> Result<Self, Self::Err> {
39        let name = s.to_lowercase();
40        if let Some(tool) = Self::all()
41            .iter()
42            .find(|tool| tool.as_str().eq_ignore_ascii_case(&name))
43        {
44            return Ok(*tool);
45        }
46        // Names other than the display names.
47        match name.as_str() {
48            // Cursors
49            "crosscursor" | "crosshair" | "cursor" => Ok(Self::CrossCursor),
50            "dotcursor" | "dot" => Ok(Self::DotCursor),
51            "arrowcursor" | "pointer" => Ok(Self::ArrowCursor),
52            "erase" => Ok(Self::Eraser),
53
54            // Lines
55            "trendline" | "trend" => Ok(Self::TrendLine),
56            "infoline" | "info" => Ok(Self::InfoLine),
57            "extendedline" | "extended" => Ok(Self::ExtendedLine),
58            "horizontalline" | "horizontal" | "hline" => Ok(Self::HorizontalLine),
59            "horizontalray" | "hray" => Ok(Self::HorizontalRay),
60            "verticalline" | "vertical" | "vline" => Ok(Self::VerticalLine),
61            "crossline" | "cross" => Ok(Self::CrossLine),
62            "trendangle" | "angle" => Ok(Self::TrendAngle),
63
64            // Channels
65            "parallelchannel" | "channel" => Ok(Self::ParallelChannel),
66            "regressiontrend" | "regression" | "linear regression" => Ok(Self::RegressionTrend),
67            "flattopbottom" | "flat top bottom" | "flat channel" => Ok(Self::FlatTopBottom),
68            "disjointchannel" => Ok(Self::DisjointChannel),
69
70            // Pitchforks
71            "andrews pitchfork" | "andrews" => Ok(Self::Pitchfork),
72            "schiffpitchfork" | "schiff" => Ok(Self::SchiffPitchfork),
73            "modifiedschiffpitchfork" | "modified schiff" => Ok(Self::ModifiedSchiffPitchfork),
74            "insidepitchfork" | "inside" => Ok(Self::InsidePitchfork),
75
76            // Fibonacci
77            "fibonacci" | "fib" | "fibonacci retracement" => Ok(Self::FibonacciRetracement),
78            "fibonacciextension" | "fibonacci extension" | "fib extension" | "fib ext" => {
79                Ok(Self::FibonacciExtension)
80            }
81            "fibonaccichannel" | "fibonacci channel" => Ok(Self::FibonacciChannel),
82            "fibonaccitimezones" | "fibonacci time zones" | "fib time" | "fib time zones" => {
83                Ok(Self::FibonacciTimeZones)
84            }
85            "fibonaccispeedfan" | "fibonacci speed fan" | "fib speed fan" | "speed fan" => {
86                Ok(Self::FibonacciSpeedFan)
87            }
88            "trendbasedfibtime" | "trend based fib time" | "fib trend time" => {
89                Ok(Self::TrendBasedFibTime)
90            }
91            "fibonaccicircles" | "fibonacci circles" => Ok(Self::FibonacciCircles),
92            "fibonaccispiral" | "fibonacci spiral" | "spiral" => Ok(Self::FibonacciSpiral),
93            "fibonaccispeedresistancearcs" | "fibonacci speed resistance arcs" | "fib arcs" => {
94                Ok(Self::FibonacciSpeedResistanceArcs)
95            }
96            "fibonacciwedge" | "fibonacci wedge" => Ok(Self::FibonacciWedge),
97            "pitch fan" => Ok(Self::Pitchfan),
98
99            // Gann
100            "gannbox" => Ok(Self::GannBox),
101            "gannsquare" => Ok(Self::GannSquare),
102            "gannfixed" | "gann fixed" => Ok(Self::GannFixed),
103            "gannfan" | "gann" => Ok(Self::GannFan),
104
105            // Patterns
106            "xabcdpattern" | "xabcd" => Ok(Self::XABCDPattern),
107            "cypherpattern" | "cypher" => Ok(Self::CypherPattern),
108            "headandshoulders" | "h&s" | "head shoulders" => Ok(Self::HeadAndShoulders),
109            "abcdpattern" | "abcd" => Ok(Self::ABCDPattern),
110            "trianglepattern" => Ok(Self::TrianglePattern),
111            "threedrivespattern" | "three drives" => Ok(Self::ThreeDrivesPattern),
112
113            // Elliott Wave
114            "elliottimpulse" | "elliott impulse" | "impulse wave" | "impulse" => {
115                Ok(Self::ElliottImpulse)
116            }
117            "elliottcorrection" | "elliott correction" | "correction wave" | "abc" => {
118                Ok(Self::ElliottCorrection)
119            }
120            "elliotttriangle" | "elliott triangle" | "triangle wave" => Ok(Self::ElliottTriangle),
121            "elliottdoublecombo" | "elliott double combo" | "wxy" => Ok(Self::ElliottDoubleCombo),
122            "elliotttriplecombo" | "elliott triple combo" | "wxyxz" => Ok(Self::ElliottTripleCombo),
123
124            // Cycles
125            "cycliclines" | "cyclic" => Ok(Self::CyclicLines),
126            "timecycles" => Ok(Self::TimeCycles),
127            "sineline" | "sine" => Ok(Self::SineLine),
128
129            // Projection
130            "longposition" | "long" => Ok(Self::LongPos),
131            "shortposition" | "short" => Ok(Self::ShortPos),
132            "barspattern" => Ok(Self::BarsPattern),
133            "ghostfeed" => Ok(Self::GhostFeed),
134            "projectiontool" | "projection tool" => Ok(Self::ProjectionTool),
135
136            // Volume Tools
137            "anchoredvwap" | "vwap" => Ok(Self::AnchoredVWAP),
138            "fixedrangevolumeprofile" | "volume profile" => Ok(Self::FixedRangeVolumeProfile),
139            "anchoredvolumeprofile" => Ok(Self::AnchoredVolumeProfile),
140
141            // Measurers
142            "ruler" => Ok(Self::Measure),
143            "pricerange" => Ok(Self::PriceRange),
144            "daterange" | "time range" => Ok(Self::DateRange),
145            "dateandpricerange" => Ok(Self::DateAndPriceRange),
146
147            // Brushes
148            "freehand" | "paintbrush" | "paint brush" | "paint" => Ok(Self::Brush),
149            "highlight" => Ok(Self::Highlighter),
150
151            // Arrows
152            "arrowmarker" => Ok(Self::ArrowMarker),
153            "arrowmarkup" | "arrow up" => Ok(Self::ArrowMarkUp),
154            "arrowmarkdown" | "arrow down" => Ok(Self::ArrowMarkDown),
155            "arrowmarkleft" | "arrow left" => Ok(Self::ArrowMarkLeft),
156            "arrowmarkright" | "arrow right" => Ok(Self::ArrowMarkRight),
157
158            // Shapes
159            "rect" => Ok(Self::Rect),
160            "rotatedrect" | "rotated rect" => Ok(Self::RotatedRect),
161            "multipath" => Ok(Self::Path),
162            "oval" => Ok(Self::Ellipse),
163            "poly line" | "multiline" => Ok(Self::Polyline),
164            "bezierquadro" | "bezier quadro" => Ok(Self::Curve),
165            "doublecurve" | "beziercubic" | "bezier cubic" => Ok(Self::DoubleCurve),
166
167            // Annotations
168            "textlabel" | "text label" | "label" => Ok(Self::TextLabel),
169            "anchoredtext" => Ok(Self::AnchoredText),
170            "textnote" | "text note" => Ok(Self::Note),
171            "pricenote" => Ok(Self::PriceNote),
172            "anchorednote" | "anchored note" => Ok(Self::AnchoredNote),
173            "pricelabel" => Ok(Self::PriceLabel),
174            "flagnote" | "flag note" | "flag" | "flagmark" => Ok(Self::FlagNote),
175
176            // Content
177            "img" => Ok(Self::Image),
178            "twitter" => Ok(Self::Tweet),
179
180            // Icons
181            "fonticon" | "font icon" | "emoji" => Ok(Self::FontIcon),
182
183            _ => Err(ParseToolTypeError {
184                input: s.to_string(),
185            }),
186        }
187    }
188}
189
190impl DrawingToolType {
191    /// Returns a human-readable display name for the tool (e.g., `"Trend Line"`,
192    /// `"Fib Retracement"`).
193    ///
194    /// This is the string shown in the toolbar UI and in the [`Display`](std::fmt::Display)
195    /// implementation. Each tool has its own name, and [`FromStr`] parses it back
196    /// to the same tool, ignoring case.
197    pub fn as_str(&self) -> &str {
198        match self {
199            // Cursors
200            Self::CrossCursor => "Cross Cursor",
201            Self::DotCursor => "Dot Cursor",
202            Self::ArrowCursor => "Arrow Cursor",
203            Self::Eraser => "Eraser",
204
205            // Lines
206            Self::TrendLine => "Trend Line",
207            Self::Ray => "Ray",
208            Self::InfoLine => "Info Line",
209            Self::ExtendedLine => "Extended Line",
210            Self::HorizontalLine => "Horizontal Line",
211            Self::HorizontalRay => "Horizontal Ray",
212            Self::VerticalLine => "Vertical Line",
213            Self::CrossLine => "Cross Line",
214            Self::TrendAngle => "Trend Angle",
215
216            // Channels
217            Self::ParallelChannel => "Parallel Channel",
218            Self::RegressionTrend => "Regression Trend",
219            Self::FlatTopBottom => "Flat Top/Bottom",
220            Self::DisjointChannel => "Disjoint Channel",
221
222            // Pitchforks
223            Self::Pitchfork => "Pitchfork",
224            Self::SchiffPitchfork => "Schiff Pitchfork",
225            Self::ModifiedSchiffPitchfork => "Modified Schiff Pitchfork",
226            Self::InsidePitchfork => "Inside Pitchfork",
227
228            // Fibonacci
229            Self::FibonacciRetracement => "Fib Retracement",
230            Self::FibonacciExtension => "Trend-Based Fib Extension",
231            Self::FibonacciChannel => "Fib Channel",
232            Self::FibonacciTimeZones => "Fib Time Zone",
233            Self::FibonacciSpeedFan => "Fib Speed Resistance Fan",
234            Self::TrendBasedFibTime => "Trend-Based Fib Time",
235            Self::FibonacciCircles => "Fib Circles",
236            Self::FibonacciSpiral => "Fib Spiral",
237            Self::FibonacciSpeedResistanceArcs => "Fib Speed Resistance Arcs",
238            Self::FibonacciWedge => "Fib Wedge",
239            Self::Pitchfan => "Pitchfan",
240
241            // Gann
242            Self::GannBox => "Gann Box",
243            Self::GannSquare => "Gann Square",
244            Self::GannFixed => "Gann Square Fixed",
245            Self::GannFan => "Gann Fan",
246
247            // Patterns
248            Self::XABCDPattern => "XABCD Pattern",
249            Self::CypherPattern => "Cypher Pattern",
250            Self::HeadAndShoulders => "Head and Shoulders",
251            Self::ABCDPattern => "ABCD Pattern",
252            Self::TrianglePattern => "Triangle Pattern",
253            Self::ThreeDrivesPattern => "Three Drives Pattern",
254
255            // Elliott Wave
256            Self::ElliottImpulse => "Elliott Impulse Wave (12345)",
257            Self::ElliottCorrection => "Elliott Correction Wave (ABC)",
258            Self::ElliottTriangle => "Elliott Triangle Wave (ABCDE)",
259            Self::ElliottDoubleCombo => "Elliott Double Combo Wave (WXY)",
260            Self::ElliottTripleCombo => "Elliott Triple Combo Wave (WXYXZ)",
261
262            // Cycles
263            Self::CyclicLines => "Cyclic Lines",
264            Self::TimeCycles => "Time Cycles",
265            Self::SineLine => "Sine Line",
266
267            // Projection
268            Self::LongPos => "Long Position",
269            Self::ShortPos => "Short Position",
270            Self::Forecast => "Forecast",
271            Self::BarsPattern => "Bars Pattern",
272            Self::GhostFeed => "Ghost Feed",
273            Self::ProjectionTool => "Projection",
274
275            // Volume
276            Self::AnchoredVWAP => "Anchored VWAP",
277            Self::FixedRangeVolumeProfile => "Fixed Range Volume Profile",
278            Self::AnchoredVolumeProfile => "Anchored Volume Profile",
279
280            // Measurers
281            Self::Measure => "Measure",
282            Self::PriceRange => "Price Range",
283            Self::DateRange => "Date Range",
284            Self::DateAndPriceRange => "Date and Price Range",
285
286            // Brushes
287            Self::Brush => "Brush",
288            Self::Highlighter => "Highlighter",
289
290            // Arrows
291            Self::ArrowMarker => "Arrow Marker",
292            Self::Arrow => "Arrow",
293            Self::ArrowMarkUp => "Arrow Mark Up",
294            Self::ArrowMarkDown => "Arrow Mark Down",
295            Self::ArrowMarkLeft => "Arrow Mark Left",
296            Self::ArrowMarkRight => "Arrow Mark Right",
297
298            // Shapes
299            Self::Rect => "Rectangle",
300            Self::RotatedRect => "Rotated Rectangle",
301            Self::Path => "Path",
302            Self::Circle => "Circle",
303            Self::Ellipse => "Ellipse",
304            Self::Polyline => "Polyline",
305            Self::Triangle => "Triangle",
306            Self::Sector => "Sector",
307            Self::Arc => "Arc",
308            Self::Curve => "Curve",
309            Self::DoubleCurve => "Double Curve",
310
311            // Annotations
312            Self::TextLabel => "Text",
313            Self::AnchoredText => "Anchored Text",
314            Self::Note => "Note",
315            Self::PriceNote => "Price Note",
316            Self::AnchoredNote => "Pin",
317            Self::Table => "Table",
318            Self::Callout => "Callout",
319            Self::Comment => "Comment",
320            Self::PriceLabel => "Price Label",
321            Self::Signpost => "Signpost",
322            Self::FlagNote => "Flag Mark",
323
324            // Content
325            Self::Image => "Image",
326            Self::Tweet => "Tweet",
327            Self::Idea => "Idea",
328
329            // Icons
330            Self::Sticker => "Sticker",
331            Self::FontIcon => "Icon",
332        }
333    }
334
335    /// Returns the data-name identifier for the tool.
336    ///
337    /// These identifiers (e.g., `"LineToolTrendLine"`, `"LineToolFibRetracement"`)
338    /// follow the common `LineTool*` naming convention for drawing tools and are
339    /// used for serialization/protocol compatibility.
340    pub fn data_name(&self) -> &str {
341        match self {
342            Self::CrossCursor => "cursor",
343            Self::DotCursor => "dot",
344            Self::ArrowCursor => "arrow",
345            Self::Eraser => "eraser",
346            Self::TrendLine => "LineToolTrendLine",
347            Self::Ray => "LineToolRay",
348            Self::InfoLine => "LineToolInfoLine",
349            Self::ExtendedLine => "LineToolExtended",
350            Self::HorizontalLine => "LineToolHorzLine",
351            Self::HorizontalRay => "LineToolHorzRay",
352            Self::VerticalLine => "LineToolVertLine",
353            Self::CrossLine => "LineToolCrossLine",
354            Self::TrendAngle => "LineToolTrendAngle",
355            Self::ParallelChannel => "LineToolParallelChannel",
356            Self::RegressionTrend => "LineToolRegressionTrend",
357            Self::FlatTopBottom => "LineToolFlatBottom",
358            Self::DisjointChannel => "LineToolDisjointAngle",
359            Self::Pitchfork => "LineToolPitchfork",
360            Self::SchiffPitchfork => "LineToolSchiffPitchfork2",
361            Self::ModifiedSchiffPitchfork => "LineToolSchiffPitchfork",
362            Self::InsidePitchfork => "LineToolInsidePitchfork",
363            Self::FibonacciRetracement => "LineToolFibRetracement",
364            Self::FibonacciExtension => "LineToolTrendBasedFibExtension",
365            Self::FibonacciChannel => "LineToolFibChannel",
366            Self::FibonacciTimeZones => "LineToolFibTimeZone",
367            Self::FibonacciSpeedFan => "LineToolFibSpeedResistanceFan",
368            Self::TrendBasedFibTime => "LineToolTrendBasedFibTime",
369            Self::FibonacciCircles => "LineToolFibCircles",
370            Self::FibonacciSpiral => "LineToolFibSpiral",
371            Self::FibonacciSpeedResistanceArcs => "LineToolFibSpeedResistanceArcs",
372            Self::FibonacciWedge => "LineToolFibWedge",
373            Self::Pitchfan => "LineToolPitchfan",
374            Self::GannBox => "LineToolGannSquare",
375            Self::GannSquare => "LineToolGannComplex",
376            Self::GannFixed => "LineToolGannFixed",
377            Self::GannFan => "LineToolGannFan",
378            Self::XABCDPattern => "LineTool5PointsPattern",
379            Self::CypherPattern => "LineToolCypherPattern",
380            Self::HeadAndShoulders => "LineToolHeadAndShoulders",
381            Self::ABCDPattern => "LineToolABCD",
382            Self::TrianglePattern => "LineToolTrianglePattern",
383            Self::ThreeDrivesPattern => "LineToolThreeDrivers",
384            Self::ElliottImpulse => "LineToolElliottImpulse",
385            Self::ElliottCorrection => "LineToolElliottCorrection",
386            Self::ElliottTriangle => "LineToolElliottTriangle",
387            Self::ElliottDoubleCombo => "LineToolElliottDoubleCombo",
388            Self::ElliottTripleCombo => "LineToolElliottTripleCombo",
389            Self::CyclicLines => "LineToolCircleLines",
390            Self::TimeCycles => "LineToolTimeCycles",
391            Self::SineLine => "LineToolSineLine",
392            Self::LongPos => "LineToolRiskRewardLong",
393            Self::ShortPos => "LineToolRiskRewardShort",
394            Self::Forecast => "LineToolPrediction",
395            Self::BarsPattern => "LineToolBarsPattern",
396            Self::GhostFeed => "LineToolGhostFeed",
397            Self::ProjectionTool => "LineToolProjection",
398            Self::AnchoredVWAP => "LineToolAnchoredVWAP",
399            Self::FixedRangeVolumeProfile => "LineToolFixedRangeVolumeProfile",
400            Self::AnchoredVolumeProfile => "LineToolAnchoredVolumeProfile",
401            Self::Measure => "measure",
402            Self::PriceRange => "LineToolPriceRange",
403            Self::DateRange => "LineToolDateRange",
404            Self::DateAndPriceRange => "LineToolDateAndPriceRange",
405            Self::Brush => "LineToolBrush",
406            Self::Highlighter => "LineToolHighlighter",
407            Self::ArrowMarker => "LineToolArrowMarker",
408            Self::Arrow => "LineToolArrow",
409            Self::ArrowMarkUp => "LineToolArrowMarkUp",
410            Self::ArrowMarkDown => "LineToolArrowMarkDown",
411            Self::ArrowMarkLeft => "LineToolArrowMarkLeft",
412            Self::ArrowMarkRight => "LineToolArrowMarkRight",
413            Self::Rect => "LineToolRect",
414            Self::RotatedRect => "LineToolRotatedRect",
415            Self::Path => "LineToolPath",
416            Self::Circle => "LineToolCircle",
417            Self::Ellipse => "LineToolEllipse",
418            Self::Polyline => "LineToolPolyline",
419            Self::Triangle => "LineToolTriangle",
420            Self::Sector => "LineToolSector",
421            Self::Arc => "LineToolArc",
422            Self::Curve => "LineToolBezierQuadro",
423            Self::DoubleCurve => "LineToolBezierCubic",
424            Self::TextLabel => "LineToolText",
425            Self::AnchoredText => "LineToolTextAbsolute",
426            Self::Note => "LineToolTextNote",
427            Self::PriceNote => "LineToolPriceNote",
428            Self::AnchoredNote => "LineToolNote",
429            Self::Table => "LineToolTable",
430            Self::Callout => "LineToolCallout",
431            Self::Comment => "LineToolComment",
432            Self::PriceLabel => "LineToolPriceLabel",
433            Self::Signpost => "LineToolSignpost",
434            Self::FlagNote => "LineToolFlagMark",
435            Self::Image => "LineToolImage",
436            Self::Tweet => "LineToolTweet",
437            Self::Idea => "LineToolIdea",
438            Self::Sticker => "LineToolSticker",
439            Self::FontIcon => "LineToolFontIcon",
440        }
441    }
442}