ASE Home Page Products Download Purchase Support About ASE
ChartDirector General
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Questions about Gantt Charts please help
Posted by AJ on Sep-14-2009 18:41
Hi guys,

I'm browsing your docs and examples because I'm interested in creating your colorgantt
but with some modifications found in the other samples. I'm wondering if someone can
help or direct me with what to do with the following.

I am currently working on the sample named colorgantt.java. I intend to use it for
scholarly purposes and not for commercial or any other that will distribute it in any
manner and earn anything especially with monetary value.

Here's what I'm looking to do:

a. Change the "ticks" or division to hourly and/or daily.

this code sets it in the original program :

// Set the y-axis scale to be date scale from Aug 16, 2004 to Nov 22, 2004,
        // with ticks every 7 days (1 week) 86400
        c.yAxis().setDateScale(new GregorianCalendar(2004, 7, 1).getTime(),
            new GregorianCalendar(2004, 10, 31).getTime(), 86400*7);

why is it 86400 * 7? what should i place if i want it to be at least DAILY and not weekly?

b. Putting a scroll bar on it, like the example named ZoomScrollDemo.java even w/o the
zoom just the scroll function.

I am unsure if this concern was already answered before. If it was already tackled could
anyone please direct me to it so I can study it and see if it suites what I'm looking for. If
not, any help and guidance would be greatly appreciated.


Thanks~

regards,

aj

  Re: Questions about Gantt Charts please help
Posted by AJ on Sep-15-2009 00:29
Attachments:
Hi, I have an update. I've been trying out the codes in order to get what I am thinking while
browsing the other samples.

I was able to show a gantt chart on the window of "ZoomScrollDemo" but the problem is the
background is not moving when I move my mouse or the scroll bar. It is not synchronize
worse, it is not moving totally.

I was wondering how can I make it move and function as how it is intended too when there
is a scroll bar. That is true for Horizontal and Vertical scroll bars.

Lastly, is it possible to have a "marker" on the y-axis that is HOURLY not daily or weekly?

Thanks for your help. I included the code that I am working on where I intend to see those
that I'm asking about.
ZoomScrollDemo.java
ZoomScrollDemo.java

39.74 Kb

  Re: Questions about Gantt Charts please help
Posted by Peter Kwan on Sep-15-2009 01:46
Attachments:
Hi AJ,

(a) The 86400 * 7 means 7 days. (1 day = 86400 seconds). So in the sample code, the distance btween the ticks is 7 days. If you want to use 1 day, please change it to 86400 instead. If you want to use 1 hour, please change it to 3600 (1 hour = 3600 seconds).

(b) The scrollbar control is unrelated to ChartDirector. It is a just standard Java control.

In the sample code, when the scrollbar moves, the code computes the portion of the view port that is supposed to be visible. Your charting code in drawChart should then draw the chart based on what is visible.

Currently, your code draws the same chart (hard coded the axis to the same scale) no matter what is visible, so the background does not change.

Also, your current code does not use the horizontal scrollbar to control the horizontal scale, so the horizontal scrollbar has no effect.


I have attached an example I just wrote for your reference. I have only done the horizontal scrolling part. If you want vertical scrolling too, please implement it yourself. The implementation should be quite simple. If the vertical scrollbar indicates only 3 tasks are visible, just pass the data for those 3 tasks to ChartDirector (do not pass everything to ChartDirector regardless of what is visible).


Hope this can help.

