Java tutorial
/* * Copyright 2009 Google Inc. * * 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.google.speedtracer.client.view; import com.google.gwt.dom.client.Element; import com.google.gwt.graphics.client.Color; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.resources.client.ImageResource.ImageOptions; import com.google.gwt.resources.client.ImageResource.RepeatStyle; import com.google.speedtracer.client.model.Visualization; import com.google.speedtracer.client.timeline.GraphModel; import com.google.speedtracer.client.timeline.GraphUiProps; import com.google.speedtracer.client.timeline.HighlightModel; import com.google.speedtracer.client.timeline.TimeLineGraph; import com.google.speedtracer.client.timeline.HighlightModel.HighlightEntry; import com.google.speedtracer.client.util.dom.DocumentExt; import com.google.speedtracer.client.visualizations.view.HintletIndicator; import java.util.Iterator; import java.util.List; /** * The main graph that renders the current zoom range for all visualizations. */ public class MainGraph extends TimeLineGraph { /** * Default Style for {@link TimeLineGraph}. */ public interface Css extends CssResource { String graphBase(); String graphCanvas(); String yAxisLabel(); } /** * Resources for {@link TimeLineGraph}. */ public interface Resources extends ClientBundle { @Source("resources/scale_line.png") @ImageOptions(repeatStyle = RepeatStyle.Both) ImageResource graphScaleLines(); @Source("resources/MainGraph.css") Css mainGraphCss(); @Source("resources/tablist-background.png") @ImageOptions(repeatStyle = RepeatStyle.Horizontal) ImageResource tabListBackground(); } // List of loaded visualizations. // This is a reference to the same collection owned by our parent timeline. // Mutations to this collection may have side effects. private final List<Visualization<?, ?>> visualizations; // Placeholder for the Y Axis label. private final Element yAxisScaleLabel; public MainGraph(MainTimeLine parent, List<Visualization<?, ?>> visualizations, Resources resources) { super(parent); getElement().setClassName(resources.mainGraphCss().graphBase()); canvas.getElement().setClassName(resources.mainGraphCss().graphCanvas()); this.visualizations = visualizations; yAxisScaleLabel = DocumentExt.get().createDivWithClassName(resources.mainGraphCss().yAxisLabel()); getElement().appendChild(yAxisScaleLabel); } @Override protected void paint() { double coordDelta = getCoordDelta(); double leftBound = getLeftBound(); double rightBound = getRightBound(); double domainDelta = getDomainDelta(); canvas.clear(); // We draw all the other ones with global opacity on to de-emphasize them. for (int i = 0, n = visualizations.size() - 1; i < n; i++) { Visualization<?, ?> viz = visualizations.get(i); // Render the background graphs with lower opacity. canvas.setGlobalAlpha(0.25); paintGraph(coordDelta, leftBound, rightBound, domainDelta, viz.getGraphUiProps(), viz.getModel().getGraphModel()); paintHighlights(coordDelta, leftBound, rightBound, domainDelta, viz.getModel().getHighlightModel()); } // Draw the last graph clearly with higher opacity. canvas.setGlobalAlpha(0.7); Visualization<?, ?> viz = visualizations.get(visualizations.size() - 1); paintGraph(coordDelta, leftBound, rightBound, domainDelta, viz.getGraphUiProps(), viz.getModel().getGraphModel()); canvas.setGlobalAlpha(0.9); paintHighlights(coordDelta, leftBound, rightBound, domainDelta, viz.getModel().getHighlightModel()); } protected void updateScaleLabel(double value, String yAxisUnit) { yAxisScaleLabel.setInnerHTML(" " + (int) value + yAxisUnit); } private void paintGraph(double coordDelta, double leftBound, double rightBound, double domainDelta, GraphUiProps graphUiProps, GraphModel model) { canvas.setStrokeStyle(graphUiProps.getStrokeColor()); canvas.setFillStyle(graphUiProps.getGraphColor()); double maxYValueInWindow = graphUiProps.getYAxisScaleCap(); double yAdjustment = COORD_Y_HEIGHT / graphUiProps.getActiveMaxYAxisValue(); canvas.setLineWidth(2); // Redraw timeline canvas.beginPath(); canvas.moveTo(0, COORD_Y_HEIGHT); for (int x = 0, p = getPlotPrecision(); x <= p; x++) { double xVal = x * coordDelta; double yVal = model.getRangeValue(leftBound + (domainDelta * x), domainDelta); // Log the max Y value drawn in this current window. // If we ever want a graph to plot negative Y values, we would need to // override this paint method anyways, but we should be aware that we // would want to log the Abs value here instead. maxYValueInWindow = (yVal > maxYValueInWindow) ? yVal : maxYValueInWindow; canvas.lineTo(xVal, COORD_Y_HEIGHT - (yVal * yAdjustment)); } canvas.lineTo(COORD_X_WIDTH, COORD_Y_HEIGHT); canvas.closePath(); canvas.fill(); // Draw Start and End regions double now = getTimeLine().getModel().getMostRecentDomainValue(); double timeToCoordConversion = getCoordsPerTime(); if (now < rightBound) { double end = (now - leftBound) * timeToCoordConversion; canvas.setFillStyle(Color.LIGHT_GREY); canvas.fillRect(end, 0, COORD_X_WIDTH - end, COORD_Y_HEIGHT); if (now > leftBound) { canvas.setFillStyle(Color.GREEN); canvas.fillRect(end, 0, 2, COORD_Y_HEIGHT); } } if (leftBound < 0) { canvas.setFillStyle(Color.RED); canvas.fillRect((-leftBound * timeToCoordConversion) - 4, 0, 2, COORD_Y_HEIGHT); } // Remember the active max value for this graph graphUiProps.setActiveMaxYAxisValue(maxYValueInWindow); } /** * Highlights indicate special data at these points (e.g. some hintlets * present). * * @param highlights */ private void paintHighlights(double coordDelta, double leftBound, double rightBound, double domainDelta, HighlightModel highlights) { // If there is no highlight data, then bail. if (highlights == null || canvas == null) { return; } double coordsPerDomain = COORD_X_WIDTH / (rightBound - leftBound); Iterator<HighlightEntry> it = highlights.getRangeValues(leftBound, rightBound, domainDelta); while (it.hasNext()) { HighlightEntry highlightEntry = it.next(); double xVal = (highlightEntry.getKey() - leftBound) * coordsPerDomain; int val = highlightEntry.getValue(); canvas.beginPath(); canvas.setStrokeStyle(HintletIndicator.getSeverityColor(val)); canvas.setLineWidth(2); canvas.moveTo(xVal, COORD_Y_HEIGHT); canvas.lineTo(xVal, COORD_Y_HEIGHT * .8); canvas.stroke(); } } }