import Editor from '../Editor';
import { ToolbarLocalization } from './localization';
import { ActionButtonIcon } from './types';
import BaseWidget, { ToolbarWidgetTag } from './widgets/BaseWidget';
import { DispatcherEventListener } from '../EventDispatcher';
import { BaseTool } from '../lib';
export interface SpacerOptions {
    grow: number;
    minSize: string;
    maxSize: string;
}
export type ToolbarActionButtonOptions = {
    mustBeToplevel?: boolean;
    autoDisableInReadOnlyEditors?: boolean;
};
/**
 * Abstract base class for js-draw editor toolbars.
 *
 * See {@link Editor.addToolbar}, {@link makeDropdownToolbar}, and {@link makeEdgeToolbar}.
 */
export default abstract class AbstractToolbar {
    #private;
    protected editor: Editor;
    private static colorisStarted;
    protected localizationTable: ToolbarLocalization;
    /** @internal */
    constructor(editor: Editor, localizationTable: ToolbarLocalization);
    private closeColorPickerOverlay;
    private setupCloseColorPickerOverlay;
    setupColorPickers(): void;
    protected closeColorPickers(): void;
    protected getWidgetUniqueId(widget: BaseWidget): string;
    protected getWidgetFromId(id: string): BaseWidget | undefined;
    /** Do **not** modify the return value. */
    protected getAllWidgets(): Array<BaseWidget>;
    /**
     * Adds a spacer.
     *
     * **Toolbars can choose to ignore calls to `addSpacer`**.
     *
     * @example
     * Adding a save button that moves to the very right edge of the toolbar
     * while keeping the other buttons centered:
     * ```ts
     * const toolbar = editor.addToolbar(false);
     *
     * toolbar.addSpacer({ grow: 1 });
     * toolbar.addDefaults();
     * toolbar.addSpacer({ grow: 1 });
     *
     * toolbar.addActionButton({
     * 	label: 'Save',
     * 	icon: editor.icons.makeSaveIcon(),
     * }, () => {
     * 	  saveCallback();
     * });
     * ```
     */
    abstract addSpacer(options?: Partial<SpacerOptions>): void;
    /**
     * Adds an `ActionButtonWidget` or `BaseToolWidget`. The widget should not have already have a parent
     * (i.e. its `addTo` method should not have been called).
     *
     * @example
     * ```ts
     * const toolbar = editor.addToolbar();
     * const insertImageWidget = new InsertImageWidget(editor);
     * toolbar.addWidget(insertImageWidget);
     * ```
     */
    addWidget(widget: BaseWidget): void;
    /** Called by `addWidget`. Implement this to add a new widget to the toolbar. */
    protected abstract addWidgetInternal(widget: BaseWidget): void;
    /** Removes the given `widget` from this toolbar. */
    removeWidget(widget: BaseWidget): void;
    /** Called by `removeWidget`. Implement this to remove a new widget from the toolbar. */
    protected abstract removeWidgetInternal(widget: BaseWidget): void;
    private static rootToolbarId;
    /** Returns a snapshot of the state of widgets in the toolbar. */
    serializeState(): string;
    /**
     * Deserialize toolbar widgets from the given state.
     * Assumes that toolbar widgets are in the same order as when state was serialized.
     */
    deserializeState(state: string): void;
    /**
     * Called by `serializeState` to attach any additional JSONifyable data
     * to the serialized result.
     *
     * @returns an object that can be converted to JSON with `JSON.stringify`.
     */
    protected serializeInternal(): any;
    /**
     * Called by `deserializeState` with a version of the JSON outputted
     * previously by `serializeInternal`.
     */
    protected deserializeInternal(_json: any): void;
    /**
     * Creates, but does not add, an action button to this container.
     *
     * @see
     * {@link addActionButton}
     */
    protected makeActionButton(title: string | ActionButtonIcon, command: () => void, options?: ToolbarActionButtonOptions | boolean): BaseWidget;
    /**
     * Adds an action button with `title` to this toolbar (or to the given `parent` element).
     *
     * `options` can either be an object with properties `mustBeToplevel` and/or
     * `autoDisableInReadOnlyEditors` or a boolean value. If a boolean, it is interpreted
     * as being the value of `mustBeToplevel`.
     *
     * @return The added button.
     *
     * **Example**:
     * ```ts,runnable
     * import { Editor } from 'js-draw';
     * const editor = new Editor(document.body);
     * const toolbar = editor.addToolbar();
     *
     * function makeTrashIcon() {
     *   const container = document.createElement('div');
     *   container.textContent = '🗑️';
     *   return container;
     * }
     *
     * toolbar.addActionButton({
     *   icon: makeTrashIcon(), // can be any Element not in the DOM
     *   label: 'Delete all',
     * }, () => {
     *   alert('to-do!');
     * });
     */
    addActionButton(title: string | ActionButtonIcon, command: () => void, options?: ToolbarActionButtonOptions | boolean): BaseWidget;
    /**
     * Like {@link addActionButton}, except associates `tags` with the button that allow
     * different toolbar styles to give the button tag-dependent styles.
     */
    addTaggedActionButton(tags: (ToolbarWidgetTag | string)[], title: string | ActionButtonIcon, command: () => void, options?: ToolbarActionButtonOptions | boolean): BaseWidget;
    /**
     * Adds a save button that, when clicked, calls `saveCallback`.
     *
     * @example
     * ```ts,runnable
     * import { Editor, makeDropdownToolbar } from 'js-draw';
     *
     * const editor = new Editor(document.body);
     * const toolbar = makeDropdownToolbar(editor);
     *
     * toolbar.addDefaults();
     * toolbar.addSaveButton(() => alert('save clicked!'));
     * ```
     *
     * `labelOverride` can optionally be used to change the `label` or `icon` of the button.
     */
    addSaveButton(saveCallback: () => void, labelOverride?: Partial<ActionButtonIcon>): BaseWidget;
    /**
     * Adds an "Exit" button that, when clicked, calls `exitCallback`.
     *
     * **Note**: This is *roughly* equivalent to
     * ```ts
     * toolbar.addTaggedActionButton([ ToolbarWidgetTag.Exit ], {
     *   label: this.editor.localization.exit,
     *   icon: this.editor.icons.makeCloseIcon(),
     *
     *   // labelOverride can be used to override label or icon.
     *   ...labelOverride,
     * }, () => {
     *   exitCallback();
     * });
     * ```
     * with some additional configuration.
     *
     * @final
     */
    addExitButton(exitCallback: () => void, labelOverride?: Partial<ActionButtonIcon>): BaseWidget;
    /**
     * Adds undo and redo buttons that trigger the editor's built-in undo and redo
     * functionality.
     */
    addUndoRedoButtons(undoFirst?: boolean): void;
    /**
     * Adds widgets for pen/eraser/selection/text/pan-zoom primary tools.
     *
     * If `filter` returns `false` for a tool, no widget is added for that tool.
     * See {@link addDefaultToolWidgets}
     */
    addWidgetsForPrimaryTools(filter?: (tool: BaseTool) => boolean): void;
    /**
     * Adds toolbar widgets based on the enabled tools, and additional tool-like
     * buttons (e.g. {@link DocumentPropertiesWidget} and {@link InsertImageWidget}).
     */
    addDefaultToolWidgets(): void;
    /**
     * Adds widgets that don't correspond to tools, but do allow the user to control
     * the editor in some way.
     *
     * By default, this includes {@link DocumentPropertiesWidget} and {@link InsertImageWidget}.
     */
    addDefaultEditorControlWidgets(): void;
    addDefaultActionButtons(): void;
    /**
     * Adds both the default tool widgets and action buttons.
     */
    abstract addDefaults(): void;
    /**
     * Remove this toolbar from its container and clean up listeners.
     * This should only be called **once** for a given toolbar.
     */
    remove(): void;
    /**
     * Removes `listener` when {@link remove} is called.
     */
    protected manageListener(listener: DispatcherEventListener): void;
    /**
     * Internal logic for {@link remove}. Implementers should remove the toolbar
     * from its container.
     */
    protected abstract onRemove(): void;
}