Regards
Peter Kwan
ZoomScrollDemo.java
import ChartDirector.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ZoomScrollDemo extends JFrame implements DemoModule
{
	// Data arrays for the scrollable / zoomable chart.
	// data for the gantt chart, representing the start date, end date and names
	// for various activities
	Date[] startDate = {new GregorianCalendar(2004, 7, 16).getTime(),
		new GregorianCalendar(2004, 7, 30).getTime(), new GregorianCalendar(2004,
		8, 13).getTime(), new GregorianCalendar(2004, 8, 20).getTime(),
		new GregorianCalendar(2004, 8, 27).getTime(), new GregorianCalendar(2004,
		9, 4).getTime(), new GregorianCalendar(2004, 9, 25).getTime(),
		new GregorianCalendar(2004, 10, 1).getTime(), new GregorianCalendar(2004,
		10, 8).getTime()};
	Date[] endDate = {new GregorianCalendar(2004, 7, 30).getTime(),
		new GregorianCalendar(2004, 8, 13).getTime(), new GregorianCalendar(2004,
		8, 27).getTime(), new GregorianCalendar(2004, 9, 4).getTime(),
		new GregorianCalendar(2004, 9, 11).getTime(), new GregorianCalendar(2004,
		10, 8).getTime(), new GregorianCalendar(2004, 10, 8).getTime(),
		new GregorianCalendar(2004, 10, 22).getTime(), new GregorianCalendar(
		2004, 10, 22).getTime()};
	String[] labels = {"Market Research", "Define Specifications",
		"Overall Archiecture", "Project Planning", "Detail Design",
		"Software Development", "Test Plan", "Testing and QA",
		"User Documentation"};

		
	// The earliest date and the duration in seconds for horizontal scrolling
	private Date minDate;
	private double dateRange;
		
	// The vertical range of the chart for vertical scrolling
	private double maxValue;
	private double minValue;
		
	// The current visible duration of the view port in seconds
	private double currentDuration = 360 * 86400;
	// In this demo, the maximum zoom-in is set to 10 days
	private double minDuration = 10 * 86400;
	
	// Will set to true at the end of initialization
	private boolean hasFinishedInitialization;
	
	//
	// Controls in the JFrame
	//
	private ChartViewer chartViewer1;
	private JComboBox duration;
	private JScrollBar hScrollBar1;
	private JButton pointerPB;
	private JComboBox startDay;
	private JComboBox startMonth;
	private JComboBox startYear;
	private JScrollBar vScrollBar1;
	private JButton xZoomPB;
	private JButton xyZoomPB;
	private JButton zoomInPB;
	private JButton zoomOutPB;

	/// <summary>
	/// The main method to allow this demo to run as a standalone program.
	/// </summary>
	public static void main(String args[]) 
	{
		ZoomScrollDemo d = new ZoomScrollDemo();
		d.initComponents(true);
		d.setVisible(true);
	}
	
	/// <summary>
	/// Create the JFrame and put controls in it. 
	/// </summary>
	private void initComponents(final boolean closeOnExit) 
	{
		// Do nothing if already initialized
		if (hasFinishedInitialization)
			return;
    	
		setTitle("ChartDirector Zooming and Scrolling Demonstration");
		setResizable(false);

		// End application upon closing main window
		if (closeOnExit)
		{
			addWindowListener(new WindowAdapter() {
				public void windowClosing(WindowEvent e) { System.exit(0); }});
		}
		
		// Top label bar
		JLabel topLabel = new JLabel("Advanced Software Engineering");
		topLabel.setForeground(new java.awt.Color(255, 255, 51));
		topLabel.setBackground(new java.awt.Color(0, 0, 128));
		topLabel.setBorder(new javax.swing.border.EmptyBorder(2, 0, 2, 5));
		topLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
		topLabel.setOpaque(true);
		getContentPane().add(topLabel, java.awt.BorderLayout.NORTH);

		// Left panel
		JPanel leftPanel = new JPanel(null);
		leftPanel.setBorder(javax.swing.BorderFactory.createRaisedBevelBorder());
		
		// Pointer push button
		pointerPB = new JButton("Pointer", loadImageIcon("pointer.gif"));
		pointerPB.setHorizontalAlignment(SwingConstants.LEFT);
		pointerPB.setMargin(new Insets(5, 5, 5, 5));
		pointerPB.addActionListener(new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt)	{
				pointerPB_Clicked();
			}});
		leftPanel.add(pointerPB).setBounds(1, 0, 148, 24);
        
		// Zoom In push button
		zoomInPB = new JButton("Zoom In", loadImageIcon("zoomin.gif"));
		zoomInPB.setHorizontalAlignment(SwingConstants.LEFT);
		zoomInPB.setMargin(new Insets(5, 5, 5, 5));
		zoomInPB.addActionListener(new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt)	{
				zoomInPB_Clicked();
			}});		
		leftPanel.add(zoomInPB).setBounds(1, 24, 148, 24);

		// Zoom out push button
		zoomOutPB = new JButton("Zoom Out", loadImageIcon("zoomout.gif"));
		zoomOutPB.setHorizontalAlignment(SwingConstants.LEFT);
		zoomOutPB.setMargin(new Insets(5, 5, 5, 5));
		zoomOutPB.addActionListener(new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt)	{
				zoomOutPB_Clicked();
			}});		
		leftPanel.add(zoomOutPB).setBounds(1, 48, 148, 24);

		// Zoom mode label
		leftPanel.add(new JLabel("Zoom Mode")).setBounds(5, 80, 130, 20);
	
		// X Zoom push button
		xZoomPB = new JButton("X Zoom / Y Auto", loadImageIcon("xrange.gif"));
		xZoomPB.setHorizontalAlignment(SwingConstants.LEFT);
		xZoomPB.setMargin(new Insets(5, 5, 5, 5));
		xZoomPB.addActionListener(new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt)	{
				xZoomPB_Clicked();
			}});		
		leftPanel.add(xZoomPB).setBounds(1, 100, 148, 25);

		// XY Zoom push button
		xyZoomPB = new JButton("XY Zoom", loadImageIcon("xyrange.gif"));
		xyZoomPB.setHorizontalAlignment(SwingConstants.LEFT);
		xyZoomPB.setMargin(new Insets(5, 5, 5, 5));
		xyZoomPB.addActionListener(new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt)	{
				xyZoomPB_Clicked();
			}});	
		leftPanel.add(xyZoomPB).setBounds(1, 124, 148, 24);
			
		// Start Date label
		leftPanel.add(new JLabel("Start Date")).setBounds(5, 160, 130, 20);
		
		// Start Year, Start Month, Start Day combo boxes
		startYear = new JComboBox();
		startMonth = new JComboBox(new Object[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", 
			"10", "11", "12"} );
		startDay = new JComboBox(new Object[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", 
			"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
			"24", "25", "26", "27", "28", "29", "30", "31"} );
		leftPanel.add(startYear).setBounds(1, 180, 60, 20);
		leftPanel.add(startMonth).setBounds(61, 180, 44, 20);
		leftPanel.add(startDay).setBounds(105, 180, 44, 20);
		ActionListener startDateHandler = new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				startDate_ValueChanged(); 
			}};
		startYear.addActionListener(startDateHandler);
		startMonth.addActionListener(startDateHandler);
		startDay.addActionListener(startDateHandler);
		
		// Duration label
		leftPanel.add(new JLabel("Duration (Days)")).setBounds(5, 212, 130, 20);
		
		// Duration combo box
		duration = new JComboBox(new Object[] { "10", "20", "30", "60", "90", "180", "360", "720",
			"1080", "1440" });
		duration.setEditable(true);
		duration.addActionListener(new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				duration_ValueChanged(); 
			}			
		});
		leftPanel.add(duration).setBounds(1, 232, 148, 20);
		
		// Total expected panel size
		leftPanel.setPreferredSize(new Dimension(150, 264));
		
		// Chart Viewer
		chartViewer1 = new ChartViewer();
		chartViewer1.setBackground(new java.awt.Color(255, 255, 255));
		chartViewer1.setOpaque(true);
		chartViewer1.setPreferredSize(new Dimension(616, 316));
		chartViewer1.setHorizontalAlignment(SwingConstants.CENTER);
		chartViewer1.setHotSpotCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		chartViewer1.addViewPortListener(new ViewPortAdapter() {
			public void viewPortChanged(ViewPortChangedEvent e) {
				chartViewer1_ViewPortChanged(e);
			}
		});
		chartViewer1.addHotSpotListener(new HotSpotAdapter() {
			public void hotSpotClicked(HotSpotEvent e) {
				chartViewer1_HotSpotClicked(e);
		}});
		chartViewer1.addMouseListener(new MouseAdapter() {
			public void mouseEntered(MouseEvent e) {
				chartViewer1_MouseEntered();
			}
		});
		
		// Vertical Scroll Bar
		vScrollBar1 = new JScrollBar(JScrollBar.VERTICAL, 0, 100000000, 0, 1000000000);
		vScrollBar1.addAdjustmentListener(new AdjustmentListener() {
			public void adjustmentValueChanged(AdjustmentEvent e) {
				vScrollBar1_ValueChanged();		 
			}
		});

		// Horizontal Scroll bar
		hScrollBar1 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 100000000, 0, 1000000000);
		hScrollBar1.addAdjustmentListener(new AdjustmentListener() {
			public void adjustmentValueChanged(AdjustmentEvent e) {
				hScrollBar1_ValueChanged();		 
			}
		});

		// We need to put the horizontal scroll bar inside a panel with a filler, because
		// the horizontal scroll bar does not exactly touch the right edge of the right panel
		JPanel filler = new JPanel();
		filler.setPreferredSize(new Dimension(vScrollBar1.getPreferredSize().width, 1));
		JPanel bottomScrollPanel = new JPanel(new BorderLayout());
		bottomScrollPanel.add(hScrollBar1, java.awt.BorderLayout.CENTER);
		bottomScrollPanel.add(filler, java.awt.BorderLayout.EAST);

		// Put the ChartViewer and the scroll bars in the right panel
		JPanel rightPanel = new JPanel(new BorderLayout());
		rightPanel.add(chartViewer1, java.awt.BorderLayout.CENTER);
		rightPanel.add(vScrollBar1, java.awt.BorderLayout.EAST);
		rightPanel.add(bottomScrollPanel, java.awt.BorderLayout.SOUTH);
		
		// Put the leftPanel and rightPanel on the JFrame
		getContentPane().add(leftPanel, java.awt.BorderLayout.WEST);
		getContentPane().add(rightPanel, java.awt.BorderLayout.CENTER);
		
		// Set all UI fonts (except labels)
		Font uiFont = new Font("Dialog", Font.PLAIN, 11);
		for (int i = 0; i < leftPanel.getComponentCount(); ++i)
		{
			Component c = leftPanel.getComponent(i);
			if (!(c instanceof JLabel))
				c.setFont(uiFont);
		}

		// In this demo, we obtain the horizontal scroll range from the actual data.
		minDate = startDate[0];
		dateRange = (endDate[endDate.length - 1].getTime() - minDate.getTime()) / 1000;

		// Set the date range of the startYear combo box to match the scrollable date range.
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(minDate);
		int minYear = calendar.get(Calendar.YEAR);
		calendar.add(Calendar.SECOND, (int)dateRange);
		int maxYear = calendar.get(Calendar.YEAR);

		startYear.removeAllItems();
		for (int i = minYear; i <= maxYear; ++i)
			startYear.addItem(new Integer(i));

		// Set ChartViewer to reflect the visible and minimum duration
		chartViewer1.setZoomInWidthLimit(minDuration / dateRange);
		chartViewer1.setViewPortWidth(currentDuration / dateRange);
		chartViewer1.setViewPortLeft(1 - chartViewer1.getViewPortWidth());
		
		// Initially choose the pointer mode (draw to scroll mode)
		pointerPB.doClick();
		xZoomPB.doClick();		

		// Can update the chart now
		pack();
		hasFinishedInitialization = true;
		chartViewer1.updateViewPort(true, true);
	}

	/// <summary>
	/// A utility to load an image icon from the Java class path
	/// </summary>
	private ImageIcon loadImageIcon(String path)
	{
		try { return new ImageIcon(getClass().getClassLoader().getResource(path)); }
		catch (Exception e) { return null; }
	}
	
	/// <summary>
	/// Click event for the pointerPB.
	/// </summary>
	private void pointerPB_Clicked()
	{
		pointerPB.setBackground(new Color(0x80, 0xff, 0x80));
		zoomInPB.setBackground(null);
		zoomOutPB.setBackground(null);
		chartViewer1.setMouseUsage(Chart.MouseUsageScrollOnDrag);
	}

	/// <summary>
	/// Click event for the zoomInPB.
	/// </summary>
	private void zoomInPB_Clicked()
	{
		pointerPB.setBackground(null);
		zoomInPB.setBackground(new Color(0x80, 0xff, 0x80));
		zoomOutPB.setBackground(null);
		chartViewer1.setMouseUsage(Chart.MouseUsageZoomIn);
	}

	/// <summary>
	/// Click event for the zoomOutPB.
	/// </summary>
	private void zoomOutPB_Clicked()
	{
		pointerPB.setBackground(null);
		zoomInPB.setBackground(null);
		zoomOutPB.setBackground(new Color(0x80, 0xff, 0x80));
		chartViewer1.setMouseUsage(Chart.MouseUsageZoomOut);
	}
	
	/// <summary>
	/// Click event for the xZoomPB. Sets X-Zoom / Y-Axis auto-scaled mode.
	/// </summary>
	private void xZoomPB_Clicked()
	{
		xZoomPB.setBackground(new Color(0x80, 0xff, 0x80));
		xyZoomPB.setBackground(null);

		// Horizontal zooming and scrolling only
		chartViewer1.setZoomDirection(Chart.DirectionHorizontal);
		chartViewer1.setScrollDirection(Chart.DirectionHorizontal);
				
		// Viewport is always unzoomed as y-axis is auto-scaled
		chartViewer1.setViewPortTop(0);
		chartViewer1.setViewPortHeight(1);
				
		// Update chart to auto-scale axis
		if (hasFinishedInitialization)
			chartViewer1.updateViewPort(true, false);
	}

	/// <summary>
	/// Click event for the xZoomPB. Set XY-Zoom mode.
	/// </summary>
	private void xyZoomPB_Clicked()
	{
		xZoomPB.setBackground(null);
		xyZoomPB.setBackground(new Color(0x80, 0xff, 0x80));
		
		// Horizontal and Vertical zooming and scrolling
		chartViewer1.setZoomDirection(Chart.DirectionHorizontalVertical);
		chartViewer1.setScrollDirection(Chart.DirectionHorizontalVertical);		
	}
		
	/// <summary>
	/// Event handler for startYear, startMonth and startDay.
	/// </summary>
	private void startDate_ValueChanged()
	{
		if (hasFinishedInitialization && !chartViewer1.isInViewPortChangedEvent())
		{
			// Get the date represented by the combo boxes
			GregorianCalendar startYMD = new GregorianCalendar(
				Integer.parseInt(startYear.getSelectedItem().toString()), 
				startMonth.getSelectedIndex(), startDay.getSelectedIndex() + 1);
			Date startDate = startYMD.getTime();
			
			// Set the view port to reflect the selected date
			chartViewer1.setViewPortLeft((startDate.getTime() - minDate.getTime()) / dateRange / 1000);
			chartViewer1.updateViewPort(true, false);
		}
	}
	
	/// <summary>
	/// Sets the startYear, startMonth and startDay to the given date.
	/// </summary>
	private void setStartDate(Date d)
	{
		GregorianCalendar startYMD = new GregorianCalendar();
		startYMD.setTime(d);
		
		startYear.setSelectedItem(new Integer(startYMD.get(Calendar.YEAR)));
		startMonth.setSelectedIndex(startYMD.get(Calendar.MONTH));
		normalizeDate();
		startDay.setSelectedIndex(startYMD.get(Calendar.DAY_OF_MONTH) - 1);
	}
	
	/// <summary>
	/// Normalize the startDay combo box to ensure it only shows the valid days for the month.
	/// </summary>
	private void normalizeDate()
	{
		final int[] daysTable = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
		int daysInMonth = daysTable[Integer.parseInt(startMonth.getSelectedItem().toString()) - 1];
		if ((daysInMonth == 28) && (Integer.parseInt(startYear.getSelectedItem().toString()) % 4 == 0))
			++daysInMonth; 
		
		int currentDay = Integer.parseInt(startDay.getSelectedItem().toString());
		while (daysInMonth < startDay.getItemCount())
			startDay.removeItemAt(startDay.getItemCount() - 1);
		while (daysInMonth > startDay.getItemCount())
			startDay.addItem(new Integer(startDay.getItemCount() + 1));
		if (currentDay > daysInMonth)
			startDay.setSelectedIndex(daysInMonth - 1);
	}
	
	/// <summary>
	/// Event handler for duration.
	/// </summary>
	private void duration_ValueChanged()
	{
		if (hasFinishedInitialization && !chartViewer1.isInViewPortChangedEvent())
		{
			try 
			{ 
				//get the duration chosen or entered by the user
				double enteredDuration = Double.parseDouble(duration.getSelectedItem().toString()) 
					* 86400;
				if (enteredDuration <= minDuration)
					enteredDuration = minDuration;
					
				// Check if duration has really changed - sometimes the combo box may issue 
				// redundant value changed events when value has not actually changed.
				double newViewPortWidth = enteredDuration / dateRange;
				if (Math.abs(chartViewer1.getViewPortWidth() - newViewPortWidth) > 
					0.00001 * chartViewer1.getViewPortWidth())
				{
					// Set the view port based on the duration
					chartViewer1.setViewPortWidth(newViewPortWidth);
					chartViewer1.updateViewPort(true, false);
				}				
			}
			catch (Exception e)
			{
				// If user entered invalid text as duration, we just reset the duration
				duration.setSelectedItem("" + 
					Math.round(chartViewer1.getViewPortWidth() * dateRange / 86400));
			}
		}		
	}

	/// <summary>
	/// Horizontal ScrollBar ValueChanged event handler
	/// </summary>
	private void hScrollBar1_ValueChanged()
	{
		if (hasFinishedInitialization && !chartViewer1.isInViewPortChangedEvent())
		{
			// Get the view port left as according to the scroll bar
			double newViewPortLeft = ((double)(hScrollBar1.getValue() - hScrollBar1.getMinimum())) 
				/ (hScrollBar1.getMaximum() - hScrollBar1.getMinimum());

			// Check if view port has really changed - sometimes the scroll bar may issue redundant
			// value changed events when value has not actually changed.
			if (Math.abs(chartViewer1.getViewPortLeft() - newViewPortLeft) > 
				0.00001 * chartViewer1.getViewPortWidth())
			{
				// Set the view port based on the scroll bar
				chartViewer1.setViewPortLeft(newViewPortLeft);
	
				// Update the chart display without updating the image maps. We delay updating
				// the image map because the chart may still be unstable (still scrolling).
				chartViewer1.updateViewPort(true, false);
			}
		}
	}

	/// <summary>
	/// Vertical ScrollBar ValueChanged event handler
	/// </summary>
	private void vScrollBar1_ValueChanged()
	{
		if (hasFinishedInitialization && !chartViewer1.isInViewPortChangedEvent())
		{
			// Get the view port top as according to the scroll bar
			double scrollBarTop = ((double)(vScrollBar1.getValue() - vScrollBar1.getMinimum())) 
				/ (vScrollBar1.getMaximum() - vScrollBar1.getMinimum());
			
			// Check if view port has really changed - sometimes the scroll bar may issue redundant
			// value changed events when value has not actually changed.
			if (Math.abs(chartViewer1.getViewPortTop() - scrollBarTop) >  
				0.00001 * chartViewer1.getViewPortHeight())
			{
				// Set the view port based on the scroll bar
				chartViewer1.setViewPortTop(scrollBarTop);
	
				// Update the chart display without updating the image maps. We delay updating
				// the image map because the chart may still be unstable (still scrolling).
				chartViewer1.updateViewPort(true, false);
			}
		}		
	}
	
	/// <summary>
	/// The MouseEntered handler for the ChartViewer. In this demo, we delay creating the image 
	/// map until the mouse actually enters the chart. This avoids creating unnecessary image
	/// maps while the chart is still scrolling.
	/// </summary>
	private void chartViewer1_MouseEntered()
	{
		updateImageMap(chartViewer1);
	}

	/// <summary>
	///	Handler when a hot spot on a chart is clicked. In this demo, we just list out the hot spot
	/// information in a pop up dialog.
	/// </summary>
	private void chartViewer1_HotSpotClicked(HotSpotEvent e)
	{
		// We show the pop up dialog only when the mouse action is not in zoom-in or zoom-out mode.
		if ((chartViewer1.getMouseUsage() != Chart.MouseUsageZoomIn) && 
			(chartViewer1.getMouseUsage() != Chart.MouseUsageZoomOut))
			showHotSpotParam(e);
	}
	
	/// <summary>
	///	Utility to list out all hot spot parameters on a pop-up dialog
	/// </summary>
	private void showHotSpotParam(HotSpotEvent e)
	{
		//Get all parameters and sort them by key
		Hashtable parameters = e.getAttrValues();
		Object[] attributes = parameters.keySet().toArray();
		Arrays.sort(attributes);
	
		//Create a JTable to show the hot spot attribute/value pairs
		Object[][] rows = new Object[parameters.size()][2];
		for (int i = 0; i < attributes.length; ++i)
		{
			rows[i][0] = attributes[i];
			rows[i][1] = parameters.get(attributes[i]);
		}
		JTable table = new JTable(rows, new Object[] {"Parameter", "Value"});

		//Show the table in a dialog
		JDialog d = new JDialog(this, "Hot Spot Parameters", true);
		d.setSize(300, 300);
		Container container = d.getContentPane();

		//Just add some descriptive text to the dialg
		JTextArea t = new JTextArea ("This dialog is for demonstration only." +
			" In this demo, we simply list out all hot spot parameters.");
		t.setLineWrap(true);
		t.setWrapStyleWord(true);
		t.setEditable(false);
		t.setOpaque(false);
		t.setMargin(new Insets(5, 5, 5, 5));
		container.add(t, BorderLayout.NORTH);
	
		//Create the scroll pane on the dialog and add the table to it.
		JScrollPane scrollPane = new JScrollPane(table);
		container.add(scrollPane);

		//Show the dialog on where the mouse click occur	
		Point topLeft = ((ChartViewer)e.getSource()).getLocationOnScreen();
		d.setLocation(topLeft.x + e.getX(), topLeft.y + e.getY());
		d.setVisible(true);
	}
	
	/// <summary>
	/// The ViewPortChanged event handler. This event occurs when the user changes the ChartViewer
	/// view port by dragging scrolling, or by zoom in/out, or the ChartViewer.updateViewPort method
	/// is being called.
	/// </summary>
	private void chartViewer1_ViewPortChanged(ViewPortChangedEvent e)
	{
		// Compute the view port start date and duration
		Date currentStartDate = new Date(minDate.getTime() + Math.round(chartViewer1.getViewPortLeft() * 
			dateRange) * 1000);
		currentDuration = Math.round(chartViewer1.getViewPortWidth() * dateRange);

		// Synchronize the startDate and duration controls
		setStartDate(currentStartDate);
		duration.setSelectedItem("" + Math.round(currentDuration / 86400));

		// Synchronize the horizontal scroll bar with the ChartViewer
		hScrollBar1.setEnabled(chartViewer1.getViewPortWidth() < 1);
		hScrollBar1.setVisibleAmount((int)Math.ceil(chartViewer1.getViewPortWidth() * 
			(hScrollBar1.getMaximum() - hScrollBar1.getMinimum())));
		hScrollBar1.setBlockIncrement(hScrollBar1.getVisibleAmount());
		hScrollBar1.setUnitIncrement((int)Math.ceil(hScrollBar1.getVisibleAmount() * 0.1));
		hScrollBar1.setValue((int)Math.round(chartViewer1.getViewPortLeft() * 
			(hScrollBar1.getMaximum() - hScrollBar1.getMinimum())) + hScrollBar1.getMinimum());
		
		// Synchronize the vertical scroll bar with the ChartViewer
		vScrollBar1.setEnabled(chartViewer1.getViewPortHeight() < 1);
		vScrollBar1.setVisibleAmount((int)Math.ceil(chartViewer1.getViewPortHeight() * 
			(vScrollBar1.getMaximum() - vScrollBar1.getMinimum())));
		vScrollBar1.setBlockIncrement(vScrollBar1.getVisibleAmount());
		vScrollBar1.setUnitIncrement((int)Math.ceil(vScrollBar1.getVisibleAmount() * 0.1));
		vScrollBar1.setValue((int)Math.round(chartViewer1.getViewPortTop() * 
			(vScrollBar1.getMaximum() - vScrollBar1.getMinimum())) + vScrollBar1.getMinimum());
		
		// Update chart and image map if necessary
		if (e.needUpdateChart())
			drawChart(chartViewer1);
		if (e.needUpdateImageMap())
			updateImageMap(chartViewer1);	
	}

	/// <summary>
	/// Draw the chart.
	/// </summary>
	private void drawChart(ChartViewer viewer)
	{ 
		//
		// In this demo, we copy the visible part of the data to a separate buffer for chart
		// plotting. 
		//
		// Note that if you only have a small amount of data (a few hundred data points), it
		// may be easier to just plot all data in any case (so the following copying code is 
		// not needed), and let ChartDirector "clip" the chart to the plot area. 
		//

		// Using ViewPortLeft and ViewPortWidth, get the start and end dates of the view port.
		Date viewPortStartDate = new Date(minDate.getTime() + Math.round(viewer.getViewPortLeft() *
			dateRange) * 1000);
		Date viewPortEndDate = new Date(viewPortStartDate.getTime() + 
			Math.round(viewer.getViewPortWidth() * dateRange) * 1000);
				
		//
		// Now we have obtained the data, we can plot the chart. 
		//

		///////////////////////////////////////////////////////////////////////////////////////
		// Step 1 - Configure overall chart appearance. 
		///////////////////////////////////////////////////////////////////////////////////////

		// Create a XYChart object of size 620 x 280 pixels. Set background color to
		// light blue (ccccff), with 1 pixel 3D border effect.
		XYChart c = new XYChart(620, 280, 0xccccff, 0x000000, 1);

		// Add a title to the chart using 15 points Times Bold Itatic font, with
		// white (ffffff) text on a deep blue (000080) background
		c.addTitle("Simple Gantt Chart Demo", "Times New Roman Bold Italic", 15,
			0xffffff).setBackground(0x000080);

		// Set the plotarea at (140, 55) and of size 460 x 200 pixels. Use
		// alternative white/grey background. Enable both horizontal and vertical
		// grids by setting their colors to grey (c0c0c0). Set vertical major grid
		// (represents month boundaries) 2 pixels in width
		c.setPlotArea(140, 55, 460, 200, 0xffffff, 0xeeeeee, Chart.LineColor,
			0xc0c0c0, 0xc0c0c0).setGridWidth(2, 1, 1, 1);

		// swap the x and y axes to create a horziontal box-whisker chart
		c.swapXY();
		c.setClipping();
		
		///////////////////////////////////////////////////////////////////////////////////////
		// Step 2 - Add data to chart
		///////////////////////////////////////////////////////////////////////////////////////
		
		// 
		// In this example, we represent the data by lines. You may modify the code below if 
		// you want to use other representations (areas, scatter plot, etc).
		//

		// Add a green (33ff33) box-whisker layer showing the box only.
		c.addBoxWhiskerLayer(Chart.CTime(startDate), Chart.CTime(endDate), null,
			null, null, 0x00cc00, Chart.SameAsMainColor, Chart.SameAsMainColor);


		///////////////////////////////////////////////////////////////////////////////////////
		// Step 3 - Set up y-axis scale
		///////////////////////////////////////////////////////////////////////////////////////

		// Set the y-axis scale to be date scale from Aug 16, 2004 to Nov 22, 2004,
		// with ticks every 7 days (1 week)
		c.yAxis().setDateScale(viewPortStartDate, viewPortEndDate, 86400 * 7);

		// Set multi-style axis label formatting. Month labels are in Arial Bold font
		// in "mmm d" format. Weekly labels just show the day of month and use minor
		// tick (by using '-' as first character of format string).
		c.yAxis().setMultiFormat(Chart.StartOfMonthFilter(),
			"<*font=Arial Bold*>{value|mmm d}", Chart.StartOfDayFilter(),
			"-{value|d}");

		// Set the y-axis to shown on the top (right + swapXY = top)
		c.setYAxisOnRight();

		///////////////////////////////////////////////////////////////////////////////////////
		// Step 4 - Set up x-axis scale
		///////////////////////////////////////////////////////////////////////////////////////
			
		// Set the labels on the x axis
		c.xAxis().setLabels(labels);

		// Reverse the x-axis scale so that it points downwards.
		c.xAxis().setReverse();

		// Set the horizontal ticks and grid lines to be between the bars
		c.xAxis().setTickOffset(0.5);

		///////////////////////////////////////////////////////////////////////////////////////
		// Step 5 - Display the chart
		///////////////////////////////////////////////////////////////////////////////////////
		
		chartViewer1.setChart(c);
	}
	
	/// <summary>
	/// Update the image map used on the chart.
	/// </summary>
	private void updateImageMap(ChartViewer viewer)
	{
		// Include tool tip for the chart
		if (viewer.getImageMap() == null)
		{
			viewer.setImageMap(viewer.getChart().getHTMLImageMap("clickable", "",
				"title='{xLabel}: {top|mmm dd, yyyy} to {bottom|mmm dd, yyyy}'"));
		}
	}
	
	//
	// Implementation of the DemoModule interface to allow this demo to run inside the 
	// ChartDirectorDemo browser
	//
    
	// Name of demo program
	public String toString() 
	{ 
		return "Zoom/Scroll Demo"; 
	}

	// Number of charts produced in this demo
	public int getNoOfCharts() 
	{ 
		// This demo open its own frame instead of using the right pane of the ChartDirectorDemo 
		// browser for display, so we just load the frame, then returns 0.
		initComponents(false); 
		setVisible(true); 
		return 0; 
	}

	// Main code for creating charts
	public void createChart(ChartViewer viewer, int index)
	{
		// do nothing, as the ChartDirectorDemo browser right pane is not used
	}
}


  Re: Questions about Gantt Charts please help
