Package com.peterhi.ui

Source Code of com.peterhi.ui.Snapshot2

package com.peterhi.ui;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
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.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

public final class ViewContainer extends Composite
                 implements Listener, ViewConstants {

  private final SplitDock centerPanel;
  private final AutohideBar leftBar;
  private final AutohideBar topBar;
  private final AutohideBar rightBar;
  private final AutohideBar bottomBar;
  private final List<Control> views;
  private Control activeView;
 
  public static void main(String[] args) throws Exception {
    Display d = Display.getDefault();
    Shell s = new Shell(d);
    s.setLayout(new FillLayout());
    ViewContainer v = new ViewContainer(s, SWT.NONE);
   
    s.setSize(1152, 640);

    Button v0 = new Button(v, SWT.NONE);
    {
      v0.setText("View 0");
     
      ViewSpec vs0 = new ViewSpec(v, "view0");
      vs0.setTitle("View 0");
     
      v.add(v0, vs0);
    }

    Button v1 = new Button(v, SWT.NONE);
    {
      v1.setText("View 1");
     
      ViewSpec vs1 = new ViewSpec(v, "view1");
      vs1.setTitle("View 1");
     
      v.add(v1, vs1);
    }
   
    Button v2 = new Button(v, SWT.NONE);
    {
      v2.setText("View 2");
     
      ViewSpec vs2 = new ViewSpec(v, "view2");
      vs2.setTitle("View 2");
      vs2.setPosition(TAB_BEFORE);
     
      v.add(v2, vs2);
    }
   
    Button v3 = new Button(v, SWT.NONE);
    {
      v3.setText("View 3");
     
      ViewSpec vs3 = new ViewSpec(v, "view3");
      vs3.setTitle("View 3");
      vs3.setReference(v0);
      vs3.setPosition(SPLIT_TOP);
      vs3.setExtent(0.2f);
     
      v.add(v3, vs3);
    }
   
    Button v4 = new Button(v, SWT.NONE);
    {
      v4.setText("View 4");
     
      ViewSpec vs4 = new ViewSpec(v, "view4");
      vs4.setTitle("View 4");
      vs4.setReference(v0);
      vs4.setPosition(SPLIT_LEFT);
      vs4.setExtent(150);
     
      v.add(v4, vs4);
    }
   
    Button v5 = new Button(v, SWT.NONE);
    {
      v5.setText("View 5");
     
      ViewSpec vs5 = new ViewSpec(v, "view5");
      vs5.setTitle("View 5");
      vs5.setReference(v0);
      vs5.setPosition(SPLIT_BOTTOM);
      vs5.setExtent(150);
     
      v.add(v5, vs5);
    }
   
    Button v6 = new Button(v, SWT.NONE);
    {
      v6.setText("View 6");
     
      ViewSpec vs6 = new ViewSpec(v, "view6");
      vs6.setTitle("View 6");
      vs6.setReference(v0);
      vs6.setExtent(200);
      vs6.setPosition(SPLIT_RIGHT);
     
      v.add(v6, vs6);
    }

    v.activate(v1);
    s.open();
   
    while (!s.isDisposed()) {
      if (!d.readAndDispatch()) {
        d.sleep();
      }
    }
  }
 
  public ViewContainer(Composite parent, int style) {
    super(parent, style);
   
    Display d = Display.getCurrent();
   
    centerPanel = new SplitDock(this, SWT.CENTER);
    leftBar = new AutohideBar(this, SWT.LEFT);
    topBar = new AutohideBar(this, SWT.TOP);
    rightBar = new AutohideBar(this, SWT.RIGHT);
    bottomBar = new AutohideBar(this, SWT.BOTTOM);

    centerPanel.setBackground(d.getSystemColor(SWT.COLOR_BLACK));
    leftBar.setBackground(d.getSystemColor(SWT.COLOR_RED));
    topBar.setBackground(d.getSystemColor(SWT.COLOR_YELLOW));
    rightBar.setBackground(d.getSystemColor(SWT.COLOR_BLUE));
    bottomBar.setBackground(d.getSystemColor(SWT.COLOR_GREEN));
   
    views = new ArrayList<Control>();
   
    addListener(SWT.Resize, this);
  }
 
  @Override
  public void layout(boolean changed) {
    Rectangle cli = getClientArea();
   
    Point ls = leftBar.computeSize(SWT.DEFAULT, cli.height);
    Point ts = topBar.computeSize(cli.width, SWT.DEFAULT);
    Point rs = rightBar.computeSize(SWT.DEFAULT, cli.height);
    Point bs = bottomBar.computeSize(cli.width, SWT.DEFAULT);
   
    centerPanel.setBounds(cli.x + ls.x, cli.y + ts.y,
              cli.width - ls.x - rs.x, cli.height - ts.y - bs.y);
   
    leftBar.setBounds(cli.x, cli.y + ts.y,
              ls.x, cli.height - ts.y - bs.y);
   
    topBar.setBounds(cli.x + ls.x, cli.y,
             cli.width - ls.x - rs.x, ts.y);
   
    rightBar.setBounds(cli.x + cli.width - rs.x, cli.y + ts.y,
               rs.x, cli.height - ts.y - bs.y);
   
    bottomBar.setBounds(cli.x + ls.x, cli.y + cli.height - bs.y,
              cli.width - ls.x - rs.x, bs.y);
  }

  @Override
  public void setLayout(Layout layout) {
  }
 
  @Override
  public Point computeSize(int wHint, int hHint, boolean changed) {
    return super.computeSize(wHint, hHint, changed);
  }
 
  @Override
  public void handleEvent(Event event) {
    if (event.widget == this && event.type == SWT.Resize) {
      layout();
    }
  }
 
  public void add(Control view, ViewSpec vs) throws ViewException {
    if (views.contains(view)) {
      activate(view);
      return;
    }
   
    if (views.isEmpty()) {
      vs.setPosition(DEFAULT);
      centerPanel.add(view, vs);
    } else if (vs.getPosition() == DEFAULT) {
      vs.setReference(getActiveView());
      vs.setPosition(TAB_AFTER);
      centerPanel.add(view, vs);
    } else if (vs.isTabbed()) {
      centerPanel.add(view, vs);
    } else if (vs.isSplit()) {
      centerPanel.add(view, vs);
    }
   
    view.setData(VIEW_SPEC, vs);
    views.add(view);
    activate(view);
  }
 
  public void activate(Control view) throws ViewException {
    if (view == activeView) {
      return;
    }
   
    deactivate(activeView);
   
    if (view == null) {
      view = getActiveView();
    }
   
    if (!views.contains(view)) {
      return;
    }
   
    ViewSpec vs = (ViewSpec )view.getData(VIEW_SPEC);
   
    if (vs == null) {
      throw new ViewException();
    }
   
    Object item = vs.getItem();
   
    if (item instanceof CTabItem) {
      CTabItem ti = (CTabItem )item;
      CTabFolder tf = ti.getParent();
      tf.setSelection(ti);
      ti.setFont(Ui.FONT_BOLD);
    }
   
    activeView = view;
  }
 
  private void deactivate(Control view) throws ViewException {
    if (view == null) {
      view = getActiveView();
    }
   
    if (!views.contains(view)) {
      return;
    }
   
    ViewSpec vs = (ViewSpec )view.getData(VIEW_SPEC);
   
    if (vs == null) {
      throw new ViewException();
    }
   
    Object item = vs.getItem();
   
    if (item instanceof CTabItem) {
      CTabItem ti = (CTabItem )item;
      ti.setFont(Ui.FONT_PLAIN);
    }
  }
 
  public Control getActiveView() {
    return activeView;
  }
}

