Author Topic: Handy List Box for Item Selection  (Read 6028 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Handy List Box for Item Selection
« on: September 04, 2018, 09:36:52 am »
Here is current state of Array Item selection, demo and tester. It seems to be working as I had hoped but if you find anything buggy let me know (2nd part I tested as File Viewer for the file name the code was saved as.)
Code: QB64: [Select]
  1. _TITLE "getArrayItemClicked v2"
  2.  
  3. ' Main testing and demo of the FUNCTION  getArrayItemNumber%
  4.  
  5. 'started 2018-08-31 B+  developing a general purpose display and select app of a string array
  6. ' in this version want
  7. ' 1 to be able to select item from larger arrays that take several pages to screen
  8. ' 2 highlite mouse over ?
  9. ' 3 colorize print? Eh! bloats parameters in call, if really want, modify function for app.
  10. '   Using dark blue on sky blue and reverse for highlite, pretty easy on eyes and sets off
  11. '   selection area.
  12. ' 4 keep modifiable for possibly adding fonts, I think that means use only locate and print,
  13. '  as _printstring works in pixels, no good for different fonts. (Neither is LOCATE)
  14.  
  15. ' 2018-09-01 yea, finally got everything working and playing together
  16. ' oh yeah, to mouse click an escape along with expected escape button press.
  17. ' I might to build a frame around the list box control? (No, just a bar above and below)
  18.  
  19. '2018-09-03 OK everything working great! But I have added two lines to maxHeight.
  20. ' Do I adjust maxHeight to reflect actual height of box on screen, I think better do it.
  21. ' Oh heck that was easy!  Just calc maxHeight off boxHeight!
  22. ' Clean up instructions for using the function.
  23. ' NEXT project is message box that doesn't need Windows OS calls,
  24. ' so I could offer help here with h keypress!
  25. ' Just tested a font with locate and print and locate does not work.
  26. ' So this is done until I get messageBox working.
  27.  
  28. '2018-09-04 post v2 bak 9-3_9PM
  29.  
  30. CONST nArr = 92 'ubound of array = actual amount of items if LBound = 1
  31. CONST LB = 1 'try different lower bounds not just 0, 1
  32. CONST WW = 1200 'Window Width
  33. CONST WH = 600 'Window Height
  34.  
  35. SCREEN _NEWIMAGE(WW, WH, 32)
  36. _SCREENMOVE 100, 60
  37.  
  38. 'test string array, use indexes in lines for alignment to code for function
  39. REDIM arr(LB TO nArr) AS STRING
  40. FOR i = LB TO nArr
  41.     arr(i) = "This is arr item:" + STR$(i)
  42.  
  43.     CLS
  44.     PRINT
  45.     cp "*** Mouse and Key Instructions ***"
  46.     PRINT
  47.     cp "Mouse, mouse wheel, and arrow keys should work as expected for item selection."
  48.     cp "Press spacebar to select a highlighted item or just click it."
  49.     cp "Use number(s) + enter to select an array item by it's index number,"
  50.     cp "backspace will remove last number pressed, c will clear a number started."
  51.     cp "Numbers started are shown in bottom right PgDn bar."
  52.     cp "Enter will also select the highlighted item, if no number has been started."
  53.     cp "Home starts you at lowest array index, End highlights then highest index."
  54.     cp "Use PgUp and PgDn keys or bars to flip through pages of array items."
  55.     PRINT
  56.     cp "Escape returns -1719 to allow a Cancel function and signal no slection."
  57.     PRINT ""
  58.     locRow = 16: locCol = (WW / 8 - 25) / 2: boxWidth = 25: boxHeight = 17 '< displays 15 lines of array items
  59.     'boxHeight is actual screen space in character units, the display uses 2 of the lines for control bars.
  60.     'boxWidth will include item numbers displayed to left of array string item
  61.     ch = getArrayItemNumber(locRow, locCol, boxWidth, boxHeight, arr())
  62.     COLOR _RGB32(255, 255, 255), _RGB32(0, 0, 0): LOCATE 32, 1
  63.     IF ch = -1719 THEN cp "You canceled selection process." ELSE cp "You chose index (" + LTRIM$(STR$(ch)) + ") = " + arr(ch)
  64.     IF NOT goAgain THEN EXIT WHILE
  65.  
  66. 'see this file
  67. REDIM fArr(500) AS STRING
  68. lnCnt = fLines("getArrayItemClicked v2.bas", fArr()) '<<<<<<<<<<<<<<<<<<< or whatever name you gave this file AND SAVED!
  69. ch = getArrayItemNumber(5, 5, 140, 30, fArr())
  70. LOCATE 1, 1: PRINT ch
  71.  
  72. ' Future Help Message Box for the function.
  73. ' "*** Mouse and Key Instructions ***"
  74. '
  75. ' "Mouse, mouse wheel, and arrow keys should work as expected for item selection."
  76. ' "Press spacebar to select a highlighted item or just click it."
  77. ' "Use number(s) + enter to select an array item by it's index number,"
  78. ' "backspace will remove last number pressed, c will clear a number started."
  79. ' "Numbers started are shown in bottom right PgDn bar."
  80. ' "Enter will also select the highlighted item, if no number has been started."
  81. ' "Home starts you at lowest array index, End highlights then highest index."
  82. ' "Use PgUp and PgDn keys to flip through pages of array items."
  83. '
  84. ' "Escape returns -1719 to allow a Cancel function and signal no slection."
  85. FUNCTION getArrayItemNumber& (locateRow, locateColumn, boxWidth, boxHeight, arr() AS STRING)
  86.     'Notes: locateRow, locateColumn for top right corner of selection box on screen in characters for LOCATE.
  87.     'boxWidth and boxHeight are in character units, again for locate and print at correct places.
  88.     'All displaying is restricted to inside the box, which has PgUP and PgDn as top and bottom lines in the display.
  89.     '
  90.     DIM maxWidth AS INTEGER, maxHeight AS INTEGER, page AS INTEGER, hlite AS INTEGER, mx AS INTEGER, my AS INTEGER
  91.     DIM lba AS LONG, uba AS LONG, choice AS LONG
  92.     maxWidth = boxWidth '       number of characters in box
  93.     maxHeight = boxHeight - 2 ' number of lines displayed of array at one time = 1 page
  94.     lba = LBOUND(arr)
  95.     uba = UBOUND(arr)
  96.     page = 0
  97.     hlite = 0 '                 line in display ready for selection by spacebar or if no number is started, enter
  98.     clrStr$ = SPACE$(maxWidth) 'clearing a display line
  99.  
  100.     GOSUB update '              show the beginning of the array items for selection
  101.  
  102.     'signal cancel selection process, exit sub with this unlikely index to signal canel
  103.     choice = -1719 'primes 7 and 8, not likely to be a select index of an array
  104.  
  105.     DO 'until get a selection or demand exit
  106.  
  107.         'handle the key stuff
  108.         kh& = _KEYHIT
  109.         IF kh& THEN
  110.             IF kh& > 0 AND kh& < 255 THEN
  111.                 IF INSTR("0123456789", CHR$(kh&)) > 0 THEN b$ = b$ + CHR$(kh&): GOSUB update
  112.                 IF CHR$(kh&) = "c" THEN b$ = "": GOSUB update
  113.                 IF kh& = 13 THEN 'enter pressed check if number is being entered?
  114.                     IF LEN(b$) THEN
  115.                         IF VAL(b$) >= lba AND VAL(b$) <= uba THEN 'we have number started
  116.                             choice = VAL(b$): EXIT DO
  117.                         ELSE 'clear b$ to show some response to enter
  118.                             b$ = "": GOSUB update 'clear the value that doesn't work
  119.                         END IF
  120.                     ELSE
  121.                         choice = hlite + page * maxHeight + lba 'must mean to select the highlighted item
  122.                     END IF
  123.                 END IF
  124.                 IF kh& = 27 THEN EXIT DO 'escape clause offered to Cancel selection process
  125.                 IF kh& = 32 THEN choice = hlite + page * maxHeight + lba 'best way to choose highlighted selection
  126.                 IF kh& = 8 THEN 'backspace to edit number
  127.                     IF LEN(b$) THEN b$ = LEFT$(b$, LEN(b$) - 1): GOSUB update
  128.                 END IF
  129.             ELSE
  130.                 SELECT CASE kh& 'choosing sections of array to display and highlighted item
  131.                     CASE 20736 'pg dn
  132.                         IF (page + 1) * maxHeight + lba <= uba THEN page = page + 1: GOSUB update
  133.                     CASE 18688 'pg up
  134.                         IF (page - 1) * maxHeight + lba >= lba THEN page = page - 1: GOSUB update
  135.                     CASE 18432 'up
  136.                         IF hlite - 1 < 0 THEN
  137.                             IF page > 0 THEN
  138.                                 page = page - 1: hlite = maxHeight - 1: GOSUB update
  139.                             END IF
  140.                         ELSE
  141.                             hlite = hlite - 1: GOSUB update
  142.                         END IF
  143.                     CASE 20480 'down
  144.                         IF (hlite + 1) + page * maxHeight + lba <= uba THEN 'ok to move up
  145.                             IF hlite + 1 > maxHeight - 1 THEN
  146.                                 page = page + 1: hlite = 0: GOSUB update
  147.                             ELSE
  148.                                 hlite = hlite + 1: GOSUB update
  149.                             END IF
  150.                         END IF
  151.                     CASE 18176 'home
  152.                         page = 0: hlite = 0: GOSUB update
  153.                     CASE 20224 ' end
  154.                         page = INT((uba - lba) / maxHeight): hlite = maxHeight - 1: GOSUB update
  155.                 END SELECT
  156.             END IF
  157.         END IF
  158.  
  159.         'handle the mouse stuff
  160.         WHILE _MOUSEINPUT
  161.             IF _MOUSEWHEEL = -1 THEN 'up?
  162.                 IF hlite - 1 < 0 THEN
  163.                     IF page > 0 THEN
  164.                         page = page - 1: hlite = maxHeight - 1: GOSUB update
  165.                     END IF
  166.                 ELSE
  167.                     hlite = hlite - 1: GOSUB update
  168.                 END IF
  169.             ELSEIF _MOUSEWHEEL = 1 THEN 'down?
  170.                 IF (hlite + 1) + page * maxHeight + lba <= uba THEN 'ok to move up
  171.                     IF hlite + 1 > maxHeight - 1 THEN
  172.                         page = page + 1: hlite = 0: GOSUB update
  173.                     ELSE
  174.                         hlite = hlite + 1: GOSUB update
  175.                     END IF
  176.                 END IF
  177.             END IF
  178.         WEND
  179.         mx = INT((_MOUSEX - locateColumn * 8) / 8) + 2: my = INT((_MOUSEY - locateRow * 16) / 16) + 2
  180.         IF _MOUSEBUTTON(1) THEN 'click contols or select array item
  181.             _DELAY .2
  182.             IF mx >= 1 AND mx <= maxWidth AND my >= 1 AND my <= maxHeight THEN
  183.                 choice = my + page * maxHeight + lba - 1 'select item clicked
  184.             ELSEIF mx >= 1 AND mx <= maxWidth AND my = 0 THEN 'page up or exit
  185.                 IF my = 0 AND (mx <= maxWidth AND mx >= maxWidth - 2) THEN 'exit sign
  186.                     EXIT DO 'escape plan for mouse click top right corner of display box
  187.                 ELSE 'PgUp bar clicked
  188.                     IF (page - 1) * maxHeight + lba >= lba THEN page = page - 1: GOSUB update
  189.                 END IF
  190.             ELSEIF mx >= 1 AND mx <= maxWidth AND my = maxHeight + 1 THEN 'page down bar clicked
  191.                 IF (page + 1) * maxHeight + lba <= uba THEN page = page + 1: GOSUB update
  192.             END IF
  193.         ELSE '   mouse over highlighting, only if mouse has moved!
  194.             IF mx >= 1 AND mx <= maxWidth AND my >= 1 AND my <= maxHeight THEN
  195.                 IF mx <> lastmx OR my <> lastmy THEN
  196.                     IF my - 1 <> hlite AND (my - 1 + page * maxHeight + lba <= uba) THEN
  197.                         hlite = my - 1
  198.                         lastmx = mx: lastmy = my
  199.                         GOSUB update
  200.                     END IF
  201.                 END IF
  202.             END IF
  203.         END IF
  204.         _LIMIT 200
  205.     LOOP UNTIL choice >= lba AND choice <= uba
  206.     getArrayItemNumber& = choice
  207.     EXIT SUB
  208.  
  209.     'display of array sections and controls on screen
  210.     update:
  211.  
  212.     'fix hlite if it has dropped below last array item
  213.     WHILE hlite + page * maxHeight + lba > uba
  214.         hlite = hlite - 1
  215.     WEND
  216.  
  217.     'main display of array items at page * maxHeight (lines high)
  218.     FOR row = 0 TO maxHeight - 1
  219.         IF hlite = row THEN COLOR _RGB(200, 200, 255), _RGB32(0, 0, 88) ELSE COLOR _RGB32(0, 0, 88), _RGB(200, 200, 255)
  220.         LOCATE locateRow + row, locateColumn: PRINT clrStr$
  221.         index = row + page * maxHeight + lba
  222.         IF index >= lba AND index <= uba THEN
  223.             LOCATE locateRow + row, locateColumn
  224.             PRINT LEFT$(LTRIM$(STR$(index)) + ") " + arr(index), maxWidth)
  225.         END IF
  226.     NEXT
  227.  
  228.     'make page up and down bars to click, print PgUp / PgDn if available
  229.     COLOR _RGB32(200, 200, 255), _RGB32(0, 100, 50)
  230.     LOCATE locateRow - 1, locateColumn: PRINT SPACE$(maxWidth)
  231.     IF page <> 0 THEN LOCATE locateRow - 1, locateColumn: PRINT LEFT$(" Pg Up" + SPACE$(maxWidth), maxWidth)
  232.     LOCATE locateRow + maxHeight, locateColumn: PRINT SPACE$(maxWidth)
  233.     IF page <> INT(uba / maxHeight) THEN
  234.         LOCATE locateRow + maxHeight, locateColumn: PRINT LEFT$(" Pg Dn" + SPACE$(maxWidth), maxWidth)
  235.     END IF
  236.     'make exit sign for mouse click
  237.     COLOR _RGB32(255, 255, 255), _RGB32(200, 100, 0)
  238.     LOCATE locateRow - 1, locateColumn + maxWidth - 3
  239.     PRINT " X "
  240.  
  241.     'if a number selection has been started show it's build = b$
  242.     IF LEN(b$) THEN
  243.         COLOR _RGB(255, 255, 0), _RGB32(0, 0, 0)
  244.         LOCATE locateRow + maxHeight, locateColumn + maxWidth - LEN(b$) - 1
  245.         PRINT b$;
  246.     END IF
  247.     _DISPLAY
  248.     _LIMIT 100
  249.     RETURN
  250.  
  251. '                              These are needed only for the demo and testing of the function:
  252. '  It should be noted I had trouble using INPUT and INKEY$ after using the function being tested, ie inquiring about another test.
  253. '                              Something about clearing keypresses (and enter specially).
  254. FUNCTION goAgain% ()
  255.     WHILE LEN(INKEY$): WEND 'clear inkey$
  256.     PRINT: cp "Go again? press y for yes, any other for no."
  257.     k$ = ""
  258.     WHILE k$ = "": k$ = INKEY$: WEND
  259.     IF k$ = "y" THEN goAgain% = -1
  260.  
  261. SUB cp (s$)
  262.     LOCATE CSRLIN, (WW / 8 - LEN(s$)) / 2: PRINT s$
  263.  
  264. FUNCTION fLines (fileName$, arr() AS STRING)
  265.     filecount% = 0
  266.     IF _FILEEXISTS(fileName$) THEN
  267.         OPEN fileName$ FOR INPUT AS #1
  268.         DO UNTIL EOF(1)
  269.             LINE INPUT #1, arr(filecount%)
  270.             'PRINT filecount%, arr(filecount%)
  271.             filecount% = filecount% + 1
  272.         LOOP
  273.         CLOSE #1
  274.         REDIM _PRESERVE arr(filecount% - 1)
  275.     END IF
  276.     fLines = filecount% 'this file returns the number of lines loaded, 0 means file did not exist
  277.  
  278.  

Alas! Locate does not work for fonts so I am working on that aspect already have a bunch of font subs working:
fPRINT, fLOCATE, fLP (Locate and Print), fCP (center print), and of course fINPUT to convert above code to handle fonts.

But with fonts there is problem of alignments, getting Character width just right so that if you print a string across the screen it will align perfectly if you print the same string character by character with fLOCATE and fPRINT.

Code: QB64: [Select]
  1. _TITLE "Font procedures"
  2. 'QB64 X 64 version 1.2 20180228/86  from git b301f92
  3.  
  4. '2018-09-03 started to duplicate subs I used to do large printing with Print, Locate, Input
  5. '2018=09-04 post
  6.  
  7. CONST WW = 800
  8. CONST WH = 600
  9. SCREEN _NEWIMAGE(WW, WH, 32)
  10. _SCREENMOVE (1280 - WW) / 2 + 30, (760 - WH) / 2
  11.  
  12. DIM SHARED CC AS INTEGER, CR AS INTEGER, CW AS INTEGER, CH AS INTEGER, FH AS LONG, MAXCOL AS INTEGER, MAXROW AS INTEGER
  13. 'FH = _LOADFONT("C:\windows\fonts\arial.ttf", 16, "MONOSPACE") '  OK
  14. 'FH = _LOADFONT("NotoMono-Regular.ttf", 16, "MONOSPACE") 'OK
  15. FH = _LOADFONT("ARLRDBD.ttf", 14, "MONOSPACE") 'this is nice!!! low 10 and still legible 12+ excellent(72x50 on 800, 600 screen)
  16. 'for CW = CH - 1
  17. ' sz = 8  get 114 x 75 'no alignment between printing string and printing char x char
  18. ' sz =10  get  88 x 60 'good
  19. ' sz =12  get  72 x 50 'good
  20. ' sz =14  get  61 x 42 '<<< good practice here
  21. ' sz =16  get  57 x 37 'good
  22. ' sz =18  get  47 x 33 'good
  23. ' sz =20  get  42 x 30 'good
  24. ' sz =22  get  38 x 27 'good
  25. ' sz =24  get  34 x 25 'good
  26. ' sz =48  get   misaligned
  27. 'FH = _LOADFONT("verdanab.ttf", 8, "MONOSPACE") 'not bad either, some style to it
  28. 'for CW = CH+2
  29. 'sz 8  114x75 'ch+1
  30. 'sz10   88x60 'ch+2
  31. 'sz12   72x50 'CH+2 aligned
  32. 'sz14   61x42 'ch+2
  33. 'sz16   53x37 'ch+2
  34.  
  35.  
  36. IF FH <= 0 THEN PRINT "Trouble with font load file, goodbye.": SLEEP: END
  37. CH = _FONTHEIGHT(FH): CW = CH - 1 'this make printing char by char the same as printing a string for ARLRDBD.ttf
  38. MAXCOL = INT(WW / CW): MAXROW = INT(WH / CH): CC = 1: CR = 1
  39.  
  40. fLP 1, 1, "max (row, col) = (" + LTRIM$(STR$(MAXCOL)) + "," + LTRIM$(STR$(MAXROW)) + ")"
  41. fPRINT "     ;"
  42. fPRINT "max (row, col) = (" + LTRIM$(STR$(MAXCOL)) + "," + LTRIM$(STR$(MAXROW)) + ")"
  43. fPRINT "This is another row."
  44. fLOCATE 10, 10
  45. fPRINT "This is a located print line."
  46. FOR i = 4 TO 10
  47.     IF i = 9 THEN
  48.         FOR j = 1 TO 10
  49.             fPRINT RIGHT$(STR$(j), 1) + ";"
  50.         NEXT
  51.     END IF
  52.     fLOCATE i, 1: fPRINT LTRIM$(STR$(i))
  53. fCP "Center this text in the line."
  54. fPRINT "And this should follow the centered text on the next line."
  55. COLOR _RGB32(0, 0, 128), _RGB32(200, 200, 255)
  56. fCP "How about some color?"
  57. COLOR _RGB32(200, 200, 255), _RGB32(0, 0, 0)
  58. fINPUT "Can you answer y for yes or n for no ?", ans$
  59. fPRINT "Ah! you answered, *" + ans$ + "*"
  60.  
  61.  
  62. 'the f for font subs
  63.  
  64. SUB fLOCATE (row, col) 'locate xColumnCell, yRowCell for printing
  65.     IF 0 < col AND col <= MAXCOL AND 0 < row AND row <= MAXROW THEN
  66.         CC = col: CR = row
  67.     ELSE
  68.         BEEP
  69.     END IF
  70.  
  71. SUB fPRINT (s$) 'print line (feed)
  72.     IF RIGHT$(s$, 1) = ";" THEN LFTF = 0: mess$ = LEFT$(s$, LEN(s$) - 1) ELSE LFTF = -1: mess$ = s$
  73.     _PRINTSTRING ((CC - 1) * CW, (CR - 1) * CH), mess$
  74.     IF LFTF THEN
  75.         CC = 1
  76.         CR = CR + 1
  77.         IF CR > MAXROW THEN CR = MAXROW 'yuck!
  78.     ELSE
  79.         CC = CC + LEN(mess$)
  80.     END IF
  81.  
  82. SUB fLP (row, col, mess$) 'locate x, y : print mess$ lp = locate and print assume LF
  83.     'if locate = x col and y row then and top left corner locates as 1, 1
  84.     IF 0 < col AND col <= MAXCOL AND 0 < row AND row <= MAXROW THEN
  85.         _PRINTSTRING ((col - 1) * CW, (row - 1) * CH), mess$
  86.         CC = 1
  87.         CR = CR + 1
  88.         IF CR > MAXROW THEN CR = MAXROW 'yuck!
  89.     END IF
  90.  
  91. SUB fCP (s$) 'cp Center Print on line y the cpText$
  92.     col = (MAXCOL - LEN(s$)) / 2
  93.     fLP CR, col, s$
  94.  
  95. SUB fINPUT (prompt$, var$) 'input
  96.     DIM pRow AS INTEGER, pCol AS INTEGER, done AS _BYTE
  97.     'save current location
  98.     pRow = CR: pCol = CC 'save these for redrawing var
  99.     fLOCATE pRow, pCol
  100.     fPRINT prompt$ + " {} ;"
  101.     OK$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz"
  102.     OK$ = OK$ + CHR$(8) + CHR$(27) + CHR$(13) + "1234567890!@#$%^&*()_-+={}[]|\:;'<,>.?/"
  103.     DO
  104.         k$ = INKEY$
  105.         IF INSTR(OK$, k$) THEN
  106.             IF k$ = CHR$(8) THEN
  107.                 IF t$ <> "" THEN
  108.                     IF LEN(t$) = 1 THEN t$ = "" ELSE t$ = LEFT$(t$, LEN(t$) - 1)
  109.                 END IF
  110.             ELSE
  111.                 IF k$ = CHR$(13) OR k$ = CHR$(27) THEN
  112.                     IF k$ = CHR$(27) THEN t$ = ""
  113.                     EXIT DO
  114.                 ELSE
  115.                     t$ = t$ + k$
  116.                 END IF
  117.             END IF
  118.             fLOCATE pRow, pCol
  119.             fPRINT prompt$ + " {" + t$ + "} ;"
  120.             k$ = ""
  121.         END IF
  122.     LOOP UNTIL done
  123.     CC = 1: CR = pRow + 1 'update the next print location
  124.     var$ = t$ 'return the sub's var$ with desired entered or escape string.

Attached is Arial Round Bold from Windows System.

PS for fPRINT, if you put a semi-colon at the end of string to print, there will be no CR+LF like with normal PRINT s$;
* ARLRDBD.TTF (Filesize: 44.2 KB, Downloads: 227)
« Last Edit: September 04, 2018, 10:00:18 am by bplus »

Offline codeguy

  • Forum Regular
  • Posts: 174
    • View Profile
Re: Handy List Box for Item Selection
« Reply #1 on: September 04, 2018, 11:20:22 am »
if you want a stable sort for your list items (yes, it beats standard MergeSort by a 25% margin): It includes the merging element of TimSort and some minor tweaks like eccentric recursion and use of InsertionSort for tiny subarray sorting. Gains are realized by dealing with smaller subsections first. For VERY large arrays, this tactic is invaluable. I have tested this code thoroughly and verified against other algorithms, as well as a sequence check used during VERY time-consuming development and verification of my library. All 5000+ executable lines (exclusive of comments) have been tested for correctness. That literal 4.390647888183594, has been reached through extensive testing using Newtonian methods.
Code: QB64: [Select]
  1. SUB MergeInsert (CGSortStringArray() as string, start AS LONG, finish AS LONG, order&)
  2.     IF finish - start > 5 THEN
  3.         IF (finish - start) AND 0 THEN
  4.             m& = start + (finish - start) / 4.390647888183594
  5.             MergeInsert CGSortStringArray(), start, m&, order&
  6.             MergeInsert CGSortStringArray(), m& + 1, finish, order&
  7.             Tim_merge CGSortStringArray(), start, m&, finish, order&
  8.         ELSE
  9.             m& = start + (finish - start) / 2
  10.             MergeInsert CGSortStringArray(), start, m&, order&
  11.             MergeInsert CGSortStringArray(), m& + 1, finish, order&
  12.             EfficientMerge CGSortStringArray(), start, finish, order&
  13.         END IF
  14.      ELSE
  15.         InsertionSort CGSortStringArray(), start, finish, order&
  16.     END IF
  17.  
  18. SUB Tim_merge (CGSortStringArray() as string, left AS LONG, middle AS LONG, right AS LONG, order&)
  19.     DIM Tim_Merge_LenLeft AS LONG
  20.     DIM Tim_Merge_LenRight AS LONG
  21.     DIM Tim_Merge_i AS LONG
  22.     DIM Tim_Merge_J AS LONG
  23.     DIM Tim_Merge_k AS LONG
  24.     Tim_Merge_LenLeft = middle - left + 1
  25.     Tim_Merge_LenRight = right - middle
  26.     DIM array_left(0 TO Tim_Merge_LenLeft - 1) AS DOUBLE
  27.     DIM array_right(0 TO Tim_Merge_LenRight - 1) AS DOUBLE
  28.  
  29.     '* load up left side (lower half in left) (start ... middle)
  30.     FOR Tim_Merge_i = 0 TO Tim_Merge_LenLeft - 1
  31.         array_left(Tim_Merge_i) = CGSortStringArray(left + Tim_Merge_i)
  32.     NEXT
  33.  
  34.     '* load up right side (upper half in left) (middle + 1 ... finish)
  35.     FOR Tim_Merge_i = 0 TO Tim_Merge_LenRight - 1
  36.         array_right(Tim_Merge_i) = CGSortStringArray(middle + Tim_Merge_i + 1)
  37.     NEXT
  38.  
  39.     Tim_Merge_i = 0
  40.     Tim_Merge_J = 0
  41.     Tim_Merge_k = left
  42.     IF order& = 1 THEN
  43.         WHILE (Tim_Merge_i < Tim_Merge_LenLeft AND Tim_Merge_J < Tim_Merge_LenRight)
  44.             IF (array_left(Tim_Merge_i) <= array_right(Tim_Merge_J)) THEN
  45.                 CGSortStringArray(Tim_Merge_k) = array_left(Tim_Merge_i)
  46.                 Tim_Merge_i = Tim_Merge_i + 1
  47.             ELSE
  48.                 CGSortStringArray(Tim_Merge_k) = array_right(Tim_Merge_J)
  49.                 Tim_Merge_J = Tim_Merge_J + 1
  50.             END IF
  51.             Tim_Merge_k = Tim_Merge_k + 1
  52.         WEND
  53.     ELSE
  54.         WHILE (Tim_Merge_i < Tim_Merge_LenLeft AND Tim_Merge_J < Tim_Merge_LenRight)
  55.             IF (array_left(Tim_Merge_i) >= array_right(Tim_Merge_J)) THEN
  56.                 CGSortStringArray(Tim_Merge_k) = array_left(Tim_Merge_i)
  57.                 Tim_Merge_i = Tim_Merge_i + 1
  58.             ELSE
  59.                 CGSortStringArray(Tim_Merge_k) = array_right(Tim_Merge_J)
  60.                 Tim_Merge_J = Tim_Merge_J + 1
  61.             END IF
  62.             Tim_Merge_k = Tim_Merge_k + 1
  63.         WEND
  64.     END IF
  65.  
  66.     WHILE (Tim_Merge_i < Tim_Merge_LenLeft)
  67.         CGSortStringArray(Tim_Merge_k) = array_left(Tim_Merge_i)
  68.         Tim_Merge_k = Tim_Merge_k + 1
  69.         Tim_Merge_i = Tim_Merge_i + 1
  70.     WEND
  71.  
  72.     WHILE (Tim_Merge_J < Tim_Merge_LenRight)
  73.         CGSortStringArray(Tim_Merge_k) = array_right(Tim_Merge_J)
  74.         Tim_Merge_k = Tim_Merge_k + 1
  75.         Tim_Merge_J = Tim_Merge_J + 1
  76.     WEND
  77.     ERASE array_left
  78.     ERASE array_right
  79.  
  80. SUB EfficientMerge (right() as string, start&, finish&, order&)
  81.     half& = start& + (finish& - start&) \ 2
  82.     REDIM left(start& TO half&) AS DOUBLE '* hold the first half of the array in left() -- must be the same type as right()
  83.     FOR LoadLeft& = start& TO half&
  84.         left(LoadLeft&) = right(LoadLeft&)
  85.     NEXT
  86.     SELECT CASE order&
  87.         CASE 1
  88.             i& = start&
  89.             j& = half& + 1
  90.             insert& = start&
  91.             DO
  92.                 IF i& > half& THEN '* left() exhausted
  93.                     IF j& > finish& THEN '* right() exhausted
  94.                         EXIT DO
  95.                     ELSE
  96.                         '* stuff remains in right to be inserted, so flush right()
  97.                         WHILE j& <= finish&
  98.                             right(insert&) = right(j&)
  99.                             j& = j& + 1
  100.                             insert& = insert& + 1
  101.                         WEND
  102.                         EXIT DO
  103.                         '* and exit
  104.                     END IF
  105.                 ELSE
  106.                     IF j& > finish& THEN
  107.                         WHILE i& < LoadLeft&
  108.                             right(insert&) = left(i&)
  109.                             i& = i& + 1
  110.                             insert& = insert& + 1
  111.                         WEND
  112.                         EXIT DO
  113.                     ELSE
  114.                         IF right(j&) < left(i&) THEN
  115.                             right(insert&) = right(j&)
  116.                             j& = j& + 1
  117.                         ELSE
  118.                             right(insert&) = left(i&)
  119.                             i& = i& + 1
  120.                         END IF
  121.                         insert& = insert& + 1
  122.                     END IF
  123.                 END IF
  124.             LOOP
  125.         CASE ELSE
  126.             i& = start&
  127.             j& = half& + 1
  128.             insert& = start&
  129.             DO
  130.                 IF i& > half& THEN '* left() exhausted
  131.                     IF j& > finish& THEN '* right() exhausted
  132.                         EXIT DO
  133.                     ELSE
  134.                         '* stuff remains in right to be inserted, so flush right()
  135.                         WHILE j& <= finish&
  136.                             right(insert&) = right(j&)
  137.                             j& = j& + 1
  138.                             insert& = insert& + 1
  139.                         WEND
  140.                         EXIT DO
  141.                         '* and exit
  142.                     END IF
  143.                 ELSE
  144.                     IF j& > finish& THEN
  145.                         WHILE i& < LoadLeft&
  146.                             right(insert&) = left(i&)
  147.                             i& = i& + 1
  148.                             insert& = insert& + 1
  149.                         WEND
  150.                         EXIT DO
  151.                     ELSE
  152.                         IF right(j&) > left(i&) THEN
  153.                             right(insert&) = right(j&)
  154.                             j& = j& + 1
  155.                         ELSE
  156.                             right(insert&) = left(i&)
  157.                             i& = i& + 1
  158.                         END IF
  159.                         insert& = insert& + 1
  160.                     END IF
  161.                 END IF
  162.             LOOP
  163.     END SELECT
  164.     ERASE left
  165.  
  166. SUB InsertionSort (CGSortStringArray() as string, start AS LONG, finish AS LONG, order&)
  167.     DIM InSort_Local_ArrayTemp AS DOUBLE
  168.     DIM InSort_Local_i AS LONG
  169.     DIM InSort_Local_j AS LONG
  170.     SELECT CASE order&
  171.         CASE 1
  172.             FOR InSort_Local_i = start + 1 TO finish
  173.                 InSort_Local_j = InSort_Local_i - 1
  174.                 IF CGSortStringArray(InSort_Local_i) < CGSortStringArray(InSort_Local_j) THEN
  175.                     InSort_Local_ArrayTemp = CGSortStringArray(InSort_Local_i)
  176.                     DO UNTIL InSort_Local_j < start
  177.                         IF (InSort_Local_ArrayTemp < CGSortStringArray(InSort_Local_j)) THEN
  178.                             CGSortStringArray(InSort_Local_j + 1) = CGSortStringArray(InSort_Local_j)
  179.                             InSort_Local_j = InSort_Local_j - 1
  180.                         ELSE
  181.                             EXIT DO
  182.                         END IF
  183.                     LOOP
  184.                     CGSortStringArray(InSort_Local_j + 1) = InSort_Local_ArrayTemp
  185.                 END IF
  186.             NEXT
  187.         CASE ELSE
  188.             FOR InSort_Local_i = start + 1 TO finish
  189.                 InSort_Local_j = InSort_Local_i - 1
  190.                 IF CGSortStringArray(InSort_Local_i) > CGSortStringArray(InSort_Local_j) THEN
  191.                     InSort_Local_ArrayTemp = CGSortStringArray(InSort_Local_i)
  192.                     DO UNTIL InSort_Local_j < start
  193.                         IF (InSort_Local_ArrayTemp > CGSortStringArray(InSort_Local_j)) THEN
  194.                             CGSortStringArray(InSort_Local_j + 1) = CGSortStringArray(InSort_Local_j)
  195.                             InSort_Local_j = InSort_Local_j - 1
  196.                         ELSE
  197.                             EXIT DO
  198.                         END IF
  199.                     LOOP
  200.                     CGSortStringArray(InSort_Local_j + 1) = InSort_Local_ArrayTemp
  201.                 END IF
  202.             NEXT
  203.     END SELECT
  204.  
« Last Edit: September 04, 2018, 11:36:54 am by codeguy »

Offline TerryRitchie

  • Seasoned Forum Regular
  • Posts: 495
  • Semper Fidelis
    • View Profile
Re: Handy List Box for Item Selection
« Reply #2 on: September 04, 2018, 06:21:13 pm »
Codeguy your code is always top notch. I really miss [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there] and the wealth of code everyone put there. I wish now I would have taken the time to archive your sorting algorithms (as well as the plethora of other code there) locally on my system.

By the way, how is the transfer from QB64.org to [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there] coming?
In order to understand recursion, one must first understand recursion.

FellippeHeitor

  • Guest
Re: Handy List Box for Item Selection
« Reply #3 on: September 04, 2018, 07:06:29 pm »
We’re still waiting for Galleon to fulfill his promise.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Handy List Box for Item Selection
« Reply #4 on: September 04, 2018, 07:46:44 pm »
I've got a set of routines which I use regularly now to create list boxes:  http://qb64.freeforums.net/thread/56/menu-linked-list-library

One point of interest with my little selectable list maker: you can "link" lists together, which I find amazingly useful for a ton of stuff.  (Say, for example, an address book:  one list for name, another for address, another for phone or email...  and all the lists line up and keep themselves straight, even if you sort one or the other.)

Link above has a demo of it at work, if you'd be interested in checking it out.  ;D
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Handy List Box for Item Selection
« Reply #5 on: September 04, 2018, 09:31:35 pm »
I've got a set of routines which I use regularly now to create list boxes:  http://qb64.freeforums.net/thread/56/menu-linked-list-library

One point of interest with my little selectable list maker: you can "link" lists together, which I find amazingly useful for a ton of stuff.  (Say, for example, an address book:  one list for name, another for address, another for phone or email...  and all the lists line up and keep themselves straight, even if you sort one or the other.)

Link above has a demo of it at work, if you'd be interested in checking it out.  ;D

"little" 790 lines and we stall out on first. Skimming I notice _FONTHEIGHT used, had you worked out way to do different fonts?
This looks like a whole menu system!

"amazingly useful for a ton of stuff", yeah I was entertaining ideas of an editor. I made a calculator with a list box once.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Handy List Box for Item Selection
« Reply #6 on: September 04, 2018, 10:30:45 pm »
Oh yeah! The font procedures worked like a charm!
Working with the font attached above, I used normal font for demo and Ariel Round Bold for the List Display.
Code: QB64: [Select]
  1. _TITLE "getArrayItem v3 font tests"
  2.  
  3. ' Main testing and demo of the FUNCTION  getArrayItemNumber%
  4.  
  5. 'started 2018-08-31 B+  developing a general purpose display and select app of a string array
  6. ' in this version want
  7. ' 1 to be able to select item from larger arrays that take several pages to screen
  8. ' 2 highlite mouse over ?
  9. ' 3 colorize print? Eh! bloats parameters in call, if really want, modify function for app.
  10. '   Using dark blue on sky blue and reverse for highlite, pretty easy on eyes and sets off
  11. '   selection area.
  12. ' 4 keep modifiable for possibly adding fonts, I think that means use only locate and print,
  13. '  as _printstring works in pixels, no good for different fonts. (Neither is LOCATE)
  14.  
  15. ' 2018-09-01 yea, finally got everything working and playing together
  16. ' oh yeah, to mouse click an escape along with expected escape button press.
  17. ' I might to build a frame around the list box control? (No, just a bar above and below)
  18.  
  19. '2018-09-03 OK everything working great! But I have added two lines to maxHeight.
  20. ' Do I adjust maxHeight to reflect actual height of box on screen, I think better do it.
  21. ' Oh heck that was easy!  Just calc maxHeight off boxHeight!
  22. ' Clean up instructions for using the function.
  23. ' NEXT project is message box that doesn't need Windows OS calls,
  24. ' so I could offer help here with h keypress!
  25. ' Just tested a font with locate and print and locate does not work.
  26. ' So this is done until I get messageBox working.
  27.  
  28. '2018-09-04 post v2 bak 9-3_9PM
  29.  
  30. '2018-09-04 getArrayItem v3.bas start tests with font subs, hurrah! it worked!
  31.  
  32. CONST nArr = 92 'ubound of array = actual amount of items if LBound = 1
  33. CONST LB = 1 'try different lower bounds not just 0, 1
  34. CONST WW = 1200 'Window Width
  35. CONST WH = 600 'Window Height
  36.  
  37. SCREEN _NEWIMAGE(WW, WH, 32)
  38. _SCREENMOVE 100, 60
  39.  
  40. 'font stuff CC = currnet column, CR = current row, CW = cell width, CH = cell height, MAXCOL = max columns/rows allowed for screen
  41. DIM SHARED SF AS LONG, CC AS INTEGER, CR AS INTEGER, CW AS INTEGER, CH AS INTEGER, FH AS LONG, MAXCOL AS INTEGER, MAXROW AS INTEGER
  42.  
  43. SF = _FONT 'normal screen font
  44.  
  45. 'FH is font handle for Arial Round Bold, set up font SHARED variables for font subs
  46. FH = _LOADFONT("ARLRDBD.ttf", 14, "MONOSPACE") 'this is nice!!! low 10 and still legible 12+ excellent(72x50 on 800, 600 screen)
  47. IF FH <= 0 THEN PRINT "Trouble with font load file, goodbye.": SLEEP: END
  48. CH = _FONTHEIGHT(FH): CW = CH - 1 'this make printing char by char the same as printing a string for ARLRDBD.ttf
  49. MAXCOL = INT(WW / CW): MAXROW = INT(WH / CH): CC = 1: CR = 1
  50.  
  51. 'test string array, use indexes in lines for alignment to code for function
  52. REDIM arr(LB TO nArr) AS STRING
  53. FOR i = LB TO nArr
  54.     arr(i) = "This is arr item:" + STR$(i)
  55.  
  56.     CLS
  57.     PRINT
  58.     cp "*** Mouse and Key Instructions ***"
  59.     PRINT
  60.     cp "Mouse, mouse wheel, and arrow keys should work as expected for item selection."
  61.     cp "Press spacebar to select a highlighted item or just click it."
  62.     cp "Use number(s) + enter to select an array item by it's index number,"
  63.     cp "backspace will remove last number pressed, c will clear a number started."
  64.     cp "Numbers started are shown in bottom right PgDn bar."
  65.     cp "Enter will also select the highlighted item, if no number has been started."
  66.     cp "Home starts you at lowest array index, End highlights then highest index."
  67.     cp "Use PgUp and PgDn keys or bars to flip through pages of array items."
  68.     PRINT
  69.     cp "Escape returns -1719 to allow a Cancel function and signal no slection."
  70.     PRINT ""
  71.     locRow = 20: locCol = (WW / CW - 25) / 2: boxWidth = 25: boxHeight = 17 '< displays 15 lines of array items
  72.     'boxHeight is actual screen space in character units, the display uses 2 of the lines for control bars.
  73.     'boxWidth will include item numbers displayed to left of array string item
  74.     _FONT FH
  75.     choice = getArrayItemNumber(locRow, locCol, boxWidth, boxHeight, arr())
  76.     _FONT SF
  77.     COLOR _RGB32(255, 255, 255), _RGB32(0, 0, 0): LOCATE 32, 1
  78.     IF choice = -1719 THEN cp "You canceled selection process." ELSE cp "You chose index (" + LTRIM$(STR$(choice)) + ") = " + arr(choice)
  79.     IF NOT goAgain THEN EXIT WHILE
  80.  
  81. 'see this file
  82. REDIM fArr(500) AS STRING
  83. lnCnt = fLines("getArrayItem v3.bas", fArr()) '<<<<<<<<<<<<<<<<<<< or whatever name you gave this file AND SAVED!
  84. choice = getArrayItemNumber(5, 2, 90, 27, fArr())
  85. LOCATE 1, 1: PRINT choice
  86.  
  87. ' Future Help Message Box for the function.
  88. ' "*** Mouse and Key Instructions ***"
  89. '
  90. ' "Mouse, mouse wheel, and arrow keys should work as expected for item selection."
  91. ' "Press spacebar to select a highlighted item or just click it."
  92. ' "Use number(s) + enter to select an array item by it's index number,"
  93. ' "backspace will remove last number pressed, c will clear a number started."
  94. ' "Numbers started are shown in bottom right PgDn bar."
  95. ' "Enter will also select the highlighted item, if no number has been started."
  96. ' "Home starts you at lowest array index, End highlights then highest index."
  97. ' "Use PgUp and PgDn keys to flip through pages of array items."
  98. '
  99. ' "Escape returns -1719 to allow a Cancel function and signal no slection."
  100. FUNCTION getArrayItemNumber& (locateRow, locateColumn, boxWidth, boxHeight, arr() AS STRING)
  101.     'Notes: locateRow, locateColumn for top right corner of selection box on screen in characters for LOCATE.
  102.     'boxWidth and boxHeight are in character units, again for locate and print at correct places.
  103.     'All displaying is restricted to inside the box, which has PgUP and PgDn as top and bottom lines in the display.
  104.     '
  105.     DIM maxWidth AS INTEGER, maxHeight AS INTEGER, page AS INTEGER, hlite AS INTEGER, mx AS INTEGER, my AS INTEGER
  106.     DIM lba AS LONG, uba AS LONG, choice AS LONG
  107.     maxWidth = boxWidth '       number of characters in box
  108.     maxHeight = boxHeight - 2 ' number of lines displayed of array at one time = 1 page
  109.     lba = LBOUND(arr)
  110.     uba = UBOUND(arr)
  111.     page = 0
  112.     hlite = 0 '                 line in display ready for selection by spacebar or if no number is started, enter
  113.     clrStr$ = SPACE$(maxWidth) 'clearing a display line
  114.     CC = 1: CR = 1
  115.     GOSUB update '              show the beginning of the array items for selection
  116.  
  117.     'signal cancel selection process, exit sub with this unlikely index to signal canel
  118.     choice = -1719 'primes 7 and 8, not likely to be a select index of an array
  119.  
  120.     DO 'until get a selection or demand exit
  121.  
  122.         'handle the key stuff
  123.         kh& = _KEYHIT
  124.         IF kh& THEN
  125.             IF kh& > 0 AND kh& < 255 THEN
  126.                 IF INSTR("0123456789", CHR$(kh&)) > 0 THEN b$ = b$ + CHR$(kh&): GOSUB update
  127.                 IF CHR$(kh&) = "c" THEN b$ = "": GOSUB update
  128.                 IF kh& = 13 THEN 'enter pressed check if number is being entered?
  129.                     IF LEN(b$) THEN
  130.                         IF VAL(b$) >= lba AND VAL(b$) <= uba THEN 'we have number started
  131.                             choice = VAL(b$): EXIT DO
  132.                         ELSE 'clear b$ to show some response to enter
  133.                             b$ = "": GOSUB update 'clear the value that doesn't work
  134.                         END IF
  135.                     ELSE
  136.                         choice = hlite + page * maxHeight + lba 'must mean to select the highlighted item
  137.                     END IF
  138.                 END IF
  139.                 IF kh& = 27 THEN EXIT DO 'escape clause offered to Cancel selection process
  140.                 IF kh& = 32 THEN choice = hlite + page * maxHeight + lba 'best way to choose highlighted selection
  141.                 IF kh& = 8 THEN 'backspace to edit number
  142.                     IF LEN(b$) THEN b$ = LEFT$(b$, LEN(b$) - 1): GOSUB update
  143.                 END IF
  144.             ELSE
  145.                 SELECT CASE kh& 'choosing sections of array to display and highlighted item
  146.                     CASE 20736 'pg dn
  147.                         IF (page + 1) * maxHeight + lba <= uba THEN page = page + 1: GOSUB update
  148.                     CASE 18688 'pg up
  149.                         IF (page - 1) * maxHeight + lba >= lba THEN page = page - 1: GOSUB update
  150.                     CASE 18432 'up
  151.                         IF hlite - 1 < 0 THEN
  152.                             IF page > 0 THEN
  153.                                 page = page - 1: hlite = maxHeight - 1: GOSUB update
  154.                             END IF
  155.                         ELSE
  156.                             hlite = hlite - 1: GOSUB update
  157.                         END IF
  158.                     CASE 20480 'down
  159.                         IF (hlite + 1) + page * maxHeight + lba <= uba THEN 'ok to move up
  160.                             IF hlite + 1 > maxHeight - 1 THEN
  161.                                 page = page + 1: hlite = 0: GOSUB update
  162.                             ELSE
  163.                                 hlite = hlite + 1: GOSUB update
  164.                             END IF
  165.                         END IF
  166.                     CASE 18176 'home
  167.                         page = 0: hlite = 0: GOSUB update
  168.                     CASE 20224 ' end
  169.                         page = INT((uba - lba) / maxHeight): hlite = maxHeight - 1: GOSUB update
  170.                 END SELECT
  171.             END IF
  172.         END IF
  173.  
  174.         'handle the mouse stuff
  175.         WHILE _MOUSEINPUT
  176.             IF _MOUSEWHEEL = -1 THEN 'up?
  177.                 IF hlite - 1 < 0 THEN
  178.                     IF page > 0 THEN
  179.                         page = page - 1: hlite = maxHeight - 1: GOSUB update
  180.                     END IF
  181.                 ELSE
  182.                     hlite = hlite - 1: GOSUB update
  183.                 END IF
  184.             ELSEIF _MOUSEWHEEL = 1 THEN 'down?
  185.                 IF (hlite + 1) + page * maxHeight + lba <= uba THEN 'ok to move up
  186.                     IF hlite + 1 > maxHeight - 1 THEN
  187.                         page = page + 1: hlite = 0: GOSUB update
  188.                     ELSE
  189.                         hlite = hlite + 1: GOSUB update
  190.                     END IF
  191.                 END IF
  192.             END IF
  193.         WEND
  194.         mx = INT((_MOUSEX - locateColumn * CW) / CW) + 2: my = INT((_MOUSEY - locateRow * CH) / CH) + 2
  195.         IF _MOUSEBUTTON(1) THEN 'click contols or select array item
  196.             _DELAY .2
  197.             IF mx >= 1 AND mx <= maxWidth AND my >= 1 AND my <= maxHeight THEN
  198.                 choice = my + page * maxHeight + lba - 1 'select item clicked
  199.             ELSEIF mx >= 1 AND mx <= maxWidth AND my = 0 THEN 'page up or exit
  200.                 IF my = 0 AND (mx <= maxWidth AND mx >= maxWidth - 2) THEN 'exit sign
  201.                     EXIT DO 'escape plan for mouse click top right corner of display box
  202.                 ELSE 'PgUp bar clicked
  203.                     IF (page - 1) * maxHeight + lba >= lba THEN page = page - 1: GOSUB update
  204.                 END IF
  205.             ELSEIF mx >= 1 AND mx <= maxWidth AND my = maxHeight + 1 THEN 'page down bar clicked
  206.                 IF (page + 1) * maxHeight + lba <= uba THEN page = page + 1: GOSUB update
  207.             END IF
  208.         ELSE '   mouse over highlighting, only if mouse has moved!
  209.             IF mx >= 1 AND mx <= maxWidth AND my >= 1 AND my <= maxHeight THEN
  210.                 IF mx <> lastmx OR my <> lastmy THEN
  211.                     IF my - 1 <> hlite AND (my - 1 + page * maxHeight + lba <= uba) THEN
  212.                         hlite = my - 1
  213.                         lastmx = mx: lastmy = my
  214.                         GOSUB update
  215.                     END IF
  216.                 END IF
  217.             END IF
  218.         END IF
  219.         _LIMIT 200
  220.     LOOP UNTIL choice >= lba AND choice <= uba
  221.     getArrayItemNumber& = choice
  222.     EXIT SUB
  223.  
  224.     'display of array sections and controls on screen
  225.     update:
  226.  
  227.     'fix hlite if it has dropped below last array item
  228.     WHILE hlite + page * maxHeight + lba > uba
  229.         hlite = hlite - 1
  230.     WEND
  231.  
  232.     'main display of array items at page * maxHeight (lines high)
  233.     FOR row = 0 TO maxHeight - 1
  234.         IF hlite = row THEN COLOR _RGB(200, 200, 255), _RGB32(0, 0, 88) ELSE COLOR _RGB32(0, 0, 88), _RGB(200, 200, 255)
  235.         fLOCATE locateRow + row, locateColumn: fPRINT clrStr$
  236.         index = row + page * maxHeight + lba
  237.         IF index >= lba AND index <= uba THEN
  238.             fLOCATE locateRow + row, locateColumn
  239.             fPRINT LEFT$(LTRIM$(STR$(index)) + ") " + arr(index), maxWidth)
  240.         END IF
  241.     NEXT
  242.  
  243.     'make page up and down bars to click, print PgUp / PgDn if available
  244.     COLOR _RGB32(200, 200, 255), _RGB32(0, 100, 50)
  245.     fLOCATE locateRow - 1, locateColumn: fPRINT SPACE$(maxWidth)
  246.     IF page <> 0 THEN fLOCATE locateRow - 1, locateColumn: fPRINT LEFT$(" Pg Up" + SPACE$(maxWidth), maxWidth)
  247.     fLOCATE locateRow + maxHeight, locateColumn: fPRINT SPACE$(maxWidth)
  248.     IF page <> INT(uba / maxHeight) THEN
  249.         fLOCATE locateRow + maxHeight, locateColumn: fPRINT LEFT$(" Pg Dn" + SPACE$(maxWidth), maxWidth)
  250.     END IF
  251.     'make exit sign for mouse click
  252.     COLOR _RGB32(255, 255, 255), _RGB32(200, 100, 0)
  253.     fLOCATE locateRow - 1, locateColumn + maxWidth - 3
  254.     fPRINT " X "
  255.  
  256.     'if a number selection has been started show it's build = b$
  257.     IF LEN(b$) THEN
  258.         COLOR _RGB(255, 255, 0), _RGB32(0, 0, 0)
  259.         fLOCATE locateRow + maxHeight, locateColumn + maxWidth - LEN(b$) - 1
  260.         fPRINT b$ + ";"
  261.     END IF
  262.     _DISPLAY
  263.     _LIMIT 100
  264.     RETURN
  265.  
  266.  
  267. 'font subs
  268.  
  269. SUB fLOCATE (row, col) 'locate xColumnCell, yRowCell for printing
  270.     IF 0 < col AND col <= MAXCOL AND 0 < row AND row <= MAXROW THEN
  271.         CC = col: CR = row
  272.     ELSE
  273.         BEEP
  274.     END IF
  275.  
  276. SUB fPRINT (s$) 'print line (feed)
  277.     IF RIGHT$(s$, 1) = ";" THEN LFTF = 0: mess$ = LEFT$(s$, LEN(s$) - 1) ELSE LFTF = -1: mess$ = s$
  278.     _PRINTSTRING ((CC - 1) * CW, (CR - 1) * CH), mess$
  279.     IF LFTF THEN
  280.         CC = 1
  281.         CR = CR + 1
  282.         IF CR > MAXROW THEN CR = MAXROW 'yuck!
  283.     ELSE
  284.         CC = CC + LEN(mess$)
  285.     END IF
  286.  
  287. SUB fLP (row, col, mess$) 'locate x, y : print mess$ lp = locate and print assume LF
  288.     'if locate = x col and y row then and top left corner locates as 1, 1
  289.     IF 0 < col AND col <= MAXCOL AND 0 < row AND row <= MAXROW THEN
  290.         _PRINTSTRING ((col - 1) * CW, (row - 1) * CH), mess$
  291.         CC = 1
  292.         CR = CR + 1
  293.         IF CR > MAXROW THEN CR = MAXROW 'yuck!
  294.     END IF
  295.  
  296. SUB fCP (s$) 'cp Center Print on line y the cpText$
  297.     col = (MAXCOL - LEN(s$)) / 2
  298.     fLP CR, col, s$
  299.  
  300. SUB fINPUT (prompt$, var$) 'input
  301.     DIM pRow AS INTEGER, pCol AS INTEGER, done AS _BYTE
  302.     'save current location
  303.     pRow = CR: pCol = CC 'save these for redrawing var
  304.     fLOCATE pRow, pCol
  305.     fPRINT prompt$ + " {} ;"
  306.     OK$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz"
  307.     OK$ = OK$ + CHR$(8) + CHR$(27) + CHR$(13) + "1234567890!@#$%^&*()_-+={}[]|\:;'<,>.?/"
  308.     DO
  309.         k$ = INKEY$
  310.         IF INSTR(OK$, k$) THEN
  311.             IF k$ = CHR$(8) THEN
  312.                 IF t$ <> "" THEN
  313.                     IF LEN(t$) = 1 THEN t$ = "" ELSE t$ = LEFT$(t$, LEN(t$) - 1)
  314.                 END IF
  315.             ELSE
  316.                 IF k$ = CHR$(13) OR k$ = CHR$(27) THEN
  317.                     IF k$ = CHR$(27) THEN t$ = ""
  318.                     EXIT DO
  319.                 ELSE
  320.                     t$ = t$ + k$
  321.                 END IF
  322.             END IF
  323.             fLOCATE pRow, pCol
  324.             fPRINT prompt$ + " {" + t$ + "} ;"
  325.             k$ = ""
  326.         END IF
  327.     LOOP UNTIL done
  328.     CC = 1: CR = pRow + 1 'update the next print location
  329.     var$ = t$ 'return the sub's var$ with desired entered or escape string.
  330.  
  331. '                              These are needed only for the demo and testing of the function:
  332. '  It should be noted I had trouble using INPUT and INKEY$ after using the function being tested, ie inquiring about another test.
  333. '                              Something about clearing keypresses (and enter specially).
  334. FUNCTION goAgain% ()
  335.     WHILE LEN(INKEY$): WEND 'clear inkey$
  336.     PRINT: cp "Go again? press y for yes, any other for no."
  337.     k$ = ""
  338.     WHILE k$ = "": k$ = INKEY$: WEND
  339.     IF k$ = "y" THEN goAgain% = -1
  340.  
  341. SUB cp (s$)
  342.     LOCATE CSRLIN, (WW / 8 - LEN(s$)) / 2: PRINT s$
  343.  
  344. FUNCTION fLines (fileName$, arr() AS STRING)
  345.     filecount% = 0
  346.     IF _FILEEXISTS(fileName$) THEN
  347.         OPEN fileName$ FOR INPUT AS #1
  348.         DO UNTIL EOF(1)
  349.             LINE INPUT #1, arr(filecount%)
  350.             'PRINT filecount%, arr(filecount%)
  351.             filecount% = filecount% + 1
  352.         LOOP
  353.         CLOSE #1
  354.         REDIM _PRESERVE arr(filecount% - 1)
  355.     END IF
  356.     fLines = filecount% 'this file returns the number of lines loaded, 0 means file did not exist
  357.  
  358.  

 
Holy Moly the font procs worked!.PNG

Offline codeguy

  • Forum Regular
  • Posts: 174
    • View Profile
Re: Handy List Box for Item Selection
« Reply #7 on: September 04, 2018, 11:28:14 pm »
nice work, bplus.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Handy List Box for Item Selection
« Reply #8 on: September 05, 2018, 02:00:21 am »
I've got a set of routines which I use regularly now to create list boxes:  http://qb64.freeforums.net/thread/56/menu-linked-list-library

One point of interest with my little selectable list maker: you can "link" lists together, which I find amazingly useful for a ton of stuff.  (Say, for example, an address book:  one list for name, another for address, another for phone or email...  and all the lists line up and keep themselves straight, even if you sort one or the other.)

Link above has a demo of it at work, if you'd be interested in checking it out.  ;D

"little" 790 lines and we stall out on first. Skimming I notice _FONTHEIGHT used, had you worked out way to do different fonts?
This looks like a whole menu system!

"amazingly useful for a ton of stuff", yeah I was entertaining ideas of an editor. I made a calculator with a list box once.

If it stalled out on the first line, you simply don't have my handy dandy color name library in your Qb64 folder:  http://qb64.freeforums.net/thread/5/32-bit-color-const-names

It's definitely my most used library as it lets me specify colors by name in 32-bit color mode.  Black, white, red, gold, skyblue, limegreen -- these are all so much easier to remember and use, rather than having to guess at what RGBA combo makes them up for us.   ;D
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!