Package com.peterhi.ui.stripbar3

Source Code of com.peterhi.ui.stripbar3.StripBar

package com.peterhi.ui.stripbar3;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
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.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
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.Interpolator;
import org.jdesktop.core.animation.timing.TimingTarget;
import org.jdesktop.core.animation.timing.TimingTargetAdapter;
import org.jdesktop.core.animation.timing.interpolators.AccelerationInterpolator;

import com.peterhi.runtime.RT;
import com.peterhi.ui.UI;
import com.peterhi.ui.UIImageResource;
import com.peterhi.ui.obsolete.Bounds;

public final class StripBar extends Canvas implements Listener {

  public static final class StripItem {
    private final String id;
    private String text;
    private Image image;
   
    public StripItem(String id) {
      this.id = id;
    }
   
    public String getId() {
      return id;
    }
   
    public String getText() {
      return text;
    }

    public void setText(String value) {
      this.text = value;
    }

    public Image getImage() {
      return image;
    }

    public void setImage(Image value) {
      this.image = 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;
      StripItem other = (StripItem) 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 MessageFormat.format("{0} ({1})", id, text);
    }
  }
 
  static final class StripItemController {
    private final StripItem item;
    private RGB foreground;
    private RGB background;
    private Animator backgroundAnimator;
    private Animator offsetAnimator;
    private int offset;
    private Rectangle oldBounds;
   
    public StripItemController(StripItem item) {
      this.item = item;
    }
   
    public StripItem getItem() {
      return item;
    }
   
    public boolean hasForeground() {
      return foreground != null;
    }
   
    public RGB getForeground() {
      return foreground;
    }
   
    public void setForeground(RGB value) {
      foreground = value;
    }
   
    public boolean hasBackground() {
      return background != null;
    }
   
    public RGB getBackground() {
      return background;
    }
   
    public void setBackground(RGB value) {
      background = value;
    }
   
    public boolean hasBackgroundAnimator() {
      return backgroundAnimator != null;
    }
   
    public Animator getBackgroundAnimator() {
      return backgroundAnimator;
    }
   
    public void setBackgroundAnimator(Animator value) {
      backgroundAnimator = value;
    }
   
    public boolean hasOffsetAnimator() {
      return offsetAnimator != null;
    }
   
    public Animator getOffsetAnimator() {
      return offsetAnimator;
    }
   
    public void setOffsetAnimator(Animator value) {
      offsetAnimator = value;
    }
   
    public int getOffset() {
      return offset;
    }
   
    public void setOffset(int value) {
      offset = value;
    }
   
    public Rectangle getOldBounds() {
      return oldBounds;
    }
   
    public void setOldBounds(Rectangle value) {
      oldBounds = value;
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((item == null) ? 0 : item.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;
      StripItemController other = (StripItemController) obj;
      if (item == null) {
        if (other.item != null)
          return false;
      } else if (!item.equals(other.item))
        return false;
      return true;
    }
  }
 
  public static final int SPACE = 5;
  public static final int NONE = 0;
  public static final int HOVERED = 1;
  public static final int PRESSED = 2;
  public static final int SELECTED = 3;
  public static final RGB[] FOREGROUNDS;
  public static final RGB[] BACKGROUNDS;
 
  static {
    Display display = Display.getDefault();
    FOREGROUNDS = new RGB[4];
    BACKGROUNDS = new RGB[4];
   
    Color color = display.getSystemColor(SWT.COLOR_WIDGET_FOREGROUND);
    RGB rgb = color.getRGB();
    FOREGROUNDS[0] = rgb;
    FOREGROUNDS[1] = rgb;
    FOREGROUNDS[2] = rgb;
   
    color = display.getSystemColor(SWT.COLOR_LIST_BACKGROUND);
    rgb = color.getRGB();
    FOREGROUNDS[3] = rgb;
   
    color = display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
    rgb = color.getRGB();
    BACKGROUNDS[0] = rgb;

    rgb = new RGB(72, 118, 255);
    BACKGROUNDS[1] = rgb;
   
    rgb = new RGB(65, 105, 225);
    BACKGROUNDS[2] = rgb;
   
    rgb = new RGB(67, 110, 238);
    BACKGROUNDS[3] = rgb;
  }
 
