Time for action – groups and tab folders

A new TimezoneView will show a list of clocks in time zones around the world. This time, instead of using the plug-in wizard, the extension will be added manually.

Note

Time for action – groups and tab folders E4: The way views are defined for E4 is covered in Chapter 7, Understanding the Eclipse 4 Model. This chapter discusses how to do it in Eclipse 3.x and the Eclipse 3.x compatibility model of Eclipse 4.x.

  1. Right-click on the project and navigate to Plug-in Tools | Open Manifest, or find the plugin.xml file in the navigator and double-click on it.
  2. Go to the manifest editor's Extensions tab. The extensions will list org.eclipse.ui.views. Expand this, and underneath the Timekeeping (category) the Clock View (view) will be displayed, added via the plug-in wizard.
  3. Right-click on org.eclipse.ui.views and navigate to New | view from the menu. A placeholder entry name (view) will be added to the list, and the right-hand side lists properties such as the id, name, class, and category. Fill in the following:
    • ID: com.packtpub.e4.clock.ui.views.TimeZoneView
    • Name: Time Zone View
    • Class: com.packtpub.e4.clock.ui.views.TimeZoneView
    • Category: com.packtpub.e4.clock.ui
    • Icon: icons/sample.gif
  4. Save the file. The following will be added into the plugin.xml file:
    <view
      category="com.packtpub.e4.clock.ui"
      class="com.packtpub.e4.clock.ui.views.TimeZoneView"
      icon="icons/sample.gif"
      id="com.packtpub.e4.clock.ui.views.TimeZoneView"
      name="Time Zone View"
      restorable="true">
    </view>
  5. Create the TimeZoneView class. The easiest way is to go to the plugin.xml file's Extensions tab, select the Time Zone View and click on the hyperlinked class* label next to the class name. Alternatively, use the New Class wizard by navigating to File | New | Class to create TimeZoneView as a subclass of ViewPart, in the com.packtpub.e4.clock.ui.views package.
  6. Create a class called TimeZoneComparator, which implements Comparator, in a new package com.packtpub.e4.clock.ui.internal. It is conventional to provide utility classes in an internal package to ensure that the implementation is not visible to others. The compare method should delegate to the TimeZone class's compareTo() method:
    public class TimeZoneComparator implements Comparator {
      public int compare(Object o1, Object o2) {
        if(o1 instanceof TimeZone && o2 instanceof TimeZone) {
          return ((TimeZone) o1).getID().
           compareTo(((TimeZone) o2).getID());
        } else {
          throw new IllegalArgumentException();
        }
      }
    }
  7. Add a public static method to the TimeZoneComparator class called getTimeZones(), which will return a Map of Sets of TimeZones. The Map will be indexed by the first half of the TimeZone class's ID. (A TimeZone class's ID is something like Europe/Milton_Keynes or America/New_York.) This will group all TimeZone in Europe together, and all TimeZone in America together:
    public static Map<String, Set<TimeZone>> getTimeZones(){
      String[] ids = TimeZone.getAvailableIDs();
      Map<String, Set<TimeZone>> timeZones =
       new TreeMap<String, Set<TimeZone>>();
      for (int i = 0; i < ids.length; i++) {
        String[] parts = ids[i].split("/");
        if (parts.length == 2) {
          String region = parts[0];
          Set<TimeZone> zones = timeZones.get(region);
          if (zones == null) {
            zones = new TreeSet<TimeZone>(new TimeZoneComparator());
            timeZones.put(region, zones);
          }
          TimeZone timeZone = TimeZone.getTimeZone(ids[i]);
          zones.add(timeZone);
    
        }
      }
      return timeZones;
    }
  8. In the createPartControl() method in TimeZoneView, create CTabFolder and then iterate through the time zones, creating CTabItem for each one:
    public void createPartControl(Composite parent) {
      Map<String, Set<TimeZone>> timeZones = 
      TimeZoneComparator.getTimeZones();
      CTabFolder tabs = new CTabFolder(parent, SWT.BOTTOM);
      Iterator<Entry<String, Set<TimeZone>>> regionIterator =
       timeZones.entrySet().iterator();
      while(regionIterator.hasNext()) {
        Entry<String, Set<TimeZone>> region =
         regionIterator.next();
        CTabItem item = new CTabItem(tabs, SWT.NONE);
        item.setText(region.getKey());
      }
      tabs.setSelection(0);
    }
  9. Run this example and show the Time Zone View, and there should be a populated list of tabs along the bottom:
    Time for action – groups and tab folders
  10. Inside the while loop, add a Composite instance to hold multiple ClockWidget classes for each TimeZone instance:
    item.setText(region.getKey()); // from before
    Composite clocks = new Composite(tabs, SWT.NONE);
    clocks.setLayout(new RowLayout());
    item.setControl(clocks);
  11. Now iterate through the TimeZones, adding a ClockWidget for each:
    RGB rgb = new RGB(128, 128, 128);
    TimeZone td = TimeZone.getDefault();
    Iterator<TimeZone> timezoneIterator = region.getValue().iterator();
    while (timezoneIterator.hasNext()) {
      TimeZone tz = timezoneIterator.next();
      ClockWidget clock = new ClockWidget(clocks, SWT.NONE, rgb);
      clock.setOffset((
       tz.getOffset(System.currentTimeMillis()) - 
       td.getOffset(System.currentTimeMillis())) / 3600000);
    }
  12. Run the Eclipse instance and open the Time Zone View to see all of the clocks:
    Time for action – groups and tab folders
  13. To make the clocks more identifiable, each will be put into a Group with an associated text label, so that the view hierarchy goes from CTabItemCompositeClockWidget to CTabItemCompositeGroupClockWidget. Replace the call to create the the ClockWidget with this:
    //Replace the following commented code
    /* ClockWidget clock = new ClockWidget(clocks, SWT.NONE, rgb);*/
    Group group = new Group(clocks,SWT.SHADOW_ETCHED_IN);
    group.setText(tz.getID().split("/")[1]);
    ClockWidget clock = new ClockWidget(group, SWT.NONE, rgb);
  14. Run it again, and a series of blank elements will be shown:
    Time for action – groups and tab folders
  15. Since the default layout manager for general Composite classes is null, Groups don't have a layout manager and thus, the clocks are not getting sized appropriately. This can be fixed by setting a layout manager explicitly:
    group.setLayout(new FillLayout());
  16. Run it again, it looks a little bit more sane:
    Time for action – groups and tab folders
  17. The clocks at the bottom are squashed and the view can't be scrolled, even though there are clearly more time zones available. To add scrolling to a widget, the ScrolledComposite can be used. This provides automatic scroll bars and interaction with the user to permit a much larger virtual area to be scrolled. The View hierarchy will change from CtabItemCompositeGroupClockWidget to CTabItemScrolledCompositeCompositeGroupClockWidget instead:
    //The following  commented code needs to be removed
    /*Composite clocks = new Composite(tabs, SWT.NONE);
    item.setControl(clocks);*/
    ScrolledComposite scrolled = new
     ScrolledComposite(tabs,SWT.H_SCROLL | SWT.V_SCROLL);
    Composite clocks = new Composite(scrolled, SWT.NONE);
    item.setControl(scrolled);
    scrolled.setContent(clocks);
  18. Run it again, but unfortunately this will be seen:
    Time for action – groups and tab folders
  19. The problem is that ScrolledComposite has no minimum size. This can be calculated from the clocks container. Add this to the bottom of the while loop, after the contents of ScrolledComposite have been created:
    Point size = clocks.computeSize(SWT.DEFAULT,SWT.DEFAULT);
    scrolled.setMinSize(size);
    scrolled.setExpandHorizontal(true);
    scrolled.setExpandVertical(true);
  20. Run it again, and the clocks now show up as expected:
    Time for action – groups and tab folders
  21. The ScrolledComposite has a different background. To change it, add this line after constructing the clock's Composite:
    clocks.setBackground(Display.getDefault()
     .getSystemColor(SWT.COLOR_LIST_BACKGROUND));
  22. Now the Time Zone View is complete:
    Time for action – groups and tab folders

