Skip to content

Commit

Permalink
Access to the underlying .NET chart object (#102)
Browse files Browse the repository at this point in the history
* Exposed access to the underlying
 System.Windows.Forms.DataVisualization.Charting.Chart object via a
 "visitor"-esque member method ApplyToChart(...), in order to enable
 programmatic control over the chart form window (which is already accessible
 to the user manually via the Properties tab of the chart form). This enables
 us to use charting with the following example pattern:

let inputData = [1;2;3]
inputData
|> Chart.Line
|> fun c      -> c.WithLegend()  // add legend using the existing method
|> fun c      -> ( c, c.ShowChart() )    // create the chart form
|> fun (c, _) -> (c, c.ApplyToChart( fun c -> c.ChartAreas.[0].CursorX.IsUserSelectionEnabled <- true ) )   // can now modify chart form using all of the available .NET Chart API by chaining lines like this one
|> ignore   // avoid displaying the chart twice

* ApplyToChart() now returns the Chart object, enabling us to chain calls, like in the example below:

inputData
|> Chart.Line
// do things necessary before chart is rendered
|> fun c -> c.WithLegend( FontSize = 5.0 )
             .WithStyling( Color = System.Drawing.Color.Red )
// create the chart form and render the chart
|> fun c -> ( c, c.ShowChart() )
// do things that can only be done after the chart is rendered
|> fun ( c, _ ) -> c.ApplyToChart( fun c -> c.ChartAreas.[0].CursorX.IsUserSelectionEnabled <- true )
                    .ApplyToChart( fun c -> c.ChartAreas.[0].CursorY.IsUserSelectionEnabled <- true )
|> ignore  // avoid displaying the chart twice

* Implemented the "caching" of functions applid using ApplytoChart() until the point of drawing of the actual chart, as discussed in #102 (comment). ApplyToChart() is now usable with the existing simple dot-notation.

* Added ApplyToChart to the documentation.

* CustomizationFunctions need to be applied in the order they were added, if only for the sake of clarity. This was noticed by @simra.
  • Loading branch information
mtikilay authored and simra committed Apr 15, 2016
1 parent bbbc9bd commit b70b4a6
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 2 deletions.
15 changes: 14 additions & 1 deletion docs/content/FurtherSamples.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,17 @@ Chart.Line(data,Name="SomeData").WithDataPointLabels(PointToolTip="Hello, I am #
Chart.Stock(timeHighLowOpenClose)
Chart.ThreeLineBreak(data,Name="SomeData").WithDataPointLabels(PointToolTip="Hello, I am #SERIESNAME")

Chart.Histogram([for x in 1 .. 100 -> rand()*10.],LowerBound=0.,UpperBound=10.,Intervals=10.)
Chart.Histogram([for x in 1 .. 100 -> rand()*10.],LowerBound=0.,UpperBound=10.,Intervals=10.)

// Example of .ApplyToChart() used to alter the settings on the window chart and to access the chart child objects.
// This can normally be done manually, in the chart property grid (right click the chart, then "Show Property Grid").
// This is useful when you want to try out carious settings first. But once you know what you want, .ApplyToChart()
// allows programmatic access to the window properties. The two examples below are: IsUserSelectionEnabled essentially
// allows zooming in and out along the given axes, and the longer fiddly example below does the same work as .WithDataPointLabels()
// but across all series objects.
[ Chart.Column(data);
Chart.Column(data2) |> Chart.WithSeries.AxisType( YAxisType = Windows.Forms.DataVisualization.Charting.AxisType.Secondary ) ]
|> Chart.Combine
|> fun c -> c.WithLegend()
.ApplyToChart( fun c -> c.ChartAreas.[0].CursorX.IsUserSelectionEnabled <- true )
.ApplyToChart( fun c -> let _ = [0 .. c.Series.Count-1] |> List.map ( fun s -> c.Series.[ s ].ToolTip <- "#SERIESNAME (#VALX, #VAL{0:00000})" ) in () )
2 changes: 1 addition & 1 deletion docs/content/fsharpcharting.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ The following methods are used to style chart objects:
* `WithTitle`
* `WithXAxis`
* `WithYAxis`

* `ApplyToChart`

Please [contribute](contributing.html) more documentation on the following topics:

Expand Down
7 changes: 7 additions & 0 deletions src/FSharp.Charting.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,7 @@ namespace FSharp.Charting

let mutable data = ChartData.Values (NotifySeq.ignoreReset (NotifySeq.notifyOrOnce []), ChartValueType.Auto, "Item1", "Item2", "")
let mutable margin = DefaultMarginForEachChart
let mutable customizationFunctions : (Chart -> unit) list = []

[<Obsolete("This type does not support GetHashCode()")>]
override x.GetHashCode() = 0
Expand All @@ -1165,6 +1166,11 @@ namespace FSharp.Charting
member internal x.Chart with get() = chart.Value and set v = chart <- evalLazy v
member internal x.Margin with get() = margin and set v = margin <- v
member internal x.Name with get() = name and set v = name <- v
member internal x.CustomizationFunctions with get() = customizationFunctions

member x.ApplyToChart ( fn : Chart -> unit ) =
customizationFunctions <- ( fn :: customizationFunctions )
x

/// Ensure the chart has a Title
member internal x.ForceTitle() =
Expand Down Expand Up @@ -3944,6 +3950,7 @@ namespace FSharp.Charting
frm.Text <- ProvideTitle ch
frm.Controls.Add(ctl)
frm.Show()
ch.CustomizationFunctions |> List.rev |> List.map (fun fn -> fn ch.Chart) |> ignore
ctl.Focus() |> ignore
frm

Expand Down

0 comments on commit b70b4a6

Please sign in to comment.