index.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import { assign } from 'min-dash';
  2. import inherits from 'inherits';
  3. import Refs from 'object-refs';
  4. var parentRefs = new Refs({ name: 'children', enumerable: true, collection: true }, { name: 'parent' }),
  5. labelRefs = new Refs({ name: 'labels', enumerable: true, collection: true }, { name: 'labelTarget' }),
  6. attacherRefs = new Refs({ name: 'attachers', collection: true }, { name: 'host' }),
  7. outgoingRefs = new Refs({ name: 'outgoing', collection: true }, { name: 'source' }),
  8. incomingRefs = new Refs({ name: 'incoming', collection: true }, { name: 'target' });
  9. /**
  10. * @namespace djs.model
  11. */
  12. /**
  13. * @memberOf djs.model
  14. */
  15. /**
  16. * The basic graphical representation
  17. *
  18. * @class
  19. *
  20. * @abstract
  21. */
  22. export function Base() {
  23. /**
  24. * The object that backs up the shape
  25. *
  26. * @name Base#businessObject
  27. * @type Object
  28. */
  29. Object.defineProperty(this, 'businessObject', {
  30. writable: true
  31. });
  32. /**
  33. * Single label support, will mapped to multi label array
  34. *
  35. * @name Base#label
  36. * @type Object
  37. */
  38. Object.defineProperty(this, 'label', {
  39. get: function() {
  40. return this.labels[0];
  41. },
  42. set: function(newLabel) {
  43. var label = this.label,
  44. labels = this.labels;
  45. if (!newLabel && label) {
  46. labels.remove(label);
  47. } else {
  48. labels.add(newLabel, 0);
  49. }
  50. }
  51. });
  52. /**
  53. * The parent shape
  54. *
  55. * @name Base#parent
  56. * @type Shape
  57. */
  58. parentRefs.bind(this, 'parent');
  59. /**
  60. * The list of labels
  61. *
  62. * @name Base#labels
  63. * @type Label
  64. */
  65. labelRefs.bind(this, 'labels');
  66. /**
  67. * The list of outgoing connections
  68. *
  69. * @name Base#outgoing
  70. * @type Array<Connection>
  71. */
  72. outgoingRefs.bind(this, 'outgoing');
  73. /**
  74. * The list of incoming connections
  75. *
  76. * @name Base#incoming
  77. * @type Array<Connection>
  78. */
  79. incomingRefs.bind(this, 'incoming');
  80. }
  81. /**
  82. * A graphical object
  83. *
  84. * @class
  85. * @constructor
  86. *
  87. * @extends Base
  88. */
  89. export function Shape() {
  90. Base.call(this);
  91. /**
  92. * The list of children
  93. *
  94. * @name Shape#children
  95. * @type Array<Base>
  96. */
  97. parentRefs.bind(this, 'children');
  98. /**
  99. * @name Shape#host
  100. * @type Shape
  101. */
  102. attacherRefs.bind(this, 'host');
  103. /**
  104. * @name Shape#attachers
  105. * @type Shape
  106. */
  107. attacherRefs.bind(this, 'attachers');
  108. }
  109. inherits(Shape, Base);
  110. /**
  111. * A root graphical object
  112. *
  113. * @class
  114. * @constructor
  115. *
  116. * @extends Shape
  117. */
  118. export function Root() {
  119. Shape.call(this);
  120. }
  121. inherits(Root, Shape);
  122. /**
  123. * A label for an element
  124. *
  125. * @class
  126. * @constructor
  127. *
  128. * @extends Shape
  129. */
  130. export function Label() {
  131. Shape.call(this);
  132. /**
  133. * The labeled element
  134. *
  135. * @name Label#labelTarget
  136. * @type Base
  137. */
  138. labelRefs.bind(this, 'labelTarget');
  139. }
  140. inherits(Label, Shape);
  141. /**
  142. * A connection between two elements
  143. *
  144. * @class
  145. * @constructor
  146. *
  147. * @extends Base
  148. */
  149. export function Connection() {
  150. Base.call(this);
  151. /**
  152. * The element this connection originates from
  153. *
  154. * @name Connection#source
  155. * @type Base
  156. */
  157. outgoingRefs.bind(this, 'source');
  158. /**
  159. * The element this connection points to
  160. *
  161. * @name Connection#target
  162. * @type Base
  163. */
  164. incomingRefs.bind(this, 'target');
  165. }
  166. inherits(Connection, Base);
  167. var types = {
  168. connection: Connection,
  169. shape: Shape,
  170. label: Label,
  171. root: Root
  172. };
  173. /**
  174. * Creates a new model element of the specified type
  175. *
  176. * @method create
  177. *
  178. * @example
  179. *
  180. * var shape1 = Model.create('shape', { x: 10, y: 10, width: 100, height: 100 });
  181. * var shape2 = Model.create('shape', { x: 210, y: 210, width: 100, height: 100 });
  182. *
  183. * var connection = Model.create('connection', { waypoints: [ { x: 110, y: 55 }, {x: 210, y: 55 } ] });
  184. *
  185. * @param {String} type lower-cased model name
  186. * @param {Object} attrs attributes to initialize the new model instance with
  187. *
  188. * @return {Base} the new model instance
  189. */
  190. export function create(type, attrs) {
  191. var Type = types[type];
  192. if (!Type) {
  193. throw new Error('unknown type: <' + type + '>');
  194. }
  195. return assign(new Type(), attrs);
  196. }