All Downloads are FREE. Search and download functionalities are using the official Maven repository.

timeBench.util.DemoEnvironmentFactory Maven / Gradle / Ivy

Go to download

TimeBench, a flexible, easy-to-use, and reusable software library written in Java that provides foundational data structures and algorithms for time- oriented data in Visual Analytics.

The newest version!
package timeBench.util;

import java.awt.BorderLayout;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;

import prefuse.Display;
import prefuse.controls.PanControl;
import prefuse.controls.ZoomControl;
import prefuse.util.ColorLib;
import prefuse.util.display.PaintListener;
import prefuse.util.ui.JRangeSlider;
import timeBench.action.layout.timescale.AdvancedTimeScale;
import timeBench.action.layout.timescale.FisheyeTimeScale;
import timeBench.action.layout.timescale.RangeAdapter;
import timeBench.calendar.Calendar;
import timeBench.calendar.CalendarManager;
import timeBench.calendar.JavaDateCalendarManager;
import timeBench.controls.RangePanControl;
import timeBench.controls.RangeZoomControl;
import timeBench.data.TemporalDataException;
import timeBench.data.TemporalDataset;
import timeBench.data.TemporalElement;
import timeBench.data.TemporalObject;
import timeBench.ui.FisheyeSlider;
import timeBench.ui.MouseTracker;
import timeBench.ui.TimeAxisDisplay;
import timeBench.ui.TimeScaleHeader;
import timeBench.ui.TimeScalePainter;
import timeBench.ui.TimeScaleStatusBar;
import timeBench.ui.actions.PanAction;
import timeBench.ui.actions.RangePanAction;
import timeBench.ui.actions.RangeZoomAction;
import timeBench.ui.actions.ZoomAction;

public class DemoEnvironmentFactory {

    public static final String ACTION_INIT = "init";
    public static final String ACTION_UPDATE = "update";

    /**
     * 10-class Paired qualitative color scheme from colorbrewer2.org
     */
    public static int[] pairedQualitative = { ColorLib.rgb(166, 206, 227),
            ColorLib.rgb(31, 120, 180), ColorLib.rgb(178, 223, 138),
            ColorLib.rgb(51, 160, 44), ColorLib.rgb(251, 154, 153),
            ColorLib.rgb(227, 26, 28), ColorLib.rgb(253, 191, 111),
            ColorLib.rgb(255, 127, 0), ColorLib.rgb(202, 178, 214),
            ColorLib.rgb(106, 61, 154) };

    public static int[] set3Qualitative = {
    	ColorLib.rgb(141, 211, 199),	//  0	light turqueoise
    	ColorLib.rgb(255, 255, 179),	//  1	light yellow    
    	ColorLib.rgb(190, 186, 218),	//  2	light purple
        ColorLib.rgb(251, 128, 114),	//  3	light red	
        ColorLib.rgb(128, 177, 211),	//	4	light blue
        ColorLib.rgb(253, 180, 98),		//	5	light orange
        ColorLib.rgb(179, 222, 105),	//	6	light green
        ColorLib.rgb(252, 205, 229) };	//	7	light pink

    public static int[] set12Qualitative = {
    	ColorLib.rgb(141, 211, 199),
    	ColorLib.rgb(255, 255, 179),	//  1	light yellow    
    	ColorLib.rgb(190, 186, 218),	//  2	light purple
        ColorLib.rgb(251, 128, 114),	//  3	light red	
        ColorLib.rgb(128, 177, 211),	//	4	light blue
        ColorLib.rgb(253, 180, 98),		//	5	light orange
        ColorLib.rgb(179, 222, 105),	//	6	light green
        ColorLib.rgb(252, 205, 229),	//	7	light pink
        ColorLib.rgb(217, 217, 217),
        ColorLib.rgb(188, 128, 189),
        ColorLib.rgb(204, 235, 197),
        ColorLib.rgb(255, 237, 111)};
    
