/********************************************************************************
 * Copyright (c) 2019-2024 EclipseSource and others.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License v. 2.0 are satisfied: GNU General Public License, version 2
 * with the GNU Classpath Exception which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 ********************************************************************************/
import { Action, ElementAndBounds, ElementMove, GModelElement, IActionDispatcher, IActionHandler, ICommand, Writable } from '@eclipse-glsp/sprotty';
import { SelectionService } from '../../base/selection-service';
import { BoundsAwareModelElement } from '../../utils/gmodel-util';
import { IMovementRestrictor } from '../change-bounds/movement-restrictor';
/**
 * Used to specify the desired resize dimension for a {@link ResizeElementsCommand}.
 */
export declare enum ResizeDimension {
    Width = 0,
    Height = 1,
    Width_And_Height = 2
}
/**
 * A function that computes a single number from a set of given numbers
 * i.e. it reduces the given numbers to one single number.
 * Mainly used by the {@link ResizeElementsCommand} to reduce the given dimensions to a target dimension value.
 */
export type ReduceFunction = (...values: number[]) => number;
export declare namespace ReduceFunction {
    /**
     * Returns the minimal value of the given numbers.
     * @param values Numbers to be evaluated.
     * @returns The reduced number.
     */
    function min(...values: number[]): number;
    /**
     * Returns the maximal value of the given numbers.
     * @param values Numbers to be evaluated.
     * @returns The reduced number.
     */
    function max(...values: number[]): number;
    /**
     * Computes the  average of the given numbers.
     * @param values Numbers to be evaluated.
     */
    function avg(...values: number[]): number;
    /**
     *  Returns the last value of the given numbers.
     *  @param values Numbers to be evaluated.
     *  @returns The reduced number.
     */
    function first(...values: number[]): number;
    /**
     *  Returns the minimal value of the given numbers.
     *  @param values Numbers  to be evaluated.
     *  @returns The reduced number.
     */
    function last(...values: number[]): number;
    /**
     * Returns the reduce function that corresponds to the given {@link ReduceFunctionType}.
     * @param type The reduce function kind.
     * @returns The corresponding reduce function.
     */
    function get(type: ReduceFunctionType): ReduceFunction;
}
/** Union type of all {@link ReduceFunction} keys. */
export type ReduceFunctionType = Exclude<keyof typeof ReduceFunction, 'get'>;
export interface ResizeElementsAction extends Action {
    kind: typeof ResizeElementsAction.KIND;
    /**
     * IDs of the elements that should be resized. If no IDs are given, the selected elements will be resized.
     */
    elementIds: string[];
    /**
     * Resize dimension. The default is {@link ResizeDimension.Width}.
     */
    dimension: ResizeDimension;
    /**
     * Type of the {@link ReduceFunction} that should be used to reduce the dimension to a target dimension value
     */
    reduceFunction: ReduceFunctionType;
}
export declare namespace ResizeElementsAction {
    const KIND = "resizeElementAction";
    function is(object: any): object is ResizeElementsAction;
    function create(options: {
        elementIds?: string[];
        dimension?: ResizeDimension;
        reduceFunction: ReduceFunctionType;
    }): ResizeElementsAction;
}
export declare abstract class LayoutElementsActionHandler implements IActionHandler {
    protected actionDispatcher: IActionDispatcher;
    protected selectionService: SelectionService;
    protected movementRestrictor?: IMovementRestrictor;
    abstract handle(action: Action): void | Action | ICommand;
    getSelectedElements(selection: {
        elementIds: string[];
    }): BoundsAwareModelElement[];
    protected abstract isActionElement(element: GModelElement): element is BoundsAwareModelElement;
    dispatchAction(action: Action): void;
    dispatchActions(actions: Action[]): void;
}
export declare class ResizeElementsActionHandler extends LayoutElementsActionHandler {
    handle(action: ResizeElementsAction): void;
    resizeWidth(elements: BoundsAwareModelElement[], reduceFn: ReduceFunction): void;
    resizeHeight(elements: BoundsAwareModelElement[], reduceFn: ReduceFunction): void;
    resizeWidthAndHeight(elements: BoundsAwareModelElement[], reduceFn: ReduceFunction): void;
    dispatchResizeActions(elements: BoundsAwareModelElement[], change: (element: BoundsAwareModelElement, bounds: Writable<ElementAndBounds>) => void): void;
    createElementAndBounds(element: BoundsAwareModelElement, change: (_element: BoundsAwareModelElement, _bounds: Writable<ElementAndBounds>) => void): Writable<ElementAndBounds> | undefined;
    protected isActionElement(element: GModelElement): element is BoundsAwareModelElement;
}
export declare enum Alignment {
    Left = 0,
    Center = 1,
    Right = 2,
    Top = 3,
    Middle = 4,
    Bottom = 5
}
/**
 * A function that retrieves a specific (sub)-selection of elements from a given set of elements.
 * Mainly used by the {@link AlignElementsActionHandler}.
 */
