Package com.cburch.logisim.gui.generic

Source Code of com.cburch.logisim.gui.generic.GridPainter$Listener

/* Copyright (c) 2010, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.logisim.gui.generic;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.MemoryImageSource;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Arrays;

public class GridPainter {
  public static final String ZOOM_PROPERTY = "zoom";
  public static final String SHOW_GRID_PROPERTY = "showgrid";
 
  private static final int GRID_DOT_COLOR = 0xFF777777;
  private static final int GRID_DOT_ZOOMED_COLOR = 0xFFCCCCCC;

  private static final Color GRID_ZOOMED_OUT_COLOR = new Color(210, 210, 210);
 
  private class Listener implements PropertyChangeListener {
    public void propertyChange(PropertyChangeEvent event) {
      String prop = event.getPropertyName();
      Object val = event.getNewValue();
      if (prop.equals(ZoomModel.ZOOM)) {
        setZoomFactor(((Double) val).doubleValue());
        destination.repaint();
      } else if (prop.equals(ZoomModel.SHOW_GRID)) {
        setShowGrid(((Boolean) val).booleanValue());
        destination.repaint();
      }
    }
  }

  private Component destination;
  private PropertyChangeSupport support;
  private Listener listener;
  private ZoomModel zoomModel;
  private boolean showGrid;
  private int gridSize;
  private double zoomFactor;
  private Image gridImage;
  private int gridImageWidth;
 
  public GridPainter(Component destination) {
    this.destination = destination;
    support = new PropertyChangeSupport(this);
    showGrid = true;
    gridSize = 10;
    zoomFactor = 1.0;
    updateGridImage(gridSize, zoomFactor);
  }
 
  public void addPropertyChangeListener(String prop,
      PropertyChangeListener listener) {
    support.addPropertyChangeListener(prop, listener);
  }
 
  public void removePropertyChangeListener(String prop,
      PropertyChangeListener listener) {
    support.removePropertyChangeListener(prop, listener);
  }
 
  public boolean getShowGrid() {
    return showGrid;
  }
 
  public void setShowGrid(boolean value) {
    if (showGrid != value) {
      showGrid = value;
      support.firePropertyChange(SHOW_GRID_PROPERTY, !value, value);
    }
  }
 
  public double getZoomFactor() {
    return zoomFactor;
  }
 
  public void setZoomFactor(double value) {
    double oldValue = zoomFactor;
    if (oldValue != value) {
      zoomFactor = value;
      updateGridImage(gridSize, value);
      support.firePropertyChange(ZOOM_PROPERTY, Double.valueOf(oldValue),
          Double.valueOf(value));
    }
  }
 
  public ZoomModel getZoomModel() {
    return zoomModel;
  }
 
  public void setZoomModel(ZoomModel model) {
    ZoomModel old = zoomModel;
    if (model != old) {
      if (listener == null) {
        listener = new Listener();
      }
      if (old != null) {
        old.removePropertyChangeListener(ZoomModel.ZOOM, listener);
        old.removePropertyChangeListener(ZoomModel.SHOW_GRID, listener);
      }
      zoomModel = model;
      if (model != null) {
        model.addPropertyChangeListener(ZoomModel.ZOOM, listener);
        model.addPropertyChangeListener(ZoomModel.SHOW_GRID, listener);
      }
      setShowGrid(model.getShowGrid());
      setZoomFactor(model.getZoomFactor());
      destination.repaint();
    }
  }

  public void paintGrid(Graphics g) {
    Rectangle clip = g.getClipBounds();
    Component dest = destination;
    double zoom = zoomFactor;
    int size = gridSize;

    if (!showGrid) return;

    Image img = gridImage;
    int w = gridImageWidth;
    if (img == null) {
      paintGridOld(g, size, zoom, clip);
      return;
    }
    int x0 = (clip.x / w) * w; // round down to multiple of w
    int y0 = (clip.y / w) * w;
    for (int x = 0; x < clip.width + w; x += w) {
      for (int y = 0; y < clip.height + w; y += w) {
        g.drawImage(img, x0 + x, y0 + y, dest);
      }
    }
  }
 
  private void paintGridOld(Graphics g, int size, double f, Rectangle clip) {
    g.setColor(Color.GRAY);
    if (f == 1.0) {
      int start_x = ((clip.x + 9) / size) * size;
      int start_y = ((clip.y + 9) / size) * size;
      for (int x = 0; x < clip.width; x += size) {
        for (int y = 0; y < clip.height; y += size) {
          g.fillRect(start_x + x, start_y + y, 1, 1);
        }
      }
    } else {
      /* Kevin Walsh of Cornell suggested the code below instead. */
      int x0 = size * (int) Math.ceil(clip.x / f / size);
      int x1 = x0 + (int) (clip.width / f);
      int y0 = size * (int) Math.ceil(clip.y / f / size);
      int y1 = y0 + (int) (clip.height / f);
      if (f <= 0.5) g.setColor(GRID_ZOOMED_OUT_COLOR);
      for (double x = x0; x < x1; x += size) {
        for (double y = y0; y < y1; y += size) {
          int sx = (int) Math.round(f * x);
          int sy = (int) Math.round(f * y);
          g.fillRect(sx, sy, 1, 1);
        }
      }
      if (f <= 0.5) { // make every 5th pixel darker
        int size5 = 5 * size;
        g.setColor(Color.GRAY);
        x0 = size5 * (int) Math.ceil(clip.x / f / size5);
        y0 = size5 * (int) Math.ceil(clip.y / f / size5);
        for (double x = x0; x < x1; x += size5) {
          for (double y = y0; y < y1; y += size5) {
            int sx = (int) Math.round(f * x);
            int sy = (int) Math.round(f * y);
            g.fillRect(sx, sy, 1, 1);
          }
        }
      }              
     
      /* Original code by Carl Burch
      int x0 = 10 * (int) Math.ceil(clip.x / f / 10);
      int x1 = x0 + (int)(clip.width / f);
      int y0 = 10 * (int) Math.ceil(clip.y / f / 10);
      int y1 = y0 + (int) (clip.height / f);
      int s = f > 0.5 ? 1 : f > 0.25 ? 2 : 3;
      int i0 = s - ((x0 + 10*s - 1) % (s * 10)) / 10 - 1;
      int j0 = s - ((y1 + 10*s - 1) % (s * 10)) / 10 - 1;
      for (int i = 0; i < s; i++) {
        for (int x = x0+i*10; x < x1; x += s*10) {
          for (int j = 0; j < s; j++) {
            g.setColor(i == i0 && j == j0 ? Color.gray : GRID_ZOOMED_OUT_COLOR);
            for (int y = y0+j*10; y < y1; y += s*10) {
              int sx = (int) Math.round(f * x);
              int sy = (int) Math.round(f * y);
              g.fillRect(sx, sy, 1, 1);
            }
          }
        }
      }
      */
    }
  }

  //
  // creating the grid image
  //
  private void updateGridImage(int size, double f) {
    double ww = f * size * 5;
    while (2 * ww < 150) ww *= 2;
    int w = (int) Math.round(ww);
    int[] pix = new int[w * w];
    Arrays.fill(pix, 0xFFFFFF);

    if (f == 1.0) {
      int lineStep = size * w;
      for (int j = 0; j < pix.length; j += lineStep) {
        for (int i = 0; i < w; i += size) {
          pix[i + j] = GRID_DOT_COLOR;
        }
      }
    } else {
      int off0 = 0;
      int off1 = 1;
      if (f >= 2.0) { // we'll draw several pixels for each grid point
        int num = (int) (f + 0.001);
        off0 = -(num / 2);
        off1 = off0 + num;
      }
     
      int dotColor = f <= 0.5 ? GRID_DOT_ZOOMED_COLOR : GRID_DOT_COLOR;
      for (int j = 0; true; j += size) {
        int y = (int) Math.round(f * j);
        if (y + off0 >= w) break;
       
        for (int yo = y + off0; yo < y + off1; yo++) {
          if (yo >= 0 && yo < w) {
            int base = yo * w;
            for (int i = 0; true; i += size) {
              int x = (int) Math.round(f * i);
              if (x + off0 >= w) break;
              for (int xo = x + off0; xo < x + off1; xo++) {
                if (xo >= 0 && xo < w) {
                  pix[base + xo] = dotColor;
                }
              }
            }
          }
        }
      }
      if (f <= 0.5) { // repaint over every 5th pixel so it is darker
        int size5 = size * 5;
        for (int j = 0; true; j += size5) {
          int y = (int) Math.round(f * j);
          if (y >= w) break;
          y *= w;
         
          for (int i = 0; true; i += size5) {
            int x = (int) Math.round(f * i);
            if (x >= w) break;
            pix[y + x] = GRID_DOT_COLOR;
          }
        }
      }
    }
    gridImage = destination.createImage(new MemoryImageSource(w, w, pix, 0, w));
    gridImageWidth = w;
  }
}
TOP

Related Classes of com.cburch.logisim.gui.generic.GridPainter$Listener

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.