fxruby-enhancement 0.1.0 → 0.2.0

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.
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ =begin rdoc
3
+ This is a color map for Enhancement to make it
4
+ easier to deal with colors in FXRuby.
5
+
6
+ To use, just do:
7
+ include RGB
8
+ == List of available colors
9
+ <% for @fxcolor, @fxstring in @fxc %>
10
+ * <%= @fxcolor.snake %>
11
+ <% end %>
12
+
13
+ == NOTE WELL
14
+ This file is generated by fxruby-enhancement.
15
+ Do NOT modify this file. Modify the ERB template
16
+ file instead, and run 'rake scrape'.
17
+ =end
18
+
19
+ module RGB
20
+ <% for @fxcolor, @fxstring in @fxc %>
21
+ def <%= @fxcolor.snake %>; <%= @fxstring %>; end
22
+ <% end %>
23
+ end
@@ -1,4 +1,3 @@
1
- # coding: utf-8
2
1
  module Fox
3
2
 
4
3
  # Include this in your top class objects.
@@ -9,10 +8,12 @@ module Fox
9
8
  @stack = []
10
9
  @base = nil
11
10
  @components = {}
11
+ @kinder_parents = {}
12
12
  SPECIAL = [:FXApp,
13
13
  :FXColorItem,
14
14
  :FXRegion,
15
15
  :FXRectangle,
16
+ :FXPoint,
16
17
  :FXGradient,
17
18
  :FXEvent,
18
19
  :FXDataTarget,
@@ -23,6 +24,7 @@ module Fox
23
24
  # Module-level
24
25
  class << self
25
26
  attr_accessor :stack,
27
+ :kinder_parents, # this is to make 'as' delecrations work intuitively.
26
28
  :base, # the very first component declared, usually the app.
27
29
  :components,
28
30
  :deferred_setups,
@@ -97,6 +99,9 @@ module Fox
97
99
  end
98
100
  return inst
99
101
  end
102
+
103
+ def rgb
104
+ end
100
105
 
101
106
  # Find the referenced component's wrapper object
102
107
  def refc sym, &block
@@ -128,6 +133,31 @@ module Fox
128
133
  end
129
134
  alias_method :fxi, :fox_instance
130
135
 
136
+ # To allow for adding new components at
137
+ # other places other than the immediate
138
+ # parental nesting.
139
+ def as tag, kpos: Enhancement.stack.last, &block
140
+ Enhancement.stack << (@os = os = refc(tag))
141
+
142
+ # We must add our actual parent to the kinder parent
143
+ # registry, and remove it before we're done here.
144
+ kstacklvl = Enhancement.stack.size + 1
145
+ Enhancement.kinder_parents[kstacklvl] = kpos
146
+
147
+ def instance a=nil, &block
148
+ @os.instance_name = a
149
+ @os.instance_block ||= []
150
+ @os.instance_block << [a, block]
151
+ end
152
+
153
+ self.instance_eval &block
154
+
155
+ Enhancement.kinder_parents.delete kstacklvl
156
+ Enhancement.stack.pop
157
+ @os = Enhancement.stack.last
158
+ return os
159
+ end
160
+
131
161
  # Handles incomming external messages of type given
132
162
  # block, written by user, is called with |type, message|.
133
163
  # Zero or more symbols may be given,
@@ -148,7 +178,16 @@ module Fox
148
178
  # TODO: Not sure we need this. This may go away.
149
179
  def deferred_setup &block
150
180
  Enhancement.deferred_setups << block
151
- end
181
+ end
182
+
183
+ # This simplifies creating the FXDCWindow object.
184
+ def fx_dc tag, event=nil, &block
185
+ unless event.nil?
186
+ FXDCWindow.new(ref(tag), event) { |dc| block.(dc) }
187
+ else
188
+ FXDCWindow.new(ref(tag)) { |dc| block.(dc) }
189
+ end
190
+ end
152
191
  end
153
192
  end
154
193
  end
@@ -16,6 +16,7 @@ class OpenStruct
16
16
  def create_fox_components use_as_base = nil
17
17
  if use_as_base.nil?
18
18
  self.inst = fx.() if self.inst.nil?
19
+ self.as_tasks.map{ |a| a.() } unless self.as_tasks.nil?
19
20
  self.kinder.each{ |os|
20
21
  os.create_fox_components unless os.reusable?
21
22
  }
@@ -38,13 +39,27 @@ class OpenStruct
38
39
  }
