Improved SpinGadget dealing with decimal values

Share your advanced PureBasic knowledge/code with the community.
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Improved SpinGadget dealing with decimal values

Post by chi »

For a 3D-Editor I needed a more flexible way to treat SpinGadgets than the usual one can provide.
So I came up with this fake SpinGadget version which works with regular expression and deals with different inputs
like: double values with 2-10 decimals | restricted to 0-9,.- | update on lostfocus | ...

Please let me know if you´d change or improve something! Thx :D

Code: Select all

; English forum: http://www.purebasic.fr/english/viewtopic.php?f=12&t=46669
; Author: chi
; Date: 18. June 2011
; OS: Windows
; Demo: No


;////////////////////////////////////////////////////////
;//  Improved SpinGadget dealing with decimal values  //
;//////////////////////////////////////////////////////


EnableExplicit


;{ Enum
  Enumeration
    #Win
    #Return
    
    #Txt_1
    #Str_1
    #Spn_1
    
    #Txt_2
    #Str_2
    #Spn_2
    
    #Txt_3
    #Str_3
    #Spn_3
    
    #RegExp
    
    #PB_EventType_SpinUp   = 1
    #PB_EventType_SpinDown = -1
  EndEnumeration
;}

;{ Inits
  Define event.i
  Define eventgadget.i
  
  Global decimalplaces.i = 4  ; min = 2 / max = 10
  
  Declare GetStringCursorPos( gadget )
  Declare String_Event( gadget )
  Declare Enter_Event( gadget )
  Declare Spin_Event( gadget )
  Declare Debug_Gadget( gadget.i, text.s )
;}

