sirens 0.0.1 → 0.1.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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/lib/components/{component_behaviour.rb → abstract_component.rb} +32 -47
  3. data/lib/components/component.rb +24 -9
  4. data/lib/components/containers/splitter.rb +12 -64
  5. data/lib/components/containers/stack.rb +1 -1
  6. data/lib/components/containers/tabs.rb +3 -3
  7. data/lib/components/containers/window.rb +4 -0
  8. data/lib/components/primitive_component.rb +4 -57
  9. data/lib/components/widgets/checkbox.rb +2 -2
  10. data/lib/components/widgets/input_text.rb +1 -1
  11. data/lib/components/widgets/tree_choice.rb +2 -9
  12. data/lib/{components/widgets → components_builder}/column_props.rb +14 -2
  13. data/lib/{layouts → components_builder}/columns_builder.rb +0 -0
  14. data/lib/components_builder/layout_builder.rb +215 -0
  15. data/lib/{layouts → components_builder}/radio_button_group_builder.rb +0 -0
  16. data/lib/sirens.rb +18 -11
  17. data/lib/sirens/browsers/module_browser.rb +4 -4
  18. data/lib/sirens/browsers/object_browser.rb +4 -1
  19. data/lib/sirens/components/ancestors_list.rb +4 -1
  20. data/lib/sirens/components/class_browser.rb +5 -4
  21. data/lib/sirens/components/constants_list.rb +1 -1
  22. data/lib/sirens/components/method_source_code.rb +1 -1
  23. data/lib/sirens/components/methods_list.rb +5 -2
  24. data/lib/sirens/components/modules_list.rb +4 -1
  25. data/lib/sirens/components/namespaces_list.rb +4 -1
  26. data/lib/sirens/models/constant_model.rb +2 -1
  27. data/lib/sirens/models/icons.rb +28 -0
  28. data/lib/sirens/models/method.rb +94 -0
  29. data/lib/sirens/models/method_model.rb +8 -83
  30. data/lib/sirens/models/module_browser_model.rb +85 -25
  31. data/lib/sirens/models/object_browser_model.rb +4 -0
  32. data/lib/views/{view.rb → abstract_view.rb} +16 -50
  33. data/lib/views/button_view.rb +1 -1
  34. data/lib/views/{check_button_view.rb → checkbox_view.rb} +1 -1
  35. data/lib/views/component_view.rb +12 -0
  36. data/lib/views/{entry_view.rb → input_text_view.rb} +1 -1
  37. data/lib/views/list_view.rb +33 -8
  38. data/lib/views/menu_view.rb +1 -1
  39. data/lib/views/radio_button_view.rb +1 -1
  40. data/lib/views/splitter_view.rb +101 -0
  41. data/lib/views/stack_view.rb +1 -1
  42. data/lib/views/{notebook_view.rb → tabs_view.rb} +1 -1
  43. data/lib/views/text_view.rb +1 -1
  44. data/lib/views/tree_view.rb +42 -20
  45. data/lib/views/widget_view.rb +96 -0
  46. data/lib/views/window_view.rb +1 -1
  47. data/resources/icons/array.png +0 -0
  48. data/resources/icons/class.png +0 -0
  49. data/resources/icons/false.png +0 -0
  50. data/resources/icons/hash.png +0 -0
  51. data/resources/icons/method.png +0 -0
  52. data/resources/icons/module.png +0 -0
  53. data/resources/icons/number.png +0 -0
  54. data/resources/icons/object.png +0 -0
  55. data/resources/icons/private-method.png +0 -0
  56. data/resources/icons/protected-method.png +0 -0
  57. data/resources/icons/public-method.png +0 -0
  58. data/resources/icons/string.png +0 -0
  59. data/resources/icons/true.png +0 -0
  60. metadata +46 -15
  61. data/lib/layouts/layout_builder.rb +0 -203
  62. data/lib/views/paned_view.rb +0 -26
@@ -94,6 +94,10 @@ module Sirens
94
94
 
