Flexicious 3.2 Released!

clock August 4, 2014 06:44 by author Flexicious

As with our previous releases, 3.2 has been shipping for a while to our early adopters, and we figured since there have been no major issues, it would be a good time to release it to all of you! Similar to 3.1, this is a rather large release, we listened to your feedback and spaced out our releases so that you dont have to upgrade every few weeks. Consequently, the releases now have a TON of functionality. Major chunks of functionality have their own blog posts linked to from this one. That said, with no further ado, presenting, Flexicious 3.2!!

 

  • Enhancement, Ultimate: New Settings popup that support for reordering columns. Support for controlling visibility of inner level columns. More details here
  • Enhancement, All Products: Support for pre and post print pages. More details here.
  • Enhancement, Ultimate: Added support for inner level filters. Click here for a screenshot
  • Enhancement, Ultimate: Added support for "sticky headers". This allows you to lock the inner level header rows as you scroll through the child items. Click here for a screenshot
  • Enhancement, Dashboard : A Number of enhancements were added to the Pie Chart. Full details here.
    • animationMode: fade,sweep,explode,explodeAndSweep. How to animate the pie chart. Supported modes are fade,sweep, and explode.
    • totalDegrees : The max degrees for this pie. Defaults to 360. Max 360.
    • startAngle : The angle for the first pie.
    • pieSelectedOffset : How far out to draw the selected pie slice.
    • pieSliceRadiusPercent : What percent of the overall chart should the pie take. If the chart is 50x50, and the pieSliceRadiusPercent is 50, then the pie will be of 25 radius. This is useful when you want to have large labels that sit outside the individual pie slices.
    • drawArcUsingGraphicsPath : Boolean flag that instructs the painter to use the Graphics path based drawing for regular charts. Only supported for 2d pie chart.
    • bezelBrightness : How much to darken the pie color by for the bezel. Only for 2d Pie charts.
    • bezelDistance : The distance of the bezel for 2d pie charts.
    • threeDShadeIntensity : Default shading intensity for the 3d pie painter
    • showLabelsOnPie : Flag to show text input labels with percentages on the pies.
    • pieLabelOffset : How far out (or in) to draw the label relative to the edge of the pie
    • pieLabelFunction : The label function for the label on the pie slice. Should take a PlotPoint, and return an String
  • Bug Fix, Ultimate : Preferences were not saving sort order for multiple column sort
  • Enhancement, Ultimate: Parameterized constants used on settings popup
  • Enhancement, Dashboard: Extended Calendar to support multi day items. Addition of support for stacking multi day items via the stackMultiDayItems boolean flag.
  • Enhancement, Dashboard: Extended Calendar to support deletion of events. New events added:
    • public static const CALENDAR_ITEM_ADDED:String = "calendarItemAdded";           
    • public static const CALENDAR_ITEM_DELETED:String = "calendarItemDeleted";
  • Enhancement, All Products: Intrinsic support for Unicode excel export. Added a flag, prependUnicodeMarkers, to ExportOptions. This will save the file with a unicode BOM. This makes the file unicode enabled without the need to save it in a non-native HTML format, instead of the regular CSV format.
  • Enhancement, Classic : Performance improvements for flat grids with filter/paging enabled.
  • Enhancement, Dashboard: Better mouse tracking of rollover points on Cartesian charts. Instead of having to hover over the very small rectangle around a plot point, now as you move the mouse along the axis, it will recognize the point within that vertical or horizontal cross section and show the tooltip for that point. Added support for enableSeriesHighlight. This highlights the series for multi series charts that is being highlighted.
  • Bug Fix, Dashboard: The position of Cartesian charts was off by half a bar.
  • Enhancement, Ultimate : Added support for copy selected cells, similar to excel. For contiguous selection (assuming all selected cells belong to the same column), a new menu item "Copy Selected Cells" is added. Hitting CTRL-C will also trigger this same behavior.
  • Enhancement, All Products : Performance improvement on MultiSelectCombBox with a large number of items to choose from.
  • Enhancement, All Products: Addition of the blankValuesLabel to the column. This allows for a new item added to the list of filter choices. Allows you to filter on null/blank values.
  • Bug Fix, Ultimate : For Boolean fields with dot notation based dataField, sorting was not working
  • Enhancement (Work In Progress), All Products : Spark version of all filter controls. We now have a SWC where we have ported a few of the filter controls, like to Spark based versions.
  • Bug Fix, Dashboard : Issue with 3d Pie chart where it was drawing a part of the slice outside the main pie.
  • Enhancement, Utlimate : Added editorHeightOffset, editorWidthOffset, editorXOffset, and editorYOffset for better control over the positioning of the itemEditor.
  • Bug Fix, Ultimate : For header heights, the column group height is now based off headerHeight instead of rowHeight.
  • Bug Fix, Classic : Better support for ArrayList dataprovider as opposed to ArrayCollection
  • Enhancement, Ultimate: Support for column header menu operations.
  • Enhancement, Ultimate: Added ability to define split headers at each level. Previously, this was a global setting.
  • Enhancement, Ultimate: Added iconPlacementFunction:A function that allows you to position the icon when you provide an iconFunction or iconUrl. By default, we use the iconLeft, iconRight, iconTop and iconBottom style properties. However incase of hierarchical grids, you may want to control the positioning of the icon. Takes a FlexDataGridCell object, and a Image object. The image object is already positioned x,y at the result of the calculation based upon iconLeft, Right, Top and Bottom properties for you to make additional adjustments.
  • Bug fix, Ultimate : Fix when a row is both selectable/disabled. Disabled rows should not be selectable.
  • Enhancement, All Products: Added a new value for filterTriggerEvent : enterKeyUpOrFocusOut. This triggers the filter when the user hits the Enter Key OR the user tabs out after entering something into the field.
  • Enhancement, Dashboard: Added support for selectable legends. Added show the hide this item checkbox. For Multi series chart, we allow the user to select which series to view if there are more than 1 visible series. For single series pie/funnel/pyramid charts, we use it as a filter on the dataprovider . Flag is named enableHideCheckbox
  • Enhancement, Dashboard : Added startAngle and endAngle to the Pie Chart, to draw partial pie charts
  • Enhancement, Ultimate: Added flag inExport¸and   recordBeingExported. This flag is set to true while the export is running, so you can embed custom logic in labelFunctions, etc.
  • Enhancement, Ultimate : Added a callback function, headerTextFunction. A function that determines the header text for a column. This method is called in 3 different contexts.
    • 1) When the grid is rendered and the header cells are drawn
    • 2) When the user clicks on export or print or sort and it shows the list of columns
    • 3) When the export is run, and the records are being exported.
  •  In each context we get different types of information that helps us determine the correct text to return. When the grid is being rendererd, the method gets a value of type IFlexDataGridCell for the cell parameter. This will let you determine the cell.rowInfo.data object being rendered. In the export or print popups, you will get the column, and no row context can be determined since there is none. You can use the defaultHeaderText property to figure out what you specified as the original headertext. NOTE : DO NOT use the .headerText in here, since it will cause a recursive loop. Finally, in case of an actual exprot, you can check to see grid.inExport, and determine the value to display on basis of the grid.recordBeingExported. This is usually the parent level record when the header is being written out.  Example: public function getHeaderText(col:FlexDataGridColumn, cell:IFlexDataGridCell=null):String
  • Enhancement, All Products: Added a custom Constants.NEW_LINE, which is determined on basis of the operating system that the application is running on.
  • Enhancement, Ultimate : Added support for custom right click menu. Full details about this enhancement are included in this blog post.
  • Bug Fix, Ultimate : The dropdown for enableColumnHeaderOperations was not being destroyed in certain circumstances after mouseout
  • Enhancement, Ultimate : Added MultiSelectComboBoxEx. a searchable Multi Select Combo Box.
  • Enhancement, Dashboard: Added support for a background striped pattern for all the Charts. The following properties were added to make this happen:

