Drawing Toolbar and Drawing List
Two ready-made UI components give users the drawing tools:
| Component | Plain TypeScript | React |
|---|---|---|
| Drawing toolbar A rail of drawing tools: click one to start it | Drawing | < |
| Drawing list The drawings on the chart, with buttons to select, edit and delete them | Drawing | < |
Both drive a DrawingToolsController, which enables point-and-click drawing. Like the other UI components, each is plain DOM in scichart-scitrader, and scichart-scitrader-react wraps it for React. They take the SciTrader theme's colours, so they follow setTheme.
DrawingToolbar: A Rail of Drawing Tools
DrawingToolbar shows a button per tool, with a divider between tool groups. Click a tool to start it, then click the chart to place its points:
- the tool's button lights up while it is in use, and clicking it again cancels it;
- a Stop drawing button appears while any tool is in use;
- All drawing tools, the last button, opens every tool, grouped and labelled. A tool started there joins the rail while it is in use.
// Plain TypeScript
import { DrawingToolbar, DrawingToolsController } from "scichart-scitrader";
const drawing = DrawingToolsController.attach(financeChartPanel.financeApi);
const toolbar = DrawingToolbar.create(document.getElementById("tools"), drawing, {
tools: [ETradingAnnotationType.ExtendedLineAnnotation, ETradingAnnotationType.FibonacciRetracementAnnotation], // the rail's tools
orientation: "horizontal", // or "vertical", the default
showAllTools: true, // the button that opens every tool. Default true
});
toolbar.setTools([...]); // change the tools on the rail
toolbar.destroy(); // remove it
// React: the props are the same options, and the controller comes from useDrawingTools
import { DrawingToolbar, useDrawingTools } from "scichart-scitrader-react";
const { controller } = useDrawingTools(chartApi);
<DrawingToolbar controller={controller} tools={tools} orientation="horizontal" />
Without tools, the rail shows DEFAULT_DRAWING_TOOLBAR_TOOLS, one of each common family: Poly Line, Extended Line, Horizontal Line, Channel, Pitchfork, Fibonacci Retracement, Measure, Stop Loss / Take Profit, Freehand and Eraser. Any tool id can go on the rail.
| Option | Default | What it does |
|---|---|---|
tools | DEFAULT_ | The tools on the rail, in order |
orientation | "vertical" | "vertical" (top to bottom) or "horizontal" (left to right) |
show | true | Adds the button that opens every tool |
In React, changing tools updates the rail in place; changing orientation or showAllTools rebuilds it.
DrawingList: The Chart's Drawings
DrawingList lists the drawings on the chart, each with its tool's icon and name. Given a controller, it follows the chart's drawings by itself, and:
- clicking a row selects that drawing on the chart;
- each row's delete button removes it;
- Clear all, in the header, removes every drawing, after asking in a small built-in dialog.
// Plain TypeScript
import { DrawingList } from "scichart-scitrader";
const list = DrawingList.create(document.getElementById("drawings"), { controller: drawing, title: "Drawings" });
list.update({ title: "My drawings" }); // change options later
list.destroy(); // remove it
// React
import { DrawingList } from "scichart-scitrader-react";
<DrawingList controller={controller} title="Drawings" />
Drawing List Callbacks: onSelect, onEdit, onDelete and onClearAll
Each callback you pass replaces the controller's own action for it, so you can log, confirm or change what happens. To keep the action as well, do it in the callback, as the examples below do:
| Callback | Called when | Default, with a controller |
|---|---|---|
on | A row is clicked | Select that drawing: controller. |
on | A row's edit button is clicked. Passing it adds the button | No edit button. Open your own editor, or controller. |
on | A row's delete button is clicked | Remove that drawing: controller. |
on | Clear all is confirmed | Remove every drawing: controller. |
confirm | Clear all is clicked, before on | The built-in dialog. Ask your own way, and call proceed( if the user agrees |
Each callback gets the drawing's id, its annotation's id. Find the drawing with controller.drawings.find((d) => d.id === id).
const find = (id: string) => drawing.drawings.find((d) => d.id === id);
DrawingList.create(container, {
controller: drawing,
onSelect: (id) => drawing.select(find(id)), // the default, made explicit
onEdit: (id) => drawing.openEditor(find(id)), // adds an edit button: open the full editor
onDelete: (id) => {
analytics.track("drawing deleted"); // your own code
drawing.remove(find(id)); // then the default action
},
confirmClearAll: (proceed) => myConfirmDialog("Remove every drawing?").then((yes) => yes && proceed()),
});
Driving the list yourself. Without a controller, pass items, the drawings to show, and the callbacks, and update items as your state changes: list.update({ items }), or new props in React. Each item has the drawing's id, its annotation type, and the toolId that made it, which tells an Elliott wave from a plain poly line.
| Option | Default | What it does |
|---|---|---|
controller | The drawing tools to follow | |
items | The drawings to show, without a controller | |
on, on, on, on, confirm | See the callbacks | |
title | "Drawing | The heading |
empty | "No | Shown when there are no drawings |
TypeScript Example: A Drawing Toolbar and a Drawing List with Callbacks
A BTC-USD chart from Coinbase with a horizontal rail of six tools, chosen with tools, and the All drawing tools button. Draw a few things: they appear in the list on the right. Click a row, its edit or delete button, or Clear all, and the line at the bottom shows the callback. Clear all asks for confirmation in that line, through confirmClearAll, instead of the built-in dialog.
The code for this example is found below.
- TS
import "scichart-scitrader/scitrader.css";
import { ETradingAnnotationType } from "scichart-financial-tools";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
DRAWING_TOOL_BY_ID,
DrawingList,
DrawingToolbar,
DrawingToolsController,
EDrawingToolVariantId,
idbPriceStore,
OHLCStudy,
SciFinanceChartPanel,
TDrawingToolId,
VolumeStudy,
} from "scichart-scitrader";
// This example expects this HTML:
// <div style="display: flex; flex-direction: column; height: 100%">
// <div id="tools"></div>
// <div style="display: flex; flex: 1; min-height: 0">
// <div id="chart" style="flex: 1; min-width: 0"></div>
// <div id="drawings" style="width: 280px; overflow-y: auto"></div>
// </div>
// <div id="log"></div>
// </div>
// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);
// The tools on the rail, in order. Every other tool is in the "All drawing tools" panel
const TOOLS: TDrawingToolId[] = [
ETradingAnnotationType.ExtendedLineAnnotation,
ETradingAnnotationType.HorizontalTrendLineAnnotation,
ETradingAnnotationType.FibonacciRetracementAnnotation,
EDrawingToolVariantId.PatternElliottImpulse,
ETradingAnnotationType.StopLossTakeProfitAnnotation,
EDrawingToolVariantId.Eraser,
];
async function createChart() {
const log = document.getElementById("log");
Object.assign(log.style, logStyle);
const say = (text: string) => (log.textContent = text);
const financeChartPanel = await SciFinanceChartPanel.create(document.getElementById("chart"), {
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
studies: [new OHLCStudy(), new VolumeStudy()],
});
const drawing = DrawingToolsController.attach(financeChartPanel.financeApi);
// DrawingToolbar: a rail of tools that drives the controller. A tool's button lights up while it
// is in use; clicking it again cancels it. showAllTools adds the button that opens every tool
const toolbar = DrawingToolbar.create(document.getElementById("tools"), drawing, {
tools: TOOLS,
orientation: "horizontal",
showAllTools: true,
});
// DrawingList: the drawings on the chart, following the controller. Each callback you pass
// replaces the controller's own action for it, so these log the event, then do the action
const find = (id: string) => drawing.drawings.find((d) => d.id === id);
const name = (id: string) => DRAWING_TOOL_BY_ID.get(find(id)?.toolId ?? "")?.label ?? id;
const list = DrawingList.create(document.getElementById("drawings"), {
controller: drawing,
title: "My drawings",
emptyMessage: "Pick a tool above, then click the chart",
// A row was clicked. Default: select that drawing
onSelect: (id) => {
say(`onSelect: ${name(id)}`);
drawing.select(find(id));
},
// Adds an edit button to each row. Open your own editor here, or drawing.openEditor(item)
onEdit: (id) => say(`onEdit: ${name(id)}`),
// A row's delete button. Default: remove that drawing
onDelete: (id) => {
say(`onDelete: ${name(id)}`);
drawing.remove(find(id));
},
// "Clear all", once confirmed. Default: remove every drawing
onClearAll: () => {
say("onClearAll");
drawing.remove();
},
// Ask in your own way before "Clear all"; call proceed() if the user agrees.
// Default: the list's built-in dialog (.st-confirm-dialog)
confirmClearAll: (proceed) => {
say("Remove every drawing? ");
log.append(
button("Remove all", () => proceed()),
button("Cancel", () => say("Clear all cancelled"))
);
},
});
// When the page goes away: list.destroy(); toolbar.destroy(); drawing.detach(); financeChartPanel.cleanup();
return { financeChartPanel, drawing, toolbar, list };
}
function button(text: string, onClick: () => void) {
const b = document.createElement("button");
b.textContent = text;
b.onclick = onClick;
Object.assign(b.style, buttonStyle);
return b;
}
// The log uses SciTrader's UI colours: its --st-ui-* CSS variables, with the stylesheet's defaults
const logStyle: Partial<CSSStyleDeclaration> = {
display: "flex",
alignItems: "center",
gap: "8px",
minHeight: "36px",
padding: "4px 12px",
background: "var(--st-ui-background, #2b2839)",
borderTop: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
color: "var(--st-ui-text-muted, #9da2bc)",
fontSize: "13px",
};
const buttonStyle: Partial<CSSStyleDeclaration> = {
padding: "2px 10px",
border: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
borderRadius: "6px",
background: "var(--st-ui-surface, #373447)",
color: "var(--st-ui-text, #ffffff)",
font: "inherit",
fontSize: "13px",
cursor: "pointer",
};
createChart();
React Example: A Drawing Toolbar and a Drawing List with Callbacks
The same in React. The confirmation is React state: confirmClearAll stores the proceed callback, and Remove all calls it.
The code for this example is found below.
- React
import "scichart-scitrader/scitrader.css";
import * as React from "react";
import { ETradingAnnotationType } from "scichart-financial-tools";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
DRAWING_TOOL_BY_ID,
EDrawingToolVariantId,
idbPriceStore,
ISciFinanceChartPanelApi,
ISciFinanceChartPanelConfig,
OHLCStudy,
TDrawingToolId,
VolumeStudy,
} from "scichart-scitrader";
import { DrawingList, DrawingToolbar, SciFinanceChartView, useDrawingTools } from "scichart-scitrader-react";
// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);
// The tools on the rail, in order. Every other tool is in the "All drawing tools" panel
const TOOLS: TDrawingToolId[] = [
ETradingAnnotationType.ExtendedLineAnnotation,
ETradingAnnotationType.HorizontalTrendLineAnnotation,
ETradingAnnotationType.FibonacciRetracementAnnotation,
EDrawingToolVariantId.PatternElliottImpulse,
ETradingAnnotationType.StopLossTakeProfitAnnotation,
EDrawingToolVariantId.Eraser,
];
export function DrawingToolbarAndListChart() {
const [chartApi, setChartApi] = React.useState<ISciFinanceChartPanelApi>();
const { controller, drawings } = useDrawingTools(chartApi);
const [message, setMessage] = React.useState("");
// Set while asking to confirm "Clear all": the list's proceed callback
const [pendingClear, setPendingClear] = React.useState<() => void>();
// Create the config once per mounted chart: studies are live objects bound to one chart
const config = React.useMemo<ISciFinanceChartPanelConfig>(
() => ({
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
studies: [new OHLCStudy(), new VolumeStudy()],
}),
[]
);
const find = (id: string) => drawings.find((d) => d.id === id);
const name = (id: string) => DRAWING_TOOL_BY_ID.get(find(id)?.toolId ?? "")?.label ?? id;
// Fills its parent, so give the parent a height
return (
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
{/* DrawingToolbar: a rail of tools that drives the controller. A tool's button lights up while
it is in use; clicking it again cancels it. showAllTools adds the button that opens every tool */}
<DrawingToolbar controller={controller} tools={TOOLS} orientation="horizontal" showAllTools />
<div style={{ display: "flex", flex: 1, minHeight: 0 }}>
<div style={{ flex: 1, minWidth: 0 }}>
<SciFinanceChartView config={config} onInit={setChartApi} />
</div>
{/* DrawingList: the drawings on the chart, following the controller. Each callback you pass
replaces the controller's own action for it, so these log the event, then do the action */}
<DrawingList
controller={controller}
title="My drawings"
emptyMessage="Pick a tool above, then click the chart"
// A row was clicked. Default: select that drawing
onSelect={(id) => {
setMessage(`onSelect: ${name(id)}`);
controller.select(find(id));
}}
// Adds an edit button to each row. Open your own editor here, or controller.openEditor(item)
onEdit={(id) => setMessage(`onEdit: ${name(id)}`)}
// A row's delete button. Default: remove that drawing
onDelete={(id) => {
setMessage(`onDelete: ${name(id)}`);
controller.remove(find(id));
}}
// "Clear all", once confirmed. Default: remove every drawing
onClearAll={() => {
setMessage("onClearAll");
controller.remove();
}}
// Ask in your own way before "Clear all"; call proceed() if the user agrees.
// Default: the list's built-in dialog (.st-confirm-dialog)
confirmClearAll={(proceed) => setPendingClear(() => proceed)}
style={{ width: 280, overflowY: "auto" }}
/>
</div>
<div style={logStyle}>
{pendingClear ? (
<>
Remove every drawing?
<button
style={buttonStyle}
onClick={() => {
setPendingClear(undefined);
pendingClear();
}}
>
Remove all
</button>
<button
style={buttonStyle}
onClick={() => {
setPendingClear(undefined);
setMessage("Clear all cancelled");
}}
>
Cancel
</button>
</>
) : (
message
)}
</div>
</div>
);
}
// The log uses SciTrader's UI colours: its --st-ui-* CSS variables, with the stylesheet's defaults
const logStyle: React.CSSProperties = {
display: "flex",
alignItems: "center",
gap: 8,
minHeight: 36,
padding: "4px 12px",
background: "var(--st-ui-background, #2b2839)",
borderTop: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
color: "var(--st-ui-text-muted, #9da2bc)",
fontSize: 13,
};
const buttonStyle: React.CSSProperties = {
padding: "2px 10px",
border: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
borderRadius: 6,
background: "var(--st-ui-surface, #373447)",
color: "var(--st-ui-text, #ffffff)",
font: "inherit",
fontSize: 13,
cursor: "pointer",
};
Styling the Drawing Toolbar and Drawing List
Both are styled by scitrader.css, with these classes:
| Class | Element |
|---|---|
., ., . | The rail, in each orientation |
. | A tool's button. aria- while its tool is in use |
. | A divider between tool groups, and before the All drawing tools button |
., ., . | The All drawing tools panel, its group headings and its items |
., ., . | The list, its header and heading |
. | The Clear all button |
., . | The rows, and one row |
., . | A row's tool icon and name |
., ., . | A row's buttons |
. | The message when there are no drawings |
., ., ., ., ., ., . | The built-in Clear all dialog |
Colours come from the --st-ui-* CSS variables, so a theme restyles them. To change one thing, override its rule after importing scitrader.css:
/* Bigger tool buttons on the rail */
.st-drawing-toolbar__button { width: 40px; height: 40px; }
/* Show the Clear all button in red */
.st-drawing-list__clear { color: #ef5350; }
The default drawing toolbar CSS (.st-drawing-toolbar), from scitrader.css
.st-drawing-toolbar {
gap: 2px;
background: var(--st-ui-menu-background, rgba(20,20,30,0.95));
}
.st-drawing-toolbar--vertical {
padding: 6px 4px;
border-right: 1px solid rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.08);
}
.st-drawing-toolbar--horizontal {
padding: 4px 6px;
border-bottom: 1px solid rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.08);
}
.st-drawing-toolbar__button {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: 34px;
height: 34px;
padding: 0;
border: 1px solid rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.12);
border-radius: 6px;
background: transparent;
color: rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.55);
cursor: pointer;
transition: background 100ms, border-color 100ms, color 100ms;
}
.st-drawing-toolbar__button:hover:not([aria-pressed="true"]) {
color: var(--st-ui-text, #ffffff);
}
.st-drawing-toolbar__button[aria-pressed="true"] {
border-color: var(--st-ui-selection, #60A5FA);
background: color-mix(in srgb, var(--st-ui-selection, #60A5FA) 15%, transparent);
color: var(--st-ui-selection, #60A5FA);
}
.st-drawing-toolbar__divider {
flex-shrink: 0;
background: rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.1);
}
.st-drawing-toolbar--vertical .st-drawing-toolbar__divider {
width: 24px;
height: 1px;
margin: 3px 0;
}
.st-drawing-toolbar--horizontal .st-drawing-toolbar__divider {
width: 1px;
height: 24px;
margin: 0 3px;
}
.st-drawing-toolbar__flyout {
padding: 6px;
background: var(--st-ui-menu-background, rgba(20,20,30,0.95));
border: 1px solid rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.12);
border-radius: 8px;
box-shadow: 0 8px 24px rgba(0,0,0,0.35);
font-family: var(--st-font-family, sans-serif);
font-size: 13px;
}
.st-drawing-toolbar__heading {
padding: 8px 6px 4px;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--st-ui-text-muted, #9da2bc);
}
.st-drawing-toolbar__item {
display: flex;
align-items: center;
gap: 10px;
width: 100%;
padding: 6px 8px;
border: none;
border-radius: 6px;
background: transparent;
color: var(--st-ui-text, #ffffff);
cursor: pointer;
text-align: left;
font: inherit;
}
.st-drawing-toolbar__item:hover,
.st-drawing-toolbar__item[aria-pressed="true"] {
background: rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.08);
}
.st-drawing-toolbar__item[aria-pressed="true"] {
color: var(--st-ui-selection, #60A5FA);
}
The default drawing list CSS (.st-drawing-list), from scitrader.css
.st-drawing-list {
--bg: var(--st-ui-background, #2b2839);
height: 100%;
overflow: hidden;
background: var(--st-ui-background, #2b2839);
color: var(--st-ui-text-secondary, #c8cbdf);
font-family: var(--st-font-family, "DM Sans", sans-serif);
}
.st-drawing-list__header {
display: flex;
flex-shrink: 0;
align-items: center;
gap: 8px;
padding: 20px 24px 16px;
}
.st-drawing-list__title {
flex: 1;
color: var(--st-ui-text, #ffffff);
font-size: 22px;
font-weight: 700;
letter-spacing: -0.01em;
}
.st-drawing-list__items {
overflow-x: hidden;
scrollbar-width: thin;
scrollbar-color: var(--st-ui-scrollbar-thumb, #4a4560) var(--st-ui-scrollbar-track, #1e1b2e);
}
.st-drawing-list__row {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 20px;
border-bottom: 1px solid rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.05);
font-size: 13px;
cursor: pointer;
user-select: none;
outline: none;
}
.st-drawing-list__row:hover,
.st-drawing-list__row:focus-visible {
background: rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.05);
}
.st-drawing-list__icon {
display: flex;
flex-shrink: 0;
align-items: center;
color: var(--st-ui-text-muted, #9da2bc);
}
.st-drawing-list__label {
flex: 1;
min-width: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.st-drawing-list__empty {
display: flex;
flex: 1;
align-items: center;
justify-content: center;
padding: 0 24px;
color: #5a5f7a;
font-size: 13px;
text-align: center;
}
.st-drawing-list__button {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
padding: 0;
border: 0;
border-radius: 50%;
background: transparent;
color: var(--st-ui-text-muted, #9da2bc);
cursor: pointer;
transition: background-color 150ms ease, color 150ms ease;
}
.st-drawing-list__clear {
width: 36px;
height: 36px;
}
.st-drawing-list__button:hover:not(:disabled) {
background: rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.08);
}
.st-drawing-list__edit:hover {
color: var(--st-ui-text, #ffffff);
}
.st-drawing-list__delete:hover,
.st-drawing-list__clear:hover:not(:disabled) {
color: #ff6b6b;
}
.st-drawing-list__button:disabled {
color: rgba(157, 162, 188, 0.35);
cursor: default;
}
.st-drawing-list__button:focus-visible {
outline: 2px solid rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.45);
outline-offset: -2px;
}
The default confirm dialog CSS (.st-confirm-dialog), from scitrader.css
.st-confirm-dialog {
background: rgba(0, 0, 0, 0.5);
}
.st-confirm-dialog__panel {
box-sizing: border-box;
width: calc(100% - 64px);
max-width: 440px;
margin: 32px;
border-radius: 6px;
background: var(--st-ui-background, #2b2839);
color: var(--st-ui-text, #ffffff);
box-shadow: 0 11px 15px -7px rgba(0, 0, 0, 0.2), 0 24px 38px 3px rgba(0, 0, 0, 0.14),
0 9px 46px 8px rgba(0, 0, 0, 0.12);
font-family: var(--st-font-family, "DM Sans", sans-serif);
}
.st-confirm-dialog__title {
margin: 0;
padding: 16px 24px;
font-size: 20px;
font-weight: 700;
line-height: 1.6;
}
.st-confirm-dialog__text {
margin: 0;
padding: 0 24px 20px;
color: rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.85);
font-size: 13px;
}
.st-confirm-dialog__actions {
display: flex;
justify-content: flex-end;
gap: 8px;
padding: 8px;
}
.st-confirm-dialog__cancel,
.st-confirm-dialog__confirm {
padding: 6px 8px;
border: 0;
border-radius: 6px;
background: transparent;
font-family: inherit;
font-size: 14px;
cursor: pointer;
}
.st-confirm-dialog__cancel {
color: rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.7);
}
.st-confirm-dialog__confirm {
color: #ff6b6b;
font-weight: 600;
}
.st-confirm-dialog__cancel:hover {
background: rgb(var(--st-ui-overlay-rgb, 255 255 255) / 0.08);
}
.st-confirm-dialog__confirm:hover {
background: rgba(255, 107, 107, 0.08);
}
DrawingToolbar API
The DrawingToolbar class, IDrawingToolbarOptions and DEFAULT_DRAWING_TOOLBAR_TOOLS, with their TSDoc
/**
* The tools a toolbar shows when none are specified: one of each common family rather than the
* whole catalogue. The rest are one click away in the "All drawing tools" panel.
*/
const DEFAULT_DRAWING_TOOLBAR_TOOLS: readonly TDrawingToolId[];
interface IDrawingToolbarOptions {
/** Tools on the rail, in order. Default {@link DEFAULT_DRAWING_TOOLBAR_TOOLS}. */
tools?: readonly TDrawingToolId[];
/** Lay the rail out top to bottom (default) or left to right. */
orientation?: "vertical" | "horizontal";
/** Show the button that opens every tool, grouped and labelled. Default `true`. */
showAllTools?: boolean;
}
/**
* A drawing-tools rail in plain DOM, for any framework or none. It drives a
* {@link DrawingToolsController}: click a tool to start it, click it again (or Stop) to cancel,
* and the button lights up while the tool is in use. Its look is `.st-drawing-toolbar` in
* `scitrader.css`, coloured by the SciTrader theme's CSS variables, so it follows `setTheme` on
* the chart it sits beside.
*
* ```ts
* const drawing = DrawingToolsController.attach(panel.financeApi);
* const toolbar = DrawingToolbar.create(document.getElementById("tools"), drawing);
* // later: toolbar.destroy(); drawing.detach();
* ```
*
* React apps use the React `DrawingToolbar`.
*/
class DrawingToolbar {
/** The rail element, inside the container passed to {@link create}. */
readonly element: HTMLDivElement;
static create(container: HTMLElement, controller: DrawingToolsController, options?: IDrawingToolbarOptions): DrawingToolbar;
/** Change the tools on the rail. */
setTools(tools: readonly TDrawingToolId[]): void;
destroy(): void;
}
DrawingList API
The DrawingList class and the IDrawingListOptions and IDrawingListItem interfaces, with their TSDoc
/** One drawing in a {@link DrawingList}. */
interface IDrawingListItem {
/** The annotation's `id`. */
id: string;
/** The annotation type, an `ETradingAnnotationType` value. Names the row when `toolId` is absent. */
type: string;
/** The tool that made it, which tells presets apart (a pattern from a plain polyline). */
toolId?: string;
}
/** Options for {@link DrawingList}. */
interface IDrawingListOptions {
/**
* The drawing tools to follow. The list shows `controller.drawings` as they change; clicking a
* row selects that drawing, its delete button removes it, and "Clear all" removes them all.
* Pass `items` and the callbacks instead to drive the list yourself.
*/
controller?: DrawingToolsController;
/** The drawings to show, when not following a `controller`. */
items?: readonly IDrawingListItem[];
/** Called when a row is clicked. Default with a `controller`: select that drawing. */
onSelect?: (id: string) => void;
/** When set, each row gets an edit button that calls this. */
onEdit?: (id: string) => void;
/** When set (or with a `controller`), each row gets a delete button. */
onDelete?: (id: string) => void;
/**
* When set (or with a `controller`), the header gets a "Clear all" button. It asks for
* confirmation first (see {@link confirmClearAll}), then calls this.
*/
onClearAll?: () => void;
/**
* Ask for confirmation your own way before clearing: call `proceed` if the user agrees. Default:
* a small built-in dialog (`.st-confirm-dialog`).
*/
confirmClearAll?: (proceed: () => void) => void;
/** The heading. Default `"Drawing Tools"`. */
title?: string;
/** Shown when there are no drawings. Default `"No drawing tools added yet"`. */
emptyMessage?: string;
}
/**
* The drawings on a chart as a list, in plain DOM, to go beside the {@link DrawingToolbar}: each
* row shows the tool's icon and name, and clicking it selects the drawing. Optional row buttons
* edit or delete a drawing, and a header button clears them all after a confirmation.
*
* Give it a {@link DrawingToolsController} and it follows the chart's drawings by itself; or pass
* `items` and the callbacks to drive it from your own state. Its look is `.st-drawing-list` in
* `scitrader.css`.
*
* ```ts
* const drawing = DrawingToolsController.attach(panel.financeApi);
* DrawingList.create(sidePanel, { controller: drawing });
* ```
*
* React apps use the React `DrawingList`.
*/
class DrawingList {
/** The list, inside the container passed to {@link create}. */
readonly element: HTMLDivElement;
static create(container: HTMLElement, options: IDrawingListOptions): DrawingList;
/** The drawings shown. */
get items(): readonly IDrawingListItem[];
/** Change any of the options; the ones not given stay as they are. */
update(options: Partial<IDrawingListOptions>): void;
destroy(): void;
}
DrawingToolbar and DrawingList in React
The React components take the same options as props, plus className and style for their <div>. DrawingToolbar renders once its controller is set.
The React DrawingToolbar and DrawingList components and their props, from scichart-scitrader-react, with their TSDoc
/** Props for {@link DrawingToolbar}. */
interface IDrawingToolbarProps extends IDrawingToolbarOptions {
/** The chart's drawing tools, from {@link useDrawingTools}. The rail renders once it is set. */
controller: DrawingToolsController | undefined;
className?: string;
style?: React.CSSProperties;
}
/**
* The SDK's drawing-tools rail in React: the vanilla `DrawingToolbar`, mounted into a `<div>`.
* Changing `tools` updates the rail in place; changing `orientation` or `showAllTools` rebuilds it.
*
* ```tsx
* const { controller } = useDrawingTools(chart);
*
* <DrawingToolbar controller={controller} />
* <SciFinanceChartView config={config} onInit={setChart} />
* ```
*/
function DrawingToolbar({ controller, tools, orientation, showAllTools, className, style, }: IDrawingToolbarProps): JSX.Element;
/** Props for {@link DrawingList}. */
interface IDrawingListProps {
/** The drawing tools to follow, from {@link useDrawingTools}. Or pass `items` and the callbacks. */
controller?: DrawingToolsController;
/** The drawings to show, when not following a `controller`. */
items?: readonly IDrawingListItem[];
/** Called when a row is clicked. Default with a `controller`: select that drawing. */
onSelect?: (id: string) => void;
/** When set, each row gets an edit button. */
onEdit?: (id: string) => void;
/** When set (or with a `controller`), each row gets a delete button. */
onDelete?: (id: string) => void;
/** When set (or with a `controller`), the header gets a "Clear all" button. */
onClearAll?: () => void;
/** Ask for confirmation your own way: call `proceed` if the user agrees. Default: a built-in dialog. */
confirmClearAll?: (proceed: () => void) => void;
title?: string;
emptyMessage?: string;
className?: string;
style?: React.CSSProperties;
}
/**
* The SDK's list of drawings in React: the vanilla `DrawingList` in a `<div>`. With a
* `controller` it follows the chart's drawings by itself:
*
* ```tsx
* const { controller } = useDrawingTools(chart);
*
* <DrawingToolbar controller={controller} />
* <DrawingList controller={controller} />
* ```
*/
function DrawingList({ className, style, ...options }: IDrawingListProps): JSX.Element;
Where to read next
- Add Drawing Tools to a Financial Chart: the controller the toolbar and list drive.
- Every Drawing Tool: the tool ids for the rail.
- Editing Drawings: the full editor that
openEditoropens.