kamelopard 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,12 +11,13 @@ module Kamelopard
11
11
  require 'xml'
12
12
  require 'yaml'
13
13
  require 'erb'
14
+ require 'cgi'
14
15
 
15
16
  @@sequence = 0
16
17
  @@id_prefix = ''
17
18
 
18
19
  def Kamelopard.get_document
19
- Document.instance
20
+ DocumentHolder.instance.current_document
20
21
  end
21
22
 
22
23
  def Kamelopard.get_next_id # :nodoc
@@ -127,6 +128,11 @@ module Kamelopard
127
128
  attr_accessor :kml_id
128
129
  attr_reader :comment
129
130
 
131
+ # This constructor looks for values in the options hash that match
132
+ # class attributes, and sets those attributes to the values in the
133
+ # hash. So a class with an attribute called :when can be set via the
134
+ # constructor by including ":when => some-value" in the options
135
+ # argument to the constructor.
130
136
  def initialize(options = {})
131
137
  @kml_id = "#{Kamelopard.id_prefix}#{self.class.name.gsub('Kamelopard::', '')}_#{ Kamelopard.get_next_id }"
132
138
 
@@ -140,15 +146,15 @@ module Kamelopard
140
146
  end
141
147
  end
142
148
 
143
- def comment=(a)
144
- if a.respond_to? :gsub then
145
- @comment = a.gsub(/</, '&lt;')
146
- else
147
- @comment = a
148
- end
149
+ # Adds an XML comment to this node. Handles HTML escaping the comment
150
+ # if needed
151
+ def comment=(cmnt)
152
+ require 'cgi'
153
+ @comment = CGI.escapeHTML(cmnt)
149
154
  end
150
155
 
151
- # Returns KML string for this object. Objects should override this method
156
+ # Returns XML::Node containing this object's KML. Objects should
157
+ # override this method
152
158
  def to_kml(elem)
153
159
  elem.attributes['id'] = @kml_id.to_s
154
160
  if not @comment.nil? and @comment != '' then
@@ -260,9 +266,9 @@ module Kamelopard
260
266
  # Note that this will not accept a one-dimensional array of numbers to add
261
267
  # a single point. Instead, create a Point with those numbers, and pass
262
268
  # it to add_element
263
- #-
269
+ #--
264
270
  # XXX The above stipulation is a weakness that needs fixing
265
- #+
271
+ #++
266
272
  def add_element(a)
267
273
  if a.kind_of? Enumerable then
268
274
  # We've got some sort of array or list. It could be a list of
@@ -517,7 +523,9 @@ module Kamelopard
517
523
  class TimePrimitive < Object
518
524
  end
519
525
 
520
- # Corresponds to KML's TimeStamp object. The @when attribute must be in a format KML understands.
526
+ # Corresponds to KML's TimeStamp object. The @when attribute must be in a
527
+ # format KML understands. Refer to the KML documentation to see which
528
+ # formats are available.
521
529
  class TimeStamp < TimePrimitive
522
530
  attr_accessor :when
523
531
  def initialize(ts_when = nil, options = {})
@@ -605,7 +613,7 @@ module Kamelopard
605
613
  end
606
614
  end
607
615
 
608
- # ExtendedData SchemaData objects
616
+ # Corresponds to KML's ExtendedData SchemaData objects
609
617
  class SchemaData
610
618
  attr_accessor :schemaUrl, :simpleData
611
619
  def initialize(schemaUrl, simpleData = {})
@@ -632,13 +640,14 @@ module Kamelopard
632
640
  end
633
641
 
634
642
  # Abstract class corresponding to KML's Feature object.
643
+ #--
635
644
  # XXX Make this support alternate namespaces
645
+ #++
636
646
  class Feature < Object
637
- # Abstract class
638
647
  attr_accessor :visibility, :open, :atom_author, :atom_link, :name,
639
- :phoneNumber, :description, :abstractView, :styles,
640
- :timeprimitive, :styleUrl, :styleSelector, :region, :metadata
641
- attr_reader :addressDetails, :snippet, :extendedData
648
+ :phoneNumber, :abstractView, :styles, :timeprimitive, :styleUrl,
649
+ :styleSelector, :region, :metadata
650
+ attr_reader :addressDetails, :snippet, :extendedData, :description
642
651
 
643
652
  include Snippet
644
653
 
@@ -650,6 +659,15 @@ module Kamelopard
650
659
  @name = name unless name.nil?
651
660
  end
652
661
 
662
+ def description=(a)
663
+ b = CGI.escapeHTML(a)
664
+ if b != a then
665
+ @description = XML::Node.new_cdata a
666
+ else
667
+ @description = a
668
+ end
669
+ end
670
+
653
671
  def extendedData=(a)
