~ubuntu-branches/ubuntu/wily/ctioga2/wily

« back to all changes in this revision

Viewing changes to lib/ctioga2/graphics/styles/sheet.rb

  • Committer: Package Import Robot
  • Author(s): Vincent Fourmond
  • Date: 2013-07-08 20:58:17 UTC
  • mfrom: (6.1.1 experimental)
  • Revision ID: package-import@ubuntu.com-20130708205817-cephnc6etndyxrrp
Tags: 0.4-2
* Upload to unstable
* Already conforms to newer standards

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# sheet.rb: handling of style sheets
 
2
# copyright (c) 2012 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 'ctioga2/utils'
 
15
require 'ctioga2/log'
 
16
 
 
17
require 'ctioga2/graphics/coordinates'
 
18
 
 
19
# This module contains all the classes used by ctioga
 
20
module CTioga2
 
21
 
 
22
  Version::register_svn_info('$Revision$', '$Date$')
 
23
 
 
24
  module Graphics
 
25
 
 
26
    module Styles
 
27
   
 
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)
 
34
      #
 
35
      # The style are cascading and scoped. A scope should begin in
 
36
      # each plot.
 
37
      #
 
38
      # Cascades happen in two ways:
 
39
      # 
 
40
      # * more specific styles inherit from less specific (axis ->
 
41
      #   yaxis -> left)
 
42
      # * children style inherit from parent style
 
43
      class StyleSheet
 
44
 
 
45
        # The parent of the style sheet, or nil if this is the top one.
 
46
        attr_accessor :parent
 
47
 
 
48
        # The styles, in form of a style class -> style name -> style
 
49
        # object nested hash
 
50
        #
 
51
        # The style object is actually a hash ready to be fed to the
 
52
        # BasicStyle#set_from_hash
 
53
        attr_accessor :own_styles
 
54
 
 
55
        def initialize(par = nil)
 
56
          @parent = par
 
57
          @own_styles = {}
 
58
        end
 
59
 
 
60
        # This hash contains the parent style for each of the style
 
61
        # listed in
 
62
        #
 
63
        # Keyed by class -> style name -> parent name
 
64
        @style_parent = {}
 
65
 
 
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
 
70
        end
 
71
        
 
72
        # Returns the parent style for the style (or _nil_ should the
 
73
        # style have no parent)
 
74
        #
 
75
        # All styles (but base) derive from the corresponding "base"
 
76
        # style.
 
77
        def self.get_parent(cls, style)
 
78
          @style_parent[cls] ||= {}
 
79
          stl = @style_parent[cls][style]
 
80
          if (! stl) and (! (style == 'base'))
 
81
            return 'base'
 
82
          end
 
83
          return stl
 
84
        end
 
85
 
 
86
        set_parent AxisStyle, "x",  "base"
 
87
        set_parent AxisStyle, "y",  "base"
 
88
 
 
89
        set_parent AxisStyle, "bottom", "x"
 
90
        set_parent AxisStyle, "top",    "x"
 
91
        set_parent AxisStyle, "left",   "y"
 
92
        set_parent AxisStyle, "right",  "y"
 
93
 
 
94
 
 
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).
 
98
        #
 
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)
 
102
          base = {}
 
103
          if p
 
104
            base = own_style_hash_for(cls, p)
 
105
          end
 
106
          @own_styles[cls] ||= {}
 
107
          style = @own_styles[cls][name]
 
108
          if ! style
 
109
            return base
 
110
          end
 
111
          style = style.dup
 
112
          style.merge!(base) { |key, v1, v2| v1 }
 
113
          return style
 
114
        end
 
115
 
 
116
        # The style for the given name, including all cascading
 
117
        def get_style_hash_for(cls, name)
 
118
          ps = {}
 
119
          if @parent
 
120
            ps = @parent.get_style_hash_for(cls, name);
 
121
          end
 
122
          style = own_style_hash_for(cls, name)
 
123
          style.merge!(ps) { |key, v1, v2| v1 }
 
124
          return style
 
125
        end
 
126
 
 
127
 
 
128
 
 
129
        # The current sheet
 
130
        @sheet = StyleSheet.new
 