Posted by AJ on Sep-15-2009 09:17
Hello, thanks for your reply and the reference code too it's very much appreciated.
However, I do have some further questions.

a. Currently the code displays the "background" of the chart to be from august to november
which is an "interval" how can I set it to be like a "duration" wherein it starts from i.e jan 1
to december 31 meaning based on our data there would be areas with no markings. The
markings would be only visible on the interval that it will fall on.

b. The tooltip labels, what should I use to display also the time?  based on this
"title='{xLabel}: {top|mmm dd, yyyy} to {bottom|mmm dd, yyyy}'"

c. About the horizontal scrolling, What I'm thinking of is that there is a list on the left side
Market Research, Define Specifications...etc now I see all of them because it is somehow
short but when it gets longer I need also to move that not just the chart plots but both of
them..somehow synchronized. With your previous suggestion would that be possible?

Thanks for your help.

Regards,

aj

  Re: Questions about Gantt Charts please help
Posted by AJ on Sep-15-2009 11:25
just an update. I was able to solve some of the questions. I only now require

items B (about the tool tip with time) and C (about vertical scrolling which includes the X
axis label moving possibility).

Thank you so much.

  Re: Questions about Gantt Charts please help
Posted by Peter Kwan on Sep-15-2009 17:14
Hi AJ,

