309 lines
8.3 KiB
Julia
309 lines
8.3 KiB
Julia
|
|
# https://github.com/tbreloff/Qwt.jl
|
|
|
|
|
|
supported_attrs(::QwtBackend) = merge_with_base_supported([
|
|
:annotations,
|
|
:linecolor,
|
|
:fillrange,
|
|
:fillcolor,
|
|
:label,
|
|
:legend,
|
|
:seriescolor, :seriesalpha,
|
|
:linestyle,
|
|
:linewidth,
|
|
:markershape,
|
|
:markercolor,
|
|
:markersize,
|
|
:bins,
|
|
:pos,
|
|
:title,
|
|
:window_title,
|
|
:guide, :lims, :ticks, :scale,
|
|
])
|
|
supported_types(::QwtBackend) = [:path, :scatter, :hexbin, :bar]
|
|
supported_markers(::QwtBackend) = [:none, :auto, :rect, :circle, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :star8, :hexagon]
|
|
supported_scales(::QwtBackend) = [:identity, :log10]
|
|
is_subplot_supported(::QwtBackend) = true
|
|
|
|
|
|
# --------------------------------------------------------------------------------------
|
|
|
|
function _initialize_backend(::QwtBackend; kw...)
|
|
@eval begin
|
|
warn("Qwt is no longer supported... many features will likely be broken.")
|
|
import Qwt
|
|
export Qwt
|
|
end
|
|
end
|
|
|
|
# -------------------------------
|
|
|
|
const _qwtAliases = KW(
|
|
:bins => :heatmap_n,
|
|
:fillrange => :fillto,
|
|
:linewidth => :width,
|
|
:markershape => :marker,
|
|
:hexbin => :heatmap,
|
|
:path => :line,
|
|
:steppost => :step,
|
|
:steppre => :stepinverted,
|
|
:star5 => :star1,
|
|
:star8 => :star2,
|
|
)
|
|
|
|
function fixcolors(d::KW)
|
|
for (k,v) in d
|
|
if typeof(v) <: ColorScheme
|
|
d[k] = getColor(v)
|
|
end
|
|
end
|
|
end
|
|
|
|
function replaceQwtAliases(d, s)
|
|
if haskey(_qwtAliases, d[s])
|
|
d[s] = _qwtAliases[d[s]]
|
|
end
|
|
end
|
|
|
|
function adjustQwtKeywords(plt::Plot{QwtBackend}, iscreating::Bool; kw...)
|
|
d = KW(kw)
|
|
st = d[:seriestype]
|
|
if st == :scatter
|
|
d[:seriestype] = :none
|
|
if d[:markershape] == :none
|
|
d[:markershape] = :circle
|
|
end
|
|
|
|
elseif st in (:hline, :vline)
|
|
addLineMarker(plt, d)
|
|
d[:seriestype] = :none
|
|
d[:markershape] = :circle
|
|
d[:markersize] = 1
|
|
if st == :vline
|
|
d[:x], d[:y] = d[:y], d[:x]
|
|
end
|
|
|
|
elseif !iscreating && st == :bar
|
|
d = barHack(; kw...)
|
|
elseif !iscreating && st == :histogram
|
|
d = barHack(; histogramHack(; kw...)...)
|
|
end
|
|
|
|
replaceQwtAliases(d, :seriestype)
|
|
replaceQwtAliases(d, :markershape)
|
|
|
|
for k in keys(d)
|
|
if haskey(_qwtAliases, k)
|
|
d[_qwtAliases[k]] = d[k]
|
|
end
|
|
end
|
|
|
|
d[:x] = collect(d[:x])
|
|
d[:y] = collect(d[:y])
|
|
|
|
d
|
|
end
|
|
|
|
# function _create_plot(pkg::QwtBackend, d::KW)
|
|
function _create_backend_figure(plt::Plot{QwtBackend})
|
|
fixcolors(plt.attr)
|
|
dumpdict(plt.attr,"\n\n!!! plot")
|
|
o = Qwt.plot(zeros(0,0); plt.attr..., show=false)
|
|
# plt = Plot(o, pkg, 0, d, KW[])
|
|
# plt
|
|
end
|
|
|
|
# function _series_added(::QwtBackend, plt::Plot, d::KW)
|
|
function _series_added(plt::Plot{QwtBackend}, series::Series)
|
|
d = adjustQwtKeywords(plt, false; series.d...)
|
|
fixcolors(d)
|
|
dumpdict(d,"\n\n!!! plot!")
|
|
Qwt.oplot(plt.o; d...)
|
|
# push!(plt.seriesargs, d)
|
|
# plt
|
|
end
|
|
|
|
|
|
# ----------------------------------------------------------------
|
|
|
|
function updateLimsAndTicks(plt::Plot{QwtBackend}, d::KW, isx::Bool)
|
|
lims = get(d, isx ? :xlims : :ylims, nothing)
|
|
ticks = get(d, isx ? :xticks : :yticks, nothing)
|
|
w = plt.o.widget
|
|
axisid = Qwt.QWT.QwtPlot[isx ? :xBottom : :yLeft]
|
|
|
|
if typeof(lims) <: Union{Tuple,AVec} && length(lims) == 2
|
|
if isx
|
|
plt.o.autoscale_x = false
|
|
else
|
|
plt.o.autoscale_y = false
|
|
end
|
|
w[:setAxisScale](axisid, lims...)
|
|
end
|
|
|
|
if typeof(ticks) <: Range
|
|
if isx
|
|
plt.o.autoscale_x = false
|
|
else
|
|
plt.o.autoscale_y = false
|
|
end
|
|
w[:setAxisScale](axisid, float(minimum(ticks)), float(maximum(ticks)), float(step(ticks)))
|
|
elseif !(ticks in (nothing, :none, :auto))
|
|
warn("Only Range types are supported for Qwt xticks/yticks. typeof(ticks)=$(typeof(ticks))")
|
|
end
|
|
|
|
# change the scale
|
|
scalesym = isx ? :xscale : :yscale
|
|
if haskey(d, scalesym)
|
|
scaletype = d[scalesym]
|
|
scaletype == :identity && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLinearScaleEngine())
|
|
# scaletype == :log && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(e))
|
|
# scaletype == :log2 && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(2))
|
|
scaletype == :log10 && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLog10ScaleEngine())
|
|
scaletype in supported_scales() || warn("Unsupported scale type: ", scaletype)
|
|
end
|
|
|
|
end
|
|
|
|
|
|
function _update_plot_object(plt::Plot{QwtBackend}, d::KW)
|
|
haskey(d, :title) && Qwt.title(plt.o, d[:title])
|
|
haskey(d, :xguide) && Qwt.xlabel(plt.o, d[:xguide])
|
|
haskey(d, :yguide) && Qwt.ylabel(plt.o, d[:yguide])
|
|
updateLimsAndTicks(plt, d, true)
|
|
updateLimsAndTicks(plt, d, false)
|
|
end
|
|
|
|
function _update_plot_pos_size(plt::AbstractPlot{QwtBackend}, d::KW)
|
|
haskey(d, :size) && Qwt.resizewidget(plt.o, d[:size]...)
|
|
haskey(d, :pos) && Qwt.movewidget(plt.o, d[:pos]...)
|
|
end
|
|
|
|
|
|
# ----------------------------------------------------------------
|
|
|
|
# curve.setPen(Qt.QPen(Qt.QColor(color), linewidth, self.getLineStyle(linestyle)))
|
|
function addLineMarker(plt::Plot{QwtBackend}, d::KW)
|
|
for yi in d[:y]
|
|
marker = Qwt.QWT.QwtPlotMarker()
|
|
ishorizontal = (d[:seriestype] == :hline)
|
|
marker[:setLineStyle](ishorizontal ? 1 : 2)
|
|
marker[ishorizontal ? :setYValue : :setXValue](yi)
|
|
qcolor = Qwt.convertRGBToQColor(getColor(d[:linecolor]))
|
|
linestyle = plt.o.widget[:getLineStyle](string(d[:linestyle]))
|
|
marker[:setLinePen](Qwt.QT.QPen(qcolor, d[:linewidth], linestyle))
|
|
marker[:attach](plt.o.widget)
|
|
end
|
|
|
|
# marker[:setValue](x, y)
|
|
# marker[:setLabel](Qwt.QWT.QwtText(val))
|
|
# marker[:attach](plt.o.widget)
|
|
end
|
|
|
|
function createQwtAnnotation(plt::Plot, x, y, val::PlotText)
|
|
marker = Qwt.QWT.QwtPlotMarker()
|
|
marker[:setValue](x, y)
|
|
qwttext = Qwt.QWT.QwtText(val.str)
|
|
qwttext[:setFont](Qwt.QT.QFont(val.font.family, val.font.pointsize))
|
|
qwttext[:setColor](Qwt.convertRGBToQColor(getColor(val.font.color)))
|
|
marker[:setLabel](qwttext)
|
|
marker[:attach](plt.o.widget)
|
|
end
|
|
|
|
function createQwtAnnotation(plt::Plot, x, y, val::AbstractString)
|
|
marker = Qwt.QWT.QwtPlotMarker()
|
|
marker[:setValue](x, y)
|
|
marker[:setLabel](Qwt.QWT.QwtText(val))
|
|
marker[:attach](plt.o.widget)
|
|
end
|
|
|
|
function _add_annotations(plt::Plot{QwtBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
|
|
for ann in anns
|
|
createQwtAnnotation(plt, ann...)
|
|
end
|
|
end
|
|
|
|
# ----------------------------------------------------------------
|
|
|
|
# accessors for x/y data
|
|
|
|
function getxy(plt::Plot{QwtBackend}, i::Int)
|
|
series = plt.o.lines[i]
|
|
series.x, series.y
|
|
end
|
|
|
|
function setxy!(plt::Plot{QwtBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y}
|
|
series = plt.o.lines[i]
|
|
series.x, series.y = xy
|
|
plt
|
|
end
|
|
|
|
|
|
# -------------------------------
|
|
|
|
# -------------------------------
|
|
|
|
# # create the underlying object (each backend will do this differently)
|
|
# function _create_subplot(subplt::Subplot{QwtBackend}, isbefore::Bool)
|
|
# isbefore && return false
|
|
# i = 0
|
|
# rows = Any[]
|
|
# row = Any[]
|
|
# for (i,(r,c)) in enumerate(subplt.layout)
|
|
# push!(row, subplt.plts[i].o)
|
|
# if c == ncols(subplt.layout, r)
|
|
# push!(rows, Qwt.hsplitter(row...))
|
|
# row = Any[]
|
|
# end
|
|
# end
|
|
# # for rowcnt in subplt.layout.rowcounts
|
|
# # push!(rows, Qwt.hsplitter([plt.o for plt in subplt.plts[(1:rowcnt) + i]]...))
|
|
# # i += rowcnt
|
|
# # end
|
|
# subplt.o = Qwt.vsplitter(rows...)
|
|
# # Qwt.resizewidget(subplt.o, getattr(subplt,1)[:size]...)
|
|
# # Qwt.moveToLastScreen(subplt.o) # hack so it goes to my center monitor... sorry
|
|
# true
|
|
# end
|
|
|
|
function _expand_limits(lims, plt::Plot{QwtBackend}, isx::Bool)
|
|
for series in plt.o.lines
|
|
_expand_limits(lims, isx ? series.x : series.y)
|
|
end
|
|
end
|
|
|
|
|
|
function _remove_axis(plt::Plot{QwtBackend}, isx::Bool)
|
|
end
|
|
|
|
|
|
# ----------------------------------------------------------------
|
|
|
|
function Base.show(io::IO, ::MIME"image/png", plt::Plot{QwtBackend})
|
|
Qwt.refresh(plt.o)
|
|
Qwt.savepng(plt.o, "/tmp/dfskjdhfkh.png")
|
|
write(io, readall("/tmp/dfskjdhfkh.png"))
|
|
end
|
|
|
|
# function Base.show(io::IO, ::MIME"image/png", subplt::Subplot{QwtBackend})
|
|
# for plt in subplt.plts
|
|
# Qwt.refresh(plt.o)
|
|
# end
|
|
# Qwt.savepng(subplt.o, "/tmp/dfskjdhfkh.png")
|
|
# write(io, readall("/tmp/dfskjdhfkh.png"))
|
|
# end
|
|
|
|
|
|
function Base.display(::PlotsDisplay, plt::Plot{QwtBackend})
|
|
Qwt.refresh(plt.o)
|
|
Qwt.showwidget(plt.o)
|
|
end
|
|
|
|
# function Base.display(::PlotsDisplay, subplt::Subplot{QwtBackend})
|
|
# for plt in subplt.plts
|
|
# Qwt.refresh(plt.o)
|
|
# end
|
|
# Qwt.showwidget(subplt.o)
|
|
# end
|