UNPKG

@odoo/o-spreadsheet

Version:
169 lines (168 loc) 7.16 kB
import { UuidGenerator } from "./helpers"; import { EventBus } from "./helpers/event_bus"; import { StateUpdateMessage } from "./types/collaborative/transport_service"; import { CommandDispatcher } from "./types/commands"; import { Getters } from "./types/getters"; import { Mode, ModelConfig } from "./types/model"; import { GridRenderingContext, LayerName } from "./types/rendering"; import { SelectionStreamProcessor } from "./types/selection_stream_processor"; import { WorkbookData } from "./types/workbook_data"; import { XLSXExport } from "./types/xlsx"; /** * Model * * The Model class is the owner of the state of the Spreadsheet. However, it * has more a coordination role: it defers the actual state manipulation work to * plugins. * * At creation, the Model instantiates all necessary plugins. They each have * a private state (for example, the Selection plugin has the current selection). * * State changes are then performed through commands. Commands are dispatched * to the model, which will then relay them to each plugins (and the history * handler). Then, the model will trigger an 'update' event to notify whoever * is concerned that the command was applied (if it was not canceled). * * Also, the model has an unconventional responsibility: it actually renders the * visible viewport on a canvas. This is because each plugins actually manage a * specific concern about the content of the spreadsheet, and it is more natural * if they are able to read data from their internal state to represent it on the * screen. * * Note that the Model can be used in a standalone way to manipulate * programmatically a spreadsheet. */ export declare class Model extends EventBus<any> implements CommandDispatcher { private corePlugins; private statefulUIPlugins; private range; private session; /** * In a collaborative context, some commands can be replayed, we have to ensure * that these commands are not replayed on the UI plugins. */ private isReplayingCommand; /** * A plugin can draw some contents on the canvas. But even better: it can do * so multiple times. The order of the render calls will determine a list of * "layers" (i.e., earlier calls will be obviously drawn below later calls). * This list simply keeps the renderers+layer information so the drawing code * can just iterate on it */ private renderers; /** * Internal status of the model. Important for command handling coordination */ private status; /** * The config object contains some configuration flag and callbacks */ readonly config: ModelConfig; private corePluginConfig; private coreViewPluginConfig; private uiPluginConfig; private state; readonly selection: SelectionStreamProcessor; /** * Getters are the main way the rest of the UI read data from the model. Also, * it is shared between all plugins, so they can also communicate with each * other. */ getters: Getters; /** * Getters that are accessible from the core plugins. It's a subset of `getters`, * without the UI getters */ private coreGetters; uuidGenerator: UuidGenerator; private readonly handlers; private readonly uiHandlers; private readonly coreHandlers; constructor(data?: any, config?: Partial<ModelConfig>, stateUpdateMessages?: StateUpdateMessage[], uuidGenerator?: UuidGenerator, verboseImport?: boolean); joinSession(): void; leaveSession(): Promise<void>; private setupUiPlugin; private setupCoreViewPlugin; /** * Initialize and properly configure a plugin. * * This method is private for now, but if the need arise, there is no deep * reason why the model could not add dynamically a plugin while it is running. */ private setupCorePlugin; private onRemoteRevisionReceived; private setupSession; private setupSessionEvents; private setupConfig; private setupExternalConfig; private setupCorePluginConfig; private setupCoreViewPluginConfig; private setupUiPluginConfig; /** * Check if the given command is allowed by all the plugins and the history. */ private checkDispatchAllowed; private processCommandResults; private checkDispatchAllowedRemoteCommand; private checkDispatchAllowedCoreCommand; private checkDispatchAllowedLocalCommand; private finalize; /** * Check if a command can be dispatched, and returns a DispatchResult object with the possible * reasons the dispatch failed. */ canDispatch: CommandDispatcher["dispatch"]; /** * The dispatch method is the only entry point to manipulate data in the model. * This is through this method that commands are dispatched most of the time * recursively until no plugin want to react anymore. * * CoreCommands dispatched from this function are saved in the history. * * Small technical detail: it is defined as an arrow function. There are two * reasons for this: * 1. this means that the dispatch method can be "detached" from the model, * which is done when it is put in the environment (see the Spreadsheet * component) * 2. This allows us to define its type by using the interface CommandDispatcher */ dispatch: CommandDispatcher["dispatch"]; /** * Dispatch a command from a Core Plugin (or the History). * A command dispatched from this function is not added to the history. */ private dispatchFromCorePlugin; /** * Dispatch the given command to the given handlers. * It will call `beforeHandle` and `handle` */ private dispatchToHandlers; /** * When the Grid component is ready (= mounted), it has a reference to its * canvas and need to draw the grid on it. This is then done by calling this * method, which will dispatch the call to all registered plugins. * * Note that nothing prevent multiple grid components from calling this method * each, or one grid component calling it multiple times with a different * context. This is probably the way we should do if we want to be able to * freeze a part of the grid (so, we would need to render different zones) */ drawLayer(context: GridRenderingContext, layer: LayerName): void; /** * As the name of this method strongly implies, it is useful when we need to * export data out of the model. */ exportData(): WorkbookData; _exportData(shouldSquish: boolean): WorkbookData; updateMode(mode: Mode): void; /** * Exports the current model data into a list of serialized XML files * to be zipped together as an *.xlsx file. * * We need to trigger a cell revaluation on every sheet and ensure that even * async functions are evaluated. * This prove to be necessary if the client did not trigger that evaluation in the first place * (e.g. open a document with several sheet and click on download before visiting each sheet) */ exportXLSX(): Promise<XLSXExport>; }