final class SplitDock extends Composite implements Listener, ViewConstants {

  private final List<ViewGroup> groups;
  private Rectangle oldClientArea;
  private int gap;
 
  public SplitDock(ViewContainer parent, int style) {
    super(parent, style);
    groups = new ArrayList<ViewGroup>();
    gap = 10;
    addListener(SWT.Resize, this);
  }
 
  public void add(Control view, ViewSpec vs) throws ViewException {
    if (vs.getPosition() == DEFAULT) {
      ViewGroup vg = new ViewGroup(this, SWT.NONE);
      vg.setBounds(getClientArea());
      vg.add(view, vs, -1);
      groups.add(vg);
    } else if (vs.isTabbed()) {
      ViewGroup vg = findViewGroup(vs);
      int index = findIndex(vs);
      vg.add(view, vs, index);
    } else if (vs.isSplit()) {
      Control reference = vs.getReference();
      ViewSpec rvs = (ViewSpec )reference.getData(VIEW_SPEC);
      Point oldMinSize = rvs.getMinSize();
      Point neoMinSize = vs.getMinSize();
      ViewGroup vg = findViewGroup(vs);
      Rectangle entire = vg.getBounds();
      Rectangle old = new Rectangle(entire.x, entire.y,
        entire.width, entire.height);
      Rectangle neo = new Rectangle(entire.x, entire.y,
        entire.width, entire.height);
     
      int extent;
      int minExtent;
     
      if (vs.isVertical()) {
        extent = vs.getExtent(entire.width - gap);
        minExtent = neoMinSize.x;
      } else {
        extent = vs.getExtent(entire.height - gap);
        minExtent = neoMinSize.y;
      }
     
      if (extent < minExtent) {
        extent = minExtent;
      }
     
      if (vs.getPosition() == SPLIT_LEFT) {
        neo.width = extent;
        old.x += neo.width + gap;
        old.width -= old.x;
      } else if (vs.getPosition() == SPLIT_TOP) {
        neo.height = extent;
        old.y += neo.height + gap;
        old.height -= old.y;
      } else if (vs.getPosition() == SPLIT_BOTTOM) {
        neo.height = extent;
        old.height -= extent + gap;
        neo.y += old.height + gap;
      } else {
        neo.width = extent;
        old.width -= extent + gap;
        neo.x += old.width + gap;
      }
     
      ViewGroup nvg = new ViewGroup(this, SWT.NONE);
      nvg.add(view, vs, -1);
      groups.add(nvg);
     
      if (old.width < oldMinSize.x || old.height < oldMinSize.y) {
        throw new ViewException(MessageFormat.format(
            "Insufficient size to lay out the view, " +
            "min = {0} but actual = {1}.", oldMinSize,
            new Point(old.width, old.height)));
      }
     
      if (neo.width < neoMinSize.x || neo.height < neoMinSize.y) {
        throw new ViewException(MessageFormat.format(
            "Insufficient size to lay out the view, " +
            "min = {0} but actual = {1}.", neoMinSize,
            new Point(neo.width, neo.height)));
      }
     
      vg.setBounds(old);
      nvg.setBounds(neo);
    }
  }

