blob: 3da917c2d589e8adbff5083528b616c9e4fb9d51 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 The Regents of the University of California.
* This material was produced under U.S. Government contract W-7405-ENG-36
* for Los Alamos National Laboratory, which is operated by the University
* of California for the U.S. Department of Energy. The U.S. Government has
* rights to use, reproduce, and distribute this software. NEITHER THE
* GOVERNMENT NOR THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
* ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified
* to produce derivative works, such modified software should be clearly marked,
* so as not to confuse it with the version available from LANL.
*
* Additionally, this program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* LA-CC 04-115
*******************************************************************************/
package org.eclipse.ptp.ui.views;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.ptp.core.IModelManager;
import org.eclipse.ptp.core.PTPCorePlugin;
import org.eclipse.ptp.core.elements.IPJob;
import org.eclipse.ptp.core.elements.IPMachine;
import org.eclipse.ptp.core.elements.IPNode;
import org.eclipse.ptp.core.elements.IPProcess;
import org.eclipse.ptp.core.elements.IPQueue;
import org.eclipse.ptp.core.elements.IResourceManager;
import org.eclipse.ptp.core.elements.attributes.JobAttributes;
import org.eclipse.ptp.core.elements.attributes.ResourceManagerAttributes;
import org.eclipse.ptp.core.elements.events.IChangedJobEvent;
import org.eclipse.ptp.core.elements.events.IChangedMachineEvent;
import org.eclipse.ptp.core.elements.events.IChangedNodeEvent;
import org.eclipse.ptp.core.elements.events.IChangedQueueEvent;
import org.eclipse.ptp.core.elements.events.INewJobEvent;
import org.eclipse.ptp.core.elements.events.INewMachineEvent;
import org.eclipse.ptp.core.elements.events.INewNodeEvent;
import org.eclipse.ptp.core.elements.events.INewQueueEvent;
import org.eclipse.ptp.core.elements.events.IRemoveJobEvent;
import org.eclipse.ptp.core.elements.events.IRemoveMachineEvent;
import org.eclipse.ptp.core.elements.events.IRemoveNodeEvent;
import org.eclipse.ptp.core.elements.events.IRemoveQueueEvent;
import org.eclipse.ptp.core.elements.listeners.IMachineChildListener;
import org.eclipse.ptp.core.elements.listeners.IQueueChildListener;
import org.eclipse.ptp.core.elements.listeners.IResourceManagerChildListener;
import org.eclipse.ptp.core.events.IChangedResourceManagerEvent;
import org.eclipse.ptp.core.events.INewResourceManagerEvent;
import org.eclipse.ptp.core.events.IRemoveResourceManagerEvent;
import org.eclipse.ptp.core.listeners.IModelManagerChildListener;
import org.eclipse.ptp.ui.UIUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.WorkbenchJob;
/**
* @author Daniel (JD) Barboza
*
* Based on original work by Greg Watson and Clement Chu
*
*/
public class MachinesNodesView extends ViewPart {
private final IModelManagerChildListener modelManagerListener = new MMChildListener();
private final IResourceManagerChildListener resourceManagerListener = new RMChildListener();
private final IMachineChildListener machineListener = new MachineChildListener();
private final IQueueChildListener queueChildListener = new QueueChildListener();
private final ArrayList <MachineGraphicalRepresentation> machinesGraphicalRepresentations =
new ArrayList <MachineGraphicalRepresentation>();
private final Hashtable <String, NodeGraphicalRepresentation> nodesHashMap =
new Hashtable <String, NodeGraphicalRepresentation> ();
protected RefreshWorkbenchJob refreshWorkbench = new RefreshWorkbenchJob();
private MachineNodesCanvas canvas = null;
private Listener listener = null;
private Font defaultFont = null;
private Object elementSelected = null;
public MachinesNodesView() {
super();
}
public void createPartControl(final Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new FillLayout());
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
composite.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_WHITE));
canvas = new MachineNodesCanvas(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
FontData[] fd = composite.getDisplay().getSystemFont().getFontData();
for (int i = 0; i < fd.length; i++) {
fd[i].setHeight(8);
}
defaultFont = new Font( composite.getDisplay(),fd);
/*
* Wait until the view has been created before registering for events
*/
IModelManager mm = PTPCorePlugin.getDefault().getModelManager();
synchronized (mm) {
/*
* Add us to any existing RM's. I guess it's possible we could
* miss a RM if a new event arrives while we're doing this, but is
* it a problem?
*/
for (IResourceManager rm : mm.getUniverse().getResourceManagers()) {
rm.addChildListener(resourceManagerListener);
/*
* We need to get the current state of the nodes on this
* resource manager, browsing through the machines and adding
* them to our view
*/
for (int i = 0; i < rm.getMachines().length; i++) {
IPMachine machine = rm.getMachines()[i];
machine.addChildListener(machineListener);
MachineGraphicalRepresentation machinegr =
new MachineGraphicalRepresentation(machine.getName(), machine.getID());
for (IPNode node : machine.getNodes()) {
// create graphical representation of the node
NodeGraphicalRepresentation nodegr =
new NodeGraphicalRepresentation(node.getName(), node.getID());
machinegr.addNode(nodegr);
machinesGraphicalRepresentations.add(machinegr);
}
}
}
mm.addListener(modelManagerListener);
}
refreshView();
}
private void refreshView() {
refreshWorkbench.schedule(true, true);
}
/*
* Method required so the class can extends ViewPart
* @see org.eclipse.ui.part.WorkbenchPart#setFocus()
*/
public void setFocus() {
}
private class MachineGraphicalRepresentation {
private ArrayList <NodeGraphicalRepresentation> nodes = null;
private Rectangle rectangle = null;
private String machineName = "";
private String machineID = "";
private static final int WIDTH = 50;
private static final int HEIGHT = 50;
private Color color = null;
private boolean halted;
private boolean selected = false;
public MachineGraphicalRepresentation(String machineName, String machineID) {
this.machineName = machineName;
this.setMachineID(machineID);
nodes = new ArrayList <NodeGraphicalRepresentation> ();
rectangle = new Rectangle(0, 0, WIDTH, HEIGHT);
halted = false;
}
public MachineGraphicalRepresentation(String machineName, String machineID, Color color) {
this.machineName = machineName;
this.setMachineID(machineID);
nodes = new ArrayList <NodeGraphicalRepresentation> ();
rectangle = new Rectangle(0, 0, WIDTH, HEIGHT);
this.color = color;
halted = false;
}
public MachineGraphicalRepresentation(String machineName, Color color, int Ox, int Oy, int width, int height) {
this.machineName = machineName;
this.color = color;
nodes = new ArrayList <NodeGraphicalRepresentation> ();
rectangle = new Rectangle(Ox, Oy, width, height);
}
public MachineGraphicalRepresentation(String machineName, Color color, int Ox, int Oy) {
this.machineName = machineName;
this.color = color;
nodes = new ArrayList <NodeGraphicalRepresentation> ();
rectangle = new Rectangle(Ox, Oy, WIDTH, HEIGHT);
}
public boolean containsPoint(int x, int y) {
return rectangle.contains(x, y);
}
public String getMachineName() {
return machineName;
}
public Rectangle getGraphicalRepresentation() {
return rectangle;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public boolean addNode(NodeGraphicalRepresentation node) {
return nodes.add(node);
}
public boolean removeNode(NodeGraphicalRepresentation node) {
return nodes.remove(node);
}
public void removeNode(String nodeID) {
for (int i = 0; i < nodes.size(); i ++) {
if (nodes.get(i).getNodeID().equals(nodeID)) {
nodes.remove(i);
break;
}
}
}
public void setHalted(boolean halted) {
this.halted = halted;
}
public boolean isHalted() {
return halted;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public boolean isSelected() {
return selected;
}
public ArrayList <NodeGraphicalRepresentation> getNodes() {
return nodes;
}
public void setMachineID(String nodeID) {
this.machineID = nodeID;
}
public String getMachineID() {
return machineID;
}
}
private class NodeGraphicalRepresentation {
private Rectangle rectangle = null;
private String nodeName = "";
private String nodeID = "";
private static final int WIDTH = 20;
private static final int HEIGHT = 20;
private boolean selected = false;
private ArrayList <String> jobsIDs = null;
public NodeGraphicalRepresentation (String nodeName, String nodeID) {
this.nodeName = nodeName;
this.nodeID = nodeID;
rectangle = new Rectangle(0, 0, WIDTH, HEIGHT);
jobsIDs = new ArrayList<String> ();
}
public String getNodeName() {
return nodeName;
}
public Rectangle getGraphicalRepresentation() {
return rectangle;
}
public void setGraphicalRepresentation(Rectangle ret) {
rectangle = ret;
}
public void setNodeID(String nodeID) {
this.nodeID = nodeID;
}
public String getNodeID() {
return nodeID;
}
public int getNumberOfJobs() {
return jobsIDs.size();
}
public void addJob(String jobID) {
if (! jobsIDs.contains(jobID))
jobsIDs.add(jobID);
}
public void removeJob(String jobID) {
jobsIDs.remove(jobID);
}
public ArrayList <String> getJobsIDs () {
return jobsIDs;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public boolean isSelected() {
return selected;
}
public boolean containsPoint(int x, int y) {
return rectangle.contains(x, y);
}
}
private class MachineNodesCanvas extends Canvas {
private Composite composite = null;
Point origin = new Point (0, 0);
ScrollBar verticalBar = null;
ScrollBar horizontalBar = null;
int WIDTH = 1000;
int HEIGHT = 3000;
public MachineNodesCanvas(Composite composite, int style) {
super(composite, style);
this.composite = composite;
/*
* Limit the width size based on screen width
*/
if (getDisplay(). getPrimaryMonitor() != null)
WIDTH = getDisplay(). getPrimaryMonitor().getBounds().width;
installListeners();
}
protected void installListeners() {
listener = new Listener() {
public void handleEvent(Event event) {
switch (event.type) {
case SWT.Dispose:
//handleDispose(event);
break;
case SWT.KeyDown:
//handleKeyDown(event);
break;
case SWT.KeyUp:
//handleKeyUp(event);
break;
case SWT.MouseDown:
handleMouseDown(event);
break;
case SWT.MouseUp:
//handleMouseUp(event);
break;
case SWT.MouseDoubleClick:
//handleMouseDoubleClick(event);
break;
case SWT.MouseMove:
//handleMouseMove(event);
break;
case SWT.MouseHover:
//handleMouseHover(event);
break;
case SWT.Paint:
handlePaint(event);
break;
case SWT.Resize:
handleResize(event);
break;
case SWT.FocusOut:
//handleFocusOut(event);
break;
}
}
};
addListener(SWT.Dispose, listener);
addListener(SWT.KeyDown, listener);
addListener(SWT.KeyUp, listener);
addListener(SWT.MouseDown, listener);
addListener(SWT.MouseUp, listener);
addListener(SWT.MouseDoubleClick, listener);
addListener(SWT.MouseMove, listener);
addListener(SWT.MouseHover, listener);
addListener(SWT.Paint, listener);
addListener(SWT.Resize, listener);
addListener(SWT.FocusOut, listener);
verticalBar = this. getVerticalBar();
horizontalBar = this.getHorizontalBar();
if (horizontalBar != null) {
horizontalBar.addListener (SWT.Selection, new Listener () {
public void handleEvent (Event e) {
int hSelection = horizontalBar.getSelection ();
origin.x = -hSelection;
redraw();
}
});
}
if ( verticalBar!= null) {
verticalBar.addListener (SWT.Selection, new Listener () {
public void handleEvent (Event e) {
int vSelection = verticalBar.getSelection ();
origin.y = -vSelection;
redraw();
}
});
}
}
protected void handleMouseDown(Event e) {
/*
* Check if the user clicked on some element of our view. First, check
* if the y coordinate matches with some of our machine representations,
* considering that our nodes y's range will be the same as their respective
* machines.
*/
int mouseX = e.x - origin.x;
int mouseY = e.y - origin.y;
Object selection = null;
for (MachineGraphicalRepresentation machinegr: machinesGraphicalRepresentations) {
if ( (mouseY > machinegr.getGraphicalRepresentation().y ) && (mouseY < machinegr.getGraphicalRepresentation().y + machinegr.getGraphicalRepresentation().height )) {
/*
* mouseY belongs to this machine representation's Y range. Now
* we check the machine and its nodes to see if we have a match
*/
if (machinegr.containsPoint(mouseX, mouseY) )
selection = machinegr;
else {
for (NodeGraphicalRepresentation nodegr: machinegr.getNodes()) {
if (nodegr.containsPoint(mouseX, mouseY)) {
selection = nodegr;
break;
}
}
}
break;
}
}
if (selection != elementSelected) {
elementSelected = selection;
refreshView();
}
}
protected void handleResize(Event event) {
Rectangle rect = getBounds ();
Rectangle client = getClientArea ();
horizontalBar.setMaximum (WIDTH);
verticalBar.setMaximum (HEIGHT);
horizontalBar.setThumb (Math.min (rect.width, client.width));
verticalBar.setThumb (Math.min (rect.height, client.height));
int hPage = WIDTH - client.width;
int vPage = HEIGHT - client.height;
int hSelection = horizontalBar.getSelection ();
int vSelection = verticalBar.getSelection ();
if (hSelection >= hPage) {
if (hPage <= 0) hSelection = 0;
origin.x = -hSelection;
}
if (vSelection >= vPage) {
if (vPage <= 0) vSelection = 0;
origin.y = -vSelection;
}
redraw ();
}
protected void handlePaint(Event event){
Rectangle clientArea = getClientArea();
int renderWidth = clientArea.width;
int renderHeight = clientArea.height;
if (event.height == 0 || (renderWidth == 0 && renderHeight == 0)) {
// Check if there is work to do
return;
}
Image imageBuffer = null;
GC newGC = null;
imageBuffer = new Image(getDisplay(), WIDTH, HEIGHT);
newGC = new GC(imageBuffer, SWT.LEFT_TO_RIGHT);
/*
* set font to our predefined default font
*/
newGC.setFont(defaultFont);
/*
* set some parameters regarding font size
*/
int fontHeight = defaultFont .getFontData()[0].getHeight();
/*
* If some graphical element is selected, write additional info about it
* on the top of the view.
*/
String additionalInfo= null;
if (elementSelected != null) {
additionalInfo="Selected: ";
newGC.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_WHITE));
if (elementSelected instanceof MachineGraphicalRepresentation) {
MachineGraphicalRepresentation machine = (MachineGraphicalRepresentation) elementSelected;
additionalInfo += "Machine name : " + machine.getMachineName() + " || ID: " + machine.getMachineID();
}
else if (elementSelected instanceof NodeGraphicalRepresentation) {
NodeGraphicalRepresentation node = (NodeGraphicalRepresentation) elementSelected;
additionalInfo += "Node name : " + node.getNodeName() + " || ID: " + node.getNodeID();
if (node.getNumberOfJobs() > 0) {
additionalInfo += " || jobs current running: ";
for (String jobID: node.getJobsIDs())
additionalInfo += jobID + " ";
}
}
// mark this element to receive different background color
if (elementSelected instanceof MachineGraphicalRepresentation)
((MachineGraphicalRepresentation) elementSelected).setSelected(true);
else
((NodeGraphicalRepresentation) elementSelected).setSelected(true);
}
/*
* Some constants used to paint machines and nodes
*/
int Ox = 10;
int x = Ox;
int Oy = 10;
int y = Oy;
int nodeWidth =fontHeight*2;
int nodeHeight = fontHeight*2;
/*
* It seems that 2* fontHeight is equivalent to the exact height size
* of the font in pixels. This space will be used to draw the
* info string later
*/
y = y + (fontHeight * 4);
/*
* paint machines and processes
*/
for (MachineGraphicalRepresentation machinegr: machinesGraphicalRepresentations)
{
if (! machinegr.isHalted() )
{
if (machinegr.isSelected()) {
newGC.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_YELLOW));
machinegr.setSelected(false);
}
else
newGC.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_RED));
machinegr.getGraphicalRepresentation().x = x;
machinegr.getGraphicalRepresentation().y = y;
newGC.fillGradientRectangle(x, y, machinegr.getGraphicalRepresentation().width, machinegr.getGraphicalRepresentation().height, false);
int currentX = machinegr.getGraphicalRepresentation().x + MachineGraphicalRepresentation.WIDTH + 10;
int currentY = machinegr.getGraphicalRepresentation().y;
// paint process of this node
if ( machinegr.getNodes() != null)
{
/*
* If the machine has more than 5 nodes, we draw them in 2 rows.
* otherwise, draw them in a single row
*/
if (machinegr.getNodes().size() > 5) {
int totalSize =machinegr.getNodes().size();
int half = totalSize / 2;
int i;
int xRow = currentX;
for ( i = 0; i < half +(totalSize % 2); i++) {
NodeGraphicalRepresentation nodegr = machinegr.getNodes() .get(i);
// adjusting node graphical representation
nodegr.getGraphicalRepresentation().width = nodeWidth;
nodegr.getGraphicalRepresentation().height = nodeHeight;
nodegr.getGraphicalRepresentation().x = currentX;
nodegr.getGraphicalRepresentation().y = currentY;
if (nodegr.isSelected()) {
newGC.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_YELLOW));
nodegr.setSelected(false);
}
else
newGC.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_WHITE));
newGC.fillRectangle(nodegr.getGraphicalRepresentation());
newGC.setForeground(composite.getDisplay().getSystemColor(SWT.COLOR_BLACK));
if (nodegr.getNumberOfJobs() > 9)
newGC.drawString("+", currentX + fontHeight/2, currentY);
else
newGC.drawString(String.valueOf(nodegr.getNumberOfJobs()), currentX + fontHeight/2, currentY);
newGC.drawRectangle(nodegr.getGraphicalRepresentation());
currentX = currentX + NodeGraphicalRepresentation.WIDTH + 1;
}
// updatex and y to paint next row
//
currentX = xRow;
currentY += nodeHeight + 5;
for (int j = i ; j < totalSize; j++) {
NodeGraphicalRepresentation nodegr = machinegr.getNodes() .get(j);
// adjusting node graphical representation
nodegr.getGraphicalRepresentation().width = nodeWidth;
nodegr.getGraphicalRepresentation().height = nodeHeight;
nodegr.getGraphicalRepresentation().x = currentX;
nodegr.getGraphicalRepresentation().y = currentY;
if (nodegr.isSelected()) {
newGC.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_YELLOW));
nodegr.setSelected(false);
}
else
newGC.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_WHITE));
newGC.fillRectangle(nodegr.getGraphicalRepresentation());
newGC.setForeground(composite.getDisplay().getSystemColor(SWT.COLOR_BLACK));
if (nodegr.getNumberOfJobs() > 9)
newGC.drawString("+", currentX + fontHeight/2, currentY);
else
newGC.drawString(String.valueOf(nodegr.getNumberOfJobs()), currentX + fontHeight/2, currentY);
newGC.drawRectangle(nodegr.getGraphicalRepresentation());
currentX = currentX + NodeGraphicalRepresentation.WIDTH + 1;
}
}
/*
* If the machine has less than 5 nodes, paint all of them in a single row.
*/
else
for (NodeGraphicalRepresentation nodegr : machinegr.getNodes()) {
// adjusting node graphical representation
nodegr.getGraphicalRepresentation().width = nodeWidth;
nodegr.getGraphicalRepresentation().height = nodeHeight;
nodegr.getGraphicalRepresentation().x = currentX;
nodegr.getGraphicalRepresentation().y = currentY;
if (nodegr.isSelected()) {
newGC.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_YELLOW));
nodegr.setSelected(false);
}
else
newGC.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_WHITE));
newGC.fillRectangle(nodegr.getGraphicalRepresentation());
newGC.setForeground(composite.getDisplay().getSystemColor(SWT.COLOR_BLACK));
if (nodegr.getNumberOfJobs() > 9)
newGC.drawString("+", currentX + fontHeight/2, currentY);
else
newGC.drawString(String.valueOf(nodegr.getNumberOfJobs()), currentX + fontHeight/2, currentY);
newGC.drawRectangle(nodegr.getGraphicalRepresentation());
currentX = currentX + NodeGraphicalRepresentation.WIDTH + 1;
}
}
// update y to print machine name
y = y + MachineGraphicalRepresentation.HEIGHT + 10;
newGC.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_WHITE));
newGC.drawString(machinegr.getMachineName(), x, y);
// update y to paint next machine
y = y + 30;
}
}
/*
* We write the info string now, thus it'll be on top and
* always visible. Note that we use x instead of
* the relative position because we want this string
* to be 'scrollable' on the horizontal., but not
* on the vertical
*/
if (additionalInfo != null) {
newGC.setBackground(composite.getDisplay().getSystemColor(SWT.COLOR_YELLOW));
newGC.drawString(additionalInfo, x, Oy - origin.y);
}
event.gc.drawImage(imageBuffer, origin.x, origin.y);
newGC.dispose();
imageBuffer.dispose();
}
}
private boolean machineRepresentationExists(String machineID) {
for (MachineGraphicalRepresentation machinegr : machinesGraphicalRepresentations)
if (machinegr.getMachineID().equals(machineID))
return true;
return false;
}
/*
* Listener to take care of job events.
*/
private final class QueueChildListener implements IQueueChildListener {
public void handleEvent(IChangedJobEvent e) {
boolean needRefresh = false;
for (IPJob job : e.getJobs()) {
if ( (job.getState() == JobAttributes.State.STARTED) || ( job.getState() == JobAttributes.State.RUNNING) ||
(job.getState() == JobAttributes.State.PENDING ) ) {
/*
* Add job to the graphical representation of its node
*/
for (int i = 0; i < job.getProcesses().length; i ++) {
IPProcess process= job.getProcesses()[i];
if (process.getNode() != null) {
nodesHashMap.get(process.getNode().getID())
.addJob(job.getID());
needRefresh = true;
}
}
}
else {
/*
* remove job from the graphical representation of its node
*/
for (int i = 0; i < job.getProcesses().length; i ++) {
IPProcess process= job.getProcesses()[i];
if (process.getNode() != null) {
nodesHashMap.get(process.getNode().getID())
.removeJob(job.getID());
needRefresh = true;
}
}
}
if (needRefresh)
refreshView();
}
}
public void handleEvent(final INewJobEvent e) {
boolean needRefresh = false;
for (IPJob job: e.getJobs()) {
/*
* Add job to the graphical representation of its node
*/
for (int i = 0; i < job.getProcesses().length; i ++) {
IPProcess process= job.getProcesses()[i];
if (process.getNode() != null) {
nodesHashMap.get(process.getNode().getID())
.addJob(job.getID());
needRefresh = true;
}
}
}
if (needRefresh)
refreshView();
}
public void handleEvent(IRemoveJobEvent e) {
boolean needRefresh = false;
for (IPJob job: e.getJobs()) {
/*
* remove job from the graphical representation of its node
*/
for (int i = 0; i < job.getProcesses().length; i ++) {
IPProcess process= job.getProcesses()[i];
if (process.getNode() != null) {
nodesHashMap.get(process.getNode().getID())
.removeJob(job.getID());
break;
}
}
}
if (needRefresh)
refreshView();
}
}
private final class MachineChildListener implements IMachineChildListener {
public void handleEvent(final IChangedNodeEvent e) {
}
public void handleEvent(final INewNodeEvent e) {
UIUtils.safeRunAsyncInUIThread(new SafeRunnable() {
public void run() {
for (IPNode node : e.getNodes()) {
// create graphical representation of the node
NodeGraphicalRepresentation nodegr = new NodeGraphicalRepresentation(node.getName(), node.getID());
// associate it with the correspondent IPMachine
for (MachineGraphicalRepresentation machine : machinesGraphicalRepresentations) {
if (machine.getMachineID().equals(node.getMachine().getID()) ){
machine.addNode(nodegr);
nodesHashMap.put(node.getID(), nodegr);
break;
}
}
}
}
});
refreshView();
}
public void handleEvent(final IRemoveNodeEvent e) {
UIUtils.safeRunAsyncInUIThread(new SafeRunnable() {
public void run() {
for (IPNode node : e.getNodes()) {
// delete the node graphical view on the corresponding IPMachine
for (MachineGraphicalRepresentation machine : machinesGraphicalRepresentations) {
if (machine.getMachineID().equals(node.getMachine().getID()) ){
machine.removeNode(node.getID());
nodesHashMap.remove(node.getID());
break;
}
}
}
}
});
refreshView();
}
}
private final class MMChildListener implements IModelManagerChildListener {
public void handleEvent(IChangedResourceManagerEvent e) {
boolean needRefresh = false;
for (IResourceManager rm : e.getResourceManagers()) {
if ( ( rm.getState() == ResourceManagerAttributes.State.STOPPED ) ||
( rm.getState() == ResourceManagerAttributes.State.SUSPENDED) ||
( rm.getState() == ResourceManagerAttributes.State.ERROR) ) {
/*
* refresh the view, removing the resource manager machines, but
* not removing machine listeners.
*/
for (IPMachine machine : rm.getMachines()) {
String machineID = machine.getID();
for (MachineGraphicalRepresentation machinegr : machinesGraphicalRepresentations)
if (machinegr.getMachineID().equals(machineID)) {
machinegr.setHalted(true);
needRefresh = true;
break;
}
}
}
/*
* otherwise, reactivate machines of the started / starting resource
* manager
*/
else {
for (IPMachine machine : rm.getMachines()) {
String machineID = machine.getID();
for (MachineGraphicalRepresentation machinegr : machinesGraphicalRepresentations)
if (machinegr.getMachineID().equals(machineID)) {
machinegr.setHalted(false);
needRefresh = true;
break;
}
}
}
}
if (needRefresh)
refreshView();
}
public void handleEvent(INewResourceManagerEvent e) {
/*
* Add resource manager child listener so we get notified when new
* machines are added to the model.
*/
final IResourceManager rm = e.getResourceManager();
rm.addChildListener(resourceManagerListener);
}
public void handleEvent(IRemoveResourceManagerEvent e) {
/*
* Removed resource manager child listener when resource manager is removed.
*/
e.getResourceManager().removeChildListener(resourceManagerListener);
}
}
private final class RMChildListener implements IResourceManagerChildListener {
public void handleEvent(IChangedMachineEvent e) {
}
public void handleEvent(IChangedQueueEvent e) {
}
public void handleEvent(final INewMachineEvent e) {
boolean needRefresh = false;
for (IPMachine machine : e.getMachines()) {
/*
* check if the machine wasn't added already on the
* start of the view
*/
if (! machineRepresentationExists(machine.getID()) ){
/*
* Add us as a child listener so we get notified of node events
*/
machine.addChildListener(machineListener);
MachineGraphicalRepresentation machinegr = new MachineGraphicalRepresentation(machine.getName(), machine.getID() );
machinesGraphicalRepresentations.add(machinegr);
needRefresh = true;
}
}
//refresh if needed
if (needRefresh)
refreshView();
}
public void handleEvent(INewQueueEvent e) {
for (IPQueue queue : e.getQueues()) {
queue.addChildListener(queueChildListener);
}
}
public void handleEvent(final IRemoveMachineEvent e) {
/*
* Update views when a machine is removed.
*/
UIUtils.safeRunAsyncInUIThread(new SafeRunnable() {
public void run() {
for (IPMachine machine : e.getMachines()) {
for (int i = 0; i < machinesGraphicalRepresentations.size(); i++) {
if (machinesGraphicalRepresentations.get(i).getMachineID().equals(machine.getID())) {
machinesGraphicalRepresentations.remove(i);
break;
}
}
/*
* Remove child listener
*/
machine.removeChildListener(machineListener);
}
}
});
refreshView();
}
public void handleEvent(IRemoveQueueEvent e) {
for (IPQueue queue : e.getQueues()) {
queue.removeChildListener(queueChildListener);
}
}
}
class RefreshWorkbenchJob extends WorkbenchJob {
private final ReentrantLock waitLock = new ReentrantLock();
private List<Boolean> refreshList = new ArrayList<Boolean>();
public RefreshWorkbenchJob() {
super("Refreshing workbench...");
}
public IStatus runInUIThread(IProgressMonitor monitor) {
boolean refreshAll = isRefreshAll();
if (!canvas.isDisposed()) {
canvas.redraw();
}
//if last refresh object is true and previous refresh is false, then refresh again
boolean lastValue = isRefreshAll();
waitLock.lock();
try {
refreshList.clear();
if (refreshAll != lastValue && !refreshAll) {
refreshList.add(new Boolean(true));
schedule();
}
}
finally {
waitLock.unlock();
}
return Status.OK_STATUS;
}
public boolean shouldSchedule() {
int size = size();
return (size == 1);
}
private int size() {
waitLock.lock();
try {
return refreshList.size();
}
finally {
waitLock.unlock();
}
}
private boolean isRefreshAll() {
waitLock.lock();
try {
return refreshList.get(refreshList.size()-1).booleanValue();
}
finally {
waitLock.unlock();
}
}
public void schedule(boolean refresh_all, boolean force) {
waitLock.lock();
try {
if (force)
refreshList.clear();
refreshList.add(new Boolean(refresh_all));
}
finally {
waitLock.unlock();
}
schedule();
}
}
}