+                      /**

+                      *  The part that draws the background

+                      */                   

+                      public var backgroundPattern:Group;

+                      /**

+                      *  If this flag is set to true, the stripes are drawn vertically,

+                      * otherwise they are drawn horizontally.

+                      */                   

+                      public var backgroundStripesVertical:Boolean=false;

+                      /**

+                      * Flag to enable background stripes for this chart.

+                      */                   

+                      public var enableBackgroundStripes:Boolean=true;

  • Added support to darken/lighten the series on rollover : +                /**

+                      * If you set this to true, the  chart will darken the series on rollover.

+                      */                   

+                      public var darkenOnRollOver:Boolean=true;

+                      /**

+                      * If you set this darkenOnRollOver to true, the chart will darken the series on rollover.

+                      * The darkening will happen by this amount

+                      */                   

+                      public var darkenOnRollOverOffset:int=-0x30;

+                      /**

+                      * When using the default fills (which are colors), you can control apply a global alpha value.

+                      */                   

+                      public var defaultItemAlpha:Number=.8;

 

  • Enhancement, Dashboard: Added support multiple axes. More details in this blog post.
  • Enhancement, Dashboard: Added support scrollable charts. More details in this blog post.
  •  Enhancement, All Products : Moved the include files into a shared location to avoid issues wrt parent folders. e.g. instead of - include "../../../../../../../FlexGrid/includes/ClickPopupInclude.as"; include "C:/Code/flxssrc/includes/ClickPopupInclude.as";
  • Enhancement, All Products: Added support for persisting custom data as a part of preferences.
  • Enhancement, Dashboard: Added labelFunction for all Gauges.
  • Bug Fix, Dashboard: Preferences got corrupted when the preferences were saved with a maximized dashlet.
  • Enhancement, Dashboard: Added custom labels for HLOC chart.