  @Override
  public void layout(boolean changed) {
    if (groups.isEmpty()) {
      return;
    }
   
    Rectangle newClientArea = getClientArea();
    float[] scales = computeScales(newClientArea);
    float xscale = scales[0];
    float yscale = scales[1];
   
    Map<ViewGroup, Rectangle> caches = new HashMap<ViewGroup, Rectangle>();
   
    for (ViewGroup group : groups) {
      Rectangle cache = group.getBounds();
      caches.put(group, cache);
    }
   
    for (Rectangle cache : caches.values()) {
      inflate(cache, oldClientArea, gap);
    }
   
    Snapshot2 snapshot = new Snapshot2(groups.toArray(
      new ViewGroup[groups.size()]), oldClientArea, caches);
   
    for (ViewGroup group : groups) {
      Rectangle cache = caches.get(group);
      cache.width = Math.round((float )cache.width * xscale);
      cache.height = Math.round((float )cache.height * yscale);
    }
   
    ViewGroup upperLeft = snapshot.getUpperLeft();
    lineUp(upperLeft, snapshot, caches);
   
    adjustRightAndBottomCorners(snapshot, caches, newClientArea);
   
    for (ViewGroup key : caches.keySet()) {
      Rectangle cache = caches.get(key);
      deflate(cache, newClientArea, gap);
      key.setBounds(cache);
    }
  }
 