  private final List<StripItemController> controllers = new ArrayList<StripItemController>();
  private StripItemController hovered;
  private StripItemController pressed;
  private StripItemController dragged;
  private final Set<StripItemController> selected = new HashSet<StripItemController>();
  private Point mouseDownLocation;
  private Point mouseDownOffset;
  private Point mouseMoveLocation;
  private List<StripItemController> temp;
 
  public StripBar(Composite parent, int style) {
    super(parent, style);
    addListener(SWT.Paint, this);
    addListener(SWT.MouseEnter, this);
    addListener(SWT.MouseExit, this);
    addListener(SWT.MouseDown, this);
    addListener(SWT.MouseMove, this);
    addListener(SWT.MouseUp, this);
  }

  @Override
  public void handleEvent(Event event) {
    if (equals(event.widget)) {
      if (event.type == SWT.Paint) {
        onPaint(event);
      } else if (event.type == SWT.MouseEnter) {
        onMouseEnter(event);
      } else if (event.type == SWT.MouseExit) {
        onMouseExit(event);
      } else if (event.type == SWT.MouseDown) {
        onMouseDown(event);
      } else if (event.type == SWT.MouseMove) {
        onMouseMove(event);
      } else if (event.type == SWT.MouseUp) {
        onMouseUp(event);
      }
    }
  }
 
  @Override
  public Point computeSize(int wHint, int hHint, boolean changed) {
    Point size = new Point(0, 0);
   
    for (StripItemController controller : controllers) {
      Rectangle bounds = getItemBounds(controller.getItem());
      size.x += bounds.width;
      size.y = Math.max(size.y, bounds.height);
    }
   
    size.x += SPACE * (getItemCount() - 1);
    size.y += SPACE * 2;
   
    Rectangle boundsWithTrim = computeTrim(0, 0, size.x, size.y);
    size.x = boundsWithTrim.width;
    size.y = boundsWithTrim.height;
   
    return size;
  }
 
  public boolean isMultiSelection() {
    int style = getStyle();
    boolean multi = (style & SWT.MULTI) == SWT.MULTI;
    return multi;
  }

  public int getItemCount() {
    return controllers.size();
  }
 
  public boolean addItem(StripItem item) {
    return insertItem(item, getItemCount());
  }

  public boolean insertItem(StripItem item, int index) {
    if (item == null) {
      throw new NullPointerException();
    }

    if (containsItem(item)) {
      return false;
    }
   
    controllers.add(index, new StripItemController(item));
    return true;
  }
 
  public boolean removeItem(StripItem item) {
    return removeItem(indexOfItem(item)) != null;
  }
 
  public StripItem removeItem(int index) {
    StripItemController controller = controllers.remove(index);
   
    if (controller == null) {
      return null;
    }
   
    if (controller.equals(hovered)) {
      hovered = null;
    }
   
    if (controller.equals(pressed)) {
      pressed = null;
    }
   
    if (selected.contains(controller)) {
      selected.remove(controller);
    }

    return controller.getItem();
  }
 
  public StripItem getItem(int index) {
    StripItemController controller = controllers.get(index);
   
    if (controller == null) {
      return null;
    }
   
    return controller.getItem();
  }
 
  public StripItem getItem(int x, int y) {
    StripItemController controller = getController(x, y);

    if (controller == null) {
      return null;
    }

    return controller.getItem();
  }
 
  public int indexOfItem(StripItem item) {
    if (item == null) {
      throw new NullPointerException();
    }

    for (int i = 0; i < controllers.size(); i++) {
      StripItemController controller = controllers.get(i);
     
      if (controller.getItem().equals(item)) {
        return i;
      }
    }

    return -1;
  }
 
  public boolean containsItem(StripItem item) {
    return indexOfItem(item) >= 0;
  }
 
