Implementing a simple list
-
On 28/05/2013 at 09:26, xxxxxxxx wrote:
^Yeah. I know. I was just kidding you about that.
-ScottA
-
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
-
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 needsRui Batista
-
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.
-
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? -
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
-
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
-
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.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
-
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 howRui Batista
-
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.