  @Override
  public void setLayout(Layout layout) {
  }
 
  @Override
  public Point computeSize(int wHint, int hHint, boolean changed) {
    return super.computeSize(wHint, hHint, changed);
  }
 
  @Override
  public ViewContainer getParent() {
    return (ViewContainer )super.getParent();
  }
 
  @Override
  public boolean setParent(Composite parent) {
    if (!(parent instanceof ViewContainer)) {
      throw new IllegalArgumentException(
        "Parent is not an instance of GrandPanel.");
    }
   
    return super.setParent(parent);
  }
 
  @Override
  public void handleEvent(Event event) {
    if (event.widget == this && event.type == SWT.Resize) {
      if (oldClientArea != null) {
        layout();
      }
     
      oldClientArea = getClientArea();
    }
  }
 
  public int getGap() {
    return gap;
  }
 
  public void setGap(int gap) {
    if (gap <= 0) {
      gap = 10;
    }
   
    this.gap = gap;
  }
 
  private float[] computeScales(Rectangle newClientArea) {
    if (oldClientArea == null) {
      return new float[] { 1.0f, 1.0f };
    }
   
    float[] factors = new float[] { 1.0f, 1.0f };
   
    if (oldClientArea.width != 0 && newClientArea.width != 0) {
      factors[0] = (float )newClientArea.width / oldClientArea.width;
    }
   
    if (oldClientArea.height != 0 && newClientArea.height != 0) {
      factors[1] = (float )newClientArea.height / oldClientArea.height;
    }
   
    return factors;
  }
 
  private void deflate(Rectangle rect, Rectangle clientArea, int amt) {
    int left = rect.x;
    int top = rect.y;
    int right = rect.x + rect.width;
    int bottom = rect.y + rect.height;
   
    int cleft = clientArea.x;
    int ctop = clientArea.y;
    int cright = clientArea.x + clientArea.width;
    int cbottom = clientArea.y + clientArea.height;
   
    if (left > cleft) {
      left += amt / 2;
    }
   
    if (top > ctop) {
      top += amt / 2;
    }
   
    if (right < cright) {
      right -= amt / 2;
    }
   
    if (bottom < cbottom) {
      bottom -= amt / 2;
    }
   
    rect.x = left;
    rect.y = top;
    rect.width = right - left;
    rect.height = bottom - top;
  }
 
  private void inflate(Rectangle rect, Rectangle clientArea, int amt) {
    int left = rect.x;
    int top = rect.y;
    int right = rect.x + rect.width;
    int bottom = rect.y + rect.height;
   
    int cleft = clientArea.x;
    int ctop = clientArea.y;
    int cright = clientArea.x + clientArea.width;
    int cbottom = clientArea.y + clientArea.height;

    left -= amt / 2;
    top -= amt / 2;
    right += amt / 2;
    bottom += amt / 2;
   
    if (left < cleft) {
      left = cleft;
    }
   
    if (top < ctop) {
      top = ctop;
    }
   
    if (right > cright) {
      right = cright;
    }
   
    if (bottom > cbottom) {
      bottom = cbottom;
    }
   
    rect.x = left;
    rect.y = top;
    rect.width = right - left;
    rect.height = bottom - top;
  }
 
