Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Facet Chart - how to limit X labels

    Hello,

    I wonder how to limit number of labels on X axis on Facet Chart. Currently, X axis covers 24 hours period with data entries for every 15 minutes period. When chart is small, it doesn't look good.

    I'm using SmartGWT Full Demo on Chrome.

    Thanks in advance,
    Sava.
    Attached Files

    #2
    The labels on the axis are based on the data fed to the FacetChart. So you could reduce the number of points before providing the data to the chart, or your could provide explicit facet.values where you set the titles for some points to  .

    Comment


      #3
      In our case it was important to keep number of points, since smoothness of the graph and rate of change in graph depends of number of points.

      Is it possible to reduce number of X labels, not points? Like, have one point every 5 minutes, while showing one timestamp label per hour on X axis?

      Facet chart does it automatically on Y axes - when chart is small, it shows just labels for 0 and 100, while maximized chart has 0,10, 20...100 for maximized chart. How to get the same functionality for X axis?

      Thanks,
      Sava.

      Comment


        #4
        We mentioned two approaches in the previous post, the second one solves your issue.

        Comment


          #5
          I have the same business requirement as Sava, and have tried your " " suggestion, but it doesn't solve the problem. This probably makes sense, as multiple values are being mapped to the same x-axis attribute of " "

          What happens is there are indeed fewer x-axis labels, but the corresponding points on the chart (lines in my case) are omitted as well. So in a "time series" chart, where I might have several lines with dozens if not hundreds of data points (imagine stock prices for 6 months, or two years), if I choose to label, say, every 10th day, I only see the price action once every 10 days as well -- clearly a very different looking chart than seeing daily price movements.

          As Sava points out, an acceptable (space-adapting) labeling scheme for the x-axis is already in place on the y-axis.

          I'm using the SmartGWT Pro build from May 3rd, 3.1d.

          Thanks.

          Comment


            #6
            Setting the label to blank should not prevent data display. You may be removing the value instead. If you think you're doing it right, can you show your technique?

            Note X and Y label reduction is a totally different problem (discrete vs continuous).

            Comment


              #7
              I have the same issue. Can you please post sample java source for SmartGWT FacetChart for this?

              Comment


                #8
                How can I return say a dozen dates, that are not every month, say some random distribution in a year. And get that to graph on the x axis?

                All the charts seem to be a string type, and thus assume an even distribution.

                This is really tough to assume for us.

                Thanks,
                Evan

                Comment


                  #9
                  went and tried the moxie GWT wrapper on highstock

                  which works fine, and support irregular x axis values.

                  happy to use smart gwt stuff if it supported this.

                  Comment


                    #10
                    I hadn't forgotten your request from May 4th -- was only now able to get back to this issue.

                    Here's a simple class that demonstrates the problem. Goals:
                    1. Graph two or more time-series lines that don't necessarily all have values for every point on the X axis.
                    2. Visually support hundreds of points (values) in the time-series.
                    3. Limit the number of X axis labels to something legible. Ideally this would be handled for me.

                    Code:
                    public class app_GraphTester implements EntryPoint
                    {
                    
                    	private FacetChart d_chart;
                    	private int d_numPointsInChart = 50;
                    
                    	/**
                         * This is the entry point method.
                         */
                        public void onModuleLoad()
                        {
                            Log.warn("app_GraphTester.onModuleLoad was called.");
                    
                            GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler()
                            {
                                public void onUncaughtException(Throwable e)
                                {
                                    Log.error("Uncaught exception", e);
                                }
                            });
                    
                    
                    		Canvas d_mainCanvas = new Canvas();
                    
                    		// Just to work around some HTML within the page
                    		d_mainCanvas.setTop(300);
                    
                    		VLayout layout = new VLayout();
                    		createChart();
                    
                    		generateDataAndRedraw();
                    
                    		IButton redrawButton = new IButton("Change Data");
                    		redrawButton.addClickHandler(new ClickHandler()
                    		{
                    			public void onClick(ClickEvent event)
                    			{
                    				generateDataAndRedraw();
                    			}
                    		});
                    
                    		layout.addMember(d_chart);
                    		layout.addMember(redrawButton);
                    
                    		d_mainCanvas.addChild(layout);
                    
                    		d_mainCanvas.show();
                        }
                    
                    	private static class GraphDataStruct
                    	{
                    		private int d_index;
                    		private double d_value;
                    
                    		private GraphDataStruct(int index, double value)
                    		{
                    			d_index = index;
                    			d_value = value;
                    		}
                    
                    		public int getIndex()
                    		{
                    			return d_index;
                    		}
                    
                    		public double getValue()
                    		{
                    			return d_value;
                    		}
                    	}
                    
                    	public static class FacetRecord extends Record
                    	{
                    		public FacetRecord(String time, double value, String description) {
                    			setAttribute("time", time);
                    			setAttribute("value", value);
                    			setAttribute("description", description);
                    		}
                    
                    		public String dumpString()
                    		{
                    			StringBuilder buf = new StringBuilder(256);
                    			buf.append("Time: [").append(getAttribute("time")).append("]");
                    			buf.append(",value = [" + getAttributeAsDouble("value")).append("]");
                    			buf.append(",desc [" + getAttribute("description")).append("]");
                    
                    			return buf.toString();
                    		}
                    	}
                    
                    		private FacetChart createChart()
                    	{
                    		Log.warn("Version is " + Version.getVersion());
                    		Log.warn("Major is " + Version.getMajor());
                    		Log.warn("Minor is " + Version.getMinor());
                    		Log.warn("Patch is " + Version.getPatch());
                    		Log.warn("Build Date is " + Version.getBuildDate());
                    
                    		if(!SC.hasCharts()) {
                    			Log.error("No charts?");
                    		}
                    		if(!SC.hasDrawing()) {
                    			Log.error("No drawing.");
                    		}
                    
                    		d_chart = new FacetChart();
                    		d_chart.setWidth(350);
                    		d_chart.setHeight(350);
                    
                    		d_chart.setFacets(new Facet("time", "Day"), new Facet("description", "Node"));
                    		d_chart.setValueTitle("$");
                    		d_chart.setValueProperty("value");
                    
                    		d_chart.setChartType(ChartType.LINE);
                    		d_chart.setTitle("Test of chart with " + d_numPointsInChart + " points");
                    		d_chart.setShowDataAxisLabel(true);
                    		d_chart.setShowValueAxisLabel(true);
                    
                    		// Note that setting this to 'true' slows down the rendering considerably
                    		d_chart.setShowDataPoints(true);
                    
                    		return d_chart;
                    	}
                    
                    	private void generateDataAndRedraw()
                    	{
                    		ArrayList<FacetRecord> graphRecords = new ArrayList<FacetRecord>();
                    
                    		boolean includeSeries2 = false;
                    
                    		ArrayList<GraphDataStruct> series1 = new ArrayList<GraphDataStruct>();
                    		ArrayList<GraphDataStruct> series2 = null;
                    
                    		if (includeSeries2){
                    			series2 = new ArrayList<GraphDataStruct>();
                    		}
                    
                    		HashSet<Integer> labelledIndicies = new HashSet<Integer>();
                    
                    		// Simulate some data being generated by some other process which would be handed off
                    		// to the rendering code.    As series1 will contain all the values, we should see one line
                    		// with 50 data points, and another with something less than 50 data points.   My use case
                    		// requires that the missing points in series2 do not affect the rendering of series1.
                    		int i = 0;
                    		Random rnd = new Random((new Date().getTime()));
                    		while (i < d_numPointsInChart){
                    			int value = ((int)(rnd.nextDouble() * 10)) + 30;
                    
                    			series1.add(new GraphDataStruct(i,value));
                    
                    			if (includeSeries2){
                    				// series 2 will not contain a point for every i value.
                    				if (rnd.nextDouble() < 0.7){
                    					value = ((int)(rnd.nextDouble() * 10)) + 15;
                    					series2.add(new GraphDataStruct(i,value));
                    				}
                    			}
                    
                    			if ((i % 5) == 0){
                    				labelledIndicies.add(i);
                    			}
                    			i++;
                    		}
                    
                    		addSeriesToChart(series1,labelledIndicies,graphRecords,"series 1");
                    		if (includeSeries2){
                    			addSeriesToChart(series2,labelledIndicies,graphRecords,"series 2");
                    		}
                    
                    		i = 0;
                    		Log.warn("Total number of GraphDataRecords: " + graphRecords.size());
                    		for (FacetRecord facetRecord : graphRecords){
                    			Log.warn(i + ": " + facetRecord.dumpString());
                    			i++;
                    		}
                    
                    		d_chart.setData(graphRecords.toArray(new FacetRecord[graphRecords.size()]));
                    
                    
                    	}
                    
                    
                    	private void addSeriesToChart(List<GraphDataStruct> observations,
                    								  HashSet<Integer> labelledIndicies,
                    								  List<FacetRecord> facetRecords,
                    								  String seriesDesc)
                    	{
                    		Log.warn("Processing '" + seriesDesc + "' with " + observations.size() + " observations");
                    		for (GraphDataStruct obs : observations){
                    			int index = obs.getIndex();
                    
                    			String dataLabel = "p" + index;
                    			if (!labelledIndicies.contains(index)){
                    				dataLabel = "x";
                    //				Log.warn("     *** index " + index + " is intentionally unlabeled.");
                    			}
                    			else{
                    			}
                    
                    			facetRecords.add(new FacetRecord(dataLabel, obs.getValue(), seriesDesc));
                    		}
                    	}
                    
                    
                    }
                    As the the attached JPG shows, the chart that should have 50 points in it only has 11, corresponding to the 11 points that have the titles set to something other than "x" (my proxy for your "&nbsp;" which just rendered literally as that string -- I tried enclosing that in HTML tags as well and it also rendered it literally).

                    If I'm horribly confused about all this, it's in how to specify distinct data values for the Y axis while sharing identical values for the attribute that drives the X axis (as per my understanding of your solution). Indeed, what the chart seems to be showing is all of the points that have distinct "time" attribute values -- most of the points share the time attribute value of "x" and are therefore, omitted.

                    Here's a snippet of the logging, showing the values that were generated for one iteration of the chart:
                    Code:
                    (app_GraphTester.java:225) 2012-07-11 11:38:32,284 [WARN ] 40: Time: [p40],value = [35.0],desc [series 1]
                    (app_GraphTester.java:225) 2012-07-11 11:38:32,289 [WARN ] 41: Time: [x],value = [36.0],desc [series 1]
                    (app_GraphTester.java:225) 2012-07-11 11:38:32,291 [WARN ] 42: Time: [x],value = [31.0],desc [series 1]
                    (app_GraphTester.java:225) 2012-07-11 11:38:32,294 [WARN ] 43: Time: [x],value = [31.0],desc [series 1]
                    (app_GraphTester.java:225) 2012-07-11 11:38:32,296 [WARN ] 44: Time: [x],value = [32.0],desc [series 1]
                    (app_GraphTester.java:225) 2012-07-11 11:38:32,298 [WARN ] 45: Time: [p45],value = [32.0],desc [series 1]
                    (app_GraphTester.java:225) 2012-07-11 11:38:32,300 [WARN ] 46: Time: [x],value = [32.0],desc [series 1]
                    (app_GraphTester.java:225) 2012-07-11 11:38:32,304 [WARN ] 47: Time: [x],value = [38.0],desc [series 1]
                    (app_GraphTester.java:225) 2012-07-11 11:38:32,306 [WARN ] 48: Time: [x],value = [33.0],desc [series 1]
                    (app_GraphTester.java:225) 2012-07-11 11:38:32,309 [WARN ] 49: Time: [x],value = [30.0],desc [series 1]
                    Perhaps there's some other way you can restate your solution -- you've made it sound very easy to do this.

                    As per goal #1 above, the 'includeSeries2' local variable can control that, but I've set that to false to make the rendering problem more clear.

                    Please also note this in the code:
                    Code:
                    // Note that setting this to 'true' slows down the rendering considerably
                    d_chart.setShowDataPoints(true);
                    I turned that on for your benefit, to more easily show the distinct points, and was very surprised at the slowdown when the "Change Data" button is clicked.

                    Thanks.
                    Attached Files

                    Comment


                      #11
                      Looks like you missed the direction to use facet.values in our first reply - see Facet.setValues(). By explicitly setting the facet.values you can set up several facetValues that have distinct ids but identical (blank) labels. There is no way to do this while allowing facetValues to be automatically derived from the data (as you attempted).

                      Comment


                        #12
                        Indeed I did miss that... sorry. I got it to work by following the "Example with two facets:" in the FacetChart doc discussing inlinedValues, but it hurt my head for a time series graphing implementation.

                        I'd appreciate a lookover of this code to see if this is what you had in mind, because it's pretty non-intuitive. Also, your "&nbsp;" direction required some tweaking. However, the solution nicely handled my requirement of graphing multiple time series where not every series will have a value for every x-axis value. Unlike the non-inlinedValues attempts, this solution doesn't render 0's for the missing values, but instead nicely connects the adjacent points. The attached JPG shows that.

                        Here's the rendering code, for the others on this thread who expressed an interest:
                        Code:
                        FacetChart chartWidget = new FacetChart();
                        
                        chartWidget.setChartType(ChartType.LINE);
                        String chartTitle = "Test of chart with " + d_numPointsInChart + " points and " + d_series2.size()  + " random points";
                        chartWidget.setTitle(chartTitle);
                        chartWidget.setShowDataAxisLabel(true);
                        chartWidget.setShowValueAxisLabel(true);
                        
                        // Note that setting this to 'true' slows down the rendering considerably
                        chartWidget.setShowDataPoints(false);
                        
                        ArrayList<CellRecord> cellRecords = new ArrayList<CellRecord>();
                        
                        // 'd_series1' and 'd_series2' are populated elsewhere with random values.   series2 intentionally has fewer
                        // values that series1.
                        cellRecords.add(createCellRecord(d_series1, "series 1"));
                        cellRecords.add(createCellRecord(d_series2, "series 2"));
                        
                        ArrayList<FacetValue> xAxisLabels = new ArrayList<FacetValue>();
                        int i = 0;
                        int n = d_numPointsInChart;
                        while (i < n){
                        
                           // This string renders literally:
                           // String dataLabel = "<HTML><BODY>&nbsp;</BODY></HTML>";
                        
                           // This string also renders literally.
                           // String dataLabel = "&nbsp;";
                        
                           //  Interesting -- If dataLabel is "", the chart widget renders the id name instead, like "id17"
                           //  String dataLabel = "";
                        
                           // This works! (a single space char)
                           String dataLabel = " ";
                        
                           // 'd_labelledIndicies' is populated elsewhere.   Ensure the last point gets a label.
                           if ((d_labelledIndicies.contains(i)) || (i == (n-1))){
                             dataLabel = "LABEL (" + i + ")";
                           }
                        
                           FacetValue labelThing = new FacetValue("id" + i,dataLabel);
                           xAxisLabels.add(labelThing);
                           i++;
                        }
                        
                        Facet xAxisFacet = new Facet();
                        xAxisFacet.setInlinedValues(true);
                        xAxisFacet.setValues(xAxisLabels.toArray(new FacetValue[xAxisLabels.size()]));
                        
                        chartWidget.setFacets(xAxisFacet, new Facet("description", "thing"));
                        chartWidget.setData(cellRecords.toArray(new CellRecord[cellRecords.size()]));
                        chartWidget.setValueTitle("Hours");
                        
                        ...
                        private CellRecord createCellRecord(List<GraphDataStruct> observations, String seriesDesc)
                        {
                           Log.warn("Processing '" + seriesDesc + "' with " + observations.size() + " observations");
                           CellRecord record = new CellRecord();
                           record.setAttribute("description",seriesDesc);
                        
                           for (GraphDataStruct obs : observations){
                              int index = obs.getIndex();
                              record.setAttribute("id" + index,obs.getValue());
                           }
                        
                           return record;
                        }
                        Adding the chart to a Window as per attached JPG:
                        Code:
                        chartWidget.setWidth100();
                        chartWidget.setHeight100();
                        
                        Window popup = new Window();
                        popup.setTitle(chartTitle);
                        popup.setDismissOnEscape(false);
                        popup.setCanDragResize(true);
                        popup.setCanDragReposition(true);
                        
                        popup.addItem(chartWidget);
                        popup.setWidth(800);
                        popup.setHeight(500);
                        
                        popup.show();
                        I'm still wondering how I can update an existing FacetChart with new data. I've seen errors like this:
                        Code:
                        java.lang.IllegalStateException: Cannot change configuration property 'facets' to [Lcom.smartgwt.client.widgets.cube.Facet;@31f28bdd after the component has been created.
                        	at com.smartgwt.client.widgets.BaseWidget.error(BaseWidget.java:600)
                        	at com.smartgwt.client.widgets.BaseWidget.error(BaseWidget.java:588)
                        	at com.smartgwt.client.widgets.BaseWidget.setAttribute(BaseWidget.java:683)
                        	at com.smartgwt.client.widgets.chart.FacetChart.setFacets(FacetChart.java:1871)
                        This is what led me to change my earlier-posted example with the "Change Data" button into one that pops up the chart in a Window. If I have some screen real estate dedicated to a chart and my data changes, I need to be able to handle that.

                        I hope all of this helps someone else.
                        Attached Files
                        Last edited by dzarras; 11 Jul 2012, 19:13.

                        Comment


                          #13
                          Thanks for posting your solution, sorry about the bad steer on "&nbsp;". Yes a blank space is correct since the title is not rendered as HTML but as VML/<canvas> content.

                          The code you need to write to specify which labels are visible seems straightforward and minimal. The only way to reduce it seems to be having a new feature of automatically picking a subset of labels to show.

                          Right now, facets cannot be changed on the fly, however, given a new dataset you can just run the same code to product a new instance of FacetChart and destroy() the old.

                          Comment


                            #14
                            The complexity is not in the amount of code (indeed, minimal), or even in any of the code itself, but in the design: the separation of the x-axis-value of the data from the y-axis-value, via insertion of a translation layer (the "id-(n)") which glues the two together, to which I attach either blank labels or human-readable ones. It's just a very different idiom for plotting time-series data (as opposed to defining a series, adding a bunch of x,y pairs to it, and then having some kind of renderer for the axis). The verbal semantics are a stretch too: having to think of Y-axis part of my timeseries an instance of a "CellRecord", for example. But I'll get over it! I will wind up encapsulating the idiom within a helper class with more traditional semantics. Granted, I fully understand how in other use-cases, the multi-dimensional aspects of the FacetChart could be extremely cool.

                            Unfortunately in any case, a show-stopper for me in many uses cases might be the lack of a second y-axis. I'll think about a sponsorship for that. It will come down to price, considering there are alternatives on the market.

                            Thanks again.

                            Comment


                              #15
                              Attached is a class called TimeSeriesChart, a subclass of FacetChart. From the class doc:
                              Code:
                              /**                                                                                                                              
                               * A subclass of FacetChart optimized for time series plotting with support for limiting the number of x-axis labels.            
                               * When multiple series are added, they are intersected via their 'Key' values that will form x-axis labels.                     
                               * If any given series does not support a value for a given key, it will be skipped, with the series' line connecting            
                               * the two adjacent points (as per the behavior of the superclass).                                                              
                               * Two LabelModes are supported: Interval and Count -- see 'setXAxisFormatting'.                                                 
                               * In a typical usage, the Key class will be a Date and the Value class will be some POJO or data structure that contains        
                               * both the Date and the value that is being plotted on the y-axis.                                                              
                               *                                                                                                                               
                               * @param <K> The Key class used to intersect Values.  Natural sort order must correspond to the order in which                  
                               *           labels will be presented along the x-axis.                                                                          
                               * @param <V> The Value class whose data will form the Y values of the chart.   Note that if this is 'Object',                   
                               *           different Extractors can be used with different value classes for each series.                                      
                               */
                              public class TimeSeriesChart<K extends Comparable,V> extends FacetChart
                              Anyone is free to use the code, modify it so it's not a subclass, whatever. A demo of how to use it is below, and the output of two runs of the demo are attached as JPG's. Note that the demo is designed to produce random upwardly-sloping curves, so running it repeatedly will produce different looking charts each time.

                              TimeSeriesChart has two x-axis label modes, Interval and Count. Interval places an x-axis label every N data points, and Count produces exactly N labels. The class is parameterized so that different types of objects can be used to generate the keys that make it work, and to produce the labels themselves, which are formated via an optional Renderer.

                              Here's an example of how it is used. Note that about half of the code below exists to generate and hold the data that will be plotted, and a section of code at the end places the chart within a Window. The TimeSeriesChart.java source itself is attached to this post. In the case of both demo images, the optional x-axis formatting parameter that ensures that the last data point in the series gets an x-axis label has been set to 'true'.
                              Code:
                              // A POJO to hold the generated timeseries data
                              private static class TimeSeriesPoint
                              {
                                  private Date d_timepoint;
                                  private double d_value;
                              
                                  private TimeSeriesPoint(Date timepoint, double value)
                                  {
                                      d_timepoint = timepoint;
                                      d_value = value;
                                   }
                              
                                   public Date getTimepoint()
                                   {
                                        return d_timepoint;
                                   }
                              
                                   public double getValue()
                                   {
                                         return d_value;
                                   }
                              }
                              
                              private void runTimeSeriesDemo()
                              {
                                  Date startDate = new Date();
                                  Log.warn("Now date is [" + startDate + "]");
                              
                                  // Randomly generate some lines of data
                                  int numLines = 3;
                                  int lineLen = 40;
                                  List<List<TimeSeriesPoint>> lines = new ArrayList<List<TimeSeriesPoint>>();
                                  int line = 0;
                                  Random rnd = new Random(startDate.getTime());
                                  while (line < numLines){
                                      int i = 0;
                                      List<TimeSeriesPoint> lineData = new ArrayList<TimeSeriesPoint>(lineLen);
                                      double lastValue = 10.0;
                                      while (i < lineLen){
                                           double thisValue = lastValue + ((rnd.nextDouble()-(0.40 + ((line * 2)/100.0))) * 2);
                                           TimeSeriesPoint point = new TimeSeriesPoint(hackOffsetDate(startDate,i),thisValue);
                                           lineData.add(point);
                              
                                           lastValue = thisValue;
                                           i++;
                                       }
                                       Log.warn("Len = " + lineData.size());
                                       lines.add(lineData);
                                       line++;
                                  }
                              
                                   // Randomly remove some data from some of the lines -- we should still have the same number of unique keys
                                  lines.get(0).remove(5);
                                  lines.get(1).remove(30);
                                  lines.get(2).remove(20);
                              
                                  // Instantiate the chart
                                  TimeSeriesChart<Date,TimeSeriesPoint> chartWidget = new TimeSeriesChart<Date,TimeSeriesPoint>();
                                  chartWidget.setTitle("Time Series Demo - Count Mode");
                                  chartWidget.setValueTitle("Opportunity Cost");
                              
                                  // Create an Extractor for the data
                                  TimeSeriesChart.SeriesValueExtractor<Date,TimeSeriesPoint> extractor = new TimeSeriesChart.SeriesValueExtractor<Date,TimeSeriesPoint>()
                                  {
                                      public Date getXAxisAttribute(TimeSeriesPoint o)
                                      {
                                            return o.getTimepoint();
                                      }
                              
                                      public Double getValue(TimeSeriesPoint o)
                                      {
                                             return o.getValue();
                                      }
                                   };
                              
                                    // Add the lines to the chart
                                    int lineNum = 0;
                                    for (List<TimeSeriesPoint> lineData : lines){
                                         chartWidget.addSeries("series " + lineNum,lineData,extractor);
                                         lineNum++;
                                    }
                              
                                    // LabelMode.Interval,5 produces a label every 5 days
                                    // LabelModel.Count,5 produces 5 labels for the x-axis (or 6 if the third param is 'true')
                                     chartWidget.setXAxisFormatting(TimeSeriesChart.LabelMode.Interval,5, true,new TimeSeriesChart.XAxisRenderer<Date>()
                                      {
                                           private DateTimeFormat d_dtf = DateTimeFormat.getFormat("MMM d, yyyy");
                              
                                            public String getLabel(Date keyValue)
                                            {
                                                 return d_dtf.format(keyValue);
                                            }
                                       });
                              
                                       chartWidget.setWidth100();
                                       chartWidget.setHeight100();
                              
                                       chartWidget.dumpKeys();
                              
                                       if (chartWidget.getNumberOfKeys() == lineLen){
                                            Log.warn("Passed sanity check on number of keys.");
                                       }
                              
                                       chartWidget.plotChart();
                              
                                       Window popup = new Window();
                                       popup.setTitle("Your window title here...");
                                       popup.setDismissOnEscape(false);
                                       popup.setCanDragResize(true);
                                       popup.setCanDragReposition(true);
                              
                              	// Add 'items' to Windows
                                      popup.addItem(chartWidget);
                                      popup.setWidth(800);
                                      popup.setHeight(500);
                              
                                     popup.show();
                              
                              }
                              
                              // A function to create dates relative to some other date
                              private static Date hackOffsetDate(Date source,int offsetDays)
                              {
                                  Date output = new Date(source.getTime());
                                  CalendarUtil.addDaysToDate(output,offsetDays);
                              
                              //   Log.warn("Returning [" + output + "]");
                              
                                  return output;
                              }
                              Attached Files
                              Last edited by dzarras; 12 Jul 2012, 18:42.

                              Comment

                              Working...
                              X