such 0.2.0 → 2.0.210201
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 +5 -5
- data/{README.rdoc → README.md} +61 -41
- data/lib/such.rb +5 -3
- data/lib/such/part.rb +16 -12
- data/lib/such/parts.rb +6 -8
- data/lib/such/such.rb +5 -6
- data/lib/such/thing.rb +30 -24
- data/lib/such/things.rb +14 -4
- metadata +16 -22
- data/lib/such/version.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 84767a253e3e1535798068135516617e3c198fc4b3ed756e529c16c27f25a649
|
4
|
+
data.tar.gz: 919ffcc84f13208bb3fc232ad8dc2ac92eb16b40d0cc6f63bb81b2b79c8b7e63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d53f03a3dc85ad766199e40d0f7d08011420ec1c437de865cdda76f2757a8c4bac012379098fd087af1f78ce11918be949b46fe0cff68668806df237a175a5f0
|
7
|
+
data.tar.gz: 96c391adf17465cdf4330a37c83eece66a1d4ae37337067fc8b04cd1f0105fe5f4b45b4863371c60d558552980e5ab744f9cb817c4c26322895b50139567760a
|
data/{README.rdoc → README.md}
RENAMED
@@ -1,54 +1,77 @@
|
|
1
|
-
|
1
|
+
# Such
|
2
2
|
|
3
|
-
|
3
|
+
* [VERSION 2.0.210201](https://github.com/carlosjhr64/such/releases)
|
4
|
+
* [github](https://www.github.com/carlosjhr64/such)
|
5
|
+
* [rubygems](https://rubygems.org/gems/such)
|
4
6
|
|
5
|
-
|
7
|
+
## DESCRIPTION:
|
8
|
+
|
9
|
+
Wraps widgets with an alternate constructor
|
6
10
|
which factors out the configuration and assembly procedures into metadata.
|
11
|
+
Can be used to wrap any class with the alternate constructor,
|
12
|
+
although targeted only Gtk3 widgets.
|
13
|
+
|
14
|
+
## INSTALL:
|
7
15
|
|
8
|
-
|
9
|
-
|
16
|
+
```shell
|
17
|
+
$ sudo gem install such
|
18
|
+
```
|
10
19
|
|
11
|
-
|
20
|
+
## SYNOPSIS:
|
12
21
|
|
13
|
-
|
14
|
-
|
15
|
-
|
22
|
+
```ruby
|
23
|
+
require 'gtk3'
|
24
|
+
require 'such'
|
25
|
+
include Such; Things.in Gtk::Widget
|
16
26
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
27
|
+
Thing.configure window: {
|
28
|
+
set_title: 'Synopsis Example',
|
29
|
+
set_window_position: :center},
|
30
|
+
BUTTON: [label: 'Button!'],
|
31
|
+
button: {
|
32
|
+
set_size_request: [100,50],
|
33
|
+
into:[:add]}
|
22
34
|
|
23
|
-
|
24
|
-
|
25
|
-
|
35
|
+
window = Window.new(:window, 'destroy'){Gtk.main_quit} #~> Such::Window
|
36
|
+
Button.new(window, :button!){puts 'Button pressed!'} #~> Such::Button
|
37
|
+
window.show_all
|
26
38
|
|
27
|
-
|
39
|
+
Gtk.main #=> nil
|
40
|
+
```
|
28
41
|
|
29
|
-
|
42
|
+
## MORE:
|
30
43
|
|
31
44
|
Arrays are passed to constructer's super,
|
32
45
|
Hashes are method=>arguments pairs, and Strings are signals.
|
33
46
|
Other objects are assumed to be containers:
|
34
47
|
|
35
|
-
|
48
|
+
```ruby
|
49
|
+
Such::Button.new(
|
50
|
+
window,
|
51
|
+
[label: 'Hello!'],
|
52
|
+
{set_size_request:[100,50]},
|
53
|
+
'clicked'
|
54
|
+
){ puts 'OK'}
|
36
55
|
|
37
|
-
|
56
|
+
# Is equivalent to:
|
38
57
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
58
|
+
button = Gtk::Button.new(label:'Hello!')
|
59
|
+
window.add button
|
60
|
+
button.set_size_request 100, 50
|
61
|
+
button.signal_connect('clicked'){puts 'OK'}
|
62
|
+
```
|
43
63
|
|
44
|
-
To set the packing method to say
|
64
|
+
To set the packing method to say `:pack_start`, set the `:into` method as follows:
|
45
65
|
|
46
|
-
|
47
|
-
|
48
|
-
|
66
|
+
```ruby
|
67
|
+
{into: [:pack_start, expand:false, fill:false, padding:0]}
|
68
|
+
# The effect in the contructor will be as if the following was run:
|
69
|
+
# container.pack_start(self, expand:false, fill:false, padding:0)
|
70
|
+
```
|
49
71
|
|
50
72
|
One can configure Symbol keys to represent metadata about a widget:
|
51
73
|
|
74
|
+
```ruby
|
52
75
|
Thing.configure(
|
53
76
|
KEY: [ arg1, arg2, arg3 ], # an array for super(arg1, arg2, arg3)
|
54
77
|
key: { # a hash for like self.method(args)
|
@@ -58,11 +81,12 @@ One can configure Symbol keys to represent metadata about a widget:
|
|
58
81
|
},
|
59
82
|
key!: [[arg1, arg2], {meth1:args1, meth2:args2}, 'signal1', 'signal2'] # the splatter bang!
|
60
83
|
)
|
84
|
+
```
|
61
85
|
|
62
86
|
The examples in this repository are reworks of the examples given in
|
63
|
-
ZetCode.com[http://zetcode.com/gui/rubygtk/].
|
87
|
+
ZetCode.com[http://zetcode.com/gui/rubygtk/] (back in 2015).
|
64
88
|
|
65
|
-
|
89
|
+
## Features:
|
66
90
|
|
67
91
|
* :key! content *splat
|
68
92
|
* Undefined :key! expanded to :KEY, :key
|
@@ -71,21 +95,17 @@ ZetCode.com[http://zetcode.com/gui/rubygtk/].
|
|
71
95
|
* Packing method defaults (ultimately) to :add
|
72
96
|
* Way to change default packing behaviour
|
73
97
|
|
74
|
-
|
75
|
-
|
76
|
-
$ sudo gem install such
|
77
|
-
|
78
|
-
== But wait! One more thing:
|
98
|
+
## But wait! One more thing:
|
79
99
|
|
80
|
-
See
|
81
|
-
and
|
82
|
-
Such::Part module
|
100
|
+
See [such_parts_demo](examples/such_parts_demo) in the examples directory
|
101
|
+
and [tc_part](test/tc_part) for hints on how to use the powerful
|
102
|
+
[Such::Part module](lib/such/part.rb).
|
83
103
|
|
84
|
-
|
104
|
+
## LICENSE:
|
85
105
|
|
86
106
|
(The MIT License)
|
87
107
|
|
88
|
-
Copyright (c)
|
108
|
+
Copyright (c) 2021 CarlosJHR64
|
89
109
|
|
90
110
|
Permission is hereby granted, free of charge, to any person obtaining
|
91
111
|
a copy of this software and associated documentation files (the
|
data/lib/such.rb
CHANGED
data/lib/such/part.rb
CHANGED
@@ -1,29 +1,33 @@
|
|
1
1
|
module Such
|
2
2
|
module Part
|
3
|
+
PLUG_PATTERN = /^(?<sym>[^\W_]+)_(?<cls>[^\W_]+)$/
|
4
|
+
|
3
5
|
def initialize(*parameters, &block)
|
4
6
|
super(*parameters)
|
5
7
|
self.class.plugs.each do |plg|
|
6
|
-
if
|
7
|
-
plg, sym, cls =
|
8
|
-
plg
|
8
|
+
if md = PLUG_PATTERN.match(plg)
|
9
|
+
plg, sym, cls = "#{plg}=".to_sym, "#{md[:sym]}!".to_sym, Object.const_get("Such::#{md[:cls]}")
|
10
|
+
# self.<plg> = Such::<cls>.new(self, :<sym>!, &block)
|
11
|
+
public_send plg, cls.new(self, sym, &block)
|
9
12
|
end
|
10
13
|
end
|
11
14
|
end
|
12
15
|
|
13
16
|
def message(*parameters)
|
14
|
-
self.class.plugs.each{|plg|
|
17
|
+
self.class.plugs.each{|plg| public_send(plg).message(*parameters) }
|
15
18
|
end
|
16
19
|
|
17
|
-
def method_missing(
|
18
|
-
super unless args.length==0 and
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
def method_missing(maybe,*args) # maybe a plug down the plugged things.
|
21
|
+
super unless args.length==0 and PLUG_PATTERN.match?(maybe)
|
22
|
+
self.class.plugs.each do |plug|
|
23
|
+
thing = public_send(plug)
|
24
|
+
if thing.is_a? Such::Part
|
25
|
+
if obj = thing.public_send(maybe)
|
26
|
+
return obj
|
27
|
+
end
|
24
28
|
end
|
25
29
|
end
|
26
|
-
return
|
30
|
+
return nil
|
27
31
|
end
|
28
32
|
end
|
29
33
|
end
|
data/lib/such/parts.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
module Such
|
2
2
|
module Parts
|
3
3
|
def self.make(part, thing, *plugs)
|
4
|
-
|
4
|
+
unless thing < Such::Thing and [part,*plugs].all?{_1.is_a? Symbol}
|
5
|
+
raise "Expected Such::Parts.make(Symbol part, Class thing < Such::Thing, *Symbol plugs)"
|
6
|
+
end
|
5
7
|
plugs.each do |plug|
|
6
8
|
if /^[^\W_]+_(?<klass>[^\W_]+)$/=~plug
|
7
9
|
next unless $VERBOSE
|
@@ -12,13 +14,9 @@ module Such
|
|
12
14
|
raise "Plugs must have the form key_class: #{plug}"
|
13
15
|
end
|
14
16
|
end
|
15
|
-
Such.subclass
|
16
|
-
|
17
|
-
|
18
|
-
[:#{plugs.join(', :')}]
|
19
|
-
end
|
20
|
-
include Such::Part
|
21
|
-
EOT
|
17
|
+
subklass = Such.subclass(part, thing, include: Such::Part, attr_accessor: plugs)
|
18
|
+
subklass.singleton_class.class_eval{ define_method(:plugs){plugs} }
|
19
|
+
return subklass
|
22
20
|
end
|
23
21
|
end
|
24
22
|
end
|
data/lib/such/such.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
module Such
|
2
|
-
def self.subclass(
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
CODE
|
2
|
+
def self.subclass(name, klass, **kw, &block)
|
3
|
+
subklass = const_set(name, Class.new(klass))
|
4
|
+
kw.each{|method, args| subklass.public_send(method, *args)}
|
5
|
+
subklass.class_eval(&block) if block
|
6
|
+
return subklass
|
8
7
|
end
|
9
8
|
end
|
data/lib/such/thing.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
module Such
|
2
2
|
module Thing
|
3
|
-
|
3
|
+
SIGNALS = ['clicked']
|
4
|
+
INTOS = [:set_submenu, :pack_start, :append, :add]
|
4
5
|
|
5
|
-
PARAMETERS
|
6
|
+
# PARAMETERS' pretense of being a Hash constant :P
|
7
|
+
@@PARAMETERS = {}
|
8
|
+
PARAMETERS = lambda{|k| @@PARAMETERS[k]}
|
9
|
+
def PARAMETERS.to_h = @@PARAMETERS
|
6
10
|
def self.configure(conf)
|
7
|
-
|
11
|
+
@@PARAMETERS = conf
|
8
12
|
end
|
9
13
|
|
10
14
|
def self.trace_method(obj, mthd, args)
|
@@ -16,8 +20,8 @@ module Such
|
|
16
20
|
end
|
17
21
|
|
18
22
|
def self.do_symbol(parameter, parameters)
|
19
|
-
if PARAMETERS.has_key?(parameter)
|
20
|
-
p = PARAMETERS[parameter]
|
23
|
+
if @@PARAMETERS.has_key?(parameter)
|
24
|
+
p = @@PARAMETERS[parameter]
|
21
25
|
(parameter[-1]=='!')? parameters.unshift(*p) : parameters.unshift(p)
|
22
26
|
else
|
23
27
|
if parameter[-1]=='!'
|
@@ -25,7 +29,7 @@ module Such
|
|
25
29
|
parameters.unshift(p.downcase.to_sym)
|
26
30
|
parameters.unshift(p.upcase.to_sym)
|
27
31
|
else
|
28
|
-
warn "Warning: Such::PARAMETERS[#{parameter}] not defined"
|
32
|
+
warn "Warning: Such::Thing::PARAMETERS[#{parameter}] not defined"
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
@@ -36,17 +40,17 @@ module Such
|
|
36
40
|
case parameter
|
37
41
|
when Symbol
|
38
42
|
# Symbols are expected to translate to something else.
|
39
|
-
Thing.do_symbol
|
43
|
+
Thing.do_symbol parameter, parameters
|
40
44
|
when Array
|
41
45
|
# Arrays are added to the Thing's arguments list.
|
42
|
-
arguments
|
46
|
+
arguments.concat parameter
|
43
47
|
when Hash
|
44
48
|
# Hashes are expected to be a symbol list of methods on Thing with respective arguments.
|
45
49
|
# It's possible to override a previously defined method with new arguments.
|
46
|
-
|
50
|
+
methods.merge! parameter
|
47
51
|
when String
|
48
52
|
# Typically a signal: Thing#signal_connect(signal){|*emits| block.call(*emits)}
|
49
|
-
signals.push
|
53
|
+
signals.push parameter
|
50
54
|
else
|
51
55
|
# Assume it's a container
|
52
56
|
container = parameter
|
@@ -57,18 +61,22 @@ module Such
|
|
57
61
|
end
|
58
62
|
|
59
63
|
def self.which_method(container, methods=INTOS)
|
60
|
-
methods.
|
61
|
-
raise "Don't know how to put into #{container.class}."
|
64
|
+
mthd = methods.detect{|m| container.respond_to?(m)}
|
65
|
+
raise "Don't know how to put into #{container.class}." if mthd.nil?
|
66
|
+
return mthd
|
62
67
|
end
|
63
68
|
|
64
69
|
def self.into(obj, container=nil, mthd=nil, *args)
|
65
70
|
if container
|
66
|
-
|
67
|
-
|
68
|
-
|
71
|
+
if mthd
|
72
|
+
unless mthd.class==Symbol and container.respond_to?(mthd)
|
73
|
+
raise "Need container & method. Got #{container.class}##{mthd}(#{obj.class}...)"
|
74
|
+
end
|
75
|
+
else
|
76
|
+
mthd=Thing.which_method(container)
|
69
77
|
end
|
70
78
|
Thing.trace_method(container, mthd, [obj.class,*args]) if $VERBOSE
|
71
|
-
container.
|
79
|
+
container.public_send(mthd, obj, *args)
|
72
80
|
else
|
73
81
|
warn "Warning: Container for #{self.class} not given."
|
74
82
|
end
|
@@ -81,17 +89,14 @@ module Such
|
|
81
89
|
m.call(*args)
|
82
90
|
rescue ArgumentError, TypeError
|
83
91
|
# Assume user meant to iterate. Note that the heuristic is not perfect.
|
84
|
-
$stderr.puts "# Iterated Method #{mthd}
|
92
|
+
$stderr.puts "# Iterated Method #{mthd}." if $VERBOSE
|
85
93
|
[*args].each{|arg| m.call(*arg)}
|
86
|
-
if $!.class == ArgumentError and not m.arity == 1
|
87
|
-
warn "Warning: Iterated method's arity not one."
|
88
|
-
end
|
89
94
|
end
|
90
95
|
end
|
91
96
|
|
92
97
|
def self.do_methods(obj, methods, container=nil)
|
93
98
|
# If user does not specify how to add to container, assume default way.
|
94
|
-
methods[:into]=Thing.which_method(container) if container and
|
99
|
+
methods[:into]=Thing.which_method(container) if container and not methods.has_key?(:into)
|
95
100
|
methods.each do |mthd, args|
|
96
101
|
(mthd==:into)? Thing.into(obj, container, *args) :
|
97
102
|
Thing.do_method(obj, mthd, *args)
|
@@ -99,16 +104,17 @@ module Such
|
|
99
104
|
end
|
100
105
|
|
101
106
|
def self.do_links(obj, signals, block)
|
107
|
+
return if signals.first==''
|
102
108
|
none = (signals.length==0)
|
103
109
|
if block
|
104
|
-
signals.push(
|
110
|
+
signals.push(*SIGNALS) if none
|
105
111
|
signals.each do |signal|
|
106
112
|
break if signal==''
|
107
113
|
begin
|
108
|
-
obj.signal_connect(signal){|*emits| block.call(*emits, signal)}
|
114
|
+
obj.signal_connect(signal){|*emits| block.call(*emits, signal)}
|
109
115
|
Thing.trace_signal(obj, signal) if $VERBOSE
|
110
116
|
rescue GLib::NoSignalError
|
111
|
-
warn "Warning: no
|
117
|
+
warn "Warning: no #{signal} signal for #{obj.class}"
|
112
118
|
end
|
113
119
|
end
|
114
120
|
elsif not none
|
data/lib/such/things.rb
CHANGED
@@ -1,11 +1,21 @@
|
|
1
1
|
module Such
|
2
2
|
module Things
|
3
|
-
def self.list(
|
4
|
-
ObjectSpace.each_object(Class).select{|
|
3
|
+
def self.list(superklass)
|
4
|
+
ObjectSpace.each_object(Class).select{|klass| klass < superklass}
|
5
5
|
end
|
6
6
|
|
7
|
-
def self.
|
8
|
-
|
7
|
+
def self.subclass(klass)
|
8
|
+
Such.subclass(klass.name.sub(/^.*::/,'').to_sym, klass, include: Such::Thing)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.in(superklass)
|
12
|
+
Things.list(superklass).each do |klass|
|
13
|
+
begin
|
14
|
+
Things.subclass(klass)
|
15
|
+
rescue
|
16
|
+
$stderr.puts "#{$!.class}:\t#{superklass}" if $VERBOSE
|
17
|
+
end
|
18
|
+
end
|
9
19
|
end
|
10
20
|
end
|
11
21
|
end
|
metadata
CHANGED
@@ -1,43 +1,38 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: such
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.210201
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- carlosjhr64
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-01 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
|
-
Wraps
|
14
|
+
Wraps widgets with an alternate constructor
|
15
15
|
which factors out the configuration and assembly procedures into metadata.
|
16
|
-
|
17
|
-
|
18
|
-
although currently only _Gtk3_ widgets is supported.
|
16
|
+
Can be used to wrap any class with the alternate constructor,
|
17
|
+
although targeted only Gtk3 widgets.
|
19
18
|
email: carlosjhr64@gmail.com
|
20
19
|
executables: []
|
21
20
|
extensions: []
|
22
|
-
extra_rdoc_files:
|
23
|
-
- README.rdoc
|
21
|
+
extra_rdoc_files: []
|
24
22
|
files:
|
25
|
-
- README.
|
23
|
+
- README.md
|
26
24
|
- lib/such.rb
|
27
25
|
- lib/such/part.rb
|
28
26
|
- lib/such/parts.rb
|
29
27
|
- lib/such/such.rb
|
30
28
|
- lib/such/thing.rb
|
31
29
|
- lib/such/things.rb
|
32
|
-
- lib/such/version.rb
|
33
30
|
homepage: https://github.com/carlosjhr64/such
|
34
31
|
licenses:
|
35
32
|
- MIT
|
36
33
|
metadata: {}
|
37
|
-
post_install_message:
|
38
|
-
rdoc_options:
|
39
|
-
- "--main"
|
40
|
-
- README.rdoc
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
41
36
|
require_paths:
|
42
37
|
- lib
|
43
38
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -51,12 +46,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
51
46
|
- !ruby/object:Gem::Version
|
52
47
|
version: '0'
|
53
48
|
requirements:
|
54
|
-
- 'ruby: ruby
|
55
|
-
|
56
|
-
|
57
|
-
signing_key:
|
49
|
+
- 'ruby: ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]'
|
50
|
+
rubygems_version: 3.2.3
|
51
|
+
signing_key:
|
58
52
|
specification_version: 4
|
59
|
-
summary: Wraps
|
60
|
-
|
53
|
+
summary: Wraps widgets with an alternate constructor which factors out the configuration
|
54
|
+
and assembly procedures into metadata. Can be used to wrap any class with the alternate
|
55
|
+
constructor, although targeted only Gtk3 widgets.
|
61
56
|
test_files: []
|
62
|
-
has_rdoc:
|
data/lib/such/version.rb
DELETED