    public static int[] set1Qualitative = { ColorLib.rgb(228, 26, 28),
            ColorLib.rgb(55, 126, 184), ColorLib.rgb(77, 175, 74),
            ColorLib.rgb(152, 78, 163), ColorLib.rgb(255, 127, 0),
            ColorLib.rgb(255, 255, 51), ColorLib.rgb(166, 86, 40),
            ColorLib.rgb(247, 129, 191), ColorLib.rgb(153, 153, 153) };

    
    /**
     * demo name to be displayed in the window title
     */
    private String name;

    /**
     * If the {@link RangeAdapter} is null, the panning in time will be
     * unconstrained and there will be no range slider.
     */
    // RangeAdapter rangeAdapter = null;

    /**
     * Time scale of the main display. This is the "detail" time scale in an
     * overview and detail setting.
     */
    // AdvancedTimeScale timeScale;

    /**
     * pan time with a {@link JScrollBar} instead of a {@link JRangeSlider}. The
     * scroll bar is less powerful, but more familiar to novice users.
     */
    private boolean useScrollbar = false;

    private boolean paintWeekends = true;

    public DemoEnvironmentFactory(String name) {
        super();
        this.name = name;
    }

    public void show(TimeAxisDisplay display, RangeAdapter rangeAdapter) {
        show(display, rangeAdapter, rangeAdapter.getActualScale(),true);
    }
    public void show(TimeAxisDisplay display, RangeAdapter rangeAdapter,boolean showToolbar) {
        show(display, rangeAdapter, rangeAdapter.getActualScale(),showToolbar);
    }

    public void show(TimeAxisDisplay display, AdvancedTimeScale timeScale,boolean showToolbar) {
        show(display, null, timeScale,showToolbar);
    }

    private void show(TimeAxisDisplay display, RangeAdapter rangeAdapter,
            AdvancedTimeScale timeScale,boolean showToolbar) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle("TimeBench | " + name);

        prepareTimeDisplay(display, rangeAdapter, timeScale);
        frame.getContentPane()
                .add(prepareGui(display, rangeAdapter, timeScale));
        if(showToolbar) {
        	frame.getContentPane()
                	.add(prepareToolbar(SwingConstants.VERTICAL, rangeAdapter,
                			timeScale), BorderLayout.EAST);
        }

