Skip to content

Commit

Permalink
rework update mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
daign committed May 17, 2023
1 parent 9866492 commit e6d3998
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 159 deletions.
6 changes: 1 addition & 5 deletions lib/application/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,19 @@ export class Application extends Group {
super();

this.selectionManager = new SelectionManager();
this.updateManager = new UpdateManager();

if ( interactive ) {
// If interactive then use the InteractiveViewPort and ControlLayer.
this.drawingLayer = new InteractiveViewport( context, this );
this.appendChild( this.drawingLayer );
this.controlLayer = new ControlLayer( this );
this.appendChild( this.controlLayer );


} else {
// If not interactive then use the normal Viewport and no ControlLayer.
this.drawingLayer = new Viewport( context, this );
this.appendChild( this.drawingLayer );
}

this.updateManager = new UpdateManager( this.selectionManager, this.controlLayer,
this.drawingLayer );
}

/**
Expand Down
7 changes: 6 additions & 1 deletion lib/application/controlLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ export class ControlLayer extends Group {
super();

this.baseClass = 'control-layer';

// Subscribe to the update manager to know when to redraw the controls.
this.application.updateManager.redrawControlsSignal.setObserver( (): void => {
this.redrawControls();
} )
}

/**
* Create the control elements for the active control object.
*/
public createControls(): void {
private redrawControls(): void {
this.clearChildren();

const activeObject = this.application.selectionManager.activeObject;
Expand Down
1 change: 1 addition & 0 deletions lib/application/interactiveViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export class InteractiveViewport extends Viewport {
// Define action to deactivate element.
handle.clicked = (): void => {
this.application.selectionManager.setSelection( null, null );
this.application.updateManager.redrawSignal.emit();
};

// Define zoom action.
Expand Down
76 changes: 19 additions & 57 deletions lib/application/updateManager.ts
Original file line number Diff line number Diff line change
@@ -1,73 +1,35 @@
import { Observable } from '@daign/observable';

import { SelectionManager } from './selectionManager';
import { ControlLayer } from './controlLayer';
import { Viewport } from './viewport';

// Observable implementation with a public invoke method.
class EventSource extends Observable {
public constructor() {
super();
}
public invoke(): void {
this.notifyObservers();
}
}
import { EventEmitter, UnicastEventEmitter } from '@daign/observable';

/**
* Class that manages update and change notifications between components.
* Class that manages the steps to update and redraw the graphic.
*/
export class UpdateManager {
// Subscribe to know when the graphic data has changes.
public dataChangeEvent: EventSource = new EventSource();
// Incoming signal to run the update and redraw cycle.
public redrawSignal: UnicastEventEmitter = new UnicastEventEmitter();

// Subscribe to know when the selection changes.
public selectionChangeEvent: EventSource = new EventSource();
// Components that want to update when the graphic was changed subscribe to this event.
public graphicUpdateEvent: EventEmitter = new EventEmitter();

// Subscribe to know when the graphic needs to be redrawn.
public redrawEvent: EventSource = new EventSource();
// The control layer subscribes to this event to know when to redraw the controls.
public redrawControlsSignal: UnicastEventEmitter = new UnicastEventEmitter();

// Subscribe to know when the viewport has changed.
public viewportInputEvent: EventSource = new EventSource();
// Subscribe your render function to this event.
public renderSignal: UnicastEventEmitter = new UnicastEventEmitter();

/**
* Constructor.
* @param selectionManager - The selection manager.
* @param controlLayer - The control layer.
* @param drawingLayer - The drawing layer.
*/
public constructor(
private selectionManager: SelectionManager,
private controlLayer: ControlLayer | null,
private drawingLayer: Viewport
) {
// Actions to take when the selection manager has changes.
this.selectionManager.subscribeToChanges( (): void => {
this.selectionChangeEvent.invoke();
this.createControls();
this.redrawEvent.invoke();
} );
public constructor() {
// Run the update and redraw cycle on incoming signal.
this.redrawSignal.setObserver( (): void => {
// Notify components that want to update when the graphic was changed.
this.graphicUpdateEvent.emit();

// Actions to take when the drawing layer has changes.
this.drawingLayer.subscribeToChanges( (): void => {
this.dataChangeEvent.invoke();
this.createControls();
this.redrawEvent.invoke();
} );
// Redraw the controls.
this.redrawControlsSignal.emit();

// Actions to take when the viewport has changed.
this.viewportInputEvent.subscribeToChanges( (): void => {
this.createControls();
this.redrawEvent.invoke();
// Render the graphic.
this.renderSignal.emit();
} );
}

/**
* Let the control layer create the controls for the currently selected object.
*/
public createControls(): void {
if ( this.controlLayer ) {
this.controlLayer.createControls();
}
}
}
2 changes: 1 addition & 1 deletion lib/application/viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,6 @@ export class Viewport extends Group {
this.scaleTransform.scaling.copy( scaling );
this.translateTransform.translation.copy( translation );

this.application.updateManager.viewportInputEvent.invoke();
this.application.updateManager.redrawSignal.emit();
}
}
2 changes: 2 additions & 0 deletions lib/control-elements/controlPoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,7 @@ export class ControlPoint extends Group {
} );

this.calculateOffset();

this.application.updateManager.redrawSignal.emit();
}
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@daign/2d-graphics",
"version": "1.1.2",
"version": "1.1.3",
"description": "Two dimensional graphics library that implements the daign-2d-pipeline.",
"keywords": [
"graphics",
Expand Down Expand Up @@ -45,6 +45,7 @@
"dependencies": {
"@daign/handle": "^1.1.0",
"@daign/math": "^1.1.1",
"@daign/observable": "^1.1.3",
"@daign/2d-pipeline": "^1.1.1",
"@daign/style-sheets": "^1.1.0"
},
Expand Down
25 changes: 20 additions & 5 deletions test/application/controlLayer.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect } from 'chai';
import { spy } from 'sinon';

import { View } from '@daign/2d-pipeline';
import { Vector2 } from '@daign/math';
Expand All @@ -25,9 +26,23 @@ describe( 'ControlLayer', (): void => {
// Assert
expect( ( controlLayer as any ).application ).to.equal( application );
} );

it( 'should call redrawControls when update manager emits signal', (): void => {
// Arrange
const context = new TestContext();
const application = new Application( context );
const controlLayer = new ControlLayer( application );
const redrawControlsSpy = spy( controlLayer as any, 'redrawControls' );

// Act
application.updateManager.redrawControlsSignal.emit();

// Assert
expect( redrawControlsSpy.calledOnce ).to.be.true;
} );
} );

describe( 'createControls', (): void => {
describe( 'redrawControls', (): void => {
it( 'should attach the node returned from the active object', (): void => {
// Arrange
const context = new TestContext();
Expand All @@ -45,14 +60,14 @@ describe( 'ControlLayer', (): void => {
application.selectionManager.setSelection( controlObject, null );

// Act
controlLayer.createControls();
( controlLayer as any ).redrawControls();

// Assert
expect( controlLayer.children.length ).to.equal( 1 );

// Act
application.selectionManager.setSelection( null, null );
controlLayer.createControls();
( controlLayer as any ).redrawControls();

// Assert
expect( controlLayer.children.length ).to.equal( 0 );
Expand All @@ -73,12 +88,12 @@ describe( 'ControlLayer', (): void => {
application.drawingLayer.appendChild( controlObject );

application.selectionManager.setSelection( controlObject, null );
controlLayer.createControls();
( controlLayer as any ).redrawControls();
expect( controlLayer.children.length ).to.equal( 1 );

// Act
application.selectionManager.setSelection( null, null );
controlLayer.createControls();
( controlLayer as any ).redrawControls();

// Assert
expect( controlLayer.children.length ).to.equal( 0 );
Expand Down
4 changes: 2 additions & 2 deletions test/application/interarctiveViewport.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ describe( 'InteractiveViewport', (): void => {
const dragEvent = new MockEvent().setClientPoint( 1, 10 );
const endEvent = new MockEvent().setClientPoint( 2, 10 );

const redrawSpy = spy( application.updateManager.redrawEvent, 'invoke' );
const redrawSpy = spy( application.updateManager.redrawSignal, 'emit' );

// Act
domNode.sendEvent( 'mousedown', startEvent );
Expand Down Expand Up @@ -390,7 +390,7 @@ describe( 'InteractiveViewport', (): void => {
const controlObject = new TestObject();
application.selectionManager.setSelection( controlObject, null );

const redrawSpy = spy( application.updateManager.redrawEvent, 'invoke' );
const redrawSpy = spy( application.updateManager.redrawSignal, 'emit' );

const clickEvent = new MockEvent();
clickEvent.setOffsetPoint( 100, 100 );
Expand Down

0 comments on commit e6d3998

Please sign in to comment.