  private void lineUp(ViewGroup current, Snapshot2 snapshot,
    Map<ViewGroup, Rectangle> caches) {
    Rectangle cbounds = caches.get(current);
    ViewGroup[] rights = snapshot.rightOf(current);
    ViewGroup[] bottoms = snapshot.bottomOf(current);
   
    for (ViewGroup right : rights) {
      Rectangle rbounds = caches.get(right);
      rbounds.x = cbounds.x + cbounds.width;
      lineUp(right, snapshot, caches);
    }
   
    for (ViewGroup bottom : bottoms) {
      Rectangle bbounds = caches.get(bottom);
      bbounds.y = cbounds.y + cbounds.height;
      lineUp(bottom, snapshot, caches);
    }
  }
 
  private void adjustRightAndBottomCorners(Snapshot2 snapshot,
    Map<ViewGroup, Rectangle> caches, Rectangle clientArea) {
    for (ViewGroup key : caches.keySet()) {
      Rectangle cache = caches.get(key);
     
      if (snapshot.containsRightmost(key)) {
        int right = cache.x + cache.width;
        int cright = clientArea.x + clientArea.width;
        int diff = cright - right;
        cache.width += diff;
      }
     
      if (snapshot.containsBottommost(key)) {
        int bottom = cache.y + cache.height;
        int cbottom = clientArea.y + clientArea.height;
        int diff = cbottom - bottom;
        cache.height += diff;
      }
    }
  }
 
  private ViewGroup findViewGroup(ViewSpec vs) {
    Control reference = vs.getReference();
    ViewSpec rvs = (ViewSpec )reference.getData(VIEW_SPEC);
    CTabItem item = (CTabItem )rvs.getItem();
   
    if (item == null) {
      return null;
    }
   
    CTabFolder folder = item.getParent();
   
    if (folder == null) {
      return null;
    }
   
    ViewGroup vg = (ViewGroup )folder.getParent();
    return vg;
  }
 
  private int findIndex(ViewSpec vs) {
    Control reference = vs.getReference();
    ViewSpec rvs = (ViewSpec )reference.getData(VIEW_SPEC);
    CTabItem item = (CTabItem )rvs.getItem();
   
    if (item == null) {
      return -1;
    }
   
    CTabFolder folder = item.getParent();
   
    if (folder == null) {
      return -1;
    }
   
    int index = folder.indexOf(item);
   
    if (vs.getPosition() == TAB_AFTER) {
      index++;
    }
   
    return index;
  }
}

final class AutohideBar extends Composite implements ViewConstants {

  public AutohideBar(ViewContainer parent, int style) {
    super(parent, style);
  }
 
  @Override
  public Point computeSize(int wHint, int hHint, boolean changed) {
    return super.computeSize(isVertical() ? 10 : wHint,
                 isVertical() ? hHint : 10, changed);
  }
 
  @Override
  public ViewContainer getParent() {
    return (ViewContainer )super.getParent();
  }

  @Override
  public boolean setParent(Composite parent) {
    if (!(parent instanceof ViewContainer)) {
      throw new IllegalArgumentException(
        "Parent is not an instance of GrandPanel.");
    }
   
    return super.setParent(parent);
  }
 
  private boolean isVertical() {
    int style = getStyle();
    return (style & (SWT.LEFT | SWT.RIGHT)) != 0;
  }
}

final class ViewGroup extends Composite implements ViewConstants {
 
  private final CTabFolder tabPanel;

  public ViewGroup(SplitDock parent, int style) {
    super(parent, style);
    setLayout(new FillLayout());
    tabPanel = new CTabFolder(this, style);
    tabPanel.setBorderVisible(true);
    bindActivationListeners();
  }
 
  public void add(Control view, ViewSpec vs, int index) {
    if (index < 0 || index > tabPanel.getItemCount()) {
      index = tabPanel.getItemCount();
    }
   
    CTabItem item = new CTabItem(tabPanel, SWT.CLOSE, index);
    item.setText(vs.getTitle());
    item.setImage(vs.getIcon());
    view.setParent(tabPanel);
    item.setControl(view);
    tabPanel.setSelection(item);
    vs.setItem(item);
  }

  public SplitDock getParent() {
    return (SplitDock )super.getParent();
  }
 
