com.google.gwt.sample.mobilewebapp.client.desktop.PieChart.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.sample.mobilewebapp.client.desktop.PieChart.java

Source

/*
 * 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();
            }
        });
    }
}