@@ -9,6 +9,7 @@ import * as movement from 'movement';
99import * as Rect from 'rectangle' ;
1010import * as Node from 'node' ;
1111import * as Fork from 'fork' ;
12+ import * as geom from 'geom' ;
1213
1314import type { Entity } from 'ecs' ;
1415import type { Rectangle } from './rectangle' ;
@@ -25,6 +26,13 @@ const UP = Movement.UP;
2526const LEFT = Movement . LEFT ;
2627const RIGHT = Movement . RIGHT ;
2728
29+ export interface MoveByCursor { cursor : Rectangular }
30+
31+ export interface MoveByKeyboard {
32+ src : Rectangular
33+ }
34+
35+ export type MoveBy = MoveByCursor | MoveByKeyboard
2836
2937/** A request to move a window into a new location. */
3038interface Request {
@@ -178,9 +186,34 @@ export class Forest extends Ecs.World {
178186 }
179187
180188 /** Attaches a `new` window to the fork which `onto` is attached to. */
181- attach_window ( ext : Ext , onto_entity : Entity , new_entity : Entity , cursor : Rectangle , stack_from_left : boolean ) : [ Entity , Fork . Fork ] | null {
189+ attach_window ( ext : Ext , onto_entity : Entity , new_entity : Entity , move_by : MoveBy , stack_from_left : boolean ) : [ Entity , Fork . Fork ] | null {
182190 const right_node = Node . Node . window ( new_entity ) ;
183191
192+ function swap_branches ( fork : Fork . Fork ) {
193+ const temp = fork . left
194+ fork . left = fork . right as Node . Node
195+ fork . right = temp
196+ }
197+
198+ const placement = ( fork : Fork . Fork , left_ : [ number , number , number , number ] , right_ : [ number , number , number , number ] ) => {
199+ const inner_left = new Rect . Rectangle ( left_ ) , inner_right = new Rect . Rectangle ( right_ )
200+
201+ if ( "cursor" in move_by ) {
202+ if ( inner_left . contains ( move_by . cursor ) ) {
203+ swap_branches ( fork )
204+ }
205+ } else if ( "src" in move_by ) {
206+ const { src } = move_by
207+
208+ const from : [ number , number ] = [ src . x + ( src . width / 2 ) , src . y + ( src . height / 2 ) ]
209+
210+ const left = geom . shortest_side ( from , inner_left )
211+ const right = geom . shortest_side ( from , inner_right )
212+
213+ if ( left < right ) swap_branches ( fork )
214+ }
215+ }
216+
184217 for ( const [ entity , fork ] of this . forks . iter ( ) ) {
185218 if ( fork . left . is_window ( onto_entity ) ) {
186219 if ( fork . right ) {
@@ -189,16 +222,11 @@ export class Forest extends Ecs.World {
189222
190223 const { x, y, width, height } = new_fork . area ;
191224
192- const inner_left = new Rect . Rectangle ( new_fork . is_horizontal ( )
193- ? [ x , y , width / 2 , height ]
194- : [ x , y , width , height / 2 ]
195- ) ;
225+ const [ left_ , right_ ] : [ [ number , number , number , number ] , [ number , number , number , number ] ] = new_fork . is_horizontal ( )
226+ ? [ [ x , y , width / 2 , height ] , [ x + ( width / 2 ) , y , width / 2 , height ] ]
227+ : [ [ x , y , width , height / 2 ] , [ x , y + ( height / 2 ) , width , height / 2 ] ]
196228
197- if ( inner_left . contains ( cursor ) ) {
198- const temp = new_fork . left ;
199- new_fork . left = new_fork . right as Node . Node ;
200- new_fork . right = temp ;
201- }
229+ placement ( new_fork , left_ , right_ )
202230
203231 fork . left = Node . Node . fork ( fork_entity ) ;
204232 this . parents . insert ( fork_entity , entity ) ;
@@ -217,18 +245,14 @@ export class Forest extends Ecs.World {
217245 const [ fork_entity , new_fork ] = this . create_fork ( fork . right , right_node , area , fork . workspace , fork . monitor ) ;
218246 const { x, y, width, height } = new_fork . area ;
219247
220- const inner_left = new Rect . Rectangle ( new_fork . is_horizontal ( )
221- ? [ x , y , width / 2 , height ]
222- : [ x , y , width , height / 2 ]
223- ) ;
224-
225- if ( inner_left . contains ( cursor ) ) {
226- const temp = new_fork . left ;
227- new_fork . left = new_fork . right as Node . Node ;
228- new_fork . right = temp ;
229- }
248+ const [ left_ , right_ ] : [ [ number , number , number , number ] , [ number , number , number , number ] ] = new_fork . is_horizontal ( )
249+ ? [ [ x , y , width / 2 , height ] , [ x + width / 2 , y , width / 2 , height ] ]
250+ : [ [ x , y , width , height / 2 ] , [ x , y + height / 2 , width , height / 2 ] ]
230251
231252 fork . right = Node . Node . fork ( fork_entity ) ;
253+
254+ placement ( new_fork , left_ , right_ )
255+
232256 this . parents . insert ( fork_entity , entity ) ;
233257 return this . _attach ( onto_entity , new_entity , this . on_attach , entity , fork , [ fork_entity , new_fork ] ) ;
234258 } else if ( fork . right . is_in_stack ( onto_entity ) ) {
0 commit comments