Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Text Menu Library Project
#1
Hopefully this will progress into a text menu library...

Code: (Select All)
Width 80, 28
_Font 16
_ScreenMove _Middle

Gui

erhandler_data:
msg$ = "Error: " + LTrim$(Str$(Err)) + " at line " + LTrim$(Str$(Erl)) + "." + Chr$(13) + Chr$(10) + Chr$(13) + Chr$(10)
msg$ = msg$ + "Incorrect alignment of data is the most likely cause."
_MessageBox " Error Message", msg$, "alert"
End

Sub Gui
    Type menu
        top As Integer
        height As Integer
        left As Integer
        width As Integer
        oldtop As Integer
        oldleft As Integer
        oldwidth As Integer
    End Type
    Dim m As menu
    Type color
        MenuBdrFg As Integer
        MenubrdBg As Integer
        MenuSdwFg As Integer
        MenuSdwBg As Integer
        MenuFg As Integer
        MenuBg As Integer
        MenuHlFg As Integer
        MenuHlBg As Integer
        MenuAbr As Integer
        MenuTopActiveFg As Integer
        MenuTopActiveBg As Integer
        MenuTopAbrFg As Integer
        MenuTopAbrBg As Integer
        MenuTopHlFg As Integer
        MenuTopHlBg As Integer
        LineFg As Integer
        LineBg As Integer
        PageFg As Integer
        PageBg As Integer
    End Type
    Dim c As color
    Do
        ReDim heading$(0), MapHeading$(0)

        Gui_Menu_Setup c, m, heading$(), MapHeading$(), spacing, justify, pop, CurStyle, PageAltFg, PageAltBg, pete

        MenuType$ = "": pete = 0
    Loop
End Sub

Sub Gui_User (MenuType$, spacing, justify, CurStyle, pop, selection, sucker)
    Static initiate
    If initiate = 0 Then
        initiate = 1
        ' Gui_User defined.............................
        spacing = 0
        CurStyle = 1
        pop = 1
        justify = 0
        '..........................................
    End If
    Select Case MenuType$
        Case "display"
            Restore menu_data
        Case "header"
            Select Case selection
                Case 1: Restore data1
                Case 2: Restore data2
                Case 3: Restore data3
                Case 4: Restore data4
            End Select
        Case "suckerfish"
            Select Case sucker
                Case 1: Restore suckerfish1
                Case 2: Restore suckerfish2
                Case 3: Restore suckerfish3
                Case 4: Restore suckerfish4
            End Select
        Case "footer"
            ' Nothing to do here.
    End Select

    color_palette_data:
    ' Palette assignments 1-15.
    Data 1,-1,2,-1,3,-1,4,-1,5,-1,6,63,7,-1,8,-1,9,-1,10,-1,11,-1,12,-1,13,-1,14,-1,15,-1: Rem Do not add to this data.
    color_data:
    Rem c.MenuBdrFg, c.MenubrdBg, c.MenuSdwFg, c.MenuSdwBg
    Rem c.MenuFg, c.MenuBg, c.MenuHlFg, c.MenuHlBg, c.MenuAbr
    Rem c.MenuTopActiveFg, c.MenuTopActiveBg, c.MenuTopAbrFg, c.MenuTopAbrBg
    Rem c.MenuTopHlFg, c.MenuTopHlBg, c.LineFg, c.LineBg, c.PageFg, c.PageBg
    Data 1,6,8,0
    Data 0,6,15,1,1
    Data 0,7,9,7
    Data 15,0,14,1,9,1
    Data -999: Rem eof

    menu_data:
    Data "1) Single-Space Display Menu",0
    Data "2) Double-Space Display Menu",0
    Data "3) Triple-Space Display Menu",0
    Data "4) Toggle Block/Center Style",0
    Data "5) Toggle Background",0
    Data "6) Toggle Link Cursor On/Off",0
    Data "7) Toggle Flat/Popup Window",0
    Data eof

    data1:
    Data New,N,0,Open,O,0,Save,S,0,,Export,E,1,,Exit,x,0
    Data eof
    data2:
    Data Undo,U,0,Redo,R,0,,Cut,0,0,Copy,0,0,Paste,0,0,Select All,0,0
    Data eof
    data3:
    Data Subs...,S,0,Line Numbers,L,2,Compiler Warnings,C,0
    Data eof
    data4:
    Data Find,F,0,Repeat Last Find,R,0,Change,C,0,,Clear Search History,H,0,,Quick Navigation,Q,0,Go To Line,G,0
    Data eof

    suckerfish1:
    Data Hypertext,H,Rich Text,R,Code Block,C
    Data eof

    suckerfish2:
    Data Show Line Numbers,L,Background Color,B,Show Separator,S
    Data eof

    suckerfish3:
    Data
    Data eof

    suckerfish4:
    Data
    Data eof

    help_data:
    Data This demo includes this
    Data handy dandy help window
    Data where we simply add data
    Data statements to produce
    Data then help text displayed
    Data in this pop-up window.
    Data eof
End Sub

Sub Gui_Menu_Setup (c As color, m As menu, heading$(), MapHeading$(), spacing, justify, pop, CurStyle, PageAltFg, PageAltBg, pete)

    Gui_User MenuType$, spacing, justify, CurStyle, pop, selection, sucker

    Restore color_palette_data
    For i = 1 To 15
        Read j, k
        If k <> -1 Then Palette j, k
    Next
    Restore color_data
    i = 0
    Do
        i = i + 1
        Read j
        If j = -999 Then Exit Do
        Select Case i
            Case 1: c.MenuBdrFg = j
            Case 2: c.MenubrdBg = j
            Case 3: c.MenuSdwFg = j
            Case 4: c.MenuSdwBg = j
            Case 5: c.MenuFg = j
            Case 6: c.MenuBg = j
            Case 7: c.MenuHlFg = j
            Case 8: c.MenuHlBg = j
            Case 9: c.MenuAbr = j
            Case 10: c.MenuTopActiveFg = j
            Case 11: c.MenuTopActiveBg = j
            Case 12: c.MenuTopAbrFg = j
            Case 13: c.MenuTopAbrBg = j
            Case 14: c.MenuTopHlFg = j
            Case 15: c.MenuTopHlBg = j
            Case 16: c.LineFg = j
            Case 17: c.LineBg = j
            Case 18: c.PageFg = j
            Case 19: c.PageBg = j
        End Select
    Loop
    If PageAltFg + PageAltBk Then c.PageFg = PageAltFg: c.PageBg = PageAltBg
    Color c.PageFg, c.PageBg
    Cls
    Color c.LineFg, c.LineBg
    Locate 2, 1: Print String$(80, 196);
    Locate _Height - 1, 1: Print String$(80, 196);
    Color c.PageFg, c.PageBg
    For i = 3 To _Height - 2
        Locate i, 1: Print String$(80, 176);
    Next

    Color 1, 7: a$ = "  File  Edit  View  Search": Locate 1, 1

    Gui_Menu_Headings a$, heading$(), MapHeading$(), 0

    Color 7, 1: a$ = "[F1] Help  [Esc] Quit": Locate _Height, 1

    Gui_Menu_Headings a$, heading$(), MapHeading$(), 1

    ReDim a$(0), abr$(0), sf(0)

    MenuType$ = "display": Gui_Data_Reader m, MapHeading$(), a$(), abr$(), sf(), dcnt, MenuType$, MenuOpen, spacing, pop, justify, selection, sucker

    Gui_Menu_Placement c, m, a$(), abr$(), dcnt, spacing, pop

    Do
        _Limit 30

        MyMouse_and_Keyboard lb, mb, rb, my, mx, mw, shift%, alt%, clkcnt, drag, b$, autokey$

        Gui_Menu_Selection c, m, MenuType$, selection, spacing, justify, pop, CurStyle, my, mx, lb, mb, mw, alt%, b$, heading$(), MapHeading$(), a$(), PageAltFg, PageAltBg, pete

        If pete Then Exit Do
    Loop
End Sub

Sub Gui_Menu_Headings (heading$, heading$(), MapHeading$(), centering)
    y = CsrLin: Locate y, 1: Print Space$(_Width);
    Select Case centering
        Case 0: Locate y, 1
        Case Else: Locate y, _Width \ 2 - Len(heading$) \ 2 + 1
    End Select
    Print heading$;
    f$ = "": Locate y, 1
    For i = 1 To _Width
        f$ = f$ + Chr$(Screen(y, i))
    Next
    temp$ = " ": j = 0
    If InStr(f$, "[") Then ' Bracket format.
        For i = 1 To Len(f$) ' Map mouse hot zones.
            x$ = Mid$(f$, i, 1)
            If hot Then
                If Left$(LTrim$(Mid$(f$, i) + "["), 1) = "[" Then
                    hot = 1 - hot: temp$ = " "
                End If
            End If
            If x$ <> Chr$(32) And hot = 0 Then
                hot = 1 - hot: j = j + 1: temp$ = Chr$(96 + j)
            End If
            map$ = map$ + temp$
        Next
    Else ' Two-space format.
        For i = 1 To Len(f$) ' Map mouse hot zones.
            x$ = Mid$(f$, i, 1)
            If hot Then
                If Mid$(f$ + "  ", i, 2) = "  " Then
                    hot = 1 - hot: temp$ = " "
                End If
            End If
            If x$ <> Chr$(32) And hot = 0 Then
                hot = 1 - hot: j = j + 1: temp$ = Chr$(96 + j)
            End If
            map$ = map$ + temp$
        Next
    End If
    If y > UBound(MapHeading$) Then ReDim _Preserve MapHeading$(y): ReDim _Preserve heading$(y)
    MapHeading$(y) = map$: heading$(y) = heading$
End Sub

