glimmer-dsl-libui 0.7.0 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a247176e108fe8ba8dd7016b69bb0c6413e3b6c00c78aa068c28e70c11ec5330
4
- data.tar.gz: 94aa3f51dd0576748ea09a9899d0f26f230457a315dce3a55ef5c4aa22ce4434
3
+ metadata.gz: 7aedcfa3ba9a8d44ce0df9ee4f684535d3492c858ca0171f4181a80ed4772899
4
+ data.tar.gz: 21f8b0577f27116216821c2bcbe3fd458261a5f8c957c5c0a2aa4683d370310d
5
5
  SHA512:
6
- metadata.gz: 7a2e9ef07ac5b946e871577be49c34e0b8e38dbc506d0787178d1f5c01d1fe3294c1656bcb0ede0e6b16323760d1f47688ee023251079b95bdfa55a4e805f936
7
- data.tar.gz: 1d335aaa18baad73376426d7c8cdd4669a14e961b91f9c7cdf58f9427afde8cb1ab100b436fae24f72e9249e41f23aae8accb55679cfa23692b7ab62725d6a4a
6
+ metadata.gz: fc1404d69d320e772a50506bfde13942cc7f981fb932c1c0999340c1c048ce64935eeac799d6af3b258a1a18ccb3472b9915814da72a96f5fb4d5f0b9af13fb6
7
+ data.tar.gz: eac5a371a0d685fab5cd397a43f7b25c333d855b5972c898dd0794c4001f61c08440d5da4f80911017155f0c051cea79391eefa5e603e13fb5292db12f4d2689
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.7.2
4
+
5
+ - `table` `on_selection_changed` listener arguments now provide extra arguments of `selection`, `added_selection`, `removed_selection` after first argument (`table`)
6
+ - Update `examples/basic_table_selection.rb` to use new `on_selection_changed` arguments of `selection`, `added_selection`, and `removed_selection`
7
+
8
+ ## 0.7.1
9
+
10
+ - `table` column `on_clicked` listener (can be nested under `text_column`, `text_color_column`, `button_column`, `checkbox_column`, `checkbox_text_color_column`, `image_column`, `image_text_color_column`, `image_text_column`, and `progress_bar_column`)
11
+ - `table` column `sort_indicator` property (can be `nil`, `:ascending` [aliases: `:asc`, `:a`], `:descending` [aliases: `:desc`, `:d`])
12
+ - `table` column `set_sort_indicator` alias for `sort_indicator=` can accept an option of `reset_columns: false` to avoid resetting sort indicator of other columns when setting sort indicator on a specific column
13
+ - `table` `header_visible` property (Boolean)
14
+ - Fix issue with `table` `selection_mode` getting set to `nil` if not specified
15
+
3
16
  ## 0.7.0
4
17
 
5
18
  - Upgrade to libui v0.1.2.pre (including newer libui-ng with table selection API)
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for LibUI 0.7.0
1
+ # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for LibUI 0.7.2
2
2
  ## Prerequisite-Free Ruby Desktop Development GUI Library
3
3
  ### The Quickest Way From Zero To GUI
4
4
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-libui.svg)](http://badge.fury.io/rb/glimmer-dsl-libui)
@@ -544,7 +544,7 @@ gem install glimmer-dsl-libui
544
544
  Or install via Bundler `Gemfile`:
545
545
 
546
546
  ```ruby
547
- gem 'glimmer-dsl-libui', '~> 0.7.0'
547
+ gem 'glimmer-dsl-libui', '~> 0.7.2'
548
548
  ```
549
549
 
550
550
  Test that installation worked by running the [Meta-Example](#examples):
@@ -736,9 +736,9 @@ Keyword(Args) | Properties | Listeners
736
736
  `string(string = '')` | `font`, `color` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color), `background` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color), `underline`, `underline_color` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color), `open_type_features`, `string` (`String`) | None
737
737
  `tab` | `margined` (Boolean), `num_pages` (`Integer`) | None
738
738
  `tab_item(name as String)` | `index` [read-only] (`Integer`), `margined` (Boolean), `name` [read-only] (`String`) | None
