Forum: Ruby-Gnome 2 Best way to create table-like lists?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
474216d84e3b5381cba84cd04a3a3b35?d=identicon&s=25 joaz (Guest)
on 2007-06-23 16:16
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).
4913bcb685792f601ae9813b4713abb9?d=identicon&s=25 Detlef Reichl (Guest)
on 2007-06-23 16:41
(Received via mailing list)
Am Samstag, den 23.06.2007, 16:16 +0200 schrieb joaz:
> 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
>
Hi,

you can use the Gtk::TreeView as the display widget and the
Gtk::ListStore for your data.

Cheers
detlef


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
474216d84e3b5381cba84cd04a3a3b35?d=identicon&s=25 joaz (Guest)
on 2007-06-24 15:57
Detlef Reichl wrote:
> Hi,
>
> you can use the Gtk::TreeView as the display widget and the
> Gtk::ListStore for your data.
>
> Cheers
> detlef
Hi Detlef,

Thanks for your suggestion.

I made this list:

# test.rb
require 'gtk2'

window = Gtk::Window.new

content_types = Integer, String, String, String, Float
liststore = Gtk::ListStore.new(*content_types)
i = 0
100.times do
 iter = liststore.append
 iter[0] = i # row identified
 iter[1] = "test#{i}"
 iter[2] = "next#{i}"
 iter[3] = "lorem ipsum#{i}"
 iter[4] = rand(10000).to_f / 100

 i = i + 1
end

view = Gtk::TreeView.new(liststore)
view.enable_search=true
view.search_column=2

# render columns
i = 1
["test","super","perfect","lorem"].each do |name|
   renderer = Gtk::CellRendererText.new
   col = Gtk::TreeViewColumn.new(name, renderer, :text => i)
   col.sort_column_id = i
   col.resizable = true
   view.append_column(col)

   i = i + 1
end

# double click on row
view.signal_connect("row-activated") do |view, path, column|
  puts "Row #{path.to_str} was clicked!"

  if iter = view.model.get_iter(path)
    puts "Double-clicked row contains id #{iter[0]}!"
  end
end


# show in a scrolled window
scrolledwindow = Gtk::ScrolledWindow.new.add view

window.add scrolledwindow
window.set_default_size(640,480)

window.show_all

Gtk.main



That works nicely so far. But I need another feature: The application
should be API based and gets an already filtered list from the server.

That means I want to have a text field for searching above or below
every column head.
Is there any way to include or stick this to the table head?

I've seen the Gtk::CellEditable interface, but this has to stick with
the Head of the table. It may not disappear when scrolling.

Any ideas?
F84647ae45eca65c4ab5351f8d45ba83?d=identicon&s=25 Conan Rubymanjaro (conan)
on 2007-06-28 01:30
It looks like the TreeViewColumn object has a widget property, that you
can assign instead of a title.  This should let you customize your
headers as much as you like.  Like put a vbox in the title containing a
Gtk::Label and a Gtk::Entry(which you can rig up to search with signals
and whatnot)



>
> That works nicely so far. But I need another feature: The application
> should be API based and gets an already filtered list from the server.
>
> That means I want to have a text field for searching above or below
> every column head.
> Is there any way to include or stick this to the table head?
>
> I've seen the Gtk::CellEditable interface, but this has to stick with
> the Head of the table. It may not disappear when scrolling.
>
> Any ideas?
474216d84e3b5381cba84cd04a3a3b35?d=identicon&s=25 joaz (Guest)
on 2007-06-28 16:28
Conan Rubymanjaro wrote:
> It looks like the TreeViewColumn object has a widget property, that you
> can assign instead of a title.  This should let you customize your
> headers as much as you like.  Like put a vbox in the title containing a
> Gtk::Label and a Gtk::Entry(which you can rig up to search with signals
> and whatnot)

I tried this:
   col = Gtk::TreeViewColumn.new(name, renderer, :text => i)
   col.sort_column_id = i
   col.resizable = true

   box = Gtk::VBox.new
   box <<  Gtk::Entry.new

   box << Gtk::Label.new(name)
   box.show_all
   col.set_widget(box)


The problem is, that the Gtk::Entry is not editable at all because it
catches any mouse click on the header for the sorting function.

I think I'll switch to a sidebar for searching.
F84647ae45eca65c4ab5351f8d45ba83?d=identicon&s=25 Conan Rubymanjaro (conan)
on 2007-06-28 17:30
Hmm, that make sense.  You could always disable the sorting(hopefully
then it would forward all clicks to the widget) and add another widget
to the vbox for sorting, maybe a button or something.  But at this
point, it probably does make more sense to have a sidebar.

joaz wrote:
> I tried this:
>    col = Gtk::TreeViewColumn.new(name, renderer, :text => i)
>    col.sort_column_id = i
>    col.resizable = true
>
>    box = Gtk::VBox.new
>    box <<  Gtk::Entry.new
>
>    box << Gtk::Label.new(name)
>    box.show_all
>    col.set_widget(box)
>
>
> The problem is, that the Gtk::Entry is not editable at all because it
> catches any mouse click on the header for the sorting function.
>
> I think I'll switch to a sidebar for searching.
This topic is locked and can not be replied to.