隨筆 - 1  文章 - 1  trackbacks - 0
          <2005年11月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          搜索

          •  

          最新評論

          由GEF所構(gòu)建的圖形編輯器用戶通常的操作流程描述如下:

          1、創(chuàng)建需要繪制圖形的文件,并根據(jù)文件類型使用相應(yīng)的編輯器打開文件,為繪制工作初始化一個圖形編輯視圖。

          2、根據(jù)圖形編輯器所提供的圖元工具創(chuàng)建具體圖元,將圖元繪制于編輯器所提供的圖形編輯視圖之上

          3、已繪制圖形元素的持久化

          根據(jù)這個流程,GEF中的各個類所需要執(zhí)行的操作基本步驟如下:

          1、創(chuàng)建文件,根據(jù)文件類型選擇相應(yīng)的EditorEditor和相關(guān)的Viewer的初始化(此部分在以后會詳細(xì)說明)

          2、使用Editor所提供的PaletteViewer上繪制圖形
          a、用戶選擇想要繪制的圖元,EditDomain會將用戶選擇的Palette中的相應(yīng)的ToolEntry
          激活。

          private void handlePaletteToolChanged() 
          {
              ToolEntry entry 
          =
           getPaletteViewer().getActiveTool();
              
          if (entry !=null
          )
                  setActiveTool(entry.createTool());
              
          else

                  setActiveTool(getDefaultTool());
          }


          b、用戶在畫板視圖上按下鼠標(biāo)左鍵后,DomainEventDispatcher會監(jiān)聽鼠標(biāo)事件

          /**
           * 
          @see EventDispatcher#dispatchMousePressed(org.eclipse.swt.events.MouseEvent)
          */

          public void dispatchMousePressed(org.eclipse.swt.events.MouseEvent me) 
          {
              
          if (!
          editorCaptured) 
          {
                  
          super
          .dispatchMousePressed(me);
                  
          if
           (draw2dBusy())
                      
          return
          ;
              }
              
          if
           (okToDispatch()) 
          {
                  setFocus(
          null
          );
                  control.forceFocus();
                  setRouteEventsToEditor(
          true
          );
                  domain.mouseDown(me, viewer);
              }
          }

          然后根據(jù)事件相應(yīng)的類型將其路由到EditDomainEditDomain則根據(jù)事件的類型執(zhí)行相應(yīng)的操作。這些操作的主要工作就是獲取EditDomain中當(dāng)前被激活的工具getActiveTool()),然后執(zhí)行該工具對這些鼠標(biāo)事件的響應(yīng)。

          public void mouseDown(MouseEvent mouseEvent, EditPartViewer viewer) 
          {
              Tool tool 
          =
           getActiveTool();
              
          if (tool !=null
          )
                  tool.mouseDown(mouseEvent, viewer);
          }

          CreationTool為例,它對ButtonDown事件的響應(yīng)(handleButtonDown(int))就是創(chuàng)建一個CreateRequest,并賦予其相應(yīng)的位置信息(setLocation(Point)

          /**
           * The creation tool only works by clicking mouse button 1 (the left mouse button in a
           * right-handed world).  If any other button is pressed, the tool goes into an invalid
           * state.  Otherwise, it goes into the drag state, updates the request's location and 
           * calls {
          @link TargetingTool#lockTargetEditPart(EditPart)} with the edit part that was
           * just clicked on.
           * 
           * 
          @see
           org.eclipse.gef.tools.AbstractTool#handleButtonDown(int)
          */

          protected boolean handleButtonDown(int button) 
          {
              
          if (button !=1

          {
                  setState(STATE_INVALID);
                  handleInvalidInput();
                  
          return true
          ;
              }
              
          if
           (stateTransition(STATE_INITIAL, STATE_DRAG)) 

          {
                  getCreateRequest().setLocation(getLocation());
                  lockTargetEditPart(getTargetEditPart());
                  
          // Snap only when size on drop is employed

                  helper = (SnapToHelper)getTargetEditPart().getAdapter(SnapToHelper.class);
              }
              
          return true
          ;
          }

          cCreationTool還會根據(jù)Request的類型及位置將其分派給相應(yīng)的EditPart[Targeting tools work with a target request. This request is used along with the mouse location to obtain an active target from the current EditPartViewer. This target is then asked for the Command that performs the given request. The target is also asked to show target feedback. (摘自org.eclipse.gef.tools.TargetingTool)]

          d、此后的流程基本上就如GEF EMF Redbook中3.3.3Requests節(jié)中的Communication chain
          Request-EditPart-Command所述


          Command執(zhí)行所做的操作只是對它所涉及到的模型進(jìn)行相應(yīng)的設(shè)置,譬如大小、位置、顏色等屬性。那么圖元如何顯示在視圖之上呢?這一部分正是由GEF中所使用的MVC模式實現(xiàn)。

          GEF中的每一個模型都實現(xiàn)了某種Notifier(org.eclipse.emf.common.notify.Notifier)或者IPropertySource(org.eclipse.ui.views.properties.IPropertySource)接口作為消息源,每個EditPart則相應(yīng)的實現(xiàn)了Adapter(org.eclipse.emf.common.notify.Adapter)PropertyChangeListener(java.beans.PropertyChangeListener)等接口作為偵聽器。并在EditPart初始化時,將其本身注冊為所對應(yīng)的模型的一個偵聽器,當(dāng)模型中的屬性發(fā)生變化時,EditPart會執(zhí)行相應(yīng)的操作。

          EditPart
          初始化時,將其本身注冊為所對應(yīng)的模型的一個偵聽器,并在銷毀之前注銷注冊:

          /**
           * Upon activation, attach to the model element as a notification change
           * listener.
           
          */
          public void activate() {
              
          if (!
          isActive()) {
                  
          super
          .activate();
                  ((ModelElement) getModel()).eAdapters().add(
          this
          );
              }
          }

          /**

           * Upon deactivation, detach from the model element as a notification change
           * listener.
           
          */
          public void deactivate() {
              
          if
           (isActive()) {
                  
          super
          .deactivate();
                  ((ModelElement) getModel()).eAdapters().remove(
          this
          );
              }
          }



          當(dāng)模型中的屬性發(fā)生變化時,會向所有的偵聽器發(fā)出消息:

          /**
           * <!-- begin-user-doc -->
           * <!-- end-user-doc -->
           * @generated
           
          */
          public void setName(String newName) {
              String oldName 
          =
           name;
              name 
          =
           newName;
              
          if
           (eNotificationRequired())
                  eNotify(
          new ENotificationImpl(this
          , Notification.SET, ModelPackage.ARC_MODEL__NAME, oldName, name));
          }

          對于所有在該模型上注冊的偵聽器(EditPart)都會接收到屬性變化的消息,根據(jù)消息做出相應(yīng)的反應(yīng):
          /*
           * (non-Javadoc)
           * 
           * @see org.eclipse.emf.common.notify.Adapter#notifyChanged(org.eclipse.emf.common.notify.Notification)
           
          */
          public void notifyChanged(Notification notification) {

              
          int featureID = notification.getFeatureID(ModelPackage.class
          );

              
          if (ModelPackage.NODE_MODEL__HEIGHT ==
           featureID
                      
          || ModelPackage.NODE_MODEL__WIDTH ==
           featureID
                      
          || ModelPackage.NODE_MODEL__X ==
           featureID
                      
          || ModelPackage.NODE_MODEL__Y ==
           featureID) {
                  refreshVisuals();
              } 
          else if (ModelPackage.NODE_MODEL__INPUT_ARCS ==
           featureID) {
                  refreshTargetConnections();
              } 
          else if (ModelPackage.NODE_MODEL__OUTPUT_ARCS ==
           featureID) {
                  refreshSourceConnections();
              }
          }

          (注意:上述示例代碼中,模型部分代碼是由EMF自動生成,因此使用了Notifier-Adapter偵聽機(jī)制)
          posted @ 2005-11-24 19:57 genesis 閱讀(2354) | 評論 (1)編輯 收藏
          主站蜘蛛池模板: 临朐县| 山丹县| 青龙| 龙胜| 磐安县| 肃宁县| 怀集县| 五台县| 温州市| 长宁县| 库尔勒市| 东港市| 偏关县| 上犹县| 阿拉善右旗| 城固县| 陕西省| 唐山市| 志丹县| 崇礼县| 积石山| 庆元县| 同江市| 高淳县| 济阳县| 泗水县| 嵊州市| 建平县| 剑川县| 永春县| 虎林市| 峨山| 广丰县| 合作市| 同江市| 许昌县| 济阳县| 双峰县| 淮南市| 玉环县| 湖口县|