001/* =========================================================== 002 * Orson Charts : a 3D chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C)opyright 2013-2016, by Object Refinery Limited. All rights reserved. 006 * 007 * http://www.object-refinery.com/orsoncharts/index.html 008 * 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as published by 011 * the Free Software Foundation, either version 3 of the License, or 012 * (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with this program. If not, see <http://www.gnu.org/licenses/>. 021 * 022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 023 * Other names may be trademarks of their respective owners.] 024 * 025 * If you do not wish to be bound by the terms of the GPL, an alternative 026 * commercial license can be purchased. For details, please see visit the 027 * Orson Charts home page: 028 * 029 * http://www.object-refinery.com/orsoncharts/index.html 030 * 031 */ 032 033package com.orsoncharts; 034 035import java.awt.Graphics2D; 036import java.awt.geom.Rectangle2D; 037import java.util.HashMap; 038import java.util.Map; 039import com.orsoncharts.graphics3d.RenderedElement; 040import com.orsoncharts.graphics3d.RenderingInfo; 041import com.orsoncharts.interaction.InteractiveElementType; 042import com.orsoncharts.table.TableElement; 043import com.orsoncharts.table.TableElementOnDraw; 044 045/** 046 * An 'onDraw' handler that handles two aspects related to chart interactivity: 047 * (1) it adds a {@link RenderedElement} instance to the {@link RenderingInfo} 048 * for each element in the chart that requires it, and (2) it adds element 049 * hinting to the {@code Graphics2D} output (how this is handled by the 050 * {@code Graphics2D} instance is implementation dependent). 051 * 052 * @since 1.3 053 */ 054public class OnDrawHandler implements TableElementOnDraw { 055 056 /** The rendering info the be populated (if not null). */ 057 private RenderingInfo info; 058 059 /** A flag indicating whether or not element hinting is added. */ 060 boolean elementHinting; 061 062 /** 063 * Creates a new handler. 064 * 065 * @param info the rendering info to be populated ({@code null} 066 * permitted). 067 * @param elementHinting a flag that controls whether or not element 068 * hinting is performed. 069 */ 070 public OnDrawHandler(RenderingInfo info, boolean elementHinting) { 071 this.info = info; 072 this.elementHinting = elementHinting; 073 } 074 075 @Override 076 public void beforeDraw(TableElement element, Graphics2D g2, 077 Rectangle2D bounds) { 078 079 InteractiveElementType t = (InteractiveElementType) 080 element.getProperty(TableElement.CLASS); 081 082 // handle rendering info 083 if (t != null && info != null) { 084 switch (t) { 085 case TITLE: 086 case SUBTITLE: 087 RenderedElement re = new RenderedElement(t, bounds); 088 this.info.addElement(re); 089 break; 090 091 case LEGEND_ITEM: 092 RenderedElement legendItemRE = new RenderedElement( 093 InteractiveElementType.LEGEND_ITEM, bounds); 094 legendItemRE.setProperty(Chart3D.SERIES_KEY, 095 element.getProperty(Chart3D.SERIES_KEY)); 096 this.info.addElement(legendItemRE); 097 break; 098 default: 099 throw new RuntimeException(); 100 } 101 } 102 103 // handle hinting 104 if (t != null && this.elementHinting) { 105 Map m = new HashMap<String, String>(); 106 switch (t) { 107 case TITLE: 108 m.put("ref", "{\"type\": \"title\"}"); 109 g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); 110 break; 111 case SUBTITLE: 112 m.put("ref", "{\"type\": \"subtitle\"}"); 113 g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); 114 break; 115 case LEGEND_ITEM: 116 m.put("ref", generateLegendItemRef(element)); 117 g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); 118 break; 119 default: 120 throw new RuntimeException(); 121 } 122 } 123 } 124 125 @Override 126 public void afterDraw(TableElement element, Graphics2D g2, 127 Rectangle2D bounds) { 128 if (!this.elementHinting) { 129 return; 130 } 131 InteractiveElementType t = (InteractiveElementType) 132 element.getProperty(TableElement.CLASS); 133 if (t == null) { 134 return; 135 } 136 switch (t) { 137 case TITLE: 138 case SUBTITLE: 139 case LEGEND_ITEM: 140 g2.setRenderingHint(Chart3DHints.KEY_END_ELEMENT, Boolean.TRUE); 141 break; 142 default: 143 throw new RuntimeException("Seeing type " + t); 144 } 145 } 146 147 private String generateLegendItemRef(TableElement element) { 148 Object key = element.getProperty(Chart3D.SERIES_KEY); 149 return "{\"type\": \"legendItem\", \"seriesKey\": \"" + key.toString() 150 + "\"}"; 151 } 152}