Seite 1 von 2

GradientGadget

Verfasst: 25.05.2012 15:31
von Lambda
Vielleicht wurde das irgendwo schon umgesetzt, aber hier mal meine Lösung dazu. <) Bis auf die Systemfarben gibt es keine WinAPI.


Ein Pfeil unterhalb des Gadgets ziehen um ihn zu löschen. Ist #GradientGadget_Adding verwendet wird durch klick in den Farbverlauf ein neuer hinzugefügt.

Code: Alles auswählen

;
; GradientGadget.pb

;/ Constant
#GradientGadget_Adding = 1<<0

#GradientGadget_CanvasSize = 5
#GradientGadget_CanvasFront = #Gray
#GradientGadget_CanvasBack = #white

;/ Colors
Global GradientGadget_BackColor            = GetSysColor_(#COLOR_3DFACE)

Global GradientGadget_ArrowColor           = GetSysColor_(#COLOR_BTNFACE)
Global GradientGadget_ArrowShadowColor     = GetSysColor_(#COLOR_BTNSHADOW)
Global GradientGadget_ArrowHighlightColor = GetSysColor_(#COLOR_BTNHILIGHT)

Global GradientGadget_BorderShadowColor    = GetSysColor_(#COLOR_3DSHADOW)
Global GradientGadget_BorderHighlightColor = GetSysColor_(#COLOR_3DHILIGHT)

Structure GRADIENTCHILD_INFO
  drag.i
  remove.i
  over.i
  pos.f
  color.i
EndStructure

Structure GRADIENT_INFO
  id.l
  img.i
  flags.l
  index.i
  
  ac.i
  ml.i
  mr.i
  drag.i
  List gradient.GRADIENTCHILD_INFO()
EndStructure

;-

Procedure DrawGradientGadget(GadgetID.i)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  Protected w.i=GadgetWidth(GadgetID), h.i=GadgetHeight(GadgetID), px.i
  Protected mx.i, my.i
  Protected x.i, y.i, s.i = #GradientGadget_CanvasSize
  
  mx = GetGadgetAttribute(GadgetID, #PB_Canvas_MouseX)
  my = GetGadgetAttribute(GadgetID, #PB_Canvas_MouseY)
  
  ResizeImage(*GG\img, w-10, h-10, #PB_Image_Raw)
  StartDrawing(ImageOutput(*GG\img))
    DrawingMode(#PB_2DDrawing_AlphaChannel)
    Box(0, 0, w, h, RGBA(255,255,255,0))
    
    If ListSize(*GG\gradient())>=2
      DrawingMode(#PB_2DDrawing_Gradient|#PB_2DDrawing_AlphaBlend)
    ForEach *GG\gradient()
      If *GG\gradient()\remove=#False
        GradientColor(*GG\gradient()\pos, *GG\gradient()\color)
      EndIf
    Next
    LinearGradient(0, 0, OutputWidth(), 0)
    Box(0, 0, OutputWidth(), OutputHeight())
    If mx>5 And mx<w-10
      *GG\ac=Point(mx+5, 2)
      Debug *GG\ac
    EndIf
    EndIf
  StopDrawing()
      
      
  StartDrawing(CanvasOutput(GadgetID))
    
    
    ;/ Canvas
    Box(0, 0, w, h, #GradientGadget_CanvasBack)
    For x=0 To (w-10)/s+1
      For y=0 To (h-10)/s+1
        Box(x*(s*2), y*(s*2), s, s, #GradientGadget_CanvasFront)
        Box(s+x*(s*2), s+y*(s*2), s, s, #GradientGadget_CanvasFront)
      Next
    Next
    
    Box(0, 0, 5, h, GradientGadget_BackColor)
    Box(w-5, 0, 5, h, GradientGadget_BackColor)
    Box(0, h-10, w, 10, GradientGadget_BackColor)
    ;/ Gadients
    If ListSize(*GG\gradient())>=2
    DrawingMode(#PB_2DDrawing_AlphaBlend)
    DrawImage(ImageID(*GG\img), 5, 2)
  Else
    Box(5, 0, w-10, h-10, GradientGadget_BackColor)
    EndIf
    
    ForEach *GG\gradient()
      
      If *GG\gradient()\drag=#True And mx>3 And mx<w-6
        *GG\gradient()\pos= (((100/(w-10))*(mx-4)))/100
      EndIf
      
      If *GG\gradient()\drag=#True And my>h And ListSize(*GG\gradient())>2
        *GG\gradient()\remove=#True
      ElseIf *GG\gradient()\drag=#True And my<h
        *GG\gradient()\remove=#False
      EndIf
      
      px =5+(*GG\gradient()\pos*(w-10))
      
      If *GG\gradient()\remove=#False
      DrawingMode(#PB_2DDrawing_Default)
      ;/ Arrow
        Select *GG\gradient()\over
          Case 0
            Box(px-4, h-9, 8, 8, GradientGadget_ArrowColor) 
          Case 1
            Box(px-4, h-9, 8, 8, GradientGadget_ArrowHighlightColor) 
        EndSelect
        DrawingMode(#PB_2DDrawing_Outlined)
        Box(px-4, h-9, 8, 8, GradientGadget_ArrowShadowColor) 
        If *GG\index=ListIndex(*GG\gradient())
        DrawingMode(#PB_2DDrawing_XOr)
        Box(px-2, h-7, 4, 4, GradientGadget_ArrowShadowColor)
      EndIf
    EndIf
  Next
  
  
    
    
    
    ;/ Border
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(4, 1, w-9, h-9, GradientGadget_BorderShadowColor)
    Box(3, 0, w-8, h-8, GradientGadget_BorderHighlightColor)
  StopDrawing()
EndProcedure

Procedure GradientGadget(GadgetID.i, x.i, y.i, Width.i, Height.i, flags.l=#Null)
  Protected *GradientGadget.GRADIENT_INFO=AllocateMemory(SizeOf(GRADIENT_INFO))
  
  If GadgetID=#PB_Any
    result = CanvasGadget(#PB_Any, x, y, Width, Height, #PB_Canvas_DrawFocus)
  Else
    result = GadgetID
    CanvasGadget(GadgetID, x, y, Width, Height)
  EndIf
  
  InitializeStructure(*GradientGadget, GRADIENT_INFO)
  
  With *GradientGadget
    \img = CreateImage(#PB_Any, Width-10, Height-10, 32|#PB_Image_Transparent)
    \id = result
    \flags = flags
    \index = -1
  EndWith

  SetGadgetData(result, *GradientGadget)
  
  DrawGradientGadget(result)
  ProcedureReturn result
EndProcedure

Procedure AddGradientGadgetItem(GadgetID, pos.f, color.i)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  
  AddElement(*GG\gradient())
  With *GG\gradient()
    \pos = pos
    \color = color
  EndWith
  DrawGradientGadget(GadgetID)
EndProcedure

Procedure RemoveGradientGadgetItem(GadgetID.i, index.i)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  
  SelectElement(*GG\gradient(), index)
  DeleteElement(*GG\gradient())
  
  DrawGradientGadget(GadgetID)
EndProcedure

Procedure GetGradientGadgetState(GadgetID.i)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  ProcedureReturn *GG\index
EndProcedure

Procedure SetGradientGadgetState(GadgetID.i, index.i)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  *GG\index=index
  DrawGradientGadget(GadgetID)
EndProcedure

Procedure GetGradientGadgetItemColor(GadgetID.i, index.i)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  SelectElement(*GG\gradient(), index)
  ProcedureReturn *GG\gradient()\color
EndProcedure

Procedure.f GetGradientGadgetItemPosition(GadgetID.i, index.i)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  SelectElement(*GG\gradient(), index)
  ProcedureReturn *GG\gradient()\pos
EndProcedure

Procedure SetGradientGadgetItemColor(GadgetID.i, index.i, color.i)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  SelectElement(*GG\gradient(), index)
  *GG\gradient()\color=color
EndProcedure

Procedure SetGradientGadgetItemPosition(GadgetID.i, index.i, Position.f)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  SelectElement(*GG\gradient(), index)
  *GG\gradient()\pos=Position
EndProcedure

Procedure CountGradientGadgetItems(GadgetID.i)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  ProcedureReturn ListSize(*GG\gradient())
EndProcedure

Procedure CheckGradientGadget(GadgetID.i)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  Protected mx.i, my.i, w.i=GadgetWidth(GadgetID), h.i=GadgetHeight(GadgetID)
  Protected ac.i, f.i
  
  
 
  
  If EventType()=#PB_EventType_LeftButtonDown Or EventType()=#PB_EventType_LeftDoubleClick
    *GG\ml=#True
  ElseIf EventType()=#PB_EventType_LeftButtonUp
    *GG\ml=#False
  EndIf
  
  
    mx = GetGadgetAttribute(GadgetID, #PB_Canvas_MouseX)
    my = GetGadgetAttribute(GadgetID, #PB_Canvas_MouseY)
  With *GG\gradient()
    ForEach *GG\gradient()
      px = 5+(*GG\gradient()\pos*(w-10))
      
      If mx> px-4 And mx<px+8 And my>h-10
      \over=#True
      If *GG\ml=#True And *GG\drag=#False
        \drag=#True
        *GG\drag=#True
        *GG\index=ListIndex(*GG\gradient())
        Break
      EndIf
    Else
      ;/ Adding
      If *GG\flags & #GradientGadget_Adding And *GG\ml=#True And my<h-10 And my>2 And *GG\drag=#False
        AddGradientGadgetItem(GadgetID, (((100/(w-10))*(mx-4)))/100, *GG\ac)
        
        *GG\ml=#False
        *GG\index=-1
      EndIf
      ;/ Removing
      If \remove=#True And ListSize(*GG\gradient())>2
        RemoveGradientGadgetItem(GadgetID, ListIndex(*GG\gradient()))
        *GG\index=-1
      EndIf
      
      \over=#False
    EndIf
    
    If *GG\ml=#False
      \drag=#False
      *GG\drag=#False
    EndIf
   
  Next
  
  ForEach *GG\gradient()
    px = 5+(*GG\gradient()\pos*(w-10))
    
    If *GG\ml=#True
      If \drag=#True
        f=#True
      EndIf
    EndIf
  Next
  
  If f=#False And *GG\ml=#True
    *GG\index=-1
  EndIf
  
EndWith
DrawGradientGadget(GadgetID)
  
EndProcedure

Procedure GetGradientGadgetImage(GadgetID.i)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  ProcedureReturn *GG\img
EndProcedure

Procedure FreeGradientGadget(GadgetID.i)
  Protected *GG.GRADIENT_INFO = GetGadgetData(GadgetID)
  If IsImage(*GG\img)
    FreeImage(*GG\img)
  EndIf
  
  FreeGadget(*GG\id)
EndProcedure


;- Example


OpenWindow(0, 0, 0, 400, 250, "GradientGadget", #PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_ScreenCentered)

GradientGadget(0, 50, 40, 300, 30, #GradientGadget_Adding)
AddGradientGadgetItem(0, 0, RGBA(0,0,0,128))
AddGradientGadgetItem(0, 0.3, RGBA(0,100,128,64))
AddGradientGadgetItem(0, 0.8, RGBA(0,64,128,255))
AddGradientGadgetItem(0, 1, RGBA(255,255,255,128))

SetGradientGadgetState(0, 2)

Procedure DrawExample()
  Protected GradientImage.i=GetGradientGadgetImage(0)
  
  StartDrawing(CanvasOutput(1))
    Box(0, 0, OutputWidth(), OutputHeight(), GetSysColor_(#COLOR_3DFACE))
    DrawingMode(#PB_2DDrawing_Gradient|#PB_2DDrawing_Transparent|#PB_2DDrawing_AlphaBlend)
    
    ; Readout Gradients
    For c=0 To CountGradientGadgetItems(0)-1
      GradientColor(GetGradientGadgetItemPosition(0, c), GetGradientGadgetItemColor(0, c))
    Next
    LinearGradient(0, 0, OutputWidth(), OutputHeight())
    Ellipse(OutputWidth()/2, OutputHeight()/2, OutputWidth()/2, OutputHeight()/2-30)
    
    DrawingMode(#PB_2DDrawing_AlphaBlend)
    ; The Image of the Gadget
    DrawImage(ImageID(GradientImage), 35, 70)
    
    DrawingMode(#PB_2DDrawing_XOr)
    DrawText(OutputWidth()/2-(TextWidth("Example")/2), OutputHeight()/2, "Example")
  StopDrawing()
EndProcedure


;- Use the Gradient

CanvasGadget(1, 10, 100, 380, 90)
DrawExample()


Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      End
      
    Case #PB_Event_Gadget
      CheckGradientGadget(0)
      DrawExample()
  EndSelect
ForEver

Re: GradientGadget

Verfasst: 25.05.2012 15:40
von ts-soft
:allright:

Ist aber leider noch ein Bug enthalten. Wenn man einen "Pfeil" links oder rechts herauszieht crasht es (zeile 92)

Re: GradientGadget

Verfasst: 25.05.2012 15:53
von Lambda
Danke, behoben. ^^

Auch noch Funktionen zum erhalten/setzen von Pfeilen. Und welcher Pfeil selektiert ist, kann man durch GetGradientGadgetState() bekommen. (-1 wenn keiner)

Edit: noch den Fehler behoben das ein Prfeil erstellt wird wenn man gerade verschiebt.

Re: GradientGadget

Verfasst: 25.05.2012 16:06
von STARGÅTE
Nette Idee, nur fehlt hier irgendwie der Einsatzzweck.
Da ich selber Farbgradienten verwende (zB in Spielen) habe ich mir ein Include geschrieben mit dem ich dann über

Code: Alles auswählen

CreateGradient(#Gradient)
AddGradientColor(#Gradient, 0.0, $FF0000FF)
AddGradientColor(#Gradient, 0.8, $FF00FF00)
AddGradientColor(#Gradient, 1.0, $FFFF0000)
einen Farbverlauf definieren kann und mit

Code: Alles auswählen

GetGradientColor(#Gradient, 0.4)
dann eine Farbe auslesen kann (unabhängig von einem Gadget), hier halt $80008080.

Was ich sagen will ist: Du hast jetzt einen Gradient-Editor, aber kein "Include" zum verwenden von Gradienten.
Vielleicht kannst du ja noch sowas hinzufügen ...

Re: GradientGadget

Verfasst: 25.05.2012 17:01
von Lambda
Naja, der Einsatzzweck war für Grafikprogramme gedacht. Ich wüsste nicht was in dem Sinn noch fehlt. <)

Re: GradientGadget

Verfasst: 25.05.2012 17:25
von STARGÅTE
Ja schön, aber wenn ich einen Gradienten "gebaut" habe, wie kann ich ihn mit deinem Gadget "exportieren" und dann in meinem Grafik-Programm nutzen (zB auf eine Box oder Line legen)?
Ich meine du lieferst hier nur ein Gadget für eine Funktion, deren Ergebnis nicht weiter nutzbar ist...

Re: GradientGadget

Verfasst: 25.05.2012 18:03
von RSBasic
:allright:

Re: GradientGadget

Verfasst: 25.05.2012 18:34
von Lambda
@STARGÅTE

Schau mal bei den Prozeduren CountGradientGadgetItems(), GetGradientGadgetItemColor(), GetGradientGadgetItemPosition()

Damit kannst du es auslesen. :wink:

Edit: Anwendungsbeispiel zum auslesen hinzugefügt.

Re: GradientGadget

Verfasst: 26.05.2012 02:30
von STARGÅTE
cOoki3druqs hat geschrieben:Edit: Anwendungsbeispiel zum auslesen hinzugefügt.
Ah oke ... gut, das ist natürlich eine möglichkeit.

Re: GradientGadget

Verfasst: 26.05.2012 12:01
von Lambda
Jetzt noch als schlankere Alternative mit GetGradient().

Hab mal daraus ein kleines Werkzeug gemacht um Source zu erzeugen. Doppelklick auf ein Pfeil um eine Farbe zu wählen.