Package com.peterhi.ui.examples

Source Code of com.peterhi.ui.examples.LineUp

package com.peterhi.ui.examples;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.jdesktop.core.animation.timing.Animator;
import org.jdesktop.core.animation.timing.TimingSource;
import org.jdesktop.core.animation.timing.TimingTarget;
import org.jdesktop.core.animation.timing.TimingTargetAdapter;
import org.jdesktop.core.animation.timing.interpolators.AccelerationInterpolator;
import org.jdesktop.swt.animation.timing.sources.SWTTimingSource;

public class LineUp {

  public static class Button {
    private final String id;
    private final Rectangle bounds;
    private Animation animation;
   
    public Button(String id) {
      if (id == null) {
        throw new NullPointerException();
      }
     
      if (id.isEmpty()) {
        throw new IllegalArgumentException();
      }
     
      this.id = id;
      this.bounds = new Rectangle(0, 0, 0, 0);
    }
   
    public String getId() {
      return id;
    }
   
    public Rectangle getBounds() {
      return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
    }
   
    public void setBounds(Rectangle value) {
      if (value == null) {
        throw new NullPointerException();
      }
     
      bounds.x = value.x;
      bounds.y = value.y;
      bounds.width = value.width;
      bounds.height = value.height;
    }
   
    public boolean hasAnimation() {
      return animation != null;
    }
   
    public Animation getAnimation() {
      return animation;
    }
   
    public void setAnimation(Animation value) {
      animation = value;
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((id == null) ? 0 : id.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      Button other = (Button) obj;
      if (id == null) {
        if (other.id != null)
          return false;
      } else if (!id.equals(other.id))
        return false;
      return true;
    }
   
    @Override
    public String toString() {
      return id;
    }
   
  }
 
  public static class Animation {
    private final Shell shell;
    private final Button target;
    private final int from;
    private final int to;
    private Animator animator;
   
    public Animation(Shell shell, Button target, int from, int to) {
      if (shell == null) {
        throw new NullPointerException();
      }
     
      if (target == null) {
        throw new NullPointerException();
      }
     
      this.shell = shell;
      this.target = target;
      this.from = from;
      this.to = to;
    }
   
    public int getFrom() {
      return from;
    }
   
    public int getTo() {
      return to;
    }
   
    public Shell getShell() {
      return shell;
    }
   
    public Button getTarget() {
      return target;
    }

    public void start() {
      Rectangle bounds = target.getBounds();
     
      TimingTarget tt = new TimingTargetAdapter() {

        @Override
        public void timingEvent(Animator source, double fraction) {
          double doubleDistance = (to - from) * fraction;
          int intDistance = (int )Math.round(doubleDistance);
          Rectangle oldBounds = target.getBounds();
          Rectangle newBounds = new Rectangle(from + intDistance, oldBounds.y, oldBounds.width, oldBounds.height);
          target.setBounds(newBounds);
          shell.redraw(oldBounds.x, oldBounds.y, oldBounds.width, oldBounds.height, true);
          shell.redraw(newBounds.x, newBounds.y, newBounds.width, newBounds.height, true);
        }
       
        @Override
        public void end(Animator source) {
          Rectangle oldBounds = target.getBounds();
          Rectangle newBounds = new Rectangle(to, oldBounds.y, oldBounds.width, oldBounds.height);
          target.setBounds(newBounds);
          shell.redraw(oldBounds.x, oldBounds.y, oldBounds.width, oldBounds.height, true);
          shell.redraw(newBounds.x, newBounds.y, newBounds.width, newBounds.height, true);
          target.setAnimation(null);
        }
       
      };
     
      animator = new Animator.Builder().addTarget(tt).setDuration(160, TimeUnit.MILLISECONDS).setInterpolator(new AccelerationInterpolator(0, 0.9)).build();
      animator.start();
    }
   
    public void stop() {
      if (animator == null) {
        return;
      }
     
      animator.stop();
    }
   
    public void cancel() {
      if (animator == null) {
        return;
      }
     
      animator.cancel();
      target.setAnimation(null);
    }
  }
 