39
40
  self.inst = nil
40
41
  end
41
-
42
+
43
+ # We can have as many instances as we like.
42
44
  def instance_final_activate
43
- self.instance_result = self.instance_block.(self.inst) unless self.instance_block.nil?
44
- self.kinder.each{ |os| os.instance_final_activate unless os.reusable? }
45
+ self.instance_result =
46
+ self.instance_block.map{ |name, inst|
47
+ inst.(self.inst)
48
+ } unless self.instance_block.nil?
49
+ self.kinder
50
+ .each{ |os|
51
+ os.instance_final_activate unless os.reusable?
52
+ }
45
53
  self
46
54
  end
47
55
 
56
+ # We must insure that instance actually is something
57
+ # other than nil.
58
+ def instance
59
+ raise "Instance is not set for #{self.klass}" if self.inst.nil?
60
+ self.inst
61
+ end
62
+
48
63
  # launch the application
49
64
  def launch ingress: false
50
65
  create_fox_components
@@ -0,0 +1,54 @@
1
+ # coding: utf-8
2
+ =begin rdoc
3
+ color = RGB::Color.from_rgb_hex("#333333")
4
+ color = RGB::Color.from_rgb_hex(0xFF0000)
5
+ color = RGB::Color.from_rgb(115, 38, 38)
6
+ color = RGB::Color.from_fractions(0, 1.0, 0.5) # HSL
7
+
8
+ # Supported color manipulations:
9
+ color.darken(20)
10
+ color.darken_percent(10)
11
+ color.darken!(20)
12
+ color.darken_percent!(10)
13
+ color.lighten(20)
14
+ color.lighten_percent(20)
15
+ color.lighten!(20)
16
+ color.lighten_percent!(20)
17
+ color.saturate(20)
18
+ color.saturate_percent(20)
19
+ color.saturate!(20)
20
+ color.saturate_percent!(20)
21
+ color.desaturate(20)
22
+ color.desaturate_percent(20)
23
+ color.desaturate!(20)
24
+ color.desaturate_percent!(20)
25
+
26
+ color.invert!
27
+
28
+ # Mixing colors:
29
+ color.mix(other_color, 20) # Mix 20% of other color into current one
30
+ color.mix(other_color) # 50% by default
31
+ color.mix!(other_color, 20)
32
+ color.mix!(other_color)
33
+
34
+ # Also you can adjust color HSL (hue, saturation, and lightness values) manually:
35
+ color.hue = 0.1
36
+ color.saturation = 0.2
37
+ color.lightness = 0.3
38
+
39
+ # Supported output formats:
40
+ color.to_rgb_hex
41
+ => "#732626"
42
+ color.to_hsl
43
+ => [0, 1.0, 0.5]
44
+ color.to_rgb
45
+ => [115, 38, 38]
46
+
47
+ =end
48
+
49
+ module RGB
50
+ class Color
51
+ def to_fx
52
+ end
53
+ end
54
+ end
@@ -0,0 +1 @@
1
+ require_relative 'xtras/charting.rb'
@@ -0,0 +1,247 @@
1
+ # coding: utf-8
2
+ module Fox
3
+ module Enhancement
4
+ module Xtras
5
+ # Charting constructs. Note that the
6
+ # rulers have built-in their own labeling, with orientation.
7
+ module Charting
8
+ # Box area of drawing interest. This is
9
+ # more virtual than actual, i.e. no clipping
10
+ # is performed.
11
+ class Box
12
+ include RGB
13
+ MAX_DOMINANCE = 3
14
+ NÄHE = [:top_box, :bottom_box, :left_box, :right_box]
15
+
16
+ # Name of this box -- we use this in some cases to avoid class polution
17
+ attr_reader :name
18
+
19
+ # coordinate and dimensions of the box
20
+ attr_accessor :x, :y, :width, :height
21
+
22
+ # hints on width and heigt, if meaningful, otherwise nil
23
+ attr_accessor :hint_width, :hint_height
24
+
25
+ # textual / apperance orientation :horizontal, :vertical, :none
26
+ # placement :top, :bottom, :left, :right
27
+ attr_accessor :orientation, :placement
28
+
29
+ # adjoining boxes
30
+ attr_accessor :top_box, :bottom_box
31
+ attr_accessor :left_box, :right_box
32
+
33
+ # margins
34
+ attr_accessor :top_margin, :bottom_margin, :left_margin, :right_margin
35
+
36
+ attr_accessor :enabled, :floating
37
+
38
+ # dominance rating (must be supplied)
39
+ attr_accessor :dominance
40
+
41
+ # always overide this the default simply renders a box
42
+ def render dc
43
+ raise "layout error in #{self.class}" if x.nil? or y.nil? or width.nil? or height.nil?
44
+ dc.setClipRectangle FXRectangle.new(x,y,width,height)
45
+ dc.foreground = black
46
+ dc.drawRectangle x, y, width-1, height-1
47
+ end
48
+
49
+ def enabled? ; enabled ; end
50
+ def floating? ; floating ; end
51
+
52
+ # calc the width and height of this box. Override!
53
+ def calculate_dimensions
54
+ self.width ||= (hint_width || 20) #TODO: remove the cheats
55
+ self.height ||= (hint_height || 10)
56
+ end
57
+
58
+ def initialize chart,
59
+ name: self.class,
60
+ float: false,
61
+ enabled: true,
62
+ dom: 1,
63
+ orient: :none,
64
+ placement: :unspecified
65
+ @chart = chart
66
+ @name = name
67
+ @dominance = dom
68
+ @floating = float
69
+ @top_margin = @bottom_margin = @left_margin = @right_margin = 0
70
+ @orientation = orient
71
+ @enabled = enabled
72
+ @placement = placement
73
+ end
74
+
75
+ def to_s
76
+ sprintf "<%50s dom=%s xywh=%-17s LRTB=%-14s %s>" % [name,
77
+ "#{dominance}",
78
+ "[#{x||'NIL'},#{y||'NIL'},#{width||'NIL'},#{height||'NIL'}]",
79
+ "[#{left_margin},#{right_margin},#{top_margin},#{bottom_margin}]",
80
+ "#{floating? ? 'floater' : ''}"
81
+ ]
82
+ end
83
+ end
84
+
85
+ # The null box represents the side of the container -- the
86
+ # canvas -- and will simplify layout.
87
+ class NullBox < Box
88
+ def initialize chart, **kv
89
+ super(chart, **kv)
90
+ @dominance = 0
91
+ end
92
+
93
+ # null box is never rendered.
94
+ def render dc ; end
95
+ end
96
+
97
+ class Ruler < Box
98
+ def render dc
99
+ super
100
+ # coord is normalized, 0 .. 1
101
+ Ticks.new(0, 1000) do |t|
102
+ dc.foreground = black
103
+
104
+ t.tick_lambda = ->(coord, value, major) {
105
+ tick_length = (orientation == :horizontal ? height : width) / (major ? 2 : 4)
106
+
107
+ x1 = if orientation == :horizontal
108
+ x + width * coord
109
+ elsif orientation == :vertical
110
+ if placement == :left
111
+ x + width
112
+ elsif placement == :right
113
+ x
114
+ else
115
+ raise "unknown placement :#{placement}"
116
+ end
117
+ else
118
+ raise "unknown orientation :#{orientation}"
119
+ end
120
+
121
+ y1 = if orientation == :horizontal
122
+ if placement == :top
123
+ y + height
124
+ elsif placement == :bottom
125
+ y
126
+ else
127
+ raise "unknown placement :#{placement}"
128
+ end
129
+ elsif orientation == :vertical
130
+ y + height * coord
131
+ else
132
+ raise "unknown orientation :#{orientation}"
133
+ end
134
+
135
+ x2 = if orientation == :horizontal
136
+ x1
137
+ elsif orientation == :vertical
138
+ if placement == :left
139
+ x1 - tick_length
140
+ elsif placement == :right
141
+ x1 + tick_length
142
+ else
143
+ raise "unknown placement :#{placement}"
144
+ end
145
+ else
146
+ raise "unknown orientation :#{orientation}"
147
+ end
148
+
149
+ y2 = if orientation == :horizontal
150
+ if placement == :top
151
+ y1 - tick_length
152
+ elsif placement == :bottom
153
+ y1 + tick_length
154
+ else
155
+ raise "unknown placement :#{placement}"
156
+ end
157
+ elsif orientation == :vertical
158
+ y1
159
+ else
160
+ raise "unknown orientation :#{orientation}"
161
+ end
162
+ dc.drawLine x1, y1, x2, y2
163
+ }
164
+
165
+ t.tick_label_lambda = ->(coord, label) {}
166
+ end.compute_ticks
167
+
168
+ end
169
+
170
+ def initialize chart, **kv
171
+ super
172
+ @dominance = 2
173
+ end
174
+ end
175
+
176
+ # For now, we assume that the placement
177
+ # of PureText boxes shall be above and
178
+ # below the GraphBox.
179
+ class PureText < Box
180
+ def calculate_wh
181
+ end
182
+
183
+ def calculate_dimensions
184
+ super
185
+ calculate_wh
186
+ begin
187
+ self.x = [top_box.width, bottom_box.width].max / 2 - self.width / 2
188
+ rescue ArgumentError, NoMethodError, TypeError => e
189
+ #puts "-->PureText unresolved: #{e}"
190
+ end
191
+ end
192
+ end
193
+
194
+ class Title < PureText
195
+ end
196
+
197
+ class Caption < PureText
198
+ end
199
+
200
+ class Legend < Box
201
+ # We calculate this on the basis
202
+ # of our actual content.
203
+ def calculate_wh
204
+ self.width = 50 # TODO: we're cheating again.
205
+ self.height = 30
206
+ end
207
+
208
+ def calculate_dimensions
209
+ super
210
+ calculate_wh
211
+
212
+ # This is a nasty hard-coding, which will not
213
+ # allow us to change the location of this box.
214
+ # Later, we'll want to add that flexibility.
215
+ self.y = right_box.height / 2 - self.height / 2
216
+ end
217
+ end
218
+
219
+ # main charting area.
220
+ class Graph < Box
221
+ def calculate_dimensions
222
+ super
223
+ begin
224
+ self.width = right_box.x \
225
+ - right_box.left_margin \
226
+ - left_box.x \
227
+ - left_box.width \
228
+ + left_box.right_margin
229
+ self.height = bottom_box.y \
230
+ - bottom_box.top_margin \
231
+ - top_box.y \
232
+ - top_box.height \
233
+ + top_box.bottom_margin
234
+ rescue NoMethodError, TypeError => e
235
+ #puts "-->Graph: unresolved: #{e}"
236
+ end
237
+ end
238
+
239
+ def initialize chart, **kv
240
+ super
241
+ @dominance = 3
242
+ end
243
+ end
244
+ end
245
+ end
246
+ end
247
+ end