  public StripItem[] getItems() {
    List<StripItem> items = new ArrayList<StripItem>();

    for (StripItemController controller : controllers) {
      items.add(controller.getItem());
    }

    return items.toArray(new StripItem[items.size()]);
  }
 
  public boolean hasItemText(StripItem item) {
    checkItem(item);
    String text = item.getText();
    return text != null && !text.isEmpty();
  }
 
  public boolean hasItemImage(StripItem item) {
    checkItem(item);
    Image image = item.getImage();
    return image != null;
  }
 
  public Point getItemTextSize(StripItem item) {
    checkItem(item);
    Point size = new Point(0, 0);
   
    if (hasItemText(item)) {
      String text = item.getText();
      GC gc = new GC(this);
      size = gc.stringExtent(text);
      gc.dispose();
    }
   
    return size;
  }
 
  public Point getItemImageSize(StripItem item) {
    checkItem(item);
    Point size = new Point(0, 0);
   
    if (hasItemImage(item)) {
      Image image = item.getImage();
      Rectangle bounds = image.getBounds();
      size.x = bounds.width;
      size.y = bounds.height;
    }
   
    return size;
  }
 
  public Image getItemCloseButtonImage() {
    return UIImageResource.T.closeNormal10();
  }
 
  public Point getItemCloseButtonSize() {
    Point size = new Point(0, 0);
    Image image = getItemCloseButtonImage();
    Rectangle bounds = image.getBounds();
    size.x = bounds.width;
    size.y = bounds.height;
    return size;
  }
 
  public Rectangle getItemBounds(StripItem item) {
    checkItem(item);
    return getItemBounds(controllers, item);
  }
 
  private Rectangle getItemBounds(List<StripItemController> controllers, StripItem item) {
    Rectangle bounds = new Rectangle(SPACE, SPACE, 0, 0);
   
    for (StripItemController controller : controllers) {
      if (hasItemImage(controller.getItem())) {
        Point imageSize = getItemImageSize(controller.getItem());
        bounds.height = Math.max(bounds.height, imageSize.y);
      }
     
      if (hasItemText(controller.getItem())) {
        Point textSize = getItemTextSize(controller.getItem());
        bounds.height = Math.max(bounds.height, textSize.y);
      }
     
      Point closeButtonSize = getItemCloseButtonSize();
      bounds.height = Math.max(bounds.height, closeButtonSize.y);
    }
   
    bounds.height += SPACE * 2;
   
    for (StripItemController controller : controllers) {
      int extent = SPACE;
     
      if (hasItemImage(controller.getItem())) {
        Point imageSize = getItemImageSize(controller.getItem());
        extent += imageSize.x;
        extent += SPACE;
      }
     
      if (hasItemText(controller.getItem())) {
        Point textSize = getItemTextSize(controller.getItem());
        extent += textSize.x;
        extent += SPACE;
      }

      Point closeButtonSize = getItemCloseButtonSize();
      extent += closeButtonSize.x;
      extent += SPACE;
     
      if (controller.getItem().equals(item)) {
        bounds.width = extent;
        break;
      } else {
        bounds.x += extent;
        bounds.x += SPACE;
      }
    }
   
    return bounds;
  }
 
  public Rectangle getItemImageBounds(StripItem item) {
    checkItem(item);
    Rectangle bounds = getItemBounds(item);
    bounds.y += bounds.height / 2;
    bounds.width = 0;
    bounds.height = 0;
   
    if (hasItemImage(item)) {
      Point imageSize = getItemImageSize(item);
      bounds.x += SPACE;
      bounds.y -= imageSize.y / 2;
      bounds.width = imageSize.x;
      bounds.height = imageSize.y;
    }
   
    return bounds;
  }
 
  public Rectangle getItemTextBounds(StripItem item) {
    checkItem(item);
    Rectangle bounds = getItemImageBounds(item);
    bounds.x += bounds.width;
    bounds.y += bounds.height / 2;
    bounds.width = 0;
    bounds.height = 0;
   
    if (hasItemText(item)) {
      Point textSize = getItemTextSize(item);
      bounds.x += SPACE;
      bounds.y -= textSize.y / 2;
      bounds.width = textSize.x;
      bounds.height = textSize.y;
    }
   
    return bounds;
  }
 