For time in tooltips, please use hh:nn:ss. You may refer to the ChartDirector documentation on "Parameter Substitution" for details (you  may look for "Parameter Substitution" from the ChartDirector documentation index).

For the labels on the left, I am not too sure the type of user interface you want. I assume you want to have two frames in your form, one for the labels on the left, and one for the gantt chart plot area on the right, and each have its own scroll bars for horizontal scrolling, and with a single scrollbar for synchronized vertical scrolling.

In the above user interface, you can always use ChartDirector for the chart (the part on the right). For the non-chart part (the part on the left frame), you can use any normal Java SWING controls.

In my previous message, I suggest for vertical scrolling, the vertical scrollbar should tell your code which bars are visible, and you just need to pass the data for the visible bars to ChartDirector. If you have two frames, when the vertical scrollbar moves, your code can scroll the left frame as well, so that it is consistent with the right frame.

Hope this can help.

Regards
Peter Kwan

  Re: Questions about Gantt Charts please help
Posted by AJ on Sep-15-2009 18:36
Hi, I was able to get the thing about the tool tip earlier I just forgot to put an update sorry
about that. Anyway, thanks for the help I did it that way too and browsed the documents.

My only concern now is about the vertical scrolling.In the original ZoomScrollDemo.java the
one with Gamma A B C the vertical scrolling there is what I have in mind and it is perfect for
my purpose. It's just that the one in the example is not a gantt chart unlike the one that
I'm working on currently.

With what I have now it is what I am looking for except for the absence of the vertical
scrolling. If I would be able to implement it then everything's perfect. I am just wondering
what am I missing (referring to the code that you shared). The vertical bar is declared,
attached to the panel and the frame and there are methods that are for the actions of the
vertical scroll just like the horizontal bar but it doesn't do anything when I move the vertical
scroll. I am quite sure I'm missing something but as to what that is where I need help.

If you could be more specific I would really appreciate it. Just the same, I am thankful for
your help, patience and understanding.

regards,

aj

  Re: Questions about Gantt Charts please help
Posted by AJ on Sep-15-2009 20:05
hello again, like what I've mentioned ZoomScrollDemo.java has the vertical scroll function
that I have in mind. When i click XY Zoom button and zoom it in the vertical scroll enables
and I am able to move the chart up and down and along with it the USD price on the left
side moves also.

I am thinking of having that too but in a Gantt chart something with what you share earlier
but the difference is that vertical scrolls can move.

I reviewed both codes to try and see what I'm missing in order to make my (program that
you shared) vertical scroll function like the one in ZoomScrollDemo.java but apparently they
are the same except for how the data is plotted maybe because they are different kinds of
charts but all the other methods and function calls are present and similar.

Again, I am not sure of these just my observation when I tried to study both codes in order
to make the vertical scroll function in my program.

If that's the case that they are almost the same in terms of codes (content) but the other
one has a working vertical scroll how could I make the vertical scroll in the other one work
too?

Can you please direct me to what I need to do, add,modify or what I'm missing in order to
make my gantt chart version have a working vertical scroll just like in the demo of
ZoomScrollDemo.java.

Thank you very much Peter.

regards,

aj

  Re: Questions about Gantt Charts please help
Posted by AJ on Sep-15-2009 23:58
Attachments:
HI, I have another update. My apologies if i keep on posting messages even if they are still
unanswered or no reply yet. I try to solve for my questions too and sometimes I am able to
figure it out but  there are cases that I come a little closer to the answer but with some
more problem just like now.

You can disregard my previous posts because the idea of them is just to implement a
vertical scrolling in my gantt chart just like in the original sample code of ZoomScrollDemo.
Currently, I am able to click XYZoom button then Zoom in and have the vertical bar move.
Yes, it does move now however, it moves ( or behaves) like a horizontal bar moving the
chart from left to right and not top to down (vice versa). Is it because of the c.swapXY()
because when I remove that the vertical bar moves the grid (because there are no labels)
top to down (vv) but when I remove that the labels won't show.

There is also another error, when I just zoom in (without clicking the XY Zoom button) and
move the chart horizontally the whole chart moves and marks only the areas that are
supposed to be marked which is correct and how its supposed to be. But when I click the
XY Zoom button before zooming in and moving the bar (horizontal and vertical both because
of the 1st problem) somehow the marked areas stays and the background or the grid are
just the ones that move.

I really need help in here may be you can see what I did wrong and guide me on how to
make it work properly. I attached the code so that you'd be able to see what's really
happening.

Thanks so much Peter for your help.

regards,

aj
ZoomScrollDemo.java
ZoomScrollDemo.java

39.31 Kb

  Re: Questions about Gantt Charts please help
Posted by Peter Kwan on Sep-16-2009 01:58
Hi AJ,

In your case, may be you can following the steps below:

(a) In drawChart, do your code know which range of bars are supposed to be visible? For example, if you have 100 bars, and viewPortTop = 0 and viewPortHeight = 0.5, the top 50% of the bars are supposed to be visible.

(b) Can your code pass the data for the visible bars to ChartDirector to draw the chart? For example, if the top 50 bars are visible, can your code pass the data for the top 50 bars to ChartDirector? Do not pass all the labels and all the data regardless of what is visible.

Currently, in your code, there does not seem to be any attempt to compute the bar range that is visible for vertical scrolling. (For horizontal scrolling, the first two lines in drawChart computes the visible date range.)

Also, your code pass all data (the full set of labels, startDates and endDates) to ChartDirector regardless of the scrollbar position. Please modify your code to copy only the data for the visible bars to temporary arrays, and use those arrays to plot the chart.

Hope this can help.

Regards
Peter Kwan

  Re: Questions about Gantt Charts please help
Posted by AJ on Sep-16-2009 08:34
Hello Peter, thanks for your reply. I am somehow confused on what to do because I see the
"point" of using temporary arrays to transfer the areas that are supposed to be visible as
well as your other pointers to make the whole thing work. But I am trying to implement it on
a program that has a gantt chart and my guide is the ZoomScrollDemo sample which is
different I think based on appearance, loading data (code wise) and others.

In the previous code that you shared you said that the vertical scroll is not working and
that I try to implement it myself. May be you can mark the program, direct me there on
what to do,modify or add in terms of codes so that I could make it work. If it's not too
much to ask is it possible that you can show me the same example (gantt chart) but with a
working vertical scroll so that I would better understand how it works also what you are
saying. Then, If ever I have further questions it would be more specific because somehow
I'm on the same page as you. I hope it's not much of a bother on your side but it will all
make things a little less difficult for me.

