/*
* Copyright (c) 2012 European Synchrotron Radiation Facility,
* Diamond Light Source Ltd.
*
* All rights reserved. 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
*/
package fable.framework.ui.views;
import java.io.PrintStream;
import jep.JepException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.layout.GridLayout;
import org.eclipse.swt.opengl.GLCanvas;
import org.eclipse.swt.opengl.GLData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IOConsoleOutputStream;
import org.eclipse.ui.part.ViewPart;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import fable.framework.toolbox.ToolBox;
import fable.framework.ui.rcp.Activator;
import fable.framework.views.FableMessageConsole;
import fable.python.ChiFile;
public class chiPlotView extends ViewPart {
/**
* Display an image as a 3d relief plot using opengl as an eclipse view. The
* data to display are updated by calling the setData() method.
*
* @author andy gotz
*
*/
public FableMessageConsole console;
public static final String ID = "fable.framework.ui.views.chiPlotView";
public static chiPlotView thisView = null;
public static GLContext context = null;
// public static GLU glu = new GLU();
// public static GLUT glut = new GLUT();
static private SceneGrip grip = null;
private static GLCanvas canvas = null;
private Spinner minimumSpinner, maximumSpinner;
private Button freezeButton, autoscaleButton;
private static boolean freeze = false, autoscale = true;
private Button updateButton, resetButton;
/* a simple lookup table to display a temperature-like lut */
private static float[] blue = { 1.0f, 0.333f, 0.666f, 0.999f, 0.833f,
0.666f, 0.5f, 0.333f, 0.166f, 0.0f, 0.0f };
private static float[] green = { 1.0f, 0.0f, 0.111f, 0.222f, 0.333f,
0.666f, 0.999f, 0.666f, 0.333f, 0.0f, 0.0f };
private static float[] red = { 1.0f, 0.0f, 0.055f, 0.110f, 0.165f, 0.220f,
0.275f, 0.333f, 0.666f, 0.999f, 1.0f };
private static int COLOR_INDEX_MAX = 10;
private float scaleMinimum, scaleMaximum;
private static int pointSize = 4;
// KE: Var iable that are not really used are commented out
// private static float scale = 1;
private static float[] image = null;
private static int imageWidth = 0;
private static int imageHeight = 0;
// private static float zcenter;
private float dots[] = null;
// private float maximum;
private float minimum, mean;
private String fileName;
// private float size;
private static int canvasWidth = 0;
private static int canvasHeight = 0;
private static float zscale;
private static boolean reliefListFirst = true;
private static int reliefList;
// private static Logger logger;
// protected float aspect;
static boolean firstImage = true;
/**
* This is a callback that will allow us to create the viewer and initialize
* it.
*/
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets
* .Composite)
*/
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets
* .Composite)
*/
public void createPartControl(Composite parent) {
// logger = FableLogger.getLogger();
console = new FableMessageConsole("Peaksearch console");
ConsolePlugin.getDefault().getConsoleManager().addConsoles(
new IConsole[] { console });
console.displayOut("Welcome to chiplotview "
+ ToolBox.getPluginVersion(Activator.PLUGIN_ID));
IOConsoleOutputStream stream = console.newOutputStream();
// console_debug = new ConsoleLineTracker();
System.setOut(new PrintStream(stream, true));
System.setErr(new PrintStream(stream));
thisView = this;
parent.setLayout(new GridLayout());
Composite controlPanelComposite = new Composite(parent, SWT.NULL);
GridLayout controlGridLayout = new GridLayout();
controlGridLayout.numColumns = 8;
controlPanelComposite.setLayout(controlGridLayout);
controlPanelComposite.setLayoutData(new GridData(SWT.FILL, SWT.NONE,
true, false));
freezeButton = new Button(controlPanelComposite, SWT.CHECK);
freezeButton.setText("Freeze");
freezeButton.setToolTipText("freeze 3d relief, disable rotation");
freezeButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if (freezeButton.getSelection())
freeze = true;
else
freeze = false;
}
});
resetButton = new Button(controlPanelComposite, SWT.NULL);
resetButton.setText("Reset");
resetButton
.setToolTipText("reset 3d projection to be flat and fill the canvas");
resetButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
grip.init();
}
});
autoscaleButton = new Button(controlPanelComposite, SWT.CHECK);
autoscaleButton.setText("Autoscale");
autoscaleButton
.setToolTipText("autoscale 3d relief between minimum and mean");
autoscaleButton.setSelection(true);
autoscaleButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if (autoscaleButton.getSelection()) {
if (!autoscale) {
autoscale = true;
scaleImage();
drawReliefList();
}
minimumSpinner.setEnabled(false);
maximumSpinner.setEnabled(false);
} else {
if (autoscale) {
autoscale = false;
scaleImage();
drawReliefList();
}
minimumSpinner.setEnabled(true);
maximumSpinner.setEnabled(true);
}
}
});
Label minLabel = new Label(controlPanelComposite, SWT.NULL);
minLabel.setText("Minimum");
minimumSpinner = new Spinner(controlPanelComposite, SWT.NULL);
minimumSpinner.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true,
false));
minimumSpinner.setMinimum(0);
minimumSpinner.setMaximum(Integer.MAX_VALUE);
minimumSpinner.setEnabled(false);
Label maxLabel = new Label(controlPanelComposite, SWT.NULL);
maxLabel.setText("Maximum");
maximumSpinner = new Spinner(controlPanelComposite, SWT.NULL);
maximumSpinner.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true,
false));
maximumSpinner.setMinimum(0);
maximumSpinner.setMaximum(Integer.MAX_VALUE);
maximumSpinner.setEnabled(false);
updateButton = new Button(controlPanelComposite, SWT.NULL);
updateButton.setText("Update");
updateButton.setToolTipText("redraw 3d relief plot");
updateButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
scaleImage();
drawReliefList();
drawRelief();
}
});
Composite comp = new Composite(parent, SWT.NONE);
comp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
comp.setLayout(new FillLayout());
GLData data = new GLData();
data.doubleBuffer = true;
canvas = new GLCanvas(comp, SWT.NONE, data);
canvas.setSize(comp.getSize());
canvas.setCurrent();
// context =
// GL11.GLDrawableFactory.getFactory().createExternalGLContext();
canvas.addListener(SWT.Resize, new Listener() {
public void handleEvent(Event event) {
Rectangle bounds = canvas.getBounds();
canvas.setCurrent();
try {
GLContext.useContext(canvas);
} catch (LWJGLException e) {
e.printStackTrace();
}
GL11.glViewport(0, 0, bounds.width, bounds.height);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
// GLU glu = new GLU();
// aspect = (float) imageWidth / (float) imageHeight;
// gl.glMatrixMode(GL.GL_MODELVIEW);
// gl.glLoadIdentity();
drawRelief();
canvas.swapBuffers();
}
});
try {
GLContext.useContext(canvas);
} catch (LWJGLException e) {
e.printStackTrace();
}
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL11.glColor3f(1.0f, 0.0f, 0.0f);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
// gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
// gl.glClearDepth(1.0);
// gl.glLineWidth(2);
// / gl.glEnable(GL.GL_DEPTH_TEST);
GL11.glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
// create the grip for users to change the orientation, translation and
// zoom
grip = new SceneGrip();
canvas.addMouseListener(grip);
canvas.addMouseMoveListener(grip);
canvas.addListener(SWT.MouseWheel, grip);
canvas.addKeyListener(grip);
// apparently opengl has to be redrawn constantly (why ?)
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
if (!canvas.isDisposed()) {
canvas.setCurrent();
// Rectangle bounds = canvas.getBounds();
/*
* canvasWidth = bounds.width; canvasHeight = bounds.height;
*/
// context.makeCurrent();
// GL gl = context.getGL ();
// gl.glClear(GL.GL_COLOR_BUFFER_BIT |
// GL.GL_DEPTH_BUFFER_BIT);
// gl.glClearColor(.0f, .0f, .0f, 1.0f); // black
// background*/
drawRelief();
canvas.swapBuffers();
}
}
});
}
/**
* Display list (glCallList )created and compiled previously in
* drawReliefList.
*
*/
static void drawRelief() {
canvas.setCurrent();
try {
GLContext.useContext(canvas);
} catch (LWJGLException e) {
e.printStackTrace();
}
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
if (!freeze)
grip.adjust();
if (image != null) {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glDisable(GL11.GL_LIGHTING);
// Execute a display list here
GL11.glCallList(reliefList);
GL11.glEnable(GL11.GL_LIGHTING);
}
}
// private static void testDraw() {
// if (canvas != null && context != null) {
//
// System.out.println("testDraw()");
// // if (!freeze) grip.adjust();
// // canvas.setCurrent();
// // context.makeCurrent();
// GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
// GL11.glColor3f(1.0f, 1.0f, 1.0f);
// GL11.glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
// GL11.glBegin(GL11.GL_POLYGON);
// GL11.glVertex3f(0.25f, 0.25f, 0.0f);
// GL11.glVertex3f(0.75f, 0.25f, 0.0f);
// GL11.glVertex3f(0.75f, 0.75f, 0.0f);
// GL11.glVertex3f(0.25f, 0.75f, 0.0f);
// GL11.glEnd();
// GL11.glFlush();
// }
// }
/**
* Build the list to display here
*/
private static void drawReliefList() {
if (!reliefListFirst) {
GL11.glDeleteLists(reliefList, 1);
}
reliefListFirst = false;
reliefList = GL11.glGenLists(1);
GL11.glNewList(reliefList, GL11.GL_COMPILE);
GL11.glColor3f(1.0f, 1.0f, 1.0f); // white
GL11.glPointSize(pointSize);
for (int i = 0; i < imageWidth - 1; i++) {
GL11.glBegin(GL11.GL_LINE_STRIP);
int j = i + 1;
int color_index = (int) image[i];
if (color_index < 0)
color_index = 0;
if (color_index > COLOR_INDEX_MAX)
color_index = COLOR_INDEX_MAX;
GL11.glColor3f(red[color_index], green[color_index],
blue[color_index]); // temperature lut
GL11.glVertex3f(i, image[i], image[j]);
// System.out.println("i=" + i + ", j=" + j + " image[i]=" +
// image[i] + " image[j]=" + image[j]);
GL11.glEnd();
}
/*
* gl.glBegin(GL.GL_TRIANGLES);
*
* gl.glVertex3f(-1.0f, -0.5f, 0.0f); // lower left vertex
* gl.glVertex3f( 1.0f, -0.5f, 0.0f); // lower right vertex
* gl.glVertex3f( 0.0f, 0.5f, 0.0f); // upper vertex
*
* gl.glEnd();
*/
GL11.glEndList();
GL11.glFlush();
}
/**
*
* @param listdots
* @param _width
* @param _height
* @param _minimum
* @param _maximum
* @param _mean
* @param _fileName
*/
public void plot(float[] listdots, int _width, int _height, float _minimum,
float _maximum, float _mean, String _fileName) {
/*
* do not listen for new images - display on the selected image until a
* new image is set manually
*/
dots = listdots; /* save a copy for rescaling later */
image = new float[_width * _height];
imageWidth = _width;
imageHeight = _height;
minimum = _minimum;
// maximum = _maximum;
mean = _mean;
if (autoscale) {
scaleMinimum = _minimum;
scaleMaximum = _mean;
}
fileName = _fileName;
// this.size = (imageWidth + imageHeight) / 2;
// aspect = (float) imageWidth / (float) imageHeight;
setPartName("Plot " + fileName);
if (firstImage) {
grip.init();
firstImage = false;
}
scaleImage();
drawReliefList();
// drawRelief();
// System.out.println("affichage fini");
}
/**
*
*/
public void scaleImage() {
if (autoscale) {
scaleMinimum = minimum;
scaleMaximum = mean;
minimumSpinner.setSelection((int) (scaleMinimum));
maximumSpinner.setSelection((int) (scaleMaximum));
} else {
scaleMinimum = minimumSpinner.getSelection();
scaleMaximum = maximumSpinner.getSelection();
}
if (scaleMinimum == scaleMaximum)
scaleMaximum = scaleMinimum + 1;
zscale = 10.0f / (2.f * (scaleMaximum - scaleMinimum));
for (int i = 0; i < imageWidth; i++) {
float imageValue;
imageValue = dots[i];
image[i] = (imageValue - scaleMinimum) * zscale;
}
}
/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
// canvas.setFocus();
}
/*******************************************************************************
* Copyright (c) 2005 Bo Majewski All rights reserved. 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/org/documents/epl-v10.html
*
* Contributors: Bo Majewski - initial API and implementation
*******************************************************************************/
/**
* Implements a scene grip, capable of rotating and moving a GL scene with
* the help of the mouse and keyboard.
*
* @author Bo Majewski
*/
public class SceneGrip extends MouseAdapter implements MouseMoveListener,
Listener, KeyListener {
private float xrot;
private float yrot;
private float zoff;
private float xoff;
private float yoff;
private float xcpy;
private float ycpy;
private float xscale;
private float yscale;
private boolean move;
private int xdown;
private int ydown;
private int mouseDown;
public SceneGrip() {
this.init();
}
protected void init() {
canvas.setCurrent();
Rectangle bounds = canvas.getBounds();
canvasWidth = bounds.width;
canvasHeight = bounds.height;
this.xrot = this.yrot = 0.0f;
this.xoff = this.yoff = 0.0f;
if (imageWidth != 0) {
xscale = canvasWidth / imageWidth;
}
if (imageHeight != 0) {
yscale = canvasHeight / imageHeight;
}
zoff = 1.0f;
if (xscale < yscale)
zoff = xscale;
else
zoff = yscale;
// logger.debug("xscale = "+xscale+" yscale = "+yscale+" zoff = "+zoff);
}
public void mouseDown(MouseEvent e) {
if (++this.mouseDown == 1) {
if ((this.move = e.button == 3)) {
this.xcpy = xoff;
this.ycpy = yoff;
((Control) e.widget).setCursor(e.widget.getDisplay()
.getSystemCursor(SWT.CURSOR_HAND));
} else {
this.xcpy = xrot;
this.ycpy = yrot;
((Control) e.widget).setCursor(e.widget.getDisplay()
.getSystemCursor(SWT.CURSOR_SIZEALL));
}
this.xdown = e.x;
this.ydown = e.y;
}
}
public void mouseUp(MouseEvent e) {
if (--this.mouseDown == 0) {
((Control) e.widget).setCursor(e.widget.getDisplay()
.getSystemCursor(SWT.CURSOR_ARROW));
}
}
public void mouseMove(MouseEvent e) {
Point p = ((Control) e.widget).getSize();
if (this.mouseDown > 0) {
int dx = e.x - this.xdown;
int dy = e.y - this.ydown;
if (this.move) {
yoff = this.ycpy + ((canvasHeight / 2.f) * dy)
/ (2.0f * p.y);
xoff = this.xcpy + ((canvasWidth / 2.f) * dx)
/ (2.0f * p.x);
} else {
xrot = this.xcpy + dy / 2.0f;
yrot = this.ycpy + dx / 2.0f;
}
}
}
public void handleEvent(Event event) {
// this.zoff += event.count/6.0f;
this.zoff *= 1.1f;
}
public void keyPressed(KeyEvent e) {
switch (e.keyCode) {
case SWT.ARROW_UP:
if ((e.stateMask & SWT.CTRL) != 0) {
this.xrot -= 5f;
} else {
this.yoff -= (float) canvasHeight / 10.f;
}
break;
case SWT.ARROW_DOWN:
if ((e.stateMask & SWT.CTRL) != 0) {
this.xrot += 5f;
} else {
this.yoff += (float) canvasHeight / 10.f;
}
break;
case SWT.ARROW_LEFT:
if ((e.stateMask & SWT.CTRL) != 0) {
this.yrot -= 5f;
} else {
this.xoff -= (float) canvasWidth / 10.f;
}
break;
case SWT.ARROW_RIGHT:
if ((e.stateMask & SWT.CTRL) != 0) {
this.yrot += 5f;
} else {
this.xoff += (float) canvasWidth / 10;
}
break;
case SWT.PAGE_UP:
this.zoff *= 1.05f;
break;
case SWT.PAGE_DOWN:
this.zoff *= .95f;
break;
case SWT.HOME:
this.init();
break;
}
}
public void keyReleased(KeyEvent e) {
}
public void adjust() {
try {
GLContext.useContext(canvas);
} catch (LWJGLException e) {
e.printStackTrace();
}
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
/* set the orthogonal projection to the size of the window */
GL11.glOrtho(0, canvasWidth, canvasHeight, 0, -1.0e5f, 1.0e5f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GL11.glTranslatef(canvasWidth / 2 + this.xoff, canvasHeight / 2
+ this.yoff, 0);
GL11.glScalef(zoff, zoff, zoff);
/*
* zoff has no effect on the orthogonal projection therefore zoom by
* passing zoff to scale
*/
GL11.glRotatef(this.xrot, 1f, 0.0f, 0.0f);
GL11.glRotatef(this.yrot, 0.0f, 1f, 0.0f);
GL11.glTranslatef(-imageWidth / 2, -imageHeight / 2, 0);
}
public void setOffsets(float x, float y, float z) {
this.xoff = x;
this.yoff = y;
this.zoff = z;
}
public void setRotation(float x, float y) {
this.xrot = x;
this.yrot = y;
}
}
public void openFile(String filename2) {
try {
ChiFile chifile = new ChiFile();
chifile.loadfile(filename2);
// float[] f = chifile.getlist();
// plot(f, 2048,
// 2048,chifile.getMin(),chifile.getMax(),chifile.getMean(),filename2);
} catch (JepException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}