sirens 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/lib/components/component.rb +46 -0
- data/lib/components/component_behaviour.rb +160 -0
- data/lib/components/containers/splitter.rb +98 -0
- data/lib/components/containers/stack.rb +42 -0
- data/lib/components/containers/tabs.rb +24 -0
- data/lib/components/containers/window.rb +20 -0
- data/lib/components/primitive_component.rb +155 -0
- data/lib/components/widgets/button.rb +16 -0
- data/lib/components/widgets/checkbox.rb +39 -0
- data/lib/components/widgets/column_props.rb +23 -0
- data/lib/components/widgets/input_text.rb +27 -0
- data/lib/components/widgets/list.rb +68 -0
- data/lib/components/widgets/list_choice.rb +89 -0
- data/lib/components/widgets/radio_button.rb +33 -0
- data/lib/components/widgets/text.rb +31 -0
- data/lib/components/widgets/tree_choice.rb +82 -0
- data/lib/layouts/columns_builder.rb +63 -0
- data/lib/layouts/layout_builder.rb +203 -0
- data/lib/layouts/radio_button_group_builder.rb +28 -0
- data/lib/models/choice_model.rb +41 -0
- data/lib/models/list_model.rb +173 -0
- data/lib/models/tree_choice_model.rb +102 -0
- data/lib/models/value_model.rb +56 -0
- data/lib/models/virtual_tree_model.rb +150 -0
- data/lib/sirens/browsers/module_browser.rb +67 -0
- data/lib/sirens/browsers/object_browser.rb +103 -0
- data/lib/sirens/components/ancestors_list.rb +22 -0
- data/lib/sirens/components/class_browser.rb +38 -0
- data/lib/sirens/components/constants_list.rb +22 -0
- data/lib/sirens/components/method_source_code.rb +22 -0
- data/lib/sirens/components/methods_list.rb +63 -0
- data/lib/sirens/components/modules_list.rb +23 -0
- data/lib/sirens/components/namespaces_list.rb +21 -0
- data/lib/sirens/models/constant_model.rb +21 -0
- data/lib/sirens/models/method_model.rb +111 -0
- data/lib/sirens/models/module_browser_model.rb +225 -0
- data/lib/sirens/models/object_browser_model.rb +125 -0
- data/lib/sirens.rb +90 -0
- data/lib/views/button_view.rb +56 -0
- data/lib/views/check_button_view.rb +65 -0
- data/lib/views/entry_view.rb +25 -0
- data/lib/views/list_view.rb +230 -0
- data/lib/views/menu_view.rb +46 -0
- data/lib/views/notebook_view.rb +27 -0
- data/lib/views/paned_view.rb +26 -0
- data/lib/views/radio_button_view.rb +67 -0
- data/lib/views/stack_view.rb +26 -0
- data/lib/views/text_view.rb +112 -0
- data/lib/views/tree_view.rb +314 -0
- data/lib/views/view.rb +206 -0
- data/lib/views/window_view.rb +51 -0
- metadata +110 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Sirens
|
|
2
|
+
|
|
3
|
+
class ConstantsList < Sirens::Component
|
|
4
|
+
|
|
5
|
+
# Building
|
|
6
|
+
|
|
7
|
+
def renderWith(layout)
|
|
8
|
+
layout.render do |component|
|
|
9
|
+
choices_list do
|
|
10
|
+
model component.model
|
|
11
|
+
|
|
12
|
+
styles(
|
|
13
|
+
show_headers: false
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
column label: 'Constants',
|
|
17
|
+
get_text_block: proc{ |constant| constant.display_string }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Sirens
|
|
2
|
+
class MethodSourceCode < Sirens::Component
|
|
3
|
+
|
|
4
|
+
# Building
|
|
5
|
+
|
|
6
|
+
def renderWith(layout)
|
|
7
|
+
layout.render do |component|
|
|
8
|
+
vertical_stack do
|
|
9
|
+
text do
|
|
10
|
+
model component.model.source_code
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
input_text do
|
|
14
|
+
model component.model.location
|
|
15
|
+
|
|
16
|
+
styles stack_expand: false
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module Sirens
|
|
2
|
+
|
|
3
|
+
class MethodsList < Sirens::Component
|
|
4
|
+
|
|
5
|
+
# Building
|
|
6
|
+
|
|
7
|
+
def renderWith(layout)
|
|
8
|
+
layout.render do |component|
|
|
9
|
+
vertical_stack do
|
|
10
|
+
|
|
11
|
+
horizontal_stack do
|
|
12
|
+
styles(
|
|
13
|
+
height: 30,
|
|
14
|
+
stack_expand: false
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
radio_buttons_group do
|
|
18
|
+
radio_button label: 'instance',
|
|
19
|
+
id: :instance,
|
|
20
|
+
model: component.props[:instance_or_class_methods_chooser],
|
|
21
|
+
stack_expand: false
|
|
22
|
+
|
|
23
|
+
radio_button label: 'class',
|
|
24
|
+
id: :class,
|
|
25
|
+
model: component.props[:instance_or_class_methods_chooser],
|
|
26
|
+
stack_expand: false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
checkbox label: 'include inherit',
|
|
30
|
+
model: component.props[:show_inherit_methods]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
choices_list do
|
|
34
|
+
model component.model
|
|
35
|
+
|
|
36
|
+
styles id: :methods_list,
|
|
37
|
+
show_headers: false
|
|
38
|
+
|
|
39
|
+
column label: 'Methods',
|
|
40
|
+
get_text_block: proc{ |method| method }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
horizontal_stack do
|
|
44
|
+
styles(
|
|
45
|
+
height: 30,
|
|
46
|
+
stack_expand: false
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
checkbox label: 'public',
|
|
50
|
+
model: component.props[:show_public_methods]
|
|
51
|
+
|
|
52
|
+
checkbox label: 'protected',
|
|
53
|
+
model: component.props[:show_protected_methods]
|
|
54
|
+
|
|
55
|
+
checkbox label: 'private',
|
|
56
|
+
model: component.props[:show_private_methods]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Sirens
|
|
2
|
+
class ModulesList < Sirens::Component
|
|
3
|
+
|
|
4
|
+
# Building
|
|
5
|
+
|
|
6
|
+
def renderWith(layout)
|
|
7
|
+
layout.render do |component|
|
|
8
|
+
|
|
9
|
+
choices_list do
|
|
10
|
+
model component.model
|
|
11
|
+
|
|
12
|
+
styles(
|
|
13
|
+
show_headers: true
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
column label: 'Namespace modules',
|
|
17
|
+
get_text_block: proc{ |a_module| a_module.name }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Sirens
|
|
2
|
+
class NamespacesList < Sirens::Component
|
|
3
|
+
|
|
4
|
+
# Building
|
|
5
|
+
|
|
6
|
+
def renderWith(layout)
|
|
7
|
+
layout.render do |component|
|
|
8
|
+
|
|
9
|
+
choices_tree do
|
|
10
|
+
model component.model
|
|
11
|
+
|
|
12
|
+
styles show_headers: true
|
|
13
|
+
|
|
14
|
+
column label: 'Namespaces',
|
|
15
|
+
get_text_block: proc{ |a_module| a_module.name }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Sirens
|
|
2
|
+
class ConstantModel
|
|
3
|
+
|
|
4
|
+
# Initializing
|
|
5
|
+
|
|
6
|
+
def initialize(name:, value:)
|
|
7
|
+
super()
|
|
8
|
+
|
|
9
|
+
@name = name
|
|
10
|
+
@value = value
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_reader :name, :value
|
|
14
|
+
|
|
15
|
+
def display_string()
|
|
16
|
+
value_print_string = value.inspect
|
|
17
|
+
|
|
18
|
+
"#{name} = #{value_print_string}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
require 'stringio'
|
|
2
|
+
|
|
3
|
+
module Sirens
|
|
4
|
+
class MethodModel
|
|
5
|
+
|
|
6
|
+
# Initializing
|
|
7
|
+
|
|
8
|
+
def initialize()
|
|
9
|
+
super()
|
|
10
|
+
|
|
11
|
+
@method_name = ValueModel.new
|
|
12
|
+
@location = ValueModel.new
|
|
13
|
+
@source_code = ValueModel.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
attr_reader :method_name,
|
|
17
|
+
:location,
|
|
18
|
+
:source_code
|
|
19
|
+
|
|
20
|
+
def set_method(method)
|
|
21
|
+
if method.nil?
|
|
22
|
+
method_name.set_value(nil)
|
|
23
|
+
location.set_value(nil)
|
|
24
|
+
source_code.set_value(nil)
|
|
25
|
+
|
|
26
|
+
return
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
method_name.set_value(method.name)
|
|
30
|
+
|
|
31
|
+
method_filename, method_line_number = method.source_location
|
|
32
|
+
|
|
33
|
+
location.set_value("#{method_filename}:#{method_line_number}")
|
|
34
|
+
|
|
35
|
+
source_code.set_value(
|
|
36
|
+
get_source_code_of(method: method, filename: method_filename, line_number: method_line_number)
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def get_source_code_of(method:, filename:, line_number:)
|
|
41
|
+
return 'Native method' if filename.nil? || ! File.exists?(filename)
|
|
42
|
+
|
|
43
|
+
source_code = StringIO.new
|
|
44
|
+
|
|
45
|
+
lines = File.read(filename).lines
|
|
46
|
+
|
|
47
|
+
method_comment = ''
|
|
48
|
+
comment_line = line_number - 1
|
|
49
|
+
while line_number >= 0
|
|
50
|
+
line = lines[comment_line - 1]
|
|
51
|
+
|
|
52
|
+
break if ! /^\s*#/.match(line)
|
|
53
|
+
|
|
54
|
+
method_comment = line + method_comment
|
|
55
|
+
|
|
56
|
+
comment_line -= 1
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
source_code.write(method_comment)
|
|
60
|
+
|
|
61
|
+
tail = lines[line_number -1 .. -1].join
|
|
62
|
+
|
|
63
|
+
stream = StringIO.new(tail)
|
|
64
|
+
|
|
65
|
+
counter = 0
|
|
66
|
+
|
|
67
|
+
keywords = ['module', 'class', 'def', 'if', 'while', 'do', 'begin']
|
|
68
|
+
|
|
69
|
+
while !stream.eof?
|
|
70
|
+
|
|
71
|
+
while !stream.eof? && (c = stream.getc) == ' '
|
|
72
|
+
source_code.write(' ')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
stream.ungetc(c)
|
|
76
|
+
|
|
77
|
+
token = stream.gets(' ')
|
|
78
|
+
|
|
79
|
+
source_code.write(token)
|
|
80
|
+
|
|
81
|
+
token = token.strip
|
|
82
|
+
|
|
83
|
+
if token == 'end'
|
|
84
|
+
counter -= 1
|
|
85
|
+
elsif keywords.include?(token)
|
|
86
|
+
counter += 1
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
break if counter == 0
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
fix_indentation(source_code.string)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def fix_indentation(source_code)
|
|
96
|
+
lines = source_code.lines
|
|
97
|
+
|
|
98
|
+
indentation = 0
|
|
99
|
+
|
|
100
|
+
/^(\s*).*$/.match(lines.first) do |matches|
|
|
101
|
+
indentation = matches[1].size
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
lines = lines.collect { |line|
|
|
105
|
+
line.gsub!(/^\s{#{indentation}}/, '')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
lines.join
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
module Sirens
|
|
2
|
+
class ModuleBrowserModel
|
|
3
|
+
|
|
4
|
+
# Initializing
|
|
5
|
+
|
|
6
|
+
def initialize()
|
|
7
|
+
super()
|
|
8
|
+
|
|
9
|
+
@namespaces = TreeChoiceModel.new(
|
|
10
|
+
selection: nil,
|
|
11
|
+
roots: get_root_namespaces,
|
|
12
|
+
get_children_block: proc { |namespace| get_modules_in(namespace) }
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
@modules = ChoiceModel.new(selection: nil, choices: [])
|
|
16
|
+
@module_ancestors = ChoiceModel.new(selection: nil, choices: [])
|
|
17
|
+
@methods = ChoiceModel.new(selection: nil, choices: [])
|
|
18
|
+
@constants = ChoiceModel.new(selection: nil, choices: [])
|
|
19
|
+
|
|
20
|
+
@instance_or_class_methods_chooser = ChoiceModel.new(selection: :instance, choices: [:instance, :class])
|
|
21
|
+
@show_inherit_methods = ValueModel.on(false)
|
|
22
|
+
|
|
23
|
+
@show_public_methods = ValueModel.on(true)
|
|
24
|
+
@show_protected_methods = ValueModel.on(false)
|
|
25
|
+
@show_private_methods = ValueModel.on(false)
|
|
26
|
+
|
|
27
|
+
@method_source_code = MethodModel.new
|
|
28
|
+
|
|
29
|
+
connect_models
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
attr_reader :namespaces,
|
|
33
|
+
:modules,
|
|
34
|
+
:module_ancestors,
|
|
35
|
+
:methods,
|
|
36
|
+
:constants,
|
|
37
|
+
:instance_or_class_methods_chooser,
|
|
38
|
+
:show_public_methods,
|
|
39
|
+
:show_protected_methods,
|
|
40
|
+
:show_private_methods,
|
|
41
|
+
:show_inherit_methods,
|
|
42
|
+
:method_source_code
|
|
43
|
+
|
|
44
|
+
def connect_models()
|
|
45
|
+
@namespaces.selection.add_observer(self, :on_namespace_changed)
|
|
46
|
+
@modules.selection.add_observer(self, :on_class_changed)
|
|
47
|
+
@module_ancestors.selection.add_observer(self, :on_module_changed)
|
|
48
|
+
@methods.selection.add_observer(self, :on_method_changed)
|
|
49
|
+
|
|
50
|
+
@instance_or_class_methods_chooser.selection.add_observer(self, :on_methods_filter_changed)
|
|
51
|
+
@show_inherit_methods.add_observer(self, :on_methods_filter_changed)
|
|
52
|
+
|
|
53
|
+
@show_public_methods.add_observer(self, :on_methods_filter_changed)
|
|
54
|
+
@show_protected_methods.add_observer(self, :on_methods_filter_changed)
|
|
55
|
+
@show_private_methods.add_observer(self, :on_methods_filter_changed)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Actions
|
|
59
|
+
|
|
60
|
+
def actual_namespace_hierarchy(a_module)
|
|
61
|
+
namespaces = a_module.name.split('::')
|
|
62
|
+
|
|
63
|
+
namespaces.pop if a_module.kind_of?(Class)
|
|
64
|
+
|
|
65
|
+
hierarchy = [Object]
|
|
66
|
+
|
|
67
|
+
namespaces.each { |module_name|
|
|
68
|
+
hierarchy << hierarchy.last.const_get(module_name)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
hierarchy
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def select_namespace(namespace)
|
|
75
|
+
hierarchy = actual_namespace_hierarchy(namespace)
|
|
76
|
+
|
|
77
|
+
@namespaces.set_selection(hierarchy)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def select_class(a_class)
|
|
81
|
+
hierarchy = actual_namespace_hierarchy(a_class)
|
|
82
|
+
|
|
83
|
+
@namespaces.set_selection(hierarchy)
|
|
84
|
+
@modules.set_selection(a_class)
|
|
85
|
+
@module_ancestors.set_selection(a_class)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Events
|
|
89
|
+
|
|
90
|
+
def on_namespace_changed(announcement)
|
|
91
|
+
namespace_hierarchy = announcement.new_value
|
|
92
|
+
|
|
93
|
+
modules.set_choices(get_modules_in(namespace_hierarchy.last))
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def on_class_changed(announcement)
|
|
97
|
+
a_class = announcement.new_value
|
|
98
|
+
|
|
99
|
+
ancestors = get_all_ancestors_of(a_class)
|
|
100
|
+
|
|
101
|
+
module_ancestors.set_choices(ancestors)
|
|
102
|
+
|
|
103
|
+
module_ancestors.set_selection(ancestors.last) unless ancestors.empty?
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def on_module_changed(announcement)
|
|
107
|
+
on_methods_filter_changed()
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def on_methods_filter_changed(announcement = nil)
|
|
111
|
+
a_module = module_ancestors.selection.value
|
|
112
|
+
|
|
113
|
+
methods.set_choices(get_all_methods_in(a_module))
|
|
114
|
+
constants.set_choices(get_all_constants_in(a_module))
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def on_method_changed(announcement)
|
|
118
|
+
method_name = announcement.new_value
|
|
119
|
+
|
|
120
|
+
if method_name.nil?
|
|
121
|
+
method_source_code.set_method(nil)
|
|
122
|
+
return
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
a_module = module_ancestors.selection.value
|
|
126
|
+
|
|
127
|
+
if showing_instance_methods?
|
|
128
|
+
method = a_module.instance_method(method_name)
|
|
129
|
+
else
|
|
130
|
+
method = a_module.method(method_name)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
method_source_code.set_method(method)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Calculated
|
|
137
|
+
|
|
138
|
+
##
|
|
139
|
+
# Answers all the namespaces in the running environment
|
|
140
|
+
#
|
|
141
|
+
def get_root_namespaces()
|
|
142
|
+
return [Object]
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
##
|
|
146
|
+
# Answers child modules of a namespace
|
|
147
|
+
#
|
|
148
|
+
def get_modules_in(a_module)
|
|
149
|
+
return [] if a_module.nil?
|
|
150
|
+
|
|
151
|
+
modules = a_module.constants(false)
|
|
152
|
+
.collect { |constant| a_module.const_get(constant) }
|
|
153
|
+
.select { |constant| constant.kind_of?(Module) }
|
|
154
|
+
.sort_by { |a_module| a_module.name }
|
|
155
|
+
|
|
156
|
+
modules.prepend(a_module)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
##
|
|
160
|
+
# Answers all the modules in the given class
|
|
161
|
+
#
|
|
162
|
+
def get_all_ancestors_of(a_class)
|
|
163
|
+
return [] if a_class.nil?
|
|
164
|
+
|
|
165
|
+
a_class.ancestors.reverse
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
##
|
|
169
|
+
# Answers all the methods in the given class
|
|
170
|
+
#
|
|
171
|
+
def get_all_methods_in(a_module)
|
|
172
|
+
return [] if a_module.nil?
|
|
173
|
+
|
|
174
|
+
methods = []
|
|
175
|
+
|
|
176
|
+
inherit = show_inherit_methods.value
|
|
177
|
+
|
|
178
|
+
if showing_instance_methods?
|
|
179
|
+
methods.concat(a_module.private_instance_methods(inherit)) if showing_private_methods?
|
|
180
|
+
methods.concat(a_module.protected_instance_methods(inherit)) if showing_protected_methods?
|
|
181
|
+
methods.concat(a_module.public_instance_methods(inherit)) if showing_public_methods?
|
|
182
|
+
else
|
|
183
|
+
methods.concat(a_module.private_methods(inherit)) if showing_private_methods?
|
|
184
|
+
methods.concat(a_module.protected_methods(inherit)) if showing_protected_methods?
|
|
185
|
+
methods.concat(a_module.public_methods(inherit)) if showing_public_methods?
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
methods.sort
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
##
|
|
192
|
+
# Answers all the constants in the given class
|
|
193
|
+
#
|
|
194
|
+
def get_all_constants_in(a_module)
|
|
195
|
+
return [] if a_module.nil?
|
|
196
|
+
|
|
197
|
+
inherit = show_inherit_methods.value
|
|
198
|
+
|
|
199
|
+
a_module.constants(inherit)
|
|
200
|
+
.collect { |constant_name|
|
|
201
|
+
ConstantModel.new(name: constant_name, value: a_module.const_get(constant_name))
|
|
202
|
+
}
|
|
203
|
+
.select { |constant_model| ! constant_model.value.kind_of?(Module) }
|
|
204
|
+
.sort_by { |constant_model| constant_model.name }
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Asking
|
|
208
|
+
|
|
209
|
+
def showing_instance_methods?()
|
|
210
|
+
instance_or_class_methods_chooser.selection.value == :instance
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def showing_private_methods?()
|
|
214
|
+
show_private_methods.value
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def showing_protected_methods?()
|
|
218
|
+
show_protected_methods.value
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def showing_public_methods?()
|
|
222
|
+
show_public_methods.value
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
module Sirens
|
|
2
|
+
class ObjectBrowserModel
|
|
3
|
+
|
|
4
|
+
# Initializing
|
|
5
|
+
|
|
6
|
+
def initialize()
|
|
7
|
+
super()
|
|
8
|
+
|
|
9
|
+
@object = ValueModel.on(nil)
|
|
10
|
+
|
|
11
|
+
@object_instance_variables = TreeChoiceModel.new(
|
|
12
|
+
selection: object,
|
|
13
|
+
roots: [InstanceVariable.new(key: nil, value: object)],
|
|
14
|
+
get_children_block: proc { |instance_variable|
|
|
15
|
+
get_child_instance_variables_of(instance_variable.value)
|
|
16
|
+
}
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
@text = ValueModel.on('')
|
|
20
|
+
|
|
21
|
+
connect_models
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def connect_models()
|
|
25
|
+
@object.add_observer(self, :on_object_changed)
|
|
26
|
+
@object_instance_variables.selection.add_observer(self, :on_instance_variable_changed)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Accessors
|
|
30
|
+
|
|
31
|
+
attr_reader :object,
|
|
32
|
+
:object_instance_variables,
|
|
33
|
+
:text
|
|
34
|
+
|
|
35
|
+
def selected_inst_var_value()
|
|
36
|
+
tree_selection = object_instance_variables.selection.value.last
|
|
37
|
+
|
|
38
|
+
tree_selection.nil? ? nil : tree_selection.value
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Events
|
|
42
|
+
|
|
43
|
+
def on_object_changed(announcement)
|
|
44
|
+
new_object = announcement.new_value
|
|
45
|
+
|
|
46
|
+
@object_instance_variables.set_tree_roots(
|
|
47
|
+
[InstanceVariable.new(key: nil, value: new_object)]
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def on_instance_variable_changed(announcement)
|
|
52
|
+
instance_variable = announcement.new_value.last
|
|
53
|
+
|
|
54
|
+
value = instance_variable.nil? ? '' : instance_variable.value.inspect
|
|
55
|
+
|
|
56
|
+
@text.set_value(value)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
##
|
|
60
|
+
# Get the child instance variables of an object.
|
|
61
|
+
#
|
|
62
|
+
def get_child_instance_variables_of(object)
|
|
63
|
+
if object.kind_of?(Array)
|
|
64
|
+
i = -1
|
|
65
|
+
object.collect{ |value|
|
|
66
|
+
i += 1
|
|
67
|
+
InstanceVariable.new(
|
|
68
|
+
key: i,
|
|
69
|
+
value: value
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
elsif object.kind_of?(Hash)
|
|
73
|
+
object.collect{ |key, value|
|
|
74
|
+
InstanceVariable.new(
|
|
75
|
+
key: "[#{key.inspect}]",
|
|
76
|
+
value: value
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
else
|
|
80
|
+
object.instance_variables.collect{ |inst_var_name|
|
|
81
|
+
InstanceVariable.new(
|
|
82
|
+
key: inst_var_name,
|
|
83
|
+
value: object.instance_variable_get(inst_var_name)
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class InstanceVariable
|
|
90
|
+
def initialize(key:, value:)
|
|
91
|
+
@key = key
|
|
92
|
+
@value = value
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
attr_reader :key, :value
|
|
96
|
+
|
|
97
|
+
def display_string()
|
|
98
|
+
return value_display_string if key.nil?
|
|
99
|
+
|
|
100
|
+
"#{key_display_string} = #{value_display_string}"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def key_display_string()
|
|
104
|
+
if key.kind_of?(Numeric)
|
|
105
|
+
"[#{key}]"
|
|
106
|
+
else
|
|
107
|
+
key.to_s
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def value_display_string()
|
|
112
|
+
return "an Array(#{value.size})" if value.kind_of?(Array)
|
|
113
|
+
return 'a Hash' if value.kind_of?(Hash)
|
|
114
|
+
|
|
115
|
+
string = value.to_s
|
|
116
|
+
|
|
117
|
+
if string.start_with?('#<')
|
|
118
|
+
"a " + value.class.name
|
|
119
|
+
else
|
|
120
|
+
value.inspect
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|