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: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