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.
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.
plugin.xml
file in the navigator and double-click on it.org.eclipse.ui.views
. Expand this, and underneath the Timekeeping (category) the Clock View (view) will be displayed, added via the plug-in wizard.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:com.packtpub.e4.clock.ui.views.TimeZoneView
Time Zone View
com.packtpub.e4.clock.ui.views.TimeZoneView
com.packtpub.e4.clock.ui
icons/sample.gif
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>
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.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(); } } }
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; }
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); }
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);
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); }
Group
with an associated text label, so that the view hierarchy goes from CTabItem
→Composite
→ClockWidget
to CTabItem
→Composite
→Group
→ClockWidget
. 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);
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());
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 CtabItem
→Composite
→Group
→ClockWidget
to CTabItem
→ScrolledComposite
→Composite
→Group
→ClockWidget
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);
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);
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));
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.
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.
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?
A set of times are displayed in different time zones, but there is scope for enhancements:
Thread
to update all clocksScrollableComposite
so that more than one row is displayed