739
- `table` | `cell_rows` (`Array` (rows) of `Arrays` (row columns) of cell values (e.g. `String` values for `text_column` cells or `Array` of `image`/`String` for `image_text_column`)), `editable` as Boolean, `selection_mode` (`:zero_or_many` , `:none` , `:zero_or_one` , or `:one`), `selection` (`Integer` for row index or `Array` of multiple row indexes) | `on_changed {|row, type, row_data| ...}`, `on_edited {|row, row_data| ...}`, `on_row_clicked {|table, row| }`, `on_row_double_clicked {|table, row| }`, and `on_selection_changed {|table| }`
739
+ `table` | `cell_rows` (`Array` (rows) of `Arrays` (row columns) of cell values (e.g. `String` values for `text_column` cells or `Array` of `image`/`String` for `image_text_column`)), `editable` as Boolean, `selection_mode` (`:zero_or_many` , `:none` , `:zero_or_one` , or `:one`), `selection` (`Integer` for row index or `Array` of multiple row indexes), `header_visible` (Boolean) | `on_changed {|row, type, row_data| ...}`, `on_edited {|row, row_data| ...}`, `on_row_clicked {|table, row| }`, `on_row_double_clicked {|table, row| }`, and `on_selection_changed {|table, selection, added_selection, removed_selection| }`
740
740
  `text(x = 0 as Numeric, y = 0 as Numeric, width = area_width as Numeric)` | `align`, `default_font` | None
741
- `text_column(name as String)` | `editable` (Boolean) | None
741
+ `text_column(name as String)` | `editable` (Boolean), `sort_indicator` (`:ascending` [alias: `:asc`, `:a`], `:descending` [alias: `:desc`, `:d`], or `nil`) | `on_clicked {|tc, column_index| }`
742
742
  `text_color_column(name as String)` | `editable` (Boolean) | None
743
743
  `time_picker` | `time` (`Hash` of keys: `sec` as `Integer`, `min` as `Integer`, `hour` as `Integer`) | `on_changed`
744
744
  `vertical_box` | `padded` (Boolean) | None
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.7.2
@@ -1520,6 +1520,12 @@ Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/
1520
1520
  ruby -r glimmer-dsl-libui -e "require 'examples/basic_table_selection'"