  public static void main(String[] args) {
    final Display display = Display.getDefault();
    final Shell shell = new Shell(display);
    final Button button0 = new Button("Button 0");
    final Button button1 = new Button("Button 1");
    final Button button2 = new Button("Button 2");
    final Button button3 = new Button("Button 3");
    final Button button4 = new Button("Button 4");
    final Button[] buttons = new Button[] { button0, button1, button2, button3, button4};
   
    TimingSource timingSource = new SWTTimingSource(16, TimeUnit.MILLISECONDS, display);
    timingSource.init();
    Animator.setDefaultTimingSource(timingSource);
   
    button0.setBounds(new Rectangle(10, 10, 100, 20));
    button1.setBounds(new Rectangle(120, 10, 60, 20));
    button2.setBounds(new Rectangle(190, 10, 140, 20));
    button3.setBounds(new Rectangle(340, 10, 50, 20));
    button4.setBounds(new Rectangle(400, 10, 80, 20));
   
    shell.addListener(SWT.Paint, new Listener() {
      @Override
      public void handleEvent(Event event) {
        GC gc = event.gc;
        Color foreground = gc.getForeground();
        Color background = gc.getBackground();
        gc.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_FOREGROUND));
        gc.setBackground(display.getSystemColor(SWT.COLOR_RED));
       
        for (Button button : buttons) {
          Rectangle bounds = button.getBounds();
          gc.fillRectangle(bounds);
          gc.drawRectangle(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1);
        }
       
        gc.setForeground(foreground);
        gc.setBackground(background);
      }
    });
   