  public Rectangle getItemCloseButtonBounds(StripItem item) {
    checkItem(item);
    Point closeButtonSize = getItemCloseButtonSize();
    Rectangle bounds = getItemTextBounds(item);
    bounds.x += bounds.width + SPACE;
    bounds.y += bounds.height / 2 - closeButtonSize.y / 2;
    bounds.width = closeButtonSize.x;
    bounds.height = closeButtonSize.y;
    return bounds;
  }
 
  public void redrawItem(StripItem item) {
    checkItem(item);
    StripItemController controller = getController(item);
    Rectangle newBounds = getItemBounds(item);
    newBounds.x += controller.getOffset();
   
    Rectangle oldBounds = controller.getOldBounds();
   
    if (oldBounds != null && !oldBounds.equals(newBounds)) {
      redraw(oldBounds.x, oldBounds.y, oldBounds.width, oldBounds.height, true);
    }
   
    redraw(newBounds.x, newBounds.y, newBounds.width, newBounds.height, true);
    controller.setOldBounds(newBounds);
  }
 
  public StripItem getHoveredItem() {
    if (hovered == null) {
      return null;
    }
   
    return hovered.getItem();
  }
 
  public boolean isItemHovered(StripItem item) {
    checkItem(item);
    return item.equals(getHoveredItem());
  }
 
  public StripItem getPressedItem() {
    if (pressed == null) {
      return null;
    }
   
    return pressed.getItem();
  }
 
  public boolean isItemPressed(StripItem item) {
    checkItem(item);
    return item.equals(getPressedItem());
  }
 
  public StripItem getDraggedItem() {
    if (dragged == null) {
      return null;
    }
   
    return dragged.getItem();
  }
 
  public boolean isItemDragged(StripItem item) {
    checkItem(item);
    return item.equals(getDraggedItem());
  }
 
  public StripItem[] getSelectedItems() {
    List<StripItem> items = new ArrayList<StripItem>();
   
    for (StripItemController controller : selected) {
      items.add(controller.getItem());
    }
   
    return items.toArray(new StripItem[items.size()]);
  }
 
  public boolean isItemSelected(StripItem item) {
    checkItem(item);
   
    for (StripItemController controller : selected) {
      if (controller.getItem().equals(item)) {
        return true;
      }
    }
   
    return false;
  }
 
  public void setItemSelected(StripItem item, boolean value) {
    setItemSelected(item, value, true);
  }
 
  public void checkItem(StripItem item) {
    if (item == null) {
      throw new NullPointerException();
    }

    if (!containsItem(item)) {
      throw new IllegalArgumentException();
    }
  }
 
  public StripItem getItemBelowMouseCursor() {
    Point location = getDisplay().getCursorLocation();
    location = toControl(location);
    return getItem(location.x, location.y);
  }
 
  private Rectangle getItemOffsetBounds(StripItem item) {
    checkItem(item);
    return getItemOffsetBounds(controllers, getController(item));
  }
 
  private Rectangle getItemOffsetBounds(List<StripItemController> controllers, StripItemController controller) {
    Rectangle bounds = getItemBounds(controllers, controller.getItem());
    bounds.x += controller.getOffset();
    return bounds;
  }
 
