Radio Button tool (on/off) (New)

Here you can link to screenshots and demos etc. of programs made using BBC BASIC
Zaphod
Posts: 78
Joined: Sat 23 Jun 2018, 15:51

Re: Radio Button tool (on/off) (New)

Post by Zaphod » Fri 06 Jul 2018, 02:41

Michael,

I was misled by the subject line. I thought you were designing a Radio button control.
What we have here are check box like controls shaped like a radio button.
In that context my earlier remarks make no sense as we were thinking of different things.
Ciao,

Z

michael
Posts: 15
Joined: Mon 02 Apr 2018, 17:13

Re: Radio Button tool (on/off) (New)

Post by michael » Fri 06 Jul 2018, 03:03

oh I see. Maybe I don't know how a radio button should work.. hmmm .. I did some checking.. ok.. a radio button would normally be in a group and only one of the group could be active.. I will see if I can modify it to be either a check box style or a group of radio buttons working as it is normally used.

Zaphod
Posts: 78
Joined: Sat 23 Jun 2018, 15:51

Re: Radio Button tool (on/off) (New)

Post by Zaphod » Fri 06 Jul 2018, 19:11

Hi, Michael,

Now we agree on what a radio button should do here is a little no frills demo that should work in all flavours of BBC BASIC.

Edit by Z. Perhaps I should add since no one else has that SDL and BB4W have perfectly good libraries for this function of button already. But if you still feel the need to roll your own ...

Code: Select all

      MODE 8
      VDU 5
      OFF

      REM Define buttons and initial state.
      DIM RB{(5) x%, y%, state%, text$}
      DATA 100,100,1,"One",100,200,0,"Two",100,300,0,"Three",100,400,0,"Four",100,500,0,"Five",100,600,0,"Six"

      REM Display buttons
      FOR I%=0 TO DIM(RB{()},1)
        READ RB{(I%)}.x%, RB{(I%)}.y%, RB{(I%)}.state%, RB{(I%)}.text$
        PROCdraw(RB{()},I%)
      NEXT

      REM Check for mouse over button and click
      OldB%=0
      REPEAT
        REM Main program loop
        MOUSE X%,Y%,B%
        IF B%<>OldB% THEN
          IF B%=4 THEN
            REM Mouse just clicked, see if it is for us.
            R%=TRUE
            FOR I%=0 TO DIM(RB{()},1)
              IF ABS(X%-RB{(I%)}.x%)<=20 AND ABS(Y%-RB{(I%)}.y%)<=20 THEN R%=I% : REM Bingo R% is the click target.
            NEXT
            REM now check the status of R%
            IF R% <> TRUE IF RB{(R%)}.state% =0 THEN
              PROCalloff(RB{()})   :REM show all off.
              RB{(R%)}.state%=1    :REM Set new button state to on.
              PROCdraw(RB{()}, R%) :REM Draw that button again.
            ENDIF
          ENDIF
        ENDIF
        OldB%=B%
        WAIT 5
      UNTIL FALSE
      END

      DEF PROCdraw(a{()}, b%)
      LOCAL x%, y%
      x%=a{(b%)}.x% y%=a{(b%)}.y%
      GCOL 7: CIRCLE FILL x%,y%,20
      IF a{(b%)}.state% GCOL0: CIRCLE FILL x%,y%,15
      GCOL 7 :MOVE x%+50,y%+10 :PRINT a{(b%)}.text$
      ENDPROC

      DEF PROCalloff(a{()})
      LOCAL x%, y%, I%
      REM We switch them all off pending the new selection
      FOR I%=0 TO DIM(a{()},1)
        x%=a{(I%)}.x% y%=a{(I%)}.y%
        GCOL 7: CIRCLE FILL x%,y%,20
        a{(I%)}.state%=0
      NEXT
      ENDPROC
It is just one of a myriad ways you could do this. I used an array of structures so it is easy to hold all the control data in an initialization part and not have it hard coded. It is easily changed to have more or fewer controls or even different types of control. Some might argue that a linked list would be better but I decided to save that for another day or others to code. The structure saves the status so you don't have to worry about TINT not working: you can color it anything you want. It uses very little CPU time.

I hope this gives you or others some ideas that you can build on.

UPDATE: I have "improved" this adding the highlighting when there is a mouse over, and separating out the drawing part so that you can easily modify the button shape. It uses more CPU time so I have tried to avoid unnecessary redrawing. Here goes:

Code: Select all

      REM Version 2 'improved?'
      MODE 8
      VDU 5
      OFF

      REM Define buttons and initial state.
      Bsize%=20
      DIM RB{(5) x%, y%, state%, text$}
      DATA 100,600,1,"One",100,500,0,"Two",100,400,0,"Three",100,300,0,"Four",100,200,0,"Five",100,100,0,"Six"

      REM Display buttons
      FOR I%=0 TO DIM(RB{()},1)
        READ RB{(I%)}.x%, RB{(I%)}.y%, RB{(I%)}.state%, RB{(I%)}.text$
        PROCdraw(RB{()},I% ,0, Bsize%)
      NEXT
      OldProd%=0 : OldB%=0 :Last%=TRUE
      REM Check for mouse over button and click
      REPEAT
        REM Main program loop
        MOUSE X%,Y%,B%
        Q%=X%*Y%+B%  :REM Used to see if mouse is changing at all, if it isn't then there is nothing to do...
        IF Q% <> OldProd% THEN
          R%=TRUE
          FOR I%=0 TO DIM(RB{()},1)
            IF ABS(X%-RB{(I%)}.x%)<=Bsize% IF ABS(Y%-RB{(I%)}.y%)<=Bsize% THEN R%=I% : REM  R% is the click target.
          NEXT
          IF R%<>TRUE THEN
            REM we are over control R%
            IF B%<>OldB% IF B%=4 THEN
              REM Button press detected
              IF RB{(R%)}.state% =0 THEN
                REM We clicked on a button that was off.
                PROCalloff(RB{()}, Bsize%)   :REM draw all off and reset state flags.
                RB{(R%)}.state%=1            :REM Set new button state to on.
              ENDIF
            ENDIF
            PROCdraw(RB{()}, R%, 1, Bsize%)  :REM Draw 'mouse over' button in highlight.
            Last%=R%
          ELSE
            IF Last%<>TRUE THEN
              REM We are not over a control so redraw the last highlighted button.
              PROCdraw(RB{()}, Last%, 0, Bsize%)
              Last%=TRUE
            ENDIF
          ENDIF
          OldB%=B%
        ENDIF
        OldProd%=Q%
        WAIT 5
      UNTIL FALSE
      END
      :
      DEF PROCdraw(a{()}, b%, n%, s%) :REM b% is the control ID, n% is highlight (1) or normal (0), s% is button Radius
      LOCAL x%, y%
      x%=a{(b%)}.x% y%=a{(b%)}.y%
      IF n% THEN
        REM Highlight
        GCOL 15: CIRCLE FILL x%,y%,Bsize% :MOVE x%+50,y%+10 :PRINT a{(b%)}.text$
        IF a{(b%)}.state% GCOL1: CIRCLE FILL x%,y%,s%*0.75
      ELSE
        REM Normal
        GCOL 7: CIRCLE FILL x%,y%,Bsize% :MOVE x%+50,y%+10 :PRINT a{(b%)}.text$
        IF a{(b%)}.state% GCOL0: CIRCLE FILL x%,y%,s%*0.75
      ENDIF
      ENDPROC
      :
      DEF PROCalloff(a{()},s%)
      LOCAL I%
      REM We switch last selection off pending the new selection
      FOR I%=0 TO DIM(a{()},1)
        IF a{(I%)}.state%=1 a{(I%)}.state%=0 :PROCdraw(a{()}, I%, 0, s%)
      NEXT
      ENDPROC

Z
Last edited by Zaphod on Mon 09 Jul 2018, 16:44, edited 2 times in total.

Zaphod
Posts: 78
Joined: Sat 23 Jun 2018, 15:51

Re: Radio Button tool (on/off) (New)

Post by Zaphod » Fri 06 Jul 2018, 21:35

Slider Control
In the same vein here is the toggle switch in the Android Slider guise usually used for settings. Clearly you could make a checkbox graphic using the same logic.
To recap you use this type of control if you only have two options and a radio button if you have 3 or more mutually exclusive options. I have not tried to integrate them but the type of control could be added as an extra structure member and the detection and drawing selected based on an individual control type. You could build up the complete user interface and then use the main loop pretty much as it is here to detect all user input.

Code: Select all

      MODE 8
      VDU 5
      OFF

      REM Define buttons and initial state.
      DIM Slide{(5) x%, y%, state%, text$}
      DATA 100,100,1,"One",100,200,0,"Two",100,300,0,"Three",100,400,1,"Four",100,500,0,"Five",100,600,0,"Six"

      REM Display buttons
      FOR I%=0 TO DIM(Slide{()},1)
        READ Slide{(I%)}.x%, Slide{(I%)}.y%, Slide{(I%)}.state%, Slide{(I%)}.text$
        PROCsdraw(Slide{()},I%)
      NEXT
      MOVE 58,670 :PRINT "Off-On"

      REM Check for mouse over button and click
      OldB%=0
      REPEAT
        REM Main program loop
        MOUSE X%,Y%,B%
        IF B%<>OldB% THEN
          IF B%=4 THEN
            REM Mouse just clicked, see if it is for us.
            R%=TRUE
            FOR I%=0 TO DIM(Slide{()},1)
              IF ABS(X%-Slide{(I%)}.x%)<=2*20 AND ABS(Y%-Slide{(I%)}.y%)<=20 THEN R%=I% : REM Bingo R% is the click target.
            NEXT
            REM now check the status of R%
            IF R% <> TRUE THEN
              REM Change state and text if required.
              IF Slide{(R%)}.state% THEN
                Slide{(R%)}.state% =0
              ELSE
                Slide{(R%)}.state% =1     :REM Set new button state.
              ENDIF
              PROCsdraw(Slide{()}, R%)     :REM Draw that button again in new position.
            ENDIF
          ENDIF
        ENDIF
        OldB%=B%
        WAIT 5
      UNTIL FALSE
      END

      DEF PROCsdraw(a{()}, b%)
      LOCAL x%, y%, r%
      x%=a{(b%)}.x% y%=a{(b%)}.y% r%=20
      GCOL 7: CIRCLE FILL x%-r%,y%,r%
      RECTANGLE FILL x%-r%,y%-r%,2*r%
      CIRCLE FILL x%+r%,y%,r%
      IF a{(b%)}.state% GCOL0: CIRCLE FILL x%+r%,y%,r%-2 ELSE GCOL0: CIRCLE FILL x%-r%,y%,r%-2
      GCOL 7 :MOVE x%+50,y%+10 :PRINT a{(b%)}.text$
      ENDPROC

Note that I made the origin of the control the mid point to make the code simpler. It is 40 high by 80 wide and hard coded in.

Z

Post Reply