• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 AndroidPlot.com
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 
17 package com.androidplot.xy;
18 
19 import android.graphics.*;
20 import com.androidplot.ui.LayoutManager;
21 import com.androidplot.ui.SeriesAndFormatterList;
22 import com.androidplot.ui.SizeMetrics;
23 import com.androidplot.ui.TableModel;
24 import com.androidplot.ui.widget.Widget;
25 import com.androidplot.util.FontUtils;
26 
27 import java.util.*;
28 
29 public class XYLegendWidget extends Widget {
30 
31     /**
32      * This class is of no use outside of XYLegendWidget.  It's just used to alphabetically sort
33      * Region legend entries.
34      */
35     private static class RegionEntryComparator implements Comparator<Map.Entry<XYRegionFormatter, String>> {
36         @Override
compare(Map.Entry<XYRegionFormatter, String> o1, Map.Entry<XYRegionFormatter, String> o2)37         public int compare(Map.Entry<XYRegionFormatter, String> o1, Map.Entry<XYRegionFormatter, String> o2) {
38             return o1.getValue().compareTo(o2.getValue());
39         }
40     }
41 
42     private enum CellType {
43         SERIES,
44         REGION
45     }
46 
47     private XYPlot plot;
48     //private float iconWidth = 12;
49     private Paint textPaint;
50     private Paint iconBorderPaint;
51     private TableModel tableModel;
52     private boolean drawIconBackgroundEnabled = true;
53     private boolean drawIconBorderEnabled = true;
54 
55     private SizeMetrics iconSizeMetrics;
56     private static final RegionEntryComparator regionEntryComparator = new RegionEntryComparator();
57     //private RectF iconRect = new RectF(0, 0, ICON_WIDTH_DEFAULT, ICON_HEIGHT_DEFAULT);
58 
59     {
60         textPaint = new Paint();
61         textPaint.setColor(Color.LTGRAY);
62         textPaint.setAntiAlias(true);
63 
64         iconBorderPaint = new Paint();
65         iconBorderPaint.setStyle(Paint.Style.STROKE);
66         //regionEntryComparator = new RegionEntryComparator();
67     }
68 
XYLegendWidget(LayoutManager layoutManager, XYPlot plot, SizeMetrics widgetSizeMetrics, TableModel tableModel, SizeMetrics iconSizeMetrics)69     public XYLegendWidget(LayoutManager layoutManager, XYPlot plot,
70                           SizeMetrics widgetSizeMetrics,
71                           TableModel tableModel,
72                           SizeMetrics iconSizeMetrics) {
73         super(layoutManager, widgetSizeMetrics);
74         this.plot = plot;
75         setTableModel(tableModel);
76         this.iconSizeMetrics = iconSizeMetrics;
77     }
78 
setTableModel(TableModel tableModel)79     public synchronized void setTableModel(TableModel tableModel) {
80         this.tableModel = tableModel;
81     }
82 
getIconRect(RectF cellRect)83     private RectF getIconRect(RectF cellRect) {
84         float cellRectCenterY = cellRect.top + (cellRect.height()/2);
85         RectF iconRect = iconSizeMetrics.getRectF(cellRect);
86 
87         // center the icon rect vertically
88         float centeredIconOriginY = cellRectCenterY - (iconRect.height()/2);
89         iconRect.offsetTo(cellRect.left + 1, centeredIconOriginY);
90         return iconRect;
91     }
92 
getRectCenterY(RectF cellRect)93     private static float getRectCenterY(RectF cellRect) {
94         return cellRect.top + (cellRect.height()/2);
95     }
96 
beginDrawingCell(Canvas canvas, RectF iconRect)97     private void beginDrawingCell(Canvas canvas, RectF iconRect) {
98 
99         Paint bgPaint = plot.getGraphWidget().getGridBackgroundPaint();
100         if(drawIconBackgroundEnabled && bgPaint != null) {
101             canvas.drawRect(iconRect, bgPaint);
102         }
103     }
104 
finishDrawingCell(Canvas canvas, RectF cellRect, RectF iconRect, String text)105     private void finishDrawingCell(Canvas canvas, RectF cellRect, RectF iconRect, String text) {
106 
107         Paint bgPaint = plot.getGraphWidget().getGridBackgroundPaint();
108         if(drawIconBorderEnabled && bgPaint != null) {
109             iconBorderPaint.setColor(bgPaint.getColor());
110             canvas.drawRect(iconRect, iconBorderPaint);
111         }
112 
113         float centeredTextOriginY = getRectCenterY(cellRect) + (FontUtils.getFontHeight(textPaint)/2);
114                 canvas.drawText(text, iconRect.right + 2, centeredTextOriginY, textPaint);
115     }
116 
drawRegionLegendIcon(Canvas canvas, RectF rect, XYRegionFormatter formatter)117     protected void drawRegionLegendIcon(Canvas canvas, RectF rect, XYRegionFormatter formatter) {
118             canvas.drawRect(rect, formatter.getPaint());
119         }
120 
drawRegionLegendCell(Canvas canvas, XYRegionFormatter formatter, RectF cellRect, String text)121     private void drawRegionLegendCell(Canvas canvas, XYRegionFormatter formatter, RectF cellRect, String text) {
122         RectF iconRect = getIconRect(cellRect);
123         beginDrawingCell(canvas, iconRect);
124 
125                 drawRegionLegendIcon(
126                         canvas,
127                         iconRect,
128                         formatter
129                         );
130         finishDrawingCell(canvas, cellRect, iconRect, text);
131     }
132 
drawSeriesLegendCell(Canvas canvas, XYSeriesRenderer renderer, XYSeriesFormatter formatter, RectF cellRect, String seriesTitle)133     private void drawSeriesLegendCell(Canvas canvas, XYSeriesRenderer renderer, XYSeriesFormatter formatter, RectF cellRect, String seriesTitle) {
134         RectF iconRect = getIconRect(cellRect);
135         beginDrawingCell(canvas, iconRect);
136 
137                 renderer.drawSeriesLegendIcon(
138                         canvas,
139                         iconRect,
140                         formatter);
141         finishDrawingCell(canvas, cellRect, iconRect, seriesTitle);
142     }
143 
144     @Override
doOnDraw(Canvas canvas, RectF widgetRect)145     protected synchronized void doOnDraw(Canvas canvas, RectF widgetRect) {
146         // TODO: a good amount of iterating could be avoided if
147         // we create a temporary list of all the legend items up here.
148         if(plot.isEmpty()) {
149             return;
150         }
151 
152         //Hashtable<XYRegionFormatter, XYSeriesRenderer> regionRendererLookup = new Hashtable<XYRegionFormatter, XYSeriesRenderer>();
153 
154         // Keep an alphabetically sorted list of regions:
155         TreeSet<Map.Entry<XYRegionFormatter, String>> sortedRegions = new TreeSet<Map.Entry<XYRegionFormatter, String>>(new RegionEntryComparator());
156 
157         // Calculate the number of cells needed to draw the Legend:
158         int seriesCount = 0;
159         for(XYSeriesRenderer renderer : plot.getRendererList()) {
160 
161             SeriesAndFormatterList sfl = plot.getSeriesAndFormatterListForRenderer(renderer.getClass());
162             if(sfl != null) {
163                 seriesCount += sfl.size();
164             }
165 
166             // Figure out how many regions need to be added to the legend:
167             Hashtable<XYRegionFormatter, String> urf = renderer.getUniqueRegionFormatters();
168             /*for(XYRegionFormatter xyf : urf.keySet()) {
169                 regionRendererLookup.put(xyf, renderer);
170             }*/
171             sortedRegions.addAll(urf.entrySet());
172             //sortedRegions.addAll(renderer.getUniqueRegionFormatters().entrySet());
173         }
174         seriesCount += sortedRegions.size();
175 
176         // Create an iterator specially created to draw the number of cells we calculated:
177         Iterator<RectF> it = tableModel.getIterator(widgetRect, seriesCount);
178 
179         RectF cellRect;
180 
181         // draw each series legend item:
182         for(XYSeriesRenderer renderer : plot.getRendererList()) {
183             SeriesAndFormatterList<XYSeries,XYSeriesFormatter> sfl = plot.getSeriesAndFormatterListForRenderer(renderer.getClass());
184 
185             if (sfl != null) {
186                 // maxIndex is only used if it has been determined.
187                 // if it is 0 then it could not be determined.
188                 for (int i = 0; i < sfl.size() && it.hasNext(); i++) {
189                     cellRect = it.next();
190                     XYSeriesFormatter formatter = sfl.getFormatter(i);
191                     drawSeriesLegendCell(canvas, renderer, formatter, cellRect, sfl.getSeries(i).getTitle());
192                 }
193             }
194         }
195 
196         // draw each region legend item:
197         for(Map.Entry<XYRegionFormatter, String> entry : sortedRegions) {
198             if(!it.hasNext()) {
199                 break;
200             }
201             cellRect = it.next();
202             XYRegionFormatter formatter = entry.getKey();
203             drawRegionLegendCell(canvas, formatter, cellRect, entry.getValue());
204         }
205     }
206 
207 
getTextPaint()208     public Paint getTextPaint() {
209         return textPaint;
210     }
211 
setTextPaint(Paint textPaint)212     public void setTextPaint(Paint textPaint) {
213         this.textPaint = textPaint;
214     }
215 
isDrawIconBackgroundEnabled()216     public boolean isDrawIconBackgroundEnabled() {
217         return drawIconBackgroundEnabled;
218     }
219 
setDrawIconBackgroundEnabled(boolean drawIconBackgroundEnabled)220     public void setDrawIconBackgroundEnabled(boolean drawIconBackgroundEnabled) {
221         this.drawIconBackgroundEnabled = drawIconBackgroundEnabled;
222     }
223 
isDrawIconBorderEnabled()224     public boolean isDrawIconBorderEnabled() {
225         return drawIconBorderEnabled;
226     }
227 
setDrawIconBorderEnabled(boolean drawIconBorderEnabled)228     public void setDrawIconBorderEnabled(boolean drawIconBorderEnabled) {
229         this.drawIconBorderEnabled = drawIconBorderEnabled;
230     }
231 
getTableModel()232     public TableModel getTableModel() {
233         return tableModel;
234     }
235 
getIconSizeMetrics()236     public SizeMetrics getIconSizeMetrics() {
237         return iconSizeMetrics;
238     }
239 
240     /**
241      * Set the size of each legend's icon.  Note that when using relative sizing,
242      * the size is calculated against the countaining cell's size, not the plot's size.
243      * @param iconSizeMetrics
244      */
setIconSizeMetrics(SizeMetrics iconSizeMetrics)245     public void setIconSizeMetrics(SizeMetrics iconSizeMetrics) {
246         this.iconSizeMetrics = iconSizeMetrics;
247     }
248 }
249