+                      public var openLabel:String =  "Open\t: ";

+                      public var closeLabel:String = "Close\t: ";

+                      public var highLabel:String =  "High\t: ";

+                      public var lowLabel:String =   "Low\t: ";

  • Bug Fix, Ultimate: In certain scenarios, export did not include inner level records.
  • Enhancement, Ultimate: Added allowLastColumnResize. When the horizontal scroll policy is auto or on, this flag allows resizing of the last column.

 

 

 

 

 



Ultimate Flex DataGrid - Sticky Headers and Inline Filters

clock August 4, 2014 06:41 by author Flexicious

A couple cool new features being shipped with the upcoming 3.2 build:

 

 

Inline Filters:

 



Flex Charts - Numerous Enhancements

clock August 4, 2014 06:04 by author Flexicious

 

The charting library that we initially released a couple years ago has now grown into a fully fledged data visualization library with Tiny Charts, Regular Charts, Gauges, Calendar, Treemap, and many more. In this release, the charts are all getting a facelift. The most amount of work went into the Pie Chart.

A number of API additions were made:

  •  
    • animationMode: fade,sweep,explode,explodeAndSweep. How to animate the pie chart. Supported modes are fade,sweep, and explode.
    • totalDegrees : The max degrees for this pie. Defaults to 360. Max 360.
    • startAngle : The angle for the first pie.
    • pieSelectedOffset : How far out to draw the selected pie slice.
    • pieSliceRadiusPercent : What percent of the overall chart should the pie take. If the chart is 50x50, and the pieSliceRadiusPercent is 50, then the pie will be of 25 radius. This is useful when you want to have large labels that sit outside the individual pie slices.
    • drawArcUsingGraphicsPath : Boolean flag that instructs the painter to use the Graphics path based drawing for regular charts. Only supported for 2d pie chart.
    • bezelBrightness : How much to darken the pie color by for the bezel. Only for 2d Pie charts.
    • bezelDistance : The distance of the bezel for 2d pie charts.
    • threeDShadeIntensity : Default shading intensity for the 3d pie painter
    • showLabelsOnPie : Flag to show text input labels with percentages on the pies.
    • pieLabelOffset : How far out (or in) to draw the label relative to the edge of the pie
    • pieLabelFunction : The label function for the label on the pie slice. Should take a PlotPoint, and return an String

For regular charts, we added support for a background striped pattern for all the Charts. The following properties were added to make this happen:

+                      /**

+                      *  The part that draws the background

+                      */                   

+                      public var backgroundPattern:Group;

+                      /**

+                      *  If this flag is set to true, the stripes are drawn vertically,

+                      * otherwise they are drawn horizontally.

+                      */                   

+                      public var backgroundStripesVertical:Boolean=false;

+                      /**

+                      * Flag to enable background stripes for this chart.

+                      */                   

+                      public var enableBackgroundStripes:Boolean=true;

We also added support to darken/lighten the series on rollover : +                      /**

+                      * If you set this to true, the  chart will darken the series on rollover.

+                      */                   

+                      public var darkenOnRollOver:Boolean=true;

