<commit_before>import { State, StateOptions } from './State';
import { Action, ActionEvent, InputType } from '../core-actions/Action';
import { CanvasEngine } from '../CanvasEngine';

export interface AbstractDisplacementStateEvent {
	displacementX: number;
	displacementY: number;
	virtualDisplacementX: number;
	virtualDisplacementY: number;
	event: React.MouseEvent | React.TouchEvent;
}

export abstract class AbstractDisplacementState<E extends CanvasEngine = CanvasEngine> extends State<E> {
	initialX: number;
	initialY: number;
	initialXRelative: number;
	initialYRelative: number;

	constructor(options: StateOptions) {
		super(options);
		this.registerAction(
			new Action({
				type: InputType.MOUSE_DOWN,
				fire: (actionEvent: ActionEvent<React.MouseEvent>) => {
					this.initialX = actionEvent.event.clientX;
					this.initialY = actionEvent.event.clientY;
					const rel = this.engine.getRelativePoint(actionEvent.event.clientX, actionEvent.event.clientY);
					this.initialXRelative = rel.x;
					this.initialYRelative = rel.y;
				}
			})
		);
		this.registerAction(
			new Action({
				type: InputType.MOUSE_MOVE,
				fire: (actionEvent: ActionEvent<React.MouseEvent>) => {
					const { event } = actionEvent;

					if (event.buttons === 0) {
						// If buttons is 0, it means the mouse is not down, the user may have released it
						// outside of the canvas, then we eject the state
						this.eject();

						return;
					}

					this.fireMouseMoved({
						displacementX: event.clientX - this.initialX,
						displacementY: event.clientY - this.initialY,
						virtualDisplacementX: (event.clientX - this.initialX) / (this.engine.getModel().getZoomLevel() / 100.0),
						virtualDisplacementY: (event.clientY - this.initialY) / (this.engine.getModel().getZoomLevel() / 100.0),
						event: event
					});
				}
			})
		);
		this.registerAction(
			new Action({
				type: InputType.MOUSE_UP,
				fire: (event: ActionEvent<React.MouseEvent>) => {
					// when the mouse if up, we eject this state
					this.eject();
				}
			})
		);

		this.registerAction(
			new Action({
				type: InputType.TOUCH_START,
				fire: (actionEvent: ActionEvent<React.TouchEvent>) => {
					const touch = actionEvent.event.touches[0];
					this.initialX = touch.clientX;
					this.initialY = touch.clientY;
					const rel = this.engine.getRelativePoint(touch.clientX, touch.clientY);
					this.initialXRelative = rel.x;
					this.initialYRelative = rel.y;
				}
			})
		);
		this.registerAction(
			new Action({
				type: InputType.TOUCH_MOVE,
				fire: (actionEvent: ActionEvent<React.TouchEvent>) => {
					const { event } = actionEvent;
					const touch = event.touches[0];
					this.fireMouseMoved({
						displacementX: touch.clientX - this.initialX,
						displacementY: touch.clientY - this.initialY,
						virtualDisplacementX: (touch.clientX - this.initialX) / (this.engine.getModel().getZoomLevel() / 100.0),
						virtualDisplacementY: (touch.clientY - this.initialY) / (this.engine.getModel().getZoomLevel() / 100.0),
						event: event
					});
				}
			})
		);
		this.registerAction(
			new Action({
				type: InputType.TOUCH_END,
				fire: (event: ActionEvent<React.TouchEvent>) => {
					// when the mouse if up, we eject this state
					this.eject();
				}
			})
		);
	}

	abstract fireMouseMoved(event: AbstractDisplacementStateEvent);
}<commit_msg>removes code duplication on AbstractDisplacementState<commit_after>import { State, StateOptions } from './State';
import { Action, ActionEvent, InputType } from '../core-actions/Action';
import { CanvasEngine } from '../CanvasEngine';

export interface AbstractDisplacementStateEvent {
	displacementX: number;
	displacementY: number;
	virtualDisplacementX: number;
	virtualDisplacementY: number;
	event: React.MouseEvent | React.TouchEvent;
}

export abstract class AbstractDisplacementState<E extends CanvasEngine = CanvasEngine> extends State<E> {
	initialX: number;
	initialY: number;
	initialXRelative: number;
	initialYRelative: number;

	constructor(options: StateOptions) {
		super(options);
		this.registerAction(
			new Action({
				type: InputType.MOUSE_DOWN,
				fire: (actionEvent: ActionEvent<React.MouseEvent>) => {
					const { clientX, clientY } = actionEvent.event;
					this.handleMoveStart(clientX, clientY);
				}
			})
		);
		this.registerAction(
			new Action({
				type: InputType.MOUSE_MOVE,
				fire: (actionEvent: ActionEvent<React.MouseEvent>) => {
					const { event } = actionEvent;

					if (event.buttons === 0) {
						// If buttons is 0, it means the mouse is not down, the user may have released it
						// outside of the canvas, then we eject the state
						this.eject();

						return;
					}

					const { clientX, clientY } = event;
					this.handleMove(clientX, clientY, event);
				}
			})
		);
		this.registerAction(
			new Action({
				type: InputType.MOUSE_UP,
				fire: () => this.handleMoveEnd(),
			})
		);

		this.registerAction(
			new Action({
				type: InputType.TOUCH_START,
				fire: (actionEvent: ActionEvent<React.TouchEvent>) => {
					const { clientX, clientY } = actionEvent.event.touches[0];
					this.handleMoveStart(clientX, clientY);
				}
			})
		);
		this.registerAction(
			new Action({
				type: InputType.TOUCH_MOVE,
				fire: (actionEvent: ActionEvent<React.TouchEvent>) => {
					const { event } = actionEvent;
					const { clientX, clientY } = event.touches[0];
					this.handleMove(clientX, clientY, event);
				}
			})
		);
		this.registerAction(
			new Action({
				type: InputType.TOUCH_END,
				fire: () => this.handleMoveEnd(),
			})
		);
	}

	protected handleMoveStart(x: number, y: number): void {
		this.initialX = x;
		this.initialY = y;
		const rel = this.engine.getRelativePoint(x, y);
		this.initialXRelative = rel.x;
		this.initialYRelative = rel.y;
	}

	protected handleMove(x: number, y: number, event: React.MouseEvent | React.TouchEvent): void {
		this.fireMouseMoved({
			displacementX: x - this.initialX,
			displacementY: y - this.initialY,
			virtualDisplacementX: (x - this.initialX) / (this.engine.getModel().getZoomLevel() / 100.0),
			virtualDisplacementY: (y - this.initialY) / (this.engine.getModel().getZoomLevel() / 100.0),
			event,
		});
	}

	protected handleMoveEnd(): void {
		this.eject();
	}

	abstract fireMouseMoved(event: AbstractDisplacementStateEvent);
}
{'fraction_non_alphanumeric': 0.1266961186494162, 'fraction_numerical': 0.0050489113284947935, 'mean_word_length': 3.4082058414464536, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5832919', 'n_tokens_mistral': 2473, 'n_tokens_neox': 2023, 'n_words': 439}