rgw 0.5.0
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/AUTHORS +1 -0
- data/COPYING +502 -0
- data/README.md +22 -0
- data/lib/data/pixmaps/lock16.png +0 -0
- data/lib/data/pixmaps/unlock16.png +0 -0
- data/lib/rgw/big-list.rb +316 -0
- data/lib/rgw/property-editor.rb +278 -0
- data/lib/rgw/radio-revealer.rb +109 -0
- data/lib/rgw/restricted-entry.rb +129 -0
- data/lib/rgw/synced-spin-button.rb +78 -0
- data/lib/rgw/types.rb +129 -0
- data/lib/rgw/version.rb +3 -0
- metadata +84 -0
data/README.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
## RGW Ruby Gtk Widgets
|
2
|
+
|
3
|
+
Rgw is a collection of [Gtk+](http://www.gtk.org/) widgets implemented in and for the
|
4
|
+
[ruby](https://www.ruby-lang.org) programming language.
|
5
|
+
|
6
|
+
**requirements**
|
7
|
+
ruby >= 2.0.0
|
8
|
+
ruby-gtk >= 2.2.0
|
9
|
+
gtk >= 3.10
|
10
|
+
|
11
|
+
**how to install**
|
12
|
+
ruby setup.rb config
|
13
|
+
ruby setup.rb setup
|
14
|
+
*get root / superuser*
|
15
|
+
ruby setup.rb install
|
16
|
+
|
17
|
+
At this point, the widgets are working, but special functionality may be missing. A TODO list is at
|
18
|
+
the head of every library file. Feel free to implement :-)
|
19
|
+
|
20
|
+
If you also have created gtk widgets in ruby and think, that they may be useful for others,
|
21
|
+
fork this project, include them and send me a pull request. Please attend, that you also provide
|
22
|
+
a small example of the widgets use under the *examples* directory.
|
Binary file
|
Binary file
|
data/lib/rgw/big-list.rb
ADDED
@@ -0,0 +1,316 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
BigList is free software; you can redistribute it and/or
|
5
|
+
modify it under the terms of the GNU Lesser General Public
|
6
|
+
License as published by the Free Software Foundation; either
|
7
|
+
version 2.1 of the License, or (at your option) any later version.
|
8
|
+
|
9
|
+
BigList is distributed in the hope that it will be useful,
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
Lesser General Public License for more details.
|
13
|
+
|
14
|
+
You should have received a copy of the GNU Lesser General Public
|
15
|
+
License along with BigList; if not, write to the Free Software
|
16
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
|
+
|
18
|
+
Copyright 2014 Detlef Reichl detlef!reichl()gmx!org
|
19
|
+
=end
|
20
|
+
|
21
|
+
|
22
|
+
=begin
|
23
|
+
TODO:
|
24
|
+
get all colors from the system settings
|
25
|
+
make the columns resizable
|
26
|
+
use copy while scrolling
|
27
|
+
add a data provider that calls a block. For very big data pools or as backend for a DB
|
28
|
+
=end
|
29
|
+
|
30
|
+
require 'rgw/types'
|
31
|
+
|
32
|
+
# Rgw::BigList is a widget, that shows a data list from an array of arrays. It has no bells and
|
33
|
+
# whistles, but is _very_ fast.
|
34
|
+
|
35
|
+
module Rgw
|
36
|
+
class BigList < Gtk::Table
|
37
|
+
|
38
|
+
ROW_PADDING = 4 # @private
|
39
|
+
# Initializes a new Rgw::BigList object
|
40
|
+
#
|
41
|
+
# @param num_cols [Integer, nil] The number of columns the list sould have.
|
42
|
+
def initialize num_cols=1
|
43
|
+
super(2, 2, false)
|
44
|
+
raise ArgumentError, 'positive integer expected' unless (num_cols.is_a? Integer and num_cols > 0)
|
45
|
+
@numCols = num_cols
|
46
|
+
# the X poxitions of the column ends
|
47
|
+
@colsX = []
|
48
|
+
# current displayed top column
|
49
|
+
@col = 0
|
50
|
+
# current displayed left column
|
51
|
+
@row = 0
|
52
|
+
|
53
|
+
@data = nil
|
54
|
+
@heads = nil
|
55
|
+
@headHeight = 0.0
|
56
|
+
@separator = "\t"
|
57
|
+
|
58
|
+
@area = Gtk::DrawingArea.new
|
59
|
+
self.attach @area, 0, 1, 0, 2, Gtk::AttachOptions::EXPAND | Gtk::AttachOptions::FILL,
|
60
|
+
Gtk::AttachOptions::EXPAND | Gtk::AttachOptions::FILL
|
61
|
+
|
62
|
+
# I don't use the integrated double buffering, cause it flickers
|
63
|
+
# I can do it better myself
|
64
|
+
double_buffered = false
|
65
|
+
@backBuffer = nil
|
66
|
+
|
67
|
+
@area.add_events Gdk::Event::Mask::SCROLL_MASK
|
68
|
+
|
69
|
+
@area.signal_connect(:scroll_event) {|object, event| on_scroll event.direction; false}
|
70
|
+
@area.signal_connect(:draw) {|object, cc| redraw; false}
|
71
|
+
@area.signal_connect(:configure_event) {|object, event| on_configure event; false}
|
72
|
+
|
73
|
+
@scroll = Gtk::Scrollbar.new :vertical
|
74
|
+
self.attach @scroll, 1, 2, 1, 2, 0, Gtk::AttachOptions::EXPAND | Gtk::AttachOptions::FILL
|
75
|
+
|
76
|
+
dummy = Gtk::Label.new ' '
|
77
|
+
self.attach dummy, 1, 2, 0, 1, 0, 0
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [Array] The complete data of the list as set by {#data=} or
|
81
|
+
# nil if not.
|
82
|
+
attr_reader :data
|
83
|
+
|
84
|
+
# @return [Array<String>, nil] The heads of the list if set by {#heads=}
|
85
|
+
# or nil if not.
|
86
|
+
attr_reader :heads
|
87
|
+
|
88
|
+
# @return [String] The separator to split data strings as set by {#separator=}
|
89
|
+
attr_reader :separator
|
90
|
+
|
91
|
+
# @return [Integer] The number of columns for the list as set by {#num_cols=}
|
92
|
+
attr_reader :numCols
|
93
|
+
|
94
|
+
|
95
|
+
# Set the lists data
|
96
|
+
#
|
97
|
+
# @param data [Array] The data for the list. The array has to contain Strings, which will
|
98
|
+
# be split with [separator], or arrays of strings, which will be used directly.
|
99
|
+
def data=(data)
|
100
|
+
@data = data
|
101
|
+
configure_scrollbar
|
102
|
+
queue_draw
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
# Set the heads of the the list
|
107
|
+
# @param heads [Array<String>] The texts which should be displayed as the columns heads.
|
108
|
+
def heads=(heads)
|
109
|
+
unless heads.nil?
|
110
|
+
raise ArgumentError, "invalid type %s for heads; expect Array of String" % heads.class.to_s unless heads.is_a? Array
|
111
|
+
raise ArgumentError, "invalid size of heads" unless @numCols == heads.length
|
112
|
+
heads.each {|head| raise ArgumentError, "invalid type %s for head; expect String" % head.class.to_s unless head.is_a? String}
|
113
|
+
end
|
114
|
+
@heads = heads
|
115
|
+
calculate_rows
|
116
|
+
configure_scrollbar
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
# Set the column separator
|
121
|
+
#
|
122
|
+
# @param sep [String] For lists, where the data is provided as an array of strings the
|
123
|
+
# separator will be used to split the input to the text for each column.
|
124
|
+
def separator=(sep)
|
125
|
+
@separator = sep
|
126
|
+
queue_draw
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
# Sets the number of columns
|
131
|
+
#
|
132
|
+
# @param cols [Integer] The number of columns the list should display
|
133
|
+
# @raise [ArgumentError] if cols is not an Integer or less then 1
|
134
|
+
def num_cols=(cols)
|
135
|
+
|
136
|
+
raise ArgumentError, 'invalid column number' unless cols.is_a? Integer and cols > 0
|
137
|
+
@numCols = cols
|
138
|
+
@colsX = []
|
139
|
+
width = @width.to_f / @numCols.to_f
|
140
|
+
0.upto(@numCols) {|col| @colsX << col.to_f * width}
|
141
|
+
queue_draw
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
# Get the row data from a given position
|
146
|
+
#
|
147
|
+
# @param x [Integer] Ignored for now.
|
148
|
+
# @param y [Integer] The vertical position in pixels from the list top position from where
|
149
|
+
# to get the data from
|
150
|
+
# @return [Array<String>] The rows data for the requested position. The data is owend
|
151
|
+
# by the list and should not be modified, because it will change your original data!
|
152
|
+
def row_at_pos x, y
|
153
|
+
@data[@row + y.to_f / @rowHeight]
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def queue_draw
|
159
|
+
@area.queue_draw_area 0, 0, @area.allocation.width, @area.allocation.height
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
def on_scroll dir
|
164
|
+
return if @data.nil?
|
165
|
+
case dir
|
166
|
+
when Gdk::EventScroll::Direction::UP
|
167
|
+
return if @row == 0
|
168
|
+
@row -= 1
|
169
|
+
@scroll.adjustment.value = @row
|
170
|
+
queue_draw
|
171
|
+
when Gdk::EventScroll::Direction::DOWN
|
172
|
+
return if @row + @numRows > @data.length
|
173
|
+
@row += 1
|
174
|
+
@scroll.adjustment.value = @row
|
175
|
+
queue_draw
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
def configure_scrollbar
|
181
|
+
return if @data.nil? or @numRows.nil? or @height.nil?
|
182
|
+
if @numRows >= @data.length()
|
183
|
+
@scroll.hide
|
184
|
+
else
|
185
|
+
@scroll.show
|
186
|
+
@scroll.adjustment = Gtk::Adjustment.new 0, 0, @data.length(), 1, @numRows, @numRows
|
187
|
+
@scroll.adjustment.signal_connect(:value_changed) {on_scrollbar_change}
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
def on_scrollbar_change
|
193
|
+
@row = @scroll.value.to_i
|
194
|
+
queue_draw
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
def on_configure event
|
199
|
+
@width = event.width
|
200
|
+
@height = event.height
|
201
|
+
ctx = self.toplevel.style_context
|
202
|
+
fnt = ctx.get_font :normal
|
203
|
+
@ccFontSize = Pango.pixels(fnt.size) / 72.0 * self.toplevel.screen.resolution
|
204
|
+
@ccFontFamily = fnt.family
|
205
|
+
calculate_rows
|
206
|
+
configure_scrollbar
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
def calculate_rows
|
211
|
+
return if self.window.nil?
|
212
|
+
@backBuffer = Cairo::ImageSurface.new Cairo::Format::RGB24, @width, @height
|
213
|
+
cc = Cairo::Context.new @backBuffer
|
214
|
+
cc.font_size = @ccFontSize
|
215
|
+
@rowHeight = cc.text_extents('XgqT)!_').height.to_f + ROW_PADDING.to_f * 2.0
|
216
|
+
@headHeight = @heads.nil? ? 0.0 : @rowHeight + 4.0
|
217
|
+
@numRows = ((@height.to_f - @headHeight) / @rowHeight).ceil
|
218
|
+
|
219
|
+
if @colsX.length() == 0
|
220
|
+
width = @width.to_f / @numCols.to_f
|
221
|
+
0.upto(@numCols) {|col| @colsX << col.to_f * width}
|
222
|
+
else
|
223
|
+
@colsX[-1] = @width.to_f
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
def redraw
|
229
|
+
return if self.window.nil?
|
230
|
+
cc = Cairo::Context.new @backBuffer
|
231
|
+
cc.antialias = :none
|
232
|
+
cc.set_source_rgb 1.0, 1.0, 1.0
|
233
|
+
cc.paint
|
234
|
+
|
235
|
+
# draw the head
|
236
|
+
unless @heads.nil?
|
237
|
+
cc.set_source_rgb 0.9, 0.9, 0.9
|
238
|
+
cc.rectangle 0, 0, @width, @headHeight
|
239
|
+
cc.fill.stroke
|
240
|
+
cc.antialias = :subpixel
|
241
|
+
cc.set_source_rgb 0.0, 0.0, 0.0
|
242
|
+
cc.font_size = @ccFontSize
|
243
|
+
cc.select_font_face @ccFontFamily, :normal, :bold
|
244
|
+
|
245
|
+
@heads.each_with_index do |head, col|
|
246
|
+
cc.move_to @colsX[col] + 4, @rowHeight - 4
|
247
|
+
cc.show_text head
|
248
|
+
cc.stroke
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# draw the data
|
253
|
+
unless @data.nil?
|
254
|
+
colClips = []
|
255
|
+
cellData = []
|
256
|
+
(@row).upto(@row + @numRows - 1) do |row|
|
257
|
+
break if row >= @data.length()
|
258
|
+
textRow = @data[row]
|
259
|
+
if textRow.is_a? Array
|
260
|
+
cellData << textRow
|
261
|
+
else
|
262
|
+
cellData << textRow.split(@separator)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
0.upto(@numCols - 1) do |col|
|
267
|
+
cc = Cairo::Context.new @backBuffer
|
268
|
+
cc.antialias = :subpixel
|
269
|
+
cc.set_source_rgb 0.0, 0.0, 0.0
|
270
|
+
cc.font_size = @ccFontSize
|
271
|
+
cc.select_font_face @ccFontFamily, :normal, :normal
|
272
|
+
|
273
|
+
cc.rectangle @colsX[col], @headHeight, @colsX[col + 1] - @colsX[col], @height - @headHeight
|
274
|
+
cc.clip
|
275
|
+
cc.new_path
|
276
|
+
0.upto(cellData.length() - 1) do |row|
|
277
|
+
tok = cellData[row][col]
|
278
|
+
next if tok.nil?
|
279
|
+
cc.move_to @colsX[col] + 4, (row + 1) * @rowHeight - 4 + @headHeight
|
280
|
+
cc.show_text tok
|
281
|
+
cc.stroke
|
282
|
+
cc.new_path
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
cc = Cairo::Context.new @backBuffer
|
287
|
+
cc.antialias = :none
|
288
|
+
cc.set_source_rgb 0.0, 0.0, 0.0
|
289
|
+
cc.line_width = 1.0
|
290
|
+
lg = @data.nil? ? 0 : @data.length()
|
291
|
+
lg += 1 unless @heads.nil?
|
292
|
+
|
293
|
+
# draw the vertical lines
|
294
|
+
0.upto(@numCols - 1) do |col|
|
295
|
+
x = @colsX[col]
|
296
|
+
cc.move_to x, 0
|
297
|
+
cc.line_to x, @height.min(lg * @rowHeight)
|
298
|
+
end
|
299
|
+
cc.stroke
|
300
|
+
|
301
|
+
# draw the horizontal lines
|
302
|
+
0.upto(@numRows.min(lg - 1)) do |row|
|
303
|
+
y = @rowHeight * row + @headHeight
|
304
|
+
cc.move_to 0, y
|
305
|
+
cc.line_to @width, y
|
306
|
+
end
|
307
|
+
cc.stroke
|
308
|
+
|
309
|
+
# copy backbuffer to the window
|
310
|
+
cb = @area.window.create_cairo_context
|
311
|
+
cb.set_source @backBuffer
|
312
|
+
cb.paint
|
313
|
+
false
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
@@ -0,0 +1,278 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
=begin
|
4
|
+
PropertyEditor is free software; you can redistribute it and/or
|
5
|
+
modify it under the terms of the GNU Lesser General Public
|
6
|
+
License as published by the Free Software Foundation; either
|
7
|
+
version 2.1 of the License, or (at your option) any later version.
|
8
|
+
|
9
|
+
PropertyEditor is distributed in the hope that it will be useful,
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
Lesser General Public License for more details.
|
13
|
+
|
14
|
+
You should have received a copy of the GNU Lesser General Public
|
15
|
+
License along with PropertyEditor; if not, write to the Free Software
|
16
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
|
+
|
18
|
+
Copyright 2014 Detlef Reichl detlef!reichl()gmx!org
|
19
|
+
=end
|
20
|
+
|
21
|
+
require 'rgw/synced-spin-button'
|
22
|
+
require 'rgw/radio-revealer'
|
23
|
+
|
24
|
+
module Rgw
|
25
|
+
class PropertyEditor < Gtk::Box
|
26
|
+
|
27
|
+
self.type_register
|
28
|
+
self.signal_new :property_changed, GLib::Signal::RUN_FIRST, nil, GLib::Type['void'], String, Object
|
29
|
+
|
30
|
+
def signal_do_property_changed foo, bla; end
|
31
|
+
|
32
|
+
def initialize props, type
|
33
|
+
super(:orientation => :vertical)
|
34
|
+
@widgetDefaults = []
|
35
|
+
@selectedElement = nil
|
36
|
+
table = create_prop_editor props, type
|
37
|
+
pack_start table, :expand => false, :fill => false, :padding => 4
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :selectedElement
|
41
|
+
|
42
|
+
|
43
|
+
def create_prop_editor props, type=nil
|
44
|
+
table = Gtk::Table.new props.length() + 1, 2
|
45
|
+
table.column_spacings = 8
|
46
|
+
table.row_spacings = 4
|
47
|
+
|
48
|
+
unless type.nil?
|
49
|
+
headline = Gtk::Label.new
|
50
|
+
headline.markup = '<b><big>' + type + '</big></b>'
|
51
|
+
headline.xalign = 0.1
|
52
|
+
table.attach headline, 0, 2, 0, 1, Gtk::AttachOptions::EXPAND | Gtk::AttachOptions::FILL,
|
53
|
+
Gtk::AttachOptions::EXPAND | Gtk::AttachOptions::FILL
|
54
|
+
end
|
55
|
+
|
56
|
+
0.upto(props.length()-1) { |a| create_prop_entry props[a], table, a + 1}
|
57
|
+
table.show_all
|
58
|
+
table
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def create_prop_entry data, table, row
|
63
|
+
label = Gtk::Label.new
|
64
|
+
label.xalign = 1.0
|
65
|
+
widget = nil
|
66
|
+
|
67
|
+
case data[:type]
|
68
|
+
when :iRadio
|
69
|
+
label.text = data[:label]
|
70
|
+
hbox = Gtk::Box.new :horizontal
|
71
|
+
|
72
|
+
i = 0
|
73
|
+
while true do
|
74
|
+
sym = ('img' + i.to_s).to_sym
|
75
|
+
break if data[sym].nil?
|
76
|
+
i += 1
|
77
|
+
end
|
78
|
+
|
79
|
+
group = nil
|
80
|
+
0.upto(i-1) do |n|
|
81
|
+
if n == 0
|
82
|
+
button = Gtk::RadioButton.new
|
83
|
+
group = button
|
84
|
+
else
|
85
|
+
button = Gtk::RadioButton.new group
|
86
|
+
end
|
87
|
+
hbox.pack_start button, :expand => false, :fill => false, :padding => 2
|
88
|
+
button.draw_indicator = false
|
89
|
+
sym = ('img' + n.to_s).to_sym
|
90
|
+
# img = Gtk::Image.new(:file => Rgw::PIXMAP_PATH + data[sym] + '.png')
|
91
|
+
button.image = img
|
92
|
+
button.signal_connect(:toggled) do |widget|
|
93
|
+
0.upto(widget.group.length() - 1) do |m|
|
94
|
+
if widget.group[m].active?
|
95
|
+
signal_emit :property_changed, data[:id0], widget.group.length() - 1 - m
|
96
|
+
break
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
group.group[i - 1 - data[:default0]].active = true
|
102
|
+
@widgetDefaults << [group, data]
|
103
|
+
hbox.show_all
|
104
|
+
widget = hbox
|
105
|
+
when :sSpin
|
106
|
+
label.text = data[:label]
|
107
|
+
widget = Rgw::SyncedSpinButton.new data[:range].first, data[:range].last, data[:step], data[:synced]
|
108
|
+
@widgetDefaults << [widget, data]
|
109
|
+
widget.set_values data[:default0], data[:default1]
|
110
|
+
widget.signal_connect(:value1_changed) {|wid, val| signal_emit :property_changed, data[:id0], val}
|
111
|
+
widget.signal_connect(:value2_changed) {|wid, val| signal_emit :property_changed, data[:id1], val}
|
112
|
+
when :spin
|
113
|
+
label.text = data[:label]
|
114
|
+
widget = Gtk::SpinButton.new data[:range].first, data[:range].last, data[:step]
|
115
|
+
widget.value = data[:default0]
|
116
|
+
@widgetDefaults << [widget, data]
|
117
|
+
widget.signal_connect(:value_changed) do |wid|
|
118
|
+
signal_emit :property_changed, data[:id0], wid.value
|
119
|
+
end
|
120
|
+
when :toggle
|
121
|
+
label.text = data[:label].split[0..-2].join(' ')
|
122
|
+
widget = Gtk::ToggleButton.new data[:label].split[-1]
|
123
|
+
widget.active = data[:default0]
|
124
|
+
@widgetDefaults << [widget, data]
|
125
|
+
widget.signal_connect(:toggled) do |wid|
|
126
|
+
signal_emit :property_changed, data[:id0], wid.active?
|
127
|
+
end
|
128
|
+
when :entry
|
129
|
+
label.text = data[:label]
|
130
|
+
widget = Gtk::Entry.new
|
131
|
+
widget.text = data[:default0]
|
132
|
+
@widgetDefaults << [widget, data]
|
133
|
+
widget.signal_connect(:changed) do |wid|
|
134
|
+
signal_emit :property_changed, data[:id0], wid.text
|
135
|
+
end
|
136
|
+
when :color
|
137
|
+
label.text = data[:label]
|
138
|
+
# fix for ruby gtk 2.2.0
|
139
|
+
col = data[:default0].map{|c| c * 0xffff}.take(3)
|
140
|
+
color = Gdk::Color.new *col
|
141
|
+
#color = Gdk::RGBA.new(*data[:default0])
|
142
|
+
widget = Gtk::ColorButton.new color
|
143
|
+
widget.use_alpha = true
|
144
|
+
@widgetDefaults << [widget, data]
|
145
|
+
widget.signal_connect(:color_set) do |wid|
|
146
|
+
cl = wid.rgba
|
147
|
+
signal_emit :property_changed, data[:id0], [cl.red, cl.green, cl.blue, cl.alpha]
|
148
|
+
end
|
149
|
+
when :combo
|
150
|
+
label.text = data[:label]
|
151
|
+
widget = Gtk::ComboBoxText.new
|
152
|
+
data[:entries].each {|entry| widget.append nil, entry}
|
153
|
+
@widgetDefaults << [widget, data]
|
154
|
+
widget.signal_connect(:changed) do |wid|
|
155
|
+
signal_emit :property_changed, data[:id0], wid.active
|
156
|
+
end
|
157
|
+
when :radioRevealer
|
158
|
+
rbox = Gtk::Box.new :vertical
|
159
|
+
table.attach_defaults rbox, 0, 2, row, row+1
|
160
|
+
rbox.pack_start Gtk::Separator.new(:horizontal), :expand => :false, :fill => :false
|
161
|
+
label.set_xalign(0.5)
|
162
|
+
label.markup = '<span size="large" weight="bold">' + data[:label] + '</span>'
|
163
|
+
rbox.pack_start label, :expand => :false, :fill => :false
|
164
|
+
widget = Rgw::RadioRevealer.new
|
165
|
+
rbox.pack_start widget, :expand => :false, :fill => :false
|
166
|
+
@widgetDefaults << [widget, data]
|
167
|
+
data[:revealSections].each do |section|
|
168
|
+
revealerChild = create_prop_editor section[:data]
|
169
|
+
label = Gtk::Label.new
|
170
|
+
label.markup = '<span size="medium" weight="bold">' + section[:section] + '</span>'
|
171
|
+
widget.create_entry label, revealerChild
|
172
|
+
widget.signal_connect(:revealed) do |wid, idx|
|
173
|
+
signal_emit :property_changed, data[:id0], idx
|
174
|
+
end
|
175
|
+
end
|
176
|
+
return
|
177
|
+
else
|
178
|
+
raise RuntimeError, 'invalid property type'
|
179
|
+
end
|
180
|
+
table.attach_defaults label, 0, 1, row, row+1
|
181
|
+
table.attach_defaults widget, 1, 2, row, row+1
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
def set_selected_element element
|
186
|
+
@selectedElement = element
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
def set_from_data
|
191
|
+
@widgetDefaults.each do |data|
|
192
|
+
val1 = @selectedElement.get_by_name data[1][:id0]
|
193
|
+
if data[1][:type] == :iRadio
|
194
|
+
data[0].group[data[0].group.length() - 1 - val1].active = true
|
195
|
+
elsif data[1][:type] == :toggle
|
196
|
+
data[0].active = val1
|
197
|
+
elsif data[1][:type] == :spin
|
198
|
+
data[0].value = val1
|
199
|
+
elsif data[1][:type] == :sSpin
|
200
|
+
val2 = @selectedElement.get_by_name data[1][:id1]
|
201
|
+
data[0].set_values val1, val2
|
202
|
+
elsif data[1][:type] == :entry
|
203
|
+
data[0].text = val1
|
204
|
+
elsif data[1][:type] == :color
|
205
|
+
col = Gdk::RGBA.new *val1
|
206
|
+
data[0].rgba = col
|
207
|
+
elsif data[1][:type] == :combo
|
208
|
+
data[0].active = val1
|
209
|
+
elsif data[1][:type] == :radioRevealer
|
210
|
+
data[0].active = val1
|
211
|
+
else
|
212
|
+
raise RuntimeError, 'invalid type in set_from_data'
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
|
218
|
+
def set_defaults
|
219
|
+
@widgetDefaults.each do |data|
|
220
|
+
# set from defaults
|
221
|
+
if data[1][:useDefault]
|
222
|
+
if data[1][:type] == :iRadio
|
223
|
+
# the buttons in a radio button group are orderd reverse. strange...
|
224
|
+
data[0].group[data[0].group.length() - 1 - data[1][:default0]].active = true
|
225
|
+
elsif data[1][:type] == :toggle
|
226
|
+
data[0].active = data[1][:default0]
|
227
|
+
elsif data[1][:type] == :spin
|
228
|
+
data[0].value = data[1][:default0]
|
229
|
+
elsif data[1][:type] == :sSpin
|
230
|
+
data[0].set_values data[1][:default0], data[1][:default1]
|
231
|
+
elsif data[1][:type] == :entry
|
232
|
+
data[0].text = data[1][:default0]
|
233
|
+
elsif data[1][:type] == :color
|
234
|
+
col = Gdk::RGBA.new(*data[1][:default0])
|
235
|
+
data[0].rgba = col
|
236
|
+
elsif data[1][:type] == :combo
|
237
|
+
data[0].active = data[1][:default0]
|
238
|
+
elsif data[1][:type] == :radioRevealer
|
239
|
+
data[0].active = data[1][:default0]
|
240
|
+
else
|
241
|
+
raise RuntimeError, 'invalid type in set_defaults useDefault'
|
242
|
+
end
|
243
|
+
# move from the widget into the data store
|
244
|
+
else
|
245
|
+
if data[1][:type] == :iRadio
|
246
|
+
nb = data[0].group.length
|
247
|
+
0.upto(nb - 1) do |i|
|
248
|
+
if data[0].group[i].active?
|
249
|
+
signal_emit :property_changed, data[1][:id0], nb - 1 - i
|
250
|
+
break
|
251
|
+
end
|
252
|
+
end
|
253
|
+
elsif data[1][:type] == :toggle
|
254
|
+
f = data[0].active? ? 1.0 : 0.0
|
255
|
+
signal_emit :property_changed, data[1][:id0], f
|
256
|
+
elsif data[1][:type] == :spin
|
257
|
+
signal_emit :property_changed, data[1][:id0], data[0].value
|
258
|
+
elsif data[1][:type] == :sSpin
|
259
|
+
s1, s2 = *data[0].get_values
|
260
|
+
signal_emit :property_changed, data[1][:id0], s1 if s1 >= 0.0
|
261
|
+
signal_emit :property_changed, data[1][:id1], s2 if s2 >= 0.0
|
262
|
+
elsif data[1][:type] == :entry
|
263
|
+
signal_emit :property_changed, data[1][:id0], data[0].text
|
264
|
+
elsif data[1][:type] == :color
|
265
|
+
cl = data[0].rgba
|
266
|
+
signal_emit :property_changed, data[1][:id0], [cl.red, cl.green, cl.blue, cl.alpha]
|
267
|
+
elsif data[1][:type] == :combo
|
268
|
+
signal_emit :property_changed, data[1][:id0], data[0].active
|
269
|
+
elsif data[1][:type] == :radioRevealer
|
270
|
+
signal_emit :property_changed, data[1][:id0], data[0].active
|
271
|
+
else
|
272
|
+
raise RuntimeError, 'invalid type in set_defaults !useDefault'
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|