/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.gui.workflow.view.timeline; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.commons.logging.LogFactory; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectWriter; import org.codehaus.jackson.node.ArrayNode; import org.codehaus.jackson.node.ObjectNode; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Slider; import org.eclipse.ui.IActionBars; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; import de.rcenvironment.core.communication.common.CommunicationException; import de.rcenvironment.core.communication.common.ResolvableNodeId; import de.rcenvironment.core.component.api.DistributedComponentKnowledgeService; import de.rcenvironment.core.component.model.api.ComponentInstallation; import de.rcenvironment.core.datamanagement.MetaDataService; import de.rcenvironment.core.datamanagement.commons.ComponentRunInterval; import de.rcenvironment.core.datamanagement.commons.WorkflowRunTimline; import de.rcenvironment.core.datamodel.api.TimelineIntervalType; import de.rcenvironment.core.gui.resources.api.ImageManager; import de.rcenvironment.core.gui.resources.api.StandardImages; import de.rcenvironment.core.utils.common.JsonUtils; import de.rcenvironment.core.utils.incubator.ServiceRegistry; import de.rcenvironment.core.utils.incubator.ServiceRegistryAccess; /** * The complete Timeline View. * * @author Hendrik Abbenhaus * @author David Scholz * */ public class TimelineView extends ViewPart implements AreaChangedListener, ResizeListener, ControlListener, SelectionListener { /** Identifier used to find the this view within the workbench. */ public static final String ID = "de.rcenvironment.gui.TimeTable"; private static final Map<String, Image> COMPONENT_ICON_CACHE = new HashMap<>(); private Composite rootComposite = null; private TimelineNavigationControl navigation = null; private SashForm sashMiddle = null; private TimelineComponentList list = null; private TimelineComponentRow[] rows = new TimelineComponentRow[0]; private Slider scrollBar = null; private final int scrollBarMaximum = 10000; private Action refreshAction = null; private Action zoomInAction = null; private Action zoomOutAction = null; private Action filterAction = null; private Date wfStartDate = null; private Date wfEndDate = null; private Label workflowNameLabel = null; private String[] allowedComponentNames = null; private final Color backgroundColorWhite = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE); private final int defaultMaximumZoomValue = 10000; private final int defaultMinimumZoomValue = 45; private int currentZoomValue = defaultMaximumZoomValue; private MetaDataService metaDataService; private Long workflowDmId; private ResolvableNodeId workflowCtrlNode; private boolean workflowTerminated = false; private Composite parentComposite; private boolean actualContentSet = false; private Label refreshLabel; public TimelineView() { metaDataService = ServiceRegistry.createAccessFor(this).getService(MetaDataService.class); } @Override public void createPartControl(Composite parent) { parentComposite = parent; parentComposite.setBackground(backgroundColorWhite); refreshLabel = new Label(parentComposite, SWT.NONE); refreshLabel.setText("Fetching workflow timeline..."); rootComposite = new Composite(new Shell(), SWT.NONE); rootComposite.setBackground(backgroundColorWhite); GridLayout mainLayout = new GridLayout(1, false); mainLayout.marginHeight = 0; mainLayout.marginBottom = 0; mainLayout.verticalSpacing = 0; rootComposite.setLayout(mainLayout); // For itself GridData gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; gridData.horizontalSpan = 1; gridData.grabExcessHorizontalSpace = true; gridData.verticalAlignment = GridData.FILL; gridData.verticalSpan = 1; gridData.grabExcessVerticalSpace = true; rootComposite.setLayoutData(gridData); makeActions(rootComposite); initGUI(rootComposite); contributeToActionBars(); rootComposite.setEnabled(false); } private void initGUI(Composite parent) { GridData gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; gridData.horizontalSpan = 1; gridData.grabExcessHorizontalSpace = true; gridData.verticalAlignment = GridData.BEGINNING; gridData.verticalSpan = 1; gridData.grabExcessVerticalSpace = false; GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 2; Composite titleComposite = new Composite(parent, SWT.None); titleComposite.setLayoutData(gridData); titleComposite.setBackground(backgroundColorWhite); titleComposite.setLayout(gridLayout); Composite workflowName = new Composite(titleComposite, SWT.None); workflowName.setLayoutData(gridData); workflowName.setBackground(backgroundColorWhite); workflowName.setLayout(new RowLayout()); workflowNameLabel = new Label(workflowName, SWT.None); workflowNameLabel.setBackground(backgroundColorWhite); Composite colorLegend = new Composite(titleComposite, SWT.RIGHT_TO_LEFT); colorLegend.setLayoutData(gridData); colorLegend.setBackground(backgroundColorWhite); colorLegend.setLayout(new RowLayout()); for (TimelineActivityType current : TimelineActivityType.values()) { if (current.getColor() != null) { Label label = new Label(colorLegend, SWT.None); label.setBackground(backgroundColorWhite); label.setText(" " + current.getDisplayName() + " "); Label colorLabel = new Label(colorLegend, SWT.None); colorLabel.setText(" "); // FIXME: the newly created color object will never be disposed colorLabel.setBackground(new Color(label.getDisplay(), current.getColor())); } } gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; gridData.horizontalSpan = 1; gridData.grabExcessHorizontalSpace = true; gridData.verticalAlignment = GridData.FILL; gridData.verticalSpan = 1; gridData.grabExcessVerticalSpace = true; SashForm master = new SashForm(parent, SWT.VERTICAL); master.setSashWidth(2); // master.setBackground(backgroundColorWhite); master.setLayoutData(gridData); initTopGUI(master); initBottomGUI(master); master.setWeights(new int[] { 5, 1 }); } private void initTopGUI(Composite parent) { Composite master = new Composite(parent, SWT.NONE); master.setBackground(backgroundColorWhite); master.setLayout(new GridLayout(1, true)); // Top: list = new TimelineComponentList(master); GridData gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; gridData.grabExcessHorizontalSpace = true; gridData.horizontalSpan = 1; gridData.grabExcessVerticalSpace = true; gridData.verticalAlignment = GridData.FILL; list.setLayoutData(gridData); list.addResizeListener(this); list.setBackground(backgroundColorWhite); // bottom: sashMiddle = new SashForm(master, SWT.HORIZONTAL); gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; gridData.grabExcessHorizontalSpace = true; gridData.horizontalSpan = 1; sashMiddle.setLayoutData(gridData); // left: Composite zoomComposite = new Composite(sashMiddle, SWT.NONE); zoomComposite.setBackground(backgroundColorWhite); GridLayout layout = new GridLayout(3, false); layout.marginHeight = 0; zoomComposite.setLayout(layout); // right: scrollBar = new Slider(sashMiddle, SWT.HORIZONTAL); scrollBar.setMaximum(scrollBarMaximum); // maximum scrollBar.setPageIncrement(scrollBarMaximum); scrollBar.setIncrement(10); // jump on press left or right scrollBar.setThumb(scrollBar.getMaximum()); // SWT Slider does not always disable slider if value == maximum value // as at start when value == maximum scrollBar.setEnabled(false); scrollBar.setLayoutData(gridData); scrollBar.addControlListener(this); scrollBar.addSelectionListener(this); sashMiddle.setWeights(new int[] { 1, 7 }); } private void initBottomGUI(Composite parent) { this.navigation = new TimelineNavigationControl(parent); navigation.setBackground(backgroundColorWhite); GridData gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; gridData.horizontalSpan = 3; gridData.grabExcessHorizontalSpace = true; this.navigation.setLayoutData(gridData); this.navigation.addAreaChangeListener(this); } /** * Sets dm id and controller node of workflow related to this view instance. * * @param wfDmId dm id of workflow run * @param wfCtrlNode a generic or specific id referring to the workflow controller instance */ public void initialize(Long wfDmId, ResolvableNodeId wfCtrlNode) { workflowDmId = wfDmId; workflowCtrlNode = wfCtrlNode; updateContent(); } private void updateContent() { refreshAction.setEnabled(false); Job job = new Job("Workflow Timeline") { @Override protected IStatus run(IProgressMonitor monitor) { try { monitor.beginTask("Fetching workflow timeline", 2); monitor.worked(1); WorkflowRunTimline timeline = metaDataService.getWorkflowTimeline(workflowDmId, workflowCtrlNode); final String timelineAsString = getWorkflowRunTimelineAsJsonString(timeline); monitor.worked(1); Display.getDefault().asyncExec(new Runnable() { @Override public void run() { if (!parentComposite.isDisposed()) { updateContent(timelineAsString); if (!actualContentSet) { // replace placeholder content with actual content refreshLabel.setParent(new Shell()); refreshLabel.dispose(); rootComposite.setParent(parentComposite); rootComposite.getShell().layout(true, true); zoomInAction.setEnabled(true); zoomOutAction.setEnabled(true); filterAction.setEnabled(true); actualContentSet = true; } rootComposite.setEnabled(true); // update the scrollbars (needed if new components were contributing to the timeline) list.setMinSize(list.computeSize(SWT.DEFAULT, SWT.DEFAULT, true)); list.layout(); refreshAction.setEnabled(!workflowTerminated); } } }); } catch (IOException | CommunicationException e) { LogFactory.getLog(TimelineView.class).error("Failed to load timeline of workflow", e); Display.getDefault().asyncExec(new Runnable() { @Override public void run() { PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().hideView(TimelineView.this); MessageDialog.openError(getSite().getShell(), "Workflow Timeline", "Failed to load the timeline. Did you get disconnected from a remote instance?\n\n" + "Please refresh the workflow data browser and try again.\n\nSee log for more details."); } }); } finally { monitor.done(); } return Status.OK_STATUS; }; }; job.setUser(true); job.schedule(); } private String getWorkflowRunTimelineAsJsonString(WorkflowRunTimline timeline) throws IOException { final String timeNodeName = "Time"; final String typeNodeName = "Type"; ObjectMapper mapper = JsonUtils.getDefaultObjectMapper(); ObjectNode rootNode = mapper.createObjectNode(); rootNode.put("WorkflowName", timeline.getWorkflowRunName()); rootNode.put("WorkflowStartTime", String.valueOf(timeline.getWorkflowRunInterval().getStartTime())); if (timeline.getWorkflowRunInterval().getEndTime() != null) { rootNode.put("WorkflowEndTime", String.valueOf(timeline.getWorkflowRunInterval().getEndTime())); workflowTerminated = true; } else { rootNode.put("WorkflowEndTime", String.valueOf(System.currentTimeMillis())); } ArrayNode componentsArray = rootNode.putArray("Components"); Map<String, ObjectNode> componentNodes = new HashMap<>(); Map<String, SortedMap<Long, ObjectNode>> componentEventNodes = new HashMap<>(); for (ComponentRunInterval cri : timeline.getComponentRunIntervalsSortedByTime()) { if (!componentNodes.containsKey(cri.getComponentInstanceName())) { ObjectNode componentNode = mapper.createObjectNode(); componentNode.put("Name", cri.getComponentInstanceName()); componentNode.put("Id", cri.getComponentID()); componentNode.putArray("Events"); componentNodes.put(cri.getComponentInstanceName(), componentNode); } if (!componentEventNodes.containsKey(cri.getComponentInstanceName())) { componentEventNodes.put(cri.getComponentInstanceName(), new TreeMap<Long, ObjectNode>()); } SortedMap<Long, ObjectNode> sortedEventNodes = componentEventNodes.get(cri.getComponentInstanceName()); if (cri.getType() == TimelineIntervalType.COMPONENT_RUN) { ObjectNode eventNode = mapper.createObjectNode(); eventNode.put(timeNodeName, String.valueOf(cri.getStartTime())); eventNode.put(typeNodeName, String.valueOf(cri.getType().name())); sortedEventNodes.put(cri.getStartTime(), eventNode); if (cri.getEndTime() != null) { ObjectNode waitEventNode = mapper.createObjectNode(); waitEventNode.put(timeNodeName, String.valueOf(cri.getEndTime())); waitEventNode.put(typeNodeName, "COMPONENT_WAIT"); sortedEventNodes.put(cri.getEndTime(), waitEventNode); } } else { ObjectNode eventNode = mapper.createObjectNode(); eventNode.put(timeNodeName, String.valueOf(cri.getStartTime())); eventNode.put(typeNodeName, String.valueOf(cri.getType().name())); sortedEventNodes.put(cri.getStartTime(), eventNode); // second check: sanity check if tool run end and component run end are equal if (cri.getEndTime() != null && !sortedEventNodes.containsKey(cri.getEndTime())) { ObjectNode runEventNode = mapper.createObjectNode(); runEventNode.put(timeNodeName, String.valueOf(cri.getEndTime())); runEventNode.put(typeNodeName, TimelineIntervalType.COMPONENT_RUN.name()); sortedEventNodes.put(cri.getEndTime(), runEventNode); } } } for (String compInstanceName : componentNodes.keySet()) { ArrayNode eventsNode = (ArrayNode) componentNodes.get(compInstanceName).get("Events"); for (ObjectNode eventNode : componentEventNodes.get(compInstanceName).values()) { eventsNode.add(eventNode); } componentsArray.add(componentNodes.get(compInstanceName)); } ObjectWriter writer = mapper.writerWithDefaultPrettyPrinter(); return writer.writeValueAsString(rootNode); } /** * Updates the Content of the View. * * @param resource the resource */ @SuppressWarnings("unchecked") public void updateContent(String resource) { // delete all! this.list.clear(); // read json file try { ObjectMapper mapper = JsonUtils.getDefaultObjectMapper(); Map<String, Object> jsonStructureRoot = mapper.readValue(resource, new HashMap<String, Object>().getClass()); String jsonWorkflowName = (String) jsonStructureRoot.get(TimelineViewConstants.JSON_WORKFLOWNAME); String jsonWorkflowStart = (String) jsonStructureRoot .get(TimelineViewConstants.JSON_WORKFLOWSTARTTIME); String jsonWorkflowEnd = (String) jsonStructureRoot .get(TimelineViewConstants.JSON_WORKFLOWENDTIME); List<Object> jsonComponentList = (ArrayList<Object>) jsonStructureRoot .get(TimelineViewConstants.JSON_COMPONENTS); if (jsonWorkflowName == null || jsonWorkflowName.equals("") || jsonWorkflowStart == null || jsonWorkflowStart.equals("") || jsonWorkflowEnd == null || jsonWorkflowEnd.equals("") || jsonComponentList == null || jsonComponentList.isEmpty()) { return; } workflowNameLabel.setText(jsonWorkflowName); workflowNameLabel.pack(); this.wfStartDate = new Date(); this.wfStartDate.setTime(Long.valueOf(jsonWorkflowStart) .longValue()); this.wfEndDate = new Date(); this.wfEndDate.setTime(Long.valueOf(jsonWorkflowEnd).longValue()); setVisibleArea(wfStartDate, wfEndDate); // set start end endtime to list composite legend // list.setWorkflowStartEndTime(wfStartDate, wfEndDate); this.navigation.setWorflowStartEndTime(wfStartDate, wfEndDate); List<TimelineComponentRow> currentRows = new ArrayList<TimelineComponentRow>(); for (Object jsonCurrentComponentObject : jsonComponentList) { Map<String, Object> jsonCurrentComponent = (Map<String, Object>) jsonCurrentComponentObject; String currentComponentName = (String) jsonCurrentComponent .get(TimelineViewConstants.JSON_COMPONENT_NAME); String currentComponentID = (String) jsonCurrentComponent .get(TimelineViewConstants.JSON_COMPONENT_ID); TimelineComponentRow currentRow = new TimelineComponentRow( currentComponentName, currentComponentID, wfStartDate, wfEndDate); List<Object> jsonActivityList = (ArrayList<Object>) jsonCurrentComponent .get(TimelineViewConstants.JSON_COMPONENT_EVENTS); Collections.sort(jsonActivityList, new Comparator<Object>() { /* * (non-Javadoc) * * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ @Override public int compare(Object o1, Object o2) { Map<String, String> compare1 = (HashMap<String, String>) o1; Map<String, String> compare2 = (HashMap<String, String>) o2; return compare1 .get(TimelineViewConstants.JSON_ACTIVITYTIME) .compareTo( compare2.get(TimelineViewConstants.JSON_ACTIVITYTIME)); } }); List<TimelineActivityPart> currentActivities = new ArrayList<TimelineActivityPart>(); int run = 1; for (Object jsonCurrentActivity : jsonActivityList) { Map<String, String> currentActivityMap = (Map<String, String>) jsonCurrentActivity; Date currentActivityTime = new Date(); long activityTime = Long.valueOf(currentActivityMap .get(TimelineViewConstants.JSON_ACTIVITYTIME)); currentActivityTime.setTime(activityTime); String currentEventType = currentActivityMap .get(TimelineViewConstants.JSON_ACTIVITYTYPE); TimelineActivityType eventType = TimelineActivityType .valueOfjsonName(currentEventType); String comment = null; if (currentActivityMap .containsKey(TimelineViewConstants.JSON_COMPONENT_EVENT_INFOTEXT)) { comment = currentActivityMap .get(TimelineViewConstants.JSON_COMPONENT_EVENT_INFOTEXT); } TimelineActivityPart currentActivity = null; if (eventType == TimelineActivityType.COMPONENT_RUN) { currentActivity = new TimelineActivityPart(currentComponentName, eventType, currentActivityTime, String.valueOf(run++), comment); } else { currentActivity = new TimelineActivityPart(currentComponentName, eventType, currentActivityTime, comment); } if (currentActivities.size() == 0 && !currentActivityTime.equals(wfStartDate)) { TimelineActivityPart currentFirstActivity = new TimelineActivityPart(currentComponentName, TimelineActivityType.WAITING, wfStartDate, null); currentFirstActivity.setEndtime(currentActivityTime); if (currentActivities.size() > 0) { currentActivities.get(currentActivities.size() - 1) .setEndtime(currentActivityTime); } currentActivities.add(currentFirstActivity); } if (currentActivities.size() > 0) { currentActivities.get(currentActivities.size() - 1) .setEndtime(currentActivityTime); } currentActivities.add(currentActivity); } currentRow.setActivities(currentActivities .toArray(new TimelineActivityPart[currentActivities .size()])); currentRow.setWorkflowStartTime(wfStartDate); currentRow.setWorkflowEndTime(wfEndDate); currentRows.add(currentRow); } rows = currentRows.toArray(new TimelineComponentRow[currentRows .size()]); } catch (IOException e) { LogFactory.getLog(TimelineView.class).error(e); return; } showComponentRows(this.rows); } private void setVisibleArea(Date visibleStartTime, Date visibleEndTime) { this.list.setTimeArea(visibleStartTime, visibleEndTime); // if (!mouseDown) { this.navigation.setVisibleArea(visibleStartTime, visibleEndTime); // } } private void showComponentRows(TimelineComponentRow[] newrows) { this.navigation.setWorflowStartEndTime(wfStartDate, wfEndDate); this.navigation.setTimeTableComponentRows(filter(newrows, this.allowedComponentNames)); this.list.setTimeTableComponentRows(filter(newrows, this.allowedComponentNames)); } private TimelineComponentRow[] filter(TimelineComponentRow[] oldrows, String[] allowed) { if (allowed == null) { return oldrows; } List<TimelineComponentRow> showRows = new ArrayList<TimelineComponentRow>(); for (TimelineComponentRow currentRow : oldrows) { if (filterContains(currentRow.getName(), allowed)) { showRows.add(currentRow); } } return showRows.toArray(new TimelineComponentRow[showRows.size()]); } private boolean filterContains(String name, String[] filter) { for (String filterKey : filter) { if (filterKey.equals(name)) { return true; } } return false; } private void makeActions(final Composite parent) { refreshAction = new Action("Refresh") { @Override public void run() { updateContent(); } }; refreshAction.setImageDescriptor(ImageManager.getInstance().getImageDescriptor(StandardImages.REFRESH_16)); refreshAction.setEnabled(false); zoomInAction = new Action(Messages.zoomin) { @Override public void run() { int maxZoom = defaultMaximumZoomValue / 10; int minZoom = currentZoomValue - maxZoom; if (minZoom == 0) { setZoom(defaultMinimumZoomValue); } else if (minZoom > 0) { setZoom(minZoom); } else if (minZoom < 0) { setZoom(defaultMinimumZoomValue); } } }; zoomInAction.setImageDescriptor(ImageDescriptor .createFromURL(TimelineView.class .getResource("/resources/icons/zoom_in.gif"))); zoomInAction.setEnabled(false); zoomOutAction = new Action(Messages.zoomout) { @Override public void run() { int maxZoom = defaultMaximumZoomValue / 10; int minZoom = defaultMaximumZoomValue - currentZoomValue; if (currentZoomValue + maxZoom <= defaultMaximumZoomValue) { setZoom(currentZoomValue + maxZoom); } else if (minZoom > 0 && minZoom < maxZoom) { setZoom(currentZoomValue + minZoom); } } }; zoomOutAction.setImageDescriptor(ImageDescriptor .createFromURL(TimelineView.class .getResource("/resources/icons/zoom_out.gif"))); zoomOutAction.setEnabled(false); filterAction = new Action("Filter") { @Override public void run() { if (allowedComponentNames == null) { List<String> currentList = new ArrayList<String>(); for (TimelineComponentRow currentRow : rows) { currentList.add(currentRow.getName()); } allowedComponentNames = currentList .toArray(new String[currentList.size()]); } TimelineFilterDialog dialog = new TimelineFilterDialog( Display.getCurrent().getActiveShell(), allowedComponentNames); dialog.create(); dialog.setContent(rows); if (dialog.open() == 0) { // 0 = ok allowedComponentNames = dialog.getFilteredNames(); showComponentRows(rows); } } }; filterAction.setImageDescriptor(ImageDescriptor .createFromURL(TimelineView.class .getResource("/resources/icons/filter.gif"))); filterAction.setEnabled(false); } private void contributeToActionBars() { IActionBars bars = getViewSite().getActionBars(); IToolBarManager manager = bars.getToolBarManager(); manager.add(refreshAction); manager.add(new Separator()); manager.add(zoomOutAction); manager.add(zoomInAction); manager.add(new Separator()); manager.add(filterAction); manager.add(new Separator()); } /** * Get an component Icon by its component type Id. * * @param identifier the id * @param caller the caller * @return the image */ public static Image getImageIconFromId(String identifier, Object caller) { ServiceRegistryAccess serviceRegistryAccess = ServiceRegistry .createAccessFor(caller); DistributedComponentKnowledgeService componentKnowledgeService = serviceRegistryAccess .getService(DistributedComponentKnowledgeService.class); Collection<ComponentInstallation> installations = componentKnowledgeService .getCurrentComponentKnowledge().getAllInstallations(); for (ComponentInstallation installation : installations) { if (installation.getInstallationId().startsWith(identifier)) { if (!COMPONENT_ICON_CACHE.containsKey(installation.getInstallationId())) { byte[] icon = installation.getComponentRevision().getComponentInterface().getIcon16(); Image image = ImageDescriptor.createFromImage(new Image(Display.getCurrent(), new ByteArrayInputStream(icon))).createImage(); COMPONENT_ICON_CACHE.put(installation.getInstallationId(), image); } return COMPONENT_ICON_CACHE.get(installation.getInstallationId()); } } return null; } /** * Get a component group Name by an id. * * @param identifier the id * @param caller the caller * @return the display name */ public static String getComponentNameFromId(String identifier, Object caller) { if (identifier == null) { return null; } ServiceRegistryAccess serviceRegistryAccess = ServiceRegistry .createAccessFor(caller); DistributedComponentKnowledgeService componentKnowledgeService = serviceRegistryAccess .getService(DistributedComponentKnowledgeService.class); Collection<ComponentInstallation> installations = componentKnowledgeService .getCurrentComponentKnowledge().getAllInstallations(); for (ComponentInstallation installation : installations) { if (installation.getInstallationId().startsWith(identifier)) { return installation.getComponentRevision().getComponentInterface().getDisplayName(); } } return null; } /** * Calculates the current zoom level. * * @param zoom The current zoomfactor 10000 == 100% */ public void setZoom(int zoom) { final int complete = 10000; Date vET = this.navigation.getVisibleEndTime(); Date vST = this.navigation.getVisibleStartTime(); long diffVSET = vET.getTime() - vST.getTime(); double middleTimeStamp = vST.getTime() + (diffVSET / 2); long startTime = wfStartDate.getTime(); long endTime = wfEndDate.getTime(); double currentAddValue = (zoom * (wfEndDate.getTime() - wfStartDate.getTime())) / (2 * complete); Date newStartDate = new Date((long) (middleTimeStamp - currentAddValue)); Date newEndDate = new Date((long) (middleTimeStamp + currentAddValue)); long newStartTime = newStartDate.getTime(); long newEndTime = newEndDate.getTime(); // handle the newTime, if it reaches above or below the workflowTime if (newStartTime < startTime) { long overTime = startTime - newStartTime; newEndDate = new Date(newEndTime + overTime); newStartDate = wfStartDate; } else if (newEndTime > endTime) { long overTime = endTime - newEndTime; newStartDate = new Date(newStartTime + overTime); newEndDate = wfEndDate; } navigation.setVisibleArea(newStartDate, newEndDate); navigation.notifyAreaChangeListener(); } /** * Converts a Pixel to a Date. * * @param xPixel Contains the pixel which should be converted to Date * @param canvasSizeX Contains the size of the Canvas in the x direction or the possible maximum size of selection * @param currentWorkflowStartTime Contains the start time of the current workflow * @param currentWorkflowEndTime Contains the end time of the current worklfow * @return the converted Date */ public static Date convertPixelToDate(int xPixel, int canvasSizeX, Date currentWorkflowStartTime, Date currentWorkflowEndTime) { long value = ((currentWorkflowEndTime.getTime() * xPixel) + (currentWorkflowStartTime .getTime() * (canvasSizeX - xPixel))) / canvasSizeX; Date date = new Date(); date.setTime(value); return date; } /** * * Converts a Date to a pixel. * * @param date the date * @param canvasSizeX the canvas size * @param currentWorkflowStartTime the current workflowstarttime * @param currentWorkflowEndTime the current workflowendtime * @return the return */ public static int convertDateToPixel(Date date, int canvasSizeX, Date currentWorkflowStartTime, Date currentWorkflowEndTime) { long value = date.getTime(); int xPixel = (int) (((value - currentWorkflowStartTime.getTime()) * canvasSizeX) / (currentWorkflowEndTime .getTime() - currentWorkflowStartTime.getTime())); return xPixel; } /** * {@inheritDoc} * * @see org.eclipse.ui.part.WorkbenchPart#setFocus() */ @Override public void setFocus() { } @Override public void resized() { sashMiddle.setWeights(this.list.getWeights()); } @Override public void controlMoved(ControlEvent arg0) { } @Override public void controlResized(ControlEvent arg0) { this.list.setWeights(sashMiddle.getWeights()); } @Override public void widgetDefaultSelected(SelectionEvent arg0) { } @Override public void widgetSelected(SelectionEvent arg0) { int begin = scrollBar.getMinimum() + scrollBar.getSelection(); int end = scrollBar.getMinimum() + scrollBar.getSelection() + scrollBar.getThumb(); setVisibleArea( convertPixelToDate(begin, scrollBar.getMaximum(), wfStartDate, wfEndDate), convertPixelToDate(end, scrollBar.getMaximum(), wfStartDate, wfEndDate)); } @Override public void selectedAreaChanged(Date selectedStartTime, Date selectedEndTime) { final int percent = 100; this.list.setTimeArea(selectedStartTime, selectedEndTime); long selectedTime = selectedEndTime.getTime() - selectedStartTime.getTime(); long wfTime = wfEndDate.getTime() - wfStartDate.getTime(); float dividedTime = ((float) selectedTime / wfTime) * percent; currentZoomValue = Math.round(dividedTime) * percent; // SWT Slider does not always disable slider if value == maximum value this.scrollBar.setEnabled(currentZoomValue < scrollBar.getMaximum()); if (currentZoomValue != 0) { this.scrollBar.setThumb(currentZoomValue); } else { this.scrollBar.setThumb(defaultMinimumZoomValue); } int beginSelection = convertDateToPixel(selectedStartTime, this.scrollBar.getMaximum(), wfStartDate, wfEndDate) - scrollBar.getMinimum(); this.scrollBar.setSelection(beginSelection); } }