Skip to content

Commit

Permalink
core: add support for area charts
Browse files Browse the repository at this point in the history
  • Loading branch information
Bogdanp committed Nov 6, 2023
1 parent f92767e commit 4de1c1f
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 20 deletions.
19 changes: 12 additions & 7 deletions FranzCocoa/Backend.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public enum ChartScaleType: Readable, Writable {
}

public enum ChartStyle: Readable, Writable {
case area
case bar
case candlestick(UVarint?)
case line
Expand All @@ -103,14 +104,16 @@ public enum ChartStyle: Readable, Writable {
let tag = UVarint.read(from: inp, using: &buf)
switch tag {
case 0x0000:
return .bar
return .area
case 0x0001:
return .bar
case 0x0002:
return .candlestick(
UVarint?.read(from: inp, using: &buf)
)
case 0x0002:
return .line
case 0x0003:
return .line
case 0x0004:
return .scatter
default:
preconditionFailure("ChartStyle: unexpected tag \(tag)")
Expand All @@ -119,15 +122,17 @@ public enum ChartStyle: Readable, Writable {

public func write(to out: OutputPort) {
switch self {
case .bar:
case .area:
UVarint(0x0000).write(to: out)
case .candlestick(let width):
case .bar:
UVarint(0x0001).write(to: out)
case .candlestick(let width):
UVarint(0x0002).write(to: out)
width.write(to: out)
case .line:
UVarint(0x0002).write(to: out)
case .scatter:
UVarint(0x0003).write(to: out)
case .scatter:
UVarint(0x0004).write(to: out)
}
}
}
Expand Down
57 changes: 51 additions & 6 deletions FranzCocoa/ResultDetail.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,32 @@ fileprivate struct ChartResult: View {
private func chartView() -> any View {
let view = Charts.Chart(pairs) { p in
switch chart.style {
case .area:
try? p.areaMark(
xLabel: chart.xLabel,
yLabel: chart.yLabel
)
case .bar:
try? p.barMark(xLabel: chart.xLabel, yLabel: chart.yLabel)
try? p.barMark(
xLabel: chart.xLabel,
yLabel: chart.yLabel
)
case .candlestick(let width):
try? p.candlestickMark(
xLabel: chart.xLabel,
yLabel: chart.yLabel,
width: width
)
case .line:
try? p.lineMark(xLabel: chart.xLabel, yLabel: chart.yLabel)
try? p.lineMark(
xLabel: chart.xLabel,
yLabel: chart.yLabel
)
case .scatter:
try? p.pointMark(xLabel: chart.xLabel, yLabel: chart.yLabel)
try? p.pointMark(
xLabel: chart.xLabel,
yLabel: chart.yLabel
)
}
}
switch (chart.xScale, chart.yScale) {
Expand All @@ -98,15 +112,17 @@ fileprivate struct ChartResult: View {

@MainActor
private func export(frame: CGRect) {
guard let image = ImageRenderer(content: AnyView(
guard let data = ImageRenderer(content: AnyView(
chartView()
.padding(.all, 20)
.background()
).frame(
width: frame.width * 2,
height: frame.height * 2
)).nsImage else { return }
guard let data = image.tiffRepresentation else { return }
)).nsImage?.tiffRepresentation else {
return
}

let dialog = NSSavePanel()
dialog.allowedContentTypes = [.init(filenameExtension: "tiff")!]
dialog.isExtensionHidden = false
Expand Down Expand Up @@ -142,6 +158,20 @@ fileprivate struct ChartResult: View {
let x: ChartValue
let y: ChartValue

func areaMark(xLabel: String, yLabel: String) throws -> AreaMark {
switch (x, y) {
case (.categorical(let xcat), .numerical(let y)):
return AreaMark(x: .value(xLabel, xcat), y: .value(yLabel, y))
case (.timestamp(let ts), .numerical(let y)):
return AreaMark(
x: .value(xLabel, Date(timeIntervalSince1970: Double(ts))),
y: .value(yLabel, y)
)
default:
throw ChartError.badMarks
}
}

func barMark(xLabel: String, yLabel: String) throws -> BarMark {
switch (x, y) {
case (.categorical(let xcat), .categorical(let ycat)):
Expand All @@ -152,6 +182,11 @@ fileprivate struct ChartResult: View {
return BarMark(x: .value(xLabel, x), y: .value(yLabel, ycat))
case (.numerical(let x), .numerical(let y)):
return BarMark(x: .value(xLabel, x), y: .value(yLabel, y))
case (.timestamp(let ts), .numerical(let y)):
return BarMark(
x: .value(xLabel, Date(timeIntervalSince1970: Double(ts))),
y: .value(yLabel, y)
)
default:
throw ChartError.badMarks
}
Expand Down Expand Up @@ -188,6 +223,11 @@ fileprivate struct ChartResult: View {
return LineMark(x: .value(xLabel, x), y: .value(yLabel, ycat))
case (.numerical(let x), .numerical(let y)):
return LineMark(x: .value(xLabel, x), y: .value(yLabel, y))
case (.timestamp(let ts), .numerical(let y)):
return LineMark(
x: .value(xLabel, Date(timeIntervalSince1970: Double(ts))),
y: .value(yLabel, y)
)
default:
throw ChartError.badMarks
}
Expand All @@ -203,6 +243,11 @@ fileprivate struct ChartResult: View {
return PointMark(x: .value(xLabel, x), y: .value(yLabel, ycat))
case (.numerical(let x), .numerical(let y)):
return PointMark(x: .value(xLabel, x), y: .value(yLabel, y))
case (.timestamp(let ts), .numerical(let y)):
return PointMark(
x: .value(xLabel, Date(timeIntervalSince1970: Double(ts))),
y: .value(yLabel, y)
)
default:
throw ChartError.badMarks
}
Expand Down
9 changes: 9 additions & 0 deletions FranzCross/result-detail.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
#:y-label (Chart-y-label c)
(list
((match (Chart-style c)
[(ChartStyle.area) area]
[(ChartStyle.bar) discrete-histogram]
[(ChartStyle.candlestick _) candlesticks]
[(ChartStyle.line) lines]
Expand All @@ -91,6 +92,14 @@
(ChartValue-> (ChartPair-x p))
(ChartValue-> (ChartPair-y p))))))))))))

(define (area ps)
(define min-y
(apply min (map cadr ps)))
(lines-interval
(for/list ([p (in-list ps)])
(list (car p) min-y))
ps))

(define (text-view s)
(hpanel
#:margin '(20 20)
Expand Down
1 change: 1 addition & 0 deletions core/extlib/render.lua
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ local function makeChartClass(name)
return Chart
end

render.AreaChart = makeChartClass("AreaChart")
render.BarChart = makeChartClass("BarChart")
render.CandlestickChart = makeChartClass("CandlestickChart")
render.LineChart = makeChartClass("LineChart")
Expand Down
5 changes: 4 additions & 1 deletion core/script.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
{type : ChartScaleType}])

(define-enum ChartStyle
[area]
[bar]
[candlestick
{width : (Optional UVarint)}]
Expand Down Expand Up @@ -107,6 +108,8 @@

(define (->ChartStyle type v)
(case type
[(#"AreaChart")
(ChartStyle.area)]
[(#"BarChart")
(ChartStyle.bar)]
[(#"CandlestickChart")
Expand Down Expand Up @@ -158,7 +161,7 @@
(define type
(table-ref v #"__type"))
(case type
[(#"BarChart" #"CandlestickChart" #"LineChart" #"ScatterChart")
[(#"AreaChart" #"BarChart" #"CandlestickChart" #"LineChart" #"ScatterChart")
(ReduceResult.chart
(make-Chart
#:style (->ChartStyle type v)
Expand Down
19 changes: 13 additions & 6 deletions manual/index.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -816,10 +816,17 @@ data to a window when @tech[#:key "apply"]{applying} a script.
@(define (chart-ref . content)
(apply elemref '("lua" "Chart:push") content))

@deflua[render.AreaChart (xlabel ylabel) Chart]{
Returns an instance of an area @chart-ref{chart renderer}. The first
argument represents the x axis label and the second argument, the y
axis label. The values of the x axis must be @lua[render.Timestamp]s
or @tt{string}s and the y axis values must be @tt{number}s.
}

@deflua[render.BarChart (xlabel ylabel) Chart]{
Returns an instance of a bar @chart-ref{chart renderer}. The first
argument represents the x-axis label and the second argument, the
y-axis.
argument represents the x axis label and the second argument, the
y axis.
}

@deflua[render.CandlestickChart (xlabel ylabel) Chart]{
Expand Down Expand Up @@ -854,14 +861,14 @@ data to a window when @tech[#:key "apply"]{applying} a script.

@deflua[render.LineChart (xlabel ylabel) Chart]{
Returns an instance of a line @chart-ref{chart renderer}. The first
argument represents the x-axis label and the second argument, the
y-axis.
argument represents the x axis label and the second argument, the
y axis.
}

@deflua[render.ScatterChart (xlabel ylabel) Chart]{
Returns an instance of a scatter @chart-ref{chart renderer}. The first
argument represents the x-axis label and the second argument, the
y-axis.
argument represents the x axis label and the second argument, the
y axis.
}

@deflua[render.Table (columns ...) Table]{
Expand Down

0 comments on commit 4de1c1f

Please sign in to comment.