Scroll area in UA
-
On 12/07/2018 at 07:46, xxxxxxxx wrote:
I have a User Area with multiple (vertical) images in it.
Now I want to add a vertical scroll bar to scroll through the images.
But I do not understand fully, the relation between the ua size and the visible area size?What is the best place to define the visible area?
How do I use SetVisibleArea() when the user area is resized?A little example would help me for certain!
Here the code.
import c4d from c4d import bitmaps, gui, plugins, utils, documents import collections, os, sys PLUGIN_ID = 10000010 #TestID only!!!!!!!!!!!! scrollGroup = 1001 class Area(gui.GeUserArea) : def __init__(self) : self.bmp = c4d.bitmaps.BaseBitmap() def Sized(self, w, h) : print "Sized: ", w,h return def DrawMsg(self, x1, y1, x2, y2, msg) : self.DrawRectangle(x1, y1, x2, y2) #Draws the UA rectangle area path = os.path.join(os.path.dirname(__file__), "Library", "Airbus_A380.jpg") result, ismovie = self.bmp.InitWith(path) x1 = 10 if result == c4d.IMAGERESULT_OK: y1 = 10 self.DrawBitmap(self.bmp, x1, y1, 200, 200, 0, 0, 200, 200, c4d.BMP_NORMAL) #first y1 = 220 self.DrawBitmap(self.bmp, x1, y1, 200, 200, 0, 0, 200, 200, c4d.BMP_NORMAL) #second y1 = 430 self.DrawBitmap(self.bmp, x1, y1, 200, 200, 0, 0, 200, 200, c4d.BMP_NORMAL) #third class MyDialog(gui.GeDialog) : def __init__(self, area) : self.area = area def CreateLayout(self) : self.ScrollGroupBegin(scrollGroup, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, c4d.SCROLLGROUP_VERT) self.GroupBegin(1003, c4d.BFH_CENTER | c4d.BFV_CENTER, cols=1) self.GroupBorderNoTitle(c4d.BORDER_NONE) self.GroupBorderSpace(0, 0, 0, 20) self.AddUserArea(1, c4d.BFH_LEFT | c4d.BFV_TOP) self.AttachUserArea(self.area, 1) self.GroupEnd() #end UA group self.GroupEnd() #end scrollgroup self.GroupBegin(0, flags=c4d.BFH_FIT, cols=1) self.AddButton(1027, flags=c4d.BFH_LEFT, initw=100, name="Test") #Test button self.GroupEnd() return True def Command(self, id, msg) : if (id == 1027) : print self.GetVisibleArea(scrollGroup) self.SetVisibleArea(scrollGroup, 0,0,250,250) self.area.Redraw() return True return True class MBLibrary(plugins.CommandData) : area = Area() dialog = None def Execute(self, doc) : if self.dialog is None: self.dialog = MyDialog(self.area) return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=500, defaulth=120) def RestoreLayout(self, sec_ref) : if self.dialog is None: self.dialog = MyDialog(self.area) return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref) if __name__ == "__main__": pluginString = "MB Library V01" bmp = bitmaps.BaseBitmap() dir, f = os.path.split(__file__) fn = os.path.join(dir, "res", "icon.tif") bmp.InitWith(fn) okyn = plugins.RegisterCommandPlugin(id=PLUGIN_ID, str=pluginString, info=0, help=pluginString, dat=MBLibrary(), icon=bmp) if (okyn) : print pluginString + " initialized." else: print "Error initializing " + pluginString
-
On 16/07/2018 at 07:48, xxxxxxxx wrote:
Hi Pim,
The ua size is the total size of the GeUserArea, without any scrolling, so it's the full GeUserArea size, which can be bigger than the screen of course.
The visible area is the part which is currently visible in this GeUserArea.Let' take an example, I get a ua of a 2000 pixels height, but my dialog is only 500 pixels height. So the Visible area will only be 500 pixels, but from the 2000 pixels, displayed pixels can be from 0 to 500 or either 1000 to 1500.
But looking at your code there is few adjustments to make. For example, you initialize the parent group to BFH/BFV_CENTER, so by default a GeUserArea it will be a square of 4,4 pixels since there is nothing inside, please use BFH/BFV_SCALEFIT instead, it will then automatically scale according to the size you define in GetMinSize function.
On a side note since you are going to draw more than it's allowed (by that I mean you will draw from pixel 0 to 2000 and then crop it using a scrollGroup in order to allow custom display size) so make sure to call SetClippingRegion in the DrawMsg function.
Here is your example fixed
import c4d from c4d import bitmaps, gui, plugins, utils, documents import collections, os, sys PLUGIN_ID = 10000010 #TestID only!!!!!!!!!!!! scrollGroup = 1001 class Area(gui.GeUserArea) : def __init__(self) : self.bmp = c4d.bitmaps.BaseBitmap() def Sized(self, w, h) : print "Sized: ", w,h return def GetMinSize(self) : #do a calculation here return 400, 430 + 200 def DrawMsg(self, x1, y1, x2, y2, msg) : self.DrawSetPen(c4d.COLOR_BG_HIGHLIGHT) self.SetClippingRegion(x1, y1, x2, y2) self.DrawRectangle(x1, y1, x2, y2) #Draws the UA rectangle area path = os.path.join(os.path.dirname(__file__), "Library", "Airbus_A380.jpg") result, ismovie = self.bmp.InitWith(path) x1 = 10 if result == c4d.IMAGERESULT_OK: y1 = 10 self.DrawBitmap(self.bmp, x1, y1, 200, 200, 0, 0, 200, 200, c4d.BMP_NORMAL) #first y1 = 220 self.DrawBitmap(self.bmp, x1, y1, 200, 200, 0, 0, 200, 200, c4d.BMP_NORMAL) #second y1 = 430 self.DrawBitmap(self.bmp, x1, y1, 200, 200, 0, 0, 200, 200, c4d.BMP_NORMAL) #third class MyDialog(gui.GeDialog) : def __init__(self, area) : self.area = area def CreateLayout(self) : self.ScrollGroupBegin(scrollGroup, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, c4d.SCROLLGROUP_VERT) self.GroupBegin(1003, c4d.BFH_SCALEFIT|c4d.BFH_SCALEFIT, cols=1) self.GroupBorderSpace(0, 0, 0, 20) self.AddUserArea(1005, c4d.BFH_SCALEFIT|c4d.BFH_SCALEFIT) self.AttachUserArea(self.area, 1005) self.GroupEnd() #end UA group self.GroupEnd() #end scrollgroup self.GroupBegin(0, flags=c4d.BFH_FIT, cols=1) self.AddButton(1027, flags=c4d.BFH_LEFT, initw=100, name="Test") #Test button self.GroupEnd() return True def Command(self, id, msg) : if (id == 1027) : sizes = self.GetVisibleArea(scrollGroup) ySize = sizes["y2"] - sizes["y1"] # Get the current size displayed #Jump to the 2nd picture print self.area.GetHeight() self.SetVisibleArea(scrollGroup, 0,220, 0, 220 + ySize) #self.area.Redraw() return True return True class MBLibrary(plugins.CommandData) : area = Area() dialog = None def Execute(self, doc) : if self.dialog is None: self.dialog = MyDialog(self.area) return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=500, defaulth=120) def RestoreLayout(self, sec_ref) : if self.dialog is None: self.dialog = MyDialog(self.area) return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref) if __name__ == "__main__": pluginString = "MB Library V01" bmp = bitmaps.BaseBitmap() dir, f = os.path.split(__file__) fn = os.path.join(dir, "res", "icon.tif") bmp.InitWith(fn) okyn = plugins.RegisterCommandPlugin(id=PLUGIN_ID, str=pluginString, info=0, help=pluginString, dat=MBLibrary(), icon=bmp) if (okyn) : print pluginString + " initialized." else: print "Error initializing " + pluginString
If you have any questions please let me know,
Cheers,
Maxime -
On 17/07/2018 at 03:30, xxxxxxxx wrote:
Great explanation!
Thanks, Pim -
On 18/07/2018 at 08:38, xxxxxxxx wrote:
Sorry, more questions on scrolling UA.
Next step is to size the images / thumbnails to be displayed.
For example, when I click the test button, the size of the thumbnail is decreased from 200 to 20.
Displaying the sized thumbnails is no problem, but how to size the vertical scroll bar, thus that it indicates the new size?Do I use GetMinSize() or SetVisibleArea().
If so, where and when do I call GetMinSize()?if (id == 1027) : newSize = 20 self.area.GetMinSize() print "SetVisibleArea: ", self.SetVisibleArea(scrollGroup, 0, 0, 400, 3*(newSize+10)) self.area.Redraw()
-
On 18/07/2018 at 09:39, xxxxxxxx wrote:
Hi Scott,
You don't have to call GetMinSize, it's called automatically when the parent(owner of the GeUserArea) is drawn/sized, in your case, group 1003 which is owned by your ScrollGroup.
So in order to support what's, you want I've made few adjustments.class Area(gui.GeUserArea) : size = 300 pictureCnt = 3 def GetMinSize(self) : return 400, self.pictureCnt * self.size def DrawMsg(self, x1, y1, x2, y2, msg) : self.DrawSetPen(c4d.COLOR_BG_HIGHLIGHT) self.SetClippingRegion(x1, y1, x2, y2) self.DrawRectangle(x1, y1, x2, y2) # Draws the UA rectangle area path = os.path.join(os.path.dirname(__file__), "Library", "Airbus_A380.jpg") result, ismovie = self.bmp.InitWith(path) x1 = 10 if result == c4d.IMAGERESULT_OK: for i in xrange(0, self.pictureCnt) : y1 = self.size * i self.DrawBitmap(self.bmp, x1, y1, self.size, self.size, 0, 0, self.size, self.size, c4d.BMP_NORMAL)
and in the GeDialog
if (id == 1027) : self.area.size = 400 self.LayoutChanged(scrollGroup) sizes = self.GetVisibleArea(scrollGroup) ySize = sizes["y2"] - sizes["y1"] # Get the current size displayed pictureId = 1 # ID start from 0 self.SetVisibleArea(scrollGroup, 0, self.area.size * pictureId, 0, self.area.size * pictureId + ySize) return True
So we define the new size of the picture then we call self.LayoutChanged(scrollGroup) which will call DrawMsg and also GetMinSize in order to know the size of the UserArea then finally our scrollGroup is drawn according to these data. Then after is up to us to scroll where we want.
Maybe off topic, but I did a library with thumbnail on my personal time some time ago, it's available in here you may found some interesting stuff in it.
Again if you have any question, let me know!
Cheers,
Maxime