        frame.pack();
        frame.setVisible(true);
    }

    private void prepareTimeDisplay(final TimeAxisDisplay display,
            final RangeAdapter rangeAdapter, final AdvancedTimeScale timeScale) {
        display.setTimeScale(timeScale);
        if (display.getBorder() == null) {
            display.setBorder(BorderFactory.createEmptyBorder(7, 0, 7, 0));
        }

        final TimeScalePainter timeScalePainter = new TimeScalePainter(display);
        timeScalePainter.setTimeScale(timeScale);
        timeScalePainter.setPaintWeekend(this.paintWeekends);

        final MouseTracker mouseTracker = new MouseTracker(display, timeScale);

        display.addPaintListener(new PaintListener() {
            public void postPaint(Display d, Graphics2D g) {
                mouseTracker.paintTimeAtPosition(g);
            }

            public void prePaint(Display d, Graphics2D g) {
                g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                        RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

                g.transform(d.getInverseTransform());
                timeScalePainter.paint(g);
                g.transform(d.getTransform());
            }
        });

        // react on window resize
        display.addComponentListener(new ComponentAdapter() {
            public void componentResized(ComponentEvent e) {
                if (rangeAdapter != null) {
                    rangeAdapter.getFullScale().setDisplayWidth(display.getWidth() - 1);
                }
                timeScale.setDisplayWidth(display.getWidth() - 1);
            }
        });

        // enable pan/zoom on mouse dragging
        if (rangeAdapter != null) {
            display.addControlListener(new RangePanControl(rangeAdapter));
            display.addControlListener(new RangeZoomControl(rangeAdapter));
        } else {
            display.addControlListener(new PanControl());
            display.addControlListener(new ZoomControl());
        }

        display.getVisualization().run(DemoEnvironmentFactory.ACTION_INIT);
    }

    private JComponent prepareGui(JComponent display,
            RangeAdapter rangeAdapter, AdvancedTimeScale timeScale) {
        JPanel gui = new JPanel(new BorderLayout());
        gui.add(new TimeScaleHeader(timeScale), BorderLayout.NORTH);

        gui.add(display, BorderLayout.CENTER);

        Box south = Box.createVerticalBox();
        if (rangeAdapter != null) {
            if (useScrollbar) {
                JScrollBar scroll = new JScrollBar(JScrollBar.HORIZONTAL);
                scroll.setModel(rangeAdapter);
                south.add(scroll);
            } else {
                south.add(new JRangeSlider(rangeAdapter,
                        JRangeSlider.HORIZONTAL,
                        JRangeSlider.LEFTRIGHT_TOPBOTTOM));
            }
            // TODO bug: the overview time scale shows a twice as long period  
            south.add(new TimeScaleHeader(rangeAdapter.getFullScale()));
        } else {
            TimeScaleStatusBar statusBar = new TimeScaleStatusBar(timeScale);
            // Mac-Workaround: GrowBox hides Label
            statusBar.add(Box.createHorizontalStrut(20));
            south.add(statusBar);
        }
        gui.add(south, BorderLayout.SOUTH);

        return gui;
    }

    private JToolBar prepareToolbar(int orientation, RangeAdapter rangeAdapter,
            AdvancedTimeScale timeScale) {
        JToolBar toolbar = new JToolBar();
        toolbar.setOrientation(orientation);

        if (rangeAdapter != null) {
            toolbar.add(new RangeZoomAction(rangeAdapter, 10));
            toolbar.add(new RangeZoomAction(rangeAdapter, -10));
            toolbar.add(new RangePanAction(rangeAdapter, -20));
            toolbar.add(new RangePanAction(rangeAdapter, 20));
        } else {
            toolbar.add(new ZoomAction(timeScale, 1 / 1.2));
            toolbar.add(new ZoomAction(timeScale, 1.2));
            toolbar.add(new PanAction(timeScale, -20));
            toolbar.add(new PanAction(timeScale, 20));
        }

        // TODO test fisheye
        if (timeScale instanceof FisheyeTimeScale) {
            FisheyeSlider fs = new FisheyeSlider(
                    (FisheyeTimeScale) rangeAdapter.getActualScale());
            fs.setOrientation(SwingConstants.VERTICAL);
            toolbar.add(fs);
        }

        return toolbar;
    }

    public static interface Delegate {
        public void dataLoaded(TemporalDataset tmpds);
    }

    /**
     * Generates a {@link TemporalDataset} with one data column filled with
     * random double values. The temporal elements are chronon instants with a
     * random gap (between 1 and 4 days). The data is uniformly distributed
     * between 0 and 100.
     * 
     * @param count
     *            number of objects to generate
     * @param dataColumn
     *            field name of the data column
     * @return the temporal data set
     * @throws TemporalDataException
     */
    public static TemporalDataset generateRandomNumericalInstantData(int count,
            String dataColumn) throws TemporalDataException {
        final long MIN_GAP_MS = 360000 * 24; // 1 day
        final long MAX_GAP_MS = 360000 * 24 * 4; // 4 days
        final double MIN_VALUE = 0.0d;
        final double VALUE_RANGE = 100.0d;

        TemporalDataset tmpds = new TemporalDataset();
        tmpds.addDataColumn(dataColumn, double.class, 0.0d);

        double value = Math.random() * VALUE_RANGE + MIN_VALUE;
        long time = System.currentTimeMillis();
        Calendar cal = JavaDateCalendarManager.getSingleton().getDefaultCalendar();
        TemporalElement elem;
        TemporalObject obj;

        for (int i = 0; i < count; i++) {
            elem = tmpds.addInstant(time, time,
                    cal.getBottomGranularity());
            obj = tmpds.addTemporalObject(elem);
            obj.set(dataColumn, value);
            // auto-regressive with order 1
            value = (Math.random() * VALUE_RANGE + MIN_VALUE) * 0.2d + value * 0.8d;
            time += Math.round(Math.random() * (MAX_GAP_MS - MIN_GAP_MS)
                    + MIN_VALUE);
        }

        return tmpds;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setUseScrollbar(boolean useScrollbar) {
        this.useScrollbar = useScrollbar;
    }

    public void setPaintWeekends(boolean paintWeekends) {
        this.paintWeekends = paintWeekends;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy