rayzer 0.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +35 -0
- data/Rakefile +8 -0
- data/lib/rayzer/constraint.rb +111 -0
- data/lib/rayzer/distributor.rb +126 -0
- data/lib/rayzer/layout.rb +141 -0
- data/lib/rayzer/version.rb +5 -0
- data/lib/rayzer.rb +6 -0
- data/releasing_new_version.md +6 -0
- data/sig/rayzer.rbs +4 -0
- data/usage_example.rb +48 -0
- metadata +57 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6d2d485235aff6865bd30482c32ffb45f1d4fb51ca8ecc49f4514edd774453aa
|
|
4
|
+
data.tar.gz: 6d01f1423c71f9ebe81e259fefc8db44bbc1795cd139abc2729992d52cf22c14
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 37213df3a9af6cdc3e3c75850644a89abba0991f1bcf95ab3c899193811137162d2f240de63723b70ec9aeb3dd50ed0062728cbea1385de7545c60d1b01da6af
|
|
7
|
+
data.tar.gz: cc974c31a04788be0206123bddeacfef55e11d92836264609e564ce430d2832383787b1ca47ced170cfa4faf8457f1e8f1a22c261b8fe9501387c6176c7be5ad
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 NullFluxKevin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Rayzer
|
|
2
|
+
|
|
3
|
+
A razor sharp layout engine for rectangular areas.
|
|
4
|
+
|
|
5
|
+
Use constraints such as fixed length, minimum length, percentage, ratio, and maximum length to divide a rectangular area into a tree of nested rows and columns.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
See `usage_example.rb`.
|
|
11
|
+
|
|
12
|
+
For full specs, read the tests.
|
|
13
|
+
|
|
14
|
+
TODO: more on usage
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
|
|
20
|
+
|
|
21
|
+
Install the gem and add to the application's Gemfile by executing:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## License
|
|
34
|
+
|
|
35
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
module Rayzer
|
|
2
|
+
class Constraint
|
|
3
|
+
# zero or one <=, >=, %, or :
|
|
4
|
+
# (?<=) is a look ahead assertion, if matches < or >, then check for =
|
|
5
|
+
# followed by digits
|
|
6
|
+
# then optionally followed by a decimal point "." and digits
|
|
7
|
+
@parse_arg_format_regex = /^([<>]?(?<=[<>])=|[%:])?\d+(.\d+)?$/
|
|
8
|
+
|
|
9
|
+
FIXED = :fixed
|
|
10
|
+
MINIMUM = :minimum
|
|
11
|
+
MAXIMUM = :maximum
|
|
12
|
+
PERCENTAGE = :percentage
|
|
13
|
+
RATIO = :ratio
|
|
14
|
+
|
|
15
|
+
# define factory class methods such as Constraint.fixed(value)
|
|
16
|
+
constants.each do |constraint_type|
|
|
17
|
+
define_singleton_method(constraint_type.downcase) do |value|
|
|
18
|
+
new(const_get(constraint_type), value)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
attr_reader :type, :value
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def initialize(type, value)
|
|
27
|
+
raise ArgumentError, "Negative constraint value: #{value}" if value.negative?
|
|
28
|
+
@type = type
|
|
29
|
+
@value = value
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# This intends to provide a concise api for things that accepts constraints
|
|
34
|
+
#
|
|
35
|
+
# Usage:
|
|
36
|
+
# To get a fixed constraint, pass: 30, "30", or :"30"
|
|
37
|
+
# To get a minimum constraint, pass: ">=30", or :">=30"
|
|
38
|
+
# To get a percentage constraint, pass: "30%", :"30%", "%30", :"%30"
|
|
39
|
+
# To get a ratio constraint, pass: ":30", or :":30"
|
|
40
|
+
# To get a maximum constraint, pass: "<=30", or :"<=30"
|
|
41
|
+
#
|
|
42
|
+
#
|
|
43
|
+
# API Usage Example:
|
|
44
|
+
# constraints = %i[ 3 20% <=10 >=5 :3 ] # or use %w
|
|
45
|
+
# constraints << Constraint.fixed(1)
|
|
46
|
+
#
|
|
47
|
+
# some_method(args)
|
|
48
|
+
#
|
|
49
|
+
# def some_method(args)
|
|
50
|
+
# constraints = args.map { |arg| Constraint.parse arg )
|
|
51
|
+
# ...
|
|
52
|
+
# end
|
|
53
|
+
#
|
|
54
|
+
def self.parse(arg)
|
|
55
|
+
|
|
56
|
+
is_of_valid_type = [Integer, Float, String, Symbol, self].any?{ |cls| arg.instance_of? cls }
|
|
57
|
+
|
|
58
|
+
unless is_of_valid_type
|
|
59
|
+
raise ArgumentError,
|
|
60
|
+
"Cannot parse: #{arg}. Constraint.parse only accepts: Constraint, Integer, Float, Symbol and String of valid format"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
return arg.dup if arg.instance_of? self
|
|
64
|
+
|
|
65
|
+
if [Integer, Float].include? arg.class
|
|
66
|
+
return fixed arg
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# I'm not making the regexp any more complex with look ahead assertion for checking % at the end only if the arg starts with a digit.
|
|
70
|
+
if arg[-1] == "%"
|
|
71
|
+
arg = "%" + arg[...-1]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
raise ArgumentError, "Invalid argument format in: #{arg}" unless arg =~ @parse_arg_format_regex
|
|
75
|
+
|
|
76
|
+
if arg[0] =~ /\d/
|
|
77
|
+
value = parse_number arg
|
|
78
|
+
return fixed value
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
case arg[0]
|
|
82
|
+
when ">"
|
|
83
|
+
value = parse_number arg[2..] # 2 == '>='.size
|
|
84
|
+
minimum value
|
|
85
|
+
when "%"
|
|
86
|
+
value = parse_number arg[1..]
|
|
87
|
+
percentage value
|
|
88
|
+
when "<"
|
|
89
|
+
value = parse_number arg[2..] # 2 == '<='.size
|
|
90
|
+
maximum value
|
|
91
|
+
when ":"
|
|
92
|
+
value = parse_number arg[1..]
|
|
93
|
+
ratio value
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def ==(other)
|
|
99
|
+
(@type == other.type) && (@value == other.value)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
def self.parse_number(arg)
|
|
105
|
+
arg = arg.to_s
|
|
106
|
+
arg.include?(".") ? arg.to_f : arg.to_i
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end # end of class
|
|
110
|
+
|
|
111
|
+
end # end of module
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Constraint Priority:
|
|
2
|
+
# fixed = minimum > percentage > ratio > maximum
|
|
3
|
+
#
|
|
4
|
+
# If there is still a remaining when every constraint is satisfied:
|
|
5
|
+
# If there is a minimum constraint, then the remaining is added to the result of the first minimum constraint.
|
|
6
|
+
# Otherwise:
|
|
7
|
+
# If used distribute, the remaining is added to the end of the returned array
|
|
8
|
+
# If used distribute!, raise an exception.
|
|
9
|
+
|
|
10
|
+
module Rayzer
|
|
11
|
+
module Distributor
|
|
12
|
+
refine Numeric do
|
|
13
|
+
|
|
14
|
+
def distribute(*constraints)
|
|
15
|
+
_distribute(constraints, false)
|
|
16
|
+
end # end of distribute method
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def distribute!(*constraints)
|
|
20
|
+
# raises if the value is not completely distributed
|
|
21
|
+
_distribute(constraints, true)
|
|
22
|
+
end # end of distribute! method
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
def _distribute(args, raise_if_has_remaining)
|
|
27
|
+
raise ArgumentError, "Can not distribute non-real value #{self}" unless [Integer, Float].include? self.class
|
|
28
|
+
|
|
29
|
+
raise ArgumentError, "Can not distribute non-positive value #{self}" unless self.positive?
|
|
30
|
+
|
|
31
|
+
constraints = args.map { |arg| Constraint.parse arg }
|
|
32
|
+
|
|
33
|
+
remaining = self
|
|
34
|
+
parts = Array.new(constraints.size) { 0 }
|
|
35
|
+
first_min_index = nil
|
|
36
|
+
|
|
37
|
+
total_percentage = 0
|
|
38
|
+
percentages = []
|
|
39
|
+
|
|
40
|
+
total_ratio = 0
|
|
41
|
+
ratios = []
|
|
42
|
+
|
|
43
|
+
maximums = []
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
constraints.each.with_index do |cons, i|
|
|
47
|
+
case cons.type
|
|
48
|
+
when Constraint::FIXED, Constraint::MINIMUM
|
|
49
|
+
parts[i] = cons.value
|
|
50
|
+
remaining -= cons.value
|
|
51
|
+
raise ArgumentError, "Sum of required constraints exceeds #{self}" if remaining < 0
|
|
52
|
+
|
|
53
|
+
if cons.type == Constraint::MINIMUM
|
|
54
|
+
first_min_index = i if first_min_index.nil?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
when Constraint::PERCENTAGE
|
|
58
|
+
total_percentage += cons.value
|
|
59
|
+
raise ArgumentError, "Sum of percentage constraints exceeds 100" if total_percentage > 100
|
|
60
|
+
|
|
61
|
+
percentages << [i, cons.value]
|
|
62
|
+
|
|
63
|
+
when Constraint::RATIO
|
|
64
|
+
total_ratio += cons.value
|
|
65
|
+
ratios << [i, cons.value]
|
|
66
|
+
|
|
67
|
+
when Constraint::MAXIMUM
|
|
68
|
+
maximums << [i, cons.value]
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
unless remaining.zero? or total_percentage.zero?
|
|
74
|
+
percentages.each do |i, percentage|
|
|
75
|
+
parts[i] = percentage * 0.01 * remaining
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
remaining = (1 - total_percentage * 0.01) * remaining
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
unless remaining.zero? or total_ratio.zero?
|
|
83
|
+
value_per_ratio = remaining.fdiv total_ratio
|
|
84
|
+
|
|
85
|
+
ratios.each do |i, ratio|
|
|
86
|
+
parts[i] = ratio * value_per_ratio
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
remaining = 0
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
maximums.each do |i, value|
|
|
94
|
+
if value < remaining
|
|
95
|
+
parts[i] = value
|
|
96
|
+
remaining -= value
|
|
97
|
+
else
|
|
98
|
+
parts[i] = remaining
|
|
99
|
+
remaining = 0
|
|
100
|
+
break
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
unless remaining.zero?
|
|
106
|
+
unless first_min_index.nil?
|
|
107
|
+
parts[first_min_index] += remaining
|
|
108
|
+
return parts
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
raise "Incomplete distribution of #{self}, remaining #{remaining}" if raise_if_has_remaining
|
|
112
|
+
|
|
113
|
+
parts << remaining
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
parts
|
|
118
|
+
end # end of _distribute method
|
|
119
|
+
|
|
120
|
+
# end of private
|
|
121
|
+
|
|
122
|
+
end # end of refinement
|
|
123
|
+
|
|
124
|
+
end # end of Distributor
|
|
125
|
+
|
|
126
|
+
end # end of Rayzer
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
require_relative 'distributor'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module Rayzer
|
|
5
|
+
class Layout
|
|
6
|
+
class RemainingSpaceError < ArgumentError; end
|
|
7
|
+
|
|
8
|
+
using Distributor
|
|
9
|
+
|
|
10
|
+
COLUMN_CONTAINER = :column_container
|
|
11
|
+
ROW_CONTAINER = :row_container
|
|
12
|
+
LEAF = :leaf
|
|
13
|
+
|
|
14
|
+
attr_reader :x, :y, :width, :height, :parent, :children, :type
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def initialize(x, y, width, height, parent=nil)
|
|
18
|
+
@x = x
|
|
19
|
+
@y = y
|
|
20
|
+
@width = width
|
|
21
|
+
@height = height
|
|
22
|
+
@parent = parent
|
|
23
|
+
@children = []
|
|
24
|
+
@type = LEAF
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def root?
|
|
29
|
+
@parent.nil?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def leaf?
|
|
34
|
+
@type == LEAF
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def rect
|
|
38
|
+
[@x, @y, @width, @height]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def split_to_rows(constraints, names=nil, &block)
|
|
43
|
+
heights = @height.distribute(*constraints)
|
|
44
|
+
curr_y = @y
|
|
45
|
+
@children = heights.map do |h|
|
|
46
|
+
row = self.class.new(@x, curr_y, @width, h, self)
|
|
47
|
+
curr_y += h
|
|
48
|
+
row
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
constraints_size = constraints.size
|
|
52
|
+
add_named_layout_instance_vars names, constraints_size
|
|
53
|
+
add_remaining_instance_var constraints_size
|
|
54
|
+
|
|
55
|
+
@type = ROW_CONTAINER
|
|
56
|
+
yield @children if block_given?
|
|
57
|
+
@children
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def split_to_cols(constraints, names=nil, &block)
|
|
62
|
+
widths = @width.distribute(*constraints)
|
|
63
|
+
|
|
64
|
+
curr_x = @x
|
|
65
|
+
|
|
66
|
+
@children = widths.map do |w|
|
|
67
|
+
col = self.class.new(curr_x, @y, w, @height, self)
|
|
68
|
+
curr_x += w
|
|
69
|
+
col
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
constraints_size = constraints.size
|
|
73
|
+
|
|
74
|
+
add_named_layout_instance_vars names, constraints_size
|
|
75
|
+
add_remaining_instance_var constraints_size
|
|
76
|
+
|
|
77
|
+
@type = COLUMN_CONTAINER
|
|
78
|
+
yield @children if block_given?
|
|
79
|
+
@children
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def split_to_cols!(constraints, names=nil, &block)
|
|
84
|
+
split_to_cols(constraints, names, &block)
|
|
85
|
+
raise RemainingSpaceError if instance_variable_defined? :@remaining
|
|
86
|
+
@children
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def split_to_rows!(constraints, names=nil, &block)
|
|
91
|
+
split_to_rows(constraints, names, &block)
|
|
92
|
+
raise RemainingSpaceError if instance_variable_defined? :@remaining
|
|
93
|
+
@children
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def ==(other)
|
|
98
|
+
# should require parent and children equality?
|
|
99
|
+
return false unless @x == other.x
|
|
100
|
+
return false unless @y == other.y
|
|
101
|
+
return false unless @width == other.width
|
|
102
|
+
return false unless @height == other.height
|
|
103
|
+
true
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
private
|
|
108
|
+
def add_named_layout_instance_vars(names, constraints_size)
|
|
109
|
+
unless names.nil?
|
|
110
|
+
if names.is_a? Array
|
|
111
|
+
raise ArgumentError, "Size of names and size of constraints mismatch" unless names.size == constraints_size
|
|
112
|
+
|
|
113
|
+
names.each.with_index do |name, i|
|
|
114
|
+
next if name.nil?
|
|
115
|
+
instance_variable_set "@#{name}", @children[i]
|
|
116
|
+
define_singleton_method(name) { instance_variable_get "@#{name}" }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
elsif names.is_a? Hash
|
|
120
|
+
names.each do |i, name|
|
|
121
|
+
instance_variable_set "@#{name}", @children.fetch(i)
|
|
122
|
+
define_singleton_method(name) { instance_variable_get "@#{name}" }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
else
|
|
126
|
+
raise ArgumentError, "Invalid type for arg: names. Expecting Array or Hash"
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def add_remaining_instance_var(constraints_size)
|
|
133
|
+
if @children.size - constraints_size == 1
|
|
134
|
+
instance_variable_set :@remaining, @children[-1]
|
|
135
|
+
define_singleton_method(:remaining) { instance_variable_get :@remaining }
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
end # end of layout
|
|
141
|
+
end # end of Rayzer
|
data/lib/rayzer.rb
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
## Development
|
|
2
|
+
|
|
3
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
4
|
+
|
|
5
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
6
|
+
|
data/sig/rayzer.rbs
ADDED
data/usage_example.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require "rayzer"
|
|
2
|
+
|
|
3
|
+
x = 0
|
|
4
|
+
y = 0
|
|
5
|
+
width = 100
|
|
6
|
+
height = 100
|
|
7
|
+
|
|
8
|
+
# Create a new top-level layout
|
|
9
|
+
root = Rayzer::Layout.new(x, y, width, height)
|
|
10
|
+
|
|
11
|
+
# Create 3 sections with fixed length 10, minimum length 0 and another fixed length 10.
|
|
12
|
+
sections = %w[ 10 >=0 10 ]
|
|
13
|
+
|
|
14
|
+
# You can optionally name the sections. If given a name, the section can be accessed with the reader of the same name.
|
|
15
|
+
section_names = %w[ header main footer ]
|
|
16
|
+
|
|
17
|
+
# Split_to_* returns the children as well also yields them to the block for further partition if a block is given.
|
|
18
|
+
root.split_to_rows!(sections, section_names) do |header, main, footer|
|
|
19
|
+
|
|
20
|
+
# Percentage constraint
|
|
21
|
+
constraints = %w[ 30% ]
|
|
22
|
+
|
|
23
|
+
# If there is remaining space after all constraints are satisfied, split_to_* appends the remaining to the children, whereas the bang version raises Rayzer::Layout::RemainingSpaceError.
|
|
24
|
+
#
|
|
25
|
+
# The remaining is also accessable using the remaining method.
|
|
26
|
+
#
|
|
27
|
+
# When no names are given, you can only access them using the children attr_reader later
|
|
28
|
+
main.split_to_cols(constraints) do |sidebar, remaining|
|
|
29
|
+
|
|
30
|
+
# Ratio constraints
|
|
31
|
+
rows = %i[:1 :3 :1]
|
|
32
|
+
|
|
33
|
+
# If you only want to access some inner layout by name, use a hash with index as the key and a symbol or name as value.
|
|
34
|
+
row_names = { 1 => :content }
|
|
35
|
+
|
|
36
|
+
remaining.split_to_rows!(rows, row_names)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
p root.header.rect # [0, 0, 100, 10]
|
|
42
|
+
p root.main.rect # [0, 10, 100, 80]
|
|
43
|
+
p root.footer.rect # [0, 90, 100, 10]
|
|
44
|
+
p root.main.children[0].rect # [0, 10, 30.0, 80]
|
|
45
|
+
p root.main.remaining.rect # [30.0, 10, 70.0, 80]
|
|
46
|
+
p root.main.remaining.children[0].rect # [30.0, 10, 70.0, 16.0]
|
|
47
|
+
p root.main.remaining.content.rect # [30.0, 26.0, 70.0, 48.0]
|
|
48
|
+
p root.main.remaining.children[2].rect # [30.0, 74.0, 70.0, 16.0]
|
metadata
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rayzer
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- NullFluxKevin
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: This Gem allows you to use constraints such as fixed length, minimum
|
|
13
|
+
length, percentage, ratio, and maximum length to divide a rectangular space into
|
|
14
|
+
a tree of nested rows and columns.
|
|
15
|
+
email:
|
|
16
|
+
- null_flux_kevin@outlook.com
|
|
17
|
+
executables: []
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- CHANGELOG.md
|
|
22
|
+
- LICENSE.txt
|
|
23
|
+
- README.md
|
|
24
|
+
- Rakefile
|
|
25
|
+
- lib/rayzer.rb
|
|
26
|
+
- lib/rayzer/constraint.rb
|
|
27
|
+
- lib/rayzer/distributor.rb
|
|
28
|
+
- lib/rayzer/layout.rb
|
|
29
|
+
- lib/rayzer/version.rb
|
|
30
|
+
- releasing_new_version.md
|
|
31
|
+
- sig/rayzer.rbs
|
|
32
|
+
- usage_example.rb
|
|
33
|
+
homepage: https://github.com/NullFluxKevin/rayzer
|
|
34
|
+
licenses:
|
|
35
|
+
- MIT
|
|
36
|
+
metadata:
|
|
37
|
+
homepage_uri: https://github.com/NullFluxKevin/rayzer
|
|
38
|
+
source_code_uri: https://github.com/NullFluxKevin/rayzer
|
|
39
|
+
changelog_uri: https://github.com/NullFluxKevin/rayzer/blob/main/CHANGELOG.md
|
|
40
|
+
rdoc_options: []
|
|
41
|
+
require_paths:
|
|
42
|
+
- lib
|
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 3.1.0
|
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
49
|
+
requirements:
|
|
50
|
+
- - ">="
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '0'
|
|
53
|
+
requirements: []
|
|
54
|
+
rubygems_version: 3.6.6
|
|
55
|
+
specification_version: 4
|
|
56
|
+
summary: A constraint-based layout engine for rectangular areas.
|
|
57
|
+
test_files: []
|