diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac071598e..bed13a59b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## [0.1.0] - TODO: Add release date.
+
+* Add drawing tools.
+* Make the chart compatible with the `flutter_web` platform.
+
## [0.0.1] - TODO: Add release date.
-* TODO: Describe initial release.
+* TODO: Describe initial release.
\ No newline at end of file
diff --git a/docs/drawing_tools.md b/docs/drawing_tools.md
new file mode 100644
index 000000000..10a5f9d84
--- /dev/null
+++ b/docs/drawing_tools.md
@@ -0,0 +1,42 @@
+# Drawing Tools
+
+The process initiates by opening the drawing tools dialog and selecting a preferred drawing tool. Subsequently, the user can add specific taps on the Deriv chart to start drawing with default configurations.
+
+The GestureDetector on the Deriv chart, utilized by the `drawingCreator` captures user input. Within the `onTap` method, every captured input will be added to the list of edgePoints. Simultaneously, the `drawingParts` list is created to store the drawing parts. Both lists are then passed to the `onAddDrawing` callback, which adds the complete drawing to the drawing repository and saves it in shared preferences based on the active Symbol, so the drawing data can be retrieved based on the chart's symbol.
+
+During the addition of drawing parts to the `drawingParts` list, each instance of the drawing is initialized. This initialization triggers the relevant `onPaint` method, allowing each drawing part to be painted to the chart. Since we maintain a list of `drawingParts`, each of which is an instance of a drawing, every drawing part has its own `onPaint` and `hitTest` methods inherited from CustomPaint. Consequently, any modifications in the drawing's position, such as dragging, result in the `repaint` and `hitTest` methods being invoked for each drawing part. For a more detailed explanation, please refer to the sections titled DrawingPainter, EdgePoints, and DraggableEdgePoints.
+
+Any modifications or adjustments to the drawing can be made by the user through the drawing tools dialog, it will end up in triggering an update in the drawing configuration within drawing_tools_dialog widget.
+
+To enable the drawings to be draggable, a distinct gesture is assigned to each drawing added to the chart. This gesture, embedded within the DrawingPainter, identifies any user taps on the drawing and designates the drawing as selected or deselected. The user can then drag the selected drawing across the chart.
+
+To update the position of the dragged drawing, the drawing must be repainted on the chart. This operation is performed by the CustomPaint component within the DrawingPainter.
+
+## Drawing Tool Chart
+
+DrawingToolChart widget is embedded within MainChart, enabling users to sketch particular shapes on DerivChart. This feature comprises two main parts: DrawingToolWidget and DrawingPainter. The DrawingPainter is specifically tasked with painting and repainting the drawings and is invoked for every drawing added to the chart.
+In other words, for each drawing a DrawingPainter widget is added on the DrawingToolChart stack, and DrawingToolWidget is for when any drawing tool is selected.
+
+## DrawingToolWidget
+
+It assigns the task of drawing creation to the respective drawing tool creator. Each creator employs the chart's gestures to detect user inputs and initially adds the drawing to the list by invoking the onAddDrawing callback. Every drawing tool creator extends from the DrawingCreator class.
+
+## DrawingCreator
+
+It is a base class for all drawing tool creators. It is responsible for adding the drawing to the list and invoking the onAddDrawing callback. It also provides the drawing tool creator with the chart's gestures to detect user inputs.
+
+## DrawingPainter
+
+A stateful widget which is responsible for painting and repainting the drawings based on theirs configs using `CustomPaint`. Since the CustomPaint is wrapped within GestureDetector, each drawing created possesses its dedicated gesture, designed specifically for enabling the drawings to be draggable.
+
+In this widget we make drawings selectable by means of gesture and `hitTest` of `CustomPainter`. `hitTest` method checks if the user has clicked on a drawing or not, if yes it will return true. Inside `CustomPaint` we are calling `onPaint` and `hitTest` for each drawingPart.
+
+![plot](drawing_tools.png)
+
+## EdgePoints
+
+EdgePoint is a term we coined to keep the data of points required to create a drawing. For instance, a line necessitates two points, while a channel requires three. Whenever a user taps on Deriv-chart to create a drawing, a new instance of this class is generated within each drawing creator. This instance contains data obtained from Deriv_chart's gesture detector. These EdgePoints are then passed as a list to the onAddDrawing callback for drawing creation.
+
+## DraggableEdgePints
+
+This class extends from EdgePoint. It incorporates functions to compute the edgePoints' positions after they are dragged (utilizing data obtained from the DrawingPainter gestureDetector). These instances will be created as the state of the drawing_painter widget. Subsequently, they will be passed to CustomPaint, where onPaint and hitTest methods utilize them for drawing selection and repainting the drawings on the chart.
diff --git a/docs/drawing_tools.png b/docs/drawing_tools.png
new file mode 100644
index 000000000..d9037dd9b
Binary files /dev/null and b/docs/drawing_tools.png differ
diff --git a/docs/how_chart_lib_works.md b/docs/how_chart_lib_works.md
index 70fc57090..cfd8e75a3 100644
--- a/docs/how_chart_lib_works.md
+++ b/docs/how_chart_lib_works.md
@@ -1,48 +1,53 @@
# Market data
-The market data(input data of chart) is a list of *Ticks* or *OHLC*.
+
+The market data(input data of chart) is a list of _Ticks_ or _OHLC_.
+
- A **Tick** data element has two properties, epoch (time-stamp) and quote (price).
- An **OHLC** (candle) data which shows the price changes in a period of time, each candle element has five properties, epoch (time-stamp) and open, close, high, low price values.
-These four values respectively represent starting, ending, highest and lowest price in that timeframe.
-
+ These four values respectively represent starting, ending, highest and lowest price in that timeframe.
# Chart Scheme
+
Chart widget is a Canvas that we paint all data of chart inside this Canvas.
![plot](chart_scheme.png)
-this widget has X-Axis and Y-Axis enabled by default.
-
+this widget has X-Axis and Y-Axis enabled by default.
# X-Axis
-X-Axis coordination system works with *rightBoundEpoch* and *msPerPx* variables.
+
+X-Axis coordination system works with _rightBoundEpoch_ and _msPerPx_ variables.
+
1. **rightBoundEpoch**: The time-stamp of the chart screen right edge.
We initially set it to point to `maxRightBoundEpoch`, The last Tick/OHLC epoch on closed markets, or the last element of the series (overlay/bottom) that has the most positive offset plus a constant offset in pixel (maxCurrentTickOffset).
-
2. **msPerPx**: which specifies each pixel of the chart screen horizontally consists of how many milliseconds.
3. **leftBoundEpoch**: The time-stamp of the chart screen left edge.
-By knowing **msPerPx**(chart's width in pixels) and **rightBoundEpoch**, We can then calculate the **leftBoundEpoch** like this:
-**leftBoundEpoch = rightBoundEpoch - screenWidth * msPerPx**
- Also, we can find out which data is inside this range and is going to be visible.
+ By knowing **msPerPx**(chart's width in pixels) and **rightBoundEpoch**, We can then calculate the **leftBoundEpoch** like this:
+ **leftBoundEpoch = rightBoundEpoch - screenWidth \* msPerPx**
+ Also, we can find out which data is inside this range and is going to be visible.
# Y-Axis
+
For Y-Axis coordination we would need to have min and max quote values that are in the visible area of chart.
-1. **topBoundEpoch**: The maximum quote(price) of the data between *rightBoundEpoch* and *leftBoundEpoch*.
-2. **bottomBoundEpoch**: The minimum quote(price) of the data between *rightBoundEpoch* and *leftBoundEpoch*.
+1. **topBoundEpoch**: The maximum quote(price) of the data between _rightBoundEpoch_ and _leftBoundEpoch_.
+2. **bottomBoundEpoch**: The minimum quote(price) of the data between _rightBoundEpoch_ and _leftBoundEpoch_.
- **now we can have the two conversion functions which can give us (x, y) positions inside the chart canvas for any epoch and quote values.**
+**now we can have the two conversion functions which can give us (x, y) positions inside the chart canvas for any epoch and quote values.**
# X-Axis labels
-- **gridTimestamps** calculates the X-Axis labels. it Creates a list of [DateTime] between rightBoundEpoch and leftBoundEpoch with gaps of [timeGridInterval].
-- **timeGridInterval** is calculating by function with same name. it Returns the first time interval which has the enough distance between lines.
+- **gridTimestamps** calculates the X-Axis labels. it Creates a list of [DateTime] between rightBoundEpoch and leftBoundEpoch with gaps of [timeGridInterval].
+- **timeGridInterval** is calculating by function with same name. it Returns the first time interval which has the enough distance between lines.
# Y-Axis labels
+
**YAxisModel** is a Model for calculating the grid intervals and quotes(labels).
by knowing the **topBoundQuote** and **bottomBoundQuote** we calculate the labels based on interval. this intervals calculates by **quoteGridInterval**.
+
- **quoteGridInterval** Calculates the grid interval of a quote by getting the [quotePerPx] value.
- **quotePerPx** Calculates the quotes that can be placed per pixel by division of distance between topBound and bottomBound in quote and pixel.
@@ -51,48 +56,47 @@ by knowing the **topBoundQuote** and **bottomBoundQuote** we calculate the label
One of these intervals will be selected to be the distance between Y-Axis labels.
the number from `intervals` list is selected as an interval that using it with the given [quotePerPx] will give us distance more than `minDistanceBetweenLines`.
-
# X-Axis scrolling
+
Scrolling in the chart happens by updating **rightBoundEpoch** of the chart's X-Axis.
changing the **rightBoundEpoch** amount will change the chart’s scroll position. **rightBoundEpoch** be on the last tick when we first load the chart.
-
# Zooming
+
Zooming in the chart happens by updating **msPerPx**.
**msPerPx** is for changing the zoom level of the chart, increasing it will result in zoom-out and decreasing to zoom-in.
-
-
-# *Painting data*
-
+# _Painting data_
## Data Visualisation
![plot](data_series.png)
-We have an abstract class named **ChartData** that represents any type of data that the chart takes and makes it paint its self on the chart's canvas including *Line*, *Candle* data, *Markers*, *barriers*, etc.
+We have an abstract class named **ChartData** that represents any type of data that the chart takes and makes it paint its self on the chart's canvas including _Line_, _Candle_ data, _Markers_, _barriers_, etc.
A **ChartData** can be anything that shows some data on the chart. The chart can take a bunch of ChartData objects and paint them on its canvas.
-
-**DataSeries** is a Super class of any data series that has ***one*** list of sorted data to paint (by epoch).
- **LineSeries**, **CandleSeries**, **OHLCSeries**,AbstractSingleIndicatorSeries(all indicator series that shows only one sequential data like **MASeries**(for moving average), **RSISeries**) are all subclasses of DataSeries directly or not.
+**DataSeries** is a Super class of any data series that has **_one_** list of sorted data to paint (by epoch).
+**LineSeries**, **CandleSeries**, **OHLCSeries**,AbstractSingleIndicatorSeries(all indicator series that shows only one sequential data like **MASeries**(for moving average), **RSISeries**) are all subclasses of DataSeries directly or not.
**DataSeries** holds the common functionalities of managing this list of sorted data.
**Series** is the Base class of all chart series paintings.
-The series that have ***more than one*** list of sorted data to paint (like AlligatorIndicatorSeries) extend from **Series** and have some SingleIndicatorSeries inside.
-
+The series that have **_more than one_** list of sorted data to paint (like AlligatorIndicatorSeries) extend from **Series** and have some SingleIndicatorSeries inside.
### ChartObject
+
Any component which can take a rectangle area on the chart's canvas.
It has `isOnEpochRange` and `isOnValueRange` method that shows whether this chart object is in chart horizontal or vertical visible area or not.
### BarrierObject
+
A **ChartObject** for defining position of a horizontal or vertical barrier.
### Chart annotations
+
Annotations are ChartData without any sequential data that added to the chart, like **Barriers**.
**ChartAnnotation** is a Base class of chart annotations that extends from **Series**.
### Barriers
+
**Barrier** is a base class of barrier. Its properties are title, epoch and value.
We have two kinds of barriers: **VerticalBarrier** and **HorizontalBarrier**.
**VerticalBarrier**: is a vertical line in the chart that draws on a specific timestamp. It extends from the **Barrier** class.
@@ -104,10 +108,9 @@ The reason that we have **TickIndicator** is to recognize the difference between
To add horizontal/vertical barriers, specify them in the `annotations` parameter of the chart.
They have the `createPainter` object to paint the **BarrierObject** that gets initiated in their `createObject` method.
-
### Markers
-**MarkerSeries** extends from **Series** to show the markers that are added to the chart.
+**MarkerSeries** extends from **Series** to show the markers that are added to the chart.
# Painter classes
@@ -115,11 +118,11 @@ They have the `createPainter` object to paint the **BarrierObject** that gets in
**SeriesPainter** is an abstract class responsible for painting its [series] data.
-We have an abstract class named **DataPainter** that extends from **SeriesPainter** and it is a class for painting common options of [DataSeries] data.
+We have an abstract class named **DataPainter** that extends from **SeriesPainter** and it is a class for painting common options of [DataSeries] data.
Other painters like **LinePainter**( A [DataPainter] for painting line data), **CandlePainter**(A [DataPainter] for painting CandleStick data) and **ScatterPainter**, all extend from **DataPainter**.
-**DataPainter** has a method called `onPaint` that calls `onPaintData`. It actually paints what's inside `onPaintData` that is overridden by each painter. for example **LinePainter** paints line in `onPaintData` method and **CandlePainter** paints Candles and `onPaintData` method. `onPaint` is a method where **DataPainters** need to do some common things before painting.
+**DataPainter** has a method called `onPaint` that calls `onPaintData`. It actually paints what's inside `onPaintData` that is overridden by each painter. for example **LinePainter** paints line in `onPaintData` method and **CandlePainter** paints Candles and `onPaintData` method. `onPaint` is a method where **DataPainters** need to do some common things before painting.
For painting Barriers, we have **VerticalBarrierPainter** and **HorizontalBarrierPainter** that also extend from **SeriesPainter**.
They override the `onPaint` method to draw a Vertical/Horizontal Barrier.
@@ -128,25 +131,25 @@ We have a `StatefulWidget` named **MarkerArea** to draw markers inside it.
**MarkerArea** is a Layer with markers.
For painting markers we have the **MarkerPainter** class extends from `CustomPainter`.
-***The data in Visible area are between **rightBoundEpoch**, **leftBoundEpoch** and **topBoundEpoch**, **bottomBoundEpoch**, will be painted by these painters.***
-
+**\*The data in Visible area are between **rightBoundEpoch**, **leftBoundEpoch** and **topBoundEpoch**, **bottomBoundEpoch**, will be painted by these painters.\***
# Painting chart data
+
when the list of data changes(by scrolling, zooming, or receiving new data) we need to update the chart.
There are 3 steps that the chart requires to do when these variables change in order to update its components(including mainSeries, indicators, Barrier, markers, ... ).
1. The chart goes through its components and notifies them about the change. Each of these components then updates their visible data inside the new (leftEpoch, rightEpoch) range.
- Then they can determine what are their min/max value (quote/price).
+ Then they can determine what are their min/max value (quote/price).
2. The chart then asks every component their min/max values through their `minValue` and `maxValue` getters to calculate the overall min/max of its Y-Axis range.
- Any component that is not willing to be included in defining the Y-Axis range can return `double.NaN` values as its min/max.
- Then if this component had any element outside of the chart's Y-Axis range that element will be invisible.
+ Any component that is not willing to be included in defining the Y-Axis range can return `double.NaN` values as its min/max.
+ Then if this component had any element outside of the chart's Y-Axis range that element will be invisible.
3. The conversion functions always return the converted x, y values based on the updated variables (Left/right bound epoch, min/max quote, top/bottom padding).
- The chart will pass these conversion functions along with a reference to its canvas and some other variables to ChartData class to paint their visible data.
-
+ The chart will pass these conversion functions along with a reference to its canvas and some other variables to ChartData class to paint their visible data.
# Cross-hair
+
We have a `StatefulWidget` **CrosshairArea** that places this area on top of the chart to display candle/point details on longpress.
It contains three other StatelessWidgets named **CrosshairDetails** (The details to show on a crosshair) and **CrosshairLinePainter** (A custom painter to paint the crosshair `line`) and **CrosshairDotPainter** (A custom painter to paint the crosshair `dot`).
@@ -157,50 +160,52 @@ In `onLongPressUpdate` we call `updatePanSpeed`, then we calculate how much time
In `onLongPressEnd`, `onCrosshairDisappeare` is called when the candle or the pointer is dismissed and auto-panning starts again and [crosshairTick] will clear.
# Theme
+
Chart has its own default dark and light themes that switch depending on Theme.of(context).brightness value. If the user creates their own themes, they would have to handle switching it themselves.
`chart_theme` is the interface, `chart_default_theme` is a default implementation of the `chart_theme` which is instantiated and used inside the `Chart` widget if no theme is passed from the app to the `Chart` widget.
`painting_styles` are some style classes that are used to specify how certain components of the chart should be styled. e.g. `barrier_style` contains style parameters of barriers.
-
# BasicChart
+
**BasicChart** is a simple chart widget that takes only one `Series` class to paint. It handles common functionalities of handling Y-axis range, scaling and its animation, top/bottom padding.
# MainChart
+
**MainChart** is a subclass of **BasicChart** and a customized widget that can show multiple `ChartData` (like `overlaySeries and `markerSeries`) and adds crosshair feature and some other minor features.
# BottomChart
+
Sometimes we need to show two charts on the screen, for example for showing bottom indicators. In that case, we use **BottomChart** that extends from **BasicChart** to show the other chart widgets.
![plot](basic-chart.png)
# Chart
-**Chart** is a widget that manages showing **MainChart** and multiple **BottomChart**s (to have `bottomSeries`, series that have different Y-scale than the MainChart) vertically.
+
+**Chart** is a widget that manages showing **MainChart** and multiple **BottomChart**s (to have `bottomSeries`, series that have different Y-scale than the MainChart) vertically.
**MainChart** and **BottomChart**s use the same **XAxis** (and it's provided in the root of the `Chart` widget to be accessible on the widgets at the bottom) but they have different YAxis.
# DerivChart
-**DerivChart** A wrapper around the **chart** widget which provides the UI to add/remove indicators and to manage saving/restoring selected ones on storage.
-*if you want to have indicators in the chart, you should use ***DerivChart** instead of **Chart****
+**DerivChart** A wrapper around the **chart** widget which provides the UI to add/remove addons (indicators and drawing tools) and to manage saving/restoring selected ones on storage.
-![plot](deriv-chart.png)
+\*if you want to have indicators and drawing tools in the chart, you should use **\*DerivChart** instead of **Chart\*\***
+![plot](deriv-chart.png)
# Widgets
+
## Market Selector Widget
+
The widget that we have included it in the chart project to be accessable inside any other project which is going to use the chart, because this widget is supposed to show the asset (symbols) list to be shown by the chart.
## AnimatedPopupDialog
+
AnimatedPopupDialog is just a wrapper widget to wrap around any widget to show as a dialog. The dialog will pop up with animation.
## CustomDraggableSheet
-CustomDraggableSheet is a wrapper widget to be used combined with a bottom sheet that makes to give the widget inside the bottom sheet the behavior that we want.
-
-
-
-
-
-
-
+CustomDraggableSheet is a wrapper widget to be used combined with a bottom sheet that makes to give the widget inside the bottom sheet the behavior that we want.
+## Drawing Tool Chart
+For brief explanation of how drawing tools work, please refer to [Drawing Tools](drawing_tools.md) section.
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index 5d77f4100..2ee70cb26 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -44,4 +44,5 @@
android:name="flutterEmbedding"
android:value="2" />
+
diff --git a/example/lib/main.dart b/example/lib/main.dart
index b5132f261..a905b8c21 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -310,7 +310,7 @@ class _FullscreenChartState extends State {
_updateSampleSLAndTP();
- WidgetsBinding.instance.addPostFrameCallback(
+ WidgetsBinding.instance?.addPostFrameCallback(
(Duration timeStamp) => _controller.scrollToLastTick(),
);
} on BaseAPIException catch (e) {
@@ -369,6 +369,21 @@ class _FullscreenChartState extends State {
});
}
+ DataSeries _getDataSeries(ChartStyle style) {
+ if (ticks is List && style != ChartStyle.line) {
+ switch (style) {
+ case ChartStyle.hollow:
+ return HollowCandleSeries(ticks as List);
+ case ChartStyle.ohlc:
+ return OhlcCandleSeries(ticks as List);
+ default:
+ return CandleSeries(ticks as List);
+ }
+ }
+ return LineSeries(ticks, style: const LineStyle(hasArea: true))
+ as DataSeries;
+ }
+
@override
Widget build(BuildContext context) => Material(
color: const Color(0xFF0E0E0E),
@@ -379,7 +394,6 @@ class _FullscreenChartState extends State {
child: Row(
children: [
Expanded(
- // ignore: unnecessary_null_comparison
child: _markets == null
? const SizedBox.shrink()
: _buildMarketSelectorButton(),
@@ -394,18 +408,13 @@ class _FullscreenChartState extends State {
children: [
ClipRect(
child: DerivChart(
- mainSeries:
- style == ChartStyle.candles && ticks is List
- ? CandleSeries(ticks as List)
- : LineSeries(
- ticks,
- style: const LineStyle(hasArea: true),
- ) as DataSeries,
+ mainSeries: _getDataSeries(style),
markerSeries: MarkerSeries(
_markers,
activeMarker: _activeMarker,
markerIconPainter: MultipliersMarkerIconPainter(),
),
+ activeSymbol: _symbol.name,
annotations: ticks.length > 4
? >[
..._sampleBarriers,
@@ -701,16 +710,31 @@ class _FullscreenChartState extends State {
IconButton _buildChartTypeButton() => IconButton(
icon: Icon(
- style == ChartStyle.line ? Icons.show_chart : Icons.insert_chart,
+ style == ChartStyle.line
+ ? Icons.show_chart
+ : style == ChartStyle.candles
+ ? Icons.insert_chart
+ : style == ChartStyle.hollow
+ ? Icons.insert_chart_outlined_outlined
+ : Icons.add_chart,
color: Colors.white,
),
onPressed: () {
Vibration.vibrate(duration: 50);
setState(() {
- if (style == ChartStyle.candles) {
- style = ChartStyle.line;
- } else {
- style = ChartStyle.candles;
+ switch (style) {
+ case ChartStyle.ohlc:
+ style = ChartStyle.line;
+ return;
+ case ChartStyle.line:
+ style = ChartStyle.candles;
+ return;
+ case ChartStyle.candles:
+ style = ChartStyle.hollow;
+ return;
+ default:
+ style = ChartStyle.ohlc;
+ return;
}
});
},
diff --git a/lib/deriv_chart.dart b/lib/deriv_chart.dart
index 9e7994cae..e378c6a35 100644
--- a/lib/deriv_chart.dart
+++ b/lib/deriv_chart.dart
@@ -1,6 +1,7 @@
library deriv_chart;
export 'generated/l10n.dart';
+export 'src/deriv_chart/deriv_chart.dart';
export 'src/deriv_chart/chart/chart.dart';
export 'src/deriv_chart/chart/data_visualization/annotations/barriers/accumulators_barriers/accumulators_indicator.dart';
export 'src/deriv_chart/chart/data_visualization/annotations/barriers/accumulators_barriers/accumulators_closed_indicator.dart';
@@ -13,12 +14,37 @@ export 'src/deriv_chart/chart/data_visualization/annotations/barriers/horizontal
export 'src/deriv_chart/chart/data_visualization/annotations/barriers/horizontal_barrier/tick_indicator.dart';
export 'src/deriv_chart/chart/data_visualization/annotations/barriers/vertical_barrier/vertical_barrier.dart';
export 'src/deriv_chart/chart/data_visualization/annotations/chart_annotation.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_data.dart';
export 'src/deriv_chart/chart/data_visualization/chart_series/data_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/awesome_oscillator_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/adx_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/alligator_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/aroon_series.dart';
export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/bollinger_bands_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/cci_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/donchian_channels_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/dpo_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/fcb_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/gator_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/ichimoku_cloud_series.dart';
export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/ma_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/ma_env_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/macd_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/ma_rainbow_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/parabolic_sar/parabolic_sar_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/roc_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/rsi_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/smi_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/stochastic_oscillator_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/williams_r_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/indicators_series/zigzag_series.dart';
export 'src/deriv_chart/chart/data_visualization/chart_series/line_series/line_series.dart';
export 'src/deriv_chart/chart/data_visualization/chart_series/ohlc_series/candle/candle_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/ohlc_series/hollow_candle/hollow_candle_series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/ohlc_series/ohlc_candle/ohlc_candle_series.dart';
export 'src/deriv_chart/chart/data_visualization/chart_series/series.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/series_painter.dart';
+export 'src/deriv_chart/chart/data_visualization/chart_series/line_series/line_painter.dart';
export 'src/deriv_chart/chart/data_visualization/markers/active_marker.dart';
export 'src/deriv_chart/chart/data_visualization/markers/marker.dart';
export 'src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/accumulators_marker_icon_painter.dart';
@@ -26,16 +52,50 @@ export 'src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/ma
export 'src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/multipliers_marker_icon_painter.dart';
export 'src/deriv_chart/chart/data_visualization/markers/marker_icon_painters/options_marker_icon_painter.dart';
export 'src/deriv_chart/chart/data_visualization/markers/marker_series.dart';
+export 'src/deriv_chart/chart/data_visualization/models/animation_info.dart';
export 'src/deriv_chart/chart/data_visualization/models/chart_object.dart';
+export 'src/deriv_chart/chart/helpers/functions/helper_functions.dart';
+export 'src/deriv_chart/chart/helpers/paint_functions/paint_text.dart';
export 'src/deriv_chart/chart/helpers/paint_functions/paint_line.dart';
export 'src/deriv_chart/chart/worm_chart/worm_chart.dart';
export 'src/deriv_chart/chart/x_axis/min_candle_duration_for_data_fit.dart';
-export 'src/deriv_chart/deriv_chart.dart';
export 'src/misc/chart_controller.dart';
+export 'src/misc/callbacks.dart';
export 'src/models/candle.dart';
export 'src/models/chart_axis_config.dart';
export 'src/models/chart_style.dart';
+export 'src/models/indicator_input.dart';
export 'src/models/tick.dart';
+export 'src/add_ons/add_on_config.dart';
+export 'src/add_ons/add_ons_repository.dart';
+export 'src/add_ons/drawing_tools_ui/drawing_tool_config.dart';
+export 'src/deriv_chart/drawing_tool_chart/drawing_tool_chart.dart';
+export 'src/deriv_chart/chart/data_visualization/drawing_tools/drawing_tool_widget.dart';
+export 'src/add_ons/indicators_ui/adx/adx_indicator_config.dart';
+export 'src/add_ons/indicators_ui/alligator/alligator_indicator_config.dart';
+export 'src/add_ons/indicators_ui/aroon/aroon_indicator_config.dart';
+export 'src/add_ons/indicators_ui/awesome_oscillator/awesome_oscillator_indicator_config.dart';
+export 'src/add_ons/indicators_ui/bollinger_bands/bollinger_bands_indicator_config.dart';
+export 'src/add_ons/indicators_ui/commodity_channel_index/cci_indicator_config.dart';
+export 'src/add_ons/indicators_ui/donchian_channel/donchian_channel_indicator_config.dart';
+export 'src/add_ons/indicators_ui/dpo_indicator/dpo_indicator_config.dart';
+export 'src/add_ons/indicators_ui/fcb_indicator/fcb_indicator_config.dart';
+export 'src/add_ons/indicators_ui/gator/gator_indicator_config.dart';
+export 'src/add_ons/indicators_ui/ichimoku_clouds/ichimoku_cloud_indicator_config.dart';
+export 'src/add_ons/indicators_ui/ma_env_indicator/ma_env_indicator_config.dart';
+export 'src/add_ons/indicators_ui/ma_indicator/ma_indicator_config.dart';
+export 'src/add_ons/indicators_ui/macd_indicator/macd_indicator_config.dart';
+export 'src/add_ons/indicators_ui/oscillator_lines/oscillator_lines_config.dart';
+export 'src/add_ons/indicators_ui/parabolic_sar/parabolic_sar_indicator_config.dart';
+export 'src/add_ons/indicators_ui/rainbow_indicator/rainbow_indicator_config.dart';
+export 'src/add_ons/indicators_ui/roc/roc_indicator_config.dart';
+export 'src/add_ons/indicators_ui/rsi/rsi_indicator_config.dart';
+export 'src/add_ons/indicators_ui/smi/smi_indicator_config.dart';
+export 'src/add_ons/indicators_ui/stochastic_oscillator_indicator/stochastic_oscillator_indicator_config.dart';
+export 'src/add_ons/indicators_ui/williams_r/williams_r_indicator_config.dart';
+export 'src/add_ons/indicators_ui/zigzag_indicator/zigzag_indicator_config.dart';
+export 'src/add_ons/indicators_ui/indicator_config.dart';
+export 'src/add_ons/repository.dart';
export 'src/theme/chart_default_dark_theme.dart';
export 'src/theme/chart_default_light_theme.dart';
export 'src/theme/chart_theme.dart';
@@ -49,3 +109,15 @@ export 'src/widgets/market_selector/market_selector.dart';
export 'src/widgets/market_selector/market_selector_button.dart';
export 'src/widgets/market_selector/models.dart';
export 'src/widgets/market_selector/symbol_icon.dart';
+export 'src/deriv_chart/drawing_tool_chart/drawing_tools.dart';
+export 'src/add_ons/drawing_tools_ui/vertical/vertical_drawing_tool_config.dart';
+export 'src/add_ons/drawing_tools_ui/line/line_drawing_tool_config.dart';
+export 'src/add_ons/drawing_tools_ui/ray/ray_drawing_tool_config.dart';
+export 'src/add_ons/drawing_tools_ui/continuous/continuous_drawing_tool_config.dart';
+export 'src/add_ons/drawing_tools_ui/horizontal/horizontal_drawing_tool_config.dart';
+export 'src/add_ons/drawing_tools_ui/distance_constants.dart';
+export 'src/add_ons/drawing_tools_ui/trend/trend_drawing_tool_config.dart';
+export 'src/add_ons/drawing_tools_ui/channel/channel_drawing_tool_config.dart';
+export 'src/add_ons/drawing_tools_ui/fibfan/fibfan_drawing_tool_config.dart';
+export 'src/add_ons/drawing_tools_ui/rectangle/rectangle_drawing_tool_config.dart';
+export 'src/deriv_chart/chart/data_visualization/drawing_tools/drawing_data.dart';
diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart
index 83eae7405..7b43c5db8 100644
--- a/lib/generated/intl/messages_en.dart
+++ b/lib/generated/intl/messages_en.dart
@@ -30,6 +30,7 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Base Line Period"),
"labelChannelFill":
MessageLookupByLibrary.simpleMessage("Channel Fill"),
+ "labelColor": MessageLookupByLibrary.simpleMessage("Color"),
"labelConversionLinePeriod":
MessageLookupByLibrary.simpleMessage("Conversion Line Period"),
"labelDistance": MessageLookupByLibrary.simpleMessage("Distance"),
@@ -38,6 +39,7 @@ class MessageLookup extends MessageLookupByLibrary {
"labelFastMAPeriod":
MessageLookupByLibrary.simpleMessage("Fast MA Period"),
"labelField": MessageLookupByLibrary.simpleMessage("Field"),
+ "labelFillColor": MessageLookupByLibrary.simpleMessage("Fill Color"),
"labelHighPeriod": MessageLookupByLibrary.simpleMessage("High Period"),
"labelHistogram": MessageLookupByLibrary.simpleMessage("Histogram"),
"labelIsSmooth": MessageLookupByLibrary.simpleMessage("Is Smooth"),
@@ -81,8 +83,12 @@ class MessageLookup extends MessageLookupByLibrary {
"labelTeethPeriod":
MessageLookupByLibrary.simpleMessage("Teeth Period"),
"labelType": MessageLookupByLibrary.simpleMessage("Type"),
+ "selectDrawingTool":
+ MessageLookupByLibrary.simpleMessage("Select drawing tool"),
"warnCheckAssetSearchingText": MessageLookupByLibrary.simpleMessage(
"Try checking your spelling or use a different term"),
+ "warnFailedLoadingDrawingTools": MessageLookupByLibrary.simpleMessage(
+ "Failed to load drawing tools."),
"warnFailedLoadingIndicators":
MessageLookupByLibrary.simpleMessage("Failed to load indicators.")
};
diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart
index 2df604f32..921540b0e 100644
--- a/lib/generated/l10n.dart
+++ b/lib/generated/l10n.dart
@@ -469,6 +469,46 @@ class ChartLocalization {
args: [],
);
}
+
+ /// `Failed to load drawing tools.`
+ String get warnFailedLoadingDrawingTools {
+ return Intl.message(
+ 'Failed to load drawing tools.',
+ name: 'warnFailedLoadingDrawingTools',
+ desc: '',
+ args: [],
+ );
+ }
+
+ /// `Select drawing tool`
+ String get selectDrawingTool {
+ return Intl.message(
+ 'Select drawing tool',
+ name: 'selectDrawingTool',
+ desc: '',
+ args: [],
+ );
+ }
+
+ /// `Color`
+ String get labelColor {
+ return Intl.message(
+ 'Color',
+ name: 'labelColor',
+ desc: '',
+ args: [],
+ );
+ }
+
+ /// `Fill Color`
+ String get labelFillColor {
+ return Intl.message(
+ 'Fill Color',
+ name: 'labelFillColor',
+ desc: '',
+ args: [],
+ );
+ }
}
class AppLocalizationDelegate extends LocalizationsDelegate {
diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb
index 1ad4abccc..d7b286d2f 100644
--- a/lib/l10n/intl_en.arb
+++ b/lib/l10n/intl_en.arb
@@ -41,5 +41,9 @@
"labelShowLines": "Show Lines",
"labelShowFractals": "Show Fractals",
"labelIsSmooth": "Is Smooth",
- "warnFailedLoadingIndicators": "Failed to load indicators."
-}
\ No newline at end of file
+ "warnFailedLoadingIndicators": "Failed to load indicators.",
+ "warnFailedLoadingDrawingTools": "Failed to load drawing tools.",
+ "selectDrawingTool": "Select drawing tool",
+ "labelColor": "Color",
+ "labelFillColor": "Fill Color"
+}
diff --git a/lib/src/add_ons/add_on_config.dart b/lib/src/add_ons/add_on_config.dart
new file mode 100644
index 000000000..836dcb7b1
--- /dev/null
+++ b/lib/src/add_ons/add_on_config.dart
@@ -0,0 +1,21 @@
+import 'package:equatable/equatable.dart';
+
+/// Config for add-ons such as indicators and drawing tools
+abstract class AddOnConfig with EquatableMixin {
+ /// Initializes [AddOnConfig].
+ const AddOnConfig({
+ this.isOverlay = true,
+ });
+
+ /// Whether the add-on is an overlay on the main chart or displays on a
+ /// separate chart. Default is set to `true`.
+ final bool isOverlay;
+
+ /// Serialization to JSON. Serves as value in key-value storage.
+ ///
+ /// Must specify add-on `name` with `nameKey`.
+ Map toJson();
+
+ @override
+ List