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 (

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."
class Node(object) :
    def __init__(self, name, place, animal, thing) : = name = place
        self.animal = animal
        self.thing = thing = None
    def SetNext(self, next) : = next
    def GetNext(self) :
    def GetDown(self) :
        return None
    def GetPred(self) :
        return None
    def GetName(self) :
    def GetPlace(self) :
    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")
    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
      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:
    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")
    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() :
    PLUGIN_ID, PLUGIN_NAME, 0, None, PLUGIN_HELP, MenuCommand())
if __name__ == "__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.

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~~
      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)
      print "unknown column id!"