| /* |
| * 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(); |
| } |
| } |