131
        
 
132
        # Returns a suitable style object for the given style name, or
 
133
        # crashes if the name isn't known.
 
134
        #
 
135
        # Additional arguments are passed to the constructor
 
136
        def self.style_for(cls, name, *args)
 
137
          a = cls.new(*args)
 
138
          a.set_from_hash(@sheet.get_style_hash_for(cls, name))
 
139
          return a
 
140
        end
 
141
 
 
142
        def self.enter_scope()
 
143
          @sheet = StyleSheet.new(@sheet)
 
144
        end
 
145
 
 
146
        def self.leave_scope()
 
147
          if @sheet.parent
 
148
            @sheet = @sheet.parent
 
149
          else
 
150
            warn { "Trying to leave top-level stylesheet scope" }
 
151
          end
 
152
        end
 
153
 
 
154
        def self.current_sheet()
 
155
          return @sheet
 
156
        end
 
157
        
 
158
      end
 
159
 
 
160
      StyleSheetGroup = CmdGroup.new('style-sheets',
 
161
                                     "Default styles", 
 
162
                                     <<EOD, 40)
 
163
Commands for defining default styles.
 
164
 
 
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@.
 
169
 
 
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.
 
174
 
 
175
ctioga2 may support at a later time loading style files, but that is
 
176
not the case for now.
 
177
 
 
178
EOD
 
179
      # We create the commands programmatically
 
180
      kinds = [
 
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']
 
189
              ]
 
190
 
 
191
      StyleSheetCommands = {}
 
192
      StyleSheetPredefinedNames = {}
 
193
 
 
194
      kinds.each do |k|
 
195
        name, cls, desc = *k
 
196
 
 
197
        StyleSheetCommands[name] = 
 
198
          Cmd.new("define-#{name}-style",nil,
 
199
                  "--define-#{name}-style", 
 
200
                  [
 
201
                   CmdArg.new('text'),
 
202
                  ], 
 
203
                  cls.options_hash
 
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)
 
208
        end
 
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}.
 
213
EOH
 
214
      end
 
215
      
 
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.
 
220
 
 
221
Meaning of the style parameters:
 
222
 
 
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)
 
226
 
 
227
> --define-line-style base /color=Pink
 
228
 
 
229
makes all lines  pink (unless overriden by the /color option to
 
230
{command: draw-line}), while
 
231
 
 
232
> --define-line-style line-pink /color=Pink
 
233
 
 
234
only affect those to which the /base-style=line-pink style option
 
235
was given.
 
236
EOD
 
237
 
 
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.
 
242
 
 
243
Meaning of the style parameters:
 
244
 
 
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 
 
247
   or for the tail
 
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
 
250
   degrees
 
251
 * @head_color@, @tail_color@: the {type: color} of the head or tail
 
252
EOD
 
253
 
 
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.
 
258
 
 
259
Meaning of the style parameters:
 
260
 
 
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
 
264
EOD
 
265
 
 
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.
 
270
 
 
271
Meaning of the style parameters:
 
272
 
 
273
 * @alignment@: vertical alignment
 
274
 * @justification@: horizontal alignment
 
275
 * @angle@: angle in degrees to the horizontal (or default orientation in
 
276
   some cases)
 
277
 * @color@: text color
 
278
 * @scale@: text scale
 
279
EOD
 
280
 
 
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 
 
284
style name @title@.
 
285
 
 
286
Meaning of the style parameters:
 
287
 
 
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)
 
295
EOD
 
296
 
 
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.
 
302
 
 
303
Meaning of the style parameters:
 
304
 
 
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
 
311
   strings
 
312
 * @horizontal_scale@, @vertical_scale@: scales the marker only
 
313
   horizontally or vertically
 
314
EOD
 
315
 
 
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@.
 
320
 
 
321
Meaning of the style parameters:
 
322
 
 
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
 
327
EOD
 
328
 
 
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.
 
334
 
 
335
Axis styles have lots of parameters:
 
336
 
 
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 
 
341
   tick labels to draw
 
342
 * @background_lines_@ parameters define the style of background lines, 
 
343
   as in {command: define-line-style}
 
344
EOD
 
345
      
 
346
    end
 
347
  end
 
348
end