;{ Window
  OpenWindow( #Win, 0, 0, 165, 96, "Demo", #PB_Window_SystemMenu|#PB_Window_ScreenCentered )
  AddKeyboardShortcut( #Win, #PB_Shortcut_Return, #Return )
  
  TextGadget( #Txt_1, 10, 18, 35, 19, "Pos X :" )
  StringGadget( #Str_1, 46, 15, 100, 19, StrD( -1, decimalplaces ), #ES_RIGHT )
  SpinGadget( #Spn_1, 147, 14, 9, 21, -1, 1, #PB_Spin_Numeric )
  
  TextGadget( #Txt_2, 10, 43, 35, 19, "Pos Y :" )
  StringGadget( #Str_2, 46, 40, 100, 19, StrD( 0, decimalplaces ), #ES_RIGHT )
  SpinGadget( #Spn_2, 147, 39, 9, 21, -1, 1, #PB_Spin_Numeric )
  
  TextGadget( #Txt_3, 10, 68, 35, 19, "Pos Z :" )
  StringGadget( #Str_3, 46, 65, 100, 19, StrD( 1, decimalplaces ), #ES_RIGHT )
  SpinGadget( #Spn_3, 147, 64, 9, 21, -1, 1, #PB_Spin_Numeric )
;}

;{ RegExp
  CreateRegularExpression( #RegExp, "^[-]?\d*[.,]?\d*$" )
;}

;{ EventLoop
  Repeat
    event = WaitWindowEvent()
    Select event
        
      Case #PB_Event_Menu
        Select EventMenu()
            
          Case #Return
            Enter_Event( eventgadget )
            
        EndSelect
        
      Case #PB_Event_Gadget
        Select EventGadget()
            
          Case #Str_1
            String_Event( #Str_1 )
            
          Case #Str_2
            String_Event( #Str_2 )
            
          Case #Str_3
            String_Event( #Str_3 )
            
          Case #Spn_1
            Spin_Event( #Spn_1 )
            
          Case #Spn_2
            Spin_Event( #Spn_2 )
            
          Case #Spn_3
            Spin_Event( #Spn_3 )
            
        EndSelect
        
    EndSelect
  Until event = #PB_Event_CloseWindow
  End
;}


Procedure GetStringCursorPos( gadget )
  Protected min.i, max.i
  SendMessage_( GadgetID( gadget ), #EM_GETSEL, @min, @max )
  ProcedureReturn max - SendMessage_( GadgetID( gadget ), #EM_LINEINDEX, SendMessage_( GadgetID( gadget ), #EM_LINEFROMCHAR, min, 0 ), 0 )
EndProcedure

Procedure String_Event( gadget )
  Protected last.s, text.s, deci.i, cpos.i
  Shared eventgadget.i
  Static lasttext.s
  Select EventType()
      
    Case #PB_EventType_Focus
      eventgadget = gadget
      lasttext    = StrD( ValD( GetGadgetText( gadget ) ), decimalplaces )
      
    Case #PB_EventType_Change
      cpos = GetStringCursorPos( gadget )
      text = GetGadgetText( gadget )
      If MatchRegularExpression( #RegExp, text ) = 0
        last = Mid( text, cpos, 1 )
        text = RemoveString( text, last, 0, cpos, 1 )
        SetGadgetText( gadget, text )
        SendMessage_( GadgetID( gadget ), #EM_SETSEL, cpos-1, cpos-1 )
      Else
        If FindString( text, ",", 1 ) > 0
          text = ReplaceString( text, ",", "." )
          SetGadgetText( gadget, text )
          SendMessage_( GadgetID( gadget ), #EM_SETSEL, cpos, cpos )
        EndIf
        last = StringField( text, 2, "." )
        If Len( last ) > decimalplaces
          deci = Len( StringField( text, 1, "." ) ) + 1
          deci = cpos - deci
          text = StringField( text, 1, "." ) + "." + Left ( Left( last, deci ) + Right( last, decimalplaces-deci ), decimalplaces )
          SetGadgetText( gadget, text )
          If deci >= decimalplaces
            cpos - 1
          EndIf
          SendMessage_( GadgetID( gadget ), #EM_SETSEL, cpos, cpos )
        EndIf
      EndIf
      
    Case #PB_EventType_LostFocus
      text = StrD( ValD( GetGadgetText( gadget ) ), decimalplaces )
      SetGadgetText( gadget, text )
      If lasttext <> text
        Debug_Gadget( gadget, text)
      EndIf
      
  EndSelect
EndProcedure

Procedure Enter_Event( gadget )
  Protected text.s
  text = StrD( ValD( ReplaceString( GetGadgetText( gadget ), ",", "." ) ), decimalplaces )
  SetGadgetText( gadget, text )
  SetGadgetState( gadget+1, 0 )
  SetActiveGadget( gadget+1 )
EndProcedure

Procedure Spin_Event( gadget )
  Protected value.d
  Select EventType()
      
    Case #PB_EventType_SpinUp
      value = ValD( ReplaceString( GetGadgetText( gadget-1 ), ",", "." ) )
      If value + 0.1 > 0 And value + 0.1 < 0.1
        value = Abs( value )
      Else
        value + 0.1
      EndIf
      SetGadgetText( gadget-1, StrD( value , decimalplaces ) )
      SetGadgetState( gadget, 0 )
      SetActiveGadget( gadget )
      Debug_Gadget( gadget-1, GetGadgetText( gadget-1 ) )
      
    Case #PB_EventType_SpinDown
      value = ValD( ReplaceString( GetGadgetText( gadget-1 ), ",", "." ) )
      If value - 0.1 < 0 And value - 0.1 > -0.1
        value = -value
      Else
        value - 0.1
      EndIf
      SetGadgetText( gadget-1, StrD( value, decimalplaces ) )
      SetGadgetState( gadget, 0 )
      SetActiveGadget( gadget )
      Debug_Gadget( gadget-1, GetGadgetText( gadget-1 ) )
      
  EndSelect
EndProcedure

Procedure Debug_Gadget( gadget.i, text.s )
  Debug GetGadgetText( gadget-1 ) + " " + GetGadgetText( gadget )
EndProcedure

Last edited by chi on Mon Jun 20, 2011 2:32 am, edited 3 times in total.
Et cetera is my worst enemy
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Improved SpinGadget dealing with decimal values

Post by IdeasVacuum »

Nice implementation 8)

Line 141, FindString() has a parameter missing (PB4.51 & up)
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: Improved SpinGadget dealing with decimal values

Post by chi »

Thanks, fixed

:arrow: (with pb4.6beta3 the startposition of findstring is an optional parameter)
Et cetera is my worst enemy
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: Improved SpinGadget dealing with decimal values

Post by chi »

fixed reg.expression too... much shorter now!
Et cetera is my worst enemy
Post Reply