Thank you very much for not giving up helping.

regards,

aj

  Re: Questions about Gantt Charts please help
Posted by Peter Kwan on Sep-16-2009 16:58
Attachments:
Hi AJ,

You need to compute the visible data. The detail steps are already explained in my previous message. It needs to be done before your the charting part of your code (before "Step 1" in the drawChart function).

For the charting part of the code, there is nothing you need to modify, except a change in variable names (use the visible data instead of all the data).

I think in the current case, I can only write the code for you. It is just a direct implementation of what I mentioned in my last message:

//compute the visible part of the chart
int startTask = (int)Math.floor(viewer.getViewPortTop() * labels.length);
int endTask = (int)Math.floor((viewer.getViewPortTop() + viewer.getViewPortHeight()) * labels.length - 0.001);

//these are the variables to contain the visible data
Date[] visibleStartDate = new Date[endTask - startTask + 1];
Date[] visibleEndDate = new Date[visibleStartDate.length];
String[] visibleLabels = new String[visibleStartDate.length];

//copy the visible data to the above variables
System.arraycopy(startDate, startTask, visibleStartDate, 0, visibleStartDate.length);
System.arraycopy(endDate, startTask, visibleEndDate, 0, visibleStartDate.length);
System.arraycopy(labels, startTask, visibleLabels, 0, visibleStartDate.length);

I have attached a work example for your reference. This is the same as my last example, with the above additionals.

Hope this can help.

Regards
Peter Kwan
ZoomScrollDemo.java
import ChartDirector.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ZoomScrollDemo extends JFrame implements DemoModule
{
	// Data arrays for the scrollable / zoomable chart.
	// data for the gantt chart, representing the start date, end date and names
	// for various activities
	Date[] startDate = {new GregorianCalendar(2004, 7, 16).getTime(),
		new GregorianCalendar(2004, 7, 30).getTime(), new GregorianCalendar(2004,
		8, 13).getTime(), new GregorianCalendar(2004, 8, 20).getTime(),
		new GregorianCalendar(2004, 8, 27).getTime(), new GregorianCalendar(2004,
		9, 4).getTime(), new GregorianCalendar(2004, 9, 25).getTime(),
		new GregorianCalendar(2004, 10, 1).getTime(), new GregorianCalendar(2004,
		10, 8).getTime()};
	Date[] endDate = {new GregorianCalendar(2004, 7, 30).getTime(),
		new GregorianCalendar(2004, 8, 13).getTime(), new GregorianCalendar(2004,
		8, 27).getTime(), new GregorianCalendar(2004, 9, 4).getTime(),
		new GregorianCalendar(2004, 9, 11).getTime(), new GregorianCalendar(2004,
		10, 8).getTime(), new GregorianCalendar(2004, 10, 8).getTime(),
		new GregorianCalendar(2004, 10, 22).getTime(), new GregorianCalendar(
		2004, 10, 22).getTime()};
	String[] labels = {"Market Research", "Define Specifications",
		"Overall Archiecture", "Project Planning", "Detail Design",
		"Software Development", "Test Plan", "Testing and QA",
		"User Documentation"};

		
	// The earliest date and the duration in seconds for horizontal scrolling
	private Date minDate;
	private double dateRange;
		
	// The vertical range of the chart for vertical scrolling
	private double maxValue;
	private double minValue;
		
	// The current visible duration of the view port in seconds
	private double currentDuration = 360 * 86400;
	// In this demo, the maximum zoom-in is set to 10 days
	private double minDuration = 10 * 86400;
	
	// Will set to true at the end of initialization
	private boolean hasFinishedInitialization;
	
	//
	// Controls in the JFrame
	//
	private ChartViewer chartViewer1;
	private JComboBox duration;
	private JScrollBar hScrollBar1;
	private JButton pointerPB;
	private JComboBox startDay;
	private JComboBox startMonth;
	private JComboBox startYear;
	private JScrollBar vScrollBar1;
	private JButton xZoomPB;
	private JButton xyZoomPB;
	private JButton zoomInPB;
	private JButton zoomOutPB;

	/// <summary>
	/// The main method to allow this demo to run as a standalone program.
	/// </summary>
	public static void main(String args[]) 
	{
		ZoomScrollDemo d = new ZoomScrollDemo();
		d.initComponents(true);
		d.setVisible(true);
	}
	
	/// <summary>
	/// Create the JFrame and put controls in it. 
	/// </summary>
	private void initComponents(final boolean closeOnExit) 
	{
		// Do nothing if already initialized
		if (hasFinishedInitialization)
			return;
    	
		setTitle("ChartDirector Zooming and Scrolling Demonstration");
		setResizable(false);

		// End application upon closing main window
		if (closeOnExit)
		{
			addWindowListener(new WindowAdapter() {
				public void windowClosing(WindowEvent e) { System.exit(0); }});
		}
		
		// Top label bar
		JLabel topLabel = new JLabel("Advanced Software Engineering");
		topLabel.setForeground(new java.awt.Color(255, 255, 51));
		topLabel.setBackground(new java.awt.Color(0, 0, 128));
		topLabel.setBorder(new javax.swing.border.EmptyBorder(2, 0, 2, 5));
		topLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
		topLabel.setOpaque(true);
		getContentPane().add(topLabel, java.awt.BorderLayout.NORTH);

		// Left panel
		JPanel leftPanel = new JPanel(null);
		leftPanel.setBorder(javax.swing.BorderFactory.createRaisedBevelBorder());
		
		// Pointer push button
		pointerPB = new JButton("Pointer", loadImageIcon("pointer.gif"));
		pointerPB.setHorizontalAlignment(SwingConstants.LEFT);
		pointerPB.setMargin(new Insets(5, 5, 5, 5));
		pointerPB.addActionListener(new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt)	{
				pointerPB_Clicked();
			}});
		leftPanel.add(pointerPB).setBounds(1, 0, 148, 24);
        
		// Zoom In push button
		zoomInPB = new JButton("Zoom In", loadImageIcon("zoomin.gif"));
		zoomInPB.setHorizontalAlignment(SwingConstants.LEFT);
		zoomInPB.setMargin(new Insets(5, 5, 5, 5));
		zoomInPB.addActionListener(new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt)	{
				zoomInPB_Clicked();
			}});		
		leftPanel.add(zoomInPB).setBounds(1, 24, 148, 24);

		// Zoom out push button
		zoomOutPB = new JButton("Zoom Out", loadImageIcon("zoomout.gif"));
		zoomOutPB.setHorizontalAlignment(SwingConstants.LEFT);
		zoomOutPB.setMargin(new Insets(5, 5, 5, 5));
		zoomOutPB.addActionListener(new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt)	{
				zoomOutPB_Clicked();
			}});		
		leftPanel.add(zoomOutPB).setBounds(1, 48, 148, 24);

		// Zoom mode label
		leftPanel.add(new JLabel("Zoom Mode")).setBounds(5, 80, 130, 20);
	
		// X Zoom push button
		xZoomPB = new JButton("X Zoom / Y Auto", loadImageIcon("xrange.gif"));
		xZoomPB.setHorizontalAlignment(SwingConstants.LEFT);
		xZoomPB.setMargin(new Insets(5, 5, 5, 5));
		xZoomPB.addActionListener(new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt)	{
				xZoomPB_Clicked();
			}});		
		leftPanel.add(xZoomPB).setBounds(1, 100, 148, 25);

		// XY Zoom push button
		xyZoomPB = new JButton("XY Zoom", loadImageIcon("xyrange.gif"));
		xyZoomPB.setHorizontalAlignment(SwingConstants.LEFT);
		xyZoomPB.setMargin(new Insets(5, 5, 5, 5));
		xyZoomPB.addActionListener(new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt)	{
				xyZoomPB_Clicked();
			}});	
		leftPanel.add(xyZoomPB).setBounds(1, 124, 148, 24);
			
		// Start Date label
		leftPanel.add(new JLabel("Start Date")).setBounds(5, 160, 130, 20);
		
		// Start Year, Start Month, Start Day combo boxes
		startYear = new JComboBox();
		startMonth = new JComboBox(new Object[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", 
			"10", "11", "12"} );
		startDay = new JComboBox(new Object[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", 
			"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
			"24", "25", "26", "27", "28", "29", "30", "31"} );
		leftPanel.add(startYear).setBounds(1, 180, 60, 20);
		leftPanel.add(startMonth).setBounds(61, 180, 44, 20);
		leftPanel.add(startDay).setBounds(105, 180, 44, 20);
		ActionListener startDateHandler = new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				startDate_ValueChanged(); 
			}};
		startYear.addActionListener(startDateHandler);
		startMonth.addActionListener(startDateHandler);
		startDay.addActionListener(startDateHandler);
		
		// Duration label
		leftPanel.add(new JLabel("Duration (Days)")).setBounds(5, 212, 130, 20);
		
		// Duration combo box
		duration = new JComboBox(new Object[] { "10", "20", "30", "60", "90", "180", "360", "720",
			"1080", "1440" });
		duration.setEditable(true);
		duration.addActionListener(new ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				duration_ValueChanged(); 
			}			
		});
		leftPanel.add(duration).setBounds(1, 232, 148, 20);
		
		// Total expected panel size
		leftPanel.setPreferredSize(new Dimension(150, 264));
		
		// Chart Viewer
		chartViewer1 = new ChartViewer();
		chartViewer1.setBackground(new java.awt.Color(255, 255, 255));
		chartViewer1.setOpaque(true);
		chartViewer1.setPreferredSize(new Dimension(616, 316));
		chartViewer1.setHorizontalAlignment(SwingConstants.CENTER);
		chartViewer1.setHotSpotCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		chartViewer1.addViewPortListener(new ViewPortAdapter() {
			public void viewPortChanged(ViewPortChangedEvent e) {
				chartViewer1_ViewPortChanged(e);
			}
		});
		chartViewer1.addHotSpotListener(new HotSpotAdapter() {
			public void hotSpotClicked(HotSpotEvent e) {
				chartViewer1_HotSpotClicked(e);
		}});
		chartViewer1.addMouseListener(new MouseAdapter() {
			public void mouseEntered(MouseEvent e) {
				chartViewer1_MouseEntered();
			}
		});
		
		// Vertical Scroll Bar
		vScrollBar1 = new JScrollBar(JScrollBar.VERTICAL, 0, 100000000, 0, 1000000000);
		vScrollBar1.addAdjustmentListener(new AdjustmentListener() {
			public void adjustmentValueChanged(AdjustmentEvent e) {
				vScrollBar1_ValueChanged();		 
			}
		});

		// Horizontal Scroll bar
		hScrollBar1 = new JScrollBar(JScrollBar.HORIZONTAL, 0, 100000000, 0, 1000000000);
		hScrollBar1.addAdjustmentListener(new AdjustmentListener() {
			public void adjustmentValueChanged(AdjustmentEvent e) {
				hScrollBar1_ValueChanged();		 
			}
		});

		// We need to put the horizontal scroll bar inside a panel with a filler, because
		// the horizontal scroll bar does not exactly touch the right edge of the right panel
		JPanel filler = new JPanel();
		filler.setPreferredSize(new Dimension(vScrollBar1.getPreferredSize().width, 1));
		JPanel bottomScrollPanel = new JPanel(new BorderLayout());
		bottomScrollPanel.add(hScrollBar1, java.awt.BorderLayout.CENTER);
		bottomScrollPanel.add(filler, java.awt.BorderLayout.EAST);

		// Put the ChartViewer and the scroll bars in the right panel
		JPanel rightPanel = new JPanel(new BorderLayout());
		rightPanel.add(chartViewer1, java.awt.BorderLayout.CENTER);
		rightPanel.add(vScrollBar1, java.awt.BorderLayout.EAST);
		rightPanel.add(bottomScrollPanel, java.awt.BorderLayout.SOUTH);
		
		// Put the leftPanel and rightPanel on the JFrame
		getContentPane().add(leftPanel, java.awt.BorderLayout.WEST);
		getContentPane().add(rightPanel, java.awt.BorderLayout.CENTER);
		
		// Set all UI fonts (except labels)
		Font uiFont = new Font("Dialog", Font.PLAIN, 11);
		for (int i = 0; i < leftPanel.getComponentCount(); ++i)
		{
			Component c = leftPanel.getComponent(i);
			if (!(c instanceof JLabel))
				c.setFont(uiFont);
		}

		// In this demo, we obtain the horizontal scroll range from the actual data.
		minDate = startDate[0];
		dateRange = (endDate[endDate.length - 1].getTime() - minDate.getTime()) / 1000;

		// Set the date range of the startYear combo box to match the scrollable date range.
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(minDate);
		int minYear = calendar.get(Calendar.YEAR);
		calendar.add(Calendar.SECOND, (int)dateRange);
		int maxYear = calendar.get(Calendar.YEAR);

		startYear.removeAllItems();
		for (int i = minYear; i <= maxYear; ++i)
			startYear.addItem(new Integer(i));

		// Set ChartViewer to reflect the visible and minimum duration
		chartViewer1.setZoomInWidthLimit(minDuration / dateRange);
		chartViewer1.setViewPortWidth(currentDuration / dateRange);
		chartViewer1.setViewPortLeft(1 - chartViewer1.getViewPortWidth());
		
		// Initially choose the pointer mode (draw to scroll mode)
		pointerPB.doClick();
		xZoomPB.doClick();		

		// Can update the chart now
		pack();
		hasFinishedInitialization = true;
		chartViewer1.updateViewPort(true, true);
	}

	/// <summary>
	/// A utility to load an image icon from the Java class path
	/// </summary>
	private ImageIcon loadImageIcon(String path)
	{
		try { return new ImageIcon(getClass().getClassLoader().getResource(path)); }
		catch (Exception e) { return null; }
	}
	
	/// <summary>
	/// Click event for the pointerPB.
	/// </summary>
	private void pointerPB_Clicked()
	{
		pointerPB.setBackground(new Color(0x80, 0xff, 0x80));
		zoomInPB.setBackground(null);
		zoomOutPB.setBackground(null);
		chartViewer1.setMouseUsage(Chart.MouseUsageScrollOnDrag);
	}

	/// <summary>
	/// Click event for the zoomInPB.
	/// </summary>
	private void zoomInPB_Clicked()
	{
		pointerPB.setBackground(null);
		zoomInPB.setBackground(new Color(0x80, 0xff, 0x80));
		zoomOutPB.setBackground(null);
		chartViewer1.setMouseUsage(Chart.MouseUsageZoomIn);
	}

	/// <summary>
	/// Click event for the zoomOutPB.
	/// </summary>
	private void zoomOutPB_Clicked()
	{
		pointerPB.setBackground(null);
		zoomInPB.setBackground(null);
		zoomOutPB.setBackground(new Color(0x80, 0xff, 0x80));
		chartViewer1.setMouseUsage(Chart.MouseUsageZoomOut);
	}
	
	/// <summary>
	/// Click event for the xZoomPB. Sets X-Zoom / Y-Axis auto-scaled mode.
	/// </summary>
	private void xZoomPB_Clicked()
	{
		xZoomPB.setBackground(new Color(0x80, 0xff, 0x80));
		xyZoomPB.setBackground(null);

		// Horizontal zooming and scrolling only
		chartViewer1.setZoomDirection(Chart.DirectionHorizontal);
		chartViewer1.setScrollDirection(Chart.DirectionHorizontal);
				
		// Viewport is always unzoomed as y-axis is auto-scaled
		chartViewer1.setViewPortTop(0);
		chartViewer1.setViewPortHeight(1);
				
		// Update chart to auto-scale axis
		if (hasFinishedInitialization)
			chartViewer1.updateViewPort(true, false);
	}

	/// <summary>
	/// Click event for the xZoomPB. Set XY-Zoom mode.
	/// </summary>
	private void xyZoomPB_Clicked()
	{
		xZoomPB.setBackground(null);
		xyZoomPB.setBackground(new Color(0x80, 0xff, 0x80));
		
		// Horizontal and Vertical zooming and scrolling
		chartViewer1.setZoomDirection(Chart.DirectionHorizontalVertical);
		chartViewer1.setScrollDirection(Chart.DirectionHorizontalVertical);		
	}
		
	/// <summary>
	/// Event handler for startYear, startMonth and startDay.
	/// </summary>
	private void startDate_ValueChanged()
	{
		if (hasFinishedInitialization && !chartViewer1.isInViewPortChangedEvent())
		{
			// Get the date represented by the combo boxes
			GregorianCalendar startYMD = new GregorianCalendar(
				Integer.parseInt(startYear.getSelectedItem().toString()), 
				startMonth.getSelectedIndex(), startDay.getSelectedIndex() + 1);
			Date startDate = startYMD.getTime();
			
			// Set the view port to reflect the selected date
			chartViewer1.setViewPortLeft((startDate.getTime() - minDate.getTime()) / dateRange / 1000);
			chartViewer1.updateViewPort(true, false);
		}
	}
	
	/// <summary>
	/// Sets the startYear, startMonth and startDay to the given date.
	/// </summary>
	private void setStartDate(Date d)
	{
		GregorianCalendar startYMD = new GregorianCalendar();
		startYMD.setTime(d);
		
		startYear.setSelectedItem(new Integer(startYMD.get(Calendar.YEAR)));
		startMonth.setSelectedIndex(startYMD.get(Calendar.MONTH));
		normalizeDate();
		startDay.setSelectedIndex(startYMD.get(Calendar.DAY_OF_MONTH) - 1);
	}
	
	/// <summary>
	/// Normalize the startDay combo box to ensure it only shows the valid days for the month.
	/// </summary>
	private void normalizeDate()
	{
		final int[] daysTable = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
		int daysInMonth = daysTable[Integer.parseInt(startMonth.getSelectedItem().toString()) - 1];
		if ((daysInMonth == 28) && (Integer.parseInt(startYear.getSelectedItem().toString()) % 4 == 0))
			++daysInMonth; 
		
		int currentDay = Integer.parseInt(startDay.getSelectedItem().toString());
		while (daysInMonth < startDay.getItemCount())
			startDay.removeItemAt(startDay.getItemCount() - 1);
		while (daysInMonth > startDay.getItemCount())
			startDay.addItem(new Integer(startDay.getItemCount() + 1));
		if (currentDay > daysInMonth)
			startDay.setSelectedIndex(daysInMonth - 1);
	}
	
	/// <summary>
	/// Event handler for duration.
	/// </summary>
	private void duration_ValueChanged()
	{
		if (hasFinishedInitialization && !chartViewer1.isInViewPortChangedEvent())
		{
			try 
			{ 
				//get the duration chosen or entered by the user
				double enteredDuration = Double.parseDouble(duration.getSelectedItem().toString()) 
					* 86400;
				if (enteredDuration <= minDuration)
					enteredDuration = minDuration;
					
				// Check if duration has really changed - sometimes the combo box may issue 
				// redundant value changed events when value has not actually changed.
				double newViewPortWidth = enteredDuration / dateRange;
				if (Math.abs(chartViewer1.getViewPortWidth() - newViewPortWidth) > 
					0.00001 * chartViewer1.getViewPortWidth())
				{
					// Set the view port based on the duration
					chartViewer1.setViewPortWidth(newViewPortWidth);
					chartViewer1.updateViewPort(true, false);
				}				
			}
			catch (Exception e)
			{
				// If user entered invalid text as duration, we just reset the duration
				duration.setSelectedItem("" + 
					Math.round(chartViewer1.getViewPortWidth() * dateRange / 86400));
			}
		}		
	}

	/// <summary>
	/// Horizontal ScrollBar ValueChanged event handler
	/// </summary>
	private void hScrollBar1_ValueChanged()
	{
		if (hasFinishedInitialization && !chartViewer1.isInViewPortChangedEvent())
		{
			// Get the view port left as according to the scroll bar
			double newViewPortLeft = ((double)(hScrollBar1.getValue() - hScrollBar1.getMinimum())) 
				/ (hScrollBar1.getMaximum() - hScrollBar1.getMinimum());

			// Check if view port has really changed - sometimes the scroll bar may issue redundant
			// value changed events when value has not actually changed.
			if (Math.abs(chartViewer1.getViewPortLeft() - newViewPortLeft) > 
				0.00001 * chartViewer1.getViewPortWidth())
			{
				// Set the view port based on the scroll bar
				chartViewer1.setViewPortLeft(newViewPortLeft);
	
				// Update the chart display without updating the image maps. We delay updating
				// the image map because the chart may still be unstable (still scrolling).
				chartViewer1.updateViewPort(true, false);
			}
		}
	}

	/// <summary>
	/// Vertical ScrollBar ValueChanged event handler
	/// </summary>
	private void vScrollBar1_ValueChanged()
	{
		if (hasFinishedInitialization && !chartViewer1.isInViewPortChangedEvent())
		{
			// Get the view port top as according to the scroll bar
			double scrollBarTop = ((double)(vScrollBar1.getValue() - vScrollBar1.getMinimum())) 
				/ (vScrollBar1.getMaximum() - vScrollBar1.getMinimum());
			
			// Check if view port has really changed - sometimes the scroll bar may issue redundant
			// value changed events when value has not actually changed.
			if (Math.abs(chartViewer1.getViewPortTop() - scrollBarTop) >  
				0.00001 * chartViewer1.getViewPortHeight())
			{
				// Set the view port based on the scroll bar
				chartViewer1.setViewPortTop(scrollBarTop);
	
				// Update the chart display without updating the image maps. We delay updating
				// the image map because the chart may still be unstable (still scrolling).
				chartViewer1.updateViewPort(true, false);
			}
		}		
	}
	
	/// <summary>
	/// The MouseEntered handler for the ChartViewer. In this demo, we delay creating the image 
	/// map until the mouse actually enters the chart. This avoids creating unnecessary image
	/// maps while the chart is still scrolling.
	/// </summary>
	private void chartViewer1_MouseEntered()
	{
		updateImageMap(chartViewer1);
	}

	/// <summary>
	///	Handler when a hot spot on a chart is clicked. In this demo, we just list out the hot spot
	/// information in a pop up dialog.
	/// </summary>
	private void chartViewer1_HotSpotClicked(HotSpotEvent e)
	{
		// We show the pop up dialog only when the mouse action is not in zoom-in or zoom-out mode.
		if ((chartViewer1.getMouseUsage() != Chart.MouseUsageZoomIn) && 
			(chartViewer1.getMouseUsage() != Chart.MouseUsageZoomOut))
			showHotSpotParam(e);
	}
	
	/// <summary>
	///	Utility to list out all hot spot parameters on a pop-up dialog
	/// </summary>
	private void showHotSpotParam(HotSpotEvent e)
	{
		//Get all parameters and sort them by key
		Hashtable parameters = e.getAttrValues();
		Object[] attributes = parameters.keySet().toArray();
		Arrays.sort(attributes);
	
		//Create a JTable to show the hot spot attribute/value pairs
		Object[][] rows = new Object[parameters.size()][2];
		for (int i = 0; i < attributes.length; ++i)
		{
			rows[i][0] = attributes[i];
			rows[i][1] = parameters.get(attributes[i]);
		}
		JTable table = new JTable(rows, new Object[] {"Parameter", "Value"});

		//Show the table in a dialog
		JDialog d = new JDialog(this, "Hot Spot Parameters", true);
		d.setSize(300, 300);
		Container container = d.getContentPane();

		//Just add some descriptive text to the dialg
		JTextArea t = new JTextArea ("This dialog is for demonstration only." +
			" In this demo, we simply list out all hot spot parameters.");
		t.setLineWrap(true);
		t.setWrapStyleWord(true);
		t.setEditable(false);
		t.setOpaque(false);
		t.setMargin(new Insets(5, 5, 5, 5));
		container.add(t, BorderLayout.NORTH);
	
		//Create the scroll pane on the dialog and add the table to it.
		JScrollPane scrollPane = new JScrollPane(table);
		container.add(scrollPane);

		//Show the dialog on where the mouse click occur	
		Point topLeft = ((ChartViewer)e.getSource()).getLocationOnScreen();
		d.setLocation(topLeft.x + e.getX(), topLeft.y + e.getY());
		d.setVisible(true);
	}
	
	/// <summary>
	/// The ViewPortChanged event handler. This event occurs when the user changes the ChartViewer
	/// view port by dragging scrolling, or by zoom in/out, or the ChartViewer.updateViewPort method
	/// is being called.
	/// </summary>
	private void chartViewer1_ViewPortChanged(ViewPortChangedEvent e)
	{
		// Compute the view port start date and duration
		Date currentStartDate = new Date(minDate.getTime() + Math.round(chartViewer1.getViewPortLeft() * 
			dateRange) * 1000);
		currentDuration = Math.round(chartViewer1.getViewPortWidth() * dateRange);

		// Synchronize the startDate and duration controls
		setStartDate(currentStartDate);
		duration.setSelectedItem("" + Math.round(currentDuration / 86400));

		// Synchronize the horizontal scroll bar with the ChartViewer
		hScrollBar1.setEnabled(chartViewer1.getViewPortWidth() < 1);
		hScrollBar1.setVisibleAmount((int)Math.ceil(chartViewer1.getViewPortWidth() * 
			(hScrollBar1.getMaximum() - hScrollBar1.getMinimum())));
		hScrollBar1.setBlockIncrement(hScrollBar1.getVisibleAmount());
		hScrollBar1.setUnitIncrement((int)Math.ceil(hScrollBar1.getVisibleAmount() * 0.1));
		hScrollBar1.setValue((int)Math.round(chartViewer1.getViewPortLeft() * 
			(hScrollBar1.getMaximum() - hScrollBar1.getMinimum())) + hScrollBar1.getMinimum());
		
		// Synchronize the vertical scroll bar with the ChartViewer
		vScrollBar1.setEnabled(chartViewer1.getViewPortHeight() < 1);
		vScrollBar1.setVisibleAmount((int)Math.ceil(chartViewer1.getViewPortHeight() * 
			(vScrollBar1.getMaximum() - vScrollBar1.getMinimum())));
		vScrollBar1.setBlockIncrement(vScrollBar1.getVisibleAmount());
		vScrollBar1.setUnitIncrement((int)Math.ceil(vScrollBar1.getVisibleAmount() * 0.1));
		vScrollBar1.setValue((int)Math.round(chartViewer1.getViewPortTop() * 
			(vScrollBar1.getMaximum() - vScrollBar1.getMinimum())) + vScrollBar1.getMinimum());
		
		// Update chart and image map if necessary
		if (e.needUpdateChart())
			drawChart(chartViewer1);
		if (e.needUpdateImageMap())
			updateImageMap(chartViewer1);	
	}

	/// <summary>
	/// Draw the chart.
	/// </summary>
	private void drawChart(ChartViewer viewer)
	{ 
		//
		// In this demo, we copy the visible part of the data to a separate buffer for chart
		// plotting. 
		//
		// Note that if you only have a small amount of data (a few hundred data points), it
		// may be easier to just plot all data in any case (so the following copying code is 
		// not needed), and let ChartDirector "clip" the chart to the plot area. 
		//

		// Using ViewPortLeft and ViewPortWidth, get the start and end dates of the view port.
		Date viewPortStartDate = new Date(minDate.getTime() + Math.round(viewer.getViewPortLeft() *
			dateRange) * 1000);
		Date viewPortEndDate = new Date(viewPortStartDate.getTime() + 
			Math.round(viewer.getViewPortWidth() * dateRange) * 1000);
			
		int startTask = (int)Math.floor(viewer.getViewPortTop() * labels.length);
		int endTask = (int)Math.floor((viewer.getViewPortTop() + viewer.getViewPortHeight()) * labels.length - 0.001);

		Date[] visibleStartDate = new Date[endTask - startTask + 1];
		Date[] visibleEndDate = new Date[visibleStartDate.length];
		String[] visibleLabels = new String[visibleStartDate.length];
		
		System.arraycopy(startDate, startTask, visibleStartDate, 0, visibleStartDate.length);
		System.arraycopy(endDate, startTask, visibleEndDate, 0, visibleStartDate.length);
		System.arraycopy(labels, startTask, visibleLabels, 0, visibleStartDate.length);
				
		//
		// Now we have obtained the data, we can plot the chart. 
		//

		///////////////////////////////////////////////////////////////////////////////////////
		// Step 1 - Configure overall chart appearance. 
		///////////////////////////////////////////////////////////////////////////////////////

		// Create a XYChart object of size 620 x 280 pixels. Set background color to
		// light blue (ccccff), with 1 pixel 3D border effect.
		XYChart c = new XYChart(620, 280, 0xccccff, 0x000000, 1);

		// Add a title to the chart using 15 points Times Bold Itatic font, with
		// white (ffffff) text on a deep blue (000080) background
		c.addTitle("Simple Gantt Chart Demo", "Times New Roman Bold Italic", 15,
			0xffffff).setBackground(0x000080);

		// Set the plotarea at (140, 55) and of size 460 x 200 pixels. Use
		// alternative white/grey background. Enable both horizontal and vertical
		// grids by setting their colors to grey (c0c0c0). Set vertical major grid
		// (represents month boundaries) 2 pixels in width
		c.setPlotArea(140, 55, 460, 200, 0xffffff, 0xeeeeee, Chart.LineColor,
			0xc0c0c0, 0xc0c0c0).setGridWidth(2, 1, 1, 1);

		// swap the x and y axes to create a horziontal box-whisker chart
		c.swapXY();
		c.setClipping();
		
		///////////////////////////////////////////////////////////////////////////////////////
		// Step 2 - Add data to chart
		///////////////////////////////////////////////////////////////////////////////////////
		
		// 
		// In this example, we represent the data by lines. You may modify the code below if 
		// you want to use other representations (areas, scatter plot, etc).
		//

		// Add a green (33ff33) box-whisker layer showing the box only.
		c.addBoxWhiskerLayer(Chart.CTime(visibleStartDate), Chart.CTime(visibleEndDate), null,
			null, null, 0x00cc00, Chart.SameAsMainColor, Chart.SameAsMainColor);


		///////////////////////////////////////////////////////////////////////////////////////
		// Step 3 - Set up y-axis scale
		///////////////////////////////////////////////////////////////////////////////////////

		// Set the y-axis scale to be date scale from Aug 16, 2004 to Nov 22, 2004,
		// with ticks every 7 days (1 week)
		c.yAxis().setDateScale(viewPortStartDate, viewPortEndDate, 86400 * 7);

		// Set multi-style axis label formatting. Month labels are in Arial Bold font
		// in "mmm d" format. Weekly labels just show the day of month and use minor
		// tick (by using '-' as first character of format string).
		c.yAxis().setMultiFormat(Chart.StartOfMonthFilter(),
			"<*font=Arial Bold*>{value|mmm d}", Chart.StartOfDayFilter(),
			"-{value|d}");

		// Set the y-axis to shown on the top (right + swapXY = top)
		c.setYAxisOnRight();

		///////////////////////////////////////////////////////////////////////////////////////
		// Step 4 - Set up x-axis scale
		///////////////////////////////////////////////////////////////////////////////////////
			
		// Set the labels on the x axis
		c.xAxis().setLabels(visibleLabels);

		// Reverse the x-axis scale so that it points downwards.
		c.xAxis().setReverse();

		// Set the horizontal ticks and grid lines to be between the bars
		c.xAxis().setTickOffset(0.5);

		///////////////////////////////////////////////////////////////////////////////////////
		// Step 5 - Display the chart
		///////////////////////////////////////////////////////////////////////////////////////
		
		chartViewer1.setChart(c);
	}
	
	/// <summary>
	/// Update the image map used on the chart.
	/// </summary>
	private void updateImageMap(ChartViewer viewer)
	{
		// Include tool tip for the chart
		if (viewer.getImageMap() == null)
		{
			viewer.setImageMap(viewer.getChart().getHTMLImageMap("clickable", "",
				"title='{xLabel}: {top|mmm dd, yyyy} to {bottom|mmm dd, yyyy}'"));
		}
	}
	
	//
	// Implementation of the DemoModule interface to allow this demo to run inside the 
	// ChartDirectorDemo browser
	//
    
	// Name of demo program
	public String toString() 
	{ 
		return "Zoom/Scroll Demo"; 
	}

	// Number of charts produced in this demo
	public int getNoOfCharts() 
	{ 
		// This demo open its own frame instead of using the right pane of the ChartDirectorDemo 
		// browser for display, so we just load the frame, then returns 0.
		initComponents(false); 
		setVisible(true); 
		return 0; 
	}

	// Main code for creating charts
	public void createChart(ChartViewer viewer, int index)
	{
		// do nothing, as the ChartDirectorDemo browser right pane is not used
	}
}


  Re: Questions about Gantt Charts please help