  public boolean setParent(Composite parent) {
    if (!(parent instanceof SplitDock)) {
      throw new IllegalArgumentException(
        "Parent must be an instance of DockPanel.");
    }
   
    return super.setParent(parent);
  }
 
  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder(super.toString());
   
    if (tabPanel.getItemCount() > 0) {
      sb.append(" ");
     
      CTabItem cti = tabPanel.getSelection();
     
      if (cti == null) {
        cti = tabPanel.getItem(0);
      }
     
      sb.append(cti.getText());
    }
   
    return sb.toString();
  }
 
  private ViewContainer getViewContainer() {
    return (ViewContainer )getParent().getParent();
  }
 
  private void bindActivationListeners() {
    Listener clickOnItemDirectlyListener = new Listener() {
      @Override
      public void handleEvent(Event event) {
        CTabItem item = tabPanel.getItem(new Point(event.x, event.y));
       
        if (item == null) {
          item = tabPanel.getSelection();
        }
       
        try {
          getViewContainer().activate(item.getControl());
        } catch (Exception ex) {
          ex.printStackTrace();
        }
      }
    };
   
    final Listener clickOnAnyControlInsideListener = new Listener() {
      @Override
      public void handleEvent(Event event) {
        if (!(event.widget instanceof Control)) {
          return;
        }
       
        Control control = (Control )event.widget;
       
        if (isChildOf(control)) {
          CTabItem ti = tabPanel.getSelection();
          Control view = ti.getControl();
         
          try {
            getViewContainer().activate(view);
          } catch (Exception ex) {
            ex.printStackTrace();
          }
        }
      }
     
      private boolean isChildOf(Control control) {
        if (control.getParent() == null) {
          return false;
        }
       
        if (control.getParent() == tabPanel) {
          return true;
        }
       
        return isChildOf(control.getParent());
      }
    };
   
    final Listener removeFilterListener = new Listener() {
      @Override
      public void handleEvent(Event event) {
        getDisplay().removeFilter(SWT.MouseDown,
          clickOnAnyControlInsideListener);
      }
    };
   
    tabPanel.addListener(SWT.MouseDown, clickOnItemDirectlyListener);
    tabPanel.addListener(SWT.Dispose, removeFilterListener);
    getDisplay().addFilter(SWT.MouseDown, clickOnAnyControlInsideListener);
  }
}

final class Snapshot2 {
 
  private final ViewGroup upperLeft;
  private final SortedMap<ViewGroup, SortedSet<ViewGroup>> rights;
  private final SortedMap<ViewGroup, SortedSet<ViewGroup>> bottoms;
  private final SortedSet<ViewGroup> rightmost;
  private final SortedSet<ViewGroup> bottommost;
 
  public Snapshot2(ViewGroup[] groups, Rectangle clientArea,
    Map<ViewGroup, Rectangle> caches) {
    this.upperLeft = findUpperLeft(groups, caches);
    this.rights = new TreeMap<ViewGroup, SortedSet<ViewGroup>>(
      ViewGroupComparator.getHorizontal());
    this.bottoms = new TreeMap<ViewGroup, SortedSet<ViewGroup>>(
      ViewGroupComparator.getVertical());
    this.rightmost = new TreeSet<ViewGroup>(
      ViewGroupComparator.getVertical());
    this.bottommost = new TreeSet<ViewGroup>(
      ViewGroupComparator.getHorizontal());
   
    for (ViewGroup group : groups) {
      Rectangle bounds0 = caches.get(group);
     
      if (bounds0.x + bounds0.width == clientArea.x + clientArea.width) {
        rightmost.add(group);
      }
     
      if (bounds0.y + bounds0.height == clientArea.y + clientArea.height) {
        bottommost.add(group);
      }
    }
   
    for (ViewGroup group : groups) {
      Rectangle bounds0 = caches.get(group);
      SortedSet<ViewGroup> r = rights.get(group);
      SortedSet<ViewGroup> b = bottoms.get(group);
     
      if (r == null) {
        r = new TreeSet<ViewGroup>(
          ViewGroupComparator.getVertical());
        rights.put(group, r);
      }
     
      if (b == null) {
        b = new TreeSet<ViewGroup>(
          ViewGroupComparator.getHorizontal());
        bottoms.put(group, b);
      }
     
      for (ViewGroup other : groups) {
        if (group == other) {
          continue;
        }
       
        Rectangle bounds1 = caches.get(other);
       
        if (bounds0.x + bounds0.width == bounds1.x) {
          r.add(other);
        }
       
        if (bounds0.y + bounds0.height == bounds1.y) {
          b.add(other);
        }
      }
    }
  }