  private void setItemSelected(StripItem item, boolean value, boolean affectOthers) {
    checkItem(item);
   
    StripItemController controller = getController(item);
    StripItem[] othersSelected = getSelectedItems();
   
    if (value) {
      if (!isItemSelected(item)) {
        controller.setForeground(FOREGROUNDS[SELECTED]);
       
        if (isItemHovered(item)) {
          controller.setBackground(BACKGROUNDS[SELECTED]);
          redrawItem(item);
        } else {
          RGB from;
          RGB to = BACKGROUNDS[SELECTED];
         
          if (controller.hasBackground()) {
            from = controller.getBackground();
          } else {
            from = BACKGROUNDS[NONE];
          }
         
          animateBackground(controller, from, to);
        }

        selected.add(controller);
      }
    } else {
      if (isItemSelected(item)) {
        controller.setForeground(FOREGROUNDS[NONE]);
       
        if (isItemHovered(item)) {
          controller.setBackground(BACKGROUNDS[HOVERED]);
          redrawItem(item);
        } else {
          RGB from;
          RGB to = BACKGROUNDS[NONE];
         
          if (controller.hasBackground()) {
            from = controller.getBackground();
          } else {
            from = BACKGROUNDS[SELECTED];
          }
         
          animateBackground(controller, from, to);
        }

        selected.remove(controller);
      }
    }
   
    if (affectOthers && !isMultiSelection()) {
      for (StripItem otherSelected : othersSelected) {
        setItemSelected(otherSelected, false, false);
      }
    }
  }
 
  private void animateMoveTo(final StripItemController controller, final int location) {
    if (controller.hasOffsetAnimator()) {
      controller.getOffsetAnimator().cancel();
      controller.setOffsetAnimator(null);
      return;
    }
   
    TimingTarget timingTarget = new TimingTargetAdapter() {
      private int srcOffset;
      private int destOffset;
     
      @Override
      public void begin(Animator source) {
        srcOffset = controller.getOffset();
        destOffset = location - getItemBounds(controller.getItem()).x;
      }
      @Override
      public void timingEvent(Animator source, double fraction) {
        Rectangle oldOffsetBounds = getItemOffsetBounds(controller.getItem());
        controller.setOffset((int )(srcOffset + (destOffset - srcOffset) * fraction));
        redraw(oldOffsetBounds.x, oldOffsetBounds.y, oldOffsetBounds.width, oldOffsetBounds.height, true);
        redrawItem(controller.getItem());
      }

      @Override
      public void end(Animator source) {
        Rectangle bounds = getItemBounds(controller.getItem());
        int diff = location - bounds.x;
        controller.setOffset(diff);
        redrawItem(controller.getItem());
        controller.setOffsetAnimator(null);
      }
    };
   
    Interpolator interpol = new AccelerationInterpolator(0.0, 0.1);
    Animator animator = new Animator.Builder().addTarget(timingTarget).setInterpolator(interpol).setDuration(250, TimeUnit.MILLISECONDS).build();
    controller.setOffsetAnimator(animator);
    animator.start();
    System.out.println("Started: " + System.currentTimeMillis());
  }
 
  private void animateBackground(final StripItemController controller, final RGB from, final RGB to) {
    if (controller.hasBackgroundAnimator()) {
      controller.getBackgroundAnimator().cancel();
      controller.setBackgroundAnimator(null);
    }
   
    TimingTarget timingTarget = new TimingTargetAdapter() {
      @Override
      public void timingEvent(Animator source, double fraction) {
        double r = to.red - from.red;
        double g = to.green - from.green;
        double b = to.blue - from.blue;
       
        r *= fraction;
        g *= fraction;
        b *= fraction;
       
        r += from.red;
        g += from.green;
        b += from.blue;
       
        controller.setBackground(new RGB((int )r, (int )g, (int )b));
        redrawItem(controller.getItem());
      }

      @Override
      public void end(Animator source) {
        controller.setBackground(to);
        redrawItem(controller.getItem());
        controller.setBackgroundAnimator(null);
      }
    };
   
    Interpolator interpol = new AccelerationInterpolator(0.0, 0.1);
    Animator animator = new Animator.Builder().addTarget(timingTarget).setInterpolator(interpol).setDuration(100, TimeUnit.MILLISECONDS).build();
    controller.setBackgroundAnimator(animator);
    animator.start();
  }
 
  protected void onPaint(Event event) {
    for (StripItemController controller : controllers) {
      if (controller.equals(dragged)) {
        continue;
      }
     
      paintItem(event.gc, controller);
    }
   
    if (dragged != null) {
      paintItem(event.gc, dragged);
    }
  }
 
  protected void onMouseEnter(Event event) {
    processHover(event.x, event.y);
  }

