Creating a table view using c4d.gui.TreeViewCustom

On 24/03/2016 at 23:28, xxxxxxxx wrote:

I'm trying to create a table with each row representing information about an object. To understand how this could be done, I have created a simple plugin based on c4d_treeview.pyp (https://gist.github.com/NiklasRosenstein/632e39a9b4dda391fe54)

Unfortunately, DrawCell does not render text to the cell using this approach. Am I using drawinfo["frame"].DrawText() incorrectly or is my approach the wrong way to go about implementing a table view using tree view?

The code follows

import c4d
  
PLUGIN_ID = 9912399
PLUGIN_NAME = "Python TreeView Example"
PLUGIN_HELP = "Show a simple table."
  
ID_NAME = 1
ID_PLACE = 2
ID_ANIMAL = 3
ID_THING = 4
  
class Node(object) :
    def __init__(self, name, place, animal, thing) :
        self.name = name
        self.place = place
        self.animal = animal
        self.thing = thing
        self.next = None
  
    def SetNext(self, next) :
        self.next = next
  
    def GetNext(self) :
        return self.next
  
    def GetDown(self) :
        return None
  
    def GetPred(self) :
        return None
  
    def GetName(self) :
        return self.name
  
    def GetPlace(self) :
        return self.place
  
    def GetAnimal(self) :
        return self.animal
  
    def GetThing(self) :
        return self.thing
  
class Hierarchy(c4d.gui.TreeViewFunctions) :
  
  def __init__(self, dlg) :
    node1 = Node("name1", "place1", "animal1", "thing1")
    node2 = Node("name2", "place2", "animal2", "thing2")
    node3 = Node("name3", "place3", "animal3", "thing3")
    node4 = Node("name4", "place4", "animal4", "thing4")
  
    node1.SetNext(node2)
    node2.SetNext(node3)
    node3.SetNext(node4)
    self.root = node1
  
  def GetFirst(self, root, userdata) :
    root = self.root
    return root
  
  def GetDown(self, root, userdata, obj) :
    return obj.GetDown()
  
  def GetNext(self, root, userdata, obj) :
    return obj.GetNext()
  
  def GetPred(self, root, userdata, obj) :
    return obj.GetPred()
  
  def GetName(self, root, userdata, obj) :
    return obj.GetName()
  
  def GetId(self, root, userdata, obj) :
    return obj.GetUniqueID()
  
  def DrawCell(self, root, userdata, obj, col, drawinfo, bgColor) :
    if col == ID_NAME:
      name = obj.GetName()
      w = drawinfo["frame"].DrawGetTextWidth(name)
      h = drawinfo["frame"].DrawGetFontHeight()
      xpos = drawinfo["xpos"]
      ypos = drawinfo["ypos"]
      print "%d) name = %s" % (col, name)
      print "text width= %d, font height= %d" % (w, h)
      print "width= %d, height= %d" % (drawinfo["frame"].GetWidth(), drawinfo["frame"].GetHeight())
      print "xpos= %d, ypos= %d" % (xpos, ypos)
      drawinfo["frame"].DrawText(name, xpos, ypos - h)
    elif col == ID_PLACE: pass
    elif col == ID_ANIMAL: pass
    elif col == ID_THING: pass
    else:
      print "unknown column id!"
  
  def GetColumnWidth(self, root, userdata, obj, col, area) :
    return 80
  