Sub Gui_Data_Reader (m As menu, MapHeading$(), a$(), abr$(), sf(), dcnt, MenuType$, MenuOpen, spacing, pop, justify, selection, sucker)
    Static sfTop()

    Gui_User MenuType$, spacing, justify, CurStyle, pop, selection, sucker

    On Error GoTo erhandler_data
    dcnt = 0: ReDim a$(0), abr$(0)
    Do
        Read dta$
        If dta$ = "eof" Or (_Height - 6 + pop) \ 2 <= (dcnt * (spacing + 1) + 1) \ 2 + pop Then Exit Do ' Data exceeds window max menu height.
        dcnt = dcnt + 1
        ReDim _Preserve abr$(dcnt)
        If Len(dta$) Then
            Read abr$(dcnt)
        Else
            abr$(dcnt) = "" ' Indicates a blank divider in the menu.
        End If
        If MenuType$ = "header" And Len(dta$) Then
            ReDim _Preserve sf(dcnt) ' Only header type menus contain suckerfish option.
            Read sf(dcnt)
            If sf(dcnt) Then
                ReDim sfTop(sf(dcnt)): sfTop(sf(dcnt)) = dcnt
                dta$ = dta$ + " " + Chr$(26) ' Suckerfish id symbol.
            End If
        End If
        ReDim _Preserve a$(dcnt): a$(dcnt) = dta$
        If Len(dta$) > w Then w = Len(dta$) ' Look for greatest width.
    Loop
    On Error GoTo 0
    For i = 1 To dcnt
        temp$ = a$(i)
        a$(i) = Space$(w)
        Select Case justify
            Case 0: j = 1:
            Case 1: j = w \ 2 - Len(temp$) \ 2 + 1
        End Select
        If InStr(temp$, Chr$(26)) Then
            temp$ = Mid$(temp$, 1, InStr(temp$, Chr$(26)) - 2)
            Mid$(a$(i), Len(a$(i)), 1) = Chr$(26)
        End If
        Mid$(a$(i), j) = temp$
    Next
    m.height = dcnt * (spacing + 1) - spacing + 2
    m.width = w + 4
    If MenuType$ = "display" Then
        m.top = _Height \ 2 - m.height \ 2 + 1
        m.left = _Width \ 2 - m.width \ 2 + 1
    Else
        If sucker > 0 Then
            m.top = MenuOpen + 1 + pop + sfTop(sucker) * (spacing + 1) - spacing - 1
            m.left = m.oldleft + m.oldwidth - 1 ' 1-space overlap.
        Else
            m.top = MenuOpen + 1 + pop ' "header"
            j = InStr(MapHeading$(MenuOpen), Chr$(96 + selection))
            m.left = _InStrRev(" " + Mid$(MapHeading$(MenuOpen), 1, j), " ")
        End If
    End If
End Sub

Sub Gui_Drop_Menu_Headings (c As color, b$, heading$(), MapHeading$(), alt%, altmenu, altdown, selection, TopMenuChoice)
    Static TopMenuAbbr$
    If alt% Or b$ = Chr$(27) And altmenu Then
        If altdown = 0 Then altmenu = 1 - altmenu: altdown = 1
        Select Case altmenu
            Case 1
                GoSub highlight_top_menu
            Case 0
                GoSub unhighlight_top_menu
        End Select
    Else
        altdown = 0
    End If
    Select Case b$
        Case Chr$(0) + "P"
            selection = TopMenuChoice
        Case Chr$(0) + "K"
            TopMenuChoice = TopMenuChoice - 1
            If TopMenuChoice = 0 Then TopMenuChoice = Asc(Right$(RTrim$(MapHeading$(1)), 1)) - Asc(Left$(LTrim$(MapHeading$(1)), 1)) + 1
            GoSub highlight_top_menu
        Case Chr$(0) + "M"
            TopMenuChoice = TopMenuChoice + 1
            If TopMenuChoice > Asc(Right$(RTrim$(MapHeading$(1)), 1)) - Asc(Left$(LTrim$(MapHeading$(1)), 1)) + 1 Then TopMenuChoice = 1
            GoSub highlight_top_menu
        Case "a" To "z", "A", "Z"
            If InStr(UCase$(TopMenuAbbr$), UCase$(b$)) Then
                TopMenuChoice = InStr(UCase$(TopMenuAbbr$), UCase$(b$))
                GoSub highlight_top_menu
                selection = TopMenuChoice
            End If
        Case Chr$(27)
            GoSub unhighlight_top_menu
            b$ = ""
    End Select
    Exit Sub

    highlight_top_menu:
    If TopMenuChoice = 0 Then TopMenuChoice = 1
    Color c.MenuTopActiveFg, c.MenuTopActiveBg: Locate 1, 1: Print heading$(CsrLin) + " ";: Locate 1, 1 ' Extra space is to mask out highlighted area.
    i = Asc(Left$(LTrim$(MapHeading$(CsrLin)), 1))
    Color c.MenuTopAbrFg, c.MenuTopAbrBg
    TopMenuAbbr$ = "" ' Print different color letter abbreviation to open menu from keyboard.
    Do
        j = InStr(MapHeading$(CsrLin), Chr$(i))
        If j = 0 Then Exit Do
        i = i + 1
        Locate , j
        temp$ = Mid$(heading$(CsrLin), j, 1)
        Print temp$;
        TopMenuAbbr$ = TopMenuAbbr$ + temp$
    Loop
    temp$ = Chr$(TopMenuChoice + Asc(Left$(LTrim$(MapHeading$(CsrLin)), 1)) - 1) ' Find the menu in the top list. Ex: File Edit.
    i = InStr(MapHeading$(CsrLin), temp$) - 1
    j = _InStrRev(MapHeading$(CsrLin), temp$) - i + 2
    Locate 1, i ' Print a highlighted block behind menu to be opened.
    Color c.MenuTopHlFg, c.MenuTopHlBg: Print Mid$(heading$(CsrLin) + " ", i, j);
    Return

    unhighlight_top_menu:
    Color 0, 7
    Locate 1, 1: Print heading$(CsrLin) + " ";
    Return
