001/*-------------------------------------------------------------------------+ 002| | 003| Copyright 2005-2011 The ConQAT Project | 004| | 005| Licensed under the Apache License, Version 2.0 (the "License"); | 006| you may not use this file except in compliance with the License. | 007| You may obtain a copy of the License at | 008| | 009| http://www.apache.org/licenses/LICENSE-2.0 | 010| | 011| Unless required by applicable law or agreed to in writing, software | 012| distributed under the License is distributed on an "AS IS" BASIS, | 013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 014| See the License for the specific language governing permissions and | 015| limitations under the License. | 016+-------------------------------------------------------------------------*/ 017package org.conqat.lib.commons.treemap; 018 019import java.awt.Color; 020import java.awt.Graphics2D; 021import java.awt.Rectangle; 022import java.awt.geom.Rectangle2D; 023 024import org.conqat.lib.commons.color.MultiColor; 025 026/** 027 * A very simple tree map renderer just drawing "flat" rectangles. 028 */ 029public class FlatTreeMapRenderer implements ITreeMapRenderer { 030 031 /** {@inheritDoc} */ 032 @Override 033 public <T> void renderTreeMap(ITreeMapNode<T> node, Graphics2D graphics) { 034 if (node.getChildren().isEmpty()) { 035 Rectangle2D rect = node.getLayoutRectangle(); 036 if (rect == null) { 037 return; 038 } 039 fillRect(graphics, rect, node.getColor()); 040 041 if (node.getDrawingPattern() != null) { 042 drawPattern(graphics, rect, node); 043 } 044 045 graphics.setColor(Color.BLACK); 046 graphics.draw(rect); 047 } else { 048 for (ITreeMapNode<T> child : node.getChildren()) { 049 renderTreeMap(child, graphics); 050 } 051 } 052 } 053 054 /** Fills the given rect with the given color. */ 055 private void fillRect(Graphics2D graphics, Rectangle2D rect, Color color) { 056 if (color instanceof MultiColor) { 057 fillRectMultiColor(graphics, rect, (MultiColor) color); 058 } else { 059 graphics.setColor(color); 060 graphics.fill(rect); 061 } 062 } 063 064 /** 065 * Fills the given rect with the given {@link MultiColor}. The colors are 066 * arranged in a striped pattern, which is arranged horizontally or vertically 067 * depending on the aspect ratio of the rectangle. 068 */ 069 private void fillRectMultiColor(Graphics2D graphics, Rectangle2D rect, MultiColor multiColor) { 070 double x = rect.getX(); 071 double y = rect.getY(); 072 double width = rect.getWidth(); 073 double height = rect.getHeight(); 074 075 double offset = 0; 076 for (int i = 0; i < multiColor.size(); ++i) { 077 Rectangle2D subrect; 078 double relativeFrequency = multiColor.getRelativeFrequency(i); 079 if (width > height) { 080 subrect = new Rectangle2D.Double(x + offset * width, y, width * relativeFrequency, height); 081 } else { 082 subrect = new Rectangle2D.Double(x, y + offset * height, width, height * relativeFrequency); 083 } 084 085 fillRect(graphics, subrect, multiColor.getColor(i)); 086 offset += relativeFrequency; 087 } 088 } 089 090 /** Draws the pattern. */ 091 private static <T> void drawPattern(Graphics2D graphics, Rectangle2D rect, ITreeMapNode<T> node) { 092 IDrawingPattern drawingPattern = node.getDrawingPattern(); 093 graphics.setColor(node.getPatternColor()); 094 for (int x = (int) rect.getMinX(); x <= rect.getMaxX(); ++x) { 095 for (int y = (int) rect.getMinY(); y <= rect.getMaxY(); ++y) { 096 if (drawingPattern.isForeground(x, y)) { 097 graphics.fill(new Rectangle(x, y, 1, 1)); 098 } 099 } 100 } 101 } 102 103}