zoukankan      html  css  js  c++  java
  • Enhanced RCP: How views can communicate – The e4 way | Tomsondev Blog


    Some weeks ago I published how views can communicate using the EventAdmin-Service. To get things working in an 3.x application one has to write some glue code but more importantly one has to know about all those nifty things about event publishing, getting access to OSGi-Services, … .

    One of the main topics of the Eclipse 4 Application Platform was to make easy things easy by removing the need to know about all the concepts by hiding them using DI. The service responsible to deliver events in application built on top the Eclipse 4 Application Platform is the EventBroker-Service:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    package org.eclipse.e4.core.services.events;
     
    public interface IEventBroker {
        public String DATA = "org.eclipse.e4.data"; //$NON-NLS-1$
     
        public boolean send(String topic, Object data);
        public boolean post(String topic, Object data);
     
        public boolean subscribe(String topic, EventHandler eventHandler);
     
        public boolean subscribe(String topic, String filter, EventHandler eventHandler,
                boolean headless);
     
        public boolean unsubscribe(EventHandler eventHandler);
    }

    This is all we need to know (assuming we have already understood how DI-works) to implement our sender and receiver views:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public class SenderView {
      @Inject
      private IEventBroker eventBroker;
      private Button b;
     
      @PostConstruct
      void init(Composte parent) {
        parent.setLayout(new GridLayout());
        b = new Button(parent, SWT.PUSH);
        b.setText("Send Event");
        b.addSelectionListener(new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            Date d = new Date();
            eventBroker.send("viewcommunication/syncEvent",d);
            eventBroker.post("viewcommunication/asyncEvent", d);
          }
        });
      }
     
      @Focus
      void focus() {
        b.setFocus();
      }
    }

    These are some fewer lines of code which is good but IMHO the more important fact is that you are independent from OSGi running now so the code you have there is much easier testable by simply mocking IEventBroker!

    Let’s look now at the receiver side of the story. If you take a look at the IEventBroker you see the subscribe methods which allows us to subscribe to various topics so we could as a first step implement it like this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    public class ReceiverView {
      @Inject
      private IEventBroker eventBroker;
      private TableViewer viewer;
     
      @PostConstruct
      public void init(final Composite parent) {
        parent.setLayout(new FillLayout());
        viewer = new TableViewer(parent);
        viewer.getTable().setHeaderVisible(true);
        viewer.getTable().setLinesVisible(true);
        viewer.setLabelProvider(new ColumnLabelProvider() {
          @Override
          public String getText(Object element) {
            return DateFormat.getDateTimeInstance().format(element);
          }
        });
     
        EventHandler handler = new EventHandler() {
          public void handleEvent(final Event event) {
            if( parent.getDisplay().getThread() == Thread.currentThread() ) {
              viewer.add(event.getProperty(IEventBroker.DATA));
            } else {
              parent.getDisplay().syncExec(new Runnable() {
                public void run() {
                  viewer.add(event.getProperty(IEventBroker.DATA));
                }
              });
            }
          }
        };
        eventBroker.subscribe("viewcommunication/*",handler);
      }
     
      @Focus
      void focus() {
        viewer.getTable().setFocus();
      }
    }

    This is once more making your code looser coupled because you are independent from OSGi running but we can do even better by fully leveraging the Eclipse DI-Framework. By default Eclipse DI injects data it has stored in its IEclipseContext (you can think of the IEclipseContext as a Map where the value is thing that gets injected into you “POJO”).

    The important thing for us is that one can extend Eclipse DI to consult other resources like e.g. Preferences (@Preference) and e.g. Event-Data (@EventTopic) – a blog post explaining how this works will follow hopefully soon.

    So we can rewrite our receiver code like this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    public class ReceiverView {
      private TableViewer viewer;
     
      @PostConstruct
      public void init(final Composite parent) {
        parent.setLayout(new FillLayout());
        viewer = new TableViewer(parent);
        viewer.getTable().setHeaderVisible(true);
        viewer.getTable().setLinesVisible(true);
        viewer.setLabelProvider(new ColumnLabelProvider() {
          @Override
          public String getText(Object element) {
            return DateFormat.getDateTimeInstance().format(element);
          }
        });
      }
     
      @Inject
      void eventReceived(@EventTopic("viewcommunication/*") Date date) {
        Display d = viewer.getControl().getDisplay();
        if( d.getThread() == Thread.currentThread() ) {
          viewer.add(date);
        } else {
          parent.getDisplay().syncExec(new Runnable() {
            public void run() {
              viewer.add(date);
            }
          });
        }
      }
     
      @Focus
      void focus() {
        viewer.getTable().setFocus();
      }
    }

    [Update 2011-02-07] – Start
    But we can do even better so that we don’t need to take of the UI-Thread syncing all we need to do is use another annotation:

    1
    2
    3
    4
    @Inject
      void eventReceived(@UIEventTopic("viewcommunication/*") Date date) {
        viewer.add(date);
      }

    Now the DI-Framework takes care of the Event loop syncing. Thanks to Brian de Alwis for pointing this out.
    [Update 2011-02-07] – End

    If you are interested in how you can use things like this in your Eclipse 3.x applications and you are going to be at EclipseCon you should come to my talk about “Singlesourcing for Eclipse 4.x and Eclipse 3.x

     




  • 相关阅读:
    四川省选2012 day1 喵星球上的点名 (后缀数组,并不是完全的正解)
    6.2.1 最短路
    5.3.3 敌兵布阵
    6.1.1 Constructing Roads
    6.2.4 Arbitrage
    6.1.6 Jungle Roads
    5.3.6 Cow Sorting (HDU 及 POJ)
    6.2.5 Trucking
    6.1.4 还是畅通工程
    6.1.3 畅通工程
  • 原文地址:https://www.cnblogs.com/phnix/p/3362687.html
Copyright © 2011-2022 走看看