AutoScrollManager Class: Scroll scrollbar when mouse is moving in a specified area and mouse button is down

konqside-bar Problem Summary: In a flex project, I need to insert an object to a object list which is derived from Container component. However, the list has fixed width and height, and the items of the list are too many to display one-time. So i have to scroll the list to the proper position then drag the object from a panel and insert it. I need a convenient way to complete this. I worte an AutoScrollManager utility to help myself.

Solution Summary: I add an event listener to the stage object of container’s systemManager object. It’s used to find the proper Container during the run-time because the container cannot trigger the MouseMove event while I am dragging the object from the panel. It is covered by what I am dragging. I have to find the proper container according to the Mouse coordinates. The function findContainer helps me a lot. Despite of this big problem, there is nothing hard to deal with.

Demo(DownloadDownload Full Project):

Press the left button of your mouse and do not release it. Move your mouse pointer inside the panel arbitrary. When the pointer moves around the texts, the scroll-bars scroll automatically.

Description: The AutoScrollManager provide two static functions to enable or disable auto-scrolling, addAutoScroll and removeAutoScroll, you should pass the target Container component to these functions. With the addAutoScroll function, there are another two parameters: scrollSpeed and bound. scrollSpeed determine the speed the scroll-bars scrolling. The bound is based on the model below:

clip_image002

viewMetrics is defined by the container self. Detailed info you will find in the flex SDK document.

* Returns an object that has four properties: <code>left</code>,

* <code>top</code>, <code>right</code>, and <code>bottom</code>.

* The value of each property equals the thickness of the chrome

* (visual elements) around the edge of the container.

Scroll bars appear when they are required.

Bound is defined by user. It is used to specify a particular area where the scroll bars scrolling automatically while the mouse is moving in it.

In this AutoScrollManger class , when the mouse is moving in the area of viewMetrics or Bound, the scroll bars scroll.

Codes:

  1. <?xml version=”1.0encoding=”utf-8?>
  2.  
  3. <mx:Application
  4.  
  5. xmlns:mx=”http://www.adobe.com/2006/mxml
  6.  
  7. layout=”absolute
  8.  
  9. xmlns:local=”*”
  10.  
  11. height=”200
  12.  
  13. width=”200
  14.  
  15. creationComplete=”initApp();”>
  16.  
  17. <mx:XML id=”myDataxmlns="">
  18.  
  19. <root>
  20.  
  21. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  22.  
  23. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  24.  
  25. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  26.  
  27. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  28.  
  29. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  30.  
  31. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  32.  
  33. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  34.  
  35. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  36.  
  37. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  38.  
  39. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  40.  
  41. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  42.  
  43. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  44.  
  45. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  46.  
  47. <item name=”asdfghjklasdfghjklasdfghjklasdfghjklasdfghjklasdfghjkl/>
  48.  
  49. </root>
  50.  
  51. </mx:XML>
  52.  
  53. <mx:Script>
  54.  
  55. <![CDATA[
  56.  
  57. private function initApp():void
  58.  
  59. {
  60.  
  61. AutoScrollingManager.addAutoScroll(myPan);
  62.  
  63. }
  64.  
  65. ]]>
  66.  
  67. </mx:Script>
  68.  
  69. <mx:Panel id=”myPanwidth=”{application.width}” height=”{application.height}”>
  70.  
  71. <mx:VBox width=”100%” height=”100%”>
  72.  
  73. <mx:Repeater id=”myRepdataProvider=”{myData.item}”>
  74.  
  75. <mx:Label text=”{myRep.currentItem.@name}”/>
  76.  
  77. </mx:Repeater>
  78.  
  79. </mx:VBox>
  80.  
  81. </mx:Panel>
  82.  
  83. </mx:Application>