What just happened?

A combination of Composite types created a tabbed environment using CTabFolder and CTabItem instances. Inside each CTabItem, a ScrolledComposite contained a Composite of multiple Group instances, each of which had a single ClockWidget. Adding the ScrolledComposite provided the scrolling for free, and Group allowed us to place text above the ClockWidget to display its time zone.

Note

Some of the components used here lie in the org.eclipse.swt.custom package, instead of the org.eclipse.swt.widgets package. Several of these begin with C as a custom designator to distinguish similarly named widgets. The CTabFolder/Item is an SWT-implemented class that provides the tab functionality; the corresponding OS widget TabFolder/Item uses a native rendered tab switcher.

Pop quiz – using SWT

Q1. How do you add an icon to the system menu?

Q2. What does the SWT.NO_TRIM style do for Shell objects?

Q3. How do you make a Shell transparent?

Q4. What do you need to set to create a nonrectangular Shell?

Q5. What Composite allows you to attach a label to a set of related items?

Q6. What is the default layout manager for a Group instance?

Q7. How do you add scrolling to an existing widget?

Have a go hero – enhancing the time zones

A set of times are displayed in different time zones, but there is scope for enhancements:

  • Switch to the tab with the user's default time zone when the view is created
  • Sort the clocks by time zone offset, rather than by name of the region
  • Create a favorites tab and allow it to be populated by drag-and-drop
  • Improve the speed of updates by sharing a single Thread to update all clocks
  • Improve the sizing of the ScrollableComposite so that more than one row is displayed
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset