menu.monkey2 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. Namespace mojox
  2. #rem monkeydoc @hidden
  3. #end
  4. Class MenuSeparator Extends View
  5. Method New()
  6. Style=GetStyle( "MenuSeparator" )
  7. End
  8. End
  9. #rem monkeydoc @hidden
  10. #end
  11. Class MenuButton Extends Button
  12. Method New( text:String )
  13. Super.New( text )
  14. Style=GetStyle( "MenuButton" )
  15. TextGravity=New Vec2f( 0,.5 )
  16. Layout="fill-x"
  17. ' MinSize=New Vec2i( 100,0 )
  18. End
  19. Method New( action:Action )
  20. Super.New( action )
  21. Style=GetStyle( "MenuButton" )
  22. TextGravity=New Vec2f( 0,.5 )
  23. Layout="fill-x"
  24. ' MinSize=New Vec2i( 100,0 )
  25. _action=action
  26. End
  27. Method OnMeasure:Vec2i() Override
  28. Local size:=Super.OnMeasure()
  29. If _action
  30. Local hotKey:=_action.HotKeyText
  31. If hotKey size.x+=RenderStyle.Font.TextWidth( " "+hotKey )
  32. Endif
  33. Return size
  34. End
  35. Method OnRender( canvas:Canvas ) Override
  36. Super.OnRender( canvas )
  37. If _action
  38. Local hotKey:=_action.HotKeyText
  39. If hotKey
  40. Local w:=RenderStyle.Font.TextWidth( hotKey )
  41. Local tx:=(Width-w)
  42. Local ty:=(Height-MeasuredSize.y) * TextGravity.y
  43. canvas.DrawText( hotKey,tx,ty )
  44. Endif
  45. Endif
  46. End
  47. Field _action:Action
  48. End
  49. #rem monkeydoc The Menu class.
  50. #end
  51. Class Menu Extends DockingView
  52. #rem monkeydoc Creates a new menu.
  53. #end
  54. Method New( text:String="" )
  55. Style=GetStyle( "Menu" )
  56. Visible=False
  57. Layout="float"
  58. Gravity=New Vec2f( 0,0 )
  59. _text=text
  60. End
  61. #rem monkeydoc Menu text
  62. #end
  63. Property Text:String()
  64. Return _text
  65. End
  66. #rem monkeydoc Clears all items from the menu.
  67. #end
  68. Method Clear()
  69. Super.RemoveAllViews()
  70. End
  71. #rem monkeydoc Adds a view to the menu.
  72. #end
  73. Method AddView( view:View )
  74. AddView( view,"top" )
  75. End
  76. #rem monkeydoc Adds an action to the menu.
  77. #end
  78. Method AddAction( action:Action )
  79. Local button:=New MenuButton( action )
  80. button.Clicked=Lambda()
  81. CloseAll()
  82. '
  83. 'a bit gnarly, but makes sure menu is *really* closed...
  84. '
  85. App.RequestRender()
  86. App.Idle+=action.Trigger
  87. End
  88. AddView( button )
  89. End
  90. Method AddAction:Action( text:String )
  91. Local action:=New Action( text )
  92. AddAction( action )
  93. Return action
  94. End
  95. #rem monkeydoc Adds a separator to the menu.
  96. #end
  97. Method AddSeparator()
  98. AddView( New MenuSeparator,"top" )
  99. End
  100. #rem monkeydoc Adds a submenu to the menu.
  101. #end
  102. Method AddSubMenu( menu:Menu )
  103. Local button:=New MenuButton( menu.Text )
  104. button.Clicked=Lambda()
  105. If menu.Visible
  106. menu.Close()
  107. Else
  108. Local location:=New Vec2i( button.Bounds.Right,button.Bounds.Top )
  109. menu.Open( location,button,Self )
  110. Endif
  111. End
  112. AddView( button,"top" )
  113. End
  114. #rem monkeydoc Opens the menu.
  115. #end
  116. Method Open()
  117. Open( App.MouseLocation,App.ActiveWindow,Null )
  118. End
  119. #rem monkeydoc @hidden
  120. #end
  121. Method Open( location:Vec2i,view:View,owner:View )
  122. Assert( Not Visible )
  123. While Not _open.Empty And _open.Top<>owner
  124. _open.Top.Close()
  125. Wend
  126. If _open.Empty
  127. _filter=App.MouseEventFilter
  128. App.MouseEventFilter=MouseEventFilter
  129. Endif
  130. Local window:=view.Window
  131. location=view.TransformPointToView( location,window )
  132. window.AddChildView( Self )
  133. Offset=location
  134. Visible=True
  135. _owner=owner
  136. _open.Push( Self )
  137. End
  138. #rem monkeydoc @hidden
  139. #end
  140. Method Close()
  141. Assert( Visible )
  142. While Not _open.Empty
  143. Local menu:=_open.Pop()
  144. menu.Parent.RemoveChildView( menu )
  145. menu.Visible=False
  146. menu._owner=Null
  147. If menu=Self Exit
  148. Wend
  149. If Not _open.Empty Return
  150. App.MouseEventFilter=_filter
  151. _filter=Null
  152. End
  153. Private
  154. Field _text:String
  155. Field _owner:View
  156. Global _open:=New Stack<Menu>
  157. Global _filter:Void( MouseEvent )
  158. Function CloseAll()
  159. _open[0].Close()
  160. End
  161. Function MouseEventFilter( event:MouseEvent )
  162. If event.Eaten Return
  163. Local view:=event.View
  164. For Local menu:=Eachin _open
  165. If view.IsChildOf( menu ) Return
  166. Next
  167. If _open[0]._owner
  168. If view<>_open[0]._owner And view.IsChildOf( _open[0]._owner ) Return
  169. If event.Type=EventType.MouseDown
  170. CloseAll()
  171. Else
  172. ' event.Eat()
  173. Endif
  174. Else
  175. If event.Type=EventType.MouseDown
  176. CloseAll()
  177. Else
  178. ' event.Eat()
  179. Endif
  180. Endif
  181. End
  182. End
  183. Class MenuBar Extends ToolBar
  184. Method New()
  185. Style=GetStyle( "MenuBar" )
  186. Layout="fill-x"
  187. Gravity=New Vec2f( 0,0 )
  188. End
  189. Method AddMenu( menu:Menu )
  190. Local button:=New MenuButton( menu.Text )
  191. button.Clicked=Lambda()
  192. If menu.Visible
  193. menu.Close()
  194. Else
  195. Local location:=New Vec2i( button.Bounds.Left,button.Bounds.Bottom )
  196. menu.Open( location,button,Self )
  197. Endif
  198. End
  199. AddView( button )
  200. End
  201. End