Posted by AJ on Sep-16-2009 19:41
Hi Peter,

Thank you for your fast reply and help. As of the moment it works like what I am looking for
from the beginning. I will try now to plot my own data on the chart.

I will keep you posted about my progress may the entire outcome be a success or if some
questions pop along the way. I appreciate all of your efforts for helping me.

Thank you very much.

Regards,

aj

  Re: Questions about Gantt Charts please help
Posted by AJ on Oct-05-2009 21:16
Hello Peter,

It's been a while. Everything is working fine I am now able to plot my own data and
customize it to some of my specific needs. Moreover, I was able to implement your
"multilayer" gantt chart sample with the "multi" bars responding to the zoom and scroll
functionality.

I just have another question with regards to it.


a. in the multigantt sample it is like the striped red bar is shown by providing its
corresponding start and end date too just like the original solid color bars. Is it possible to
put some sort of a label (not really java label but a marking) but not using the start and end
date? I am thinking of..say 1 bar (any bar), its length is the total of 100%. I would like to
have some sort of marking that will label it as 50,60 % and etc.

If my thoughts are confusing I am just asking if it is possible to mark the chart and the bars
in it like what the "multilayer gantt" sample is doing with the use of some other "technique"
and not by providing the start and end dates.

If you have an example for this or something similar may be in your docs  (I browsed
through it but may be I missed it) or other previous discussions kindly point me to it.