95
95
  attr_reader :key, :value
96
96
 
97
+ def icon()
98
+ Icons.icon_for(@value)
99
+ end
100
+
97
101
  def display_string()
98
102
  return value_display_string if key.nil?
99
103
 
@@ -3,15 +3,15 @@ require 'set'
3
3
  module Sirens
4
4
  ##
5
5
  # A View is the library binding to a GUI interface handle.
6
- # It is not a Component but is wrapped by a PrimitiveComponent.
6
+ # It is not a Component but is wrapped by a Component.
7
7
  # a View takes care of handling the internals of the GUI objects such as handles, events, default initialization,
8
8
  # etc.
9
9
  #
10
- # By separating the View from the PrimitiveComponent that wraps it makes the PrimitiveComponents responsibilities
10
+ # By separating the View from the Component that wraps it makes the Component responsibilities
11
11
  # more consistent with regular Components and it makes it easier to switch between GUI libraries
12
12
  # (say, from Gtk to Qt).
13
13
  #
14
- class View
14
+ class AbstractView
15
15
 
16
16
  # Class methods
17
17
 
@@ -37,37 +37,21 @@ module Sirens
37
37
  # Initializes this View handles
38
38
  #
39
39
  def initialize()
40
- @event_handles = Hash[]
40
+ super()
41
41
 
42
- @main_handle = nil
43
-
44
- initialize_handles
45
-
46
- subscribe_to_ui_events
42
+ @child_views = []
43
+ @attributes = Hash[]
47
44
  end
48
45
 
49
- ## Instantiates this view handles.
50
- # A View usually has a single handle to the GUI library, but in same cases it may have more than one.
51
- # For instance when adding a Scroll decorator to the actual widget.
52
- #
53
- def initialize_handles()
54
- raise RuntimeError.new("Subclass #{self.class.name} must implement the method ::initialize_handles().")
55
- end
46
+ # Accessing
56
47
 
57
- ##
58
- # Subscribes this View to the events/signals emitted by the GUI handle(s) of interest.
59
- # When an event/signal is received calls the proper event_handler provided by the PrimitiveComponent,
60
- # if one was given.
61
- #
62
- # This mechanism of event handler callbacks is more simple and lightweight than making this View to announce
63
- # events using the Observer pattern, and since there is only one PrimitiveComponent wrapping each View
64
- # using the Observer pattern would be unnecessary complex.
65
- #
66
- def subscribe_to_ui_events()
67
- raise RuntimeError.new("Subclass #{self.class.name} must implement the method ::subscribe_to_ui_events().")
48
+ def attribute_at(key)
49
+ @attributes[key]
68
50
  end
69
51
 
70
- # Accessing
52
+ def set_attribute(key, value)
53
+ @attributes[key] = value
54
+ end
71
55
 
72
56
  ##
73
57
  # Returns the main handle of this View.
@@ -75,7 +59,7 @@ module Sirens
75
59
  # Also, it is the handle that receives the style props and events by default.
76
60
  #
77
61
  def main_handle()
78
- @main_handle
62
+ raise RuntimeError.new("Subclass #{self.class.name} must implement the method ::initialize_handles().")
79
63
  end
80
64
 
81
65
  # Styling
@@ -87,26 +71,6 @@ module Sirens
87
71
  self.class.accepted_styles
88
72
  end
89
73
 
90
- ##
91
- # Applies each prop in props to the actual GUI object.
92
- #
93
- def apply_props(props)
94
- accepted_styles = self.accepted_styles
95
-
96
- props.each_pair { |prop, value|
97
- apply_prop(prop, value) if accepted_styles.include?(prop)
98
- }
99
- end
100
-
101
- ##
102
- # Apply the prop to the actual GUI object.
103
- #
104
- def apply_prop(prop, value)
105
- setter = prop.to_s + '='
106
-
107
- send(setter, value)
108
- end
109
-
110
74
  # Styles
111
75
 
112
76
  def width=(value)
@@ -176,13 +140,15 @@ module Sirens
176
140
  # Adds a child_view.