    Listener listener = new Listener() {
     
      private Button selected;
      private Rectangle oldBounds;
      private Point oldMouseLocation;
     
      @Override
      public void handleEvent(Event event) {
        if (event.type == SWT.MouseDown) {
          onMouseDown(event);
        } else if (event.type == SWT.MouseMove) {
          onMouseMove(event);
        } else if (event.type == SWT.MouseUp) {
          onMouseUp(event);
        }
      }
     
      private void onMouseDown(Event event) {
        if (event.button != 1) {
          return;
        }
       
        selected = get(event.x, event.y);
       
        if (selected == null) {
          return;
        }
       
        oldBounds = selected.getBounds();
        oldMouseLocation = new Point(event.x, event.y);
      }
     
      private void onMouseMove(Event event) {
        if (selected == null) {
          return;
        }
       
        int xDiff = event.x - oldMouseLocation.x;
        int yDiff = event.y - oldMouseLocation.y;

        Button[] affects = getAffected(selected, xDiff);
       
        Rectangle oldBounds = selected.getBounds();
        Rectangle newBounds = new Rectangle(oldBounds.x + xDiff, oldBounds.y, oldBounds.width, oldBounds.height);
        selected.setBounds(newBounds);
        shell.redraw(oldBounds.x, oldBounds.y, oldBounds.width, oldBounds.height, true);
        shell.redraw(newBounds.x, newBounds.y, newBounds.width, newBounds.height, true);
       
        for (Button affect : affects) {
          Rectangle bounds = affect.getBounds();
         
          if (xDiff > 0) {
            // Move subsequent items before
            if (affect.hasAnimation()) {
              Animation animation = affect.getAnimation();
             
//              if (animation.getFrom() < animation.getTo()) {
                animation.cancel();
                affect.setAnimation(null);
//              }
            }
           
            if (!affect.hasAnimation()) {
              int destination = shouldAlignAfter(affect);
              Animation animation = new Animation(shell, affect, bounds.x, destination);
              affect.setAnimation(animation);
              animation.start();
            }
          }
         
          if (xDiff < 0) {
            // Move previous items after
            if (affect.hasAnimation()) {
              Animation animation = affect.getAnimation();
             
//              if (animation.getFrom() > animation.getTo()) {
                animation.cancel();
                affect.setAnimation(null);
//              }
            }
           
            if (!affect.hasAnimation()) {
              int destination = shouldAlignBefore(affect);
              Animation animation = new Animation(shell, affect, bounds.x, destination);
              affect.setAnimation(animation);
              animation.start();
            }
          }
        }
       
        oldMouseLocation.x = event.x;
        oldMouseLocation.y = event.y;
      }
     
      private void onMouseUp(Event event) {
        if (event.button != 1) {
          return;
        }
       
        if (selected == null) {
          return;
        }

        Rectangle currentBounds = selected.getBounds();
        int from = currentBounds.x;
        int to = oldBounds.x;
        Animation animation = new Animation(shell, selected, from, to);
        selected.setAnimation(animation);
        animation.start();
       
        if (selected.hasAnimation()) {
          selected.getAnimation().start();
        }
       
        selected = null;
        oldBounds = null;
        oldMouseLocation = null;
      }
     
      private int shouldAlignAfter(Button button) {
        int left = 10;
       
        for (int i = 0; i < buttons.length; i++) {
          if (buttons[i].equals(selected)) {
            continue;
          }
         
          if (buttons[i].equals(button)) {
            return left;
          }
         
          Rectangle bounds = buttons[i].getBounds();
          left += bounds.width;
          left += 10;
        }
       
        return 0;
       
        /*for (int i = 0; i < buttons.length; i++) {
          if (!buttons[i].equals(button)) {
            continue;
          }
         
          int previousIndex = i - 1;
         
          if (previousIndex < 0) {
            return 10;
          }
         
          if (buttons[previousIndex].equals(selected)) {
            previousIndex --;
          }
         
          if (previousIndex < 0) {
            return 10;
          }
         
          Rectangle otherBounds = buttons[previousIndex].getBounds();
          return otherBounds.x + otherBounds.width + 10;
        }
       
        return 0;*/
      }
     
      private int shouldAlignBefore(Button button) {
        int right = 480;
       
        for (int i = buttons.length - 1; i >= 0; i--) {
          if (buttons[i].equals(selected)) {
            continue;
          }
         
          if (buttons[i].equals(button)) {
            Rectangle bounds = button.getBounds();
            return right - bounds.width;
          }
         
          Rectangle bounds = buttons[i].getBounds();
          right -= bounds.width;
          right -= 10;
        }
       
        return 0;
       
        /*for (int i = 0; i < buttons.length; i++) {
          if (!buttons[i].equals(button)) {
            continue;
          }
         
          Rectangle bounds = button.getBounds();
          int nextIndex = i + 1;
         
          if (nextIndex == buttons.length) {
            return 490 - 10 - bounds.width;
          }
         
          if (buttons[nextIndex].equals(selected)) {
            nextIndex ++;
          }
         
          if (nextIndex == buttons.length) {
            return 490 - 10 - bounds.width;
          }
         
          Rectangle otherBounds = buttons[nextIndex].getBounds();
          return otherBounds.x - 10 - bounds.width;
        }
       
        return 0;*/
      }
     
      private Button get(int x, int y) {
        for (Button button : buttons) {
          Rectangle bounds = button.getBounds();
         
          if (bounds.contains(x, y)) {
            return button;
          }
        }
       
        return null;
      }
     
      private Button[] getAffected(Button button, int delta) {
        Set<Button> affected = new HashSet<Button>();
        Rectangle bounds = button.getBounds();
       
        for (Button otherButton : buttons) {
          if (otherButton.equals(button)) {
            continue;
          }
         
          Rectangle otherBounds = otherButton.getBounds();
         
          if (delta > 0) {
            if (bounds.x < otherBounds.x) {
              if (bounds.x + delta + bounds.width > otherBounds.x + otherBounds.width / 2) {
                affected.add(otherButton);
              }
            }
          }
         
          if (delta < 0) {
            if (bounds.x > otherBounds.x) {
              if (bounds.x + delta < otherBounds.x + otherBounds.width / 2) {
                affected.add(otherButton);
              }
            }
          }
        }
       
        return affected.toArray(new Button[affected.size()]);
      }
     
      private int indexOf(Button button) {
        for (int i = 0; i < buttons.length; i++) {
          if (buttons[i].equals(button)) {
            return i;
          }
        }
       
        return -1;
      }
    };
   
    shell.addListener(SWT.MouseDown, listener);
    shell.addListener(SWT.MouseMove, listener);
    shell.addListener(SWT.MouseUp, listener);
   
    shell.open();
   
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) {
        display.sleep();
      }
    }
  }

}
TOP

Related Classes of com.peterhi.ui.examples.LineUp

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.