blob: a2982780d463f3d674ec3b494cdb84a12c645aa6 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.uiDesigner.designSurface;
import com.intellij.uiDesigner.radComponents.RadContainer;
import com.intellij.uiDesigner.radComponents.RadComponent;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.reference.SoftReference;
import com.intellij.openapi.wm.ex.WindowManagerEx;
import java.awt.*;
/**
* @author yole
*/
public class CachedGridImage {
private static final Object CACHED_GRID_IMAGE_KEY = new Object();
private static final float[] ourDashes = new float[] { 3.0f, 1.0f };
private final Image myImage;
private int[] myHorzGridLines;
private int[] myVertGridLines;
private int[] myRows;
private int[] myRowSpans;
private int[] myCols;
private int[] myColSpans;
private CachedGridImage(final RadContainer container) {
final GraphicsConfiguration graphicsConfiguration =
WindowManagerEx.getInstanceEx().getFrame(container.getProject()).getGraphicsConfiguration();
if (container.getWidth() * container.getHeight() < 4096*4096) {
myImage = graphicsConfiguration.createCompatibleImage(container.getWidth(), container.getHeight(),
Transparency.BITMASK);
update(container);
}
else {
// create fake image for insanely large containers
myImage = graphicsConfiguration.createCompatibleImage(16, 16, Transparency.BITMASK);
}
}
private void update(final RadContainer container) {
if (container.getWidth() * container.getHeight() >= 4096*4096) return;
int count = container.getComponentCount();
int[] rows = new int[count];
int[] rowSpans = new int[count];
int[] cols = new int[count];
int[] colSpans = new int[count];
for(int i=0; i<count; i++) {
GridConstraints c = container.getComponent(i).getConstraints();
rows [i] = c.getRow();
rowSpans [i] = c.getRowSpan();
cols [i] = c.getColumn();
colSpans [i] = c.getColSpan();
}
int[] horzGridLines = container.getGridLayoutManager().getHorizontalGridLines(container);
int[] vertGridLines = container.getGridLayoutManager().getVerticalGridLines(container);
if (!arraysEqual(horzGridLines, myHorzGridLines) ||
!arraysEqual(vertGridLines, myVertGridLines) ||
!arraysEqual(rows, myRows) ||
!arraysEqual(rowSpans, myRowSpans) ||
!arraysEqual(cols, myCols) ||
!arraysEqual(colSpans, myColSpans)) {
myHorzGridLines = horzGridLines;
myVertGridLines = vertGridLines;
myRows = rows;
myRowSpans = rowSpans;
myCols = cols;
myColSpans = colSpans;
repaint(container);
}
}
private void repaint(final RadContainer container) {
final int width = container.getWidth();
final int height = container.getHeight();
if (width * height >= 4096*4096) return;
Graphics2D g2d = (Graphics2D) myImage.getGraphics();
try {
g2d.setComposite(AlphaComposite.Clear);
g2d.fillRect(0, 0, width, height);
g2d.setComposite(AlphaComposite.Src);
if (container.isSelected()) {
g2d.setColor(Painter.SELECTED_GRID_COLOR);
}
else {
g2d.setColor(Painter.NON_SELECTED_GRID_COLOR);
}
g2d.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1.0f, ourDashes, 0.0f));
if (myHorzGridLines.length > 0) {
int lastLine = (container.getDelegee().getHeight() - myHorzGridLines [myHorzGridLines.length-1] > 4)
? myHorzGridLines.length
: myHorzGridLines.length-1;
for (int i = 1; i < lastLine; i++) {
final int y = myHorzGridLines [i];
g2d.drawLine(0, y, width, y);
}
}
if (myVertGridLines.length > 0) {
// Vertical lines
int lastLine = (container.getDelegee().getWidth() - myVertGridLines [myVertGridLines.length-1] > 4)
? myVertGridLines.length
: myVertGridLines.length-1;
for (int i = 1; i < lastLine; i++) {
final int x = myVertGridLines [i];
g2d.drawLine(x, 0, x, height);
}
}
g2d.setComposite(AlphaComposite.Clear);
g2d.setStroke(new BasicStroke(1.0f));
for(RadComponent childComponent: container.getComponents()) {
final GridConstraints constraints = childComponent.getConstraints();
if (constraints.getColSpan() > 1) {
for(int col = constraints.getColumn()+1; col < constraints.getColumn() + constraints.getColSpan(); col++) {
drawVertGridLine(g2d, col, constraints.getRow(), constraints.getRowSpan());
}
}
if (constraints.getRowSpan() > 1) {
for(int row = constraints.getRow()+1; row < constraints.getRow() + constraints.getRowSpan(); row++) {
drawHorzGridLine(g2d, row, constraints.getColumn(), constraints.getColSpan());
}
}
}
}
finally {
g2d.dispose();
}
}
private void drawVertGridLine(final Graphics2D g2d, final int col, final int row, final int rowSpan) {
// protect against invalid constraints
if (col < 0 || col >= myVertGridLines.length || row < 0 || row+rowSpan >= myHorzGridLines.length) return;
g2d.drawLine(myVertGridLines [col],
myHorzGridLines [row]+4,
myVertGridLines [col],
myHorzGridLines [row+rowSpan]-4);
}
private void drawHorzGridLine(final Graphics2D g2d, final int row, final int col, final int colSpan) {
// protect against invalid constraints
if (col < 0 || col+colSpan >= myVertGridLines.length || row < 0 || row >= myHorzGridLines.length) return;
g2d.drawLine(myVertGridLines [col]+4,
myHorzGridLines [row],
myVertGridLines [col + colSpan]-4,
myHorzGridLines [row]);
}
private static boolean arraysEqual(final int[] newArray, final int[] oldArray) {
if (oldArray == null || newArray.length != oldArray.length) {
return false;
}
for(int i=0; i<oldArray.length; i++) {
if (newArray [i] != oldArray [i]) {
return false;
}
}
return true;
}
private boolean sizeEquals(final RadContainer container) {
return myImage.getWidth(null) == container.getWidth() &&
myImage.getHeight(null) == container.getHeight();
}
private Image getImage() {
return myImage;
}
public static Image getGridImage(final RadContainer container) {
//noinspection unchecked
SoftReference<CachedGridImage> imageRef = (SoftReference<CachedGridImage>) container.getDelegee().getClientProperty(CACHED_GRID_IMAGE_KEY);
CachedGridImage gridImage = SoftReference.dereference(imageRef);
if (gridImage != null && gridImage.sizeEquals(container)) {
gridImage.update(container);
}
else {
gridImage = new CachedGridImage(container);
container.getDelegee().putClientProperty(CACHED_GRID_IMAGE_KEY,
new SoftReference<CachedGridImage>(gridImage));
}
return gridImage.getImage();
}
}