177
141
  #
178
142
  def add_view(child_view)
179
- main_handle.add(child_view.main_handle)
143
+ @child_views << child_view
180
144
  end
181
145
 
182
146
  ##
183
147
  # Removes a child view.
184
148
  #
185
149
  def remove_view(child_view)
150
+ @child_views.delete(child_view)
151
+
186
152
  main_handle.remove(child_view.main_handle)
187
153
  end
188
154
 
@@ -1,5 +1,5 @@
1
1
  module Sirens
2
- class ButtonView < View
2
+ class ButtonView < WidgetView
3
3
 
4
4
  # Class methods
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Sirens
2
- class CheckButtonView < View
2
+ class CheckboxView < WidgetView
3
3
 
4
4
  # Class methods
5
5
 
@@ -0,0 +1,12 @@
1
+ module Sirens
2
+ class ComponentView < AbstractView
3
+
4
+ def main_child_view()
5
+ @child_views.first
6
+ end
7
+
8
+ def main_handle()
9
+ main_child_view.main_handle
10
+ end
11
+ end
12
+ end
@@ -1,5 +1,5 @@
1
1
  module Sirens
2
- class EntryView < View
2
+ class InputTextView < WidgetView
3
3
 
4
4
  # Initializing
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Sirens
2
- class ListView < View
2
+ class ListView < WidgetView
3
3
 
4
4
  # Class methods
5
5
 
@@ -45,12 +45,16 @@ module Sirens
45
45
 
46
46
  # Building columns
47
47
 
48
+ def list_store_type_for(column_props)
49
+ return GdkPixbuf::Pixbuf if column_props.has_image_block?
50
+
51
+ String
52
+ end
53
+
48
54
  def define_columns(columns_props_array)
49
55
  @columns_props = columns_props_array
50
56
 
51
- list_store_types = @columns_props
52
- .collect { |each_column_props| each_column_props.fetch(:type, :text) }
53
- .collect { |type| String }
57
+ list_store_types = @columns_props.collect { |type| list_store_type_for(type) }
54
58
 
55
59
  tree_view.set_model(Gtk::ListStore.new(*list_store_types))
56
60
 
@@ -60,12 +64,21 @@ module Sirens
60
64
  end
61
65
 
62
66
  def add_column_with_props(props)
63
- column_type = props.fetch(:type, :text)
64
67
  column_index = tree_view.columns.size
65
68
 
66
- renderer = Gtk::CellRendererText.new
69
+ col = nil
70
+
71
+ column_label = props[:label]
67
72
 
68
- col = Gtk::TreeViewColumn.new(props[:label], renderer, column_type => column_index)
73
+ if props.has_image_block?
74
+ renderer = Gtk::CellRendererPixbuf.new
75
+
76
+ col = Gtk::TreeViewColumn.new(column_label, renderer, pixbuf: column_index)
77
+ else
78
+ renderer = Gtk::CellRendererText.new
79
+
80
+ col = Gtk::TreeViewColumn.new(column_label, renderer, text: column_index)
81
+ end
69
82
 
70
83
  tree_view.append_column(col)
71
84
  end
@@ -189,10 +202,22 @@ module Sirens
189
202
 
190
203
  def set_item_column_values(item:, iter:)
191
204
  @columns_props.each_with_index { |column, column_index|
192
- iter[column_index] = column.display_text_of(item)
205
+ colum_value = display_data_of(item, column, column_index)
206
+
207
+ iter.set_value(column_index, colum_value)
193
208
  }
194
209
  end
195
210
 
211
+ def display_data_of(item, column, column_index)
212
+ if column.has_image_block?
213
+ image_file = column.display_image_of(item).to_s
214
+
215
+ return GdkPixbuf::Pixbuf.new(file: image_file, width: 16, height: 16)
216
+ end
217
+
218
+ column.display_text_of(item)
219
+ end
220
+
196
221
  # Querying
197
222
 
198
223
  def selection_indices()
