Page 2 of 2

Posted: Wed Dec 19, 2007 12:54 am
by electrochrisso
I did put a Delay(1) in originally but the progress slowed down to a crawl.
I will have another look at that, might have put it in the wrong spot.

Threading is very new to me.
Which part do I thread, the ProgressCircle Procedure or put the loops into a procedure and thread them. :?
I think that you can only pass one parameter to a thread. :?:

And WaitWindowEvent(1) is a nice idea too case. :)

Posted: Wed Dec 19, 2007 12:18 pm
by srod
Okay, one quick hack later!

Genarally speaking, threads which communicate with GUI elements in the main process can cause major problems. Hence, if I was doing this myself I'd probably create the new window in the thread and use a callback etc. The problem, however, is allowing such things as the user dragging the new window around whilst keeping the loop running. A timer would probably be too slow because the way your code is structured - hence the thread.

Yep, this is far from perfect but is all I have time for right now.

Code: Select all

; 
; Progress Circle by Electrochisso, Use as you wish, PB4 
; 

Global PCimage,dhWnd,gWnd 
Global gDemo1

Procedure ProgressCircleInit(WindowTitle$,MiddleX,MiddleY) 
PCimage = CreateImage(#PB_Any,MiddleX*2,MiddleY*2) 
dhWnd = OpenWindow(#PB_Any,0,0,MiddleX*2,MiddleY*2,WindowTitle$,#PB_Window_WindowCentered,WindowID(0)) 
CreateGadgetList(WindowID(dhWnd)) 
gWnd = ImageGadget(#PB_Any,0,0,MiddleX*2,MiddleY*2,ImageID(PCimage)) 
EndProcedure 

Procedure ProgressCircle(grad,MiddleX,MiddleY,Radius,PCimage,gWnd,IC,Gap,C1,C2,C3,C4,C5,C6) 
  If IsImage(PCImage)
    If StartDrawing(ImageOutput(PCimage)) 
      Box(0,0,MiddleX*2,MiddleY*2,C1) 
      Circle(MiddleX,MiddleY,Radius+1,C2) 
      LineXY(MiddleX,MiddleY,MiddleX+Sin(grad*(2*3.14159265/360))*Radius,MiddleY+Cos(grad*(2*3.14159265/360))*Radius, C3) 
      If IC > 0 
        Circle(MiddleX,MiddleY,Radius-Gap,C4) 
      EndIf 
      a.f=(grad/360)*100 
      DrawText(MiddleX-8,MiddleY-6,RSet(Str(99-a),2,"0"),C5,C6) 
      StopDrawing() 
      SetGadgetState(gWnd,ImageID(PCimage)) 
    EndIf
  EndIf
EndProcedure 

Procedure PC_Demo1(value)
  Protected Count.f, PCwidth, PCheight, InnerCircle, Gap, loop
  PCwidth=60 : PCheight=60 : InnerCircle=0 : Gap=0 
  For loop = 1 To 20000
    Count = (loop/20000)*360  ;Make the count fit into a max of 360 
    ProgressCircle(360-Count,PCwidth,PCheight,PCwidth-2,PCimage,gWnd,InnerCircle,Gap,$0000FF,$00FF00,0,$00FFFF,$FF0000,$00FF00) 
  Next
  If IsWindow(dhWnd)
    SendMessage_(WindowID(dhWnd), #WM_CLOSE, 0,0)
  EndIf
  gDemo1 = #False
EndProcedure


If OpenWindow(0,0,0,320,240,"Progress Circle Demo",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) 
  If CreateGadgetList(WindowID(0)) 
    ButtonGadget(0,5,5,WindowWidth(0)-10,20,"Press here for Progress Demo 1") 
;    ButtonGadget(1,5,30,WindowWidth(0)-10,20,"Press here for Progress Demo 2") 
  Else 
    End 
  EndIf 
  Repeat 
    event = WaitWindowEvent() 
    Select event
      Case #PB_Event_Gadget 
        If EventGadget() = 0 And gDemo1 = #False
          gDemo1=#True
          ProgressCircleInit("Progress Demo 1",60,60) 
          CreateThread(@PC_Demo1(), 0)
        EndIf 
    EndSelect 
  Until event = #PB_Event_CloseWindow 
EndIf 

End

Posted: Thu Dec 20, 2007 2:28 am
by electrochrisso
Thanks for that srod you have given me a good start and direction for implementing the thread. :D

I have made a couple of changes to the first post.
I came across some interesting results using Delay(1) and WaitWindowEvent(1)
If I use the Delay(1) windows cant be moved until progress has finished.
WaitWindowEvent(1) allows windows to be moved and continues counting.
Both Delay(1) and WaitWindowEvent(1) when you move the windows it stops counting until you release the window, then continues counting.
All of these methods reduces processor use to less than 1%.

Posted: Thu Dec 20, 2007 12:37 pm
by srod
When you move a window the system takes over the thread in which the window was created for the duration for which the mouse is captured and thus your loop will effectively be frozen. The solution in these cases is either a callback or a thread etc. :)

Posted: Fri Dec 21, 2007 1:19 am
by electrochrisso
No worries mate, I will use thread for sure, best way to go for a task such as this and thanks again for your help. :D

Posted: Thu Dec 27, 2007 2:07 am
by eJan
Good idea electrochrisso, tweak by srod and i've made some improvements based on first post.
Now the circle values can be added inside Event_Gadget which stores Structure and send it to the thread.

Code: Select all

;
; Progress Circle by Electrochisso, Use as you wish, PB4
;

Global PCimage, dhWnd, gWnd, gDemo1, gDemo2

Structure circle
  PCwidth.l
  PCheight.l
  IC.l
  Gap.l
  C1.l
  C2.l
  C3.l
  C4.l
  C5.l
  C6.l
EndStructure

Procedure ProgressCircleInit(WindowTitle$, MiddleX, MiddleY)
  PCimage = CreateImage(#PB_Any, MiddleX*2, MiddleY*2)
  dhWnd = OpenWindow(#PB_Any, 0, 0, MiddleX*2, MiddleY*2, WindowTitle$, #PB_Window_WindowCentered, WindowID(0))
  CreateGadgetList(WindowID(dhWnd))
  gWnd = ImageGadget(#PB_Any, 0, 0, MiddleX*2, MiddleY*2, ImageID(PCimage))
EndProcedure

Procedure ProgressCircle(grad, MiddleX, MiddleY, Radius, PCimage, gWnd, IC, Gap, C1, C2, C3, C4, C5, C6)
  If IsImage(PCImage)
    If StartDrawing(ImageOutput(PCimage))
      Box(0, 0, MiddleX*2, MiddleY*2, C1)
      Circle(MiddleX, MiddleY, Radius+1, C2)
      LineXY(MiddleX, MiddleY, MiddleX+Sin(grad*(2*3.14159265/360))*Radius, MiddleY+Cos(grad*(2*3.14159265/360))*Radius, C3)
      If IC > 0
        Circle(MiddleX, MiddleY, Radius-Gap, C4)
      EndIf
      a.f=(grad/360)*100
      DrawText(MiddleX-8, MiddleY-6, RSet(Str(99-a), 2, "0"), C5, C6)
      StopDrawing()
      SetGadgetState(gWnd, ImageID(PCimage))
    EndIf
  EndIf
EndProcedure

Procedure PC_Demo(*values.circle)
  Protected Count.f, loop
  With *values
    Protected PCwidth = \PCwidth
    Protected PCheight = \PCheight
    Protected InnerCircle = \IC
    Protected Gap = \Gap
    Protected C1 = \C1
    Protected C2 = \C2
    Protected C3 = \C3
    Protected C4 = \C4
    Protected C5 = \C5
    Protected C6 = \C6
  EndWith
  For loop = 1 To 20000
    Count = (loop/20000)*360  ;Make the count fit into a max of 360
    ProgressCircle(360-Count, PCwidth, PCheight, PCwidth-2, PCimage, gWnd, InnerCircle, Gap, C1, C2, C3, C4, C5, C6)
  Next
  If IsWindow(dhWnd)
    SendMessage_(WindowID(dhWnd), #WM_CLOSE, 0, 0)
  EndIf
  gDemo1 = #False
EndProcedure

If OpenWindow(0, 0, 0, 320, 240, "Progress Circle Demo", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
  If CreateGadgetList(WindowID(0))
    ButtonGadget(0, 5, 5, WindowWidth(0)-10, 20, "Press here for Progress Demo 1")
    ButtonGadget(1, 5, 30, WindowWidth(0)-10, 20, "Press here for Progress Demo 2")
  Else
    End
  EndIf
  Repeat
    event = WaitWindowEvent()
    Select event
      Case #PB_Event_Gadget
        If EventGadget() = 0 And gDemo1 = #False
          gDemo1=#True
          ProgressCircleInit("Progress Demo 1", 60, 60)
          With values.circle
            \PCwidth = 60
            \PCheight = 60
            \IC = 0
            \Gap = 0
            \C1 = $0000FF
            \C2 = $00FF00
            \C3 = 0
            \C4 = $00FFFF
            \C5 = $FF0000
            \C6 = $00FF00
          EndWith
          CreateThread(@PC_Demo(), @values)
        EndIf
        If EventGadget() = 1 And gDemo2 = #False
          gDemo2=#True
          ProgressCircleInit("Progress Demo 2", 120, 120)
          With values.circle
            \PCwidth = 120
            \PCheight = 120
            \IC = 1
            \Gap = 30
            \C1 = $BBBBBB
            \C2 = $B3A84C
            \C3 = $FFFFFF
            \C4 = $0483FB
            \C5 = $FF0000
            \C6 = $0483FB
          EndWith
          CreateThread(@PC_Demo(), @values)
        EndIf
    EndSelect
  Until event = #PB_Event_CloseWindow
EndIf
End

Posted: Thu Dec 27, 2007 2:55 am
by electrochrisso
Nice going eJan, neat code and runs like a charm. :D
I thinks I might make a simple file copy routine and actually put the progress circle to some good use. :)