+                      /**

+                      * If you set this darkenOnRollOver to true, the chart will darken the series on rollover.

+                      * The darkening will happen by this amount

+                      */                   

+                      public var darkenOnRollOverOffset:int=-0x30;

+                      /**

+                      * When using the default fills (which are colors), you can control apply a global alpha value.

+                      */                   

+                      public var defaultItemAlpha:Number=.8;

 

In addition, we added ability to show/hide series or items.

Lets take a quick look at what this looks like:

 

 

 

 

 

Below is a full flex project with sample code that is used in the screenshots above.

 

ChartSamples.zip (39.48 kb)



Pre and Post Print Pages

clock August 4, 2014 05:47 by author Flexicious

In the last release, we added support for "Print Anything", basically extended the Printing mechanism to not only print the datagrid, but also any flex component that you can render on the stage.

One of the things that a number of our customers have requested is the ability to add a few pages of text (think disclaimers, table of contents). You could do this (sort of) using the ReportHeader and ReportFooter, but this comes with a big caveat that these cannot extend beyond one page. For this purpose, we have added support for the Pre and Post print pages.

The following properties were added to Print Options for this: 

              /**

               * A class factory that is responsible for instantiating a ICustomPrintComponent

               * that will be printed before the report.

               */          

              public var preReportPagesFactory:ClassFactory;

              /**

               * A class factory that is responsible for instantiating a ICustomPrintComponent

               * that will be printed after the report.

               */          

              public var postReportPagesFactory:ClassFactory;

              /**

               * If you define a preReportPagesFactory, you may optionally provide a number

               * for this. If you do, we will not attempt to calculate how many pages by calling

               * calculateTotalPages on your ICustomPrintComponent.

               */          

              public var preReportPages:int=0;

              /**

               * If you define a postReportPagesFactory, you may optionally provide a number

               * for this. If you do, we will not attempt to calculate how many pages by calling

               * calculateTotalPages on your ICustomPrintComponent

               */          

              public var postReportPages:int=0;

The way you wire this up is :

 creationComplete="dgEmployeesUltimate.printOptions.preReportPagesFactory = new ClassFactory(PrePrintPages);

dgEmployeesUltimate.printOptions.postReportPagesFactory = new ClassFactory(PostPrintPages);"

 

The caveat here is that PostPrint and PrePrint pages need to implement implements="com.flexicious.print.customprint.ICustomPrintComponent".

Below is the full set of files that are needed to make this happen.

PostPrintPages.mxml (437.00 bytes)

PrintPreAndPostPages.mxml (6.66 kb)

PrePrintPages.mxml (1.14 kb)



Ultimate Flex DataGrid - New Settings Popup

clock August 4, 2014 05:33 by author Flexicious

As most of you are aware, all the popup windows that the grid launches, like the print, print preview, export, settings, save settings are all plug-ins. You can specify your own popup in case you want to customize their behavior. The latest release, 3.2 has a new popup, SettingsPopupUltimate that has some cool enhancements over the previous version:

  • A Tree based view of the columns that is helpful to show individual columns as well as columns inside column groups
  • A searchable screen to allow large sets of columns to easily be managed.
  • Ability to move columns as well as groups of columns up and down.
  • For grids that have inner level columns (grids inside grids), ability to manage inner level columns.

 

Let us see what this looks like: 

 

 

For those of you who want to further customize this popup, it is attached below.

SettingsPopupUltimate.mxml (13.88 kb)

 

The way you provide your own is:

grid.popupFactorySettingsPopup = new ClassFactory(YourSettingsPopupUltimate);

Hope you find this useful!



Flexicious Ultimate - Flex DataGrid Right Click Support

clock July 18, 2014 06:32 by author Flexicious

This has got to be among the most requested features. For the longest time, there was no clean way to provide built in support for right click. Flex has always had a acrimonious relationship with right click. There are a few implementations that interact with the browser and do some javascript trickery to make this work, but nothing has been clean enough for us to provide as a out-of-the-box solution.

So finally when earlier this year we Flash player provided official support for right click, we were able to tap into this new feature and provide a nice way to get you right click support, with a few easy properties and events.

 

  1. Set enableCustomContextMenu="true"
  2. Define your customContextMenuItems="{['Sample Item']}"
  3. Optional, Define itemRightClick event. where you can customize the list of customContextMenuItems if it is different for each cell.
  4. Define itemRightClickMenuSelect event, where you handle the right click menu selection response. 
