@quartic/bokehjs
Version:
Interactive, novel data visualization
167 lines (128 loc) • 4.89 kB
text/coffeescript
import * as mixins from "./property_mixins"
import {color2rgba} from "./util/color"
class ContextProperties
constructor: (obj, prefix="") ->
= obj
= prefix
= {}
do_spec = obj.properties[prefix+].spec
= do_spec.value != null
for attr in
@[attr] = obj.properties[prefix+attr]
warm_cache: (source) ->
for attr in
prop = .properties[+attr]
if prop.spec.value != undefined # TODO (bev) better test?
[attr] = prop.spec.value
else
[attr+"_array"] = prop.array(source)
cache_select: (attr, i) ->
prop = .properties[+attr]
if prop.spec.value != undefined # TODO (bev) better test?
[attr] = prop.spec.value
else
[attr] = [attr+"_array"][i]
export class Line extends ContextProperties
attrs: Object.keys(mixins.line())
do_attr: "line_color"
set_value: (ctx) ->
ctx.strokeStyle = .value()
ctx.globalAlpha = .value()
ctx.lineWidth = .value()
ctx.lineJoin = .value()
ctx.lineCap = .value()
ctx.setLineDash(.value())
ctx.setLineDashOffset(.value())
set_vectorize: (ctx, i) ->
if ctx.strokeStyle != .line_color
ctx.strokeStyle = .line_color
if ctx.globalAlpha != .line_alpha
ctx.globalAlpha = .line_alpha
if ctx.lineWidth != .line_width
ctx.lineWidth = .line_width
if ctx.lineJoin != .line_join
ctx.lineJoin = .line_join
if ctx.lineCap != .line_cap
ctx.lineCap = .line_cap
if ctx.getLineDash() != .line_dash
ctx.setLineDash(.line_dash)
if ctx.getLineDashOffset() != .line_dash_offset
ctx.setLineDashOffset(.line_dash_offset)
color_value: () ->
color = color2rgba(.value(), .value())
return "rgba(#{color[0]*255},#{color[1]*255},#{color[2]*255},#{color[3]})"
export class Fill extends ContextProperties
attrs: Object.keys(mixins.fill())
do_attr: "fill_color"
set_value: (ctx) ->
ctx.fillStyle = .value()
ctx.globalAlpha = .value()
set_vectorize: (ctx, i) ->
if ctx.fillStyle != .fill_color
ctx.fillStyle = .fill_color
if ctx.globalAlpha != .fill_alpha
ctx.globalAlpha = .fill_alpha
color_value: () ->
color = color2rgba(.value(), .value())
return "rgba(#{color[0]*255},#{color[1]*255},#{color[2]*255},#{color[3]})"
export class Text extends ContextProperties
attrs: Object.keys(mixins.text())
do_attr: "text_color"
cache_select: (name, i) ->
if name == "font"
val = super("text_font_style", i) + " " + super("text_font_size", i) + " " + super("text_font", i)
.font = val
else
super(name, i)
font_value: () ->
font = .value()
font_size = .value()
font_style = .value()
return font_style + " " + font_size + " " + font
color_value: () ->
color = color2rgba(.value(), .value())
return "rgba(#{color[0]*255},#{color[1]*255},#{color[2]*255},#{color[3]})"
set_value: (ctx) ->
ctx.font =
ctx.fillStyle = .value()
ctx.globalAlpha = .value()
ctx.textAlign = .value()
ctx.textBaseline = .value()
set_vectorize: (ctx, i) ->
if ctx.font != .font
ctx.font = .font
if ctx.fillStyle != .text_color
ctx.fillStyle = .text_color
if ctx.globalAlpha != .text_alpha
ctx.globalAlpha = .text_alpha
if ctx.textAlign != .text_align
ctx.textAlign = .text_align
if ctx.textBaseline != .text_baseline
ctx.textBaseline = .text_baseline
export class Visuals
constructor: (model) ->
for spec in model.mixins
[name, prefix=""] = spec.split(":")
cls = switch name
when "line" then Line
when "fill" then Fill
when "text" then Text
@[prefix+name] = new cls(model, prefix)
warm_cache: (source) ->
for own name, prop of @
if prop instanceof ContextProperties
prop.warm_cache(source)