blob: 679cd75907ca6d89158f649207b66d85706758d8 [file] [log] [blame]
/*
* Copyright 2011 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.gwt.sample.mobilewebapp.client.desktop;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.FillStrokeStyle;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.PartialSupport;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.RequiresResize;
import java.util.ArrayList;
import java.util.List;
/**
* A pie chart representation of data.
*/
@PartialSupport
public class PieChart extends Composite implements RequiresResize {
/**
* Information about a slice of pie.
*/
private static class Slice {
private final double weight;
private final FillStrokeStyle fill;
public Slice(double weight, FillStrokeStyle fill) {
this.weight = weight;
this.fill = fill;
}
}
/**
* The number of radians in a circle.
*/
private static final double RADIANS_IN_CIRCLE = 2 * Math.PI;
/**
* Return a new {@link Canvas} if supported, and null otherwise.
*
* @return a new {@link Canvas} if supported, and null otherwise
*/
public static PieChart createIfSupported() {
return isSupported() ? new PieChart() : null;
}
/**
* Runtime check for whether the canvas element is supported in this browser.
*
* @return whether the canvas element is supported
*/
public static boolean isSupported() {
return Canvas.isSupported();
}
private final Canvas canvas;
private final List<Slice> slices = new ArrayList<Slice>();
/**
* Create using factory methods.
*/
private PieChart() {
canvas = Canvas.createIfSupported();
canvas.setCoordinateSpaceHeight(300);
canvas.setCoordinateSpaceWidth(300);
initWidget(canvas);
}
/**
* Add a slice to the chart.
*
* @param weight the weight of the slice
* @param fill the fill color
*/
public void addSlice(double weight, FillStrokeStyle fill) {
slices.add(new Slice(weight, fill));
}
/**
* Clear all slices.
*/
public void clearSlices() {
slices.clear();
}
public void onResize() {
redraw();
}
/**
* Redraw the pie chart.
*/
public void redraw() {
if (!isAttached()) {
return;
}
// Get the dimensions of the chart.
int width = canvas.getCoordinateSpaceWidth();
int height = canvas.getCoordinateSpaceHeight();
double radius = Math.min(width, height) / 2.0;
double cx = width / 2.0;
double cy = height / 2.0;
// Clear the context.
Context2d context = canvas.getContext2d();
context.clearRect(0, 0, width, height);
// Get the total weight of all slices.
double totalWeight = 0;
for (Slice slice : slices) {
totalWeight += slice.weight;
}
// Draw the slices.
double startAngle = -0.5 * Math.PI;
for (Slice slice : slices) {
double weight = slice.weight / totalWeight;
double endAngle = startAngle + (weight * RADIANS_IN_CIRCLE);
context.setFillStyle(slice.fill);
context.beginPath();
context.moveTo(cx, cy);
context.arc(cx, cy, radius, startAngle, endAngle);
context.fill();
startAngle = endAngle;
}
}
@Override
protected void onLoad() {
super.onLoad();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute() {
redraw();
}
});
}
}