@@ -1,5 +1,5 @@
1
1
  module Sirens
2
- class MenuView < View
2
+ class MenuView < WidgetView
3
3
 
4
4
  # Initializing
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Sirens
2
- class RadioButtonView < View
2
+ class RadioButtonView < WidgetView
3
3
 
4
4
  # Class methods
5
5
 
@@ -0,0 +1,101 @@
1
+ module Sirens
2
+ class SplitterView < WidgetView
3
+
4
+ # Initializing
5
+
6
+ def initialize(orientation:)
7
+ @orientation = orientation
8
+
9
+ super()
10
+ end
11
+
12
+ def initialize_handles()
13
+ @main_handle = Gtk::Paned.new(@orientation)
14
+ end
15
+
16
+ def subscribe_to_ui_events()
17
+ main_handle.signal_connect('size-allocate') { |widget, rectangle|
18
+ on_size_allocation(width: rectangle.width, height: rectangle.height)
19
+ }
20
+ end
21
+
22
+ ##
23
+ # Adds the child_component to this component.
24
+ #
25
+ def add_view(child_view)
26
+ @child_views << child_view
27
+
28
+ if @child_views.size <= 2
29
+ main_handle.add(child_view.main_handle)
30
+ else
31
+ paned = Gtk::Paned.new(@orientation)
32
+
33
+ last_child_handle = main_handle.children.last
34
+
35
+ main_handle.remove(last_child_handle)
36
+
37
+ paned.add(last_child_handle)
38
+ paned.add(child_view.main_handle)
39
+
40
+ main_handle.add(paned)
41
+ end
42
+ end
43
+
44
+ def is_horizontal()
45
+ @orientation === :horizontal
46
+ end
47
+
48
+ def on_size_allocation(width:, height:)
49
+ return if @is_first_size_allocation === false
50
+
51
+ @is_first_size_allocation = false
52
+
53
+ remaining_proportion = 1.0
54
+
55
+ current_handle = main_handle
56
+
57
+ @child_views.each_with_index do |child_view, index|
58
+
59
+ return if index === @child_views.size
60
+
61
+ return if current_handle.children.empty?
62
+
63
+ proportion = child_view.attribute_at(:splitter_proportion)
64
+
65
+ remaining_proportion = remaining_proportion - proportion
66
+
67
+ children = current_handle.children
68
+
69
+ first_child = children[0]
70
+
71
+ set_proportional_size(
72
+ view_handle: first_child,
73
+ width: width,
74
+ height: height,
75
+ proportion: proportion
76
+ )
77
+
78
+ return if children.size < 2
79
+
80
+ second_child = children[1]
81
+
82
+ set_proportional_size(
83
+ view_handle: second_child,
84
+ width: width,
85
+ height: height,
86
+ proportion: remaining_proportion
87
+ )
88
+
89
+ current_handle = second_child
90
+ end
91
+ end
92
+
93
+ def set_proportional_size(view_handle:, width:, height:, proportion:)
94
+ if is_horizontal
95
+ view_handle.set_size_request(width * proportion, height)
96
+ else
97
+ view_handle.set_size_request(width, height * proportion)
98
+ end
99
+ end
100
+ end
101
+ end
@@ -1,5 +1,5 @@
1
1
  module Sirens
2
- class StackView < View
2
+ class StackView < WidgetView
3
3
 
4
4
  # Initializing
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Sirens
2
- class NotebookView < View
2
+ class TabsView < WidgetView
3
3
 
4
4
  # Initializing
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Sirens
2
- class TextView < View
2
+ class TextView < WidgetView
3
3
  # Class methods
4
4
 
5
5
  class << self
@@ -1,16 +1,9 @@
1
1
  module Sirens
2
- class TreeView < View
2
+ class TreeView < WidgetView
3
3
 
4
4
  # Class methods
5
5
 
6
6
  class << self
7
- ##
8
- # Answer the laze children placeholder.
9
- #
10
- def placeholder()
11
- @placeholder ||= '__placeholder__'
12
- end
13
-
14
7
  ##
