/*
* Copyright 2010-2015 Institut Pasteur.
*
* This file is part of Icy.
*
* Icy is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Icy is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Icy. If not, see <http://www.gnu.org/licenses/>.
*/
package icy.vtk;
import icy.preferences.CanvasPreferences;
import icy.util.EventUtil;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.util.Timer;
import java.util.TimerTask;
import vtk.vtkActor;
import vtk.vtkPanel;
import vtk.vtkPropPicker;
/**
* @author stephane
*/
public class IcyVtkPanelOld extends vtkPanel
{
/**
*
*/
private static final long serialVersionUID = -8455671369400627703L;
protected Timer timer;
final protected vtkPropPicker picker;
public IcyVtkPanelOld()
{
super();
// used for restore quality rendering after mouse wheel
timer = new Timer("Timer - vtkPanel");
// picker
picker = new vtkPropPicker();
// set ambient color to white
lgt.SetAmbientColor(1d, 1d, 1d);
}
@Override
public void Delete()
{
super.Delete();
// important to release timer here
timer.cancel();
}
@Override
public void removeNotify()
{
super.removeNotify();
// important to release timer here
timer.cancel();
}
@Override
public void setBounds(int x, int y, int width, int height)
{
super.setBounds(x, y, width, height);
if (windowset == 1)
{
Lock();
rw.SetSize(width, height);
UnLock();
}
}
@SuppressWarnings("deprecation")
@Override
public void setSize(int w, int h)
{
// have to use this to by-pass the wrong vtkPanel implementation
resize(w, h);
}
@Override
public void mouseEntered(MouseEvent e)
{
// nothing to do here
}
@Override
public void mouseExited(MouseEvent e)
{
// nothing to do here
}
@Override
public void mouseClicked(MouseEvent e)
{
if (e.isConsumed())
return;
// nothing to do here
}
@Override
public void mouseMoved(MouseEvent e)
{
// just save mouse position
lastX = e.getX();
lastY = e.getY();
}
@Override
public void mouseDragged(MouseEvent e)
{
// camera not yet defined --> exit
if (cam == null)
return;
if (e.isConsumed())
return;
if (ren.VisibleActorCount() == 0)
return;
// cancel pending task
timer.cancel();
// get current mouse position
final int x = e.getX();
final int y = e.getY();
int deltaX = (lastX - x);
int deltaY = (lastY - y);
// faster movement with control modifier
if (EventUtil.isControlDown(e))
{
deltaX *= 3;
deltaY *= 3;
}
if (EventUtil.isRightMouseButton(e) || (EventUtil.isLeftMouseButton(e) && EventUtil.isShiftDown(e)))
// translation mode
translateView(-deltaX, deltaY);
else if (EventUtil.isLeftMouseButton(e))
// rotation mode
rotateView(deltaX, -deltaY);
else
// zoom mode
zoomView(Math.pow(1.02, -deltaY));
// save mouse position
lastX = x;
lastY = y;
// request repaint
repaint();
}
@Override
public void mousePressed(MouseEvent e)
{
if (e.isConsumed())
return;
if (ren.VisibleActorCount() == 0)
return;
// want fast update
setCoarseRendering(0);
}
@Override
public void mouseReleased(MouseEvent e)
{
// restore quality rendering
setFineRendering(1000);
}
@Override
public void mouseWheelMoved(MouseWheelEvent e)
{
// camera not yet defined --> exit
if (cam == null)
return;
// want fast update
setCoarseRendering(0);
// get delta
double delta = e.getWheelRotation() * CanvasPreferences.getMouseWheelSensitivity();
if (CanvasPreferences.getInvertMouseWheelAxis())
delta = -delta;
// faster movement with control modifier
if (EventUtil.isControlDown(e))
delta *= 3d;
zoomView(Math.pow(1.02, delta));
// request repaint
repaint();
// restore quality rendering
setFineRendering(1000);
}
@Override
public void keyPressed(KeyEvent e)
{
if (!e.isConsumed())
super.keyPressed(e);
}
@Override
public void keyReleased(KeyEvent e)
{
if (!e.isConsumed())
super.keyReleased(e);
}
@Override
public void lock()
{
if (windowset == 0)
return;
super.lock();
}
@Override
public void unlock()
{
if (windowset == 0)
return;
super.unlock();
}
/**
* return true if currently rendering
*/
public boolean isRendering()
{
return rendering;
}
/**
* Return picker object.
*/
public vtkPropPicker getPicker()
{
return picker;
}
/**
* Pick object at specified position and return it.
*/
public vtkActor pick(int x, int y)
{
Lock();
picker.PickProp(x, rw.GetSize()[1] - y, ren);
UnLock();
return picker.GetActor();
}
/**
* Translate current camera view
*/
public void translateView(double dx, double dy)
{
// translation mode
double FPoint[];
double PPoint[];
double APoint[] = new double[3];
double RPoint[];
double focalDepth;
// get the current focal point and position
FPoint = cam.GetFocalPoint();
PPoint = cam.GetPosition();
// calculate the focal depth since we'll be using it a lot
ren.SetWorldPoint(FPoint[0], FPoint[1], FPoint[2], 1.0);
ren.WorldToDisplay();
focalDepth = ren.GetDisplayPoint()[2];
APoint[0] = rw.GetSize()[0] / 2.0 + dx;
APoint[1] = rw.GetSize()[1] / 2.0 + dy;
APoint[2] = focalDepth;
ren.SetDisplayPoint(APoint);
ren.DisplayToWorld();
RPoint = ren.GetWorldPoint();
if (RPoint[3] != 0.0)
{
RPoint[0] = RPoint[0] / RPoint[3];
RPoint[1] = RPoint[1] / RPoint[3];
RPoint[2] = RPoint[2] / RPoint[3];
}
/*
* Compute a translation vector, moving everything 1/2 the distance
* to the cursor. (Arbitrary scale factor)
*/
cam.SetFocalPoint((FPoint[0] - RPoint[0]) / 2.0 + FPoint[0], (FPoint[1] - RPoint[1]) / 2.0 + FPoint[1],
(FPoint[2] - RPoint[2]) / 2.0 + FPoint[2]);
cam.SetPosition((FPoint[0] - RPoint[0]) / 2.0 + PPoint[0], (FPoint[1] - RPoint[1]) / 2.0 + PPoint[1],
(FPoint[2] - RPoint[2]) / 2.0 + PPoint[2]);
resetCameraClippingRange();
}
/**
* Rotate current camera view
*/
public void rotateView(int dx, int dy)
{
// rotation mode
cam.Azimuth(dx);
cam.Elevation(dy);
cam.OrthogonalizeViewUp();
resetCameraClippingRange();
if (LightFollowCamera == 1)
{
lgt.SetPosition(cam.GetPosition());
lgt.SetFocalPoint(cam.GetFocalPoint());
}
}
/**
* Zoom current view by specified factor (negative value means unzoom)
*/
public void zoomView(double factor)
{
if (cam.GetParallelProjection() == 1)
cam.SetParallelScale(cam.GetParallelScale() / factor);
else
{
cam.Dolly(factor);
resetCameraClippingRange();
}
}
/**
* Set coarse and fast rendering mode immediately
*
* @see #setCoarseRendering(long)
*/
public void setCoarseRendering()
{
// set fast rendering
rw.SetDesiredUpdateRate(10.0);
}
/**
* Set fine (and possibly slow) rendering immediately
*
* @see #setFineRendering(long)
*/
public void setFineRendering()
{
// set quality rendering
rw.SetDesiredUpdateRate(0.01);
}
/**
* Set coarse and fast rendering for the specified amount of time (in ms, always when set to 0)
*/
public void setCoarseRendering(long time)
{
// cancel pending task
timer.cancel();
// want fast update
rw.SetDesiredUpdateRate(10.0);
if (time > 0)
setFineRendering(time);
}
/**
* Set fine (and possibly slow) rendering after specified time delay (in ms)
*/
public void setFineRendering(long delay)
{
// cancel pending task
timer.cancel();
if (delay > 0)
{
// schedule quality restoration
timer = new Timer();
timer.schedule(new TimerTask()
{
@Override
public void run()
{
// no parent --> exit
if (getParent() == null)
return;
// set back quality rendering
GetRenderWindow().SetDesiredUpdateRate(0.01);
// request repaint
repaint();
}
}, delay);
}
else
// set back quality rendering
rw.SetDesiredUpdateRate(0.01);
}
}