Skip to content

Commit

Permalink
Proof of concept of decorator API
Browse files Browse the repository at this point in the history
  • Loading branch information
gaearon committed Apr 18, 2015
1 parent 305686b commit 84b0ec4
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 141 deletions.
20 changes: 9 additions & 11 deletions examples/_dustbin-simple/Box.js
Expand Up @@ -29,7 +29,14 @@ const BoxSource = {
}
};

class Box extends Component {
@configureDragDrop(
register => register.dragSource(ItemTypes.BOX, BoxSource),
boxSource => ({
dragSourceRef: boxSource.connect(),
isDragging: boxSource.isDragging()
})
)
export default class Box extends Component {
static propTypes = {
name: PropTypes.string.isRequired,
isDragging: PropTypes.bool.isRequired,
Expand All @@ -48,13 +55,4 @@ class Box extends Component {
</div>
);
}
}

export default configureDragDrop(Box,
register => register.dragSource(ItemTypes.BOX, BoxSource),

(connect, monitor, dragSourceId) => ({
dragSourceRef: connect.dragSource(dragSourceId),
isDragging: monitor.isDragging(dragSourceId)
})
);
}
22 changes: 10 additions & 12 deletions examples/_dustbin-simple/Dustbin.js
Expand Up @@ -18,7 +18,15 @@ const BoxTarget = {
}
};

class Dustbin extends Component {
@configureDragDrop(
register => register.dropTarget(ItemTypes.BOX, BoxTarget),
boxTarget => ({
dropTargetRef: boxTarget.connect(),
isOver: boxTarget.isOver(),
canDrop: boxTarget.canDrop()
})
)
export default class Dustbin extends Component {
static propTypes = {
isOver: PropTypes.bool.isRequired,
canDrop: PropTypes.bool.isRequired,
Expand Down Expand Up @@ -46,14 +54,4 @@ class Dustbin extends Component {
</div>
);
}
}

export default configureDragDrop(Dustbin,
register => register.dropTarget(ItemTypes.BOX, BoxTarget),

(connect, monitor, targetId) => ({
dropTargetRef: connect.dropTarget(targetId),
isOver: monitor.isOver(targetId),
canDrop: monitor.canDrop(targetId)
})
);
}
40 changes: 16 additions & 24 deletions modules/ComponentHandlerMap.js
Expand Up @@ -5,9 +5,8 @@ import values from 'lodash/object/values';
import xor from 'lodash/array/xor';

