/* * Copyright (c) 2003-2012 Fred Hutchinson Cancer Research Center * * 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 org.fhcrc.cpl.toolbox.gui.chart; import javax.swing.*; import java.awt.*; /** * Render a Venn diagram in a panel */ public class PanelWithVenn extends JPanel { int set1Size = 0; int set2Size = 0; int overlap = 0; public PanelWithVenn() { super(); } public PanelWithVenn(int set1Size, int set2Size, int overlap) { init(set1Size, set2Size, overlap); } protected void init(int set1Size, int set2Size, int overlap) { this.set1Size = set1Size; this.set2Size = set2Size; this.overlap = overlap; } /** * All the shape calculations are done directly in paint(). * None of this is exact. Eyeballing it, it looks pretty good. * There will be plenty of corner cases that look bad, though. * @param graphics */ public void paint(Graphics graphics) { super.paint(graphics); graphics.setColor(Color.WHITE); graphics.fillRect(0,0,getWidth(), getHeight()); graphics.setColor(Color.BLACK); double totalSize = set1Size + set2Size - overlap; int set1Diam = (int) (Math.sqrt(set1Size)); int set2Diam = (int) (Math.sqrt(set2Size)); double size1TotalRatio = (double) set1Size / (double) (set1Size + set2Size - overlap); double diam1TotalRatio = set1Diam / Math.sqrt(totalSize); double diam2TotalRatio = set2Diam / Math.sqrt(totalSize); double overlapTotalRatio = overlap / totalSize; double widthHeightRatio = (set1Size + set2Size - overlap) / Math.max(set1Size,set2Size); int totalWidth = (int) Math.round(0.9 * this.getWidth()); totalWidth = (int) Math.round(Math.min(totalWidth, widthHeightRatio * ((int) Math.round(0.9 * this.getHeight())))); int set1Diameter = (int) Math.round(diam1TotalRatio * totalWidth); int set2Diameter = (int) Math.round(diam2TotalRatio * totalWidth); int verticalCenter = getHeight() / 2; int horizCenter = (int) (((getWidth() * .5) + (getWidth() * size1TotalRatio)) / 2); int set1Top = verticalCenter - (set1Diameter / 2); int set2Top = verticalCenter - (set2Diameter / 2); int set1Left = horizCenter + (int)Math.round(overlapTotalRatio * totalWidth) - set1Diameter; int set2Left = horizCenter - (int)Math.round(overlapTotalRatio * totalWidth); graphics.drawOval(set1Left, set1Top, set1Diameter, set1Diameter); graphics.drawOval(set2Left, set2Top, set2Diameter, set2Diameter); graphics.setFont(new Font("dialog", Font.BOLD, (int) (.07 * totalWidth))); String set1OnlyText = ("" + (set1Size - overlap)); graphics.drawChars(set1OnlyText.toCharArray(), 0, set1OnlyText.length(), set1Left + 5, verticalCenter-2); String overlapText = ("" + (overlap)); graphics.drawChars(overlapText.toCharArray(), 0, overlapText.length(), horizCenter - 5, verticalCenter-2); String set2OnlyText = ("" + (set2Size - overlap)); graphics.drawChars(set2OnlyText.toCharArray(), 0, set2OnlyText.length(), set1Left + set1Diameter + 5, verticalCenter-2); } }