csharpfftfsharpintegrationinterpolationlinear-algebramathdifferentiationmatrixnumericsrandomregressionstatisticsmathnet
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
6.9 KiB
187 lines
6.9 KiB
namespace Microsoft.FSharp.Plot
|
|
open System
|
|
open System.Drawing
|
|
open System.Windows.Forms
|
|
|
|
// Abstract objects that represent "plottable" items
|
|
type IPlot =
|
|
abstract BasePlot : IPlot // extend to array of IPlot (for compound plots)
|
|
|
|
// Control which can accept selected IPlot objects.
|
|
type IChart =
|
|
abstract Control : Control
|
|
abstract Accepts : IPlot -> bool
|
|
abstract Add : IPlot -> unit
|
|
abstract Context : MenuItem[]
|
|
|
|
// Each
|
|
type IChartFactory =
|
|
abstract Name : string
|
|
abstract Accepts : IPlot -> bool
|
|
abstract Create : unit -> IChart
|
|
|
|
|
|
// The window management functions for charts/plots.
|
|
module Interactive =
|
|
|
|
let menuItem str handler =
|
|
let item = new MenuItem(str:string)
|
|
item.Click.Add(fun _ -> handler())
|
|
item
|
|
|
|
// should be a property for dynamic load
|
|
let factories = ref [] : IChartFactory list ref
|
|
let addFactory f = factories := !factories @ [f]
|
|
|
|
// Frames are container Controls in which to add ChartControls.
|
|
// Focus is the current/last IChart - where to add next plots where possible.
|
|
|
|
// naive next frame
|
|
// let nextFrame() = let form = new Form(Visible=true,Title="F# Plot Window") in form :> Control
|
|
|
|
// tabbing next frame
|
|
// 1. tabControl
|
|
let mutable tabControl = null : TabControl
|
|
let ensureTabControl() =
|
|
if tabControl <> null && not tabControl.IsDisposed then
|
|
tabControl
|
|
else
|
|
let form = new Form(TopMost=true,Width=400,Height=400,Text="F# Plot Window")
|
|
let tab = new TabControl()
|
|
tabControl <- tab
|
|
form.Controls.Add(tab)
|
|
form.Show()
|
|
tab.Dock <- DockStyle.Fill
|
|
let deleteSelected _ = tab.SelectedTab.Dispose()
|
|
let deleteNonSelected _ = let keep = tab.SelectedTab
|
|
let pages = tab.Controls |> Seq.cast : TabPage seq
|
|
pages |> Seq.to_array |> Array.iter (fun page -> if page <> keep then page.Dispose())
|
|
tab.ContextMenu <- new ContextMenu [| menuItem "Delete selected tab" deleteSelected;
|
|
menuItem "Delete un-selected tab" deleteNonSelected;
|
|
|]
|
|
tab
|
|
|
|
type myTabPage(chart : IChart) =
|
|
inherit TabPage()
|
|
let mutable m_chart = chart
|
|
member this.Chart
|
|
with get() = m_chart
|
|
and set ch = m_chart <- ch
|
|
|
|
let mutable pageNumber = 0
|
|
let nextFrame (ch) =
|
|
let tab2 = ensureTabControl()
|
|
let page = new myTabPage(ch)
|
|
pageNumber <- pageNumber + 1
|
|
page.Text <- sprintf "P%d" pageNumber
|
|
let () = tab2.Controls.Add(page)
|
|
tab2.SelectTab(page)
|
|
(page :> Control)
|
|
|
|
//let mutable focus = ((new TextChartControl() :>IChart) : IChart) // dummy value
|
|
//do focus.Control.Dispose()
|
|
let setFocus x = () // focus <- x
|
|
|
|
let plot(pl:'a :> IPlot) =
|
|
let p = pl.BasePlot
|
|
match !factories |> List.tryFind (fun fac -> fac.Accepts p) with
|
|
| None -> printf "Sorry, not accepted by a registered charting engine\n"; failwith "unknown plot"
|
|
| Some fac -> let chart = fac.Create()
|
|
let frame = nextFrame(chart)
|
|
frame.Controls.Add(chart.Control)
|
|
chart.Control.Dock <- DockStyle.Fill
|
|
chart.Add p
|
|
let items =
|
|
[| new MenuItem("-");
|
|
menuItem "Delete" (fun _ -> frame.Dispose())
|
|
|]
|
|
frame.ContextMenu <- new ContextMenu(Array.append chart.Context items)
|
|
setFocus chart
|
|
(pl : 'a)
|
|
|
|
open System.Windows.Forms
|
|
let chart(ch : 'a :> IChart) =
|
|
let frame = nextFrame(ch)
|
|
frame.Controls.Add(ch.Control)
|
|
ch.Control.Dock <- DockStyle.Fill
|
|
let items =
|
|
[| new MenuItem("-");
|
|
menuItem "Delete" (fun _ -> frame.Dispose())
|
|
|]
|
|
frame.ContextMenu <- new ContextMenu(Array.append ch.Context items)
|
|
setFocus ch
|
|
(ch : 'a)
|
|
|
|
let multiplot(parray : IPlot array) =
|
|
let myTab = ensureTabControl()
|
|
for p in parray do
|
|
let tabPageList : myTabPage list = myTab.Controls |> Seq.cast |> Seq.to_list
|
|
let existingTab = tabPageList |> List.tryFind(fun c -> c.Chart.Accepts p)
|
|
match existingTab with
|
|
| Some(c) -> c.Chart.Add p
|
|
| _ -> plot p |> ignore; ()
|
|
|
|
let replot(p:'a :> IPlot) =
|
|
let myTab = ensureTabControl()
|
|
if myTab.TabCount > 0 then
|
|
let page = myTab.Controls.Item(myTab.SelectedIndex) :?> myTabPage
|
|
if page.Chart.Accepts p then
|
|
page.Chart.Add p
|
|
(p:'a)
|
|
else
|
|
plot p
|
|
else plot p
|
|
|
|
type MultiChartControl(tc : TableLayoutPanel) =
|
|
let table = tc
|
|
interface IChart with
|
|
override this.Control = table :> Control
|
|
override this.Accepts(x) = false // denies all
|
|
override this.Add(x:IPlot) = ()
|
|
override this.Context = [| |]
|
|
|
|
let subplot(parray : IPlot array) =
|
|
let calcRowsColumns len =
|
|
let rows = int (sqrt (float len) )
|
|
let cols = if (len % rows) > 0 then (len / rows) + 1
|
|
else len / rows
|
|
rows,cols
|
|
|
|
let r, c = calcRowsColumns parray.Length
|
|
let myTab = ensureTabControl()
|
|
|
|
let table = new TableLayoutPanel()
|
|
table.Dock <- DockStyle.Fill
|
|
table.RowCount <- r
|
|
table.ColumnCount <- c
|
|
|
|
|
|
let arrangeRowsCols (tbl : TableLayoutPanel)=
|
|
tbl.RowStyles.Clear()
|
|
tbl.ColumnStyles.Clear()
|
|
let rows = tbl.RowCount
|
|
let cols = tbl.ColumnCount
|
|
|
|
for i=0 to tbl.RowCount - 1 do
|
|
tbl.RowStyles.Add(new RowStyle(SizeType.Percent, float32 (100/rows))) |>ignore
|
|
for i=0 to tbl.ColumnCount - 1 do
|
|
tbl.ColumnStyles.Add(new ColumnStyle(SizeType.Percent , float32 (100 / cols))) |>ignore
|
|
|
|
arrangeRowsCols table
|
|
let multiChart = new MultiChartControl(table)
|
|
let frame = nextFrame(multiChart)
|
|
frame.Controls.Add table
|
|
|
|
Array.iter (fun p ->
|
|
match !factories |> List.tryFind (fun fac -> fac.Accepts p) with
|
|
| None -> printf "Sorry, %A not accepted by a registered charting engine\n" p
|
|
| Some fac -> let chart = fac.Create()
|
|
chart.Control.Dock <- DockStyle.Fill
|
|
chart.Add p
|
|
table.Controls.Add chart.Control
|
|
setFocus chart) parray
|
|
|
|
|
|
|
|
|
|
|
|
|