15
8
  # Answer the styles accepted by this view.
16
9
  #
@@ -60,14 +53,18 @@ module Sirens
60
53
 
61
54
  # Building columns
62
55
 
56
+ def tree_store_type_for(column_props)
57
+ return GdkPixbuf::Pixbuf if column_props.has_image_block?
58
+
59
+ String
60
+ end
61
+
63
62
  def define_columns(columns_props_array)
64
63
  @columns_props = columns_props_array
65
64
 
66
- tree_store_types = @columns_props
67
- .collect { |each_column_props| each_column_props.fetch(:type, :text) }
68
- .collect { |type| String }
65
+ list_store_types = @columns_props.collect { |type| tree_store_type_for(type) }
69
66
 
70
- tree_view.set_model(Gtk::TreeStore.new(*tree_store_types))
67
+ tree_view.set_model(Gtk::TreeStore.new(*list_store_types))
71
68
 
72
69
  @columns_props.each do |each_column_props|
73
70
  add_column_with_props(each_column_props)
@@ -75,12 +72,21 @@ module Sirens
75
72
  end
76
73
 
77
74
  def add_column_with_props(props)
78
- column_type = props.fetch(:type, :text)
79
75
  column_index = tree_view.columns.size
80
76
 
81
- renderer = Gtk::CellRendererText.new
77
+ col = nil
78
+
79
+ column_label = props[:label]
80
+
81
+ if props.has_image_block?
82
+ renderer = Gtk::CellRendererPixbuf.new
83
+
84
+ col = Gtk::TreeViewColumn.new(column_label, renderer, pixbuf: column_index)
85
+ else
86
+ renderer = Gtk::CellRendererText.new
82
87
 
83
- col = Gtk::TreeViewColumn.new(props[:label], renderer, column_type => column_index)
88
+ col = Gtk::TreeViewColumn.new(column_label, renderer, text: column_index)
89
+ end
84
90
 
85
91
  tree_view.append_column(col)
86
92
  end
@@ -193,7 +199,7 @@ module Sirens
193
199
  def on_row_expanded(iter:, tree_path:)
194
200
  child_iter = iter.first_child
195
201
 
196
- return if tree_store.get_value(child_iter, 0) != self.class.placeholder
202
+ return if ! tree_store.get_value(child_iter, 0).nil?
197
203
 
198
204
  indices_path = tree_path.indices
199
205
 
@@ -212,6 +218,12 @@ module Sirens
212
218
  tree_store.clear
213
219
  end
214
220
 
221
+ def set_roots(root_items)
222
+ clear_items
223
+
224
+ add_items(parent_iter: nil, items: root_items, index: 0)
225
+ end
226
+
215
227
  # Adding
216
228
 
217
229
  def add_items(items:, parent_iter:, index:)
@@ -234,9 +246,7 @@ module Sirens
234
246
  children_count = get_children_at(path: indices_path).size
235
247
 
236
248
  if children_count > 0
237
- placeholder = tree_store.insert(iter, 0)
238
-
239
- placeholder[0] = self.class.placeholder
249
+ tree_store.insert(iter, 0)
240
250
  end
241
251
  end
242
252
 
@@ -270,10 +280,22 @@ module Sirens
270
280
 
271
281
  def set_item_column_values(item:, iter:)
272
282
  @columns_props.each_with_index { |column, column_index|
273
- iter[column_index] = column.display_text_of(item)
283
+ colum_value = display_data_of(item, column, column_index)
284
+
285
+ iter.set_value(column_index, colum_value)
274
286
  }
275
287
  end
276
288
 
289
+ def display_data_of(item, column, column_index)
290
+ if column.has_image_block?
291
+ image_file = column.display_image_of(item).to_s
292
+
293
+ return GdkPixbuf::Pixbuf.new(file: image_file, width: 16, height: 16)
294
+ end
295
+
296
+ column.display_text_of(item)
297
+ end
298
+
277
299
  # Querying
278
300
 
279
301
  def selection_indices()