Author Topic: Basic graphical pick from list function  (Read 4757 times)

0 Members and 1 Guest are viewing this topic.

Offline 191Brian

  • Newbie
  • Posts: 91
    • View Profile
    • My Itch page
Basic graphical pick from list function
« on: March 10, 2021, 02:52:05 pm »
A basic graphical pick from list function demo PickFromList (itemList() As String, xPos As Integer, yPos As Integer) pass the list as an array and an x y cord for the top left corner of the list box use your mouse to select an item it returns the index of the item picked or (array passed ubound) + 1 if none selected

demo uses the forum slpit function to build the list
the function PickFromList uses the UDT button and Terry Ritchie's RectCollide function


Code: QB64: [Select]
  1.  
  2. ' Basic graphical pick from list function demo
  3. ' PickFromList (itemList() As String, xPos As Integer, yPos As Integer)
  4. ' pass the list as an array and an x y cord for the top left corner of the list box
  5. ' it returns the index of the item picked or array ubound + 1 if none selected
  6.  
  7. ' demo uses the forum slpit function to build the list
  8. ' the function PickFromList uses the UDT button and Terry Ritchie's RectCollide function
  9.  
  10.  
  11. Type button
  12.     x As Integer
  13.     y As Integer
  14.     w As Integer
  15.     h As Integer
  16.     no As Integer
  17.     text As String
  18.  
  19.  
  20. ReDim aList(12) As String
  21. Dim itemNo As Integer
  22.  
  23. d = "January,February,March,April,May,June,July,August,September,October,November,December"
  24.  
  25. Split d, ",", aList()
  26.  
  27. Screen _NewImage(800, 600, 32)
  28.  
  29.  
  30.  
  31.     itemNo = PickFromList(aList(), 100, 50)
  32.     Cls
  33.  
  34.     If itemNo <= UBound(alist) Then
  35.         Print "you picked "; aList(itemNo), itemNo
  36.     Else
  37.         Print "you didn't like and of the options presneted"
  38.     End If
  39.  
  40.     Print "Press any key to continue or esc twice to exit"
  41.     Sleep
  42.  
  43.  
  44.  
  45.  
  46.  
  47. Function PickFromList (itemList() As String, xPos As Integer, yPos As Integer)
  48.     Dim fi As Integer
  49.     ReDim itemBtn(UBound(itemlist) + 1) As button
  50.     Dim pickedOne As Integer
  51.     Dim mouseXPos As Integer
  52.     Dim mouseYPos As Integer
  53.     Dim listWidth As Integer
  54.  
  55.  
  56.     PickFromList = 9999
  57.     pickedOne = 0
  58.     listWidth = 0
  59.  
  60.     For fi = 0 To UBound(itemlist) + 1
  61.         itemBtn(fi).x = xPos + 2
  62.         itemBtn(fi).y = yPos + (fi * 16) + 2
  63.         itemBtn(fi).h = _FontHeight
  64.         itemBtn(fi).no = fi
  65.  
  66.         If fi <= UBound(itemlist) Then
  67.             itemBtn(fi).w = _PrintWidth(itemList(fi))
  68.             itemBtn(fi).text = itemList(fi)
  69.         Else
  70.             itemBtn(fi).w = _PrintWidth("<None of the above>")
  71.             itemBtn(fi).text = "<None of the above>"
  72.         End If
  73.         If itemBtn(fi).w > listWidth Then
  74.             listWidth = itemBtn(fi).w
  75.         End If
  76.     Next fi
  77.  
  78.     Line (xPos, yPos)-(xPos + listWidth, yPos + _FontHeight * (UBound(itembtn) + 1)), _RGB32(50), BF
  79.  
  80.     For fi = 0 To UBound(itembtn)
  81.         _PrintString (itemBtn(fi).x, itemBtn(fi).y), itemBtn(fi).text
  82.     Next fi
  83.     Do
  84.  
  85.         While _MouseInput: Wend
  86.         mouseXPos = _MouseX
  87.         mouseYPos = _MouseY
  88.         If _MouseButton(1) Then
  89.             For fi = 0 To UBound(itemBtn)
  90.                 If RectCollide(mouseXPos, mouseYPos, 1, 1, itemBtn(fi).x, itemBtn(fi).y, itemBtn(fi).w, itemBtn(fi).h) Then
  91.                     pickedOne = 1
  92.                     PickFromList = fi
  93.  
  94.                 End If
  95.             Next fi
  96.         End If
  97.     Loop Until pickedOne = 1
  98.  
  99.  
  100. FUNCTION RectCollide (rect1X as integer,rect1Y as integer,rect1Width as integer,rect1Height as integer,_
  101.                       rect2X as integer,rect2Y as integer,rect2Width as integer,rect2Height as integer)
  102.  
  103.     Dim rect1X2 As Integer
  104.     Dim rect1Y2 As Integer
  105.     Dim rect2X2 As Integer
  106.     Dim rect2Y2 As Integer
  107.  
  108.     rect1X2 = rect1X + rect1Width - 1
  109.     rect1Y2 = rect1Y + rect1Height - 1
  110.     rect2X2 = rect2X + rect2Width - 1
  111.     rect2Y2 = rect2Y + rect2Height - 1
  112.  
  113.     RectCollide = 0
  114.     If rect1X2 >= rect2X Then
  115.         If rect1X <= rect2X2 Then
  116.             If rect1Y2 >= rect2Y Then
  117.                 If rect1Y <= rect2Y2 Then
  118.                     RectCollide = -1
  119.                 End If
  120.             End If
  121.         End If
  122.     End If
  123.  
  124.  
  125.  
  126. Sub Split (SplitMeString As String, delim As String, loadMeArray() As String)
  127.     Dim curpos As Long, arrpos As Long, LD As Long, dpos As Long 'fix use the Lbound the array already has
  128.     curpos = 1: arrpos = LBound(loadMeArray): LD = Len(delim)
  129.     dpos = InStr(curpos, SplitMeString, delim)
  130.     Do Until dpos = 0
  131.         loadMeArray(arrpos) = Mid$(SplitMeString, curpos, dpos - curpos)
  132.         arrpos = arrpos + 1
  133.         If arrpos > UBound(loadMeArray) Then ReDim _Preserve loadMeArray(LBound(loadMeArray) To UBound(loadMeArray) + 1000) As String
  134.         curpos = dpos + LD
  135.         dpos = InStr(curpos, SplitMeString, delim)
  136.     Loop
  137.     loadMeArray(arrpos) = Mid$(SplitMeString, curpos)
  138.     ReDim _Preserve loadMeArray(LBound(loadMeArray) To arrpos) As String 'get the ubound correct
  139.  
  140.  
