기존의 GEF에서 Properties View를 처리하는 방식은 [그림 1]과 같은 PropertySheetPage로 구성되어 밋밋한 감이 있었습니다. GMF의 Tabbed Properties View와 같은 형식인 [그림 2]와 [그림 3]도 GEF에서도 처리가 가능합니다.
Architecture
Tabbed Properties View는 크게 세종류의 확장점으로 구성되어 있습니다.
각각의 확장점은 ITabbedPropertySheetPageContributor와 연결이 되어 있습니다.
해당 모델이 선택됨에 따라서 Sections에 등록된 Section들이 해당 Tab에 보여지게 되는 형식입니다.
Tab들은 Category에 의해 분류가 됩니다.
이번에는 이정도까지만 정리를 할까 합니다.
이클립스 아티클이 너무 잘 나와서 따로 만들기에는 양이 너무 많을 것 같아서...
나중에 신기한 기능이나 확장가능한 부분이 나오면 정리해 볼 예정입니다.
게다가 중간에 Figure가 움직이지 않는 문제가 발생하였습니다.
예전에 할 때도 그랬었는데... 실수한 것을 따로 정리를 해 놓을 것 그랬나 봅니다.
역시 왠만해선 컴퓨터는 거짓말을 하지 않습니다.
유불이 문제였습니다....
만약 GEF에서 Figure가 움직이지 않는다면 다음을 체크해보세요~
1. PropertyChangeSupport 객체에 firePropertyChange() 메소드를 호출할 때, oldValue와 newValue가 같은 값을 넘기지는 않은지...
>> 같은 값을 넘기면 GEF에서 알아서 아무 이벤트도 발생시키지 않습니다.
2. Figure와 연관된 EditPart에서 refreshVisuals() 메소드가 아닌 registerVisuals() 메소드를 오버라이딩 한 것은 아닌지...
>> 저처럼 이클립스에서 Override/Implement Methods 기능을 이용하시는 분들은 자주 당하실 수도 있습니다.
일반적으로 GEF 에서 EditPart 에 EditPolicy.LAYOUT_ROLE 로 editpolicy 를 install 하게 됩니다.
이렇게 처리할 경우 생성이나 이동, 리사이징에는 별 무리 없이 사용할 수 있을 것이라 생각하였으나 한가지 문제가 있었습니다. 다른 자식 피규어와 겹칠경우 정상적으로 이동이 되지 않는 것이었습니다. LAYOUT_ROLE 로는 다른 자식 피규어 위에서 이동하는 것에 대한 이벤트를 잡지 않는 것으로 파악이 되었습니다. 그래서 조금 찾아보니 될 것만 같은 것이 있어서 한번 수정한 후 실행을 해보았습니다.
그냥 한번 해보았을 뿐인데... 원하는 결과가 나와버렸습니다. 그래서 구글에서 좀 찾아보니 아래와 같은 자료가 있었습니다.
Because of the relationship between handles and layouts, it is recommended that thePRIMARY_DRAG_ROLEeditpolicy be installed by the parent'sLayoutEditPolicy, which defines abstract methods for this purpose. If a container changes layout managers during editing, typically the layout policy gets swapped with one for the new layout manager. The new policy then replaces the stalePRIMARY_DRAG_ROLEpolicies on each child.
무신 말씀을 하시는지는 정확하게 파악을 하지 못하였으나 잘 돌아가주시니 감사할 따름입니다.
The DragEditPartsTracker extends basic selection behavior to allow the selected parts to be dragged within their graphical viewer. Dragging the selected parts can result in three potential interactions: move, reparent, and clone. All three use theChangeBoundsRequest, which extends GroupRequest to include a size delta, move delta, and mouse location.
While dragging the selection, if the tracker targets the part's original parent, the request is typed asREQ_MOVE. If the target changes, the interaction becomes a reparent. For a reparent, a request of typeREQ_ORPHANis sent to the old parent, while the new target is sent a request of typeREQ_ADD. When the CTRL key is pressed (ALT on the Mac), the operation is always aREQ_CLONE, which is only sent to the target part.
All of these requests are related in that they require the target to process a rectangle and a mouse location. The LayoutEditPolicy is responsible for handling each of these request types. For layouts which use constraints, each part's original bounds is taken and modified by the size and move deltas to determine a new bounds, for which a corresponding constraint is found. For index-based layouts, the mouse location is used to establish the new index.
AContainerEditPolicycan optionally be used to contribute additional commands (not related to the layout) during ADD, ORPHAN, and CLONE requests.
Resizing
Resizing falls under the same category as changing bounds. Note that when resizing either the top or left sides, the location of the part is also changed. Resizing only makes sense for layouts with constraints, such as XYLayout. TheResizableEditPolicyadds up to eight resize handles to its host. When the Selection Tool is clicked on one of these resize handles, aResizeTrackerperforms a resize on the selected parts understanding "resize". SHIFT and CTRL key modifiers can be used to constrain the resize operation.
The types of handles available on an editpart depend on the layout manager in which its figure is placed. For example, parts inside a table might have handles for adjusting insets, padding, column span, or other attributes. Some layouts don't need any handles, but four corner handles should be added just to indicate selection. Dragging these handles would be the same as dragging the part itself.
Because of the relationship between handles and layouts, it is recommended that thePRIMARY_DRAG_ROLEeditpolicy be installed by the parent'sLayoutEditPolicy, which defines abstract methods for this purpose. If a container changes layout managers during editing, typically the layout policy gets swapped with one for the new layout manager. The new policy then replaces the stalePRIMARY_DRAG_ROLEpolicies on each child.
TheMatchSizeActionmatches the size of the selected parts to that of the primary selected part's size. This action is implemented in a way similar to manually resizing the individual parts, and it uses the same request and type.
TheAlignmentActionuses anAlignmentRequest, which extends ChangeBoundsRequest. When using a ChangeBoundsRequest, the part's current placement in the Control (in absolute coordinates) is passed to the request, which then returns a modified version. Using this pattern, alignment is able to adjust each part's rectangle by different amounts. In most cases, alignment can be treated no differently than a move. This action aligns all selected parts with one of the edges of the primary selected part.
기존방식은 모델에 프로퍼티를 하나 추가하게 되면 IPropertySource 를 구현한 곳에서 PropertyDescriptor 를 추가 하고 getPropertyValue 와 setPropertyValue 를 수정해야하는 귀찮은 작업을 처리해야 합니다. 그리고 보기에도 좋지 않습니다. 큰 맘 먹고 어노테이션 과 리플렉션 을 이용하여 자동화를 처리하였습니다. (프로퍼티가 얼마나 추가될지 모르는 상황이기에... 퍼포먼스 따위는 하드웨어에게 양도...)
기존의 소스...
자동화 처리된 소스...
프로퍼티 상수에 PropertyDescription 어노테이션을 정의하여 PropertySourceHelpers 에 처리를 위임합니다. 알아서 PropertyDescriptor 들을 반환해주고 값을 얻어오고 설정을 하게 됩니다.
기존 방식은 한 두개야 머 저렇게 작업하겠지만 몇 십개의 모델과 몇 백개의 프로퍼티를 관리하려면... 무리가 있겠죠...