class Glug::Layer
—– Layer
a layer in an Mapbox GL style this is where most of the hard work happens, including 'method_missing' and 'on' calls to provide the grammar
Constants
- HIDDEN
- LAYOUT
Mapbox GL properties (as distinct from OSM keys)
- PAINT
- REF_PROPERTIES
Shared properties that can be recalled by using a 'ref'
- TOP_LEVEL
Attributes
condition[RW]
kv[RW]
stylesheet[RW]
Public Class Methods
new(stylesheet, args={})
click to toggle source
# File lib/glug.rb, line 146 def initialize(stylesheet, args={}) @stylesheet = stylesheet @condition = args[:condition] @kv = args[:kv] || {} @kv[:id] = args[:id] if args[:zoom] then @kv[:zoom]=args[:zoom] end @type = nil # auto-detected layer type @write = true # write this layer out, or has it been suppressed? @cascade_cond = nil # are we currently evaluating a cascade directive? @cascades = args[:cascades] || [] # cascade list to apply to all subsequent layers @uncascaded = nil # condition to add to non-cascaded layers @kv[:source] ||= stylesheet.sources.find {|k,v| v[:default] }[0] @kv[:source_layer] ||= args[:id] @child_num = 0 # incremented sublayer suffix end
Public Instance Methods
_add_cascade_condition(k, v)
click to toggle source
# File lib/glug.rb, line 234 def _add_cascade_condition(k, v) if @cascades.length>0 && @cascades[-1][0].to_s==@cascade_cond.to_s @cascades[-1][1][k]=v else @cascades << [@cascade_cond, { k=>v }] end end
_set_filter(condition)
click to toggle source
# File lib/glug.rb, line 254 def _set_filter(condition) @condition = condition.nil? ? nil : condition.dup end
all()
click to toggle source
# File lib/glug.rb, line 269 def all ; return Subscriptable.new(:all ) end
any()
click to toggle source
cascade(*args, &block)
click to toggle source
Add a cascading condition
# File lib/glug.rb, line 228 def cascade(*args, &block) cond = (args.length==1) ? args[0] : Condition.new.from_list(:any,args) @cascade_cond = cond self.instance_eval(&block) @cascade_cond = nil end
filter(*args)
click to toggle source
Setters for @condition (making sure we copy when inheriting)
# File lib/glug.rb, line 251 def filter(*args) _set_filter(args.length==1 ? args[0] : Condition.new.from_list(:any,args)) end
id(name)
click to toggle source
Set layer name
# File lib/glug.rb, line 259 def id(name) @kv[:id] = name end
method_missing(method_sym, *arguments)
click to toggle source
Handle all missing 'method' calls If we can match it to a Mapbox GL property, it's an assignment: otherwise it's an OSM key
# File lib/glug.rb, line 167 def method_missing(method_sym, *arguments) if LAYOUT.include?(method_sym) || PAINT.include?(method_sym) || TOP_LEVEL.include?(method_sym) v = arguments.length==1 ? arguments[0] : arguments if v.is_a?(Proc) then v=v.call(@kv[method_sym]) end if @cascade_cond.nil? @kv[method_sym] = v else _add_cascade_condition(method_sym, v) end else return OSMKey.new(method_sym.to_s) end end
nilsafe_merge(a,b)
click to toggle source
Nil-safe merge
# File lib/glug.rb, line 223 def nilsafe_merge(a,b) a.nil? ? b : (a & b) end
none()
click to toggle source
# File lib/glug.rb, line 270 def none; return Subscriptable.new(:none) end
on(*args, &block)
click to toggle source
Add a sublayer with an additional filter
# File lib/glug.rb, line 182 def on(*args, &block) @child_num+=1 r = Layer.new(@stylesheet, :id => "#{@kv[:id]}__#{@child_num}".to_sym, :kv => @kv.dup, :cascades => @cascades.dup) # Set zoom level if args[0].is_a?(Range) || args[0].is_a?(Fixnum) r.kv[:zoom] = args.shift end # Set condition sub_cond = nil if args.empty? sub_cond = @condition # just inherit parent layer's condition else sub_cond = (args.length==1) ? args[0] : Condition.new.from_list(:any,args) sub_cond = nilsafe_merge(sub_cond, @condition) end r._set_filter(nilsafe_merge(sub_cond, @uncascaded)) r.instance_eval(&block) @stylesheet._add_layer(r) # Create cascaded layers child_chr='a' @cascades.each do |c| c_cond, c_kv = c l = Layer.new(@stylesheet, :id=>"#{r.kv[:id]}__#{child_chr}", :kv=>r.kv.dup) l._set_filter(nilsafe_merge(sub_cond, c_cond)) l.kv.merge!(c_kv) @stylesheet._add_layer(l) child_chr.next! end end
ref_key(hash)
click to toggle source
Key to identify matching layer properties (slow but…)
# File lib/glug.rb, line 331 def ref_key(hash) (REF_PROPERTIES.collect { |k| hash[k] } ).to_json end
set_type_from(s)
click to toggle source
Deduce 'type' attribute from style attributes
# File lib/glug.rb, line 273 def set_type_from(s) return unless s.include?('-') t = s.split('-')[0].to_sym if t==:icon || t==:text then t=:symbol end if @type && @type!=t then raise "Attribute #{s} conflicts with deduced type #{@type} in layer #{@kv[:id]}" end @type=t end
suppress()
click to toggle source
Suppress output of this layer
# File lib/glug.rb, line 264 def suppress; @write = false end
tag(k)
click to toggle source
Short-form key constructor - for reserved words
# File lib/glug.rb, line 218 def tag(k) OSMKey.new(k) end
to_hash()
click to toggle source
Create a Mapbox GL-format hash from a layer definition
# File lib/glug.rb, line 282 def to_hash hash = { :layout=> {}, :paint => {} } # Assign key/values to correct place @kv.each do |k,v| s = k.to_s.gsub('_','-') if s.include?('-color') && v.is_a?(Fixnum) then v = "#%06x" % v end if LAYOUT.include?(k) hash[:layout][s]=v set_type_from s elsif PAINT.include?(k) hash[:paint][s]=v set_type_from s elsif TOP_LEVEL.include?(k) || HIDDEN.include?(k) hash[s]=v else raise "#{s} isn't a recognised layer attribute" end end hash['type'] = @type if @condition then hash['filter'] = @condition.encode end # Convert zoom level if (v=hash['zoom']) hash['minzoom'] = v.is_a?(Range) ? v.first : v hash['maxzoom'] = v.is_a?(Range) ? v.last : v hash.delete('zoom') end # See if we can reuse an earlier layer's properties mk = ref_key(hash) if stylesheet.refs[mk] REF_PROPERTIES.each { |k| hash.delete(k) } hash['ref'] = stylesheet.refs[mk] else stylesheet.refs[mk] = hash['id'] end if hash[:layout].empty? && hash[:paint].empty? nil else hash.delete(:layout) if hash[:layout].empty? hash.delete(:paint) if hash[:paint].empty? hash end end
uncascaded(*args)
click to toggle source
# File lib/glug.rb, line 241 def uncascaded(*args) cond = case args.length when 0; nil when 1; args[0] else; Condition.new.from_list(:any,args) end @uncascaded = cond end
write?()
click to toggle source
# File lib/glug.rb, line 265 def write?; @write end