|
|
|
Start Menu(xml)
Added on 10/17/2002
|
Start Menu(xml)
This is a tree structured menu behavior. The whole menu itself comes from the makeList() function of the XMLParser xtra this will be the 'Start Menu' itself. Then the menu will be presented by field castmembers. The depth of the structure isn't limited, just the screensize does that. You don't need sprites, just field members. You can use the myParent property to track back the attributes of the tree. The return function will have the number of the clicked line, the attributes of the menuitem, the parent menuitem's attributes, and the whole submenu too.
What will you need:
- You have to make a cast named 'menu' and place field castmembers there, as many as you will need from number 1.
- If you want a bitmap to be the background of the menus, name it 'background', and put it to the 'menu' cast, anywhere!
- You must have a 'startmenu_element_clicked' global function, because it will be called, when a menuelem clicked.
- A text or field castmember, that holds the menu structure. This member's text comes from the makeList() function of the XMLParser xtra.
(So the simplest thing is to make the menu in xml, and use the XMLPArser Xtra to have the list.)
Download PC Source
-- Start menu ; 2004.01.x
-- Author: Roti ; roti@al.pmmf.hu
-- Copyright (C)
-- CHANGELOG:
-- 2004.01.
-- new property myMinwidth -- the minimum width of the menu and submenus
-- new property mySubmenuloc -- where should the submenu appears, at the top, or beside the selected row
on getBehaviorDescription me
return "Start Menu"&RETURN&RETURN&"This is a tree structured menu behavior. The whole menu itself comes from the makeList() function of the XMLParser xtra this will be the 'Start Menu' itself. Then the menu will be presented by field castmembers. The depth of the structure isn't limited, just the screensize does that. You don't need sprites, just field members. You can use the myParent property to track back the attributes of the tree. The return function will have the number of the clicked line, the attributes of the menuitem, the parent menuitem's attributes, the whole submenu with just the QUOTEnameQUOTE attributes, the whole submenu, and the clicked linenumber in the xml." & RETURN & RETURN & "What will you need:"&RETURN&"- You have to make a cast named 'menu' and place field castmembers there, as many as you will need from number 1."&RETURN&"- If you want a bitmap to be the background of the menus, name it 'background', and put it to the 'menu' cast, anywhere!"&RETURN&"- You must have a 'startmenu_element_clicked' global function, because it will be called, when a menuelem clicked."&RETURN&"- A text or field castmember, that holds the menu structure. This member's text comes from the makeList() function of the XMLParser xtra."&RETURN&" (So the simplest thing is to make the menu in xml, and use the XMLPArser Xtra to have the list.)"
end getBehaviorDescription
on getBehaviorTooltip me
return "Use this behavior to make a Start Menu"
end getBehaviorTooltip
property mySprite -- my spritenumber
property myList -- The list, which comes from the makeList() function of the XMLParser xtra
-- it can be set from script, or can come from a text member; if it is empty, than nothing happens
property myAttrib -- which property of the list contains the names of the menuitems
-- if it is empty, than nothing happens, because the handler needs to know the attribute name,
-- which holds the name of the menuitem
property myDefbg -- the background color of the unselected menu
property myDeffg -- the color of the unselected text
property myFontsize -- the size of the text (should be an odd number because of Director's bug)
property myWidth -- the width of the menutiems
property myLocz -- the locz of the menu
property myFreesprite -- this is the sprite which presents the next menu
property myParent -- the parent sprite number
property mySub -- this is the deep
property myLine_ -- store the hilited line, to send mousedown if needed
property myDelay -- this is the delay to show the menu
property MyXmlLine -- store the clciked xml line
property myBlend -- this is the blend of the background of the menuitem, is exist
property myHilite -- is the hilite enabled? Yes=Void
-- 2004.01.
property myMinwidth -- the minimum width of the menu and submenus
property mySubmenuloc -- where should the submenu appears, at the top, or beside the selected row
on beginsprite me
-- Handle the tree type
case ilk(myList) of
#string:-- if it is a string
myList=value(myList)
#member:-- if it is the member, which holds the string
myList=value(member(myList).text)
end case
-- Handle, if we put the behavior by hand
if mySprite=Void then
mySprite = me.spriteNum
end if
end
on mouseWithin me
if mySub<2 then
abort
end if
myLine=the mouseline
if myLine<>-1 and mySprite<>Void and myHilite=Void then -- hiliting the appropriate line
chars=0
repeat with i = 1 to myLine-1-- It is needed to hilite the lines properly
chars=chars+sprite(mySprite).member.text.line[i].char.count
end repeat
sprite(mySprite).member.char[chars+myLine..chars+sprite(mySprite).member.text.line[myLine].char.count+myLine].hilite()
end if
if myLine_<>myLine and mySub then -- if we change the hilited line with the mouse
-- Use a delay if we aren't at the end
starttimer
else
if the timer>myDelay-5 and the timer the timer=myDelay+5
-- First check whether to hide submenus
closemenu()
if myLine=-1 then
myLine_=myLine -- store the hilited line
-- abort
end if
mousedown(me,the mouseline) -- open the menus
end if
end if
myLine_=myLine -- store the hilited line
end mouseWithin
on rightmousedown me
mousedown(me,the mouseline)
end
on mousedown me,myLine
-- close my submenu, if it is visible
if myFreesprite<>Void then
if sprite(myFreesprite).visible=true then
closemenu()
abort
end if
end if
-- store the mousecharacter
mc=the mousechar
-- The menu, which opened the menus, can close all
if mySub=1 or mySub=Void then -- if we have children
closemenu()
end if
-- Prevent quick mouse motions
if myLine=Void then
myLine=the mouseline
end if
-- Prevent, if we have another field behind the menu
if sprite(mySprite).member.type=#field then
if the number of lines in sprite(mySprite).member.text abort
end if
end if
myMousedown=the mousedown
if myMousedown=0 then
myMousedown=the rightMouseDown
end if
-- Check the mouse
if myLine<1 or mySub=Void then
if mySub>2 then
exit -- if the mouse ran away on some submenu
else
myLine=0 -- if this is the first menu, we will use the whole tree
end if
end if
-- Check the unwanted mouse triggers
if myList=Void then -- if we caught some mouse trigger, but we don't have the list, exit
exit
end if
-- Check if we reached the end of the submenus
if myList.count>1 and myLine+1<=myList.count then
if myList[myLine+1].count =1 then -- if there aren't any submenu, then return the attributes
-- The attributes of the menuitem, and the parent's attributes
if myMousedown then
-- tempmylist is a list, where only the myAttrib attributes presented
tempmylist=(myList).duplicate()
repeat with i=2 to tempmylist.count
if tempmylist[i][1][myAttrib]=Void then
tempmylist.deleteAt(i)
i=i-1
end if
end repeat
-- Here you can add further variables to pass ..........
startmenu_element_clicked(myLine,myList[myLine+1][1],myList[1],myList,tempmylist,sprite(myParent).MyXmlLine[myLine],the rightMouseDown)
end if
exit
end if
end if
-- Search for the next free sprite for the submenu, if needed
if myFreesprite=Void then -- search for the first free sprite from the given locz to +50
repeat with myFreesprite = myLocz to myLocz+50
if sprite(myFreesprite).type=0 then
exit repeat
end if
end repeat
-- if there aren't any free sprite
if myFreesprite=myLocz+50 then
alert "I can't find an empty sprite! from "&myLocz&" to "&myLocz+50&"!"
exit
end if
end if
if sprite(myFreesprite).visible=true and sprite(myFreesprite).type<>0 and sprite(myFreesprite).member<>member(0,0) then
exit
end if
-- Check, which part of the menu should we use
if myParent then
thelist=myList[myLine+1]
else
thelist=myList[1][2] -- if it is the first submenu
end if
-- Check if this is the first menu
if mySub=Void then
mySub=1
end if
-- myFreesprite holds the first free sprite
sprite(myFreesprite).type=16 -- set the type of the sprite
sprite(myFreesprite).forecolor=255 -- set the forecolor of the sprite
MyXmlLine=[]
repeat with i = 1 to thelist.count-1 -- fill the member with the text
if thelist[i+1][1][myAttrib]<>Void then
MenuText=MenuText&thelist[i+1][1][myAttrib]&RETURN
myXmlLine.add(i) -- store the clicked xml line
end if
end repeat
delete the last char of MenuText
if member(mySub,"menu").type=#empty then
alert "You don't have enough field members in the QUOTEmenuQUOTE cast!"
exit
end if
member(mySub,"menu").text=MenuText -- use the next submenu's member
if MenuText="" then
abort
end if
sprite(myFreesprite).member=member(mySub,"menu")
-- Check if it hasn't got this behavior
if sprite(myFreesprite).scriptInstanceList.getone("StartMenu")=0 then
sprite(myFreesprite).scriptInstanceList.add(script("StartMenu").new())
end if
-- the submenus inherit the main properties
sprite(myFreesprite).myList=thelist
sprite(myFreesprite).myLocz=myLocz+1
sprite(myFreesprite).myParent=mySprite
sprite(myFreesprite).myAttrib=myAttrib
sprite(myFreesprite).myDefbg=myDefbg
sprite(myFreesprite).myDeffg=myDeffg
sprite(myFreesprite).myFontsize=myFontsize
sprite(myFreesprite).mySub=mySub+1
sprite(myFreesprite).myWidth=myWidth
sprite(myFreesprite).myDelay=myDelay
sprite(myFreesprite).myBlend=myBlend
sprite(myFreesprite).myMinwidth=myMinwidth
sprite(myFreesprite).mySubmenuloc=mySubmenuloc
-- Set the width of the field
sprite(myFreesprite).member.rect=rect(0,0,8000,0)
-- calculate the new width, using picture object on the fly
repeat with ciklus = 1 to 100
if member(ciklus).type=#empty then
exit repeat
end if
end repeat
new(#text, member(ciklus))
member(ciklus).font=member(mySub,"menu").font
myStyle=member(mySub,"menu").fontStyle
the itemdelimiter=","
myNewStyle="["
repeat with i=1 to the number of items in myStyle
myNewStyle=myNewStyle&"#"&(item i of myStyle)&","
end repeat
delete the last item of myNewStyle
myNewStyle=myNewStyle&"]"
myNewStyle=value(myNewStyle)
member(ciklus).fontStyle=myNewStyle
member(ciklus).fontsize=member(mySub,"menu").fontsize
member(ciklus).text=MenuText
pict=member(ciklus).picture
member(ciklus).erase()
new(#bitmap, member(ciklus))
member(ciklus).picture=pict
newwidth=member(ciklus).width+member(mySub,"menu").border+member(mySub,"menu").margin -- this is the width
member(ciklus).erase()
if newwidth
if myMinwidth=Void then
myMinwidth=10
end if
if newwidth sprite(myFreesprite).member.rect=rect(0,0,myMinwidth,0)
else
sprite(myFreesprite).member.rect=rect(0,0,newwidth,0)
end if
else
sprite(myFreesprite).member.rect=rect(0,0,myWidth,0)
end if
-- Check, where to set the menuitem
t=the number of lines in MenuText
sprite(myFreesprite).visible=false
if mySub=1 then -- if it is the first menu
sprite(myFreesprite).loc=point(sprite(mySprite).left,sprite(mySprite).top-sprite(myFreesprite).member.height-5)
else
if mySubmenuloc="beside" then -- put it beside
sprite(myFreesprite).loc=point(sprite(mySprite).right+1,sprite(mySprite).top+sprite(mySprite).member.charPosToLoc(mc)[2]-20)
else -- put it to the top
sprite(myFreesprite).loc=point(sprite(mySprite).right+1,sprite(mySprite).top-20)
end if
end if
updateStage
-- Check if the submenu hits the bottom
if sprite(myFreesprite).bottom>(the stageBottom-the stagetop)-20 then
sprite(myFreesprite).loc=point(sprite(mySprite).right+2,((the stageBottom-the stagetop)-sprite(myFreesprite).member.height)-10)
end if
-- Check if the submenu hits the left side
if sprite(myFreesprite).left<0 then
sprite(myFreesprite).loch=2
end if
sprite(myFreesprite).member.backcolor=myDefbg
sprite(myFreesprite).member.forecolor=myDeffg
sprite(myFreesprite).member.fontsize=myFontsize
-- Use background if we have
if member("background","menu").type<>#empty then
updatestage
sprite(myFreesprite+1).visible=false
sprite(myFreesprite).ink=36
sprite(myFreesprite+1).type=16
sprite(myFreesprite+1).forecolor=255
sprite(myFreesprite+1).member=member("background","menu")
sprite(myFreesprite+1).locz=myFreesprite-1
sprite(myFreesprite+1).rect=sprite(myFreesprite).rect
sprite(myFreesprite+1).blend=myBlend
updatestage
sprite(myFreesprite+1).visible=true
end if
sprite(myFreesprite).visible=true
myHilite=1
if myParent<>Void then
chars=0
repeat with i = 1 to myLine-1-- It is needed to hilite the lines properly
chars=chars+sprite(mySprite).member.text.line[i].char.count
end repeat
sprite(mySprite).member.char[chars+myLine..chars+sprite(mySprite).member.text.line[myLine].char.count+myLine].hilite()
end if
-- Clear the unwanted selections
numofchars=the number of chars in MenuText
sprite(myFreesprite).member.char[numofchars+1].hilite()
sprite(myFreesprite).visible=true
sendsprite(myFreesprite,#beginsprite)
end
on closemenu -- close the submenus
if myFreesprite then
if sprite(myFreesprite).visible=true and string(sprite(myFreesprite).scriptinstancelist) contains "StartMenu" then -- and sprite(myFreesprite).member<>member(0,0) then -- sprite(myFreesprite).type<>0
sprite(myFreesprite).myLine_=Void
sprite(myFreesprite).visible=false
if sprite(myFreesprite+1).member.type=#bitmap then
sprite(myFreesprite+1).visible=false
end if
sendsprite(myFreesprite,#closemenu)
myHilite=Void
exit
end if
end if
end
on isOKToAttach (me, aSpriteType)
case aSpriteType of
#script:
return FALSE
otherwise:
RETURN TRUE
end case
end
on getPropertyDescriptionList
if the currentSpriteNum = 0 then exit
return [ #myList: [#comment: "Display which member's structure on rollover?", #format: #text, #default: ""], #myAttrib: [#comment: "which property of the list contains the name of the menuitem", #format: #string, #default:"name" ], #myDefbg: [#comment: "the default background color of the menu", #format: #integer, #default: 255 ], #myDeffg : [#comment: "the default color of the text", #format: #integer, #default: 0 ], #myLocz: [#comment: "the locz of the menu", #format: #integer, #default: 50 ], #myWidth: [#comment: "the width of the menuitems", #format: #integer, #default: 150 ], #myDelay: [#comment: "the delay to show the menu", #format: #integer, #default: 20 ], #myFontsize: [#comment: "the size of the text", #format: #integer, #default: 17], #myBlend: [#comment: "the blend of the menuitems backgruond image", #format: #integer, #range: [#min:0, #max:100]] , #myMinwidth: [#comment: "the minimum width of the menu and submenus", #format: #integer, #range: [#min:10, #max:800], default:10] , #mySubmenuloc: [#comment: "where should the submenu appears, at the top, or beside the selected row", #format: #string, #range: ["top", "beside"], default:"top"]]
end getPropertyDescriptionList
|
|