Skip to content

Commit

Permalink
feat(tiling): On window move via keyboard, place in tree on nearest b…
Browse files Browse the repository at this point in the history
…ranch
  • Loading branch information
mmstick committed Jan 12, 2021
1 parent ad72dee commit 6a2d6eb
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 29 deletions.
14 changes: 7 additions & 7 deletions src/auto_tiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as stack from 'stack';

import type { Entity } from 'ecs';
import type { Ext } from 'extension';
import type { Forest } from 'forest';
import type { Forest, MoveBy } from 'forest';
import type { Fork } from 'fork';
import type { Rectangle } from 'rectangle';
import type { Result } from 'result';
Expand Down Expand Up @@ -146,8 +146,8 @@ export class AutoTiler {
}

/** Tiles a window into another */
attach_to_window(ext: Ext, attachee: ShellWindow, attacher: ShellWindow, cursor: Rectangle, stack_from_left: boolean = true) {
let attached = this.forest.attach_window(ext, attachee.entity, attacher.entity, cursor, stack_from_left);
attach_to_window(ext: Ext, attachee: ShellWindow, attacher: ShellWindow, move_by: MoveBy, stack_from_left: boolean = true) {
let attached = this.forest.attach_window(ext, attachee.entity, attacher.entity, move_by, stack_from_left);

if (attached) {
const [, fork] = attached;
Expand Down Expand Up @@ -186,7 +186,7 @@ export class AutoTiler {
if (toplevel) {
const onto = this.forest.largest_window_on(ext, toplevel);
if (onto) {
if (this.attach_to_window(ext, onto, win, lib.cursor_rect())) {
if (this.attach_to_window(ext, onto, win, { cursor: lib.cursor_rect() })) {
return;
}
}
Expand All @@ -208,7 +208,7 @@ export class AutoTiler {
if (result.kind == ERR) {
this.attach_to_workspace(ext, win, ext.workspace_id(win));
} else {
this.attach_to_window(ext, result.value, win, lib.cursor_rect())
this.attach_to_window(ext, result.value, win, { cursor: lib.cursor_rect() })
}
}

Expand Down Expand Up @@ -333,7 +333,7 @@ export class AutoTiler {
if (toplevel) {
const attach_to = this.forest.largest_window_on(ext, toplevel);
if (attach_to) {
this.attach_to_window(ext, attach_to, win, cursor);
this.attach_to_window(ext, attach_to, win, {cursor});
return;
}
}
Expand All @@ -360,7 +360,7 @@ export class AutoTiler {
this.detach_window(ext, win.entity);

if (attach_to) {
this.attach_to_window(ext, attach_to, win, cursor);
this.attach_to_window(ext, attach_to, win, {cursor});
} else {
attach_mon()
}
Expand Down
64 changes: 44 additions & 20 deletions src/forest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as movement from 'movement';
import * as Rect from 'rectangle';
import * as Node from 'node';
import * as Fork from 'fork';
import * as geom from 'geom';

import type { Entity } from 'ecs';
import type { Rectangle } from './rectangle';
Expand All @@ -25,6 +26,13 @@ const UP = Movement.UP;
const LEFT = Movement.LEFT;
const RIGHT = Movement.RIGHT;

export interface MoveByCursor { cursor: Rectangular }

export interface MoveByKeyboard {
src: Rectangular
}

export type MoveBy = MoveByCursor | MoveByKeyboard

/** A request to move a window into a new location. */
interface Request {
Expand Down Expand Up @@ -178,9 +186,34 @@ export class Forest extends Ecs.World {
}

/** Attaches a `new` window to the fork which `onto` is attached to. */
attach_window(ext: Ext, onto_entity: Entity, new_entity: Entity, cursor: Rectangle, stack_from_left: boolean): [Entity, Fork.Fork] | null {
attach_window(ext: Ext, onto_entity: Entity, new_entity: Entity, move_by: MoveBy, stack_from_left: boolean): [Entity, Fork.Fork] | null {
const right_node = Node.Node.window(new_entity);

function swap_branches(fork: Fork.Fork) {
const temp = fork.left
fork.left = fork.right as Node.Node
fork.right = temp
}

const placement = (fork: Fork.Fork, left_: [number, number, number, number], right_: [number, number, number, number]) => {
const inner_left = new Rect.Rectangle(left_), inner_right = new Rect.Rectangle(right_)

if ("cursor" in move_by) {
if (inner_left.contains(move_by.cursor)) {
swap_branches(fork)
}
} else if ("src" in move_by) {
const { src } = move_by

const from : [number, number] = [src.x + (src.width / 2), src.y + (src.height / 2)]

const left = geom.shortest_side(from, inner_left)
const right = geom.shortest_side(from, inner_right)

if (left < right) swap_branches(fork)
}
}

for (const [entity, fork] of this.forks.iter()) {
if (fork.left.is_window(onto_entity)) {
if (fork.right) {
Expand All @@ -189,16 +222,11 @@ export class Forest extends Ecs.World {

const { x, y, width, height } = new_fork.area;

const inner_left = new Rect.Rectangle(new_fork.is_horizontal()
? [x, y, width / 2, height]
: [x, y, width, height / 2]
);
const [left_, right_]: [[number, number, number, number], [number, number, number, number]] = new_fork.is_horizontal()
? [[x, y, width / 2, height], [x + (width / 2), y, width / 2, height]]
: [[x, y, width, height / 2], [x, y + (height / 2), width, height / 2]]

if (inner_left.contains(cursor)) {
const temp = new_fork.left;
new_fork.left = new_fork.right as Node.Node;
new_fork.right = temp;
}
placement(new_fork, left_, right_)

fork.left = Node.Node.fork(fork_entity);
this.parents.insert(fork_entity, entity);
Expand All @@ -217,18 +245,14 @@ export class Forest extends Ecs.World {
const [fork_entity, new_fork] = this.create_fork(fork.right, right_node, area, fork.workspace, fork.monitor);
const { x, y, width, height } = new_fork.area;

const inner_left = new Rect.Rectangle(new_fork.is_horizontal()
? [x, y, width / 2, height]
: [x, y, width, height / 2]
);

if (inner_left.contains(cursor)) {
const temp = new_fork.left;
new_fork.left = new_fork.right as Node.Node;
new_fork.right = temp;
}
const [left_, right_]: [[number, number, number, number], [number, number, number, number]] = new_fork.is_horizontal()
? [[x, y, width / 2, height], [x + width / 2, y, width / 2, height]]
: [[x, y, width, height / 2], [x, y + height / 2, width, height / 2]]

fork.right = Node.Node.fork(fork_entity);

placement(new_fork, left_, right_)

this.parents.insert(fork_entity, entity);
return this._attach(onto_entity, new_entity, this.on_attach, entity, fork, [fork_entity, new_fork]);
} else if (fork.right.is_in_stack(onto_entity)) {
Expand Down
6 changes: 4 additions & 2 deletions src/tiling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ export class Tiler {

focused.ignore_detach = true;
at.detach_window(ext, focused.entity);
at.attach_to_window(ext, move_to, focused, Lib.cursor_rect(), stack_from_left);
at.attach_to_window(ext, move_to, focused, { cursor: Lib.cursor_rect() }, stack_from_left);
watching = focused;
} else {
const parent = at.windows_are_siblings(focused.entity, move_to.entity);
Expand Down Expand Up @@ -466,9 +466,11 @@ export class Tiler {
}

if (!watching) {
let movement = { src: focused.meta.get_frame_rect()}

focused.ignore_detach = true;
at.detach_window(ext, focused.entity);
at.attach_to_window(ext, move_to, focused, Lib.cursor_rect(), false);
at.attach_to_window(ext, move_to, focused, movement, false);
watching = focused;
}
}
Expand Down

0 comments on commit 6a2d6eb

Please sign in to comment.