Skip to content
Jinyoung Jang edited this page Oct 3, 2016 · 1 revision

Model: IElement.java

public interface IElement {
    ElementView createView();

    ElementView getElementView();

    void setElementView(ElementView elementView);

    String getName();

    String getDescription();

}

View Model: ElementView.java

package org.uengine.modeling;

import java.io.Serializable;

import javax.persistence.Id;

import org.metaworks.*;
import org.metaworks.annotation.AutowiredFromClient;
import org.metaworks.annotation.Face;
import org.metaworks.annotation.ServiceMethod;
import org.metaworks.widget.ModalWindow;

/**
 * @author jyj
 */
public abstract class ElementView implements Serializable, ContextAware, Cloneable {

    String id;

    @Id
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }


    String shapeId;

    public String getShapeId() {
        return shapeId;
    }

    public void setShapeId(String shapeId) {
        this.shapeId = shapeId;
    }

    double x;
        public double getX() {
            return x;
        }

        public void setX(double x) {
            this.x = x;
        }


    double y;
        public double getY() {
            return y;
        }

        public void setY(double y) {
            this.y = y;
        }


    double width;
        public double getWidth() {
            return width;
        }

        public void setWidth(double width) {
            this.width = width;
        }


    double height;
        public double getHeight() {
            return height;
        }

        public void setHeight(double height) {
            this.height = height;
        }


    String fromEdge;

    public String getFromEdge() {
        return fromEdge;
    }

    public void setFromEdge(String fromEdge) {
        this.fromEdge = fromEdge;
    }

    String toEdge;

    public String getToEdge() {
        return toEdge;
    }

    public void setToEdge(String toEdge) {
        this.toEdge = toEdge;
    }

    String label;

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }


    IElement element;

    @Face(ejsPath = "dwr/metaworks/genericfaces/HiddenFace.ejs")
    public IElement getElement() {
        return element;
    }

    public void setElement(IElement element) {
        this.element = element;
    }


    @AutowiredFromClient
    public ElementViewActionDelegate elementViewActionDelegate;

    @ServiceMethod(callByContent = true, eventBinding = EventContext.EVENT_DBLCLICK, target = ServiceMethodContext.TARGET_POPUP)
    public Object showProperty() throws Exception {

        if(elementViewActionDelegate!=null){
            elementViewActionDelegate.onDoubleClick(this);

            return null;
        }

        return new PropertySettingDialog(this);
    }


...
}

  1. id: View 의 유일 식별키. 이것이 있어야 해당 view 만을 서버로 보내거나, Metaworks의 return 로직에 따라 해당 view 만이 refresh 될 수 있다.
  2. x,y,width,height: View 의 좌표와 bounds
  3. fromEdge, toEdge: Element 가 상소 연결된 Relation (OpenGraph에서는 Edge 라 부름) 의 edge id
  4. label: Element 상에 표시되는 label
  5. showProperty: Element 는 세부적인 값이 편집될 수 있기 때문에 이 메서드를 통하여 편집창을 열게된다. 편집창을 생성하는 것은 기본적으로 메타웍스의 MDD 기반 Form 생성 기능을 사용한다.
  6. elementViewActionDelegate: 이것이 설정되어 있으면, 엘리먼트를 더블클릭하여 설정을 시도할 경우, 기본 편집창을 생성하여 팝업해주는 것이 아니라 설치된 delegate 의 로직을 따르게 된다.

Status 표시 및 Badge 기능

ElementView.ejs.js

UMF 에서의 Element Model 은 Modeling Time (type) 과 Run Time (instance) 을 갖는다. Run time 시에는 상태가 존재하는데, instance 상태의 status 를 badge 형태로 표시할 수 있어야 한다. ElementView.java 에서는 instStatus 라는 필드에 이 값을 담아놓고 ejs.js 에서 opengraph로 전달한다.

            if (this.object.instStatus) {
                if ("Completed" == this.object.instStatus || "Running" == this.object.instStatus) {
                    shape.status = this.object.instStatus;
                }
            }

            ....
            
            this.element = this.canvas.drawShape([this.object.x, this.object.y],
                shape,
                [parseInt(this.object.width, 10), parseInt(this.object.height, 10)],
                OG.JSON.decode(unescape(style)),
                this.object.id,
                this.object.parent,
                preventDrop);

OpenGraph.js

OpenGraph에서는 ElementView.ejs.js 가 넘겨준 instance status 값을 참고하여 status 에 관한 badge 를 그려넣는다. 특히 Status 가 Running 인 경우는 애니메이션 효과로 Element 의 주변을 깜빡임 처리를 하고 있다.

[Note] 이 부분은 순전히 ElementView.ejs.js 로 코드가 옮겨져야 할 것으로 보인다. UMF 의 기능에 응집성이 높은 코드이지 일반 OG 를 사용하는 경우 필요한 기능은 아니어서 OG 를 비대하게 만드는 작용을 하고 있다.

//Status 드로우

OG.renderer.RaphaelRenderer.prototype.drawStatus = function (element) {
    var me = this, rElement = this._getREleById(OG.Util.isElement(element) ? element.id : element),
        geometry = rElement ? rElement.node.shape.geom : null,
        envelope, _upperLeft, _bBoxRect, _rect, _rect1,
        _size = me._CONFIG.COLLAPSE_SIZE,
        _hSize = _size / 2;

    _rect1 = this._getREleById(rElement.id + OG.Constants.STATUS_SUFFIX);
    if (_rect1) {
        this._remove(_rect1);
    }

    _rect = this._getREleById(rElement.id + OG.Constants.STATUS_SUFFIX + '_IMG');
    if (_rect) {
        this._remove(_rect);
    }

    envelope = geometry.getBoundary();
    _upperRight = envelope.getUpperRight();

    switch (element.shape.status) {
        case "Completed":
            _rect1 = this._PAPER.image("images/opengraph/complete.png", _upperRight.x - 25, _upperRight.y + 5, 20, 20);
            break;
        case "Running":
            _rect = this._PAPER.rect(envelope.getUpperLeft().x - 10, envelope.getUpperLeft().y - 10, envelope.getWidth() + 20, envelope.getHeight() + 20);
            _rect.attr("fill", "#C9E2FC");
            _rect.attr("stroke-width", "0.2");
            _rect.attr("r", "10");
            _rect.attr("fill-opacity", "1");
            _rect.attr("stroke-dasharray", "--");

            _rect1 = this._PAPER.image("images/opengraph/running.png", _upperRight.x - 25, _upperRight.y + 5, 20, 20);
            break;
    }

    if (element.shape.status == "Running") {
        var ani1 = Raphael.animation({
            fill: '#C9E2FC'
        }, 1000);

        var ani2 = Raphael.animation({
            fill: 'white'
        }, 1000, startAni);

        function startAni() {
            _rect.attr({fill: 'white'}).animate(ani1);
            _rect.attr({fill: '#C9E2FC'}).animate(ani2.delay(1000));
        }

        startAni();
    }
    this._add(_rect1, rElement.id + OG.Constants.STATUS_SUFFIX);
    _rect1.insertAfter(rElement);
    rElement.appendChild(_rect1);

    if (_rect) {
        this._add(_rect, rElement.id + OG.Constants.STATUS_SUFFIX + '_IMG');
        _rect.insertAfter(rElement);
        rElement.prependChild(_rect);
    }

    return null;
};