Make mouse behavior better
This commit is contained in:
parent
7f9e873323
commit
b248a016a9
66
codetab.ts
66
codetab.ts
@ -177,6 +177,7 @@ const transformForPaste = (text: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
|
doubleClickTimer: 0,
|
||||||
history: [] as Array<{code: string, anchor: number, focus: number}>,
|
history: [] as Array<{code: string, anchor: number, focus: number}>,
|
||||||
historyDebounce: 0,
|
historyDebounce: 0,
|
||||||
historyIndex: 0,
|
historyIndex: 0,
|
||||||
@ -222,6 +223,7 @@ const state = {
|
|||||||
}
|
}
|
||||||
this.historyDebounce = historyDebounceFrames;
|
this.historyDebounce = historyDebounceFrames;
|
||||||
},
|
},
|
||||||
|
wordMode: false,
|
||||||
scrollX: 0,
|
scrollX: 0,
|
||||||
scrollY: 0,
|
scrollY: 0,
|
||||||
anchor: 0,
|
anchor: 0,
|
||||||
@ -240,6 +242,34 @@ const state = {
|
|||||||
clampInRange(n: number) {
|
clampInRange(n: number) {
|
||||||
return Math.max(0, Math.min(n, this.code.length))
|
return Math.max(0, Math.min(n, this.code.length))
|
||||||
},
|
},
|
||||||
|
findNearestWordBoundaryLeft(index: number) {
|
||||||
|
if (index === this.code.length-1) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
const words1 = this.code.slice(0, index+1).split(/\b/g);
|
||||||
|
if (words1[words1.length-1].length === 1) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
const words = this.code.slice(0, index).split(/\b/g);
|
||||||
|
if (!words.length) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return index-words[words.length-1].length;
|
||||||
|
},
|
||||||
|
findNearestWordBoundaryRight(index: number) {
|
||||||
|
if (index === 0) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
const words1 = this.code.slice(index-1).split(/\b/g);
|
||||||
|
if (words1[0].length === 1) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
const words = this.code.slice(index).split(/\b/g);
|
||||||
|
if (!words.length) {
|
||||||
|
return this.code.length;
|
||||||
|
}
|
||||||
|
return index+words[0].length;
|
||||||
|
},
|
||||||
setSelection(anchor: number | {x: number, y: number}, focus?: number | {x: number, y: number}) {
|
setSelection(anchor: number | {x: number, y: number}, focus?: number | {x: number, y: number}) {
|
||||||
if (typeof anchor !== "number") {
|
if (typeof anchor !== "number") {
|
||||||
anchor = gridToIndex(this.code, anchor.x, anchor.y);
|
anchor = gridToIndex(this.code, anchor.x, anchor.y);
|
||||||
@ -248,14 +278,36 @@ const state = {
|
|||||||
if (typeof focus !== "number") {
|
if (typeof focus !== "number") {
|
||||||
focus = gridToIndex(this.code, focus.x, focus.y);
|
focus = gridToIndex(this.code, focus.x, focus.y);
|
||||||
}
|
}
|
||||||
this.anchor = this.clampInRange(anchor),
|
this.anchor = this.clampInRange(anchor);
|
||||||
this.focus = this.clampInRange(focus);
|
this.focus = this.clampInRange(focus);
|
||||||
|
if (this.wordMode) {
|
||||||
|
console.log('word mode', this.anchor, this.focus, this.findNearestWordBoundaryLeft(this.anchor), this.findNearestWordBoundaryRight(this.focus));
|
||||||
|
if (this.anchor <= this.focus) {
|
||||||
|
this.anchor = this.findNearestWordBoundaryLeft(this.anchor);
|
||||||
|
this.focus = this.findNearestWordBoundaryRight(this.focus);
|
||||||
|
} else {
|
||||||
|
this.anchor = this.findNearestWordBoundaryRight(this.anchor);
|
||||||
|
this.focus = this.findNearestWordBoundaryLeft(this.focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.anchor = this.clampInRange(this.anchor);
|
||||||
|
this.focus = this.clampInRange(this.focus);
|
||||||
},
|
},
|
||||||
setFocus(focus: number | {x: number, y: number}) {
|
setFocus(focus: number | {x: number, y: number}) {
|
||||||
if (typeof focus !== "number") {
|
if (typeof focus !== "number") {
|
||||||
focus = gridToIndex(this.code, focus.x, focus.y);
|
focus = gridToIndex(this.code, focus.x, focus.y);
|
||||||
}
|
}
|
||||||
this.focus = this.clampInRange(focus);
|
this.focus = this.clampInRange(focus);
|
||||||
|
if (this.wordMode) {
|
||||||
|
if (this.anchor <= this.focus) {
|
||||||
|
this.anchor = this.findNearestWordBoundaryLeft(this.anchor);
|
||||||
|
this.focus = this.findNearestWordBoundaryRight(this.focus);
|
||||||
|
} else {
|
||||||
|
this.anchor = this.findNearestWordBoundaryRight(this.anchor);
|
||||||
|
this.focus = this.findNearestWordBoundaryLeft(this.focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.focus = this.clampInRange(this.focus);
|
||||||
},
|
},
|
||||||
insertText(text: string) {
|
insertText(text: string) {
|
||||||
const {code, anchor, focus} = this;
|
const {code, anchor, focus} = this;
|
||||||
@ -453,13 +505,23 @@ const update = async () => {
|
|||||||
state.snapshot();
|
state.snapshot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (state.doubleClickTimer > 0) {
|
||||||
|
state.doubleClickTimer -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (mouseDown()) {
|
if (mouseDown() && !shiftKeyDown()) {
|
||||||
|
if (state.doubleClickTimer > 0) {
|
||||||
|
state.wordMode = true;
|
||||||
|
} else {
|
||||||
|
state.doubleClickTimer = 10;
|
||||||
|
}
|
||||||
const {x, y} = mousePos();
|
const {x, y} = mousePos();
|
||||||
state.setSelection(pixelToIndex(state.code, x, y-8));
|
state.setSelection(pixelToIndex(state.code, x, y-8));
|
||||||
} else if (mouseHeld()) {
|
} else if (mouseHeld()) {
|
||||||
const {x, y} = mousePos();
|
const {x, y} = mousePos();
|
||||||
state.setFocus(pixelToIndex(state.code, x, y-8));
|
state.setFocus(pixelToIndex(state.code, x, y-8));
|
||||||
|
} else {
|
||||||
|
state.wordMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const keyboardString = getKeyboardString();
|
const keyboardString = getKeyboardString();
|
||||||
|
12
mouse.ts
12
mouse.ts
@ -14,7 +14,7 @@ const mouseButtonsDown = {
|
|||||||
[M.MIDDLE]: false,
|
[M.MIDDLE]: false,
|
||||||
};
|
};
|
||||||
const mouseEvents: Array<{
|
const mouseEvents: Array<{
|
||||||
type: "click" | "down" | "up" | "move",
|
type: "click" | "down" | "up" | "move" | "dblclick",
|
||||||
button: typeof M[keyof typeof M],
|
button: typeof M[keyof typeof M],
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
@ -35,9 +35,9 @@ const eventPixelCoords = (evt: WindowMouseEvent) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// addEventListener("dblclick", (evt) => {
|
addEventListener("dblclick", (evt) => {
|
||||||
// console.log("dblclick", evt.button, evt.clientX, evt.clientY);
|
mouseEvents.push({type: "dblclick", button: evt.button, ...eventPixelCoords(evt)});
|
||||||
// });
|
});
|
||||||
|
|
||||||
addEventListener("click", (evt) => {
|
addEventListener("click", (evt) => {
|
||||||
mouseEvents.push({type: "click", button: evt.button, ...eventPixelCoords(evt)});
|
mouseEvents.push({type: "click", button: evt.button, ...eventPixelCoords(evt)});
|
||||||
@ -87,6 +87,10 @@ export const mouseClick = (button: number = M.LEFT) => {
|
|||||||
return mouseEvents.some(ev => ev.button === button && ev.type === "click");
|
return mouseEvents.some(ev => ev.button === button && ev.type === "click");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const mouseDoubleClick = (button: number = M.LEFT) => {
|
||||||
|
return mouseEvents.some(ev => ev.button === button && ev.type === "dblclick");
|
||||||
|
}
|
||||||
|
|
||||||
export const mouseHeld = (button: number = M.LEFT) => {
|
export const mouseHeld = (button: number = M.LEFT) => {
|
||||||
return mouseButtonsDown[button];
|
return mouseButtonsDown[button];
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user