Lets see what this looks like:

And here is the code that makes this happen:


RightClick.mxml (2.94 kb)

 

Enjoy!



Flexicious Ultimate - Flex DataGrid with rapid inserts and updates

clock July 14, 2014 20:26 by author Administrator

Recently, while working with a customer on optimizing some performance issues, we came across a scenario, where the customer wanted to rapidly update the grid with new data coming from the server. This is a rather complicated use case to accomodate, since the default behavior of the grid is to rebuild itself in response to additions, deletions etc in the dataprovider. It also is quite resource intensive to do so, because usually additions or deletions means you have to rebuild the sort, rerun all filters, update page indexes, and a lot of internal cached information that makes the grid extremely performant needs to be rebuilt. 

We already have the TraderView example that demonstrates how to respond to rapid updates. We do this by turning off the rebuildGridOnDataProviderChange flag, which basically means grid will not respond to changes in dataprovider, and instead will depend on you to explicitly ask it to update via either the rebuild() method or the rebuildBody method. However, in that example, we simlpy call targeted refresh cell calls, to update specific cells that need to be updated. This makes it possible for the grid to respond to a numerous updates per second.

However, keep in mind that with updates to the rows already drawn, there is no need to rebuild the internal index (unless ofcourse, you want to sort, which means you will need to rebuild the index). Basically the caveat to keep in mind is that both for insert and updates, if you want to sort, page, or filter again, there is no way to consume a large number of such operation in subsecond time frames. And this is not a limitation of the grid, but just the amount of time it takes to sort, filter and page an array (even without a grid involved) make it prohibitively expensive to perform this operation multiple times a second.

This brings us to the actual implementation of this use case. Since for this customer, we are inserting rows at the top (as new data comes in, it pushes everything else down), it makes it a lot easier, since we simply do the same thing that the grid would have done, that is, update the index. 

Lets take a quick look at the code that does this:

protected function insertTimerHandler(event:TimerEvent):void

                  {

                        fdg.rebuildGridOnDataProviderChange=false;//so we dont rebuild the index when we change the dataprovider

                        var chg:Number=getRandom(-10,10);

                        //we add it to the dataprovider, this should not affect the grid.

                        //we are adding at index 0

                        var newStock:Object={"id":stocks.length,"symbol":"NEW TICK" + stocks.length, "name":"NEW Ticker with symbol"+stocks.length

                              ,"last":getRandom(20,30),"change":chg+"%","tickUp":(chg>0)};

                        stocks.addItemAt(newStock,0);

                       

                        var rowPos:RowPositionInfo = new RowPositionInfo(

                              newStock,//the data object

                              0, //row index of the data object (0 because we are adding it at the top, you can add it anywhere

                              0,//vertical position of the data object (rowIndex * rowHeight) assuming no variable row height. Or you could lookup the verticalPos of the item above me, and add his height to that number to get this number

                              fdg.rowHeight,//same height rows. For variable row height, you can calculate this

                              fdg.columnLevel, //the top level. If you are adding a child object, you can use the appropriate inner level

                              RowPositionInfo.ROW_TYPE_DATA //type of row. For inner level rows, you can add Header, footer, filter, pager ,renderer rows

                              );   

                        for each(var existingRowPos:RowPositionInfo in fdg.bodyContainer.itemVerticalPositions)

                        {

                              existingRowPos.rowIndex +=1;

                              existingRowPos.verticalPosition += fdg.rowHeight;//push everything down.

                        }

                        for each(var row:RowInfo in fdg.bodyContainer.rows){

                              //now go through all the drawn rows, and update their y property

                              row.y=row.rowPositionInfo.verticalPosition;

                        }

                        fdg.bodyContainer.itemVerticalPositions.splice(0,0,rowPos);//add item at index 0.

                        fdg.bodyContainer.recycle(fdg.columnLevel,false,fdg.rowHeight,false);//now make sure the body draws the row

                        fdg.bodyContainer.placeComponents();//update the cell positions

                        if(stocks.length%5==0){

                              //this will paint the cell background

                              //this is very slighty heavier than other methods, so dont call it as frequently.

                              //may be call it every 2 seconds or so

                              fdg.bodyContainer.invalidateCells();

                        }

                  }

 

                 

 

Here is the sample :

 

