Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Implementing a simple list

    PYTHON Development
    0
    23
    14.2k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 28/05/2013 at 09:17, xxxxxxxx wrote:

      I don't intend to switch to C++ soon as it is much more complex than python and, also, requires different compilation for Mac an Windows.
      I may have to create my own implementation of a LIST_VIEW 😞

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 28/05/2013 at 09:26, xxxxxxxx wrote:

        ^Yeah. I know. I was just kidding you about that. Tongue

        -ScottA

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 28/05/2013 at 11:40, xxxxxxxx wrote:

          Hi Rui,

          this is a very very old implementation of a simple ListView of mine. I've used it in Description Editor
          plugin. Works relatively fine, very basic. Please don't judge my coding style, this snippet is about 2
          years old. 🙂

          Maybe you can use it.

          class ListView(GeUserArea) :
              MOUSEWHEEL_MODE         = 1027215       # Registered at Plugincafe.com
              SELECTEDROW_UP          = 1027216       # Registered at Plugincafe.com
              SELECTEDROW_DOWN        = 1027217       # Registered at Plugincafe.com     
              SELECTEDROW_CHANGED     = 1027218       # Registered at Plugincafe.com
              SELECTEDROW_PREVIOUS    = 1027219       # Registered at Plugincafe.com
            
              colors             = {
                  "background":       Vector(.2),
                  "lighterRow":       Vector(.31),
                  "darkerRow":        Vector(.29),
                  "markedRow":        Vector(.38),
                  "text":             Vector(.64705),
                  "markedText":       Vector(1., .66, .024)
              }
            
              def __init__(
                      self,
                      parentDialog    = None,                 # The parent-dialog, can be None if the 'Command'-Method should not be invoked on an Input-Event
                      initialData     = (()),                 # Data to display, must be 2 dimensional
                      rowHeight       = 16,                   # Height of a row in the ListView
                      columnWidths    = (100,),               # Widths of the columns in the ListView
                      minSize         = (300, 100),           # Minimum size of the area. If second is None, it will be calculated.
                  ) :
            
                  self.parentDialog       = parentDialog
            
                  self.rowHeight          = rowHeight
                  self.columnWidths       = tuple(columnWidths)
                  self.data               = list(initialData)
                  self.selectedRow        = -1
            
                  self.minSize            = tuple(minSize)
            
              # Overriden
              def DrawMsg(self, x1, y1, x2, y2, msg) :
                  """ Called when redrawing the UserArea """
                  self.SetClippingRegion(x1, y1, x2, y2)
            
                  self.DrawSetPen(self.colors["background"])  # Set Background Color
                  self.DrawRectangle(x1, y1, x2, y2)          # Fill Background
            
                  """
                  Draw lighter rows
                  """
                  self.DrawSetPen(self.colors["lighterRow"])
                  for i in xrange(0,len(self.data), 2) :           # Iterate the  specified rows
                      Rectangle       = {
                          'x1':               0,
                          'x2':               x2,
                          'y1':               self.rowHeight * i,
                          'y2':               self.rowHeight * (i + 1)
                      }
                      # If the selected Row is about to be drawn
                      if i == self.selectedRow and self.colors["markedRow"]:
                          self.DrawSetPen(self.colors["markedRow"])
                          self.DrawRectangle(**Rectangle)
                          self.DrawSetPen(self.colors["lighterRow"])
                      else:
                          self.DrawRectangle(**Rectangle)
            
                  """
                  Draw darker rows
                  """
                  self.DrawSetPen(self.colors["darkerRow"]) 
                  for i in xrange(1,len(self.data), 2) :           # Iterate the  specified rows
                      Rectangle       = {
                          'x1':               0,
                          'x2':               x2,
                          'y1':               self.rowHeight * i,
                          'y2':               self.rowHeight * (i + 1)
                      }
                      # If the selected Row is about to be drawn
                      if i == self.selectedRow and self.colors["markedRow"]:
                          self.DrawSetPen(self.colors["markedRow"])
                          self.DrawRectangle(**Rectangle)
                          self.DrawSetPen(self.colors["darkerRow"])
                      else:
                          self.DrawRectangle(**Rectangle)
            
                  """
                  Draw data.
                  """
                  self.DrawSetTextCol(self.colors["text"], c4d.COLOR_TRANS)
                  for i in xrange(len(self.data)) :                # Iterate the  specified rows
                      previousItemPosX    = x1 + 5
                      for j in xrange(len(self.data[i])) :         # Iterate the datas columns
                          if j >= len(self.columnWidths) :
                              width       = self.columnWidths[-1]
                          else:
                              width       = self.columnWidths[j]
            
                          textToDraw          = str(self.data[i][j])
            
                          # If the selected Row is about to be drawn
                          if i == self.selectedRow:
                              self.DrawSetTextCol(self.colors["markedText"], c4d.COLOR_TRANS)
                              self.DrawText(  txt     = textToDraw,
                                              x1      = x1 + previousItemPosX ,
                                              y1      = y1 + i *  self.rowHeight + self.rowHeight - 14,
                              )
                              self.DrawSetTextCol(self.colors["text"], c4d.COLOR_TRANS)
                          else:
                              self.DrawText(  txt     = textToDraw,
                                              x1      = x1 + previousItemPosX ,
                                              y1      = y1 + i *  self.rowHeight + self.rowHeight - 14,
                              )
                          previousItemPosX   += width
            
              def InputEvent(self, msg) :
                  inputChannel            = msg[c4d.BFM_INPUT_CHANNEL]
            
                  # Left or Right Mousebutton
                  if inputChannel in (c4d.BFM_INPUT_MOUSELEFT, c4d.BFM_INPUT_MOUSERIGHT, c4d.BFM_INPUT_MOUSEMIDDLE) :
                      positionInDialog    = self.Global2Local()
                      mousePosX           = msg[c4d.BFM_INPUT_X] + positionInDialog["x"]
                      mousePosY           = msg[c4d.BFM_INPUT_Y] + positionInDialog["y"]
            
                      clickedRow          = int(mousePosY/self.rowHeight)
            
                      msg[self.SELECTEDROW_PREVIOUS]  = self.selectedRow
            
                      if clickedRow > len(self.data) - 1:
                          self.selectedRow    = -1
                      else:
                          self.selectedRow    = clickedRow
            
                      self.Redraw()
            
                  # MouseWheel switching of elements
                  elif inputChannel == c4d.BFM_INPUT_MOUSEWHEEL:
                      inputValue      = msg[c4d.BFM_INPUT_VALUE]
                      selectedRow     = self.selectedRow
            
                      # Go up (in visual), means to go back in the list 
                      if inputValue > 0:
                          # Do not if data-begin is reached
                          if selectedRow > 0:
                              if self.parentDialog:
                                  bc         = c4d.BaseContainer()
            
                                  bc[self.MOUSEWHEEL_MODE]        = self.SELECTEDROW_UP
                                  bc[self.SELECTEDROW_CHANGED]    = -1    # Selected row + SELECTEDROW_CHANGED = newSelectedRow
            
                                  self.parentDialog.Command(self.GetId(), bc) 
            
                              self.selectedRow   -= 1
            
                      # Go down (in visual), means to go further in the list
                      elif inputValue < 0:
                          # Do not if data-end is reached
                          if selectedRow <= len(self.data) -2:
                              if self.parentDialog:
                                  bc         = c4d.BaseContainer()
            
                                  bc[self.MOUSEWHEEL_MODE]        = self.SELECTEDROW_DOWN
                                  bc[self.SELECTEDROW_CHANGED]    = 1     # Selected row + SELECTEDROW_CHANGED = newSelectedRow
            
                                  self.parentDialog.Command(self.GetId(), bc)
            
                              self.selectedRow   += 1
            
                      self.Redraw()
            
                  # if parentDialog is defined, send Command-Message
                  if self.parentDialog:
                      self.parentDialog.Command(self.GetId(), msg)
            
            
                  return True
            
              def GetMinSize(self) :
                  """ Returns the minimum size of the area. """
                  return tuple(self.minSize)
            
              # Getters
              def GetMinHeight(self) :
                  return self.minSize[1]
            
              def GetSelectedRow(self) :
                  return self.selectedRow
            
              def GetRowHeight(self) :
                  return self.rowHeight
            
              def GetColumnWidths(self) :
                  return self.columnWidths
            
              def GetParentDialog(self) :
                  return self.parentDialog
            
              # Setters
              def SetColors(self, **kwargs) :
                  for k, v in kwargs.iteritems() :
                      if k in self.colors.keys() :
                          self.colors[k]  = v
            
              def SetData(self, data) :
                  self.data   = data
            
              def SetRowHeight(self, height) :
                  self.rowHeight      = height
                  self.minSize[1]     = self.rowHeight * len(self.data)
            
              def SetColumnWidths(self, columnWidths) :
                  self.columnWidths   = columnWidths
            
              def SetSelectedRow(self, index) :
                  if index >= len(self.data) :
                      self.selectedRow    = -1
                      return False
                  else:
                      self.selectedRow    = index
                      return True
            
              def SetParentDialog(self, parent) :
                  self.parentDialog       = parent
            
              # Adders
              def AppendData(self, data) :
                  self.data.append(data)
            
              def InsertData_AtIndex(self, data, index) :
                  if index > len( self.data ) :
                      return False
                  else:
                      self.data.insert(index, data)
            
              # Removers
              def RemoveData(self, subData) :
                  if subData in self.data:
                      del self.data[ self.data.index(subData) ]
                      return True
                  else:
                      return False
            
              def RemoveData_ByIndex(self, index) :
                  if index > len( self.data ) :
                      return False
                  else:
                      del self.data[index]
            
              # Update
              pass
          

          -Nik

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 29/05/2013 at 09:06, xxxxxxxx wrote:

            Thank you very muck, Nikklas.
            I will check it out, to see if I can use it.
            This creates color bars, right?
            I want to create a list of text items. Should not be too complicated to change this to my needs 🙂

            Rui Batista

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 29/05/2013 at 09:25, xxxxxxxx wrote:

              Yep, it looks like this:

              The data it uses to display must be a two dimensional list with each row having the same number of columns! A selected item can be moved up and down by scrolling the mouse-wheel. But scrolling the view is not implemented in this user area.

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 29/05/2013 at 15:38, xxxxxxxx wrote:

                It is working fine, Nikklas 🙂
                However, if I add more than a certain number of items, they just disappear down the bottom.
                Is there any way to implement a vertical scroll bar?

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 30/05/2013 at 01:57, xxxxxxxx wrote:

                  Sure. I think the easiest way would be to implement GetMinSize() and call LayoutChange() on the
                  dialog when the elements in the list have changed and put the user area into a scroll-group.

                  -Nik

                  1 Reply Last reply Reply Quote 0
                  • H
                    Helper
                    last edited by

                    On 30/05/2013 at 02:14, xxxxxxxx wrote:

                    You code already has a GetMinSize() and the user area it already inside a SCROLLGROUP, like this:

                    SCROLLGROUP DC_SCRIPT_CONTAINER
                         {
                         SCALE_V;
                         SCALE_H;
                         SCROLL_V;
                         SCROLL_BORDER;

                    USERAREA DC_SCRIPT_LIST { SCALE_V; SCALE_H; }
                         }

                    In my main code, I already filled the data with many, many items, just to test if a vertical scroll bar would appear. But it doesn't. Even if I change the size of my plugin window 😞

                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      On 30/05/2013 at 02:42, xxxxxxxx wrote:

                      But the current GetMinSize() implementation does not calculate the height based on the number
                      of elements. 🙂

                      http://pastebin.com/Jz2yPqK8

                      But I see it is a bit buggy, I don't know why actually. While the background is drawn correctly, the
                      text is not.. Not sure where this comes from, maybe you can figure it out.

                      -Nik

                      1 Reply Last reply Reply Quote 0
                      • H
                        Helper
                        last edited by

                        On 30/05/2013 at 03:29, xxxxxxxx wrote:

                        Actually, it is working but the userarea is not refreshing correctly when I scroll down and back up again.
                        I should be able to intercept a message that tells me that the scrollgroup changed and refresh the userarea when that happens.
                        But I don't know how 😞

                        Rui Batista

                        1 Reply Last reply Reply Quote 0
                        • H
                          Helper
                          last edited by

                          On 30/05/2013 at 03:46, xxxxxxxx wrote:

                          I'm trying to detect that the scrollgroup is being dragged with msg[c4d.BFM_ACTION_INDRAG]

                          but when I use this code:

                          def Message(self, msg, result) :
                              dragging=msg[c4d.BFM_ACTION_INDRAG]
                              return GeDialog.Message(self, msg, result)

                          I get a crash while starting up Cinema4D.

                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post