Package limelight.ui.model

Source Code of limelight.ui.model.PropPanelLayout$Row

//- Copyright © 2008-2011 8th Light, Inc. All Rights Reserved.
//- Limelight and all included source files are distributed under terms of the MIT License.

package limelight.ui.model;

import limelight.LimelightException;
import limelight.Log;
import limelight.styles.Style;
import limelight.styles.abstrstyling.VerticalAlignmentValue;
import limelight.styles.values.AutoDimensionValue;
import limelight.styles.values.GreedyDimensionValue;
import limelight.ui.Panel;
import limelight.ui.model.inputs.ScrollBarPanel;
import limelight.util.Box;

import java.awt.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class PropPanelLayout implements Layout
{
  public static PropPanelLayout instance = new PropPanelLayout();

  public void doExpansion(Panel thePanel)
  {
    PropPanel panel = (PropPanel) thePanel;
    FloaterLayout.instance.doFinalization(panel);
//    Style style = panel.getStyle();
//    if(panel.isSizeChangePending() || style.hasDynamicDimension())
    snapToSize(panel);
  }

  public void doContraction(Panel thePanel)
  {
    PropPanel panel = (PropPanel) thePanel;
    establishScrollBars(panel);
    LinkedList<Row> rows = buildRows(panel);
    distributeGreediness(panel, rows);
    Dimension consumedDimensions = new Dimension();
    calculateConsumedDimentions(rows, consumedDimensions);
    collapseAutoDimensions(panel, consumedDimensions);
    layoutRows(panel, consumedDimensions, rows);
    layoutScrollBars(panel, consumedDimensions);
  }

  public void doFinalization(Panel thePanel)
  {
    PropPanel panel = (PropPanel) thePanel;
    panel.updateBorder();
    panel.markAsDirty();
  }

  // TODO MDM This gets called A LOT!  Possible speed up by re-using objects, rather then reallocating them. (rows list, rows)

  private void distributeGreediness(PropPanel panel, LinkedList<Row> rows)
  {
    for(Row row : rows)
      row.distributeGreeyWidth();
    distributeGreedyHeight(panel, rows);
  }

  private void distributeGreedyHeight(PropPanel panel, LinkedList<Row> rows)
  {
    int consumedHeight = 0;
    int greedyRows = 0;
    for(Row row : rows)
    {
      consumedHeight += row.height;
      if(row.isGreedy())
        greedyRows++;
    }

    int leftOver = panel.getChildConsumableBounds().height - consumedHeight;
    if(greedyRows > 0)
    {
      int[] split = splitEvenly(leftOver, greedyRows);
      int splitIndex = 0;
      for(Row row : rows)
      {
        if(row.isGreedy())
          row.applyGreedyHeight(split[splitIndex++]);
      }
    }
  }

  private int[] splitEvenly(int amount, int parts)
  {
    int[] split = new int[parts];
    int part = amount / parts;
    int remainder = amount % parts;
    for(int i = 0; i < split.length; i++)
    {
      split[i] = part;
      if(remainder > 0)
      {
        split[i] += 1;
        remainder--;
      }
    }
    return split;
  }

  public boolean overides(Layout other)
  {
    return true;
  }

//  private boolean hasNonScrollBarChildren(PropPanel panel)
//  {
//    List<Panel> children = panel.getChildren();
//    if(children.size() == 0)
//      return false;
//    else if(children.size() == 1)
//      return !(children.contains(panel.getVerticalScrollbar()) || children.contains(panel.getHorizontalScrollbar()));
//    else if(children.size() == 2)
//      return !(children.contains(panel.getVerticalScrollbar()) && children.contains(panel.getHorizontalScrollbar()));
//    else
//      return true;
//  }

  private void layoutScrollBars(PropPanel panel, Dimension consumedDimensions)
  {
    ScrollBarPanel vertical = panel.getVerticalScrollbar();
    ScrollBarPanel horizontal = panel.getHorizontalScrollbar();
    Box area = panel.getChildConsumableBounds();
    if(vertical != null)
    {
      vertical.setHeight(area.height);
      vertical.setLocation(area.right() + 1, area.y);
      vertical.configure(area.height, consumedDimensions.height);
    }
    if(horizontal != null)
    {
      horizontal.setWidth(area.width);
      horizontal.setLocation(area.x, area.bottom() + 1);
      horizontal.configure(area.width, consumedDimensions.width);
    }
  }

  private void collapseAutoDimensions(PropPanel panel, Dimension consumedDimensions)
  {
    Style style = panel.getStyle();

    int width = style.getCompiledWidth().collapseExcess(panel.getWidth(), consumedDimensions.width + horizontalInsets(panel), style.getCompiledMinWidth(), style.getCompiledMaxWidth());
    int height = style.getCompiledHeight().collapseExcess(panel.getHeight(), consumedDimensions.height + verticalInsets(panel), style.getCompiledMinHeight(), style.getCompiledMaxHeight());

    panel.setSize(width, height);
  }

  public int horizontalInsets(PropPanel panel)
  {
    return panel.getBounds().width - panel.getPaddedBounds().width;
  }

  public int verticalInsets(PropPanel panel)
  {
    return panel.getBounds().height - panel.getPaddedBounds().height;
  }

//  protected void doPreliminaryLayoutOnChildren(PropPanel panel, Map<Panel, Layout> panelsToLayout)
//  {
//    for(Panel child : panel.getChildren())
//    {
//      if(panelsToLayout != null && panelsToLayout.containsKey(child))
//      {
//        if(!(child instanceof PropPanel) || child.getStyle().getCompiledWidth() instanceof AutoDimensionValue)
//        {
//          child.getDefaultLayout().doLayout(child, panelsToLayout, true);
//        }
//        else
//        {
//          ((PropPanel) child).greediness.setSize(0, 0);
//          snapToSize((PropPanel) child);
//        }
//      }
//    }
//  }
//
//  protected void doPostLayoutOnChildren(PropPanel panel, Map<Panel, Layout> panelsToLayout)
//  {
//    for(Panel child : panel.getChildren())
//    {
//      if(panelsToLayout != null && panelsToLayout.containsKey(child))
//      {
//        final Layout layout = child.getDefaultLayout();
//        layout.doLayout(child, panelsToLayout, false);
//      }
//    }
//  } 1

  public void layoutRows(PropPanel panel, Dimension consumedDimension, LinkedList<Row> rows)
  {
    Style style = panel.getStyle();
    int y = style.getCompiledVerticalAlignment().getY(consumedDimension.height, panel.getChildConsumableBounds());
    if(panel.getVerticalScrollbar() != null)
    {
      y = Math.max(0, y);
      y -= panel.getVerticalScrollbar().getValue();
    }
    for(Row row : rows)
    {
      int x = style.getCompiledHorizontalAlignment().getX(row.width, panel.getChildConsumableBounds());
      if(panel.getHorizontalScrollbar() != null)
      {
        x = Math.max(0, x);
        x -= panel.getHorizontalScrollbar().getValue();
      }
      row.layoutComponents(x, y, style.getCompiledVerticalAlignment());
      y += row.height;
    }
  }

  protected LinkedList<Row> buildRows(PropPanel panel)
  {
    LinkedList<Row> rows = new LinkedList<Row>();
    Row currentRow = newRow(panel, rows);

    for(Panel child : panel.getChildren())
    {
      if(!(child instanceof ScrollBarPanel) && !child.isFloater())
      {
        if(!currentRow.isEmpty() && !currentRow.fits(child))
        {
          currentRow = newRow(panel, rows);
        }
        currentRow.add(child);
      }
    }
    return rows;
  }

  private Row newRow(PropPanel panel, LinkedList<Row> rows)
  {
    Row currentRow = new Row(panel.getChildConsumableBounds().width);
    rows.add(currentRow);
    return currentRow;
  }

  protected void calculateConsumedDimentions(LinkedList<Row> rows, Dimension consumedDimensions)
  {
    for(Row row : rows)
    {
      row.reCalculatedHeight();
      consumedDimensions.height += row.height;
      if(row.width > consumedDimensions.width)
        consumedDimensions.width = row.width;
    }
  }

  public void establishScrollBars(PropPanel panel)
  {
    Style style = panel.getStyle();
    if(panel.getVerticalScrollbar() == null && style.getCompiledVerticalScrollbar().isOn())
      panel.addVerticalScrollBar();
    else if(panel.getVerticalScrollbar() != null && style.getCompiledVerticalScrollbar().isOff())
      panel.removeVerticalScrollBar();

    if(panel.getHorizontalScrollbar() == null && style.getCompiledHorizontalScrollbar().isOn())
      panel.addHorizontalScrollBar();
    else if(panel.getHorizontalScrollbar() != null && style.getCompiledHorizontalScrollbar().isOff())
      panel.removeHorizontalScrollBar();
  }

  public void snapToSize(PropPanel panel)
  {
    if(panel.getParent() == null) // can happen if removed from tree
      return;
    Box maxArea = panel.getParent().getChildConsumableBounds();

    Style style = panel.getStyle();
    if(style.getCompiledWidth() instanceof AutoDimensionValue && style.getCompiledHeight() instanceof GreedyDimensionValue)
      throw new LimelightException("A greedy height is not allowed with auto width.");

    int newWidth = style.getCompiledWidth().calculateDimension(maxArea.width, style.getCompiledMinWidth(), style.getCompiledMaxWidth(), panel.greediness.width);
    int newHeight = style.getCompiledHeight().calculateDimension(maxArea.height, style.getCompiledMinHeight(), style.getCompiledMaxHeight(), panel.greediness.height);

    // TODO MDM - Hacky Hack!!!!  More thought needs to go into the way layouts are down and how greedy fits into it all
//    if(topLevel && style.getCompiledWidth() instanceof GreedyDimensionValue && panel.getWidth() > newWidth)
//      newWidth = panel.getWidth();
//    if(topLevel && style.getCompiledHeight() instanceof GreedyDimensionValue && panel.getHeight() > newHeight)
//      newHeight = panel.getHeight();

    panel.setSize(newWidth, newHeight);
    panel.resetPendingSizeChange();
  }

  protected class Row
  {
    private final LinkedList<Panel> items;
    private final int maxWidth;
    public int width;
    public int height;
    private int greedyWidths;
    private int greedyHeights;

    public Row(int maxWidth)
    {
      this.maxWidth = maxWidth;
      width = 0;
      height = 0;
      items = new LinkedList<Panel>();
    }

    public void add(Panel panel)
    {
      items.add(panel);
      width += panel.getWidth();
      if(panel.getHeight() > height)
        height = panel.getHeight();

      if(hasGreedyWidth(panel))
        greedyWidths += 1;
      if(hasGreedyHeight(panel))
      {
        greedyHeights += 1;
      }
    }

    public boolean isEmpty()
    {
      return items.size() == 0;
    }

    public boolean fits(Panel panel)
    {
      return (width + panel.getWidth()) <= maxWidth;
    }

    public void layoutComponents(int x, int y, VerticalAlignmentValue verticalAlignment)
    {
      Box area = new Box(x, y, width, height);
      for(Panel panel : items)
      {
        int alignedY = verticalAlignment.getY(panel.getHeight(), area);
        panel.setLocation(x, alignedY);
        x += panel.getWidth();
      }
    }

    public void distributeGreeyWidth()
    {
      int leftOver = maxWidth - width;
      if(leftOver > 0 && greedyWidths > 0)
      {
        width = maxWidth;
        int[] splits = splitEvenly(leftOver, greedyWidths);
        int splitIndex = 0;
        for(Panel item : items)
        {
          if(hasGreedyWidth(item))
          {
//            PropPanel panel = (PropPanel) item;
            int greedyWidth = splits[splitIndex++];
//            panel.greediness.width = greedyWidth;

            item.setSize(item.getWidth() + greedyWidth, item.getHeight());
          }
        }
      }
    }

    private boolean hasGreedyWidth(Panel item)
    {
      return item instanceof PropPanel && item.getStyle().getCompiledWidth() instanceof GreedyDimensionValue;
    }

    private boolean hasGreedyHeight(Panel item)
    {
      return item instanceof PropPanel && item.getStyle().getCompiledHeight() instanceof GreedyDimensionValue;
    }

    public boolean isGreedy()
    {
      return greedyHeights > 0;
    }

    public void applyGreedyHeight(int extraHeight)
    {
      height += extraHeight;
      for(Panel item : items)
      {
        if(hasGreedyHeight(item))
        {
//          PropPanel panel = (PropPanel) item;
//          panel.greediness.height = Math.max(extraHeight, (height - panel.getHeight()));
//          item.setSize(item.getWidth(), height);
          item.setSize(item.getWidth(), height);
        }
      }
    }

    public void reCalculatedHeight()
    {
      height = 0;
      for(Panel item : items)
      {
        if(item.getHeight() > height)
          height = item.getHeight();
      }
    }
  }

}
TOP

Related Classes of limelight.ui.model.PropPanelLayout$Row

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.