  protected void onMouseExit(Event event) {
    processHover(event.x, event.y);
  }

  protected void onMouseDown(Event event) {
    if (event.button != 1) {
      return;
    }
   
    StripItemController controller = getController(event.x, event.y);

    if (controller != null) {
      Rectangle bounds = getItemBounds(controller.getItem());
      controller.setBackground(BACKGROUNDS[PRESSED]);
      redrawItem(controller.getItem());
      mouseDownLocation = new Point(event.x, event.y);
      mouseDownOffset = new Point(event.x - bounds.x, event.y - bounds.y);
      mouseMoveLocation = new Point(event.x, event.y);
    }
   
    pressed = controller;
  }

  protected void onMouseMove(Event event) {
    processHover(event.x, event.y);
   
    if (pressed != null) {
      if (Math.abs(event.x - mouseDownLocation.x) > 5) {
        dragged = pressed;
        temp = new ArrayList<StripItemController>(controllers);
        pressed = null;
      }
    }
   
    if (dragged != null) {
      int offset = dragged.getOffset();
      offset += (event.x - mouseMoveLocation.x);
     
      StripItemController[] affected = null;
     
      if (event.x - mouseMoveLocation.x > 0) {
        // right to left
        affected = getControllersAfter(dragged, event.x - mouseMoveLocation.x);
      }
     
      if (event.x - mouseMoveLocation.x < 0) {
        // left to right
        affected = getControllersBefore(dragged, mouseMoveLocation.x - event.x);
      }
     
      dragged.setOffset(offset);
      redrawItem(dragged.getItem());
     
      if (event.x - mouseMoveLocation.x > 0) {
        StripItemController last = null;
       
        for (StripItemController item : affected) {
          if (last == null) {
            last = item;
          } else {
            Rectangle bounds0 = getItemBounds(last.getItem());
            Rectangle bounds1 = getItemBounds(item.getItem());
           
            if (bounds1.x > bounds0.x) {
              last = item;
            }
          }
        }
       
        if (last != null) {
          temp.remove(dragged);
          temp.add(temp.indexOf(last) + 1, dragged);
        }
       
        for (StripItemController item : affected) {
          Rectangle bounds = getItemBounds(temp, item.getItem());
          Rectangle offsetBounds = getItemOffsetBounds(item.getItem());

          if (!bounds.equals(offsetBounds)) {
            animateMoveTo(item, bounds.x);
          }
        }
      }
     
      if (event.x - mouseMoveLocation.x < 0) {
        StripItemController first = null;
       
        for (StripItemController item : affected) {
          if (first == null) {
            first = item;
          } else {
            Rectangle bounds0 = getItemBounds(first.getItem());
            Rectangle bounds1 = getItemBounds(item.getItem());
           
            if (bounds1.x < bounds0.x) {
              first = item;
            }
          }
        }
       
        if (first != null) {
          temp.remove(dragged);
          temp.add(temp.indexOf(first), dragged);
        }
       
        for (StripItemController item : affected) {
          Rectangle bounds = getItemBounds(temp, item.getItem());
          Rectangle offsetBounds = getItemOffsetBounds(item.getItem());

          if (!bounds.equals(offsetBounds)) {
            animateMoveTo(item, bounds.x);
          }
        }
      }
     
      mouseMoveLocation.x = event.x;
      mouseMoveLocation.y = event.y;
    }
  }
 
  protected void onMouseUp(Event event) {
    if (pressed != null) {
      boolean wasSelected = isItemSelected(pressed.getItem());
     
      if (wasSelected && !isMultiSelection()) {
        pressed.setBackground(BACKGROUNDS[SELECTED]);
        redrawItem(pressed.getItem());
      } else {
        setItemSelected(pressed.getItem(), !wasSelected);
      }
    }

    if (dragged != null) {
      temp = null;
     
      Rectangle bounds = getItemBounds(dragged.getItem());
      animateMoveTo(dragged, bounds.x);
     
      StripItem itemBelow = getItemBelowMouseCursor();
      StripItemController controllerBelow = getController(itemBelow);
     
      if (dragged.equals(controllerBelow)) {
        dragged.setBackground(BACKGROUNDS[HOVERED]);
        redrawItem(dragged.getItem());
      } else {
        if (isItemSelected(dragged.getItem())) {
          dragged.setBackground(BACKGROUNDS[SELECTED]);
          redrawItem(dragged.getItem());
        } else {
          animateBackground(dragged, BACKGROUNDS[PRESSED], BACKGROUNDS[NONE]);
        }
       
        if (controllerBelow != null) {
          if (!isItemPressed(controllerBelow.getItem())) {
            if (!isItemDragged(controllerBelow.getItem())) {
              animateBackground(controllerBelow, BACKGROUNDS[NONE], BACKGROUNDS[HOVERED]);
            }
          }
        }
      }
    }

    pressed = null;
    dragged = null;
    mouseDownLocation = null;
    mouseDownOffset = null;
    mouseMoveLocation = null;
  }
 
  private void processHover(int x, int y) {
    StripItemController oldController = hovered;
    StripItemController newController = getController(x, y);
   
    if (RT.equals(oldController, newController)) {
      return;
    }
   
    if (oldController != null) {
      if (!isItemSelected(oldController.getItem())) {
        if (pressed == null && dragged == null) {
          RGB from;
          RGB to = BACKGROUNDS[NONE];
         
          if (oldController.hasBackground()) {
            from = oldController.getBackground();
          } else {
            from = BACKGROUNDS[HOVERED];
          }
         
          animateBackground(oldController, from, to);
        }
      }
    }
   
    if (newController != null) {
      if (!isItemSelected(newController.getItem())) {
        if (pressed == null && dragged == null) {
          RGB from;
          RGB to = BACKGROUNDS[HOVERED];
         
          if (newController.hasBackground()) {
            from = newController.getBackground();
          } else {
            from = BACKGROUNDS[NONE];
          }
         
          animateBackground(newController, from, to);
        }
      }
    }
   
    hovered = newController;
  }
 
  private StripItemController getController(StripItem item) {
    for (StripItemController controller : controllers) {
      if (controller.getItem().equals(item)) {
        return controller;
      }
    }
   
    return null;
  }
 
  private StripItemController getController(int x, int y) {
    for (StripItemController controller : controllers) {
      StripItem item = controller.getItem();
      Rectangle bounds = getItemBounds(item);
     
      if (bounds.contains(x, y)) {
        return controller;
      }
    }
   
    return null;
  }
 
  private void paintItem(GC gc, StripItemController controller) {
    paintItemBackground(gc, controller);
    paintItemImage(gc, controller);
    paintItemText(gc, controller);
    paintItemCloseButton(gc, controller);
    paintItemFrame(gc, controller);
  }
 
  private void paintItemBackground(GC gc, StripItemController controller) {
    if (!controller.hasBackground()) {
      return;
    }
   
    Color oldColor = gc.getBackground();
    Color newColor = newColor(controller.getBackground());
    gc.setBackground(newColor);
   
    Rectangle bounds = getItemBounds(controller.getItem());
    bounds.x += controller.getOffset();
   
    gc.fillRectangle(bounds);
   
    gc.setBackground(oldColor);
    newColor.dispose();
  }

  private void paintItemImage(GC gc, StripItemController controller) {
    if (!hasItemImage(controller.getItem())) {
      return;
    }
   
    Rectangle imageBounds = getItemImageBounds(controller.getItem());
    imageBounds.x += controller.getOffset();
   
    gc.drawImage(controller.getItem().getImage(), imageBounds.x, imageBounds.y);
  }

  private void paintItemText(GC gc, StripItemController controller) {
    if (!hasItemText(controller.getItem())) {
      return;
    }
   
    Color oldColor = gc.getForeground();
    Color newColor = null;
   
    if (controller.hasForeground()) {
      newColor = newColor(controller.getForeground());
      gc.setForeground(newColor);
    }
   
    Rectangle textBounds = getItemTextBounds(controller.getItem());
    textBounds.x += controller.getOffset();
   
    gc.drawText(controller.getItem().getText(), textBounds.x, textBounds.y, true);
   
    gc.setForeground(oldColor);
   
    if (newColor != null) {
      newColor.dispose();
    }
  }
 