1521
1521
  ```
1522
1522
 
1523
+ ![glimmer-dsl-libui-mac-basic-table-selection-one.png](/images/glimmer-dsl-libui-mac-basic-table-selection-one.png)
1524
+ ![glimmer-dsl-libui-mac-basic-table-selection-zero-or-one.png](/images/glimmer-dsl-libui-mac-basic-table-selection-zero-or-one.png)
1525
+ ![glimmer-dsl-libui-mac-basic-table-selection-zero-or-many.png](/images/glimmer-dsl-libui-mac-basic-table-selection-zero-or-many.png)
1526
+ ![glimmer-dsl-libui-mac-basic-table-selection-none.png](/images/glimmer-dsl-libui-mac-basic-table-selection-none.png)
1527
+ ![glimmer-dsl-libui-mac-basic-table-selection-header-not-visible.png](/images/glimmer-dsl-libui-mac-basic-table-selection-header-not-visible.png)
1528
+
1523
1529
  ## Basic Area
1524
1530
 
1525
1531
  [examples/basic_area.rb](/examples/basic_area.rb)
@@ -4,13 +4,17 @@ class BasicTableSelection
4
4
  include Glimmer::LibUI::Application
5
5
 
6
6
  before_body do
7
- @data = [
7
+ data = [
8
8
  %w[cat meow],
9
9
  %w[dog woof],
10
10
  %w[chicken cock-a-doodle-doo],
11
11
  %w[horse neigh],
12
12
  %w[cow moo]
13
13
  ]
14
+ @one_table_data = data.dup
15
+ @zero_or_one_table_data = data.dup
16
+ @zero_or_many_table_data = data.dup
17
+ @none_table_data = data.dup
14
18
  end
15
19
 
16
20
  body {
@@ -21,8 +25,8 @@ class BasicTableSelection
21
25
  vertical_box {
22
26
  stretchy false
23
27
 
24
- @one_radio_buttons = radio_buttons {
25
- items @data.size.times.map { |row| "Row #{row} Selection" }
28
+ @one_table_selection_radio_buttons = radio_buttons {
29
+ items @one_table_data.size.times.map { |row| "Row #{row} Selection" }
26
30
 
27
31
  on_selected do |rb|
28
32
  @one_table.selection = [rb.selected]
@@ -30,13 +34,34 @@ class BasicTableSelection
30
34
  }
31
35
  }
32
36
 
37
+ button('Toggle Table Header Visibility') {
38
+ stretchy false
39
+
40
+ on_clicked do
41
+ @one_table.header_visible = !@one_table.header_visible
42
+ end
43
+ }
44
+
33
45
  @one_table = table {
34
- text_column('Animal')
35
- text_column('Description')
46
+ text_column('Animal') {
47
+ # sort_indicator :descending # (optional) can be :ascending, :descending, or nil (default)
48
+
49
+ on_clicked do |tc, column|
50
+ sort_one_table_column(tc, column)
51
+ end
52
+ }
53
+ text_column('Description') {
54
+ # sort_indicator :descending # (optional) can be :ascending, :descending, or nil (default)
55
+
56
+ on_clicked do |tc, column|
57
+ sort_one_table_column(tc, column)
58
+ end
59
+ }
36
60
 
37
- cell_rows @data
38
- selection_mode :one # other values are :zero_or_many , :zero_or_one, :none
61
+ cell_rows @one_table_data
62
+ selection_mode :one # other values are :zero_or_many , :zero_or_one, :none (default is :zero_or_one if not specified)
39
63
  selection 2 # initial selection row index (could be nil too or just left off, defaulting to 0)
64
+ # header_visible true # default
40
65
 
41
66
  on_row_clicked do |t, row|
42
67
  puts "Row Clicked: #{row}"
@@ -46,11 +71,13 @@ class BasicTableSelection
46
71
  puts "Row Double Clicked: #{row}"
47
72
  end
48
73
 
49
- on_selection_changed do |t|
74
+ on_selection_changed do |t, selection, added_selection, removed_selection|
50
75
  # selection is an array or nil if selection mode is zero_or_many
51
76
  # otherwise, selection is a single index integer or nil when not selected
52
- puts "Selection Changed: #{t.selection.inspect}"
53
- @one_radio_buttons.selected = t.selection
77
+ puts "Selection Changed: #{selection.inspect}"
78
+ puts "Added Selection: #{added_selection.inspect}"
79
+ puts "Removed Selection: #{removed_selection.inspect}"
80
+ @one_table_selection_radio_buttons.selected = selection
54
81
  end
55
82
  }
56
83
  }
@@ -61,8 +88,8 @@ class BasicTableSelection
61
88
  vertical_box {
62
89
  stretchy false
63
90
 
64
- @zero_or_one_radio_buttons = radio_buttons {
65
- items @data.size.times.map { |row| "Row #{row} Selection" }
91
+ @zero_or_one_table_selection_radio_buttons = radio_buttons {
92
+ items @zero_or_one_table_data.size.times.map { |row| "Row #{row} Selection" }
66
93
 
67
94
  on_selected do |rb|
68
95
  @zero_or_one_table.selection = [rb.selected]
@@ -70,13 +97,34 @@ class BasicTableSelection
70
97
  }
71
98
  }
72
99
 
100
+ button('Toggle Table Header Visibility') {
101
+ stretchy false
102
+
103
+ on_clicked do
104
+ @zero_or_one_table.header_visible = !@zero_or_one_table.header_visible
105
+ end
106
+ }
107
+
73
108
  @zero_or_one_table = table {
74
- text_column('Animal')
75
- text_column('Description')
109
+ text_column('Animal') {
110
+ # sort_indicator :descending # (optional) can be :ascending, :descending, or nil (default)
111
+
112
+ on_clicked do |tc, column|
113
+ sort_zero_or_one_table_column(tc, column)
114
+ end
115
+ }
116
+ text_column('Description') {
117
+ # sort_indicator :descending # (optional) can be :ascending, :descending, or nil (default)
118
+
119
+ on_clicked do |tc, column|
120
+ sort_zero_or_one_table_column(tc, column)
121
+ end
122
+ }
76
123
 
77
- cell_rows @data
78
- selection_mode :zero_or_one # other values are :zero_or_many , :one, :none
124
+ cell_rows @zero_or_one_table_data
125
+ selection_mode :zero_or_one # other values are :zero_or_many , :one, :none (default is :zero_or_one if not specified)
79
126
  # selection 0 # initial selection row index (could be nil too or just left off)
127
+ # header_visible true # default
80
128
 
81
129
  on_row_clicked do |t, row|
82
130
  puts "Row Clicked: #{row}"
@@ -86,11 +134,13 @@ class BasicTableSelection
86
134
  puts "Row Double Clicked: #{row}"
87
135
  end
88
136
 
89
- on_selection_changed do |t|
137
+ on_selection_changed do |t, selection, added_selection, removed_selection|
90
138
  # selection is an array or nil if selection mode is zero_or_many
91
139
  # otherwise, selection is a single index integer or nil when not selected
92
- puts "Selection Changed: #{t.selection.inspect}"
93
- @zero_or_one_radio_buttons.selected = t.selection
140
+ puts "Selection Changed: #{selection.inspect}"
141
+ puts "Added Selection: #{added_selection.inspect}"
142
+ puts "Removed Selection: #{removed_selection.inspect}"
143
+ @zero_or_one_table_selection_radio_buttons.selected = selection
94
144
  end
95
145
  }
96
146
  }
@@ -101,7 +151,7 @@ class BasicTableSelection
101
151
  vertical_box {
102
152
  stretchy false
103
153
 
104
- @zero_or_many_checkboxes = @data.size.times.map do |row|
154
+ @zero_or_many_table_selection_checkboxes = @zero_or_many_table_data.size.times.map do |row|
105
155
  checkbox("Row #{row} Selection") {
106
156
  on_toggled do |c|
107
157
  table_selection = @zero_or_many_table.selection.to_a
@@ -116,13 +166,34 @@ class BasicTableSelection
116
166
  end
117
167
  }
118
168
 
169
+ button('Toggle Table Header Visibility') {
170
+ stretchy false
171
+
172
+ on_clicked do
173
+ @zero_or_many_table.header_visible = !@zero_or_many_table.header_visible
174
+ end
175
+ }
176
+
119
177
  @zero_or_many_table = table {
120
- text_column('Animal')
121
- text_column('Description')
178
+ text_column('Animal') {
179
+ # sort_indicator :descending # (optional) can be :ascending, :descending, or nil (default)
180
+
181
+ on_clicked do |tc, column|
182
+ sort_zero_or_many_table_column(tc, column)
183
+ end
184
+ }
185
+ text_column('Description') {
186
+ # sort_indicator :descending # (optional) can be :ascending, :descending, or nil (default)
187
+
188
+ on_clicked do |tc, column|
189
+ sort_zero_or_many_table_column(tc, column)
190
+ end
191
+ }
122
192
 
123
- cell_rows @data
124
- selection_mode :zero_or_many # other values are :none , :zero_or_one , and :one
193
+ cell_rows @zero_or_many_table_data
194
+ selection_mode :zero_or_many # other values are :none , :zero_or_one , and :one (default is :zero_or_one if not specified)
125
195
  selection 0, 2, 4 # initial selection row indexes (could be empty array too or just left off)
196
+ # header_visible true # default
126
197
 
127
198
  on_row_clicked do |t, row|
128
199
  puts "Row Clicked: #{row}"
@@ -132,13 +203,17 @@ class BasicTableSelection
132
203
  puts "Row Double Clicked: #{row}"
133
204
  end
134
205
 
135
- on_selection_changed do |t|
206
+ on_selection_changed do |t, selection, added_selection, removed_selection|
136
207
  # selection is an array or nil if selection mode is zero_or_many
137
208
  # otherwise, selection is a single index integer or nil when not selected
138
- puts "Selection Changed: #{t.selection.inspect}"
139
- @zero_or_many_checkboxes.each { |cb| cb.checked = false }
140
- t.selection&.each do |selected_row|
141
- @zero_or_many_checkboxes[selected_row].checked = true
209
+ puts "Selection Changed: #{selection.inspect}"
210
+ puts "Added Selection: #{added_selection.inspect}"
211
+ puts "Removed Selection: #{removed_selection.inspect}"
212
+ removed_selection&.each do |selected_row|
213
+ @zero_or_many_table_selection_checkboxes[selected_row].checked = false
214
+ end
215
+ added_selection&.each do |selected_row|
216
+ @zero_or_many_table_selection_checkboxes[selected_row].checked = true
142
217
  end
143
218
  end
144
219
  }
@@ -147,12 +222,33 @@ class BasicTableSelection
147
222
 
148
223
  tab_item('None') {
149
224
  vertical_box {
225
+ button('Toggle Table Header Visibility') {
226
+ stretchy false
227
+
228
+ on_clicked do
229
+ @none_table.header_visible = !@none_table.header_visible
230
+ end
231
+ }
232
+
150
233
  @none_table = table {
151
- text_column('Animal')
152
- text_column('Description')
234
+ text_column('Animal') {
235
+ # sort_indicator :descending # (optional) can be :ascending, :descending, or nil (default)
236
+
237
+ on_clicked do |tc, column|
238
+ sort_none_table_column(tc, column)
239
+ end
240
+ }
241
+ text_column('Description') {
242
+ # sort_indicator :descending # (optional) can be :ascending, :descending, or nil (default)
243
+
244
+ on_clicked do |tc, column|
245
+ sort_none_table_column(tc, column)
246
+ end
247
+ }
153
248
 
154
- cell_rows @data
155
- selection_mode :none # other values are :zero_or_many , :zero_or_one, :one
249
+ cell_rows @none_table_data
250
+ selection_mode :none # other values are :zero_or_many , :zero_or_one, :one (default is :zero_or_one if not specified)
251
+ # header_visible true # default
156
252
 
157
253
  on_row_clicked do |t, row|
158
254
  puts "Row Clicked: #{row}"
@@ -161,12 +257,6 @@ class BasicTableSelection
161
257
  on_row_double_clicked do |t, row|
162
258
  puts "Row Double Clicked: #{row}"
163
259
  end
164
-
165
- on_selection_changed do |t|
166
- # selection is an array or nil if selection mode is zero_or_many
167
- # otherwise, selection is a single index integer or nil when not selected
168
- puts "Selection Changed: #{t.selection.inspect}"
169
- end
170
260
  }
171
261
  }
172
262
  }
@@ -174,6 +264,40 @@ class BasicTableSelection
174
264
  }
175
265
  }
176
266
  }
267
+
268
+ def sort_one_table_column(tc, column)
269
+ puts "Clicked column #{column}: #{tc.name}"
270
+ selected_row = @one_table.selection && @one_table_data[@one_table.selection]
271
+ tc.toggle_sort_indicator
272
+ @one_table_data.sort_by! { |row_data| row_data[column] }
273
+ @one_table_data.reverse! if tc.sort_indicator == :descending
274
+ @one_table.selection = @one_table_data.index(selected_row)
275
+ end
276
+
277
+ def sort_zero_or_one_table_column(tc, column)
278
+ puts "Clicked column #{column}: #{tc.name}"
279
+ selected_row = @zero_or_one_table.selection && @zero_or_one_table_data[@zero_or_one_table.selection]
280
+ tc.toggle_sort_indicator
281
+ @zero_or_one_table_data.sort_by! { |row_data| row_data[column] }
282
+ @zero_or_one_table_data.reverse! if tc.sort_indicator == :descending
283
+ @zero_or_one_table.selection = @zero_or_one_table_data.index(selected_row)
284
+ end
285
+
286
+ def sort_zero_or_many_table_column(tc, column)
287
+ puts "Clicked column #{column}: #{tc.name}"
288
+ selected_rows = @zero_or_many_table.selection&.map { |row| @zero_or_many_table_data[row] }
289
+ tc.toggle_sort_indicator
290
+ @zero_or_many_table_data.sort_by! { |row_data| row_data[column] }
291
+ @zero_or_many_table_data.reverse! if tc.sort_indicator == :descending
292
+ @zero_or_many_table.selection = selected_rows&.map {|row_data| @zero_or_many_table_data.index(row_data) }
293
+ end
294
+
295
+ def sort_none_table_column(tc, column)
296
+ puts "Clicked column #{column}: #{tc.name}"
297
+ tc.toggle_sort_indicator
298
+ @none_table_data.sort_by! { |row_data| row_data[column] }
299
+ @none_table_data.reverse! if tc.sort_indicator == :descending
300
+ end
177
301
  end
178
302
 
179
303
  BasicTableSelection.launch
Binary file
@@ -52,7 +52,58 @@ module Glimmer
52
52
 
53
53
  # actual index within table columns (disregarding extra fillings that account for DualColumn instances)
54
54
  def index
55
- @parent_proxy.columns.select {|c| c.is_a?(Column)}.index(self)
55
+ @parent_proxy.column_proxies.index(self)
56
+ end
57
+
58
+ def other_columns
59
+ @parent_proxy.column_proxies.reject {|c| c == self}
60
+ end
61
+
62
+ def sort_indicator
63
+ return @sort_indicator if !@content_added
64
+
65
+ result = ::LibUI.table_header_sort_indicator(@parent_proxy.libui, index)
66
+ LibUI.integer_to_column_sort_indicator(result)
67
+ end
68
+
69
+ def sort_indicator=(*args)
70
+ options = args.last.is_a?(Hash) ? args.pop : {reset_columns: true}
71
+ value = args.first
72
+ @sort_indicator = value
73
+ return @sort_indicator if !@content_added
74
+
75
+ other_columns.each { |c| c.set_sort_indicator(nil, reset_columns: false) } if options[:reset_columns]
76
+ value = LibUI.column_sort_indicator_to_integer(value)
77
+ ::LibUI.table_header_set_sort_indicator(@parent_proxy.libui, index, value)
78
+ end
79
+ alias set_sort_indicator sort_indicator=
80
+
81
+ def toggle_sort_indicator(value = nil)
82
+ if value.nil?
83
+ self.sort_indicator = self.sort_indicator != :ascending ? :ascending : :descending
84
+ else
85
+ self.sort_indicator = value
86
+ end
87
+ end
88
+
89
+ def can_handle_listener?(listener_name)
90
+ listener_name == 'on_clicked'
91
+ end
92
+
93
+ def handle_listener(listener_name, &listener)
94
+ column_listeners_for(listener_name) << listener
95
+ end
96
+
97
+ def column_listeners
98
+ @column_listeners ||= {}
99
+ end
100
+
101
+ def column_listeners_for(listener_name)
102
+ column_listeners[listener_name] ||= []
103
+ end
104
+
105
+ def configure_sort_indicator
106
+ set_sort_indicator(@sort_indicator, reset_columns: false)
56
107
  end
57
108
  end
58
109
  end
@@ -61,8 +61,11 @@ module Glimmer
61
61
  super
62
62
  # TODO consider automatically detecting what properties/listeners accumulated dynamically to avoid hardcoding code below
63
63
  register_listeners
64
+ register_column_listeners
64
65
  configure_selection_mode
65
66
  configure_selection
67
+ configure_header_visible
68
+ configure_column_sort_indicators
66
69
  end
67
70
 
68
71
  def post_initialize_child(child)
@@ -142,6 +145,7 @@ module Glimmer
142
145
  end
143
146
  end
144
147
  alias selection_mode= selection_mode
148
+ alias set_selection_mode selection_mode
145
149
 
146
150
  def selection
147
151
  return @selection if !@content_added
@@ -160,17 +164,35 @@ module Glimmer
160
164
  value = value.first if value.size == 1
161
165
  @selection = value
162
166
  return @selection if !@content_added
163
- return if value.nil?
167
+ return if @selection.nil?
164
168
 
165
169
  ts = ::LibUI::FFI::TableSelection.malloc
166
- ts.NumRows = value.is_a?(Array) ? value.size : 1
167
- ts.Rows = [value].flatten.pack('i*')
170
+ ts.NumRows = @selection.is_a?(Array) ? @selection.size : 1
171
+ ts.Rows = [@selection].flatten.pack('i*')
168
172
  super(ts)
169
173
  # TODO figure out why ensure block is not working (perhaps libui auto-frees that resource upon setting selection)
170
174
  # Delete following code if not needed.
171
175
  # ensure
172
176
  # ::LibUI.free_table_selection(ts)
173
177
  end
178
+ alias set_selection selection=
179
+
180
+ def header_visible
181
+ return @header_visible if !@content_added
182
+
183
+ result = ::LibUI.table_header_visible(@libui)
184
+ LibUI.integer_to_boolean(result)
185
+ end
186
+
187
+ def header_visible=(value)
188
+ @header_visible = value
189
+ return @header_visible if !@content_added
190
+ return if value.nil?
191
+
192
+ value = LibUI.boolean_to_integer(value)
193
+ ::LibUI.table_header_set_visible(@libui, value)
194
+ end
195
+ alias set_header_visible header_visible=
174
196
 
175
197
  def column_attributes
176
198
  @column_attributes ||= columns.select {|column| column.is_a?(Column)}.map(&:name).map(&:underscore)
@@ -221,10 +243,23 @@ module Glimmer
221
243
  compound_columns.index(compound_column)
222
244
  end
223
245
 
246
+ def column_proxies
247
+ @columns&.select {|c| c.is_a?(Column)}
248
+ end
249
+
224
250
  def handle_listener(listener_name, &listener)
225
- # if content has been added, then you can register listeners immediately (without accumulation
226
- if CUSTOM_LISTENER_NAMES.include?(listener_name.to_s) || @content_added
227
- super
251
+ # if content has been added, then you can register listeners immediately (without accumulation)
252
+ if CUSTOM_LISTENER_NAMES.include?(listener_name) || @content_added
253
+ actual_listener = listener
254
+ case listener_name
255
+ when 'on_selection_changed'
256
+ actual_listener = Proc.new do |myself, *args|
257
+ added_selection = selection.is_a?(Array) ? (selection - @old_selection.to_a) : selection
258
+ removed_selection = selection.is_a?(Array) ? (@old_selection.to_a - selection) : @old_selection
259
+ listener.call(myself, selection, added_selection, removed_selection)
260
+ end
261
+ end
262
+ super(listener_name, &actual_listener)
228
263
  else
229
264
  # if content is not added yet, then accumulate listeners to register later when table content is closed
230
265
  @table_listeners ||= []
@@ -577,15 +612,45 @@ module Glimmer
577
612
  @table_listeners&.each do |listener_name, listener|
578
613
  handle_listener(listener_name, &listener)
579
614
  end
615
+ handle_listener('on_selection_changed') do |myself, selection, added_selection, removed_selection|
616
+ @old_selection = selection
617
+ end
618
+ end
619
+
620
+ def register_column_listeners
621
+ # register accumulated column listeners after table content is closed
622
+ return if @columns.nil? || @columns.empty?
623
+ if @columns.any? {|column| column.is_a?(Column) && !column.column_listeners_for('on_clicked').empty? }
624
+ ::LibUI.table_header_on_clicked(@libui) do |_, column_index|
625
+ actual_columns = @columns.select {|column| column.is_a?(Column)}
626
+ column = actual_columns[column_index]
627
+ if column.is_a?(Column)
628
+ column_listeners = column.column_listeners_for('on_clicked')
629
+ if !column_listeners.empty?
630
+ column_listeners.each do |column_listener|
631
+ column_listener.call(column, column_index)
632
+ end
633
+ end
634
+ end
635
+ end
636
+ end
580
637
  end
581
638
 
582
639
  def configure_selection_mode
583
- send_to_libui('selection_mode=', @selection_mode)
640
+ send_to_libui('selection_mode=', @selection_mode) if @selection_mode
584
641
  end
585
642
 
586
643
  def configure_selection
587
644
  self.selection = @selection
588
645
  end
646
+
647
+ def configure_header_visible
648
+ self.header_visible = @header_visible
649
+ end
650
+
651
+ def configure_column_sort_indicators
652
+ column_proxies.each {|c| c.configure_sort_indicator }
653
+ end
589
654
  end
590
655
  end
591
656
  end
@@ -167,6 +167,7 @@ module Glimmer
167
167
  end
168
168
 
169
169
  def handle_listener(listener_name, &listener)
170
+ # replace first listener argument (control libui pointer) with actual Ruby libui object
170
171
  safe_listener = Proc.new { |*args| listener.call(self, *args[1..-1]) }
171
172
  if ::LibUI.respond_to?("#{libui_api_keyword}_#{listener_name}")
172
173
  if listeners[listener_name].nil?
data/lib/glimmer/libui.rb CHANGED
@@ -35,6 +35,33 @@ module Glimmer
35
35
  bool.nil? ? (allow_nil ? nil : 0) : (allow_integer && bool.is_a?(Integer) ? bool : (bool.is_a?(TrueClass) || bool.is_a?(FalseClass) ? (bool == true ? 1 : 0) : (allow_nil ? nil : 0)))
36
36
  end
37
37
 
38
+ def column_sort_indicator_to_integer(value)
39
+ return value if value.is_a?(Integer)
40
+
41
+ if value.nil?
42
+ 0
43
+ elsif 'ascending'.start_with?(value.to_s)
44
+ 1
45
+ elsif 'descending'.start_with?(value.to_s)
46
+ 2
47
+ else
48
+ 0
49
+ end
50
+ end
51
+
52
+ def integer_to_column_sort_indicator(value)
53
+ return value if value.is_a?(String) || value.is_a?(Symbol)
54
+
55
+ case value
56
+ when 1
57
+ :ascending
58
+ when 2
59
+ :descending
60
+ else
61
+ nil
62
+ end
63
+ end
64
+
38
65
  def degrees_to_radians(degrees)
39
66
  ((Math::PI * 2.0) / 360.00) * degrees.to_f
40
67
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-libui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-11 00:00:00.000000000 Z
11
+ date: 2023-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer