Distribution "gadgets"

Share your advanced PureBasic knowledge/code with the community.
Hurga
Enthusiast
Enthusiast
Posts: 148
Joined: Thu Jul 17, 2003 2:53 pm
Contact:

Distribution "gadgets"

Post by Hurga »

I hope the name fits what it does...

Its a couple of procs to create and manage some kind of "trackbargadgets", which together sums up to 100 (percent). Its not perfectly balanced, cos I use sometimes a random method to ditribute the rest...

A pic:
Image

I hope the code is more or less understandable... :-)

Maybe its useful for someone

Code: Select all

; Distribution-gadgets
; coded 2007 by Dostej
; published under the LGPL

; What does it do
; You can create some grouped Progressbar-like "gadgets" for a screen enviroment
; Each group has together a max value of 100.
; If you change one gadget, the others of this group change their values, too


Structure VTGdgt
  Number_L.l
  Group_L.l
  X_Pos_L.l
  Y_Pos_L.l
  Width_L.l
  Height_L.l
  Value_L.l
  ImageNr_L.l
EndStructure
Global NewList DSTGadget.VTGdgt()


Global DSTGadget_Mode_GL.l = 1 ; mode 0: equal  Mode 1: proportional

Global MouseX_GL.l
Global MouseY_GL.l
Global MouseButton_GL.l



Procedure Free_DSTGadget(Number_L.l) ; free the gadget
  
  ForEach DSTGadget()
    If DSTGadget()\Number_L = Number_L
      DeleteElement(DSTGadget())
    EndIf
  Next
  
EndProcedure 

Procedure Create_DSTGadget(Number_L.l, Group_L.l, X_Pos_L.l, Y_Pos_L.l, Width_L.l, Height_L.l, ImageNr_L.l) ; create a new VT gadget
  ; free an other gadget with the same number
  Free_DSTGadget(Number_L)
  
  AddElement(DSTGadget())
  With DSTGadget()
    \Number_L = Number_L
    \Group_L = Group_L
    \X_Pos_L = X_Pos_L
    \Y_Pos_L = Y_Pos_L
    \Width_L = Width_L
    \Height_L = Height_L
    \Value_L = 0
    \ImageNr_L = ImageNr_L
  EndWith
  
EndProcedure 

Procedure Draw_DSTGadgets() ; Draw all DST-gadgets
  
  If StartDrawing(ScreenOutput())
    With DSTGadget()
      ForEach DSTGadget()
        DrawingMode(#PB_2DDrawing_Outlined)
        Box(\X_Pos_L, \Y_Pos_L, \Width_L, \Height_L, $FFFF00) ; #Col_Gadget_Text)
        
        ; draw the image depending on the value given
        w = ((\Width_L-2) * \Value_L) / 100
        If w > 0
          DrawImage(ImageID(\ImageNr_L), \X_Pos_L + 1, \Y_Pos_L + 1, w, \Height_L - 2)
        EndIf
      Next
    EndWith
    StopDrawing()
  EndIf
  
EndProcedure

Procedure Distribute_DSTGadgets(Group_L.l, Number_L.l, Diff_L.l) ; distribute the Difference to all gadgets but the "number_L" one
  a = 0
  With DSTGadget()
    ;{ count how many gadgets are in this group
    ForEach DSTGadget()
      If \Group_L = Group_L 
        If \Number_L <> Number_L
          a + 1
        Else
          Value = \Value_L
        EndIf
      EndIf
    Next
    a-1
    ;}
    
    If a > -1 ; if at least one other gadget
      ;{ shuffle all elements of these group in an array
      Dim Temp.POINT(a)
      Count_L = 0
      Sum_L = 0
      ForEach DSTGadget()
        If \Group_L = Group_L And \Number_L <> Number_L
          Temp(Count_L)\x = @DSTGadget()
          Temp(Count_L)\y = \Value_L
          Sum_L + \Value_L
          Count_L + 1
        EndIf
      Next
      ;}
      
      ;{ Distribute the difference
      ; equal
      If DSTGadget_Mode_GL = 1
        ; proportional
        If Sum_L > 0
          f.f = Diff_L / Sum_L
          For x = 0 To a
            Temp(x)\y + (Temp(x)\y * f)
          Next
        Else ; if all other values are 0 -> distribute equal
          Mode = 1
        EndIf
      EndIf
      
      If DSTGadget_Mode_GL = 0 Or Mode = 1
        Rest = Diff_L
        Repeat
          ; calc one share
          d = Int(Rest / (a+1))
          Rest = 0
          For x = 0 To a
            If Temp(x)\y >= d Or d > 0
              n = d
            Else 
              n = Temp(x)\y
            EndIf
            Temp(x)\y + n
            Rest + (d - n)
          Next
        Until Rest = 0
      EndIf
      ;}
      
      ;{ check for value of 100
      n = -100 + Value
      For x = 0 To a
        n + Temp(x)\y
      Next
      
      If n <> 0
        x = Random(a)
        Repeat
          If n > 0
            If Temp(x)\y > 0
              Temp(x)\y - 1
              n - 1
            EndIf
          Else
            If Temp(x)\y < 100
              Temp(x)\y + 1
              n + 1
            EndIf
          EndIf
          x + 1
          If x > a
            x = 0
          EndIf
        Until n = 0
      EndIf
      ;}
      
      ;{ wrote the values back to the LL
      For x = 0 To a
        ChangeCurrentElement(DSTGadget(), Temp(x)\x)
        \Value_L = Temp(x)\y
      Next
      ;}
    EndIf
  EndWith
  
EndProcedure 

Procedure.l GetValue_DSTGadget(Number_L.l) ; returns the value of the gadget
  Back_L.l
  
  ForEach DSTGadget()
    If DSTGadget()\Number_L = Number_L
      Back_L = DSTGadget()\Value_L
      Break
    EndIf
  Next
  
  ProcedureReturn Back_L
EndProcedure 
Procedure.l SetValue_DSTGadget(Number_L.l, Value_L.l) ; set the value of the gadget and change the other ones
  Back_L.l
  
  ForEach DSTGadget()
    If DSTGadget()\Number_L = Number_L
      If Value_L < 0
        Value_L = 0
      ElseIf Value_L > 100
        Value_L = 100
      EndIf
      Diff_L = DSTGadget()\Value_L - Value_L
      DSTGadget()\Value_L = Value_L
      Distribute_DSTGadgets(DSTGadget()\Group_L, Number_L, Diff_L)
      Break
    EndIf
  Next
  
  ProcedureReturn Back_L
EndProcedure 

Procedure.l DSTGadgetEvents() ; handle Mouseevents with the DSTGadgets, returns the number of the DSTGadget currently klicked
  Back_L.l = -1
  
  ; check which Gadget is clicked and set the new value
  With DSTGadget()
    ForEach DSTGadget()
      If MouseX_GL >= \X_Pos_L And MouseX_GL <= \X_Pos_L + \Width_L
        If MouseY_GL >= \Y_Pos_L And MouseY_GL <= \Y_Pos_L + \Height_L
          If MouseButton_GL ; if left or right button was pressed
            Back_L = \Number_L
            t = ((MouseX_GL - \X_Pos_L) * 100) / \Width_L
            Diff_L = \Value_L - t ; calc the difference
            \Value_L = t
            Group_L = \Group_L
            Number_L = \Number_L
            Break
          EndIf
        EndIf
      EndIf
    Next
    
    If Back_L <> -1  And Diff_L <> 0 ; a gadget was klicked - set the other values
      Distribute_DSTGadgets(Group_L, Number_L, Diff_L)
    EndIf
  EndWith
  
  ProcedureReturn Back_L 
EndProcedure 


If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse()= 0
  MessageRequester("Fehler", "init") 
  End 
EndIf

If OpenWindow(1, 0, 0, 1024, 768, "", #PB_Window_BorderLess)
  If OpenWindowedScreen(WindowID(1), 0, 0, 1024, 768, 0, 0, 0)
    ; create a mouse
    If CreateSprite(0, 8, 8) 
      If StartDrawing(SpriteOutput(0)) 
        Circle(4, 4, 4, $FFFF80) 
        StopDrawing()
      EndIf 
    EndIf
    
    If CreateImage(1, 198, 18)
      If StartDrawing(ImageOutput(1))
        Box(0, 0, 198, 18, $0080FF)
        StopDrawing()
      EndIf
    EndIf
    
    Create_DSTGadget(1, 1, 100, 200, 200, 20, 1)
    Create_DSTGadget(2, 1, 100, 230, 200, 20, 1)
    Create_DSTGadget(3, 1, 100, 260, 200, 20, 1)
    Create_DSTGadget(4, 1, 100, 290, 200, 20, 1)
    
    ForEach DSTGadget()
      DSTGadget()\Value_L = 25
    Next
    
    
    ;{ Eventloop
    Repeat ; Start of the event loop
      ClearScreen(0)
      
      ExamineMouse()
      MouseX_GL = MouseX()
      MouseY_GL = MouseY()
      MouseButton_GL = MouseButton(1) | MouseButton(2)<<1
      
      GadgetClicked = DSTGadgetEvents() ; handles the gadgets
      If GadgetClicked > -1
        ; show all values
        Debug "used gadget: " + Str(GadgetClicked) + "    new values"
        ForEach DSTGadget()
          Debug DSTGadget()\Value_L
        Next
      EndIf
      Draw_DSTGadgets()
      
      DisplaySprite(0, MouseX_GL, MouseY_GL)
      
      FlipBuffers(0)
      
      
      Delay(30)
      
      ExamineMouse()
      
    Until Event = #PB_Event_CloseWindow Or MouseButton(2) ; End of the event loop
    ;}
  EndIf
EndIf


User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

howdy.

...know I know who's behind that strange nickname.... ;)

"distribution" isn't the correct translation...
"division" or "partition" is better... ;)
(look for "aufteilen" rather that "verteilen" in your dictionary)

KRGDS-KG
oh... and have a nice day.
Hurga
Enthusiast
Enthusiast
Posts: 148
Joined: Thu Jul 17, 2003 2:53 pm
Contact:

Post by Hurga »

Damn...trapped :(
Post Reply