lib/ctioga2/graphics/elements/primitive.rb in ctioga2-0.3 vs lib/ctioga2/graphics/elements/primitive.rb in ctioga2-0.4
- old
+ new
@@ -14,22 +14,28 @@
require 'ctioga2/utils'
require 'ctioga2/log'
require 'ctioga2/graphics/types'
+require 'ctioga2/graphics/styles'
require 'shellwords'
# This module contains all the classes used by ctioga
module CTioga2
- Version::register_svn_info('$Revision$', '$Date$')
+ Version::register_svn_info('$Revision: 370 $', '$Date: 2012-12-28 17:40:18 +0100 (Fri, 28 Dec 2012) $')
module Graphics
module Elements
# A TiogaElement that represents a graphics primitive.
+ #
+ # @todo Most of the objects here should rely on getting a
+ # BasicStyle object from the options hash and use it to
+ # draw. There is no need to make cumbersome and hard to extend
+ # hashes.
class TiogaPrimitiveCall < TiogaElement
# Some kind of reimplementation of Command for graphics
# primitives
class TiogaPrimitive
@@ -85,22 +91,27 @@
"Graphics primitives",
"Tioga graphics primitives", 3)
# Creates a new primitive with the given parameters, and makes
# it immediately available as a command.
- def self.primitive(name, long_name, comp, opts = {}, &code)
+ def self.primitive(name, long_name, comp, opts = {},
+ desc = nil, &code)
primitive = TiogaPrimitive.new(name, comp, opts, &code)
@known_primitives[name] = primitive
# Now, create the command
cmd_args = comp.map do |x|
CmdArg.new(x)
end
cmd_opts = {}
for k,v in opts
- cmd_opts[k] = CmdArg.new(v)
+ cmd_opts[k] = if v.respond_to?(:type)
+ v
+ else
+ CmdArg.new(v)
+ end
end
cmd = Cmd.new("draw-#{name}",nil,"--draw-#{name}",
cmd_args, cmd_opts) do |plotmaker, *rest|
options = rest.pop
@@ -109,78 +120,102 @@
rest, options)
call.last_curve_style = plotmaker.curve_style_stack.last
plotmaker.root_object.current_plot.
add_element(call)
end
+ if ! desc
+ desc = "Directly draws #{long_name} on the current plot"
+ end
cmd.describe("Draws #{long_name}",
- "Directly draws #{long_name} on the current plot", PrimitiveGroup)
+ desc,
+ PrimitiveGroup)
PrimitiveCommands[name] = cmd
end
+ # This creates a primitive base on a style object, given a
+ # _style_class_, the base _style_name_ for the underlying
+ # styling system, options to remove and options to add.
+ #
+ # The underlying code receives:
+ # * the FigureMaker object
+ # * the compulsory arguments
+ # * the style
+ # * the raw options
+ def self.styled_primitive(name, long_name, comp, style_class,
+ style_name, without = [],
+ additional_options = {},
+ set_style_command = nil, # This
+ # could be
+ # removed
+ &code)
+ options = style_class.options_hash.without(without)
+ options.merge!(additional_options)
+ options['base-style'] = 'text' # the base style name
+ set_style_command ||= style_name
+ desc = <<"EOD"
+Draws #{long_name} on the current plot, using the given style.
+For more information on the available options, see the
+{command: define-#{set_style_command}-style} command.
+EOD
+
+ self.primitive(name, long_name, comp, options, desc) do |*all|
+ opts = all.pop
+ st_name = opts['base-style'] || "base"
+ style = Styles::StyleSheet.style_for(style_class,st_name)
+ style.set_from_hash(opts)
+ all << style << opts
+ code.call(*all)
+ end
+ end
+
+
# Returns a pair primitive/primitive command for the named
# primitive, or [ _nil_, _nil_ ]
def self.get_primitive(name)
return [@known_primitives[name], PrimitiveCommands[name]]
end
# Now, a list of primitives, along with their code.
- primitive("text", "text", [ 'point', 'text' ],
- {
- 'color' => 'color',
- 'scale' => 'float',
- 'angle' => 'float',
- 'justification' => 'justification',
- 'alignment' => 'alignment',
- 'font' => 'latex-font',
- }
- ) do |t, point, string, options|
+ styled_primitive("text", "text",
+ [ 'point', 'text' ],
+ Styles::FullTextStyle,
+ 'text',
+ ['text'],
+ {'font' => 'latex-font'}
+ ) do |t, point, string, style, options|
# @todo add a way to specify fonts ???
options ||= {}
if options['font']
string = options['font'].fontify(string)
- options.delete('font')
end
- options['text'] = string
- options['at'] = point.to_figure_xy(t)
- t.show_text(options)
+ style.draw_text(t, string, *(point.to_figure_xy(t)))
end
- # @todo add rendering mode !!
- MarkerOptions = {
- 'color' => 'color',
- 'stroke_color' => 'color',
- 'fill_color' => 'color',
- 'scale' => 'float',
- 'horizontal_scale' => 'float',
- 'vertical_scale' => 'float',
- 'angle' => 'float',
- 'justification' => 'justification',
- 'alignment' => 'alignment',
- }
-
- primitive("marker", "marker", [ 'point', 'marker' ],
- MarkerOptions) do |t, point, marker, options|
- ## \todo add a way to specify fonts ???
- options ||= {}
- options['marker'] = marker
- options['at'] = point.to_figure_xy(t)
- t.show_marker(options)
+ styled_primitive("marker", "marker",
+ [ 'point', 'marker' ],
+ Styles::MarkerStringStyle,
+ 'marker',
+ ['font'] # font doesn't make any sense with a
+ # marker spec
+ ) do |t, point, marker, style, options|
+ style.draw_marker(t, marker, *point.to_figure_xy(t))
end
- primitive("string-marker", "marker", [ 'point', 'text' ],
- {'font' => 'pdf-font' }.update(MarkerOptions)
- ) do |t, point, string, options|
- ## \todo add a way to specify fonts ???
- options ||= {}
- options['text'] = string
- options['at'] = point.to_figure_xy(t)
- t.show_marker(options)
+ styled_primitive("string-marker", "marker",
+ [ 'point', 'text' ],
+ Styles::MarkerStringStyle,
+ 'marker-string', [],
+ {},
+ 'marker'
+ ) do |t, point, string, style, options|
+ style.draw_string_marker(t, string, *point.to_figure_xy(t))
end
+
# options for arrows (and therefore tangents)
ArrowOptions = {
'color' => 'color',
'head_scale' => 'float',
'head_marker' => 'marker',
@@ -190,35 +225,46 @@
'tail_color' => 'color',
'line_width' => 'float',
'line_style' => 'line-style',
}
- primitive("arrow", "arrow", [ 'point', 'point' ],
- ArrowOptions) do |t, tail,head, options|
- ## \todo a scale or marker_scale option that sets the scale
- ## of both head and tail
- options ||= {}
- options['head'] = head.to_figure_xy(t)
- options['tail'] = tail.to_figure_xy(t)
- t.show_arrow(options)
+ styled_primitive("arrow", "arrow",
+ [ 'point', 'point' ],
+ Styles::ArrowStyle,
+ 'arrow') do |t, tail, head, style, options|
+ style.draw_arrow(t, *tail.to_figure_xy(t),
+ *head.to_figure_xy(t))
end
-
- primitive("line", "line", [ 'point', 'point' ],
- {
- 'color' => 'color',
- 'line_width' => 'float',
- 'line_style' => 'line-style',
- }
- ) do |t, tail,head, options|
- options ||= {}
- for a in ['head', 'tail']
- options["#{a}_marker"] = "None"
- end
- options['head'] = head.to_figure_xy(t)
- options['tail'] = tail.to_figure_xy(t)
- t.show_arrow(options)
+
+ styled_primitive("line", "line",
+ [ 'point', 'point' ],
+ Styles::StrokeStyle,
+ 'line'
+ ) do |t, tail, head, style, options|
+ style.draw_line(t, *(tail.to_figure_xy(t)),
+ *(head.to_figure_xy(t)))
end
+ # Here, we need to add deprecated options for backward
+ # compatibility
+
+ for cmd in ['draw-line', 'draw-arrow']
+ Commands::make_alias_for_option cmd, 'width', 'line_width', true
+ Commands::make_alias_for_option cmd, 'style', 'line_style', true
+ end
+
+ styled_primitive("box", "box",
+ [ 'point', 'point' ],
+ Styles::BoxStyle,
+ 'box') do |t, tl, br, style, options|
+ x1,y1 = tl.to_figure_xy(t)
+ x2,y2 = br.to_figure_xy(t)
+ style.draw_box(t, x1, y1, x2, y2)
+ end
+
+
+ Commands::make_alias_for_option 'draw-box', 'fill_color', 'fill-color'
+ Commands::make_alias_for_option 'draw-box', 'fill_transparency', 'fill-transparency'
protected
# Draws the primitive
def real_do(t)