import { EventEmitter, InitModelOf, PropertyChangeEvent, PropertyEventMap } from '../index';
export declare class PropertyEventEmitter extends EventEmitter {
    eventMap: PropertyEventMap;
    self: PropertyEventEmitter;
    initialized: boolean;
    /**
     * Contains the names of properties that are decorated grouped by the decoration. Subclasses can add their own decorations.
     */
    propertyDecorations: Record<PropertyDecoration, Set<string>>;
    protected _propertyDimensions: Record<string, Record<string, boolean>>;
    protected _propertyDimensionDefaults: Record<string, boolean>;
    protected _propertyDimensionAliases: Record<string, {
        propertyName: string;
    } & Required<PropertyDimensionAliasConfig>>;
    constructor();
    init(model: InitModelOf<this>): void;
    protected _init(model: InitModelOf<this>): void;
    /**
     * Called during initialization to write a property onto the property event emitter.
     *
     * Can be overridden to add a special init behavior for certain properties.
     */
    protected _initProperty(propertyName: string, value: any): void;
    /**
     * Sets a new value for a specific property.
     * If the new value is the same value as the old one, nothing happens.
     *
     * There are different kinds of properties.
     * - If the property is a multidimensional property, an alias for a dimension or a specific dimension, the call will be delegated to {@link setMultiDimensionalProperty} resp. {@link setPropertyDimension}.
     * - Otherwise, the call will be delegated {@link setPropertyInternal} which takes care of actually setting the property.
     *
     * @param propertyName the name of the property
     * @param newValue the new value the property should get
     * @returns true if the property has been changed, false if not.
     */
    setProperty(propertyName: string, value: any): boolean;
    /**
     * Sets a new value for a specific property.
     *
     * If the new value is the same value as the old one, nothing happens.
     * Otherwise, {@link _setProperty} is used to set the property and trigger a property change event.
     *
     * This default behavior can be overridden by implementing a custom \_setXy function where XY is the property name.
     * If such a function exists, it will be called instead of {@link _setProperty}
     *
     * @param propertyName the name of the property
     * @param newValue the new value the property should get
     * @returns true if the property has been changed, false if not.
     */
    protected setPropertyInternal(propertyName: string, value: any): boolean;
    /**
     * Returns the name of the property that is used to store the value.
     *
     * - For regular properties, the name won't be adjusted and returned as it is.
     * - For computed properties, the name will be prefixed with '_'.
     */
    adaptPropertyName(propertyName: string): string;
    /**
     * Uses {@link _readProperty} to return the value of the property.
     */
    getProperty(propertyName: string): any;
    /**
     * Adapts the propertyName if necessary using {@link adaptPropertyName} and returns the value of the property.
     *
     * If the propertyName is a dimension or an alias for a dimension, {@link _readPropertyDimension} is used to read the property from the dimension object.
     */
    protected _readProperty(propertyName: string): any;
    /**
     * Adapts the propertyName if necessary using {@link adaptPropertyName} and writes the value of the property onto the event emitter.
     *
     * If the propertyName is a dimension or an alias for a dimension, the value won't be written onto the emitter directly.
     * Instead, {@link _writePropertyDimension} is used to write the property to the dimension object.
     */
    protected _writeProperty(propertyName: string, value: any): void;
    protected _callSetProperty(propertyName: string, value: any): void;
    /**
     * Sets the value of the property 'propertyName' to 'newValue' and then triggers a propertyChange event for that property.
     *
     * It is possible to prevent the setting of the property value by using {@link Event.preventDefault}.
     *
     * @internal
     * @param propertyName the name of the property
     * @param newValue the new value the property should get
     * @returns true if the property has been changed, false if not.
     */
    _setProperty(propertyName: string, newValue: any): boolean;
    /**
     * Triggers a property change for a single property.
     */
    triggerPropertyChange<T>(propertyName: string, oldValue: T, newValue: T): PropertyChangeEvent<T, this>;
    /**
     * Calls the setter of the given property name if it exists. A setter has to be named setXy, where Xy is the property name.
     * If there is no setter for the property name, {@link setProperty} is called.
     */
    callSetter(propertyName: string, value: any): void;
    /**
     * Adds the given properties to the list of computed properties to mark them as computed.
     * @see computedProperties
     */
    protected _addComputedProperties(properties: string[]): void;
    /**
     * @see computedProperties
     */
    isComputedProperty(propertyName: string): boolean;
    /**
     * Contains the names of the properties that should be computed.
     *
     * - A regular property will be set on the object and therefore accessible by the property name (e.g. object.property).
     * - A computed property will be prefixed with an '_' when set on the object and therefore needs a getter to make it accessible.
     *   This makes it possible to compute the state of a property when it is accessed without having to modify the actual state.
     */
    get computedProperties(): Set<string>;
    protected _decorateProperties(decoration: keyof this['propertyDecorations'], properties: string | string[]): void;
    protected _undecorateProperties(decoration: keyof this['propertyDecorations'], properties: string | string[]): void;
    isPropertyDecorated(decoration: keyof this['propertyDecorations'], property: string): any;
    /**
     * Marks a property as multidimensional.
     *
     * A multidimensional property will be computed based on its dimensions. The computation result will always be a boolean, see {@link computeMultiDimensionalProperty}.
     * @param defaultValue is used for dimensions that are not know or set and affects the computation of the value, see {@link computeMultiDimensionalProperty}.
     */
    protected _addMultiDimensionalProperty(propertyName: string, defaultValue: boolean): void;
    /**
     * @returns the list of all registered multidimensional properties.
     */
    get multiDimensionalProperties(): string[];
    /**
     * @returns whether a property is multidimensional
     */
    isMultiDimensionalProperty(propertyName: string): boolean;
    /**
     * If the value is an object, the entries in the object are expected to be property dimensions and need to have the correct data type (`boolean`).
     * In that case, {@link setPropertyDimensions} is used to set the dimensions.
     * Otherwise, the `default` dimension for the given property is set using {@link setPropertyDimension}.
     */
    setMultiDimensionalProperty(propertyName: string, value: boolean | Record<string, boolean>): boolean;
    /**
     * Called during initialization to write the property dimensions and compute the multidimensional properties.
     *
     * It expects the properties to be present on the event emitter. These properties are used as default values for the dimensions.
     * If the properties are not present or undefined, the defaults from {@link _propertyDimensionDefaults} are used.
     * If the value is a boolean, the default dimension is written. If it is an object, every dimension in the object is written.
     * If a dimension has an alias and the model contains a property with the name of the alias, that property has priority over the dimension passed as part of the dimensional object.
     *
     * Afterward, the multidimensional properties are replaced with the computed values.
     */
    protected _initMultiDimensionalProperties(model: InitModelOf<this>): void;
    protected _initMultiDimensionalProperty(propertyName: string, value: boolean | Record<string, boolean>): void;
    /**
     * Computes and sets the value for every multidimensional property.
     */
    protected _updateMultiDimensionalProperties(): void;
    /**
     * Computes and sets the value for the given multidimensional property.
     */
    protected _updateMultiDimensionalProperty(propertyName: string): boolean;
    /**
     * Computes the value for the given multidimensional property.
     * If the value of a dimension is different from the given defaultValue, the result of the computation will be the negated defaultValue.
     *
     * Examples:
     * - The default value is true. If no dimension is set, the value of the multidimensional property will be true.
     *   If at least one dimension is false, the value of the multidimensional property will be false.
     * - The default value is false. If no dimension is set, the value of the multidimensional property will be false.
     *   If at least one dimension is true, the value of the multidimensional property will be true.
     *
     * @param excludedDimensions the dimensions to not consider for the computation. By default, no dimensions are excluded.
     * @returns the computed value for the given property based on its dimensions.
     */
    computeMultiDimensionalProperty(propertyName: string, excludedDimensions?: string[]): boolean;
    /**
     * Sets the value for the given property dimension by using {@link setPropertyDimensions}.
     */
    setPropertyDimension(propertyName: string, dimension: string, value: boolean): boolean;
    /**
     * Sets the new dimensional values for the given property.
     *
     * For each dimension, a property change event is triggered with the property name and the dimension separated by '-'.
     *
     * Example: For the property 'prop' and the dimension 'dim' there will be a property change event with the name 'prop-dim'.
     * You can listen for this event in the same way as for regular property change events which is: `emitter.on('propertyChange:prop-dim')`.
     *
     * After setting the dimensions and triggering the events, the main property will be updated with the new value based on every dimension.
     * @param propertyName the name of the multidimensional property
     * @param dimension the new dimensions to be set for the given propertyName. If a specific dimension is not set in the map, the default value for that multidimensional property is used.
     *                  Hence, if the map is empty, the multidimensional property will be set to the default value
     */
    setPropertyDimensions(propertyName: string, dimensions: Record<string, boolean>): boolean;
    /**
     * @returns the value for a specific property dimension or the default value of the property if the dimension is not set or known.
     */
    getPropertyDimension(propertyName: string, dimension: string): boolean;
    /**
     * @returns an object containing all dimensions with their values for a specific property.
     */
    getPropertyDimensions(propertyName: string): Record<string, boolean>;
    /**
     * @returns the existing dimensions for a property extended with the given dimension
     */
    extendPropertyDimensions(propertyName: string, dimension: string, value: boolean): Record<string, boolean> & {
        [x: string]: boolean;
    };
    /**
     * Adds an alias for a property dimension with the same name. If a dimension has an alias, the dimension looks like a regular property but behaves like a dimension.
     *
     * Meaning: {@link setProperty}/{@link getProperty} can be called using the alias only without the need to add the name of the multidimensional property as well separated with `-`.
     * The same applies to the propertyChange event: changing the property will also trigger a propertyChange event with the name of the alias (e.g. propertyChange:alias).
     * Additionally, because it is actually a dimension, setting the property will also update the multidimensional property considering this dimension.
     *
     * To further simulate a regular property, it is recommended to add a getter with the name of the alias.
     */
    protected _addPropertyDimensionAlias(propertyName: string, alias: string, config?: PropertyDimensionAliasConfig): void;
    isPropertyDimensionAlias(dimension: string): boolean;
    /**
     * @returns the alias for a property dimension, if there is an alias registered for that dimension
     */
    getAliasForPropertyDimension(propertyName: string, dimension: string): string;
    /**
     * @returns a tuple with the property name and dimension for an alias, if there is an alias registered for that name.
     */
    getPropertyDimensionForAlias(alias: string): [string, string];
    /**
     * @returns the default value for a multidimensional property. If a dimension is specified and that dimension belongs to an inverted alias, the default value will be inverted.
     */
    getPropertyDimensionDefault(propertyName: string, dimension?: string): boolean;
    protected _readPropertyDimension(propertyName: string, dimension: string): boolean;
    /**
     * Writes a specific dimension. If the dimension has the same value as the default value of the property, the dimension will be deleted.
     */
    protected _writePropertyDimension(propertyName: string, dimension: string, value: boolean): void;
    /**
     * Overrides all existing dimensions for a property with the new ones.
     */
    protected _writePropertyDimensions(propertyName: string, dimensions: Record<string, boolean>): void;
    /**
     * If the propertyName contains the name of a multidimensional property and a dimension separated by '-',
     * an array with the name of the property and the name of the dimension is returned.
     * Otherwise, the returned array contains two null values.
     */
    extractPropertyDimension(propertyName: string): [string, string];
}
export type PropertyDecoration = 'computed';
export interface PropertyDimensionAliasConfig {
    /**
     * If set to true, the value will be inverted for the computation of the multidimensional property.
     *
     * Example: If the multidimensional property is `enabled` with the defaultValue `true` and the alias is called `locked`, the element should be disabled if locked is true instead of false -> alias needs to be inverted.
     *
     * Default is false.
     */
    inverted?: boolean;
    /**
     * If specified, this name will be used as dimension name.
     *
     * This is relevant when the dimension is accessed directly without using the alias, e.g. using {@link setPropertyDimension} {@link getPropertyDimension}.
     *
     * If not specified, the alias will be used as dimension name.
     */
    dimension?: string;
}
//# sourceMappingURL=PropertyEventEmitter.d.ts.map