export default class ComponentHandlerMap {
constructor(registry, monitor, handlers, onChange) {
this.registry = registry;
this.monitor = monitor;
constructor(manager, handlers, onChange) {
this.manager = manager;
this.onChange = onChange;

this.changeSubscriptionDisposable = new SerialDisposable();
Expand All @@ -22,38 +21,30 @@ export default class ComponentHandlerMap {

Object.keys(handlers).forEach(key => {
const handler = handlers[key];
const mapping = new ComponentHandlerMapping(this.registry, handler);
const mapping = new ComponentHandlerMapping(this.manager, handler);

this.mappings[key] = mapping;
this.disposable.add(mapping.getDisposable());
});
}

addDisposable(handlerId, disposable) {
const keys = Object.keys(this.mappings);
mapMappings(selector) {
const result = {};

for (let i = 0; i < keys.length; i++) {
const key = keys[i];
Object.keys(this.mappings).forEach(key => {
const mapping = this.mappings[key];
result[key] = selector(mapping);
});

if (mapping.getHandlerId() === handlerId) {
mapping.addDisposable(disposable);
return;
}
}

disposable.dispose();
return result;
}

getHandlerIds() {
const handlerIds = {};

Object.keys(this.mappings).forEach(key => {
const mapping = this.mappings[key];
handlerIds[key] = mapping.getHandlerId();
});
return this.mapMappings(m => m.getHandlerId());
}

return handlerIds;
getHandlerMonitors() {
return this.mapMappings(m => m.getHandlerMonitor());
}

receiveHandlers(nextHandlers) {
Expand All @@ -80,9 +71,10 @@ export default class ComponentHandlerMap {

resubscribe() {
const handlerIds = this.getHandlerIds();
const unsubscribe = this.monitor.subscribe(this.onChange, values(handlerIds));
const disposable = new Disposable(unsubscribe);
const monitor = this.manager.getMonitor();

const unsubscribe = monitor.subscribe(this.onChange, values(handlerIds));
const disposable = new Disposable(unsubscribe);
this.changeSubscriptionDisposable.setDisposable(disposable);
}

Expand Down
20 changes: 8 additions & 12 deletions modules/ComponentHandlerMapping.js
@@ -1,34 +1,30 @@
import { SerialDisposable } from 'disposables'
import { SerialDisposable } from 'disposables';
import HandlerRegistration from './HandlerRegistration';

export default class ComponentHandlerMapping {
constructor(registry, handler) {
this.registry = registry;
constructor(manager, handler) {
this.manager = manager;
this.registration = null;

this.disposable = new SerialDisposable();
this.receiveHandler(handler);
}

getHandlerId() {
if (this.registration) {
return this.registration.handlerId || null;
} else {
return null;
}
return this.registration.getHandlerId();
}

addDisposable(disposable) {
this.registration.addDisposable(disposable);
getHandlerMonitor() {
return this.registration.getHandlerMonitor();
}

receiveHandler(nextHandler) {
const { registration, registry } = this;
const { registration, manager } = this;
if (registration && registration.receiveHandler(nextHandler)) {
return true;
}

const nextRegistration = new HandlerRegistration(registry, nextHandler);
const nextRegistration = new HandlerRegistration(manager, nextHandler);
const nextDisposable = nextRegistration.getDisposable();

this.disposable.setDisposable(nextDisposable);
Expand Down
29 changes: 22 additions & 7 deletions modules/HandlerRegistration.js
Expand Up @@ -2,12 +2,16 @@ import invariant from 'invariant';
import { Disposable, CompositeDisposable } from 'disposables';
import ComponentDragSource from './ComponentDragSource';
import ComponentDropTarget from './ComponentDropTarget';
import SourceMonitor from './SourceMonitor';
import TargetMonitor from './TargetMonitor';

export default class HandlerRegistration {
constructor(registry, handler) {
this.registry = registry;
constructor(manager, handler) {
this.manager = manager;

this.handler = handler;
this.handlerId = null;
this.handlerMonitor = null;

const innerDisposable = new Disposable(this.unregister.bind(this));
this.disposable = new CompositeDisposable(innerDisposable);
Expand All @@ -16,7 +20,11 @@ export default class HandlerRegistration {
}

getHandlerId() {
return this.handlerId || null;
return this.handlerId;
}

getHandlerMonitor() {
return this.handlerMonitor;
}

receiveHandler(nextHandler) {
Expand All @@ -29,22 +37,29 @@ export default class HandlerRegistration {

register() {
invariant(!this.handlerId, 'Already registered.');
const { registry, handler } = this;
const { manager, handler } = this;
const { type } = handler;

const registry = manager.getRegistry();
if (handler instanceof ComponentDragSource) {
this.handlerId = registry.addSource(type, handler);
this.handlerMonitor = new SourceMonitor(manager, this.handlerId);
} else if (handler instanceof ComponentDropTarget) {
this.handlerId = registry.addTarget(type, handler);
this.handlerMonitor = new TargetMonitor(manager, this.handlerId);
} else {
invariant(false, 'Handle is neither a source nor a target.');
}

const monitorDisposable = this.handlerMonitor.getDisposable();
this.disposable.add(monitorDisposable);
}

unregister() {
invariant(this.handlerId, 'Not registered.');
const { registry, handler, handlerId } = this;
const { manager, handler, handlerId } = this;

const registry = manager.getRegistry();
if (handler instanceof ComponentDragSource) {
registry.removeSource(handlerId);
} else if (handler instanceof ComponentDropTarget) {
Expand All @@ -54,8 +69,8 @@ export default class HandlerRegistration {
}

this.handlerId = null;
this.handler = null;
this.registry = null;
this.handlerMonitor = null;
this.manager = null;
}

getDisposable() {
Expand Down
35 changes: 35 additions & 0 deletions modules/SourceMonitor.js
@@ -0,0 +1,35 @@
import { CompositeDisposable } from 'disposables';
import createConnectRef from './createConnectRef';

export default class SourceMonitor {
constructor(manager, sourceId) {
this.manager = manager;
this.sourceId = sourceId;

this.disposable = new CompositeDisposable();

const backend = manager.getBackend();
const connector = backend.connectDragSource(sourceId);

Object.keys(connector).forEach(name => {
const { disposable, ref } = createConnectRef(connector[name]);

this.disposable.add(disposable);
this[name] = () => ref;
});
}

canDrag() {
const monitor = this.manager.getMonitor();
return monitor.canDragSource(this.sourceId);
}

isDragging() {
const monitor = this.manager.getMonitor();
return monitor.isDraggingSource(this.sourceId);
}

getDisposable() {
return this.disposable;
}
}
35 changes: 35 additions & 0 deletions modules/TargetMonitor.js
@@ -0,0 +1,35 @@
import { CompositeDisposable } from 'disposables';
import createConnectRef from './createConnectRef';

export default class TargetMonitor {
constructor(manager, targetId) {
this.manager = manager;
this.targetId = targetId;

this.disposable = new CompositeDisposable();

const backend = manager.getBackend();
const connector = backend.connectDropTarget(targetId);

Object.keys(connector).forEach(name => {
const { disposable, ref } = createConnectRef(connector[name]);

this.disposable.add(disposable);
this[name] = () => ref;
});
}

canDrop() {
const monitor = this.manager.getMonitor();
return monitor.canDropOnTarget(this.targetId);
}

isOver(options) {
const monitor = this.manager.getMonitor();
return monitor.isOverTarget(this.targetId, options);
}

getDisposable() {
return this.disposable;
}
}

0 comments on commit 84b0ec4

Please sign in to comment.