654
672
  raise "extendedData attribute must respond to the 'each' method" unless a.respond_to? :each
655
673
  @extendedData = a
@@ -695,9 +713,9 @@ module Kamelopard
695
713
 
696
714
  def addressDetails=(a)
697
715
  if a.nil? or a == '' then
698
- Document.instance.uses_xal = false
716
+ DocumentHolder.instance.current_document.uses_xal = false
699
717
  else
700
- Document.instance.uses_xal = true
718
+ DocumentHolder.instance.current_document.uses_xal = true
701
719
  end
702
720
  @addressDetails = a
703
721
  end
@@ -794,7 +812,7 @@ module Kamelopard
794
812
  @styles = []
795
813
  @folders = []
796
814
  super
797
- Document.instance.folders << self
815
+ DocumentHolder.instance.current_document.folders << self
798
816
  end
799
817
 
800
818
  def styles=(a)
@@ -844,18 +862,29 @@ module Kamelopard
844
862
  k
845
863
  end
846
864
 
847
- # Represents KML's Document class. This is a Singleton object; Kamelopard
848
- # scripts can (for now) manage only one Document at a time.
865
+ # Represents KML's Document class.
849
866
  class Document < Container
850
- include Singleton
851
- attr_accessor :flyto_mode, :folders, :tours, :uses_xal
867
+ attr_accessor :flyto_mode, :folders, :tours, :uses_xal, :vsr_actions
852
868
 
853
869
  def initialize(options = {})
854
870
  @tours = []
855
871
  @folders = []
872
+ @vsr_actions = []
873
+ DocumentHolder.instance << self
856
874
  super
857
875
  end
858
876
 
877
+ # Returns viewsyncrelay actions as a hash
878
+ def get_actions
879
+ {
880
+ 'actions' => @vsr_actions.collect { |a| a.to_hash }
881
+ }
882
+ end
883
+
884
+ def get_actions_yaml
885
+ get_actions.to_yaml
886
+ end
887
+
859
888
  # Returns the current Tour object
860
889
  def tour
861
890
  Tour.new if @tours.length == 0
@@ -955,6 +984,61 @@ module Kamelopard
955
984
  end
956
985
  end
957
986
 
987
+ # Holds a set of Document objects, so we can work with multiple KML files
988
+ # at once and keep track of them. It's important for Kamelopard's usability
989
+ # to have the concept of a "current" document, so we don't have to specify
990
+ # the document we're talking about each time we do something interesting.
991
+ # This class supports that idea.
992
+ class DocumentHolder
993
+ include Singleton
994
+ attr_accessor :document_index, :initialized
995
+ attr_reader :documents
996
+
997
+ def initialize(doc = nil)
998
+ @documents = []
999
+ @document_index = -1
1000
+ if ! doc.nil?
1001
+ self.documents << doc
1002
+ end
1003
+ end
1004
+
1005
+ def document_index
1006
+ return @document_index
1007
+ end
1008
+
1009
+ def document_index=(a)
1010
+ @document_index = a
1011
+ end
1012
+
1013
+ def current_document
1014
+ # Automatically create a Document if we don't already have one
1015
+ if @documents.size <= 0
1016
+ Document.new
1017
+ @document_index = 0
1018
+ end
1019
+ return @documents[@document_index]
1020
+ end
1021
+
1022
+ def <<(a)
1023
+ raise "Cannot add a non-Document object to a DocumentHolder" unless a.kind_of? Document
1024
+ @documents << a
1025
+ @document_index += 1
1026
+ end
1027
+
1028
+ def [](a)
1029
+ return @documents[a]
1030
+ end
1031
+
1032
+ def []=(i, v)
1033
+ raise "Cannot include a non-Document object in a DocumentHolder" unless v.kind_of? Document
1034
+ @documents[i] = v
1035
+ end
1036
+
1037
+ def size
1038
+ return @documents.size
1039
+ end
1040
+ end
1041
+
958
1042
  # Corresponds to KML's ColorStyle object. Color is stored as an 8-character hex
959
1043
  # string, with two characters each of alpha, blue, green, and red values, in
960
1044
  # that order, matching the ordering the KML spec demands.
@@ -1273,7 +1357,7 @@ module Kamelopard
1273
1357
  def initialize(options = {})
1274
1358
  super
1275
1359
  @attached = false
1276
- Document.instance.styles << self
1360
+ DocumentHolder.instance.current_document.styles << self
1277
1361
  end
1278
1362
 
1279
1363
  def attached?
@@ -1411,7 +1495,7 @@ module Kamelopard
1411
1495
  attr_accessor :standalone
1412
1496
 
1413
1497
  def initialize(options = {})
1414
- Document.instance.tour << self unless options[:standalone]
1498
+ DocumentHolder.instance.current_document.tour << self unless options[:standalone]
1415
1499
  super