TraderView.mxml (9.67 kb)

 

And here is the screenshot:

 

 



Flex Charts with multiple axes

clock June 16, 2014 06:08 by author Flexicious

This post might reveal a few goodies that are coming as a part of the upcoming 3.2 release, but it is something a number of you have asked for. Basically, the issue is that you want to have multiple axes in our chart components. The fact that our Charts are based upon the excellent Spark skinning framework makes this endeavour a lot easier. 

When you draw something on a chart, there is always an underlying series that tells the chart its bounds. That is, given a X position (or a Y Position) on a chart, what is the value associated with that point with reference to the series. The linear axis will always use the first series, regardless of how many you have to draw the ticks. The actual painting of the series is independant, since the series is the source of the truth, the axis is dependant on it. 

With 3.2, we are introducing a new variable on the axis, called associatedSeries. 

/**

* By default, the first series is used to paint the default axis.

* If you associate another series with this axis, that series will be used

       * to calculate the min and max values.

       */

 

      public function get associatedSeries():Series

 

This allows you to override the series associated with the axis. Combine this with the power of the Spark Skinning framework, you can embed additional axes easily!

A little eye candy:

 

 

We are a few weeks away from official 3.2 release, but this is just one of the many exciting additions coming to charts in 3.2!

Below are the files used for this demo. They will not run with version < 3.2, but we do have preview builds available for those of you who cannot wait!

DualAxisChart.mxml (4.11 kb)

CustomLineChartSkin.mxml (4.46 kb)



Flex Calendar Component Customization

clock June 16, 2014 04:17 by author Flexicious

 

Over the past few months, our consulting services team has been quite busy working on client projects. For those of you who don’t know, we do a lot of consulting work for our customers. We have a number of customer projects where our components are heavily used. Since we wrote the components, our customers often come to us to build their projects around our components. Once such project we are currently working on requires a fair bit of customization on our Calendar component. This is a part of our Dashboard framework. Basically what the customer wanted here was to implement categorization of the calendar events, and implement custom rendering mechanism for the events on the calendar, and on the popup for the calendar items, they wanted to be able to pick and choose which category to associate each calendar item with.

The first thing we did, and we recommend you do this as well, is to extend the base Calendar component as below:

This makes it a lot easier to access protected functions and variables. We almost never make anything private, as a library developer try to put as few restrictions as possible for extension and custmozation.

 

Note that we provided a custom popup renderer, as well as a custom calendar item renderer. The calendar item renderer is the actual rectangle that shows on top of the week, month and day views in the calendar, while the calendar popup renderer is the popup that shows up when you double click on a calendar item (edit mode), or when you double click on a time slot on the calendar anywhere (add mode) Note that for providing custom item renderer we extended the built in CalendarItemRenderer

 

The requirement here was to implement a custom color, and for the sake of simplicity we have shown some sample logic here to draw different colors. For rendering the calendar item in different color, we override the updateDisplayList method of CalendarItemRenderer, like shown above.

And then we associate the popup renderer with the Calendar as below:

this.calendarItemPopupRenderer = new ClassFactory(MRXCalendarItemPopup);

 

Once you have the custom calendar built, you can use it like below:

 

 

Finally, the results:

 

 

 

 

Below is the sample project that we created using some of the concepts covered in this blog post.

 

SampleCalendar.zip (48.15 kb)

 

If you have any questions, please feel free to reach out to our support team. If you are interested in leveraging our expertise to build Flex/HTML/Android/iOS projects, please do not hesitate to contact us using this form: http://www.flexicious.com/Home/ContactUs 



Performance Improvements to Classic Flex DataGrid and AdvancedDataGrid

clock November 24, 2013 04:18 by author Flexicious

We have recently reworked the filtering and paging implementations for Classic, resulting in good performance improvements for Classic ExtendedDataGrid and ExtendedAdvancedDataGrid components. This is especially true if you have a large number of records. Previous performance improvements had revolved around optimizing the renderered part of the grid, but this one particularly targets the internals of how the grid stores indexes for pages and filters. We have had a couple of our consulting services customers experience dramatic improvements, especially for larger recordsets. 

If you have grids with tens of thousands of rows, please request a build, you should be able to see these improvements.

Please note, this is only for our Classic Product (Not Ultimate). We've already made a lot of advances in terms of performance for Ultimate before.