1
# sheet.rb: handling of style sheets
2
# copyright (c) 2012 by Vincent Fourmond
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.
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).
14
require 'ctioga2/utils'
17
require 'ctioga2/graphics/coordinates'
19
# This module contains all the classes used by ctioga
22
Version::register_svn_info('$Revision$', '$Date$')
28
# This is a style sheet, is a storage place for style
29
# objects. It has two related functions:
30
# * first, store the user-specified preferences
31
# * second, provide the appropriate default style for any given
32
# object, most probably at construction time (although that
33
# may get hard some times)
35
# The style are cascading and scoped. A scope should begin in
38
# Cascades happen in two ways:
40
# * more specific styles inherit from less specific (axis ->
42
# * children style inherit from parent style
45
# The parent of the style sheet, or nil if this is the top one.
48
# The styles, in form of a style class -> style name -> style
51
# The style object is actually a hash ready to be fed to the
52
# BasicStyle#set_from_hash
53
attr_accessor :own_styles
55
def initialize(par = nil)
60
# This hash contains the parent style for each of the style
63
# Keyed by class -> style name -> parent name
66
# Sets the parent for the given style
67
def self.set_parent(cls, style, parent)
68
@style_parent[cls] ||= {}
69
@style_parent[cls][style] = parent
72
# Returns the parent style for the style (or _nil_ should the
73
# style have no parent)
75
# All styles (but base) derive from the corresponding "base"
77
def self.get_parent(cls, style)
78
@style_parent[cls] ||= {}
79
stl = @style_parent[cls][style]
80
if (! stl) and (! (style == 'base'))
86
set_parent AxisStyle, "x", "base"
87
set_parent AxisStyle, "y", "base"
89
set_parent AxisStyle, "bottom", "x"
90
set_parent AxisStyle, "top", "x"
91
set_parent AxisStyle, "left", "y"
92
set_parent AxisStyle, "right", "y"
95
# This returns the style we have in this object for the given
96
# name. Inner cascading should take place (ie object
97
# hierarchy, but not scope hierarchy).
99
# This returns a hash that can be modified.
100
def own_style_hash_for(cls, name)
101
p = self.class.get_parent(cls, name)
104
base = own_style_hash_for(cls, p)
106
@own_styles[cls] ||= {}
107
style = @own_styles[cls][name]
112
style.merge!(base) { |key, v1, v2| v1 }
116
# The style for the given name, including all cascading
117
def get_style_hash_for(cls, name)
120
ps = @parent.get_style_hash_for(cls, name);
122
style = own_style_hash_for(cls, name)
123
style.merge!(ps) { |key, v1, v2| v1 }
130
@sheet = StyleSheet.new
132
# Returns a suitable style object for the given style name, or
133
# crashes if the name isn't known.
135
# Additional arguments are passed to the constructor
136
def self.style_for(cls, name, *args)
138
a.set_from_hash(@sheet.get_style_hash_for(cls, name))
142
def self.enter_scope()
143
@sheet = StyleSheet.new(@sheet)
146
def self.leave_scope()
148
@sheet = @sheet.parent
150
warn { "Trying to leave top-level stylesheet scope" }
154
def self.current_sheet()
160
StyleSheetGroup = CmdGroup.new('style-sheets',
163
Commands for defining default styles.
165
All commands take the name of the style to redefine. Different styles
166
live in a different name space, so there is no risk naming an @axis@ and
167
a @text@ style with the same name. All styles for a given type inherit from
168
the style name @base@.
170
ctioga2 does not support changing a style after its use. It may
171
affect only the following objects or all the ones that were created
172
from the beginning, depending on the context. For safety, only define
173
style before issueing any graphics command.
175
ctioga2 may support at a later time loading style files, but that is
176
not the case for now.
179
# We create the commands programmatically
181
['axis', AxisStyle, 'axis'],
182
['background', BackgroundStyle, 'plot background'],
183
['title', TextLabel, 'plot title'],
184
['text', FullTextStyle, 'text'],
185
['marker', MarkerStringStyle, 'marker'],
186
['box', BoxStyle, 'boxes'],
187
['arrow', ArrowStyle, 'arrows'],
188
['line', StrokeStyle, 'lines']
191
StyleSheetCommands = {}
192
StyleSheetPredefinedNames = {}
197
StyleSheetCommands[name] =
198
Cmd.new("define-#{name}-style",nil,
199
"--define-#{name}-style",
204
) do |plotmaker, what, opts|
205
StyleSheet.current_sheet.own_styles[cls] ||= {}
206
StyleSheet.current_sheet.own_styles[cls][what] ||= {}
207
StyleSheet.current_sheet.own_styles[cls][what].merge!(opts)
209
StyleSheetCommands[name].
210
describe("Sets the default style for the given #{desc}.",
211
<<"EOH", StyleSheetGroup)
212
Sets the default style for the named #{desc}.
216
StyleSheetCommands['line'].long_description = <<EOD
217
Sets the default style for lines. All line styles descend from the
218
@base@ style. Use a style different than @base@ by passing its name as
219
the @/base-style@ option to the {command: draw-line} command.
221
Meaning of the style parameters:
223
* @color@: the color of the line, see {type: color}
224
* @style@: the line style, see {type: line-style}
225
* @width@: the line width (in points)
227
> --define-line-style base /color=Pink
229
makes all lines pink (unless overriden by the /color option to
230
{command: draw-line}), while
232
> --define-line-style line-pink /color=Pink
234
only affect those to which the /base-style=line-pink style option
238
StyleSheetCommands['arrow'].long_description = <<EOD
239
Sets the default style for arrows. All arrow styles descend from the
240
@base@ style. Use a style different than @base@ by passing its name as
241
the @/base-style@ option to the {command: draw-arrow} command.
243
Meaning of the style parameters:
245
* @color@, @style@ and @width@: same as in {command: define-line-style}
246
* @head_marker@, @tail_marker@: a {type: marker} to be used for the head
248
* @head_scale@, @tail_scale@: scale of the head or tail markers
249
* @head_angle@, @tail_angle@: rotate the head or the tail by that many
251
* @head_color@, @tail_color@: the {type: color} of the head or tail
254
StyleSheetCommands['box'].long_description = <<EOD
255
Sets the default style for boxes. All box styles descend from the
256
@base@ style. Use a style different than @base@ by passing its name as
257
the @/base-style@ option to the {command: draw-box} command.
259
Meaning of the style parameters:
261
* @color@, @style@ and @width@: same as in {command: define-line-style}
262
* @fill_color@: fill color for the box
263
* @fill_transparency@: the transparency for the fill, from 0 to 1
266
StyleSheetCommands['text'].long_description = <<EOD
267
Sets the default style for texts. All text styles descend from the
268
@base@ style. Use a style different than @base@ by passing its name as
269
the @/base-style@ option to the {command: draw-text} command.
271
Meaning of the style parameters:
273
* @alignment@: vertical alignment
274
* @justification@: horizontal alignment
275
* @angle@: angle in degrees to the horizontal (or default orientation in
277
* @color@: text color
278
* @scale@: text scale
281
StyleSheetCommands['title'].long_description = <<EOD
282
Sets the style for title. All title styles descend from the
283
@base@ style. In addition, the title of a plot is addressed by the
286
Meaning of the style parameters:
288
* @alignment@, @justification@, @angle@, @color@ and @scale@:
289
as in {command: define-text-style}
290
* @text@: sets the title text
291
* @loc@: the side on which to display the title, a {type: location}
292
* @shift@: the distance away from the plot in text size units
293
(maybe a dimension should be better later)
294
* @position@: shift from the center (parallel to the plot side)
297
StyleSheetCommands['marker'].long_description = <<EOD
298
Sets the style for marker and marker strings. All marker and marker
299
string styles descend from the @base@ style. Use a style different
300
than @base@ by passing its name as the @/base-style@ option to the
301
{command: draw-marker} or {command: draw-string-marker} commands.
303
Meaning of the style parameters:
305
* @alignment@, @justification@, @angle@, @color@ and @scale@:
306
as in {command: define-text-style}
307
* @fill_color@ and @stroke_color@: markers are both stroked and filled,
308
you can control all colors in one go using @color@ or specifying each
309
with @fill_color@ and @stroke_color@
310
* @font@: is a PDF font number (from 1 to 14), only used for marker
312
* @horizontal_scale@, @vertical_scale@: scales the marker only
313
horizontally or vertically
316
StyleSheetCommands['background'].long_description = <<EOD
317
Sets the style for plot background. All background styles descend from the
318
@base@ style. In addition, the background of a plot is change by the
319
style name @background@.
321
Meaning of the style parameters:
323
* @watermark@: the text of the watermark
324
* all @watermark_@ styles have the same meaning as in
325
{command: define-text-style}, as the watermark is a string marker
326
* @background_color@: the color of the background
329
StyleSheetCommands['axis'].long_description = <<EOD
330
Sets the style for a whole axis. All axis styles descend from the
331
@base@ style. Horizontal and vertical axis styles descend from the
332
@x@ and @y@ styles, and plot sides are styled with the @left@, @right@,
333
@top@ and @bottom@ styles.
335
Axis styles have lots of parameters:
337
* @axis_label_@ and @tick_label_@ parameters are title style parameters
338
whose meaning is given in {command: define-title-style}, that affect
339
ticks and axis labels
340
* @decoration@: a {type: axis-decoration} that specify which ticks and
342
* @background_lines_@ parameters define the style of background lines,
343
as in {command: define-line-style}