# https://github.com/tbreloff/Qwt.jl immutable QwtPackage <: PlottingPackage end export qwt qwt() = backend(:qwt) # supportedArgs(::QwtPackage) = setdiff(_allArgs, [:xlims, :ylims, :xticks, :yticks]) supportedArgs(::QwtPackage) = [ :annotation, # :args, :axis, :background_color, :color, :fillto, :foreground_color, :group, :heatmap_c, # :kwargs, :label, :layout, :legend, :linestyle, :linetype, :marker, :markercolor, :markersize, :n, :nbins, :nc, :nr, :pos, :reg, # :ribbon, :show, :size, :title, :width, :windowtitle, :x, :xlabel, :xlims, :xticks, :y, :ylabel, :ylims, :yrightlabel, :yticks, :xscale, :yscale, ] supportedTypes(::QwtPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline] supportedMarkers(::QwtPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star1, :star2, :hexagon] supportedScales(::QwtPackage) = [:identity, :log10] # ------------------------------- const _qwtAliases = Dict( :nbins => :heatmap_n, :hexbin => :heatmap, :path => :line, :steppost => :step, :steppre => :stepinverted, ) function replaceLinetypeAlias(d) if haskey(_qwtAliases, d[:linetype]) d[:linetype] = _qwtAliases[d[:linetype]] end end function adjustQwtKeywords(plt::Plot{QwtPackage}, iscreating::Bool; kw...) d = Dict(kw) lt = d[:linetype] if lt == :scatter d[:linetype] = :none if d[:marker] == :none d[:marker] = :ellipse end elseif lt in (:hline, :vline) addLineMarker(plt, d) d[:linetype] = :none d[:marker] = :ellipse d[:markersize] = 1 if lt == :vline d[:x], d[:y] = d[:y], d[:x] end elseif !iscreating && lt == :bar d = barHack(; kw...) elseif !iscreating && lt == :hist d = barHack(; histogramHack(; kw...)...) end replaceLinetypeAlias(d) d end function plot(pkg::QwtPackage; kw...) d = Dict(kw) o = Qwt.plot(zeros(0,0); d..., show=false) plt = Plot(o, pkg, 0, d, Dict[]) plt end function plot!(::QwtPackage, plt::Plot; kw...) d = adjustQwtKeywords(plt, false; kw...) Qwt.oplot(plt.o; d...) push!(plt.seriesargs, d) plt end # ---------------------------------------------------------------- function updateLimsAndTicks(plt::Plot{QwtPackage}, d::Dict, 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) <: Tuple 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 != nothing 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 supportedScales() || warn("Unsupported scale type: ", scaletype) end end function updatePlotItems(plt::Plot{QwtPackage}, d::Dict) haskey(d, :title) && Qwt.title(plt.o, d[:title]) haskey(d, :xlabel) && Qwt.xlabel(plt.o, d[:xlabel]) haskey(d, :ylabel) && Qwt.ylabel(plt.o, d[:ylabel]) updateLimsAndTicks(plt, d, true) updateLimsAndTicks(plt, d, false) end # ---------------------------------------------------------------- # curve.setPen(Qt.QPen(Qt.QColor(color), width, self.getLineStyle(linestyle))) function addLineMarker(plt::Plot{QwtPackage}, d::Dict) for yi in d[:y] marker = Qwt.QWT.QwtPlotMarker() ishorizontal = (d[:linetype] == :hline) marker[:setLineStyle](ishorizontal ? 1 : 2) marker[ishorizontal ? :setYValue : :setXValue](yi) qcolor = Qwt.convertRGBToQColor(d[:color]) linestyle = plt.o.widget[:getLineStyle](string(d[:linestyle])) marker[:setLinePen](Qwt.QT.QPen(qcolor, d[:width], 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::AbstractString) marker = Qwt.QWT.QwtPlotMarker() marker[:setValue](x, y) marker[:setLabel](Qwt.QWT.QwtText(val)) marker[:attach](plt.o.widget) end function addAnnotations{X,Y,V}(plt::Plot{QwtPackage}, anns::AVec{Tuple{X,Y,V}}) for ann in anns createQwtAnnotation(plt, ann...) end end # ---------------------------------------------------------------- # accessors for x/y data function Base.getindex(plt::Plot{QwtPackage}, i::Int) series = plt.o.lines[i] series.x, series.y end function Base.setindex!(plt::Plot{QwtPackage}, xy::Tuple, i::Integer) series = plt.o.lines[i] series.x, series.y = xy plt end # ------------------------------- # savepng(::QwtPackage, plt::PlottingObject, fn::AbstractString, args...) = Qwt.savepng(plt.o, fn) # ------------------------------- # create the underlying object (each backend will do this differently) function buildSubplotObject!(subplt::Subplot{QwtPackage}) i = 0 rows = [] 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, subplt.initargs[1][:size]...) Qwt.moveToLastScreen(subplt.o) # hack so it goes to my center monitor... sorry end # ---------------------------------------------------------------- function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{QwtPackage}) Qwt.savepng(plt.o, "/tmp/dfskjdhfkh.png") write(io, readall("/tmp/dfskjdhfkh.png")) end function Base.display(::PlotsDisplay, plt::Plot{QwtPackage}) Qwt.refresh(plt.o) Qwt.showwidget(plt.o) end function Base.display(::PlotsDisplay, subplt::Subplot{QwtPackage}) for plt in subplt.plts Qwt.refresh(plt.o) end Qwt.showwidget(subplt.o) end