export type SelectFunction = (elements: BoundsAwareModelElement[]) => BoundsAwareModelElement[];
export declare namespace SelectFunction {
    /**
     * Select all elements from the given set of elements.
     * @param elements The set of elements.
     * @returns All elements.
     */
    function all(elements: BoundsAwareModelElement[]): BoundsAwareModelElement[];
    /**
     * Select the first element from a given set of elements.
     * @param elements The elements.
     * @returns An array containing the first element of the given elements.
     */
    function first(elements: BoundsAwareModelElement[]): BoundsAwareModelElement[];
    /**
     * Select the last element from a given set of elements.
     * @param elements The elements.
     * @returns An array containing the last element of the given elements.
     */
    function last(elements: BoundsAwareModelElement[]): BoundsAwareModelElement[];
    /**
     * Returns the select function that corresponds to the given {@link SelectFunctionType}.
     * @param type The select function type.
     * @returns The corresponding select function.
     */
    function get(kind: SelectFunctionType): SelectFunction;
}
/** Union type of all {@link SelectFunction} keys. */
export type SelectFunctionType = Exclude<keyof typeof SelectFunction, 'get'>;
export interface AlignElementsAction extends Action {
    kind: typeof AlignElementsAction.KIND;
    /**
     * IDs of the elements that should be aligned. If no IDs are given, the selected elements will be aligned.
     */
    elementIds: string[];
    /**
     * Alignment direction. The default is {@link Alignment.Left}
     */
    alignment: Alignment;
    /**
     * Function to selected elements that are considered during alignment calculation.
     * The default value is {@link Select.all}.
     */
    selectFunction: SelectFunctionType;
}
export declare namespace AlignElementsAction {
    const KIND = "alignElements";
    function is(object: any): object is AlignElementsAction;
    function create(options?: {
        elementIds?: string[];
        alignment?: Alignment;
        selectionFunction?: SelectFunctionType;
    }): AlignElementsAction;
}
export declare class AlignElementsActionHandler extends LayoutElementsActionHandler {
    handle(action: AlignElementsAction): void;
    alignLeft(elements: BoundsAwareModelElement[]): void;
    alignCenter(elements: BoundsAwareModelElement[]): void;
    alignRight(elements: BoundsAwareModelElement[]): void;
    alignTop(elements: BoundsAwareModelElement[]): void;
    alignMiddle(elements: BoundsAwareModelElement[]): void;
    alignBottom(elements: BoundsAwareModelElement[]): void;
    dispatchAlignActions(elements: BoundsAwareModelElement[], change: (element: BoundsAwareModelElement, move: Writable<ElementMove>) => void): void;
    createElementMove(element: BoundsAwareModelElement, change: (_element: BoundsAwareModelElement, _move: Writable<ElementMove>) => void): Writable<ElementMove> | undefined;
    createElementAndBounds(element: BoundsAwareModelElement, move: ElementMove): ElementAndBounds;
    protected isActionElement(element: GModelElement): element is BoundsAwareModelElement;
}
//# sourceMappingURL=layout-elements-action.d.ts.map