VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "cShapeCircle"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private WithEvents ROuter As cControlPoint
Attribute ROuter.VB_VarHelpID = -1
Private WithEvents LightSourceCenter As cControlPoint
Attribute LightSourceCenter.VB_VarHelpID = -1
Private WithEvents CenterDrag As cControlPoint
Attribute CenterDrag.VB_VarHelpID = -1

Public Sub Init(Controlpoints As cControlPoints, ByVal X As Double, ByVal Y As Double, ByVal RadiusOuter As Double, ByVal LightSourceOffsetXY As Double)
  Set ROuter = Controlpoints.Add("ROuter" & ObjPtr(Me), X + RadiusOuter, Y, vbGreen, 6)
  Set LightSourceCenter = Controlpoints.Add("LightSourceCenter" & ObjPtr(Me), X + LightSourceOffsetXY, Y + LightSourceOffsetXY, vbCyan, 4)
  Set CenterDrag = Controlpoints.Add("CenterDrag" & ObjPtr(Me), X, Y, vbMagenta, 9)
End Sub

Public Sub Draw(CC As cCairoContext)
Dim Pat As cCairoPattern
  CC.Save
  
    'as always, we define the path first... (in this case a simple circle is created)
    CC.Arc CenterDrag.X, CenterDrag.Y, RadiusOuter

    Set Pat = Cairo.CreateRadialPattern(CenterDrag.X, CenterDrag.Y, RadiusOuter * 1.5, LightSourceCenter.X, LightSourceCenter.Y, 0)
      Pat.AddColorStop 1, vbBlack, 0#
      Pat.AddColorStop 0, vbBlack, 1
    CC.Fill True, Pat '<- note the Optional "True"-param before "Pat", meaning we do *not* want to close the path yet...

    '...since we plan to draw a Border too (with a different Stroke-Color)
    CC.SetLineWidth 1
    CC.SetSourceColor &H101010, 0.5
    CC.Stroke '*now* the Path gets closed (no Optional DontClosePath-Param set) - and we ensure thereby a combined Fill+Stroke

  CC.Restore
End Sub

Public Property Get RadiusOuter() As Double
  RadiusOuter = ROuter.X - CenterDrag.X
End Property

'Control-Point Movement-Events are received below, and we will act accordingly with the necessary adaptions

Private Sub Router_PositionChanging(NewX As Double, NewY As Double)
  NewY = CenterDrag.Y

  If NewX - CenterDrag.X < 20 Then NewX = CenterDrag.X + 20   'we restrict the outer Radius to min 20 pixels
  If NewX - CenterDrag.X > 150 Then NewX = CenterDrag.X + 150   'we restrict the outer Radius to man 150 pixels
  
  'and this ensures, that the LightSource-Center is adapted accordingly to the new Radius -> (NewX - CenterDrag.X)
  AdjustLightSourcePlacement CenterDrag.X, CenterDrag.Y, (NewX - CenterDrag.X) / RadiusOuter
End Sub
Private Sub LightSourceCenter_PositionChanging(NewX As Double, NewY As Double)
Dim NewR#
  NewR = Sqr((CenterDrag.X - NewX) ^ 2 + (CenterDrag.Y - NewY) ^ 2)
  
  If NewR > RadiusOuter * 1.3 Then
    NewX = CenterDrag.X + (NewX - CenterDrag.X) / NewR * RadiusOuter * 1.3
    NewY = CenterDrag.Y + (NewY - CenterDrag.Y) / NewR * RadiusOuter * 1.3
  End If
End Sub
Private Sub CenterDrag_PositionChanging(NewX As Double, NewY As Double)
Dim RO#
  'we need to buffer the current Radius and Coords beforehand, to not mess-up the coord-adaptions below, since both are dynamically calculated in Properties
  RO = RadiusOuter
  
  ROuter.X = NewX + RO
  ROuter.Y = NewY
  
  'again, here the LightSource-Center-adjustment, according to our new, move "Main-Center-Point"
  AdjustLightSourcePlacement NewX, NewY
End Sub

'small helper-Sub, to adjust the relative placement of the "LightSource"-CenterControlPoint
Private Sub AdjustLightSourcePlacement(CenterX As Double, CenterY As Double, Optional Ratio As Double = 1)
Dim RLdX#, RLdY#
  RLdX = LightSourceCenter.X - CenterDrag.X
  RLdY = LightSourceCenter.Y - CenterDrag.Y
  
  LightSourceCenter.X = CenterX + RLdX * Ratio
  LightSourceCenter.Y = CenterY + RLdY * Ratio
End Sub


