Update v.1.00:
- Code ist nun OS Independent!
Update v.1.01
- Kleinere Bugs gefixt
- Code teilweise kommentiert
Module:
Code: Alles auswählen
;By Mijikai
;PIEC (PieChart) module [ALL OS!]
;Version: v.1.01
;Tested on Win10 x64
;PB v.5.60
DeclareModule PIEC
Declare.i Create(X.i,Y.i,Name.s,Radius.d,Flag.b)
Declare.i Add(*PieChart,Name.s,Value.d,Color.l)
Declare.i Remove(*PieChart,Name.s)
Declare.i Update(*PieChart,Name.s,Value.d)
Declare.i Free(*PieChart)
EndDeclareModule
Module PIEC
Structure PIEC_ENTRY_STRUCT
Name.s{32}
Image.i
Color.l
Value.d
Percent.d
Deg.d
*NextEntry.PIEC_ENTRY_STRUCT
EndStructure
Structure PIEC_STRUCT
Gadget.i
GadgetList.i
Image.i
X.i
Y.i
Radius.d
Flag.b
Summ.d
*FirstEntry.PIEC_ENTRY_STRUCT
EndStructure
#PIEC_MIN_RADIUS = 80
#PIEC_FACTOR = 20
#PIEC_COLUMN_VALUE = "Value"
#PIEC_COLUMN_PERCENT = "%"
#PIEC_LIST_WIDTH = 370
#PIEC_COLUMN_NAME_WIDTH = 205
#PIEC_COLUMN_VALUE_WIDTH = 55
#PIEC_COLUMN_PERCENT_WIDTH = 55
Procedure.i DrawPie(*PieChart.PIEC_STRUCT,AngleStart.d,AngleEnd.d,Color.l)
AngleStart - 90: AngleEnd - 90 ;Startposition für das Kuchenstück (oben)
StrokePath(1):MovePathCursor(*PieChart\X,*PieChart\Y) ;Strichdicke & Startposition der Zeichenoperationen festlegen
VectorSourceColor(Color) ;Zeichenfarbe
VectorSourceCircularGradient(*PieChart\X,*PieChart\Y,*PieChart\Radius * 4.5) ;Zirkularen Gradient erstellen
VectorSourceGradientColor(Color,0) ;Gradient Farbe 1
VectorSourceGradientColor(-938208236,1) ;Gradient Farbe 2
AddPathCircle(*PieChart\X,*PieChart\Y,*PieChart\Radius,AngleStart,AngleEnd, #PB_Path_Connected) ;Kuchenstück zeichnen
ClosePath():FillPath() ;Zeichenoperation abschließen & Kuchenstück füllen
EndProcedure
Procedure.i DrawIco(*PieChartEntry.PIEC_ENTRY_STRUCT)
If StartVectorDrawing(ImageVectorOutput(*PieChartEntry\Image)) ;Zeichne auf Bild X
VectorSourceColor(-1):FillVectorOutput():StrokePath(1) ;Hintergrund Zeichnen & Strichdicke einstellen
VectorSourceColor(*PieChartEntry\Color):MovePathCursor(8,8) ;Zeichenfarbe & Startposition für die Zeichnung festlegen
VectorSourceCircularGradient(8,8,40) ;Zirkularen Gradient erstellen
VectorSourceGradientColor(*PieChartEntry\Color,0) ;Gradient Farbe 1
VectorSourceGradientColor(-938208236,1) ;Gradient Farbe 2
AddPathCircle(8,8,6):ClosePath():FillPath() ;Kreis zeichnen & Zeichenoperation abschließen & Kreis füllen
StopVectorDrawing() ;Zeichenoperation beenden
ProcedureReturn #True ;Ergebnis (TRUE = alles in Ordnung)
EndIf
EndProcedure
Procedure.i Draw(*PieChart.PIEC_STRUCT)
Protected *PieChartEntry.PIEC_ENTRY_STRUCT
Protected Angle.d, Offset.d
If *PieChart
If *PieChart\FirstEntry
*PieChartEntry = *PieChart\FirstEntry
If StartVectorDrawing(ImageVectorOutput(*PieChart\Image)) ;Zeichenoperation beginnen
ClearGadgetItems(*PieChart\GadgetList) ;Liste leeren
VectorSourceColor(-1) ;Zeichenfarbe
FillVectorOutput() ;Hintergrund Zeichnen
While *PieChartEntry
If *PieChartEntry\Value > 0 ;Nur etwas Zeichnen wenn der Wert > 0 ist!
*PieChartEntry\Percent = (*PieChartEntry\Value / *PieChart\Summ) * 100 ;Prozent berechnen
*PieChartEntry\Deg = (*PieChartEntry\Value / *PieChart\Summ) * 360 ;Grad berechnen
If *PieChartEntry\Percent > 100
*PieChartEntry\Percent = 100
EndIf
Offset = Angle + *PieChartEntry\Deg ;Offset berechnen
DrawPie(*PieChart,Angle,Offset,*PieChartEntry\Color) ;Kuchenstück zeichnen
Angle = Offset ;Neuen Winkel setzen
EndIf
AddGadgetItem(*PieChart\GadgetList,-1, ;Eintrag zur Liste hinzufügen
Chr(10) + *PieChartEntry\Name +
Chr(10) + StrF(*PieChartEntry\Value,2) +
Chr(10) + StrF(*PieChartEntry\Percent,2),
ImageID(*PieChartEntry\Image))
*PieChartEntry = *PieChartEntry\NextEntry
Wend
If *PieChart\Flag
VectorSourceColor(-1) ;Donut Variante zeichnen
AddPathCircle(*PieChart\X,*PieChart\Y,*PieChart\Radius/3)
ClosePath():FillPath()
EndIf
MovePathCursor(0,0)
VectorSourceColor(-15461356)
AddPathBox(0,0,ImageWidth(*PieChart\Image) + 1,ImageHeight(*PieChart\Image)) ;Rahmen zeichnen
StrokePath(1)
ClosePath()
StopVectorDrawing()
SetGadgetState(*PieChart\Gadget,ImageID(*PieChart\Image))
ResizeGadget(*PieChart\Gadget,#PB_Ignore,#PB_Ignore,#PB_Ignore,#PB_Ignore)
ProcedureReturn #True
EndIf
Else
If StartVectorDrawing(ImageVectorOutput(*PieChart\Image)) ;Zeichenoperation beginnen (Bild Kuchenstück)
VectorSourceColor(-1) ;Zeichenfarbe
FillVectorOutput() ;Hintergrund zeichnen
DrawPie(*PieChart,0,360,-1) ;Kuchenstück (leer) zeichnen
MovePathCursor(0,0) ;Startposition für Zeichenoperation verschieben
VectorSourceColor(-15461356) ;Zeichenfarbe
AddPathBox(0,0,ImageWidth(*PieChart\Image) + 1,ImageHeight(*PieChart\Image)) ;Rahmen um das Kuchenstück zeichnen
StrokePath(1) ;Strichdicke
ClosePath() ;Zeicheoperation abschließen
If *PieChart\Flag
VectorSourceColor(-1) ;Donut Variante zeichnen
AddPathCircle(*PieChart\X,*PieChart\Y,*PieChart\Radius/3)
ClosePath():FillPath()
EndIf
StopVectorDrawing()
SetGadgetState(*PieChart\Gadget,ImageID(*PieChart\Image))
ResizeGadget(*PieChart\Gadget,#PB_Ignore,#PB_Ignore,#PB_Ignore,#PB_Ignore)
ProcedureReturn #True
EndIf
EndIf
EndIf
EndProcedure
Procedure.i Create(X.i,Y.i,Name.s,Radius.d,Flag.b)
Protected *PieChart.PIEC_STRUCT
Radius - #PIEC_FACTOR ;Zeichengröße errechnen (Radius - Platzfaktor zum Rand)
Radius * 2 ;Radius = Durchmesser
If Radius < #PIEC_MIN_RADIUS ;Ist der Radius (Durchmesser) groß genug?
Radius = #PIEC_MIN_RADIUS ;Mimimalgröße setzen
EndIf
Width = Radius + #PIEC_FACTOR ;Bildgröße festlegen
Height = Width ;Höhe = Breite (nur da um eventuelle Änderungen zu vereinfachen)
*PieChart = AllocateMemory(SizeOf(PIEC_STRUCT)) ;Speicher reservieren
If *PieChart
*PieChart\Flag = Flag ;Parameter in den Speicher übertragen
*PieChart\Radius = Radius / 2
*PieChart\X = *PieChart\Radius + #PIEC_FACTOR / 2
*PieChart\Y = *PieChart\X
*PieChart\Image = CreateImage(#PB_Any,Width,Height) ;Bild erstellen
If *PieChart\Image
*PieChart\Gadget = ImageGadget(#PB_Any,X,Y,Width,Height,0) ;Bild Container erstellen
If *PieChart\Gadget
*PieChart\GadgetList = ListIconGadget(#PB_Any,X + Width,Y,#PIEC_LIST_WIDTH,Height,#Null$,25) ;Liste erstellen
If *PieChart\GadgetList
AddGadgetColumn(*PieChart\GadgetList,1,Name,#PIEC_COLUMN_NAME_WIDTH)
AddGadgetColumn(*PieChart\GadgetList,2,#PIEC_COLUMN_VALUE,#PIEC_COLUMN_VALUE_WIDTH)
AddGadgetColumn(*PieChart\GadgetList,3,#PIEC_COLUMN_PERCENT,#PIEC_COLUMN_PERCENT_WIDTH)
If Draw(*PieChart)
ProcedureReturn *PieChart ;Erstellte Struktur zurückgeben
EndIf
EndIf
FreeGadget(*PieChart\Gadget) ;Alle Resourcen freigeben
EndIf
FreeImage(*PieChart\Image)
EndIf
FreeMemory(*PieChart)
EndIf
EndProcedure
Procedure.i Add(*PieChart.PIEC_STRUCT,Name.s,Value.d,Color.l)
Protected *PieChartEntryOld.PIEC_ENTRY_STRUCT
Protected *PieChartEntry.PIEC_ENTRY_STRUCT
If *PieChart And Not Value < 0 ;Wert darf nicht kleiner sein als 0!
If *PieChart\FirstEntry ;Ist schon ein Eintrag vorhanden?
*PieChartEntry = *PieChart\FirstEntry
While *PieChartEntry ;Durch die (verknüpfte) Liste gehen um einen freien Platz zu finden
If Not *PieChartEntry\NextEntry
*PieChartEntryOld = *PieChartEntry
*PieChartEntry\NextEntry = AllocateMemory(SizeOf(PIEC_ENTRY_STRUCT)) ;Speicher für einen neuen Eintrag reservieren
If *PieChartEntry\NextEntry
*PieChartEntry = *PieChartEntry\NextEntry ;Parameter in den Speicher übertragen
*PieChartEntry\Name = Name
*PieChartEntry\Value = Value
*PieChartEntry\Color = Color
*PieChartEntry\Image = CreateImage(#PB_Any,16,16,24) ;Bild (Icon) erstellen
If *PieChartEntry\Image
If DrawIco(*PieChartEntry) ;Icon Zeichnen
*PieChart\Summ + *PieChartEntry\Value
If Draw(*PieChart) = #True
ProcedureReturn #True
Else
*PieChart\Summ - *PieChartEntry\Value
EndIf
EndIf
FreeImage(*PieChartEntry\Image)
EndIf
FreeMemory(*PieChartEntry)
*PieChartEntryOld\NextEntry = #Null
ProcedureReturn #False
EndIf
EndIf
*PieChartEntry = *PieChartEntry\NextEntry
Wend
Else
*PieChart\FirstEntry = AllocateMemory(SizeOf(PIEC_ENTRY_STRUCT)) ;Ersten Eintrag erstellen
If *PieChart\FirstEntry
*PieChart\FirstEntry\Name = Name ;Parameter in den Speicher übertragen
*PieChart\FirstEntry\Value = Value
*PieChart\FirstEntry\Color = Color
*PieChart\FirstEntry\Image = CreateImage(#PB_Any,16,16)
If *PieChart\FirstEntry\Image
If DrawIco(*PieChart\FirstEntry)
If Draw(*PieChart)
*PieChart\Summ = Value
ProcedureReturn #True
Else
*PieChart\Summ = #Null
EndIf
EndIf
FreeImage(*PieChart\FirstEntry\Image)
EndIf
FreeMemory(*PieChart\FirstEntry)
*PieChart\FirstEntry = #Null
ProcedureReturn #False
EndIf
EndIf
EndIf
EndProcedure
Procedure.i Remove(*PieChart.PIEC_STRUCT,Name.s)
Protected *PieChartEntryOld.PIEC_ENTRY_STRUCT
Protected *PieChartEntry.PIEC_ENTRY_STRUCT
If *PieChart
If *PieChart\FirstEntry
*PieChartEntry = *PieChart\FirstEntry
While *PieChartEntry ;Durch die (verknüpfte) Liste gehen um den Eintrag zu finden
If *PieChartEntry\Name = Name
If *PieChartEntry = *PieChart\FirstEntry
*PieChart\FirstEntry = *PieChartEntry\NextEntry
Else
*PieChartEntryOld\NextEntry = *PieChartEntry\NextEntry ;Eintrag aus der Liste entfernen
EndIf
*PieChart\Summ - *PieChartEntry\Value ;Summe korrigieren
If *PieChartEntry\Image
FreeImage(*PieChartEntry\Image) ;Resourcen freigeben
EndIf
FreeMemory(*PieChartEntry)
Draw(*PieChart)
ProcedureReturn #True
EndIf
*PieChartEntryOld = *PieChartEntry
*PieChartEntry = *PieChartEntry\NextEntry
Wend
EndIf
EndIf
EndProcedure
Procedure.i Update(*PieChart.PIEC_STRUCT,Name.s,Value.d) ;Eintrag ändern
Protected *PieChartEntry.PIEC_ENTRY_STRUCT
Protected Buffer.i
If *PieChart And Not Value < 0
If *PieChart\FirstEntry
*PieChartEntry = *PieChart\FirstEntry
While *PieChartEntry
If *PieChartEntry\Name = Name
*PieChart\Summ - *PieChartEntry\Value
*PieChartEntry\Value = Value
*PieChart\Summ + Value
Draw(*PieChart)
ProcedureReturn #True
EndIf
*PieChartEntry = *PieChartEntry\NextEntry
Wend
EndIf
EndIf
EndProcedure
Procedure.i Free(*PieChart.PIEC_STRUCT) ;Alle Resourcen freigeben
Protected *PieChartEntry.PIEC_ENTRY_STRUCT
Protected Buffer.i
If *PieChart
If *PieChart\FirstEntry
*PieChartEntry = *PieChart\FirstEntry
While *PieChartEntry
If *PieChartEntry\Image
FreeImage(*PieChartEntry\Image)
EndIf
Buffer = *PieChartEntry
*PieChartEntry = *PieChartEntry\NextEntry
FreeMemory(Buffer)
Wend
If IsGadget(*PieChart\Gadget)
FreeGadget(*PieChart\Gadget)
EndIf
If IsGadget(*PieChart\GadgetList)
FreeGadget(*PieChart\GadgetList)
EndIf
If *PieChart\Image
FreeImage(*PieChart\Image)
EndIf
FreeMemory(*PieChart)
EndIf
EndIf
EndProcedure
EndModule
Code: Alles auswählen
If OpenWindow(0,0,0,510,180,"MODULE PieChart PIEC",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ButtonGadget(1,400,140,100,25,"Change Entry 3")
PieChart = PIEC::Create(10,10,"Test PieChart!",70,#True)
PIEC::Add(PieChart,"1 Sample Entry",60,RGBA(255,0,0,170))
PIEC::Add(PieChart,"2 Sample Entry",30,RGBA(255,255,0,170))
PIEC::Add(PieChart,"3 Sample Entry",50,RGBA(0,50,255,170))
PIEC::Add(PieChart,"4 Sample Entry",0,RGBA(0,444,5,170))
PIEC::Add(PieChart,"5 Sample Entry",20,RGBA(0,12,5,170))
PIEC::Remove(PieChart,"5 Sample Entry")
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
PIEC::Update(PieChart,"3 Sample Entry",Random(50,10))
EndSelect
ForEver
PIEC::Free(PieChart)
EndIf