Thanks Peter your help really makes a lot  of difference.

regards,

Aj

  Re: Questions about Gantt Charts please help
Posted by Peter Kwan on Oct-06-2009 01:49
Hi AJ,

I assume your requirement is that you need to put some labels on the bars, but the labels are not related to the data that are used to draw the bars (that is, the labels can be considered as some serial numbers or some arbitrary text strings or numbers).

To do this, you may add an extra field to the layer and ask ChartDirector to display that field as the bar label. For example:

//layer = the BoxWhiskerLayer that contains your bars
layer.addExtraField(anArrayOfTextStrings);

//show the extra field as the data label
layer.setDataLabelFormat("{field0}");
layer.setDataLabelStyle("Arial Bold", 8, 0x000000).setAlignment(Chart.Center);

Hope this can help.

Regards
Peter Kwan

  Re: Questions about Gantt Charts please help
Posted by AJ on Oct-06-2009 10:38
Attachments:
Hi Peter,

It works perfectly fine like what I was looking for. My previous question is now solved
thanks to you again.

I would just want to request for some assistance again with this:

1. The bars in the chart now are responding to the zoom/scroll functionality which shows
only the visible items. I tried to put like 30 items (sample only) of labels and
corresponding start and end dates then I set the "visible things" to 10. What happens is
that indeed I can only see the first 10 items out of the 30 but the plot area (white
background grid) is somehow divided by the original length of my items. It doesn't
allocate or a lot the entire plot area for the first 10 (this is in max zoom out mode). How
would I be able to do that? That out of X number of items it will only show that and
somehow "allocate" the entire plot area to it, so that when I scroll vertically (or even
horizontally) the "standard" number of data is 10 or what I want to initially set out of the
totality and the items will just change/scroll accordingly.

What I'm doing is I'm dividing the items so that it will show the visible things which i think
is not the right approach (dividing it by 3 won't show the remaining) because what I am
looking for is to show the total items in "segments"  based on what I am trying to
attempt earlier by dividing it by 3 is 10..so 3 "segments".

I hope I was able to express clearly my concern. I also attached the test file where I am
trying things.

I'd like to extend my apologies because even though I have an idea of what my problem
is and what to do yet from time to time I ask for help because as for the
execution/specifics I am uncertain. Just the same I am thankful for all of your efforts.

Regards,

Aj
ZoomScroll2.java
ZoomScroll2.java

34.50 Kb

  Re: Questions about Gantt Charts please help
Posted by Peter Kwan on Oct-07-2009 01:59
Hi AJ,

If the gantt chart allocate space for 30 items, it must be because your code pass the data for 30 items to ChartDirector. If your code only pass the data for the first 10 items, ChartDirector should have no way to know that the full data contains 30 items.

In your case, the array that contains 30 items is "taskNo". In your code, you use "layer.setXData(taskNo);", and the "taskNo" contains data for all 30 items. So ChartDirector must allocate enough space for the data.

To solve the problem, please pass only the data for the visible task to ChartDirector. For example:

double[] visibleTaskNo = new double[visibleStartDate.length];
System.arraycopy(taskNo, startTask, visibleTaskNo, 0, visibleStartDate.length);
//note - the task number is relative to the first visible task
for (int i = 0; i < visibleTaskNo.length; ++i) visibleTaskNo[i] -= startTask;

layer.setXData(visibleTaskNo);

Hope this can help.

Regards
Peter Kwan

  Re: Questions about Gantt Charts please help
Posted by AJ on Oct-07-2009 16:39
Attachments:
Hi Peter,

Thanks for the fast response as always. The chart displays the labels visible as intend when
in zoom and allocates spaces accordingly too. However, I noticed something "wrong" when I
hit the "XYZoom" and "ZoomIn" once it will show the visible labels, bars and provide the
suitable spaces too which is correct and by doing so the Vertical Scroll will be enabled. So
now I can scroll down and see the rest of the list. But, as I go down the labels on the left
side of the chart little by little goes up and does not occupy the total area intended for the
chart (white grid) and the colored bar counter part of each label is not synchronized where
the label is.

I don't know if I did something wrong based on your previous message or whether this
requires another solution. I included my file so you may see first hand what my concern is in
case my narration was confusing or unclear.

Thank you very much Peter for you assistance.

Regards,

Aj
ZoomScroll2.java
ZoomScroll2.java

35.95 Kb

  Re: Questions about Gantt Charts please help
Posted by Peter Kwan on Oct-08-2009 00:42
Hi AJ,

In your code, I found the lines:

for (int i = 0; i <visibleTaskNo.length; ++i)
     layer.setXData(visibleTaskNo);

The above code is incorrect and is different from the code I suggested in my last message. Please do not use the above code. Instead, please use the code I suggested in my last message. I copied the code below for your reference:

for (int i = 0; i < visibleTaskNo.length; ++i) visibleTaskNo[i] -= startTask;

layer.setXData(visibleTaskNo);

Hope this can help.

Regards
Peter Kwan

  Re: Questions about Gantt Charts please help
Posted by AJ on Oct-08-2009 08:28
Hi Peter,

Sorry my mistake, I overlooked it and thought i just have to traverse the visibleLabels not
knowing I forgot an important step. Just the same thanks.

Meanwhile, while I was trying out things with the chart I had something that I want to
implement though it did not merit to what I was thinking. This is about the setting of the
label style I assume this is the code that does it  c.xAxis().setLabelStyle("Arial Bold", 8,
111111); However, I also noticed that it changes the entire list but what I am looking for to
do is to implement that or treat each changes relative per label and not implement the
change to the whole. (ie. I have 10 labels i want all the even no.s to be bold and color red
and the rest blue or whatever or may be pass an array of font style and font color so it will
implement the specific change per specific index of the label.)

Thank you for your time and patience.

Regards,

AJ

  Re: Questions about Gantt Charts please help
Posted by Peter Kwan on Oct-09-2009 01:08
Hi AJ,

You can use CDML to achieve what you want. For example, you can use following in a label:

<*font=Arial Bold,color=FF0000*>Hello World

The above label will be in Arial Bold font in red.

Hope this can help.

Regards
Peter Kwan

  Re: Questions about Gantt Charts please help
Posted by AJ on Oct-12-2009 16:54
Hi Peter,

Thank you for your previous post it worked like a charm.

By the way, what if the chart needs to be printed how do we accommodate that? I am
particularly concerned about the size and length of the chart because if I have a lot of
items on the x-axis and my chart runs for a year that is quite long and has a huge number
of data. I just want to make sure that it would be able to print properly.

I browsed the ChartDirector v5.0 doc and there seems to be none that tackles this but then
again maybe I missed it. Can you suggest any approach, previous discussion etc. regarding
this and maybe explain or point out how it prints the material.

Thank you for your time and support.

Regards,

AJ

  Re: Questions about Gantt Charts please help
Posted by Peter Kwan on Oct-13-2009 00:26
Hi AJ,

Printing is a function of the Java framework, not of ChartDirector, that's why you cannot find printing documentation in ChartDirector. To find out how to print things, please refer to the Java documentation. For example:

http://java.sun.com/docs/books/tutorial/2d/printing/

The following is an example:

//assume g is the Graphics object for your printer, and c is the ChartDirector chart object
g.draw(c.makeImage(), 100, 100, null);

Hope this can help.

Regards
Peter Kwan