Following is AutoScrollManager Class:

  1. import flash.display.Stage;
  2. import flash.events.Event;
  3. import flash.events.MouseEvent;
  4. import flash.geom.Point;
  5. import flash.utils.Dictionary;
  6. import mx.core.Container;
  7. import mx.core.EdgeMetrics;
  8.  
  9. public class AutoScrollingManager
  10. {
  11.  
  12. private static var managers:Dictionary = new Dictionary();
  13.  
  14. public var scrollSpeed:int = 10;
  15.  
  16. public var scrollFunction:Function = horizontalScroll;
  17.  
  18. private var _bound:EdgeMetrics;
  19.  
  20. public var bound:EdgeMetrics = new EdgeMetrics(20,20,20,20);
  21.  
  22. public static function addAutoScroll(container:Container,scrollSpeed:int = 10,bound:EdgeMetrics = null):void
  23. {
  24.  
  25. var manager:AutoScrollingManager = new AutoScrollingManager();
  26.  
  27. manager.scrollSpeed = scrollSpeed;
  28.  
  29. if(bound)manager.bound = bound;
  30.  
  31. managers[container] = manager;
  32.  
  33. container.systemManager.addEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);
  34.  
  35. container.systemManager.addEventListener(MouseEvent.MOUSE_UP,onMouseUp);
  36.  
  37. }
  38.  
  39. public static function removeAutoScroll(container:Container):void
  40. {
  41.  
  42. container.systemManager.removeEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);
  43.  
  44. container.systemManager.removeEventListener(MouseEvent.MOUSE_UP,onMouseUp);
  45.  
  46. if(managers[container])
  47. {
  48.  
  49. container.systemManager.removeEventListener(Event.ENTER_FRAME,managers[container].scrollFunction);
  50.  
  51. managers[container] = null;
  52.  
  53. }
  54.  
  55. }
  56.  
  57. private static function onMouseMove(event:MouseEvent):void
  58. {
  59.  
  60. var pt:Point = new Point(event.localX,event.localY);
  61.  
  62. var container:Container = findContainer(pt,event.currentTarget.stage);
  63.  
  64. if(!container)
  65.  
  66. return;
  67.  
  68. var manager:AutoScrollingManager = managers[container];
  69.  
  70. if(!event.buttonDown)
  71. {
  72.  
  73. container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
  74.  
  75. return;
  76.  
  77. }
  78.  
  79. var vm:EdgeMetrics = container.viewMetrics;
  80.  
  81. var _bound:EdgeMetrics = new EdgeMetrics();
  82.  
  83. _bound.bottom = manager.bound.bottom;
  84.  
  85. _bound.left = manager.bound.left;
  86.  
  87. _bound.right = manager.bound.right;
  88.  
  89. _bound.top = manager.bound.top;
  90.  
  91. if(container.horizontalScrollBar)_bound.bottom += container.horizontalScrollBar.height;
  92.  
  93. if(container.verticalScrollBar)_bound.right += container.verticalScrollBar.width;
  94.  
  95. if(vm.bottom!=0) _bound.bottom += vm.bottom;
  96.  
  97. if(vm.left!=0) _bound.left += vm.left;
  98.  
  99. if(vm.right!=0) _bound.right += vm.right;
  100.  
  101. if(vm.top!=0) _bound.top += vm.top;
  102.  
  103. pt = event.target.localToGlobal(pt);
  104. pt = container.globalToLocal(pt);
  105.  
  106. var insideLeftTopCorner:Boolean;
  107. var insideLeftBottomCorner:Boolean ;
  108. var insideRightTopCorner:Boolean;
  109. var insideRightBottomCorner:Boolean ;
  110.  
  111. insideLeftTopCorner = pt.x < _bound.left && pt.y < _bound.top;
  112. insideLeftBottomCorner = pt.x < _bound.left && pt.y > container.height - _bound.bottom;
  113. insideRightTopCorner = pt.x > container.width - _bound.right && pt.y < _bound.top;
  114.  
  115. insideRightBottomCorner = pt.x > container.width - _bound.right&& pt.y > container.height - _bound.bottom;
  116.  
  117. if(insideLeftTopCorner||insideLeftBottomCorner||insideRightTopCorner||insideRightBottomCorner)
  118. {
  119.  
  120. container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
  121.  
  122. return;
  123.  
  124. }
  125.  
  126. if(container.horizontalScrollBar)
  127. {
  128.  
  129. if(pt.y > container.height - container.horizontalScrollBar.height - vm.bottom)
  130. {
  131. return;
  132. }
  133.  
  134. manager.scrollFunction = horizontalScroll;
  135.  
  136. if(pt.x < _bound.left)
  137. {
  138. if( container.horizontalScrollPosition!=0)
  139. {
  140. container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
  141. container.systemManager.addEventListener(Event.ENTER_FRAME,manager.scrollFunction);
  142. manager.scrollSpeed = Math.abs(manager.scrollSpeed)*-1;
  143. }
  144. }
  145. else if((pt.x > container.width-_bound.right && pt.x < container.width - (container.verticalScrollBar?container.verticalScrollBar.width:0) - vm.right) || pt.x > container.width - vm.right)
  146. {
  147. if(container.horizontalScrollPosition!=container.maxHorizontalScrollPosition)
  148. {
  149. container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
  150. container.systemManager.addEventListener(Event.ENTER_FRAME,manager.scrollFunction);
  151. manager.scrollSpeed = Math.abs(manager.scrollSpeed);
  152. }
  153.  
  154. }
  155. else
  156. {
  157. container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
  158. }
  159.  
  160. }
  161.  
  162. if(container.verticalScrollBar)
  163. {
  164. if(pt.x > container.width - container.verticalScrollBar.width - vm.right)
  165. {
  166. return;
  167. }
  168.  
  169. manager.scrollFunction = verticalScroll;
  170.  
  171. if(pt.y < _bound.top)
  172. {
  173. if(container.verticalScrollPosition!=0)
  174. {
  175. container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
  176. container.systemManager.addEventListener(Event.ENTER_FRAME,manager.scrollFunction);
  177. manager.scrollSpeed = Math.abs(manager.scrollSpeed)*-1;
  178. }
  179. }
  180.  
  181. else if((pt.y > container.height - _bound.bottom && pt.y < container.height - (container.horizontalScrollBar?container.horizontalScrollBar.height:0) - vm.bottom) || pt.y > container.height - vm.bottom)
  182. {
  183. if(container.verticalScrollPosition!=container.maxVerticalScrollPosition)
  184. {
  185. container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
  186. container.systemManager.addEventListener(Event.ENTER_FRAME,manager.scrollFunction);
  187. manager.scrollSpeed = Math.abs(manager.scrollSpeed);
  188. }
  189. }
  190. else
  191. {
  192. container.systemManager.removeEventListener(Event.ENTER_FRAME,manager.scrollFunction);
  193. }
  194. }
  195. }
  196.  
  197. private static function onMouseUp(event:MouseEvent):void
  198. {
  199. event.currentTarget.removeEventListener(Event.ENTER_FRAME,horizontalScroll);
  200. event.currentTarget.removeEventListener(Event.ENTER_FRAME,verticalScroll);
  201. }
  202.  
  203. private static function horizontalScroll(event:Event):void
  204. {
  205. var pt:Point = new Point(event.currentTarget.stage.mouseX,event.currentTarget.stage.mouseY);
  206. var container:Container = findContainer(pt,event.currentTarget.stage);
  207.  
  208. if(!container)
  209. return;
  210.  
  211. container.horizontalScrollPosition += managers[container].scrollSpeed;
  212. }
  213.  
  214. private static function verticalScroll(event:Event):void
  215. {
  216. var pt:Point = new Point(event.currentTarget.stage.mouseX,event.currentTarget.stage.mouseY);
  217. var container:Container = findContainer(pt,event.currentTarget.stage);
  218.  
  219. if(!container)
  220. return;
  221.  
  222. container.verticalScrollPosition += managers[container].scrollSpeed;
  223. }
  224.  
  225. private static function findContainer(pt:Point,stage:Stage):Container
  226. {
  227. var objects:Array = stage.getObjectsUnderPoint(pt);
  228.  
  229. for each(var object:Object in objects)
  230. {
  231. var result:Object = doFind(object);
  232.  
  233. if(result!=null)
  234. {
  235. return Container(result);
  236. }
  237. }
  238. return null;
  239. }
  240.  
  241. private static function doFind(object:Object):Container
  242. {
  243. if(object.parent && object.parent is Container)
  244. {
  245. if(managers[object.parent] != null)
  246. {
  247. return object.parent;
  248. }
  249. else
  250. {
  251. return doFind(object.parent);
  252. }
  253. }
  254. return null;
  255. }
  256. }
Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • Reddit
  • Technorati
  • StumbleUpon
  • Twitter