1416
1500
  end
1417
1501
  end
@@ -1585,12 +1669,13 @@ module Kamelopard
1585
1669
  class Tour < Object
1586
1670
  attr_accessor :name, :description, :last_abs_view, :playlist, :icon
1587
1671
 
1588
- def initialize(name = nil, description = nil)
1672
+ def initialize(name = nil, description = nil, no_wait = false)
1589
1673
  super()
1590
1674
  @name = name
1591
1675
  @description = description
1592
1676
  @playlist = []
1593
- Document.instance.tours << self
1677
+ DocumentHolder.instance.current_document.tours << self
1678
+ Wait.new(0.1, :comment => "This wait is automatic, and helps prevent animation glitches") unless no_wait
1594
1679
  end
1595
1680
 
1596
1681
  # Add another element to this Tour
@@ -1622,7 +1707,7 @@ module Kamelopard
1622
1707
 
1623
1708
  def initialize(options = {})
1624
1709
  super nil, options
1625
- Document.instance.folder << self
1710
+ DocumentHolder.instance.current_document.folder << self
1626
1711
  end
1627
1712
 
1628
1713
  def to_kml(elem)
@@ -1799,7 +1884,7 @@ module Kamelopard
1799
1884
  Kamelopard.add_altitudeMode(@altitudeMode, k)
1800
1885
  end
1801
1886
  m = XML::Node.new 'rotation'
1802
- m = @rotation.to_s
1887
+ m << @rotation.to_s
1803
1888
  k << m
1804
1889
  elem << k unless elem.nil?
1805
1890
  k
@@ -2113,6 +2198,7 @@ module Kamelopard
2113
2198
  end
2114
2199
  end
2115
2200
 
2201
+ # Abstract class corresponding to KML's MultiGeometry object
2116
2202
  class MultiGeometry < Geometry
2117
2203
  attr_accessor :geometries
2118
2204
 
@@ -2136,6 +2222,7 @@ module Kamelopard
2136
2222
  end
2137
2223
  end
2138
2224
 
2225
+ # Analogue of KML's NetworkLink class
2139
2226
  class NetworkLink < Feature
2140
2227
  attr_accessor :refreshVisibility, :flyToView, :link
2141
2228
 
@@ -2185,6 +2272,7 @@ module Kamelopard
2185
2272
  end
2186
2273
  end
2187
2274
 
2275
+ # Corresponds to Google Earth's gx:Track extension to KML
2188
2276
  class Track < Geometry
2189
2277
  attr_accessor :altitudeMode, :when, :coord, :angles, :model
2190
2278
  def initialize(options = {})
@@ -2210,5 +2298,43 @@ module Kamelopard
2210
2298
  e
2211
2299
  end
2212
2300
  end
2301
+
2302
+ # Viewsyncrelay action
2303
+ class VSRAction < Object
2304
+ attr_accessor :name, :tour_name, :verbose, :fail_count, :input,
2305
+ :action, :exit_action, :repeat, :constraints, :reset_constraints,
2306
+ :initially_disabled
2307
+ # XXX Consider adding some constraints, so that things like @name and @action don't go nil
2308
+ # XXX Also ensure constraints and reset_constraints are hashes,
2309
+ # containing reasonable values, and reasonable keys ('latitude' vs.
2310
+ # :latitude, for instance)
2311
+
2312
+ def initialize(name, options = {})
2313
+ @name = name
2314
+ @constraints = {}
2315
+ @repeat = 'DEFAULT'
2316
+ @input = 'ALL'
2317
+ super(options)
2318
+
2319
+ DocumentHolder.instance.current_document.vsr_actions << self
2320
+ end
2321
+
2322
+ def to_hash
2323
+ a = {}
2324
+ a['name'] = @name unless @name.nil?
2325
+ a['id'] = @id unless @id.nil?
2326
+ a['input'] = @input unless @input.nil?
2327
+ a['tour_name'] = @tour_name unless @tour_name.nil?
2328
+ a['verbose'] = @verbose unless @verbose.nil?
2329
+ a['fail_count'] = @fail_count unless @fail_count.nil?
2330
+ a['action'] = @action unless @action.nil?
2331
+ a['exit_action'] = @exit_action unless @exit_action.nil?
2332
+ a['repeat'] = @repeat unless @repeat.nil?
2333
+ a['initially_disabled'] = @initially_disabled unless @initially_disabled.nil?
2334
+ a['constraints'] = @constraints unless @constraints.nil?
2335
+ a['reset_constraints'] = @reset_constraints unless @reset_constraints.nil?
2336
+ a
2337
+ end
2338
+ end
2213
2339
  end
2214
2340
  # End of Kamelopard module