TimeSpin Gadget - Is there a better/easier way

Just starting out? Need help? Post your questions and find answers here.
Perkin
Enthusiast
Enthusiast
Posts: 504
Joined: Thu Jul 03, 2008 10:13 pm
Location: Kent, UK

TimeSpin Gadget - Is there a better/easier way

Post by Perkin »

I would like a TimeSpin gadget, but with Hours/Mins/Secs/Centis

I've created the following program, utilising 4 spin gadgets, however I would like to know if there is an better/easier way, or an all-in-one gagdet that does what I want

Here's the code

Code: Select all

;TimeSpin Gadget Test - I Need Hours:Mins:Secs:Centis
#SP_Hours=1
#SP_Mins=2
#SP_Secs=3
#SP_Centis=4

Procedure UpdateHours()
  valh.w = GetGadgetState(#SP_Hours)
   If valh=-1
     valh=11
   EndIf
   If valh=12
    valh=0
   EndIf
  SetGadgetState(#SP_Hours,valh) 
  SetGadgetText(#SP_Hours,RSet(Str(valh),2,"0")) 
EndProcedure

Procedure UpdateMinutes()
  valm.w = GetGadgetState(#SP_Mins)
  If valm=-1
    valm=059
    SetGadgetState(#SP_Hours,GetGadgetState(#SP_Hours)-1)
    UpdateHours()
  EndIf
  If valm=60
    valm=0
    SetGadgetState(#SP_Hours,GetGadgetState(#SP_Hours)+1)
    UpdateHours()
  EndIf
  SetGadgetState(#SP_Mins,valm) 
  SetGadgetText(#SP_Mins,RSet(Str(valm),2,"0")) 
EndProcedure

Procedure UpdateSeconds()
  vals.w = GetGadgetState(#SP_Secs)
  If vals=-1
    vals=059
    SetGadgetState(#SP_Mins,GetGadgetState(#SP_Mins)-1)
    UpdateMinutes()
  EndIf
  If vals=60
    vals=0
    SetGadgetState(#SP_Mins,GetGadgetState(#SP_Mins)+1)
    UpdateMinutes()
  EndIf
  SetGadgetState(#SP_Secs,vals) 
  SetGadgetText(#SP_Secs,RSet(Str(vals),2,"0")) 
EndProcedure

Procedure UpdateCentis()
  valc.w = GetGadgetState(#SP_Centis)
  If valc=-1
    valc=099
    SetGadgetState(#SP_Secs,GetGadgetState(#SP_Secs)-1)
    UpdateSeconds()
  EndIf
  If valc=100
    valc=0
    SetGadgetState(#SP_Secs,GetGadgetState(#SP_Secs)+1)
    UpdateSeconds()
  EndIf
  SetGadgetState(#SP_Centis,valc) 
  SetGadgetText(#SP_Centis,RSet(Str(valc),2,"0")) 
EndProcedure


If OpenWindow(0, 0, 0, 200, 70, "TimeSpin Gadget Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
  SpinGadget(#SP_Hours, 20, 20, 30, 20, -1, 12, #PB_Spin_ReadOnly | #PB_Spin_Numeric) 
  SetGadgetState (#SP_Hours, 0) 
  SetGadgetText(#SP_Hours, "00") 
  SpinGadget(#SP_Mins, 60, 20, 30, 20, -1, 60, #PB_Spin_ReadOnly | #PB_Spin_Numeric) 
  SetGadgetState (#SP_Mins, 0) 
  SetGadgetText(#SP_Mins, "00") 
  SpinGadget(#SP_Secs, 100, 20, 30, 20, -1, 60, #PB_Spin_ReadOnly | #PB_Spin_Numeric) 
  SetGadgetState (#SP_Secs, 0) 
  SetGadgetText(#SP_Secs, "00") 
  SpinGadget(#SP_Centis, 140, 20, 30, 20, -1, 100, #PB_Spin_ReadOnly | #PB_Spin_Numeric) 
  SetGadgetState (#SP_Centis, 0) 
  SetGadgetText(#SP_Centis, "00") 
  
  Repeat 
    event = WaitWindowEvent() 
    If event = #PB_Event_Gadget
      Select EventGadget()
      Case #SP_Hours 
        UpdateHours()
      Case #SP_Mins 
        UpdateMinutes()
      Case #SP_Secs 
        UpdateSeconds()
      Case #SP_Centis 
        UpdateCentis()
      EndSelect
    EndIf 
    
  Until event = #PB_Event_CloseWindow 
EndIf
I'm also going to add the required seperators, and info etc, but you only need the above to see what I would like.

Any thoughts?
Ollivier
Enthusiast
Enthusiast
Posts: 281
Joined: Mon Jul 23, 2007 8:30 pm
Location: FR

Post by Ollivier »

Is good?

Code: Select all

;TimeSpin Gadget Test - I Need Hours:Mins:Secs:Centis 
Enumeration
  #SP_Hours=1
  #SP_Mins
  #SP_Secs
  #SP_Centis
EndEnumeration
Global Dim SP_Max(4)
SP_Max(1) = 11
SP_Max(2) = 59
SP_Max(3) = 59
SP_Max(4) = 99
Procedure UpDate(Object.L)
  Protected Change.L
  Value.W = GetGadgetState(Object) 
  If Value < 0
    Value + (SP_Max(Object) + 1): Change = -1
  EndIf
  If Value > SP_Max(Object)
    Value - (SP_Max(Object) + 1): Change = 1    
  EndIf
  SetGadgetState(Object, Value)
  SetGadgetText(Object, RSet(Str(Value), 2, "0") )
  If Change And Object > #SP_Hours
    SetGadgetState(Object - 1, GetGadgetState(Object - 1) + Change)
    UpDate(Object - 1)
  EndIf
EndProcedure
If OpenWindow(0, 0, 0, 200, 70, "TimeSpin Gadget Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
  For i = #SP_Hours To #SP_Hours + 3
    SpinGadget(i, 20 + 40 * (i - #SP_Hours), 20, 30, 20, -1, SP_Max(i) + 1, #PB_Spin_ReadOnly | #PB_Spin_Numeric) 
    SetGadgetState (i, 0) 
    SetGadgetText(i, "00") 
  Next
  Repeat 
    event = WaitWindowEvent() 
    If event = #PB_Event_Gadget 
      UpDate(EventGadget() )
    EndIf     
  Until event = #PB_Event_CloseWindow 
EndIf 
Perkin
Enthusiast
Enthusiast
Posts: 504
Joined: Thu Jul 03, 2008 10:13 pm
Location: Kent, UK

Post by Perkin »

That does what I want :) , but I would, if possible, have just one gadget which does the same thing, rather than using the four gadgets (as I am going to need four of these on a panel - 16 spin gadgets in all, I'd rather have just four of the combined gadgets).

Is there a Single gadget (or a modified one)which can do what is required.
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

With a dategadget you get hours / minutes / seconds, but no milliseconds.

Code: Select all

Enumeration
  #Window_0
EndEnumeration
Enumeration
  #Window_0_Date_0
EndEnumeration
Define.l Event, EventWindow, EventGadget, EventType, EventMenu
Procedure OpenWindow_Window_0()
  If OpenWindow(#Window_0, 450, 200, 400, 400, "Window_0", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_TitleBar)
    If CreateGadgetList(WindowID(#Window_0))
      ; DateGadget(#Window_0_Date_0, 110, 40, 110, 25, "%hh:%ii:%ss", Date(), #PB_Date_UpDown) ; -> no seconds !?
      DateGadget(#Window_0_Date_0, 110, 40, 110, 25, "", Date(), #PB_Date_UpDown)
      SetWindowLong_(GadgetID(#Window_0_Date_0), #GWL_STYLE, GetWindowLong_(GadgetID(#Window_0_Date_0), #GWL_STYLE) | #DTS_TIMEFORMAT)
    EndIf
  EndIf
EndProcedure

OpenWindow_Window_0()

Repeat
  Event = WaitWindowEvent()
  Select Event
    Case #PB_Event_CloseWindow
      EventWindow = EventWindow()
      If EventWindow = #Window_0
        CloseWindow(#Window_0)
        Break
      EndIf
  EndSelect
ForEver
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
Perkin
Enthusiast
Enthusiast
Posts: 504
Joined: Thu Jul 03, 2008 10:13 pm
Location: Kent, UK

Post by Perkin »

gnozal - I've seen the dategadget, however do require the milliseconds units as well, that's why I'm looking for a modified/custom gadget.

I've got a couple of routines which convert hh:mm:ss:cc (string) into millis(long) and back again, but would like a gadget allowing easy altering of time (including the millisecs)
Foz
Addict
Addict
Posts: 1359
Joined: Tue Nov 13, 2007 12:42 pm
Location: Manchester, UK

Post by Foz »

Check this out - maybe it'll help you out:

http://www.purebasic.fr/english/viewtop ... 122#247122
Ollivier
Enthusiast
Enthusiast
Posts: 281
Joined: Mon Jul 23, 2007 8:30 pm
Location: FR

Post by Ollivier »

There is no lots of changes to do to have the 16 gadgets. PerkinRef contains the No of the first gadget if you don't want they start at #0

Code: Select all

; TimeSpin Gadget Test - I Need Hours:Mins:Secs:Centis 
Enumeration 
  #SP_Hours
  #SP_Mins 
  #SP_Secs 
  #SP_Centis 
EndEnumeration 
Structure OBJECT
  Type.L
EndStructure
Global Dim SP_Max(3)
Global Dim Object.OBJECT(15)
Global PerkinRef.L
PerkinRef = 0 ; Gadget numero start at #0 (Here, it finish at #0 + 15 = #15)
SP_Max(0) = 11 
SP_Max(1) = 59 
SP_Max(2) = 59 
SP_Max(3) = 99 
Procedure UpDate(Object.L)
  If Object => PerkinRef And Object <= PerkinRef + 15
    ObjectType = (Object - PerkinRef) & 3
  EndIf
  Protected Change.L 
  Value.W = GetGadgetState(Object) 
  If Value < 0 
    Value + (SP_Max(ObjectType) + 1): Change = -1 
  EndIf 
  If Value > SP_Max(ObjectType) 
    Value - (SP_Max(ObjectType) + 1): Change = 1    
  EndIf 
  SetGadgetState(Object, Value) 
  SetGadgetText(Object, RSet(Str(Value), 2, "0") ) 
  If Change And ObjectType <> #SP_Hours 
    SetGadgetState(Object - 1, GetGadgetState(Object - 1) + Change) 
    UpDate(Object - 1) 
  EndIf 
EndProcedure 
If OpenWindow(0, 0, 0, 200, 150, "TimeSpin Gadget Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
  PerkinRef = 0
  For j = 0 To 3
    Base = PerkinRef + j << 2
    For i = 0 To 3 
      SpinGadget(Base + i, 20 + 40 * i, 20 + 32 * j, 30, 20, -1, SP_Max(i) + 1, #PB_Spin_ReadOnly | #PB_Spin_Numeric) 
      Object(Base + i)\Type = i
      SetGadgetState (Base + i, 0) 
      SetGadgetText(Base + i, "00") 
    Next 
  Next
  Repeat 
    event = WaitWindowEvent() 
    If event = #PB_Event_Gadget 
      UpDate(EventGadget() ) 
    EndIf      
  Until event = #PB_Event_CloseWindow 
EndIf 
User avatar
dhouston
Enthusiast
Enthusiast
Posts: 430
Joined: Tue Aug 21, 2007 2:44 pm
Location: USA (Cincinnati)
Contact:

Post by dhouston »

Perkin wrote:gnozal - I've seen the dategadget, however do require the milliseconds units as well, that's why I'm looking for a modified/custom gadget.
Some months back I made a feature request for a general purpose multi-field spin control (like the date gadget) but there was no response. As I recall, my need was for longitude latitude, time zone with 2 fields each.
Perkin
Enthusiast
Enthusiast
Posts: 504
Joined: Thu Jul 03, 2008 10:13 pm
Location: Kent, UK

Post by Perkin »

Thanks to all

Foz - looked at topic, couldn't get my head round it :?
I'll re-read it and try some experiments when I get some time.

Ollivier - I'll be using this till I can sort out something better (i.e. One gadget each not the set of four)

dhouston - saw that topic whilst searching for help over this, it looked to have been answered, maybe re-requesting help again - bump the topic.

Any other ideas?
Foz
Addict
Addict
Posts: 1359
Joined: Tue Nov 13, 2007 12:42 pm
Location: Manchester, UK

Post by Foz »

Enjoy! :D

Code: Select all

EnableExplicit

;{- private variables
Global __TimerSpinGadget_TotalNumber.l
Global Dim __TimerSpinGadget_spnControl.l(3, 0)

Global Dim __TimerSpinGadget_SP_Max(3)
__TimerSpinGadget_SP_Max(0) = 23
__TimerSpinGadget_SP_Max(1) = 59
__TimerSpinGadget_SP_Max(2) = 59
__TimerSpinGadget_SP_Max(3) = 99
;}

;{- private procedures
Procedure __TimerSpinGadget_Update(pTimerSpinControlID.l, pSpinGadgetID.l)
  Protected Change.L
  Protected Value.W = GetGadgetState(__TimerSpinGadget_spnControl(pTimerSpinControlID, pSpinGadgetID))
  
  If Value<0
    Value + (__TimerSpinGadget_SP_Max(pTimerSpinControlID) + 1) : Change = -1
  EndIf
  
  Protected MaxValue.l = GetGadgetAttribute(__TimerSpinGadget_spnControl(pTimerSpinControlID, pSpinGadgetID), #PB_Spin_Maximum)-1
  
  If Value>__TimerSpinGadget_SP_Max(pTimerSpinControlID)
    Value-(__TimerSpinGadget_SP_Max(pTimerSpinControlID) + 1) : Change = 1
  EndIf
  
  SetGadgetState(__TimerSpinGadget_spnControl(pTimerSpinControlID, pSpinGadgetID), Value)
  SetGadgetText(__TimerSpinGadget_spnControl(pTimerSpinControlID, pSpinGadgetID), RSet(Str(Value), 2, "0") )
  
  If Change And pTimerSpinControlID>0
    SetGadgetState(__TimerSpinGadget_spnControl(pTimerSpinControlID-1, pSpinGadgetID), GetGadgetState(__TimerSpinGadget_spnControl(pTimerSpinControlID-1, pSpinGadgetID)) + Change)
    __TimerSpinGadget_Update(pTimerSpinControlID-1, pSpinGadgetID)
  EndIf
EndProcedure
;}
;{ public procedures
Procedure TimerSpinGadget_SetNumberOfInstances(pCount.l)
  __TimerSpinGadget_TotalNumber = pCount-1
  
  ReDim __TimerSpinGadget_spnControl(3, __TimerSpinGadget_TotalNumber)
  
EndProcedure

Procedure TimerSpinGadget_New(pGadgetArea.l, pOffsetX.l, pOffsetY.l, pInstanceNumber.l = 0)
  UseGadgetList(pGadgetArea)
  
  Protected i.l
  For i = 0 To 3
    __TimerSpinGadget_spnControl(i, pInstanceNumber) = SpinGadget(#PB_Any, pOffsetX + 32*(i), pOffsetY, 30, 20, -1, __TimerSpinGadget_SP_Max(i) + 1, #PB_Spin_ReadOnly | #PB_Spin_Numeric)
    SetGadgetState(__TimerSpinGadget_spnControl(i, pInstanceNumber), 0)
    SetGadgetText(__TimerSpinGadget_spnControl(i, pInstanceNumber), "00")
  Next
EndProcedure

Procedure TimerSpinGadget_Release()
  Protected i.l, j.l
  For j = 0 To __TimerSpinGadget_TotalNumber
    For i = 0 To 3
      FreeGadget(__TimerSpinGadget_spnControl(i, j))
    Next
  Next
EndProcedure

Procedure TimerSpinGadget_Event(Event.l, WindowID.l, GadgetID.l, EventType.l)
  If event = #PB_Event_Gadget
    Protected i.l, j.l
    For j = 0 To __TimerSpinGadget_TotalNumber
      For i = 0 To 3
        If __TimerSpinGadget_spnControl(i, j) = GadgetID
          __TimerSpinGadget_Update(i, j)
        EndIf
      Next
    Next
  EndIf
EndProcedure

Procedure.s TimerSpinGadget_GetTime(pInstanceNumber.l)
  Protected rv.s = ""
  rv + GetGadgetText(__TimerSpinGadget_spnControl(0, pInstanceNumber)) + ":"
  rv + GetGadgetText(__TimerSpinGadget_spnControl(1, pInstanceNumber)) + ":"
  rv + GetGadgetText(__TimerSpinGadget_spnControl(2, pInstanceNumber)) + ":"
  rv + GetGadgetText(__TimerSpinGadget_spnControl(3, pInstanceNumber))
  
  ProcedureReturn rv
EndProcedure
;}

; This section can be in another file, just include the code above as an XInclude
CompilerIf #PB_Compiler_Debugger
  OpenWindow(0, 216, 0, 300, 150, "New window ( 0 )", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar | #PB_Window_WindowCentered)
  
  TimerSpinGadget_SetNumberOfInstances(4)
  TimerSpinGadget_New(WindowID(0), 10, 10, 0)
  TimerSpinGadget_New(WindowID(0), 150, 10, 1)
  TimerSpinGadget_New(WindowID(0), 10, 50, 2)
  TimerSpinGadget_New(WindowID(0), 150, 50, 3)
  
  Define btnListValues.l = ButtonGadget(#PB_Any, 80, 90, 100, 24, "Display Values")
  
  Define Event
  Define WindowID
  Define GadgetID
  Define EventType
  
  Repeat ; Start of the event loop
    
    Event = WaitWindowEvent() ; This line waits until an event is received from Windows
    WindowID = EventWindow() ; The Window where the event is generated, can be used in the gadget procedures
    GadgetID = EventGadget() ; Is it a gadget event?
    EventType = EventType() ; The event type
    
    TimerSpinGadget_Event(Event, WindowID, GadgetID, EventType)
    
    If Event = #PB_Event_Gadget
      If GadgetID = btnListValues
        Define display.s = ""
        display + TimerSpinGadget_GetTime(0) + Chr(13) + Chr(10)
        display + TimerSpinGadget_GetTime(1) + Chr(13) + Chr(10)
        display + TimerSpinGadget_GetTime(2) + Chr(13) + Chr(10)
        display + TimerSpinGadget_GetTime(3)
        
        MessageRequester("", display)
        
        GadgetID = 0
      EndIf
    EndIf
  
Until Event = #PB_Event_CloseWindow
TimerSpinGadget_Release()

CompilerEndIf
Perkin
Enthusiast
Enthusiast
Posts: 504
Joined: Thu Jul 03, 2008 10:13 pm
Location: Kent, UK

Post by Perkin »

@Foz - Brilliant, :D works well, and each is a set, Thanks a lot for this.

I re-read tthe topic you posted earlier, still confuses me :? , I'll keep trying till I understand it, just out of sheer bloody-mindedness :lol:

Thanks
:D Perkin :D
Perkin
Enthusiast
Enthusiast
Posts: 504
Joined: Thu Jul 03, 2008 10:13 pm
Location: Kent, UK

Post by Perkin »

I've made a couple of changes to Foz's code

Ive Changed

'TimerSpinGadget_GetTime' --> 'TimerSpinGadget_GetTimeS'

Added

'__TimerSpinGadget_SP_Mult(3)' (Array of multipliers to get millis)
'TimerSpinGadget_GetTimeL' (Returns milliseconds - removes need for conversion routine)

Here's the code added :-

Code: Select all

Global Dim __TimerSpinGadget_SP_Mult(3) 
__TimerSpinGadget_SP_Mult(0) = 3600000 
__TimerSpinGadget_SP_Mult(1) = 60000 
__TimerSpinGadget_SP_Mult(2) = 1000 
__TimerSpinGadget_SP_Mult(3) = 10 

; -Return value in millis
Procedure.l TimerSpinGadget_GetTimeL(pInstanceNumber.l) 
  Protected rv.l = 0 
  rv + GetGadgetState(__TimerSpinGadget_spnControl(0, pInstanceNumber)) * __TimerSpinGadget_SP_Mult(0)
  rv + GetGadgetState(__TimerSpinGadget_spnControl(1, pInstanceNumber)) * __TimerSpinGadget_SP_Mult(1) 
  rv + GetGadgetState(__TimerSpinGadget_spnControl(2, pInstanceNumber)) * __TimerSpinGadget_SP_Mult(2)
  rv + GetGadgetState(__TimerSpinGadget_spnControl(3, pInstanceNumber)) * __TimerSpinGadget_SP_Mult(3)
  
  ProcedureReturn rv 
EndProcedure 
I also added a few lines to the display reslts event, they now read (with the other four lines included)

Code: Select all

        display + TimerSpinGadget_GetTimeS(0) + Chr(13) + Chr(10) 
        display + TimerSpinGadget_GetTimeS(1) + Chr(13) + Chr(10) 
        display + TimerSpinGadget_GetTimeS(2) + Chr(13) + Chr(10) 
        display + TimerSpinGadget_GetTimeS(3)  + Chr(13) + Chr(10)
        display + Str(TimerSpinGadget_GetTimeL(0)) + Chr(13) + Chr(10) 
        display + Str(TimerSpinGadget_GetTimeL(1)) + Chr(13) + Chr(10) 
        display + Str(TimerSpinGadget_GetTimeL(2)) + Chr(13) + Chr(10) 
        display + Str(TimerSpinGadget_GetTimeL(3))
Foz
Addict
Addict
Posts: 1359
Joined: Tue Nov 13, 2007 12:42 pm
Location: Manchester, UK

Post by Foz »

Community code - building on the shoulders of others :)
Perkin
Enthusiast
Enthusiast
Posts: 504
Joined: Thu Jul 03, 2008 10:13 pm
Location: Kent, UK

Post by Perkin »

Foz wrote
Community code - building on the shoulders of others
Building on the shoulders of the few (Foz, srod, gnozal to name just 3, I know there's more :) )
%101010 = $2A = 42
Foz
Addict
Addict
Posts: 1359
Joined: Tue Nov 13, 2007 12:42 pm
Location: Manchester, UK

Post by Foz »

Well, you brought the idea.
Ollivier brought a trimmed version.
I separated it into a "user control"
You have extended it.

That's four steps and 3 users to get it to where it is now :)
Post Reply