RSS Enjoy this Post? Subscribe to Ntt.cc

RSS Feed   RSS Feed     Email Feed  Email Feed
You can leave a response, or trackback from your own site.

12 Responses to “AutoScrollManager Class: Scroll scrollbar when mouse is moving in a specified area and mouse button is down”

  1. neel says:

    sorry for the unapproprite comment.

    i am learning the flex and actually i need help regarding the generation of the mxml file from database. any sample code example or pointers ??

    appriciate ur help.
    thanks

  2. neel says:

    sorry for the unapproprite comment.

    i am learning the flex and actually i need help regarding the generation of the mxml file from database. any sample code example or pointers ??

    thanks

  3. edison says:

    That’s a good idea, it sounds interesting. I am digging for this now. :)

  4. AutoScrollManager Class: Scroll scrollbar when mouse is moving in a specified area and mouse button is down…

    Problem Summary: In a flex project, I need to
    insert an object to a object list which is derived from Container
    component. However, the list has fixed width and height, and the items
    of the list are too many to display one-time. So i have to scroll …

  5. edison says:

    With the use of XML_MXML(http://pear.php.net/package/XML_MXML), it is able to build flex documents programmatically.
    Is this what you want?
    Could you provide detailed information about your idea?

  6. neel says:

    thanks for showing interest.

    actually i am using the flex with the Jboss seam. i have to create diferent flex pages which actually loads the data from database for different requests (e.g account info request which contains only two fields account Id and balance,so the flex page contains only two fields, for some other request more attributes….and i ahve to generate the flex out of the attributes received from database). this i want because i have buch of requests which differs from each other on attribute basis.

    thanks

  7. [...] } Permalink:http://ntt.cc/2008/08/01/autoscrollmanager-class-scroll-scrollbar-when-mouse-is-moving-in-a-specifie… [...]

  8. Ntt.cc says:

    I think you can generate the flex pages using actionscript with flex. All you should do is to load data into flex and parse it to target components.

    Or does this swfgen (http://www.swfkit.com/swfgen.html) meet your requirement?

    Or this swfscout (http://www.bytescout.com/swfscout.html)

    I think the first one is quite easy. Make a module contains only one Form component. at the initialization process , load the attributes , then parse them as FormItem.

  9. hydra1983 says:

    http://www-128.ibm.com/developerworks/cn/opensource/os-php-flash/
    This is a PHP library used to generate Swf files programmatically which may help you.

  10. [..] A bit unrelated, but I absolutely liked this site post [..]

Leave a Reply