  private void paintItemCloseButton(GC gc, StripItemController controller) {
    Rectangle closeButtonBounds = getItemCloseButtonBounds(controller.getItem());
    closeButtonBounds.x += controller.getOffset();
   
    gc.drawImage(getItemCloseButtonImage(), closeButtonBounds.x, closeButtonBounds.y);
  }

  private void paintItemFrame(GC gc, StripItemController controller) {
    Rectangle bounds = getItemBounds(controller.getItem());
    bounds.x += controller.getOffset();
   
    Color oldColor = gc.getForeground();
    Color newColor = getColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
    gc.setForeground(newColor);
    gc.drawRectangle(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1);
    gc.setForeground(oldColor);
  }
 
  private Color newColor(RGB rgb) {
    Display display = getDisplay();
    return new Color(display, rgb);
  }
 
  private Color getColor(int id) {
    Display display = getDisplay();
    return display.getSystemColor(id);
  }
 
  private StripItemController[] getControllersBefore(StripItemController controller, int moved) {
    Set<StripItemController> before = new HashSet<StripItemController>();
   
    Bounds offsetBounds = Bounds.fromRectangle(getItemOffsetBounds(controller.getItem()));
   
    for (StripItemController otherController : controllers) {
      if (otherController.equals(controller)) {
        continue;
      }
     
      Bounds otherOffsetBounds = Bounds.fromRectangle(getItemOffsetBounds(otherController.getItem()));

      if (offsetBounds.getRight() > otherOffsetBounds.getRight() && (offsetBounds.getLeft() - moved) < otherOffsetBounds.getCenterX()) {
        before.add(otherController);
      }
    }
   
    return before.toArray(new StripItemController[before.size()]);
  }
 
  private StripItemController[] getControllersAfter(StripItemController controller, int moved) {
    Set<StripItemController> after = new HashSet<StripItemController>();

    Bounds offsetBounds = Bounds.fromRectangle(getItemOffsetBounds(controller.getItem()));
   
    for (StripItemController otherController : controllers) {
      if (otherController.equals(controller)) {
        continue;
      }
     
      Bounds otherOffsetBounds = Bounds.fromRectangle(getItemOffsetBounds(otherController.getItem()));
     
      if (offsetBounds.getLeft() < otherOffsetBounds.getLeft() && (offsetBounds.getRight() + moved) > otherOffsetBounds.getCenterX()) {
        after.add(otherController);
      }
    }
   
    return after.toArray(new StripItemController[after.size()]);
  }

  public static void main(String[] args) {
    UI.initialize();
    Display display = Display.getDefault();
    Shell shell = new Shell(display);
    StripBar bar = new StripBar(shell, SWT.DOUBLE_BUFFERED);
   
    GridLayout layout = new GridLayout();
    layout.horizontalSpacing = 0;
    layout.verticalSpacing = 0;
    layout.marginWidth = 0;
    layout.marginHeight = 0;
    shell.setLayout(layout);
   
    GridData data = new GridData();
    data.horizontalAlignment = SWT.FILL;
    data.verticalAlignment = SWT.FILL;
    data.grabExcessHorizontalSpace = true;
    bar.setLayoutData(data);
   
    StripItem item0 = new StripItem("item0");
    StripItem item1 = new StripItem("item1");
    StripItem item2 = new StripItem("item2");
    StripItem item3 = new StripItem("item3");
   
    item0.setText("Item 0");
    item1.setText("Item 1");
    item0.setImage(UIImageResource.T.about16());
    item2.setImage(UIImageResource.T.addContact16());

    bar.addItem(item0);
    bar.addItem(item1);
    bar.addItem(item2);
    bar.addItem(item3);
   
    shell.open();
   
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) {
        display.sleep();
      }
    }
   
    UI.destroy();
  }

}
TOP

Related Classes of com.peterhi.ui.stripbar3.StripBar

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.