ctioga 1.11.1
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.
- data/COPYING +340 -0
- data/ctioga/bin/ctable +28 -0
- data/ctioga/bin/ctioga +37 -0
- data/ctioga/doc/ctable.1 +156 -0
- data/ctioga/doc/ctioga.1 +2363 -0
- data/ctioga/examples/README +46 -0
- data/ctioga/examples/ctioga.gnuplot +4 -0
- data/ctioga/examples/ctioga_within_tioga.rb +53 -0
- data/ctioga/examples/ctiogarc.rb +24 -0
- data/ctioga/examples/include_1.rb +15 -0
- data/ctioga/examples/noise.dat +100 -0
- data/ctioga/examples/noise.rb +13 -0
- data/ctioga/examples/trig.csv +100 -0
- data/ctioga/examples/trig.dat +100 -0
- data/ctioga/examples/trig.rb +14 -0
- data/ctioga/examples/trigh.dat +100 -0
- data/ctioga/examples/trigh.rb +10 -0
- data/ctioga/examples/tutorial +763 -0
- data/ctioga/examples/tutorial.sh +269 -0
- data/ctioga/tests/README +14 -0
- data/ctioga/tests/axes.sh +40 -0
- data/ctioga/tests/basic.sh +11 -0
- data/ctioga/tests/draw.sh +24 -0
- data/ctioga/tests/histograms.sh +14 -0
- data/ctioga/tests/insets.sh +41 -0
- data/ctioga/tests/layouts.sh +29 -0
- data/ctioga/tests/legends.sh +113 -0
- data/ctioga/tests/styles.sh +43 -0
- data/ctioga/tests/test_style.sh +8 -0
- data/ctioga/tests/tests.sh +24 -0
- data/ctioga/tests/text_backend.sh +83 -0
- data/ctioga/tests/tioga_defaults.rb +18 -0
- data/lib/CTioga/axes.rb +904 -0
- data/lib/CTioga/backends.rb +88 -0
- data/lib/CTioga/boundaries.rb +224 -0
- data/lib/CTioga/ctable.rb +134 -0
- data/lib/CTioga/curve_style.rb +246 -0
- data/lib/CTioga/debug.rb +199 -0
- data/lib/CTioga/dimension.rb +133 -0
- data/lib/CTioga/elements.rb +17 -0
- data/lib/CTioga/elements/base.rb +84 -0
- data/lib/CTioga/elements/containers.rb +578 -0
- data/lib/CTioga/elements/curves.rb +368 -0
- data/lib/CTioga/elements/tioga_primitives.rb +440 -0
- data/lib/CTioga/layout.rb +595 -0
- data/lib/CTioga/legends.rb +29 -0
- data/lib/CTioga/legends/cmdline.rb +187 -0
- data/lib/CTioga/legends/item.rb +164 -0
- data/lib/CTioga/legends/style.rb +257 -0
- data/lib/CTioga/log.rb +73 -0
- data/lib/CTioga/movingarrays.rb +131 -0
- data/lib/CTioga/partition.rb +271 -0
- data/lib/CTioga/plot_style.rb +230 -0
- data/lib/CTioga/plotmaker.rb +1677 -0
- data/lib/CTioga/shortcuts.rb +69 -0
- data/lib/CTioga/structures.rb +82 -0
- data/lib/CTioga/styles.rb +140 -0
- data/lib/CTioga/themes.rb +581 -0
- data/lib/CTioga/themes/classical.rb +82 -0
- data/lib/CTioga/themes/demo.rb +63 -0
- data/lib/CTioga/themes/fits.rb +91 -0
- data/lib/CTioga/themes/mono.rb +33 -0
- data/lib/CTioga/tioga.rb +32 -0
- data/lib/CTioga/utils.rb +173 -0
- data/lib/MetaBuilder/Parameters/dates.rb +38 -0
- data/lib/MetaBuilder/Parameters/lists.rb +132 -0
- data/lib/MetaBuilder/Parameters/numbers.rb +69 -0
- data/lib/MetaBuilder/Parameters/strings.rb +86 -0
- data/lib/MetaBuilder/Parameters/styles.rb +75 -0
- data/lib/MetaBuilder/Qt4/Parameters/dates.rb +51 -0
- data/lib/MetaBuilder/Qt4/Parameters/numbers.rb +65 -0
- data/lib/MetaBuilder/Qt4/Parameters/strings.rb +106 -0
- data/lib/MetaBuilder/Qt4/parameter.rb +172 -0
- data/lib/MetaBuilder/Qt4/parameters.rb +9 -0
- data/lib/MetaBuilder/descriptions.rb +603 -0
- data/lib/MetaBuilder/factory.rb +101 -0
- data/lib/MetaBuilder/group.rb +57 -0
- data/lib/MetaBuilder/metabuilder.rb +10 -0
- data/lib/MetaBuilder/parameter.rb +374 -0
- data/lib/MetaBuilder/parameters.rb +11 -0
- data/lib/MetaBuilder/qt4.rb +8 -0
- data/lib/SciYAG/Backends/backend.rb +379 -0
- data/lib/SciYAG/Backends/binner.rb +168 -0
- data/lib/SciYAG/Backends/cache.rb +102 -0
- data/lib/SciYAG/Backends/dataset.rb +158 -0
- data/lib/SciYAG/Backends/descriptions.rb +469 -0
- data/lib/SciYAG/Backends/filters.rb +25 -0
- data/lib/SciYAG/Backends/filters/average.rb +134 -0
- data/lib/SciYAG/Backends/filters/cumulate.rb +37 -0
- data/lib/SciYAG/Backends/filters/filter.rb +70 -0
- data/lib/SciYAG/Backends/filters/norm.rb +39 -0
- data/lib/SciYAG/Backends/filters/smooth.rb +63 -0
- data/lib/SciYAG/Backends/filters/sort.rb +43 -0
- data/lib/SciYAG/Backends/filters/strip.rb +34 -0
- data/lib/SciYAG/Backends/filters/trim.rb +64 -0
- data/lib/SciYAG/Backends/gnuplot.rb +131 -0
- data/lib/SciYAG/Backends/math.rb +108 -0
- data/lib/SciYAG/Backends/mdb.rb +462 -0
- data/lib/SciYAG/Backends/multitext.rb +96 -0
- data/lib/SciYAG/Backends/source.rb +64 -0
- data/lib/SciYAG/Backends/text.rb +339 -0
- data/lib/SciYAG/backends.rb +16 -0
- metadata +191 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# legends.rb: legend implementation of CTioga
|
|
2
|
+
# copyright (c) 2008 by Vincent Fourmond:
|
|
3
|
+
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details (in the COPYING file).
|
|
13
|
+
|
|
14
|
+
require 'CTioga/log'
|
|
15
|
+
require 'CTioga/debug'
|
|
16
|
+
require 'CTioga/curve_style'
|
|
17
|
+
require 'CTioga/dimension'
|
|
18
|
+
|
|
19
|
+
require 'CTioga/boundaries'
|
|
20
|
+
|
|
21
|
+
require 'CTioga/legends/item'
|
|
22
|
+
require 'CTioga/legends/style'
|
|
23
|
+
require 'CTioga/legends/cmdline'
|
|
24
|
+
|
|
25
|
+
module CTioga
|
|
26
|
+
|
|
27
|
+
Version::register_svn_info('$Revision: 838 $', '$Date: 2008-10-11 13:27:05 +0200 (Sat, 11 Oct 2008) $')
|
|
28
|
+
|
|
29
|
+
end
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# legends.rb: command-line parsing for legends
|
|
2
|
+
# copyright (c) 2008 by Vincent Fourmond:
|
|
3
|
+
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details (in the COPYING file).
|
|
13
|
+
|
|
14
|
+
require 'CTioga/log'
|
|
15
|
+
require 'CTioga/debug'
|
|
16
|
+
require 'CTioga/curve_style'
|
|
17
|
+
require 'CTioga/dimension'
|
|
18
|
+
|
|
19
|
+
module CTioga
|
|
20
|
+
|
|
21
|
+
Version::register_svn_info('$Revision: 870 $', '$Date: 2009-01-20 14:28:32 +0100 (Tue, 20 Jan 2009) $')
|
|
22
|
+
|
|
23
|
+
# A module to deal with legends...
|
|
24
|
+
module Legends
|
|
25
|
+
|
|
26
|
+
# Parse the legend positions
|
|
27
|
+
def self.legend_position(spec)
|
|
28
|
+
specs = {}
|
|
29
|
+
begin
|
|
30
|
+
margins = Utils::inset_margins(spec)
|
|
31
|
+
specs = margins.to_frame("legend_%s_margin")
|
|
32
|
+
rescue # in case of an incorrect margin
|
|
33
|
+
# Then we look for a position in the spirit of:
|
|
34
|
+
if spec =~ /\s*([tbc])([rlc])\s*(?::\s*([\d.eE+-]+),([\d.eE+-]+))?\s*$/
|
|
35
|
+
if($3 && $4)
|
|
36
|
+
x = Float($3)
|
|
37
|
+
y = Float($4)
|
|
38
|
+
else
|
|
39
|
+
x = y = nil
|
|
40
|
+
end
|
|
41
|
+
if $1 == 't'
|
|
42
|
+
specs['legend_top'] = y || 0.95
|
|
43
|
+
elsif $1 == 'b'
|
|
44
|
+
specs['legend_bottom'] = y || 0.05
|
|
45
|
+
else
|
|
46
|
+
specs['legend_vcenter'] = y || 0.5
|
|
47
|
+
end
|
|
48
|
+
if $2 == 'l'
|
|
49
|
+
specs['legend_left'] = x || 0.05
|
|
50
|
+
elsif $2 == 'r'
|
|
51
|
+
specs['legend_right'] = x || 0.95
|
|
52
|
+
else
|
|
53
|
+
specs['legend_hcenter'] = x || 0.5
|
|
54
|
+
end
|
|
55
|
+
else
|
|
56
|
+
raise "Incorrect legend (inside) position: '#{spec}'"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
return specs
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Fills up an OptionParser, _parser_ with legend-related command-line
|
|
63
|
+
# options. Takes a Plotmaker _target_
|
|
64
|
+
def self.fill_option_parser(parser, target)
|
|
65
|
+
|
|
66
|
+
parser.separator "\nLegends:"
|
|
67
|
+
|
|
68
|
+
parser.on("-l","--[no-]legend [LEGEND]",
|
|
69
|
+
"Sets the legend of the next curve.") do |l|
|
|
70
|
+
target.override_style.legend = l
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
parser.on("--[no-]auto-legend",
|
|
74
|
+
"Whether to automatically add legends",
|
|
75
|
+
"to curves") do |l|
|
|
76
|
+
target.autolegends = l
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
parser.on('-N', "--no-legends",
|
|
80
|
+
"Alias for --no-auto-legend") do
|
|
81
|
+
target.autolegends = false
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
## Legend scale
|
|
85
|
+
parser.on("--legend-scale FACT",
|
|
86
|
+
"Sets the scale for the legends") do |l|
|
|
87
|
+
target.add_elem_funcall(:legend_scale=, Float(l))
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
parser.on("--legend-line TEXT",
|
|
91
|
+
"Adds the line TEXT in the legend") do |l|
|
|
92
|
+
target.current_object.add_legend_info(LegendLine.new(l))
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
parser.on("--legend-dy DIM",
|
|
97
|
+
"The distance between two legend lines, ",
|
|
98
|
+
"expressed in terms of text line size") do |l|
|
|
99
|
+
target.current_object.plot_style.legend_style.dy =
|
|
100
|
+
TextDimension.new(l)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
parser.on("--legend-pos SPEC",
|
|
104
|
+
"Sets the legend position and its size.",
|
|
105
|
+
"SPEC looks like pos,size[,delta]") do |a|
|
|
106
|
+
w,s,d = a.split /\s*,\s*/
|
|
107
|
+
if d
|
|
108
|
+
warn "The delta specification (#{d}) for #{a} is ignored"
|
|
109
|
+
end
|
|
110
|
+
target.debug "Legend position #{w.inspect} #{s.inspect}"
|
|
111
|
+
target.current_object.layout_preferences.legend_position = w.to_sym
|
|
112
|
+
target.current_object.layout_preferences.legend_size = Dimension.new(s)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
parser.on("--legend-inside SPEC",
|
|
116
|
+
"Makes a legend inside the plot.",
|
|
117
|
+
"See --inset for the format of SPEC") do |a|
|
|
118
|
+
specs = legend_position(a)
|
|
119
|
+
target.debug "Specs: #{specs.inspect}"
|
|
120
|
+
target.current_object.layout_preferences.legend_position = :inside
|
|
121
|
+
target.current_object.layout_preferences.legend_spec = specs
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Frames around legends:
|
|
125
|
+
parser.on("--[no-]legend-frame [WHAT]",
|
|
126
|
+
"Which frame should ctioga draw around legends ?") do |l|
|
|
127
|
+
if l =~ /square|round/i
|
|
128
|
+
l = l.downcase.to_sym
|
|
129
|
+
elsif l =~ /none/i || (!l)
|
|
130
|
+
l = false
|
|
131
|
+
else
|
|
132
|
+
warn "Incorrect legend frame: '#{l}'"
|
|
133
|
+
end
|
|
134
|
+
target.current_object.plot_style.legend_style.box_style = l
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# TODO: make all the legend styles...
|
|
138
|
+
parser.on("--[no-]legend-background [COLOR]",
|
|
139
|
+
"Background color for the legend") do |c|
|
|
140
|
+
c = CTioga.get_tioga_color(c) if c
|
|
141
|
+
target.current_object.plot_style.legend_style.background_color = c
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
parser.on("--[no-]legend-transparency [VALUE]",
|
|
145
|
+
"Transparency for the background") do |f|
|
|
146
|
+
if !f
|
|
147
|
+
f = 0.0
|
|
148
|
+
else
|
|
149
|
+
f = f.to_f
|
|
150
|
+
end
|
|
151
|
+
target.current_object.plot_style.legend_style.
|
|
152
|
+
background_transparency = f
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
parser.on("--[no-]legend-color [COLOR]",
|
|
156
|
+
"Color for the line around the legend") do |c|
|
|
157
|
+
c = CTioga.get_tioga_color(c) if c
|
|
158
|
+
target.current_object.plot_style.legend_style.line_color = c
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
parser.on("--legend-line-width WIDTH",
|
|
162
|
+
"Line width for drawing the legend") do |c|
|
|
163
|
+
c = Float(c)
|
|
164
|
+
target.current_object.plot_style.legend_style.line_width = c
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
parser.on("--legend-line-style STYLE",
|
|
168
|
+
"Line style for drawing the legend") do |c|
|
|
169
|
+
c = MetaBuilder::ParameterType.from_string(:line_style,c)
|
|
170
|
+
target.current_object.plot_style.legend_style.line_style = c
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
parser.on("--[no-]separate-legends",
|
|
174
|
+
"If set, PDF files are produced that contain",
|
|
175
|
+
"what the legend pictogram would look like") do |l|
|
|
176
|
+
target.separate_legends = l
|
|
177
|
+
if l
|
|
178
|
+
# Switches off autolegends by default
|
|
179
|
+
target.autolegends = false
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
end
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# legends.rb: legend implementation of CTioga
|
|
2
|
+
# copyright (c) 2008 by Vincent Fourmond:
|
|
3
|
+
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details (in the COPYING file).
|
|
13
|
+
|
|
14
|
+
require 'CTioga/log'
|
|
15
|
+
require 'CTioga/debug'
|
|
16
|
+
require 'CTioga/curve_style'
|
|
17
|
+
require 'CTioga/dimension'
|
|
18
|
+
|
|
19
|
+
module CTioga
|
|
20
|
+
|
|
21
|
+
Version::register_svn_info('$Revision: 839 $', '$Date: 2008-10-11 14:47:08 +0200 (Sat, 11 Oct 2008) $')
|
|
22
|
+
|
|
23
|
+
# The base class for all legends items (real legends, spacing, lines).
|
|
24
|
+
class LegendItem
|
|
25
|
+
|
|
26
|
+
include Debug
|
|
27
|
+
include Log
|
|
28
|
+
|
|
29
|
+
# This class-wide variable is used to number text
|
|
30
|
+
# in a unique fashion
|
|
31
|
+
@@legend_item_numbering = 0
|
|
32
|
+
|
|
33
|
+
def initialize
|
|
34
|
+
@legend_number = @@legend_item_numbering
|
|
35
|
+
@@legend_item_numbering += 1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Returns the (width, height) in figure coordinates
|
|
39
|
+
# of the legend element with the given LegendStyle
|
|
40
|
+
# and FigureMaker reference objects.
|
|
41
|
+
#
|
|
42
|
+
# The returned values can be inaccurate to some extent.
|
|
43
|
+
def size(t, legend_style)
|
|
44
|
+
return [0, 0]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Draws the legend at the given top left position (x,y)
|
|
48
|
+
# in figure coordinates.
|
|
49
|
+
def draw(t, legend_style, x, y)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# For internal use
|
|
53
|
+
def legend_name
|
|
54
|
+
return "legend-#{@legend_number}"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# We put the baseline so that the space above and below in the
|
|
58
|
+
# box of height legend_style.dy is even.
|
|
59
|
+
def get_baseline_y(t, legend_style, y)
|
|
60
|
+
return y - 0.5 * ( TextDimension.new(1.0).to_figure(t, :y) +
|
|
61
|
+
legend_style.dy.to_figure(t, :y))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# A class representing the style of a single legend line (unrelated
|
|
68
|
+
# to a curve)
|
|
69
|
+
class LegendLine < LegendItem
|
|
70
|
+
|
|
71
|
+
# The text of the line
|
|
72
|
+
attr_accessor :text
|
|
73
|
+
|
|
74
|
+
def initialize(text = "")
|
|
75
|
+
super()
|
|
76
|
+
@text = text
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Draw one single text line
|
|
80
|
+
def draw(t, legend_style, x, y)
|
|
81
|
+
y = get_baseline_y(t, legend_style, y)
|
|
82
|
+
t.show_text('x' => x, 'y' => y,
|
|
83
|
+
'text' => @text,
|
|
84
|
+
'justification' => LEFT_JUSTIFIED,
|
|
85
|
+
'measure' => legend_name
|
|
86
|
+
)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Computes the size of the line. Height should always
|
|
90
|
+
# be accurate, but width can be 0 sometimes...
|
|
91
|
+
def size(t, legend_style)
|
|
92
|
+
height = legend_style.dy.to_figure(t, :y)
|
|
93
|
+
info = t.get_text_size(legend_name)
|
|
94
|
+
if info.key? 'width'
|
|
95
|
+
width = t.convert_output_to_figure_dx(10*info['width'])
|
|
96
|
+
else
|
|
97
|
+
width = 0
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
return [ width, height ]
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# The class handling the drawing of one Curve
|
|
106
|
+
class CurveLegend < LegendItem
|
|
107
|
+
|
|
108
|
+
attr_accessor :curve_style
|
|
109
|
+
|
|
110
|
+
def initialize(style)
|
|
111
|
+
super()
|
|
112
|
+
@curve_style = style
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Draw one single text line
|
|
116
|
+
def draw(t, legend_style, x, y)
|
|
117
|
+
y = get_baseline_y(t, legend_style, y)
|
|
118
|
+
t.context do
|
|
119
|
+
# Position specification for the legend pictogram
|
|
120
|
+
margin_specs = { 'left' => x,
|
|
121
|
+
'right' => 1 - x - legend_style.picto_width.to_figure(t, :x),
|
|
122
|
+
'bottom' => y,
|
|
123
|
+
'top' => 1 - y - legend_style.picto_height.to_figure(t, :y)
|
|
124
|
+
}
|
|
125
|
+
debug "Legend margins for '#{@curve_style.legend}' : #{margin_specs.inspect}"
|
|
126
|
+
t.subfigure(margin_specs) do
|
|
127
|
+
# We scale the text back to normal so the markers have the right
|
|
128
|
+
# size
|
|
129
|
+
# t.line_width = 0.1
|
|
130
|
+
# t.stroke_rect(0,0,1,1)
|
|
131
|
+
t.rescale_text(1/legend_style.text_scale)
|
|
132
|
+
@curve_style.output_legend_pictogram(t)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
t.show_text('x' => x +
|
|
136
|
+
legend_style.picto_width.to_figure(t, :x) +
|
|
137
|
+
legend_style.picto_to_text.to_figure(t, :x),
|
|
138
|
+
'y' => y, 'text' => @curve_style.legend,
|
|
139
|
+
'measure' => legend_name,
|
|
140
|
+
'justification' => LEFT_JUSTIFIED)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Computes the size of the line. Height should always
|
|
144
|
+
# be accurate, but width can be 0 sometimes...
|
|
145
|
+
def size(t, legend_style)
|
|
146
|
+
height = legend_style.dy.to_figure(t, :y)
|
|
147
|
+
|
|
148
|
+
width = legend_style.picto_width.to_figure(t, :x) +
|
|
149
|
+
legend_style.picto_to_text.to_figure(t, :x)
|
|
150
|
+
|
|
151
|
+
info = t.get_text_size(legend_name)
|
|
152
|
+
|
|
153
|
+
if info.key? 'width'
|
|
154
|
+
width += t.convert_output_to_figure_dx(10*info['width'])
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
return [ width, height ]
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
end
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# legends.rb: legend implementation of CTioga
|
|
2
|
+
# copyright (c) 2008 by Vincent Fourmond:
|
|
3
|
+
|
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details (in the COPYING file).
|
|
13
|
+
|
|
14
|
+
require 'CTioga/log'
|
|
15
|
+
require 'CTioga/debug'
|
|
16
|
+
require 'CTioga/curve_style'
|
|
17
|
+
require 'CTioga/dimension'
|
|
18
|
+
|
|
19
|
+
module CTioga
|
|
20
|
+
|
|
21
|
+
Version::register_svn_info('$Revision: 858 $', '$Date: 2009-01-07 13:39:07 +0100 (Wed, 07 Jan 2009) $')
|
|
22
|
+
|
|
23
|
+
# A class that provides style information and display facilities
|
|
24
|
+
# for legends.
|
|
25
|
+
#
|
|
26
|
+
# It does not provide contents for the legends themselves
|
|
27
|
+
class LegendStyle
|
|
28
|
+
include Debug
|
|
29
|
+
include Log
|
|
30
|
+
|
|
31
|
+
# The distance between two legend lines
|
|
32
|
+
attr_accessor :dy
|
|
33
|
+
|
|
34
|
+
# The legend scale
|
|
35
|
+
attr_accessor :scale
|
|
36
|
+
|
|
37
|
+
# The padding between the legend and anything else around
|
|
38
|
+
attr_accessor :padding
|
|
39
|
+
|
|
40
|
+
# The width of the pictogram
|
|
41
|
+
attr_accessor :picto_width
|
|
42
|
+
|
|
43
|
+
# The height of the pictogram
|
|
44
|
+
attr_accessor :picto_height
|
|
45
|
+
|
|
46
|
+
# The distance between the pictogram and the text
|
|
47
|
+
attr_accessor :picto_to_text
|
|
48
|
+
|
|
49
|
+
# Scales all the text by that factor:
|
|
50
|
+
attr_accessor :text_scale
|
|
51
|
+
|
|
52
|
+
# Style of the box around the legend : (none/round/box)
|
|
53
|
+
attr_accessor :box_style
|
|
54
|
+
|
|
55
|
+
# The amount of space that should be left around the legend
|
|
56
|
+
# when drawing the box.
|
|
57
|
+
attr_accessor :margin
|
|
58
|
+
|
|
59
|
+
# The color of the background. false means no background
|
|
60
|
+
# Only meaningful when the #box_style is set to something
|
|
61
|
+
# different of none.
|
|
62
|
+
attr_accessor :background_color
|
|
63
|
+
|
|
64
|
+
# The color for the lines
|
|
65
|
+
attr_accessor :line_color
|
|
66
|
+
|
|
67
|
+
# The color for the lines
|
|
68
|
+
attr_accessor :line_width
|
|
69
|
+
|
|
70
|
+
# The color for the lines
|
|
71
|
+
attr_accessor :line_style
|
|
72
|
+
|
|
73
|
+
# The transparency of the background
|
|
74
|
+
attr_accessor :background_transparency
|
|
75
|
+
|
|
76
|
+
def initialize
|
|
77
|
+
# All in relative units ;-)...
|
|
78
|
+
@dy = TextDimension.new(1.9)
|
|
79
|
+
@padding = TextDimension.new(0.5)
|
|
80
|
+
@picto_width = TextDimension.new(1.5)
|
|
81
|
+
@picto_height = TextDimension.new(0.75)
|
|
82
|
+
@picto_to_text = TextDimension.new(0.5)
|
|
83
|
+
@scale = 1.0
|
|
84
|
+
|
|
85
|
+
@box_style = false # For no box.
|
|
86
|
+
|
|
87
|
+
# Frame styles:
|
|
88
|
+
@background_color = false
|
|
89
|
+
@background_transparency = 0.0
|
|
90
|
+
@line_color = Tioga::FigureConstants::Black
|
|
91
|
+
@line_width = 1.0
|
|
92
|
+
@line_style = false
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@margin = TextDimension.new(0.4)
|
|
96
|
+
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# Prepares the context in which the legend is made, and run
|
|
102
|
+
# the corresponding code
|
|
103
|
+
def legend_context(t, legend_specs,plot_margins)
|
|
104
|
+
subfigure_margins = {}
|
|
105
|
+
|
|
106
|
+
if legend_specs.key?('legend_left_margin')
|
|
107
|
+
# Now, we enter a subfigure:
|
|
108
|
+
for pos in %w{left right top bottom}
|
|
109
|
+
subfigure_margins[pos] = legend_specs["legend_#{pos}_margin"]
|
|
110
|
+
end
|
|
111
|
+
debug "Legend margins #{subfigure_margins.inspect}"
|
|
112
|
+
else # We make a subfigure relative to the plot
|
|
113
|
+
if plot_margins
|
|
114
|
+
subfigure_margins = plot_margins.dup
|
|
115
|
+
else
|
|
116
|
+
plot_margins = false
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
t.context do
|
|
121
|
+
t.set_subframe(subfigure_margins) if subfigure_margins
|
|
122
|
+
t.rescale(@scale)
|
|
123
|
+
t.rescale_text(@text_scale)
|
|
124
|
+
yield
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Prepare the frame path
|
|
130
|
+
def prepare_frame_path(t,xl,yt, total_width, total_height)
|
|
131
|
+
case @box_style
|
|
132
|
+
when :square
|
|
133
|
+
t.append_rect_to_path(xl - @margin.to_figure(t, :x),
|
|
134
|
+
yt + @margin.to_figure(t, :y),
|
|
135
|
+
total_width + 2 * @margin.to_figure(t, :x),
|
|
136
|
+
- total_height - 2 * @margin.to_figure(t, :y))
|
|
137
|
+
when :round
|
|
138
|
+
# For some reason, the append_rounded_rect_to_path does not
|
|
139
|
+
# work so well...
|
|
140
|
+
dx = @margin.to_figure(t, :x)
|
|
141
|
+
dy = @margin.to_figure(t, :y)
|
|
142
|
+
xr = xl + total_width
|
|
143
|
+
yb = yt - total_height
|
|
144
|
+
t.move_to_point(xl - dx, yt)
|
|
145
|
+
t.append_curve_to_path(xl - dx, yt + 0.5 * dy, # First control point
|
|
146
|
+
xl - 0.5 * dx, yt + dy,
|
|
147
|
+
xl, yt + dy)
|
|
148
|
+
t.append_point_to_path(xr, yt + dy)
|
|
149
|
+
t.append_curve_to_path(xr + 0.5 * dx, yt + dy, # First control point
|
|
150
|
+
xr + dx, yt + 0.5 * dy,
|
|
151
|
+
xr + dx, yt)
|
|
152
|
+
t.append_point_to_path(xr + dx, yb)
|
|
153
|
+
t.append_curve_to_path(xr + dx, yb - 0.5 * dy, # First control point
|
|
154
|
+
xr + 0.5 * dx, yb - dy,
|
|
155
|
+
xr, yb - dy)
|
|
156
|
+
t.append_point_to_path(xl, yb - dy)
|
|
157
|
+
t.append_curve_to_path(xl - 0.5 * dx, yb - dy, # First control point
|
|
158
|
+
xl - dx, yb - 0.5 * dy,
|
|
159
|
+
xl - dx, yb)
|
|
160
|
+
t.close_path
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Displays legends _legend_info_ to the FigureMaker object _t_ using
|
|
165
|
+
# boundaries given by _legend_specs_ for the plot with the
|
|
166
|
+
# given _plot_margins_
|
|
167
|
+
def show_legends(t, legend_specs, plot_margins, legend_info)
|
|
168
|
+
debug "Plotting legends: #{legend_specs.inspect}"
|
|
169
|
+
@text_scale ||= t.legend_scale
|
|
170
|
+
|
|
171
|
+
# First, we collect data on the legend_info
|
|
172
|
+
widths = []
|
|
173
|
+
heights = []
|
|
174
|
+
total_height = 0
|
|
175
|
+
total_width = 0
|
|
176
|
+
legend_context(t, legend_specs, plot_margins) do
|
|
177
|
+
for item in legend_info
|
|
178
|
+
w, h = item.size(t, self)
|
|
179
|
+
widths << w
|
|
180
|
+
heights << h
|
|
181
|
+
total_height += h
|
|
182
|
+
total_width = w if total_width < w
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
debug "Total height: #{total_height}\tTotal width: #{total_width}"
|
|
187
|
+
|
|
188
|
+
# Need to scope them now, so the context down actually modifies them !
|
|
189
|
+
xl = 0
|
|
190
|
+
yl = 0
|
|
191
|
+
if legend_specs.key?('legend_left_margin')
|
|
192
|
+
legend_context(t, legend_specs, plot_margins) do
|
|
193
|
+
yl = 1
|
|
194
|
+
xl = @padding.to_figure(t, :x)
|
|
195
|
+
end
|
|
196
|
+
elsif legend_specs.key?('legend_left') or
|
|
197
|
+
legend_specs.key?('legend_right') or
|
|
198
|
+
legend_specs.key?('legend_hcenter')
|
|
199
|
+
|
|
200
|
+
legend_context(t, legend_specs, plot_margins) do
|
|
201
|
+
if legend_specs.key?('legend_left')
|
|
202
|
+
xl = t.convert_frame_to_figure_x(legend_specs['legend_left'])
|
|
203
|
+
elsif legend_specs.key?('legend_right')
|
|
204
|
+
xl = t.convert_frame_to_figure_x(legend_specs['legend_right']) -
|
|
205
|
+
total_width
|
|
206
|
+
else
|
|
207
|
+
xl = t.convert_frame_to_figure_x(legend_specs['legend_hcenter']) -
|
|
208
|
+
total_width * 0.5
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
if legend_specs.key?('legend_top')
|
|
212
|
+
yl = t.convert_frame_to_figure_y(legend_specs['legend_top'])
|
|
213
|
+
elsif legend_specs.key?('legend_bottom')
|
|
214
|
+
yl = t.convert_frame_to_figure_y(legend_specs['legend_bottom']) +
|
|
215
|
+
total_height
|
|
216
|
+
else
|
|
217
|
+
yl = t.convert_frame_to_figure_y(legend_specs['legend_vcenter']) +
|
|
218
|
+
total_height * 0.5
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
else
|
|
222
|
+
# Silently do nothing:
|
|
223
|
+
return
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Always wrapping within a context call ;-)...
|
|
227
|
+
legend_context(t, legend_specs, plot_margins) do
|
|
228
|
+
# First, we draw the box if necessary
|
|
229
|
+
if @box_style
|
|
230
|
+
t.context do
|
|
231
|
+
if @background_color
|
|
232
|
+
t.fill_color = @background_color
|
|
233
|
+
t.fill_transparency = @background_transparency
|
|
234
|
+
prepare_frame_path(t, xl, yl, total_width, total_height)
|
|
235
|
+
t.fill
|
|
236
|
+
end
|
|
237
|
+
if @line_color
|
|
238
|
+
t.stroke_color = @line_color
|
|
239
|
+
t.line_width = @line_width
|
|
240
|
+
t.line_type = @line_style if @line_style
|
|
241
|
+
prepare_frame_path(t, xl, yl, total_width, total_height)
|
|
242
|
+
t.stroke
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
for item in legend_info
|
|
248
|
+
w, h = item.size(t, self)
|
|
249
|
+
item.draw(t, self, xl, yl)
|
|
250
|
+
yl -= h
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
end
|