Skip to content

Commit

Permalink
#154 TextFieldのスクロール処理を実装(WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
ienaga committed Nov 24, 2024
1 parent 947cdd3 commit 5c75d6e
Show file tree
Hide file tree
Showing 14 changed files with 233 additions and 25 deletions.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
textFiled.type = "input";
textFiled.multiline = true;
textFiled.wordWrap = true;
textFiled.text = "Hello Next2D\nTest Mode On\n\nText Field";
textFiled.text = "Hello Next2D\nTest Mode On Test Mode On Test Mode On\n\n\n\n\n\n\n\n\n\nText Field";

const shape = sprite.addChild(new Shape());
shape
Expand Down
24 changes: 23 additions & 1 deletion packages/core/src/Canvas/usecase/CanvasWheelEventUseCase.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type { DisplayObject } from "@next2d/display";
import type { TextField } from "@next2d/text";
import { $stage } from "@next2d/display";
import { $hitObject } from "../../CoreUtil";
import {
$setEvent,
WheelEvent as Next2D_WheelEvent
Expand All @@ -13,9 +16,28 @@ import {
* @method
* @protected
*/
export const execute = (event: WheelEvent): void =>
export const execute = <D extends DisplayObject>(event: WheelEvent): void =>
{
$setEvent(event);

const displayObject = $hitObject.hit as unknown as D;
if (displayObject && displayObject.isText
&& (displayObject as unknown as TextField).scrollEnabled
) {

event.preventDefault();

if (event.deltaX) {
(displayObject as unknown as TextField).scrollX += event.deltaX / ((displayObject as unknown as TextField).textWidth / (displayObject as unknown as TextField).width);
}

if (event.deltaY) {
(displayObject as unknown as TextField).scrollY += event.deltaY / ((displayObject as unknown as TextField).textHeight / (displayObject as unknown as TextField).height);
}

return ;
}

if ($stage.willTrigger(Next2D_WheelEvent.WHEEL)) {
// イベントの伝播を止める
event.preventDefault();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { DisplayObject } from "../../DisplayObject";
import { Event } from "@next2d/events";

/**
* @description DisplayObjectのREMOVEDイベントを実行
* Execute the REMOVED event of DisplayObject
*
* @param {DisplayObject} display_object
* @return {void}
* @method
* @protected
*/
export const execute = <D extends DisplayObject>(display_object: D): void =>
{
if (!display_object.$added) {
return ;
}

display_object.$added = false;
if (display_object.willTrigger(Event.REMOVED)) {
display_object.dispatchEvent(new Event(Event.REMOVED, true));
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { DisplayObject } from "../../DisplayObject";
import { Event } from "@next2d/events";
import { $stageAssignedMap } from "../../DisplayObjectUtil";

/**
* @description DisplayObjectのREMOVED_FROM_STAGEイベントを実行
* Execute the REMOVED_FROM_STAGE event of DisplayObject
*
* @param {DisplayObject} display_object
* @return {void}
* @method
* @protected
*/
export const execute = <D extends DisplayObject>(display_object: D): void =>
{
if (!display_object.$addedToStage
|| !$stageAssignedMap.has(display_object)
) {
return ;
}

display_object.$addedToStage = false;
if (display_object.willTrigger(Event.REMOVED_FROM_STAGE)) {
display_object.dispatchEvent(new Event(Event.REMOVED_FROM_STAGE));
}
};
5 changes: 3 additions & 2 deletions packages/display/src/DisplayObjectContainer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { DisplayObject } from "./DisplayObject";
import type { IDisplayObject } from "./interface/IDisplayObject";
import { execute as displayObjectContainerAddChildUseCase } from "./DisplayObjectContainer/usecase/DisplayObjectContainerAddChildUseCase";
import { execute as displayObjectContainerRemoveChildUseCase } from "./DisplayObjectContainer/usecase/DisplayObjectContainerRemoveChildUseCase";
import { $getArray } from "./DisplayObjectUtil";
import { InteractiveObject } from "./InteractiveObject";

Expand Down Expand Up @@ -238,8 +239,8 @@ export class DisplayObjectContainer extends InteractiveObject
// if (display_object.parent && display_object.parent !== this) {
// throw new Error("ArgumentError: Parent-child relationship does not match.");
// }
return display_object;
// return this._$remove(child);

return displayObjectContainerRemoveChildUseCase(this, display_object);
}

// /**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { DisplayObjectContainer } from "../../DisplayObjectContainer";
import { execute as displayObjectDispatchRemovedToStageEventService } from "../../DisplayObject/service/DisplayObjectDispatchRemovedToStageEventService";

/**
* @description ステージに追加された DisplayObjectContainer の子要素のREMOVED_FROM_STAGEイベントを発行
* Issue REMOVED_FROM_STAGE events for child elements of DisplayObjectContainer added to the stage
*
* @param {DisplayObjectContainer} display_object_container
* @return {void}
* @method
* @protected
*/
export const execute = <C extends DisplayObjectContainer>(
display_object_container: C
): void => {

const children = display_object_container.children;
for (let idx = 0; idx < children.length; ++idx) {

const child = children[idx];
if (!child) {
continue;
}

displayObjectDispatchRemovedToStageEventService(child);

if (!child.isContainerEnabled) {
continue;
}

execute(child as unknown as DisplayObjectContainer);
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { DisplayObjectContainer } from "../../DisplayObjectContainer";
import {
$rootMap,
$stageAssignedMap
} from "../../DisplayObjectUtil";

/**
* @description DisplayObjectContainer の子要素に設定した root と stage を解除
* Remove the root and stage set for the child elements of DisplayObjectContainer
*
* @param {DisplayObjectContainer} display_object_container
* @return {void}
* @method
* @protected
*/
export const execute = <C extends DisplayObjectContainer>(
display_object_container: C
): void => {

const children = display_object_container.children;
for (let idx = 0; idx < children.length; ++idx) {

const child = children[idx];
if (!child) {
continue;
}

// set root and stage
$rootMap.delete(child);
$stageAssignedMap.delete(child);

if (!child.isContainerEnabled) {
continue;
}

execute(child as DisplayObjectContainer);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,5 @@ export const execute = <P extends DisplayObjectContainer, D extends DisplayObjec
}
}

display_object.changed = true;
displayObjectApplyChangesService(display_object_container);
displayObjectApplyChangesService(display_object);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import type { DisplayObject } from "../../DisplayObject";
import type { DisplayObjectContainer } from "../../DisplayObjectContainer";
import { execute as displayObjectApplyChangesService } from "../../DisplayObject/service/DisplayObjectApplyChangesService";
import { execute as displayObjectContainerUnAssignStageAndRootService } from "../service/DisplayObjectContainerUnAssignStageAndRootService";
import { execute as displayObjectDispatchRemovedEventService } from "../../DisplayObject/service/DisplayObjectDispatchRemovedEventService";
import { execute as displayObjectDispatchRemovedToStageEventService } from "../../DisplayObject/service/DisplayObjectDispatchRemovedToStageEventService";
import { execute as displayObjectContainerRemovedToStageService } from "../service/DisplayObjectContainerRemovedToStageService";
import {
$parentMap,
$rootMap,
$stageAssignedMap
} from "../../DisplayObjectUtil";

/**
* @description 指定の DisplayObject を DisplayObjectContainer から削除します。
* Deletes the specified DisplayObject from the DisplayObjectContainer.
*
* @param {DisplayObjectContainer} display_object_container
* @param {DisplayObject} display_object
* @return {DisplayObject}
* @method
* @protected
*/
export const execute = <P extends DisplayObjectContainer, D extends DisplayObject>(
display_object_container: P,
display_object: D
): D => {

const children = display_object_container.children;
const depth = children.indexOf(display_object);
if (depth > -1) {
children.splice(depth, 1);
}

// dispatch removed event
displayObjectDispatchRemovedEventService(display_object);

// ステージに登録されている場合はステージからの削除イベントを実行
if ($stageAssignedMap.has(display_object_container)) {
displayObjectDispatchRemovedToStageEventService(display_object);

if (display_object.isContainerEnabled) {
displayObjectContainerRemovedToStageService(
display_object as unknown as DisplayObjectContainer
);
}
}

// remove root and stage
if ($stageAssignedMap.has(display_object_container)) {
if (!$rootMap.has(display_object)) {
$rootMap.delete(display_object);
}

if ($stageAssignedMap.has(display_object)) {
$stageAssignedMap.delete(display_object);
}

// コンテナであれば子孫の DisplayObject に対しても Stage と Root を解除
if (display_object.isContainerEnabled) {
displayObjectContainerUnAssignStageAndRootService(
display_object as unknown as DisplayObjectContainer
);
}
}

// remove parent-child relationship
if ($parentMap.has(display_object)) {
$parentMap.delete(display_object);
}

// apply changes
displayObjectApplyChangesService(display_object_container);

return display_object;
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,5 @@ describe("TextFieldSetScrollXUseCase.js test", () =>
execute(textField, 10);

expect(textField.$scrollX).toBe(0);

textField.scrollEnabled = true;
textField.autoSize = "none";
execute(textField, 10);

expect(textField.$scrollX).toBe(10);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const execute = (text_field: TextField, scroll_x: number): void =>
}

const width = text_field.width;
scroll_x = $clamp(scroll_x, 0, width + 0.5, 0);
scroll_x = $clamp(scroll_x, 0, width + 4, 0);
if (text_field.scrollX === scroll_x) {
return ;
}
Expand All @@ -56,7 +56,7 @@ export const execute = (text_field: TextField, scroll_x: number): void =>
xScrollShape.x = text_field.x + 1
+ (width - 1 - xScrollShape.width)
/ (width - 1)
* (text_field.scrollX - 1);
* (scroll_x - 1);

xScrollShape.y = text_field.y + text_field.height
- xScrollShape.height - 0.5;
Expand Down Expand Up @@ -85,11 +85,11 @@ export const execute = (text_field: TextField, scroll_x: number): void =>

xScrollShape.setLocalVariable("job", job);
}

text_field.$scrollX = scroll_x;
}

if (text_field.willTrigger(Event.SCROLL)) {
text_field.dispatchEvent(new Event(Event.SCROLL, true));
}

text_field.$scrollX = scroll_x;
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ describe("TextFieldSetScrollYUseCase.js test", () =>

textField.scrollEnabled = true;
textField.autoSize = "none";

execute(textField, 10);
expect(textField.scrollY).toBe(10);

textField.multiline = false;
textField.wordWrap = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const execute = (text_field: TextField, scroll_y: number): void =>
}

const height = text_field.height;
scroll_y = $clamp(scroll_y, 0, height, 0);
scroll_y = $clamp(scroll_y, 0, height + 2, 0);
if (text_field.scrollY === scroll_y) {
return ;
}
Expand Down Expand Up @@ -58,7 +58,7 @@ export const execute = (text_field: TextField, scroll_y: number): void =>
yScrollShape.y = text_field.y + 0.5
+ (height - 1 - yScrollShape.height)
/ (height - 1)
* (text_field.scrollY - 1);
* (scroll_y - 1);

// added sprite
parent.addChildAt(
Expand All @@ -83,12 +83,12 @@ export const execute = (text_field: TextField, scroll_y: number): void =>
job.start();

yScrollShape.setLocalVariable("job", job);

text_field.$scrollY = scroll_y;
}
}

if (text_field.willTrigger(Event.SCROLL)) {
text_field.dispatchEvent(new Event(Event.SCROLL, true));
}

text_field.$scrollY = scroll_y;
};
2 changes: 1 addition & 1 deletion packages/text/src/TextUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ export const $setBlinkingTimerId = (timer_id: NodeJS.Timeout | void): void =>
/**
* @description canvasの位置をセット
* Set the position of the canvas
*
*
* @type {IElementPosition}
* @public
*/
Expand Down

0 comments on commit 5c75d6e

Please sign in to comment.