Page 1 of 1

Cover Flow Gadget

Posted: Wed Mar 27, 2013 5:19 pm
by Oliver13
Hello,

I found this nice piece of code to display a CloverFlow (viewtopic.php?f=13&t=45835 and converted it into a UserGadget. It generally works, but needs to be beautified.

Suggestions for enhancements:
- improved aligment (width/spacing)
- smooth scrolling
- reduction of flickering
- dynamical adding of entries
- highlightning of selected item
...

Note:
You need the include file from http://www.purebasic.fr/german/viewtopi ... =8&t=26471

Oliver

Code: Select all

; CoverFlowGadget

  ; Cover flow written by Michael Vogel
   ; ---------------------------------------------
   
   ; done...
   ; + configurable sizes, background color etc.
   ; + cursor keys to scroll left and right
   
   ; to do...
   ; – faster scrolling with shift ???
   ; – mouse drag and drop?
   ; – fast (!) shadow effects?
   
   ; http://forums.purebasic.com/english/viewtopic.php?f=13&t=45835
   
   
  XIncludeFile "EM_EventManager.pbi"
; http://www.purebasic.fr/german/viewtopic.php?f=8&t=26471
  
  
   Enumeration
      #ShelfLeft
      #ShelfRight
      #ShelfQuit

      #Cover
      #CoverImage
      #CoverImageTemp
      #CoverImagePool=200

   EndEnumeration
      #LovelyBird=$0A9C5E
   
    #MaxCoverImages=30

   #ShelfColor=#White
   
   #ShelfSize=12;      Anzahl der Covers in einer Zeile (äußerste nicht sichtbar)
   #ShelfPhase=5;      Anzahl der Phasen beim Durchblättern
   #ShelfSpace=6;      Pixel zwischen Thumbnails
   #ShelfMin=128;      Verkleinerung in Relation zum zentralen Cover (256)
   #ShelfVert=150;      Vertikaler Versatz (0..256)
   #ShelfWave=4;      Sinuswellenbreite

   #ShelfMid=#ShelfSize>>1
   #FontSize=20
   
   Structure tCoverSizeType
      rx.i
      ry.i
      ox.i
      oy.i
   EndStructure
   
   
Structure tCoverFlowGadget
  id.i
  canvas.i
  buttonleft.i
  buttonright.i
  MaxCoverImages.i;=30
   ShelfColor.i;=White
   ShelfSize.i;=12;      Anzahl der Covers in einer Zeile (äußerste nicht sichtbar)
   ShelfPhase.i;=5;      Anzahl der Phasen beim Durchblättern
   ShelfSpace.i;=6;      Pixel zwischen Thumbnails
   ShelfMin.i;=128;      Verkleinerung in Relation zum zentralen Cover (256)
   ShelfVert.i;=150;      Vertikaler Versatz (0..256)
   ShelfWave.i;=4;      Sinuswellenbreite
   ShelfMid.i;=ShelfSize>>1
   FontSize.i;=20
   thumbsizeX.i
   thumbsizeY.i
   ShelfX.i
   ShelfY.i
   CacheImage.i
   x.i
   y.i
   w.i
   h.i
   CoverImage.i
   Map CoverImagePool.i()
   Array CoverSize.tCoverSizeType(0,0)
   iCurrentShelf.i
   
 EndStructure
Procedure.i CoverFlowGadget_Phaser(min,max,phase)

   ProcedureReturn min+(max-min)*phase/(#ShelfPhase+1)

EndProcedure 
 
Procedure CoverFlowGadget_ShelfCalc(id)
 If IsGadget(id)
    Protected *CoverFlowObject .tCoverFlowGadget = GetGadgetData (id)
    If Not *CoverFlowObject
      ProcedureReturn 
    EndIf
  EndIf
  
  With *CoverFlowObject
    
   ; Calculate Cover Sizes and Offsets...

   n=0
   p=0
   m=\ShelfSize>>1

   For i=0 To \ShelfSize
      z=m-i
      If z<0
         z=-z
      EndIf
      If z>\ShelfWave
         f=\ShelfMin
      Else
         f=256-(256-\ShelfMin)*Sin(#PI*z/\ShelfWave/2)
      EndIf
         \CoverSize(i,0)\rx=21+(\ThumbSizeX*f)>>8
         \CoverSize(i,0)\ry=(\ThumbSizeY*f)>>8
         \CoverSize(i,0)\oy=\ShelfSpace+\ThumbSizeY-(\CoverSize(i,0)\ry*\ShelfVert+\ThumbSizeY*(256-\ShelfVert))>>8
         If i=0
            \CoverSize(i,0)\ox=-(\ThumbSizeX*\ShelfMin)>>8
         Else
            \CoverSize(i,0)\ox=\CoverSize(i-1,0)\ox+\CoverSize(i-1,0)\rx+\ShelfSpace
         EndIf
   Next i

   ; Calculate Values for Phases...
   For i=0 To \ShelfSize-1
      rxmin=\CoverSize(i,0)\rx
      rxmax=\CoverSize(i+1,0)\rx
      rymin=\CoverSize(i,0)\ry
      rymax=\CoverSize(i+1,0)\ry
      oxmin=\CoverSize(i,0)\ox
      oxmax=\CoverSize(i+1,0)\ox
      oymin=\CoverSize(i,0)\oy
      oymax=\CoverSize(i+1,0)\oy

      For p=1 To \ShelfPhase
         
            \CoverSize(i,p)\rx=CoverFlowGadget_Phaser(rxmin,rxmax,p)
            \CoverSize(i,p)\ry=CoverFlowGadget_Phaser(rymin,rymax,p)
            \CoverSize(i,p)\ox=CoverFlowGadget_Phaser(oxmin,oxmax,p)
            \CoverSize(i,p)\oy=CoverFlowGadget_Phaser(oymin,oymax,p)
      Next p
   Next i

   \ShelfX=\w-42;\CoverSize(\ShelfSize,0)\ox
   \ShelfY=\ShelfSpace*4+\ThumbSizeY+\FontSize
   SetGadgetData (id, *CoverFlowObject)
 EndWith  
 EndProcedure



Procedure CoverFlowGadget_GetCurrentShelf(id)
  If IsGadget(id)
    Protected *CoverFlowObject .tCoverFlowGadget = GetGadgetData (id)
    If Not *CoverFlowObject
      ProcedureReturn 
    EndIf
  EndIf
  
  ProcedureReturn *CoverFlowObject\iCurrentShelf
  
EndProcedure

Procedure CoverFlowGadget_CreateImages(id, iNum)
  If IsGadget(id)
    Protected *CoverFlowObject .tCoverFlowGadget = GetGadgetData (id)
    If Not *CoverFlowObject
      ProcedureReturn 
    EndIf
  EndIf
  
  With *CoverFlowObject
    
    ; Create Cover Images...
    While NextMapElement(\CoverImagePool())
      If IsImage(\CoverImagePool())
        FreeImage(\CoverImagePool())
      EndIf
    Wend
   ClearMap (\coverimagePool()) 
   For i=0 To iNum
      \CoverImagePool(Str(i))=CreateImage(#PB_Any,\ThumbSizeX,\ThumbSizeY)
      StartDrawing(ImageOutput(\CoverImagePool(Str(i))))
      Box(0,0,\ThumbSizeX,\ThumbSizeY,#LovelyBird)
      Circle(Random(\ThumbSizeX),Random(\ThumbSizeY),Random(\ThumbSizeY),Random($FFFFFF))
      DrawingMode(#PB_2DDrawing_Outlined)
      Box(0,0,\ThumbSizeX,\ThumbSizeY,#White-#ShelfColor)
      s.s="#"+Str(i)
      DrawText((\ThumbSizeX-TextWidth(s))>>1,(\ThumbSizeY-TextHeight(s))>>1,s,#LovelyBird)
      StopDrawing()
   Next i  
 EndWith  
 SetGadgetData (id, *CoverFlowObject)
EndProcedure


Procedure CoverFlowGadget_ShelfShow(id,nShow,p=0)
  If IsGadget(id)
    Protected *CoverFlowObject .tCoverFlowGadget = GetGadgetData (id)
    If Not *CoverFlowObject
      ProcedureReturn 
    EndIf
  EndIf
  
  
  With *CoverFlowObject
    
    Protected i,NewID
   Protected mode,n
   Protected s.s
   
   
   
   If nShow<0: nShow=0:EndIf
   If nShow>MapSize(\CoverImagePool())-1: nShow=MapSize(\CoverImagePool())-1:EndIf
   n=nShow
   
   ; Show Covers...

   StartDrawing(ImageOutput(\CacheImage))
   Box(0,0,\ShelfX,\ShelfY,\ShelfColor)

;   DrawingFont(ShelfFont)
   i=n
   If p>\ShelfPhase>>1
      i-1
   EndIf
   s="Image #"+Str(i)
   i=TextWidth(s)
   DrawText((\ShelfX-i)>>1,\ShelfSpace<<1+\ThumbSizeY,s,$c0c0c0,\ShelfColor)

   If p
      mode=#PB_Image_Raw
   Else
      mode=#PB_Image_Smooth
   EndIf

   n-\ShelfMid
   For i=0 To \ShelfSize-1
         If n+i>=0 And n+i<=MapSize(\CoverImagePool())-1
            CopyImage(\CoverImagePool(Str(n+i)),#CoverImageTemp)
            newID=ResizeImage(#CoverImageTemp,\CoverSize(i,p)\rx,\CoverSize(i,p)\ry,mode)
            DrawImage(NewID,\CoverSize(i,p)\ox,\CoverSize(i,p)\oy)
         EndIf
   Next i

   StopDrawing()
;   SetGadgetState(\CoverImage,\CacheImage)
   
   StartDrawing(CanvasOutput(\canvas))
   DrawImage(ImageID(\CacheImage),0,0)
   StopDrawing()
   FreeImage(#CoverImageTemp)
   \iCurrentShelf=nShow
   SetGadgetData(id,*CoverFlowObject)
 EndWith
 
EndProcedure

Procedure CoverFlowGadget_ButtonClick(*ev.EM_Events)
  Protected id=GetGadgetData(*ev\eventgadget)
    If IsGadget(id)
    Protected *CoverFlowObject .tCoverFlowGadget = GetGadgetData (id)
    If Not *CoverFlowObject
      ProcedureReturn 
    EndIf
  EndIf
  
  With  *CoverFlowObject
  Protected iCurrentShelf=\iCurrentShelf
  
  If GetGadgetText(*ev\eventgadget)="<"
    iCurrentShelf-1
  Else
    iCurrentShelf+1
  EndIf
EndWith

  For pp=1 To *CoverFlowObject\ShelfPhase
                  CoverFlowGadget_ShelfShow(id,iCurrentShelf,pp)
                  ;WaitWindowEvent(1)
               Next pp
  
  CoverFlowGadget_ShelfShow(id,iCurrentShelf)  
EndProcedure

Procedure CoverFlowGadget(id.i, x.i, y.i, width.i, height.i, ThumbnailX=120, ThumbnailY=120)
  Protected *GadgetObject.tCoverFlowGadget = AllocateMemory ( SizeOf ( tCoverFlowGadget) )
  
  If id = #PB_Any
    id = ContainerGadget(#PB_Any, x, y, width, height)
  Else
    ContainerGadget(id, x, y, width, height)
  EndIf
  
  
  
  
  With *GadgetObject
   \thumbsizeX=ThumbnailX
   \thumbsizeY=ThumbnailY
   
   \id=id
    \canvas=CanvasGadget(#PB_Any,21,0,width-42,\thumbsizeY+12)
    \buttonleft=ButtonGadget(#PB_Any,0,0,20,\thumbsizeY+12,"<")
    SetGadgetData(\buttonleft,id)
    \buttonright=ButtonGadget(#PB_Any,width-20,0,20,\thumbsizeY+12,">")
    SetGadgetData(\buttonright,id)
    CloseGadgetList()
    \MaxCoverImages.i=30
   EM_Seteventhandler(\buttonleft,#EM_Gadget,@CoverFlowGadget_ButtonClick())
   EM_Seteventhandler(\buttonright,#EM_Gadget,@CoverFlowGadget_ButtonClick())
   \ShelfColor=$FFFFFF;White
   
   \ShelfSize=(width-42)/\thumbsizeX;      Anzahl der Covers in einer Zeile (äußerste nicht sichtbar)
   \ShelfPhase=20;      Anzahl der Phasen beim Durchblättern
   \ShelfSpace=6;      Pixel zwischen Thumbnails
   \ShelfMin=128;      Verkleinerung in Relation zum zentralen Cover (256)
   \ShelfVert=150;      Vertikaler Versatz (0..256)
   \ShelfWave=4;      Sinuswellenbreite
   \ShelfMid=\ShelfSize>>1
   \FontSize=20
   \x=x
   \y=y
   \w=width
   \h=height
   
   NewMap \CoverImagePool()
   Dim \CoverSize(\ShelfSize,\ShelfPhase)
    SetGadgetData  (id , *GadgetObject )
   EndWith
    
  CoverFlowGadget_ShelfCalc(id)  
  
  *GadgetObject =GetGadgetData(id)
  With *GadgetObject
   \CacheImage=CreateImage(#PB_Any,\ShelfX,\ShelfY)
  EndWith
   SetGadgetData  (id , *GadgetObject )
  CoverFlowGadget_CreateImages(id,*GadgetObject\ShelfPhase )  
 
    
  
  
  ProcedureReturn id
  
EndProcedure

Procedure IsCoverFlowGadget (id)
  If IsGadget(id)
    Protected *CoverFlowObject .tCoverFlowGadget = GetGadgetData (id)
    If Not *CoverFlowObject
      ProcedureReturn 
    EndIf
  Else
    ProcedureReturn
  EndIf
  ProcedureReturn #True
EndProcedure

Macro DoEvent()
  Repeat : WaitWindowEvent() : ForEver
EndMacro

CompilerIf #PB_Compiler_IsIncludeFile=0



Procedure Event_CloseWindow()
    End
    
EndProcedure


Procedure Test()
   ; Open Window...
   OpenWindow(#Cover,0,0,1000,200,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
;    AddKeyboardShortcut(#Cover,#PB_Shortcut_Right,#ShelfRight)
;    AddKeyboardShortcut(#Cover,#PB_Shortcut_Left,#ShelfLeft)
;    AddKeyboardShortcut(#Cover,#PB_Shortcut_Escape,#ShelfQuit)
  EM_SetEventHandler(#PB_Event_CloseWindow, #EM_Special, @Event_CloseWindow())
  id=CoverFlowGadget(#PB_Any,0,0,1000,200,120,180)

CoverFlowGadget_ShelfShow(id,6)
doevent()
EndProcedure


Test()
CompilerEndIf