Brian ...

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Basic graphical pick from list function
« Reply #1 on: March 11, 2021, 11:41:44 am »
Well that's interesting, treating a mouse point as a box and recycling code you have for box collisions.

Finding out if a point is inside a box is so easy who would think to make a tool of it? And yet it could be time saver if did have such a tool.

Have you actually tried this for different sized fonts because I am seeing a 16 for a y dim so that is depending on default font @ 8x16 and I am seeing a _FontHeight function being employed?

And what happens when the list has more rows than screen can fit?

Well I am sure it's good for allot of things.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Basic graphical pick from list function
« Reply #2 on: March 11, 2021, 01:04:18 pm »
It certainly works as advertised, but I don't think this method would be my choice for graphics menu builds, but it's always interesting to see different techniques. Since I don't work in graphics, SCREEN 0 only, I might be missing something here. So I'm wondering if this is more a case of, "Just because you can, doesn't mean you should." or if there is a special significance, which would make this technique more elegant than other graphic menu methods.?

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline 191Brian

  • Newbie
  • Posts: 91
    • View Profile
    • My Itch page
Re: Basic graphical pick from list function
« Reply #3 on: March 11, 2021, 01:41:19 pm »
Well that's interesting, treating a mouse point as a box and recycling code you have for box collisions.

Finding out if a point is inside a box is so easy who would think to make a tool of it? And yet it could be time saver if did have such a tool.

Have you actually tried this for different sized fonts because I am seeing a 16 for a y dim so that is depending on default font @ 8x16 and I am seeing a _FontHeight function being employed?

And what happens when the list has more rows than screen can fit?

Well I am sure it's good for allot of things.
Hi bolus

Yes it currently has a few limitations but thought it was reasonably neat light weight cross platform solution. Thanks for pointing out i missed changing the 16 to _fontheight in the ypos calc.I have thoughts on a scrollable version for when the list is to long for the screen size.
Brian ...

Offline 191Brian

  • Newbie
  • Posts: 91
    • View Profile
    • My Itch page
Re: Basic graphical pick from list function
« Reply #4 on: March 11, 2021, 02:09:48 pm »
It certainly works as advertised, but I don't think this method would be my choice for graphics menu builds, but it's always interesting to see different techniques. Since I don't work in graphics, SCREEN 0 only, I might be missing something here. So I'm wondering if this is more a case of, "Just because you can, doesn't mean you should." or if there is a special significance, which would make this technique more elegant than other graphic menu methods.?

Pete

Hi Pete

I am new to QB64 so I am not aware of other cross platform graphic menu methods apart from the excellent Inform but that is quite heavy weight. I will definitely be using it in some of my programs to make them more user friendly especially for those aimed at the younger generation.
Brian ...

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Basic graphical pick from list function
« Reply #5 on: March 11, 2021, 04:13:46 pm »
I like this project so much I tried it myself :)  (v1.5 specially for ReDim's)
Code: QB64: [Select]
  1. _Title "Get Button Menu" 'bplus 2021-03-11
  2. ' B+ 2021-03-11 Rewrite 191Brian list picker  https://www.qb64.org/forum/index.php?topic=3730.msg130862#msg130862
  3. ' assuming default font 8x16
  4.  
  5. 'Globals here, Cap first letters
  6. Type Button
  7.     As Long x, y, w, h
  8.     text As String
  9.     As _Unsigned Long FC, BC
  10.  
  11. Screen _NewImage(800, 620, 32)
  12. _Delay .25 'give screen time to load before
  13.  
  14. 'locals for main event code, keep locals lowercase on first letter
  15. ReDim As Long i, nMonths, nDays, nYears, mx, my, mb
  16. ReDim monthNames$, monthPick$, years$, yearPick$, days$, dayPick$
  17. ReDim months$(1 To 1) '<<<<<<<<<<<< don't need to know in advance the number of items in split sting  but good to start at 1
  18. ReDim monthButtons(1 To 1) As Button
  19. ReDim yearButtons(1 To 1) As Button
  20. ReDim dayButtons(1 To 1) As Button
  21. For i = 1 To 31 'create days and years strings
  22.     If i = 1 Then years$ = TS$(2000 + i) Else years$ = years$ + "," + TS$(2000 + i)
  23.     If i = 1 Then days$ = TS$(i) Else days$ = days$ + "," + TS$(i)
  24. monthNames$ = "January,February,March,April,May,June,July,August,September,October,November,December"
  25. MakeButtons &HFFFF8888, &HFF880000, 300, 0, years$, yearButtons()
  26. MakeButtons &HFF88FF88, &HFF008800, 369, (_Height - 12 * 25) / 2, monthNames$, monthButtons()
  27. MakeButtons &HFF8888FF, &HFF0000FF, 478, 0, days$, dayButtons()
  28. nYears = UBound(yearButtons)
  29. nMonths = UBound(monthButtons)
  30. nDays = UBound(dayButtons)
  31.  
  32. ''check the making all good!
  33. 'For i = 1 To nMonths
  34. '    Print MonthButtons(i).x, MonthButtons(i).y, MonthButtons(i).w, MonthButtons(i).h, MonthButtons(i).text
  35. 'Next
  36. 'End
  37.  
  38.     Cls
  39.     Print "Last Date Picked: " + yearPick$ + "-" + monthPick$ + "-" + dayPick$
  40.     For i = 1 To nYears
  41.         DrawButton yearButtons(i)
  42.     Next
  43.     For i = 1 To nMonths
  44.         DrawButton monthButtons(i)
  45.     Next
  46.     For i = 1 To nDays
  47.         DrawButton dayButtons(i)
  48.     Next
  49.  
  50.     While _MouseInput: Wend ' might want mouse for other things besides checking a button click
  51.     mx = _MouseX: my = _MouseY: mb = _MouseButton(1)
  52.     If mb Then
  53.         For i = 1 To nYears
  54.             If InBoxTF&(mx, my, yearButtons(i)) Then yearPick$ = yearButtons(i).text: GoTo continue
  55.         Next
  56.         For i = 1 To nMonths
  57.             If InBoxTF&(mx, my, monthButtons(i)) Then monthPick$ = monthButtons(i).text: GoTo continue
  58.         Next
  59.         For i = 1 To nDays
  60.             If InBoxTF&(mx, my, dayButtons(i)) Then dayPick$ = dayButtons(i).text: GoTo continue
  61.         Next
  62.     End If
  63.  
  64.     continue:
  65.     _Display
  66.     _Limit 60
  67.  
  68. Sub Split (SplitMeString As String, delim As String, loadMeArray() As String)
  69.     Dim curpos As Long, arrpos As Long, LD As Long, dpos As Long 'fix use the Lbound the array already has
  70.     curpos = 1: arrpos = LBound(loadMeArray): LD = Len(delim)
  71.     dpos = InStr(curpos, SplitMeString, delim)
  72.     Do Until dpos = 0
  73.         loadMeArray(arrpos) = Mid$(SplitMeString, curpos, dpos - curpos)
  74.         arrpos = arrpos + 1
  75.         If arrpos > UBound(loadMeArray) Then ReDim _Preserve loadMeArray(LBound(loadMeArray) To UBound(loadMeArray) + 1000) As String
  76.         curpos = dpos + LD
  77.         dpos = InStr(curpos, SplitMeString, delim)
  78.     Loop
  79.     loadMeArray(arrpos) = Mid$(SplitMeString, curpos)
  80.     ReDim _Preserve loadMeArray(LBound(loadMeArray) To arrpos) As String 'get the ubound correct
  81.  
  82. Function InBoxTF& (x, y, b As Button)
  83.     If x >= b.x And x <= b.x + b.w Then
  84.         If y >= b.y And y <= b.y + b.h Then InBoxTF& = -1
  85.     End If
  86.  
  87. Sub DrawButton (b As Button)
  88.     ReDim As _Unsigned Long FC, BC
  89.     Line (b.x, b.y)-Step(b.w, b.h), b.BC, BF
  90.     Line (b.x, b.y)-Step(b.w, b.h), b.FC, B
  91.     Color b.FC, b.BC
  92.     _PrintString ((b.x + (b.w - 8 * Len(b.text)) / 2), b.y + (b.h - 16) / 2), b.text
  93.     Color FC, BC
  94.  
  95. Sub MakeButtons (fore As _Unsigned Long, back As _Unsigned Long, X As Long, Y As Long, CommaDelimitedList$, arr() As Button)
  96.     ReDim As Long items, i, lngItem
  97.     ReDim list$(1 To 1)
  98.     Split CommaDelimitedList$, ",", list$()
  99.     items = UBound(list$)
  100.  
  101.     'what's longest item?
  102.     For i = 1 To items
  103.         If Len(list$(i)) > lngItem Then lngItem = Len(list$(i))
  104.     Next
  105.     ReDim arr(1 To items) As Button ' make month buttons
  106.     For i = 1 To items
  107.         arr(i).x = X
  108.         arr(i).y = Y + 20 * (i - 1)
  109.         arr(i).w = 8 * (lngItem + 4)
  110.         arr(i).h = 18 'assuming default font
  111.         arr(i).text = list$(i)
  112.         arr(i).FC = fore
  113.         arr(i).BC = back
  114.     Next
  115.  
  116. Function TS$ (n As Long)
  117.     TS$ = _Trim$(Str$(n))
  118.  

« Last Edit: March 11, 2021, 04:19:14 pm by bplus »

Offline 191Brian

  • Newbie
  • Posts: 91
    • View Profile
    • My Itch page
Re: Basic graphical pick from list function
« Reply #6 on: March 11, 2021, 04:42:29 pm »
Hi Bplus

Great work.

Brian ...