End Sub

Sub Gui_Menu_Selection (c As color, m As menu, MenuType$, selection, spacing, justify, pop, CurStyle, my, mx, lb, mb, mw, alt%, b$, heading$(), MapHeading$(), a$(), PageAltFg, PageAltBg, pete)
    Static MenuOpen, MouseField$, abr$(), sf(), sucker, oldmy, oldmx, mshow$, dcnt
    Static mhl, oldmhl, OldMenuType$, oldselection, altmenu, altdown, TopMenuChoice, curhot
    If MenuType$ = "" Then MenuType$ = "display": Gui_Data_Reader m, MapHeading$(), a$(), abr$(), sf(), dcnt, MenuType$, MenuOpen, spacing, pop, justify, selection, sucker
    Select Case MenuOpen
        Case 0 ' Header menus are closed.
            If alt% Or Len(b$) And altmenu <> 0 Then
                If mhl Then ' Get rid of previous highlighted item if switching menus.
                    Locate m.top - pop + mhl + (mhl - 1) * spacing, m.left - pop + 2 - 1: Color c.MenuFg, c.MenuBg: Print " " + a$(mhl) + " "; ' Unhighlight.
                    mhl = 0
                End If

                Gui_Drop_Menu_Headings c, b$, heading$(), MapHeading$(), alt%, altmenu, altdown, selection, TopMenuChoice

                If selection Then MenuOpen = 1: GoSub top_menu ' Gets "header" assignemnt.
            Else
                altdown = 0 ' Needed for alt key toggle when the menu is highlighted but not yet open.
            End If
            Do
                j = 0: selection = 0
                If Len(MapHeading$(my)) Then
                    j = Asc(Mid$(MapHeading$(my), mx, 1)) - 96
                    If j > 0 Then
                        If CurStyle And mshow$ <> "LINK" Then mshow$ = "LINK": _MouseShow "LINK"
                        curhot = 1
                        If lb = 2 Then
                            If altmenu Then ' Toggle menu highlighting off.
                                alt% = 1: Gui_Drop_Menu_Headings c, b$, heading$(), MapHeading$(), alt%, altmenu, altdown, selection, TopMenuChoice
                                altdown = 0 ' Force this here because the cycle hasn't gone back to the mouse sub yet.
                            End If
                            If mhl Then ' Get rid of previous highlighted item if switching menus.
                                Locate m.top - pop + mhl + (mhl - 1) * spacing, m.left - pop + 2 - 1: Color c.MenuFg, c.MenuBg: Print " " + a$(mhl) + " "; ' Unhighlight.
                                mhl = 0
                            End If
                            selection = j ' The menu selected to be opened.
                            MenuOpen = my ' The row the selected menu occupies.
                            If MenuOpen = 1 Then ' IMPORTANT Change this to allow for top menu to be on a different row.
                                TopMenuChoice = selection

                                alt% = 1: Gui_Drop_Menu_Headings c, b$, heading$(), MapHeading$(), alt%, altmenu, altdown, selection, TopMenuChoice

                            End If
                            Exit Do
                        End If
                    Else ' Mouse pointer is at top or footer menu in a non-clickable area.
                        curhot = 0
                    End If
                Else
                    curhot = 0 ' Mouse is not on a clickable menu row.
                End If
                j = 0
                GoSub check_top_menu_status
                If MenuType$ = "display" Then
                    GoSub eval: If pete Then Exit Sub
                End If
                Exit Do
            Loop
            If selection Then
                If CurStyle And mshow$ <> "DEFAULT" Then mshow$ = "DEFAULT": _MouseShow mshow$ ' Remove link mouse appearance.
                curhot = 0
                Select Case my
                    Case 1 ' Top menu.
                        GoSub top_menu ' Opens the selected top menu.
                    Case _Height ' The footer menu.
                        Select Case selection
                            Case 1
                                Restore help_data
                                help$ = ""
                                Do
                                    Read d$
                                    If d$ = "eof" Then Exit Do
                                    help$ = help$ + Chr$(13) + Chr$(10) + Chr$(13) + Chr$(10) + d$
                                Loop
                                _MessageBox " App Help", help$, ""
                                MenuOpen = 0: selection = 0 ' Needed to clear variables.
                            Case 2: System
                        End Select
                End Select
            End If
        Case Else ' A header menu is open.
            If alt% Then alt% = 0: b$ = Chr$(27) ' Toggle close header menu.
            GoSub eval: If pete Then Exit Sub
    End Select
    oldmy = my: oldmx = mx
    Exit Sub

    eval:
    ' Evaluate mouse field.
    If my > m.top - pop And my < m.top - pop + m.height - 1 And mx > m.left - pop + 1 And mx < m.left - pop + m.width - 2 Then
        MouseField$ = "mouse-in"
    Else
        MouseField$ = "mouse-out"
        If CurStyle And mshow$ <> "DEFAULT" And curhot = 0 Then mshow$ = "DEFAULT": _MouseShow mshow$
    End If
    If oldmy And my <> oldmy Or oldmy And mx <> oldmx Then ' Only for header menus.
        If Len(MapHeading$(MenuOpen)) And my = MenuOpen Then
            j = Asc(Mid$(MapHeading$(MenuOpen), mx, 1)) - 96
            GoSub slider ' Sliding mouse to open menus.
        End If
    End If
    If lb <> 0 Or mb <> 0 Or mw <> 0 Or Len(b$) Then ' An event occured.
        If lb = 2 Then
            Select Case MouseField$
                Case "mouse-in"
                    j = (my - m.top + pop + spacing) / (spacing + 1)
                    If j And Int(j) = j Then
                        If j <> mhl And Len(LTrim$(a$(j))) Then
                            GoSub menu_item_highlight
                            _Delay .1
                        End If
                        If MenuType$ = "display" Then
                            b$ = LTrim$(Str$(mhl))
                        Else ' "header"
                            j = mhl: GoSub menu_item_selected
                        End If
                    Else
                        If mhl Then
                            Locate m.top - pop + mhl + (mhl - 1) * spacing, m.left - pop + 2 - 1: Color c.MenuFg, c.MenuBg: Print " " + a$(mhl) + " "; ' Unhighlight.
                            mhl = 0
                        End If
                    End If
                Case "mouse-out"
                    GoSub closeit: If sucker = -1 Then GoSub top_menu
            End Select
        ElseIf mb Then
            If mhl Then
                If MenuType$ = "display" Then
                    b$ = LTrim$(Str$(mhl))
                Else ' "header"
                    j = mhl: GoSub menu_item_selected
                End If
            End If
        ElseIf mw Then
            i = mw: GoSub next_menu_item
        End If
        If Len(b$) Then
            Select Case MenuType$
                Case "display"
                    Do
                        Select Case b$
                            Case Chr$(0) + "H"
                                i = -1: GoSub next_menu_item: b$ = ""
                            Case Chr$(0) + "P"
                                i = 1: GoSub next_menu_item: b$ = ""
                            Case "1": spacing = 0
                            Case "2": spacing = 1
                            Case "3": spacing = 2
                            Case "4": justify = 1 - justify
                            Case "5"
                                Select Case c.PageBg
                                    Case 0: PageAltFg = c.PageFg: PageAltBg = 1
                                    Case 1: PageAltFg = c.PageFg: PageAltBg = 0
                                End Select
                            Case "6"
                                CurStyle = 1 - CurStyle
                                If CurStyle = 0 Then
                                    If mshow$ <> "DEFAULT" Then mshow$ = "DEFAULT": _MouseShow mshow$
                                End If
                            Case "7"
                                pop = 1 - pop
                            Case Chr$(0) + Chr$(59), "F1"
                                Restore help_data
                                help$ = ""
                                Do
                                    Read d$
                                    If d$ = "eof" Then Exit Do
                                    help$ = help$ + Chr$(13) + Chr$(10) + Chr$(13) + Chr$(10) + d$
                                Loop
                                _MessageBox " App Help", help$, ""
                                b$ = ""
                            Case Chr$(13)
                                If mhl Then b$ = LTrim$(Str$(mhl)): _Continue
                            Case Chr$(27): System
                            Case Else
                                b$ = ""
                        End Select
                        Exit Do
                    Loop
                    If Len(b$) Then pete = 1: mhl = 0
                Case Else ' "header" or "suckerfish"
                    Select Case b$
                        Case Chr$(0) + "H"
                            i = -1: GoSub next_menu_item
                        Case Chr$(0) + "P"
                            i = 1: GoSub next_menu_item
                        Case Chr$(0) + "M" ' Enter alternative for suckerfish menu symbol.
                            If InStr(a$(mhl), Chr$(26)) Then
                                selection = TopMenuChoice ' Get the top menu number.
                                j = mhl: GoSub menu_item_selected ' Get the number of the item selected.
                            Else
                                j = TopMenuChoice + 1
                                If j > Asc(Right$(RTrim$(MapHeading$(1)), 1)) - Asc(Left$(LTrim$(MapHeading$(1)), 1)) + 1 Then j = 1
                                b$ = "": GoSub slider
                            End If
                        Case Chr$(0) + "K" ' Esc alternative for suckerfish menu.
                            If sucker > 0 Then
                                GoSub closeit: If sucker = -1 Then GoSub top_menu
                            Else
                                j = TopMenuChoice - 1
                                If j = 0 Then j = Asc(Right$(RTrim$(MapHeading$(1)), 1)) - Asc(Left$(LTrim$(MapHeading$(1)), 1)) + 1
                                b$ = "": GoSub slider
                            End If
                        Case Chr$(13)
                            selection = TopMenuChoice
                            j = mhl: GoSub menu_item_selected
                        Case Chr$(27)
                            GoSub closeit: If sucker = -1 Then GoSub top_menu
                        Case "a" To "z", "A", "Z"
                            For j = 1 To dcnt
                                If Len(abr$(j)) Then
                                    If UCase$(abr$(j)) = UCase$(b$) Then
                                        b$ = LTrim$(Str$(j))
                                        GoSub menu_item_selected
                                        Exit For
                                    End If
                                End If
                            Next
                    End Select
            End Select
        End If
    Else
        If MouseField$ = "mouse-in" Then
            If oldmy And my <> oldmy Or oldmy And mx <> oldmx Then
                j = (my - m.top + pop + spacing) / (spacing + 1)
                If j And Int(j) = j Then
                    If CurStyle And mshow$ <> "LINK" Then mshow$ = "LINK": _MouseShow mshow$
                    If j <> mhl And Len(LTrim$(a$(j))) Then
                        GoSub menu_item_highlight
                    End If
                Else
                    If CurStyle And mshow$ <> "DEFAULT" Then mshow$ = "DEFAULT": _MouseShow mshow$
                    If mhl Then
                        Locate m.top - pop + mhl + (mhl - 1) * spacing, m.left - pop + 2 - 1: Color c.MenuFg, c.MenuBg: Print " " + a$(mhl) + " "; ' Unhighlight.
                        mhl = 0
                    End If
                End If
            End If
        End If
    End If
    Return

    slider:
    If j > 0 And j <> selection Then
        mhl = 0: altmenu = 0: altdown = 0
        selection = j ' Leave MenuOpen as is.
        If sucker Then sucker = 0
        PCopy 1, 0
        TopMenuChoice = selection
        MenuOpen = 1 ' The row the selected menu occupies.

        alt% = 1: Gui_Drop_Menu_Headings c, b$, heading$(), MapHeading$(), alt%, altmenu, altdown, selection, TopMenuChoice

        GoSub top_menu
    End If
    Return

    check_top_menu_status:
    If lb = 2 Or rb = 2 Or mb = 2 Then ' Mouse Event.
        If altmenu Then ' Remove prep to open from top menu.
            b$ = Chr$(27): Gui_Drop_Menu_Headings c, b$, heading$(), MapHeading$(), alt%, altmenu, altdown, selection, TopMenuChoices
        End If
    End If
    Return

    top_menu:

    MenuType$ = "header": Gui_Data_Reader m, MapHeading$(), a$(), abr$(), sf(), dcnt, MenuType$, MenuOpen, spacing, pop, justify, selection, sucker

    If sucker <> -1 Then
        PCopy 0, 1

        Gui_Menu_Placement c, m, a$(), abr$(), dcnt, spacing, pop

    Else
        sucker = 0
    End If
    Return

    menu_item_highlight:
    s1 = CsrLin: s2 = Pos(0): c1 = _DefaultColor: c2 = _BackgroundColor
    If mhl Then ' Unhighlight the previous menu item.
        Locate m.top - pop + mhl + (mhl - 1) * spacing, m.left - pop + 2 - 1

        Gui_Show_Menu_Item c, mhl, a$(), abr$(), MenuType$

    End If
    Locate m.top - pop + j + (j - 1) * spacing, m.left - pop + 2 - 1
    Color c.MenuHlFg, c.MenuHlBg
    Print " " + a$(j) + " ";
    Locate s1, s2: Color c1, c2: mhl = j ' Highlight current.
    Return

    next_menu_item:
    j = mhl
    Do
        j = j + i: If j > UBound(a$) Or j < 1 Then j = 0: Exit Do
    Loop Until Len(LTrim$(a$(j))) ' Bypass dividers.
    If j Then GoSub menu_item_highlight
    Return

    suckerfish_menu:
    OldMenuType$ = MenuType$: oldmhl = mhl: m.oldtop = m.top: m.oldleft = m.left: m.oldwidth = m.width: oldselection = selection

    MenuType$ = "suckerfish": Gui_Data_Reader m, MapHeading$(), a$(), abr$(), sf(), dcnt, MenuType$, MenuOpen, spacing, pop, justify, selection, sucker

    mhl = 0 ' Don't unhighlight the parent menu, but zeroing mhl here revents the child menu from being highlighted at the parent level when it opens.
    PCopy 0, 2

    Gui_Menu_Placement c, m, a$(), abr$(), dcnt, spacing, pop

    Return

    menu_item_selected:
    If sf(j) And sucker = 0 Then ' Open suckerfish menu.
        sucker = sf(j)
        GoSub suckerfish_menu
    Else
        sucker = 0 ' Selection was made so close both windows.
        _Title a$(j)
        GoSub closeit

        MenuType$ = "display": Gui_Data_Reader m, MapHeading$(), a$(), abr$(), sf(), dcnt, MenuType$, MenuOpen, spacing, pop, justify, selection, sucker

    End If
    If mhl Then ' Get rid of previous highlighted item if switching menus.
        Locate m.top - pop + mhl + (mhl - 1) * spacing, m.left - pop + 2 - 1: Color c.MenuFg, c.MenuBg: Print " " + a$(mhl) + " "; ' Unhighlight.
        mhl = 0
    End If
    Return

    closeit:
    If sucker > 0 Then ' Closes suckerfish menu. Keeps parent menu open.
        PCopy 2, 0
        m.left = m.oldleft
        m.top = m.oldtop
        mhl = oldmhl
        selection = oldselection
        MenuType$ = OldMenuType$

        Gui_User MenuType$, spacing, justify, CurStyle, pop, selection, sucker

        sucker = -1
    Else
        If MenuType$ = "display" Then
            If mhl Then ' Get rid of previous highlighted item if switching menus.
                Locate m.top - pop + mhl + (mhl - 1) * spacing, m.left - pop + 2 - 1: Color c.MenuFg, c.MenuBg: Print " " + a$(mhl) + " "; ' Unhighlight.
                mhl = 0
            End If
        Else
            PCopy 1, 0
        End If
        MenuOpen = 0: selection = 0: MouseField$ = "": mhl = 0
        If sucker Then sucker = 0
        If CurStyle And mshow$ <> "DEFAULT" Then mshow$ = "DEFAULT": _MouseShow mshow$

        b$ = Chr$(27): Gui_Drop_Menu_Headings c, b$, heading$(), MapHeading$(), alt%, altmenu, altdown, selection, TopMenuChoice

        MenuType$ = "": TopMenuChoice = 0: altmenu = 0: altdown = 0
    End If
    Return