  public ViewGroup getUpperLeft() {
    return upperLeft;
  }
 
  public ViewGroup[] rightOf(ViewGroup vg) {
    SortedSet<ViewGroup> set = rights.get(vg);
   
    if (set == null) {
      return new ViewGroup[0];
    }
   
    return set.toArray(new ViewGroup[0]);
  }
 
  public ViewGroup[] bottomOf(ViewGroup vg) {
    SortedSet<ViewGroup> set = bottoms.get(vg);
   
    if (set == null) {
      return new ViewGroup[0];
    }
   
    return set.toArray(new ViewGroup[0]);
  }
 
  public boolean containsRightmost(ViewGroup v) {
    return rightmost.contains(v);
  }
 
  public boolean containsBottommost(ViewGroup v) {
    return bottommost.contains(v);
  }
 
  public ViewGroup[] getRightmost() {
    return rightmost.toArray(new ViewGroup[rightmost.size()]);
  }
 
  public ViewGroup[] getBottommost() {
    return bottommost.toArray(new ViewGroup[bottommost.size()]);
  }
 
  private ViewGroup findUpperLeft(ViewGroup[] groups,
    Map<ViewGroup, Rectangle> caches) {
    for (ViewGroup group : groups) {
      Rectangle bounds = caches.get(group);
     
      if (bounds.x == 0 && bounds.y == 0) {
        return group;
      }
    }
   
    throw new IllegalArgumentException("No upper left group included.");
  }
}

final class ViewGroupComparator implements Comparator<ViewGroup> {

  private static Comparator<ViewGroup> horizontal;
  private static Comparator<ViewGroup> vertical;
 
  public static Comparator<ViewGroup> getHorizontal() {
    if (horizontal == null) {
      horizontal = new ViewGroupComparator(SWT.HORIZONTAL);
    }
   
    return horizontal;
  }
 
  public static Comparator<ViewGroup> getVertical() {
    if (vertical == null) {
      vertical = new ViewGroupComparator(SWT.VERTICAL);
    }
   
    return vertical;
  }

  private int style;
 
  protected ViewGroupComparator(int style) {
    this.style = style;
  }
 
  public boolean isVertical() {
    return (style & SWT.VERTICAL) == SWT.VERTICAL;
  }
 
  @Override
  public int compare(ViewGroup vg0, ViewGroup vg1) {
    if (vg0 == vg1) {
      return 0;
    }
   
    if (vg0 == null) {
      return -1;
    }
   
    if (vg1 == null) {
      return 1;
    }
   
    Rectangle b0 = vg0.getBounds();
    Rectangle b1 = vg1.getBounds();
   
    if (isVertical()) {
      int dy = b0.y - b1.y;
     
      if (dy != 0) {
        return dy;
      }
     
      int dx = b0.x - b1.x;
     
      if (dx != 0) {
        return dx;
      }
     
      return vg0.hashCode() - vg1.hashCode();
    } else {
      int dx = b0.x - b1.x;
     
      if (dx != 0) {
        return dx;
      }
     
      int dy = b0.y - b1.y;
     
      if (dy != 0) {
        return dy;
      }
     
      return vg0.hashCode() - vg1.hashCode();
    }
  }
 
}
TOP

Related Classes of com.peterhi.ui.Snapshot2

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.