class TestDialog(c4d.gui.GeDialog) :
  
  _treegui = None
  
  def CreateLayout(self) :
    customgui = c4d.BaseContainer()
    customgui.SetBool(c4d.TREEVIEW_BORDER, True)
    customgui.SetBool(c4d.TREEVIEW_HAS_HEADER, True)
    customgui.SetBool(c4d.TREEVIEW_HIDE_LINES, True)
    customgui.SetBool(c4d.TREEVIEW_MOVE_COLUMN, False)
    customgui.SetBool(c4d.TREEVIEW_RESIZE_HEADER, True)
    customgui.SetBool(c4d.TREEVIEW_FIXED_LAYOUT, False)
    customgui.SetBool(c4d.TREEVIEW_ALTERNATE_BG, True)
    self._treegui = self.AddCustomGui(1000, c4d.CUSTOMGUI_TREEVIEW,
                                      "", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT,
                                      300, 300, customgui)
    return True
  
  def CoreMessage(self, id, msg) :
    if id == c4d.EVMSG_CHANGE:
      self._treegui.Refresh()
  
    return True
  
  def InitValues(self) :
    layout = c4d.BaseContainer()
    layout.SetLong(ID_NAME, c4d.LV_USER)
    layout.SetLong(ID_PLACE, c4d.LV_USER)
    layout.SetLong(ID_ANIMAL, c4d.LV_USER)
    layout.SetLong(ID_THING, c4d.LV_USER)
    self._treegui.SetLayout(4, layout)
  
    self._treegui.SetHeaderText(ID_NAME, "Name")
    self._treegui.SetHeaderText(ID_PLACE, "Place")
    self._treegui.SetHeaderText(ID_ANIMAL, "Animal")
    self._treegui.SetHeaderText(ID_THING, "Thing")
    self._treegui.Refresh()
  
    data_model = Hierarchy(self)
    self._treegui.SetRoot(None, data_model, None)
  
    return True
  
  
class MenuCommand(c4d.plugins.CommandData) :
  
  dialog = None
  
  def Execute(self, doc) :
    if self.dialog is None:
       self.dialog = TestDialog()
    return self.dialog.Open(
      c4d.DLG_TYPE_ASYNC, PLUGIN_ID, defaulth=600, defaultw=600)
  
  def RestoreLayout(self, sec_ref) :
    if self.dialog is None:
       self.dialog = TestDialog()
    return self.dialog.Restore(PLUGIN_ID, secret=sec_ref)
  
def main() :
  c4d.plugins.RegisterCommandPlugin(
    PLUGIN_ID, PLUGIN_NAME, 0, None, PLUGIN_HELP, MenuCommand())
  
if __name__ == "__main__":
  main()

On 25/03/2016 at 08:33, xxxxxxxx wrote:

I was able to solve the rendering issue

  1. One of the column items has to be of type LV_TREE
  2. For that item, TreeFunction.GetName() is used to render the text in the cell
  3. For other items (of type LV_USER), TreeFunction.DrawCell() is used to render the contents of the cell.

Changes:
layout.SetLong(ID_NAME, c4d.LV_USER)
layout.SetLong(ID_NAME, c4d.LV_TREE)

def DrawCell(self, root, userdata, obj, col, drawinfo, bgColor) :
~~    if col == ID_NAME:~~
~~      name = obj.GetName()~~
~~      w = drawinfo["frame"].DrawGetTextWidth(name)~~
~~      h = drawinfo["frame"].DrawGetFontHeight()~~
~~      xpos = drawinfo["xpos"]~~
~~      ypos = drawinfo["ypos"]~~
~~      print "%d) name = %s" % (col, name)~~
~~      print "text width= %d, font height= %d" % (w, h)~~
~~      print "width= %d, height= %d" % (drawinfo["frame"].GetWidth(), drawinfo["frame"].GetHeight())~~
~~      print "xpos= %d, ypos= %d" % (xpos, ypos)~~
~~      drawinfo["frame"].DrawText(name, xpos, ypos - h)~~
~~    elif col == ID_PLACE: pass~~
~~    elif col == ID_ANIMAL: pass~~
~~    elif col == ID_THING: pass~~
    else:
      print "unknown column id!"

def DrawCell(self, root, userdata, obj, col, drawinfo, bgColor) :
    if col == ID_PLACE:
drawinfo["frame"].DrawText(obj.GetPlace(), drawinfo["xpos"], drawinfo["ypos"] + 2)
    elif col == ID_ANIMAL:
drawinfo["frame"].DrawText(obj.GetAnimal(), drawinfo["xpos"], drawinfo["ypos"] + 2)
    elif col == ID_THING:
drawinfo["frame"].DrawText(obj.GetThing(), drawinfo["xpos"], drawinfo["ypos"] + 2)
    else:
      print "unknown column id!"