Hi,
I tried different approaches to create table-like lists. What I need
- a head (1-3 rows), non-scrollable
- a scrollable body
- head and body cells must align
My first draft was:
VBox
-> Table (for head), childs are labels
-> Scrolledwindow
—> Viewport
------> Table (for data), childs are labels
The problem is that head table and body table are not aligned. For
example because the scrollbars which are not present in head table.
My next attempt is this class, using a Layout object allowing me to
attach object in a fixed position.
Draft:
VBox
-> Layout (for head)
—> Labels (fixed position)
-> Scrollwindow
—> Layout (for body)
-----> Labels (fixed position)
#table.rb
class Table
attr_accessor :widths
attr_accessor :number_of_columns
attr_accessor :height
attr_accessor :x
attr_accessor :y
attr_accessor :color
attr_accessor :head_data
attr_accessor :head
attr_accessor :body
attr_accessor :body_scrollwindow
attr_accessor :x_pos #bad name should be p pos in pixel
def initialize(widths)
set_column_widths(widths)
self.height = 16
self.x = 0
self.y = 0
set_color
# Head
self.head = Gtk::Layout.new
# Body in a scrollwindow
scrollwindow = Gtk::ScrolledWindow.new
self.body =
Gtk::Layout.new(scrollwindow.hadjustment,scrollwindow.vadjustment)
scrollwindow.add body
self.body_scrollwindow = scrollwindow
end
def set_column_widths(widths)
self.widths = widths
self.number_of_columns = widths.size
self.x_pos = []
cur = 0
i = 0
widths.each do |w|
self.x_pos[i] = cur
cur = cur + w
i = i + 1
end
end
def head_data(data)
self.head_data = data
data.each do |h|
add_head_label(h)
end
end
def add(str)
label = Gtk::Label.new(str.to_s)
label.set_alignment(0,0)
label.width_request = self.widths[self.x]
label.height_request = self.height
eventbox = Gtk::EventBox.new
eventbox << label
eventbox.modify_bg(Gtk::STATE_NORMAL,self.color)
add_widget(eventbox)
end
def add_widget(widget,target=self.body)
target.put(widget,self.x_pos[self.x],self.height*self.y)
self.x = self.x + 1
check_if_linebreak
end
def check_if_linebreak
if self.x >= self.number_of_columns
self.x = 0
self.y = self.y + 1
set_color
end
end
def attach(box)
total_width = 0
self.widths.each{|w| total_width = total_width + w}
total_height = y * self.height
self.head.height_request = self.height
self.body.set_size(total_width,total_height)
box.pack_start(self.head,false,true,0)
box.pack_start(self.body_scrollwindow,true,true,0)
box.show_all
end
private
def set_color
if self.y % 2 == 0
self.color = Gdk::Color::parse("#cccccc")
else
self.color = Gdk::Color::parse("#dddddd")
end
end
def add_head_label(str)
label = Gtk::Label.new(str.to_s)
label.set_alignment(0,0)
label.width_request = self.widths[self.x]
label.height_request = self.height
eventbox = Gtk::EventBox.new
eventbox << label
eventbox.modify_bg(Gtk::STATE_NORMAL,Gdk::Color::parse("#cacaca"))
add_widget(eventbox,self.head)
end
end
This is a test program for this table:
test.rb
require ‘gtk2’
require ‘table.rb’
window = Gtk::Window.new
head = [“Test”,“Test2”,“next”,“something else”,“Hello World”]
table = Table.new([40,55,55,100,150])
table.head_data(head)
100.times do
table.add(“test”)
table.add(“test…”)
table.add("…")
table.add(“test”)
table.add(“lorem ipsum”)
end
vbox = Gtk::VBox.new
table.attach(vbox)
window.add(vbox)
window.set_default_size(640,480)
window.show_all
Gtk.main
What’s annoying me is that I have a gap between head and body of the
table. It seems to be in the scrolledwindow above the Layout object.
How to debug this?
Are there any other proposals to do this kind of table? I’ve seen that
gtk-extra has a spreadsheet widget, but I haven’t seen any ruby bindings
for it and/or a win32 binary (which is unfortunately mandatory).