End Sub

Sub Gui_Menu_Placement (c As color, m As menu, a$(), abr$(), dcnt, spacing, pop)
    ' Centers height evenly for odd window heights and 1-space towards top for even.
    Locate m.top - pop, m.left - pop
    For h = 1 To dcnt
        If h = 1 Then
            Color c.MenuBdrFg, c.MenubrdBg
            Print Chr$(218) + String$(m.width - 2, 196) + Chr$(191)
            j = CsrLin
            For i = 1 To m.height - 2
                If CsrLin < _Height Then Locate j, m.left - pop Else Locate , m.left - pop
                Color c.MenuBdrFg, c.MenubrdBg: Print Chr$(179);
                Color c.MenuBdrFg, c.MenubrdBg: Print Space$(m.width - 2);
                Color c.MenuBdrFg, c.MenubrdBg: Print Chr$(179);
                j = j + 1
            Next
            Locate j, m.left - pop
            Color c.MenuBdrFg, c.MenubrdBg: Print Chr$(192) + String$(m.width - 2, 196) + Chr$(217);
            If pop Then ' Shadow effect.
                Color c.MenuSdwFg, c.MenuSdwBg ' Shadow below.
                Locate CsrLin + 1, m.left - pop + 2
                For i = 1 To m.width
                    j = Screen(CsrLin, Pos(0))
                    Print Chr$(j);
                Next
                Locate m.top - pop + 1 ' Shadow to the right.
                For i = 1 To m.height - 1
                    Locate , m.left - pop + m.width
                    j = Screen(CsrLin, Pos(0))
                    Print Chr$(j);
                    j = Screen(CsrLin, Pos(0))
                    Print Chr$(j)
                Next
            End If
        End If
        Color c.MenuFg, c.MenuBg
        Locate m.top - pop + h + (h - 1) * spacing, m.left - pop + 2 - 1
        If Len(LTrim$(a$(h))) Then

            Gui_Show_Menu_Item c, h, a$(), abr$(), MenuType$ ' Show each menu item in this for/next loop.

        Else
            Color c.MenuBdrFg, c.MenubrdBg
            Locate , Pos(0) - 1: Print Chr$(195);
            Print String$(m.width - 2, Chr$(196)) + Chr$(180);
        End If
    Next h
End Sub

Sub Gui_Show_Menu_Item (c As color, counter, a$(), abr$(), MenuType$)
    If MenuType$ = "display" Then
        j = 0
    Else
        j = InStr(a$(counter), abr$(counter))
    End If
    If j Then ' Color coded short-cut key selection.
        If j = 1 Then
            Print " ";: Color c.MenuAbr, c.MenuBg: Print Left$(a$(counter), 1);: Color c.MenuFg, c.MenuBg: Print Mid$(a$(counter), 2); " ";
        Else
            Color c.MenuFg, c.MenuBg: Print " " + Mid$(a$(counter), 1, j - 1);: Color c.MenuAbr, c.MenuBg: Print Mid$(a$(counter), j, 1);: Color c.MenuFg, c.MenuBg: Print Mid$(a$(counter), j + 1); " ";
        End If
    Else ' Menu selection without short-cut key.
        Color c.MenuFg, c.MenuBg: Print " " + a$(counter) + " ";
    End If
End Sub

Sub MyMouse_and_Keyboard (lb, mb, rb, my, mx, mw, shift%, alt%, clkcnt, drag, b$, autokey$)
    Static oldmy, oldmx, z1, hover, mwy, oldmwy
    If Len(autokey$) Then
        b$ = Mid$(autokey$, 1, InStr(autokey$ + ",", ",") - 1)
        autokey$ = Mid$(autokey$, InStr(autokey$ + ",", ",") + 1)
        Exit Sub
    Else
        k& = _KeyHit
        If k& = 100307 Or k& = 100308 Then alt% = -1: Exit Sub Else If alt% Then alt% = 0
        If k& > 0 Then
            b$ = MKI$(k&)
            If Right$(b$, 1) = Chr$(0) Then b$ = Left$(b$, 1)
        End If
    End If
    If z1 Then If Abs(Timer - z1) > .3 Then z1 = 0: clkcnt = 0
    If lb > 0 Then
        If lb = 1 Then
            lb = -1
        Else
            lb = 0
        End If
    End If
    If rb > 0 Then If rb = 1 Then rb = -1 Else rb = 0
    If mb > 0 Then If mb = 1 Then mb = -1 Else mb = 0
    While _MouseInput
        mwy = mwy + _MouseWheel
    Wend
    my = _MouseY
    mx = _MouseX
    b_hover = 0
    For i = 1 To nob ' number of buttons.
        If my >= y_btl(i) And my <= y_bbr(i) And mx >= x_btl(i) And mx <= x_bbr(i) Then
            b_hover = i
            Exit For
        End If
    Next
    If lb = -1 Then
        If oldmy And oldmx <> mx Or oldmy And oldmy <> my Then
            If mx <> oldmx Then drag = Sgn(mx - oldmx) ' Prevent zero which can occur if mouse moves off row when being dragged horizontally.
        End If
    End If
    If drag = 0 Then
        If mwy <> oldmw Then
            mw = Sgn(mwy - oldmwy): mwy = 0
        Else
            mw = 0
        End If
        oldmwy = mwy
        If _KeyDown(100303) Or _KeyDown(100304) Then shift% = -1 Else If shift% Then shift% = 0
    End If
    If lb = -1 And _MouseButton(1) = 0 Then
        lb = 2: drag = 0: hover = 0
    ElseIf rb = -1 And _MouseButton(2) = 0 Then
        rb = 2
    ElseIf mb = -1 And _MouseButton(3) = 0 Then
        mb = 2
    End If
    If _MouseButton(1) Then
        If lb = 0 Then
            lb = 1
            If z1 = 0 Then
                z1 = Timer ' Let first click go through.
            Else
                clkcnt = clkcnt + 1
            End If
        End If
    ElseIf _MouseButton(2) And rb = 0 Then
        rb = 1
    ElseIf _MouseButton(3) And mb = 0 Then
        mb = 1
    End If
    oldmy = my: oldmx = mx
End Sub

Next step is to herd up some of the variable names into more TYPEs and make a couple more GOSUB routines out of some minor repetitious code.

Pete
Reply
#2
Wow great work Pete!
Reply
#3
What NOT Sharing variables!?!? I have seen some disparagement of both Constants and Shared.

I understand Constants somewhat but Man! Shared? I would like to understand reasoning going into that decision. Is it only because you intend a Libary for Menu's.
b = b + ...
Reply
#4
I love shared variables, especially in the middle of a large project when I know I will be wasting a lot of time passing new variables to various subroutines.

I do have some large programs that have all shared variables, and no variables passed. They all work just fine.

Yes, for the sake of a library, it is a neater job to not used shared variables, but it is only a bulletproof measure if the programs or other libraries you add to it never contain shared variables with the same names.

So it's a matter of choice, and I love BASIC for being a language that offers up so many choices over other languages, even though this is not one of those instances.

Pete
Reply




Users browsing this thread: 2 Guest(s)