Reputation: 4192
I would like to implement a "hand tool" with which the user can scroll/move something with the mouse. This feature is known from various programs such as Gimp. If the user presses the left mouse button, the tool should be activated. If the mouse is now moved, the underlying object should also be moved - proportional to the mouse movement. Hence, if the user presses the mouse and moves it by e.g. 10px, the underlying object should also be moved by 10px. I thought that it should work with my code below, but it does not work properly. The movement of the underlying ScrolledComposite
is too fast.
The code below is ready-to-run, so you can directly play with it.
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class HandTool {
public static boolean moveGraphActive = false;
public static Point moveStartPos = new Point(0, 0);
public static ScrolledComposite sc;
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
sc = new ScrolledComposite(shell, SWT.V_SCROLL);
Text text = new Text(sc, SWT.MULTI | SWT.READ_ONLY);
String multiLineText = "";
for (int i = 0; i < 30; i++) {
multiLineText += "Hello World SWT " + i + System.lineSeparator();
}
text.setText(multiLineText);
text.setEnabled(false);
text.pack();
sc.setContent(text);
sc.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(final MouseEvent e) {
moveGraphActive = e.button == 1;
if (moveGraphActive) {
moveStartPos.x = e.x;
moveStartPos.y = e.y;
}
}
@Override
public void mouseUp(final MouseEvent e) {
moveGraphActive = false;
}
});
sc.addMouseMoveListener(new MouseMoveListener() {
@Override
public void mouseMove(final MouseEvent e) {
if (moveGraphActive) {
// FIXME the movement of the canvas should be proportional
// to the mouse
// movement
final int newX = sc.getOrigin().x + moveStartPos.x - e.x;
final int newY = sc.getOrigin().y + moveStartPos.y - e.y;
sc.setOrigin(newX, newY);
}
}
});
shell.setSize(500, 150);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Upvotes: 1
Views: 317
Reputation: 36894
You almost got it right, there is just a small mistake.
final int newX = sc.getOrigin().x + moveStartPos.x - e.x;
final int newY = sc.getOrigin().y + moveStartPos.y - e.y;
should be
final int newX = startOrigin.x + moveStartPos.x - e.x;
final int newY = startOrigin.y + moveStartPos.y - e.y;
where startOrigin
is the origin of the ScrolledComposite
when you started dragging. I've updated your code:
private static boolean moveGraphActive = false;
private static Point moveStartPos = new Point(0, 0);
private static ScrolledComposite sc;
private static Point startOrigin;
public static void main(String[] args)
{
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
sc = new ScrolledComposite(shell, SWT.V_SCROLL);
Text text = new Text(sc, SWT.MULTI | SWT.READ_ONLY);
String multiLineText = "";
for (int i = 0; i < 30; i++)
{
multiLineText += "Hello World SWT " + i + System.lineSeparator();
}
text.setText(multiLineText);
text.setEnabled(false);
text.pack();
sc.setContent(text);
sc.addMouseListener(new MouseAdapter()
{
@Override
public void mouseDown(final MouseEvent e)
{
moveGraphActive = e.button == 1;
if (moveGraphActive)
{
moveStartPos.x = e.x;
moveStartPos.y = e.y;
startOrigin = sc.getOrigin();
}
}
@Override
public void mouseUp(final MouseEvent e)
{
moveGraphActive = false;
startOrigin = null;
}
});
sc.addMouseMoveListener(new MouseMoveListener()
{
@Override
public void mouseMove(final MouseEvent e)
{
if (moveGraphActive)
{
// FIXED
final int newX = startOrigin.x + moveStartPos.x - e.x;
final int newY = startOrigin.y + moveStartPos.y - e.y;
sc.setOrigin(newX, newY);
}
}
});
shell.setSize(500, 150);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
Upvotes: 2