PageRenderTime 72ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/src/org/openzoom/flash/components/MultiScaleContainer.as

http://github.com/openzoom/sdk
ActionScript | 846 lines | 447 code | 147 blank | 252 comment | 27 complexity | a3ca3b59498d70c15fdd8a488610f4bf MD5 | raw file
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // OpenZoom SDK
  4. //
  5. // Version: MPL 1.1/GPL 3/LGPL 3
  6. //
  7. // The contents of this file are subject to the Mozilla Public License Version
  8. // 1.1 (the "License"); you may not use this file except in compliance with
  9. // the License. You may obtain a copy of the License at
  10. // http://www.mozilla.org/MPL/
  11. //
  12. // Software distributed under the License is distributed on an "AS IS" basis,
  13. // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  14. // for the specific language governing rights and limitations under the
  15. // License.
  16. //
  17. // The Original Code is the OpenZoom SDK.
  18. //
  19. // The Initial Developer of the Original Code is Daniel Gasienica.
  20. // Portions created by the Initial Developer are Copyright (c) 2007-2010
  21. // the Initial Developer. All Rights Reserved.
  22. //
  23. // Contributor(s):
  24. // Daniel Gasienica <daniel@gasienica.ch>
  25. //
  26. // Alternatively, the contents of this file may be used under the terms of
  27. // either the GNU General Public License Version 3 or later (the "GPL"), or
  28. // the GNU Lesser General Public License Version 3 or later (the "LGPL"),
  29. // in which case the provisions of the GPL or the LGPL are applicable instead
  30. // of those above. If you wish to allow use of your version of this file only
  31. // under the terms of either the GPL or the LGPL, and not to allow others to
  32. // use your version of this file under the terms of the MPL, indicate your
  33. // decision by deleting the provisions above and replace them with the notice
  34. // and other provisions required by the GPL or the LGPL. If you do not delete
  35. // the provisions above, a recipient may use your version of this file under
  36. // the terms of any one of the MPL, the GPL or the LGPL.
  37. //
  38. ////////////////////////////////////////////////////////////////////////////////
  39. package org.openzoom.flash.components
  40. {
  41. import flash.display.DisplayObject;
  42. import flash.display.Graphics;
  43. import flash.display.Shape;
  44. import flash.display.Sprite;
  45. import flash.events.Event;
  46. import flash.geom.Point;
  47. import flash.geom.Rectangle;
  48. import org.openzoom.flash.core.openzoom_internal;
  49. import org.openzoom.flash.events.ViewportEvent;
  50. import org.openzoom.flash.net.ILoaderClient;
  51. import org.openzoom.flash.net.INetworkQueue;
  52. import org.openzoom.flash.net.NetworkQueue;
  53. import org.openzoom.flash.renderers.IRenderer;
  54. import org.openzoom.flash.renderers.images.ImagePyramidRenderManager;
  55. import org.openzoom.flash.renderers.images.ImagePyramidRenderer;
  56. import org.openzoom.flash.scene.IMultiScaleScene;
  57. import org.openzoom.flash.scene.IReadonlyMultiScaleScene;
  58. import org.openzoom.flash.scene.MultiScaleScene;
  59. import org.openzoom.flash.utils.IDisposable;
  60. import org.openzoom.flash.viewport.INormalizedViewport;
  61. import org.openzoom.flash.viewport.IViewportConstraint;
  62. import org.openzoom.flash.viewport.IViewportController;
  63. import org.openzoom.flash.viewport.IViewportTransformer;
  64. import org.openzoom.flash.viewport.NormalizedViewport;
  65. use namespace openzoom_internal;
  66. /**
  67. * Flash component for creating Zoomable User Interfaces.
  68. */
  69. public final class MultiScaleContainer extends Sprite
  70. implements ILoaderClient,
  71. IDisposable
  72. {
  73. include "../core/Version.as"
  74. //--------------------------------------------------------------------------
  75. //
  76. // Class constants
  77. //
  78. //--------------------------------------------------------------------------
  79. private static const DEFAULT_VIEWPORT_WIDTH:Number = 800
  80. private static const DEFAULT_VIEWPORT_HEIGHT:Number = 600
  81. private static const DEFAULT_SCENE_WIDTH:Number = 24000
  82. private static const DEFAULT_SCENE_HEIGHT:Number = 18000
  83. private static const DEFAULT_SCENE_BACKGROUND_COLOR:uint = 0x333333
  84. private static const DEFAULT_SCENE_BACKGROUND_ALPHA:Number = 0
  85. //--------------------------------------------------------------------------
  86. //
  87. // Constructor
  88. //
  89. //--------------------------------------------------------------------------
  90. /**
  91. * Constructor.
  92. */
  93. public function MultiScaleContainer()
  94. {
  95. createChildren()
  96. }
  97. //--------------------------------------------------------------------------
  98. //
  99. // Variables
  100. //
  101. //--------------------------------------------------------------------------
  102. private var mouseCatcher:Sprite
  103. private var contentMask:Shape
  104. // TODO: Consider applying dependency injection (DI)
  105. private var renderManager:ImagePyramidRenderManager
  106. //--------------------------------------------------------------------------
  107. //
  108. // Properties
  109. //
  110. //--------------------------------------------------------------------------
  111. //----------------------------------
  112. // scene
  113. //----------------------------------
  114. private var _scene:MultiScaleScene
  115. /**
  116. * @copy org.openzoom.flash.viewport.IViewport#scene
  117. */
  118. public function get scene():IMultiScaleScene
  119. {
  120. return _scene
  121. }
  122. //----------------------------------
  123. // viewport
  124. //----------------------------------
  125. private var _viewport:NormalizedViewport
  126. /**
  127. * Viewport of this container.
  128. */
  129. public function get viewport():NormalizedViewport
  130. {
  131. return _viewport
  132. }
  133. //----------------------------------
  134. // constraint
  135. //----------------------------------
  136. private var _constraint:IViewportConstraint
  137. /**
  138. * Constraint of this container.
  139. *
  140. * @see org.openzoom.flash.viewport.constraints.CenterConstraint
  141. * @see org.openzoom.flash.viewport.constraints.ScaleConstraint
  142. * @see org.openzoom.flash.viewport.constraints.ZoomConstraint
  143. * @see org.openzoom.flash.viewport.constraints.CompositeConstraint
  144. * @see org.openzoom.flash.viewport.constraints.NullConstraint
  145. */
  146. public function get constraint():IViewportConstraint
  147. {
  148. return _constraint
  149. }
  150. public function set constraint(value:IViewportConstraint):void
  151. {
  152. if (viewport)
  153. viewport.transformer.constraint = value
  154. }
  155. //----------------------------------
  156. // loader
  157. //----------------------------------
  158. private var _loader:INetworkQueue
  159. public function get loader():INetworkQueue
  160. {
  161. return _loader
  162. }
  163. public function set loader(value:INetworkQueue):void
  164. {
  165. _loader = value
  166. }
  167. //----------------------------------
  168. // transformer
  169. //----------------------------------
  170. private var _transformer:IViewportTransformer
  171. /**
  172. * @inheritDoc
  173. */
  174. public function get transformer():IViewportTransformer
  175. {
  176. return _transformer
  177. }
  178. public function set transformer(value:IViewportTransformer):void
  179. {
  180. if (viewport)
  181. viewport.transformer = value
  182. }
  183. //----------------------------------
  184. // controllers
  185. //----------------------------------
  186. private var _controllers:Array = []
  187. ;[ArrayElementType("org.openzoom.flash.viewport.IViewportController")]
  188. /**
  189. * Controllers of type IViewportController applied to this MultiScaleImage.
  190. * For example, viewport controllers are used to navigate the MultiScaleImage
  191. * by mouse or keyboard.
  192. *
  193. * @see org.openzoom.flash.viewport.controllers.MouseController
  194. * @see org.openzoom.flash.viewport.controllers.KeyboardController
  195. * @see org.openzoom.flash.viewport.controllers.ContextMenuController
  196. */
  197. public function get controllers():Array
  198. {
  199. return _controllers.slice(0)
  200. }
  201. public function set controllers(value:Array):void
  202. {
  203. // remove old controllers
  204. for each (var oldController:IViewportController in _controllers)
  205. removeController(oldController)
  206. _controllers = []
  207. // add new controllers
  208. for each (var controller:IViewportController in value)
  209. addController(controller)
  210. }
  211. //--------------------------------------------------------------------------
  212. //
  213. // Properties: Scene
  214. //
  215. //--------------------------------------------------------------------------
  216. //----------------------------------
  217. // sceneWidth
  218. //----------------------------------
  219. public function get sceneWidth():Number
  220. {
  221. return scene.sceneWidth
  222. }
  223. public function set sceneWidth(value:Number):void
  224. {
  225. scene.sceneWidth = value
  226. }
  227. //----------------------------------
  228. // sceneHeight
  229. //----------------------------------
  230. public function get sceneHeight():Number
  231. {
  232. return scene.sceneHeight
  233. }
  234. public function set sceneHeight(value:Number):void
  235. {
  236. scene.sceneHeight = value
  237. }
  238. //--------------------------------------------------------------------------
  239. //
  240. // Overridden methods: UIComponent
  241. //
  242. //--------------------------------------------------------------------------
  243. private function createChildren():void
  244. {
  245. if (!scene)
  246. createScene()
  247. if (!viewport)
  248. createViewport(_scene)
  249. if (!mouseCatcher)
  250. createMouseCatcher()
  251. if (!contentMask)
  252. createContentMask()
  253. if (!loader)
  254. createLoader()
  255. if (!renderManager)
  256. createRenderManager()
  257. }
  258. //--------------------------------------------------------------------------
  259. //
  260. // Overridden properties: DisplayObjectContainer
  261. //
  262. //--------------------------------------------------------------------------
  263. override public function get numChildren():int
  264. {
  265. return scene ? _scene.numChildren:0
  266. }
  267. //--------------------------------------------------------------------------
  268. //
  269. // Overridden methods: DisplayObjectContainer
  270. //
  271. //--------------------------------------------------------------------------
  272. override public function addChild(child:DisplayObject):DisplayObject
  273. {
  274. return addChildAt(child, numChildren)
  275. }
  276. override public function removeChild(child:DisplayObject):DisplayObject
  277. {
  278. return removeChildAt(getChildIndex(child))
  279. }
  280. override public function addChildAt(child:DisplayObject,
  281. index:int):DisplayObject
  282. {
  283. var renderer:IRenderer = child as IRenderer
  284. if (renderer)
  285. {
  286. renderer.viewport = _viewport
  287. renderer.scene = IReadonlyMultiScaleScene(_scene)
  288. var imagePyramidRenderer:ImagePyramidRenderer = renderer as ImagePyramidRenderer
  289. if (imagePyramidRenderer)
  290. renderManager.addRenderer(imagePyramidRenderer)
  291. }
  292. return _scene.addChildAt(child, index)
  293. }
  294. override public function removeChildAt(index:int):DisplayObject
  295. {
  296. var child:DisplayObject = _scene.getChildAt(index)
  297. var renderer:IRenderer = child as IRenderer
  298. if (renderer)
  299. {
  300. var imagePyramidRenderer:ImagePyramidRenderer = renderer as ImagePyramidRenderer
  301. if (imagePyramidRenderer)
  302. renderManager.removeRenderer(imagePyramidRenderer)
  303. renderer.scene = null
  304. renderer.viewport = null
  305. }
  306. return _scene.removeChildAt(index)
  307. }
  308. override public function swapChildren(child1:DisplayObject,
  309. child2:DisplayObject):void
  310. {
  311. _scene.swapChildren(child1, child2)
  312. }
  313. override public function swapChildrenAt(index1:int,
  314. index2:int):void
  315. {
  316. _scene.swapChildrenAt(index1, index2)
  317. }
  318. override public function setChildIndex(child:DisplayObject,
  319. index:int):void
  320. {
  321. _scene.setChildIndex(child, index)
  322. }
  323. override public function getChildAt(index:int):DisplayObject
  324. {
  325. return _scene.getChildAt(index)
  326. }
  327. override public function getChildIndex(child:DisplayObject):int
  328. {
  329. return _scene.getChildIndex(child)
  330. }
  331. override public function getChildByName(name:String):DisplayObject
  332. {
  333. return _scene.getChildByName(name)
  334. }
  335. //--------------------------------------------------------------------------
  336. //
  337. // Methods
  338. //
  339. //--------------------------------------------------------------------------
  340. private function createMouseCatcher():void
  341. {
  342. mouseCatcher = new Sprite()
  343. var g:Graphics = mouseCatcher.graphics
  344. g.beginFill(0x000000, 0)
  345. g.drawRect(0, 0, 100, 100)
  346. g.endFill()
  347. mouseCatcher.mouseEnabled = false
  348. super.addChildAt(mouseCatcher, 0)
  349. }
  350. private function createContentMask():void
  351. {
  352. contentMask = new Shape()
  353. var g:Graphics = contentMask.graphics
  354. g.beginFill(0xFF0000, 0)
  355. g.drawRect(0, 0, 100, 100)
  356. g.endFill()
  357. super.addChild(contentMask)
  358. mask = contentMask
  359. }
  360. //--------------------------------------------------------------------------
  361. //
  362. // Methods: Viewports
  363. //
  364. //--------------------------------------------------------------------------
  365. private function createViewport(scene:IReadonlyMultiScaleScene):void
  366. {
  367. _viewport = new NormalizedViewport(DEFAULT_VIEWPORT_WIDTH,
  368. DEFAULT_VIEWPORT_HEIGHT,
  369. scene)
  370. _viewport.addEventListener(ViewportEvent.TRANSFORM_START,
  371. viewport_transformStartHandler,
  372. false, 0, true)
  373. _viewport.addEventListener(ViewportEvent.TRANSFORM_UPDATE,
  374. viewport_transformUpdateHandler,
  375. false, 0, true)
  376. _viewport.addEventListener(ViewportEvent.TRANSFORM_END,
  377. viewport_transformEndHandler,
  378. false, 0, true)
  379. addEventListener(Event.ENTER_FRAME,
  380. enterFrameHandler,
  381. false, 0, true)
  382. }
  383. private function createScene():void
  384. {
  385. _scene = new MultiScaleScene(DEFAULT_SCENE_WIDTH,
  386. DEFAULT_SCENE_HEIGHT,
  387. DEFAULT_SCENE_BACKGROUND_COLOR,
  388. DEFAULT_SCENE_BACKGROUND_ALPHA)
  389. super.addChild(_scene)
  390. }
  391. private function createLoader():void
  392. {
  393. _loader = new NetworkQueue()
  394. }
  395. private function createRenderManager():void
  396. {
  397. renderManager = new ImagePyramidRenderManager(this, scene, viewport, loader)
  398. }
  399. //--------------------------------------------------------------------------
  400. //
  401. // Event handlers: Viewport
  402. //
  403. //--------------------------------------------------------------------------
  404. private function viewport_transformStartHandler(event:ViewportEvent):void
  405. {
  406. // trace("ViewportEvent.TRANSFORM_START")
  407. }
  408. private function viewport_transformUpdateHandler(event:ViewportEvent):void
  409. {
  410. // trace("ViewportEvent.TRANSFORM_UPDATE")
  411. invalidated = true
  412. }
  413. private var invalidated:Boolean = true
  414. private function viewport_transformEndHandler(event:ViewportEvent):void
  415. {
  416. // trace("ViewportEvent.TRANSFORM_END")
  417. }
  418. private function enterFrameHandler(event:Event):void
  419. {
  420. if (invalidated)
  421. updateDisplayList()
  422. }
  423. private function updateDisplayList():void
  424. {
  425. var v:INormalizedViewport = viewport
  426. var targetWidth:Number = v.viewportWidth / v.width
  427. var targetHeight:Number = v.viewportHeight / v.height
  428. var targetX:Number = -v.x * targetWidth
  429. var targetY:Number = -v.y * targetHeight
  430. var target:DisplayObject = scene.targetCoordinateSpace
  431. target.x = targetX
  432. target.y = targetY
  433. target.width = targetWidth
  434. target.height = targetHeight
  435. invalidated = false
  436. }
  437. //--------------------------------------------------------------------------
  438. //
  439. // Methods: Controllers
  440. //
  441. //--------------------------------------------------------------------------
  442. private function addController(controller:IViewportController):Boolean
  443. {
  444. if (_controllers.indexOf(controller) != -1)
  445. return false
  446. _controllers.push(controller)
  447. controller.viewport = viewport
  448. controller.view = this
  449. return true
  450. }
  451. private function removeController(controller:IViewportController):Boolean
  452. {
  453. if (_controllers.indexOf(controller) == -1)
  454. return false
  455. _controllers.splice(_controllers.indexOf(controller), 1)
  456. controller.viewport = null
  457. controller.view = null
  458. return true
  459. }
  460. //--------------------------------------------------------------------------
  461. //
  462. // Overridden properties: DisplayObject
  463. //
  464. //--------------------------------------------------------------------------
  465. //----------------------------------
  466. // width
  467. //----------------------------------
  468. override public function get width():Number
  469. {
  470. return mouseCatcher.width
  471. }
  472. override public function set width(value:Number):void
  473. {
  474. setActualSize(value, height)
  475. }
  476. //----------------------------------
  477. // height
  478. //----------------------------------
  479. override public function get height():Number
  480. {
  481. return mouseCatcher.height
  482. }
  483. override public function set height(value:Number):void
  484. {
  485. setActualSize(width, value)
  486. }
  487. //--------------------------------------------------------------------------
  488. //
  489. // Methods
  490. //
  491. //--------------------------------------------------------------------------
  492. public function setActualSize(width:Number, height:Number):void
  493. {
  494. if (this.width == width && this.height == height)
  495. return
  496. if (_viewport)
  497. _viewport.setSize(width, height)
  498. if (contentMask)
  499. {
  500. contentMask.width = width
  501. contentMask.height = height
  502. }
  503. if (mouseCatcher)
  504. {
  505. mouseCatcher.width = width
  506. mouseCatcher.height = height
  507. }
  508. }
  509. //--------------------------------------------------------------------------
  510. //
  511. // Properties
  512. //
  513. //--------------------------------------------------------------------------
  514. //----------------------------------
  515. // zoom
  516. //----------------------------------
  517. /**
  518. * @copy org.openzoom.flash.viewport.IViewport#zoom
  519. */
  520. public function get zoom():Number
  521. {
  522. return viewport.zoom
  523. }
  524. public function set zoom(value:Number):void
  525. {
  526. viewport.zoom = value
  527. }
  528. //----------------------------------
  529. // scale
  530. //----------------------------------
  531. /**
  532. * @copy org.openzoom.flash.viewport.IViewport#scale
  533. */
  534. public function get scale():Number
  535. {
  536. return viewport.zoom
  537. }
  538. public function set scale(value:Number):void
  539. {
  540. viewport.scale = value
  541. }
  542. //----------------------------------
  543. // viewportX
  544. //----------------------------------
  545. /**
  546. * @copy org.openzoom.flash.viewport.IViewport#x
  547. */
  548. public function get viewportX():Number
  549. {
  550. return viewport.x
  551. }
  552. public function set viewportX(value:Number):void
  553. {
  554. viewport.x = value
  555. }
  556. //----------------------------------
  557. // viewportY
  558. //----------------------------------
  559. /**
  560. * @copy org.openzoom.flash.viewport.IViewport#y
  561. */
  562. public function get viewportY():Number
  563. {
  564. return viewport.y
  565. }
  566. public function set viewportY(value:Number):void
  567. {
  568. viewport.y = value
  569. }
  570. //----------------------------------
  571. // viewportWidth
  572. //----------------------------------
  573. /**
  574. * @copy org.openzoom.flash.viewport.IViewport#width
  575. */
  576. public function get viewportWidth():Number
  577. {
  578. return viewport.width
  579. }
  580. public function set viewportWidth(value:Number):void
  581. {
  582. viewport.width = value
  583. }
  584. //----------------------------------
  585. // viewportHeight
  586. //----------------------------------
  587. /**
  588. * @copy org.openzoom.flash.viewport.IViewport#height
  589. */
  590. public function get viewportHeight():Number
  591. {
  592. return viewport.height
  593. }
  594. public function set viewportHeight(value:Number):void
  595. {
  596. viewport.height = value
  597. }
  598. //--------------------------------------------------------------------------
  599. //
  600. // Methods
  601. //
  602. //--------------------------------------------------------------------------
  603. /**
  604. * @copy org.openzoom.flash.viewport.IViewport#zoomTo()
  605. */
  606. public function zoomTo(zoom:Number,
  607. transformX:Number=0.5,
  608. transformY:Number=0.5,
  609. immediately:Boolean=false):void
  610. {
  611. viewport.zoomTo(zoom, transformX, transformY, immediately)
  612. }
  613. /**
  614. * @copy org.openzoom.flash.viewport.IViewport#zoomBy()
  615. */
  616. public function zoomBy(factor:Number,
  617. transformX:Number=0.5,
  618. transformY:Number=0.5,
  619. immediately:Boolean=false):void
  620. {
  621. viewport.zoomBy(factor, transformX, transformY, immediately)
  622. }
  623. /**
  624. * @copy org.openzoom.flash.viewport.IViewport#panTo()
  625. */
  626. public function panTo(x:Number, y:Number,
  627. immediately:Boolean=false):void
  628. {
  629. viewport.panTo(x, y, immediately)
  630. }
  631. /**
  632. * @copy org.openzoom.flash.viewport.IViewport#panBy()
  633. */
  634. public function panBy(deltaX:Number, deltaY:Number,
  635. immediately:Boolean=false):void
  636. {
  637. viewport.panBy(deltaX, deltaY, immediately)
  638. }
  639. /**
  640. * @copy org.openzoom.flash.viewport.IViewport#fitToBounds()
  641. */
  642. public function fitToBounds(bounds:Rectangle,
  643. scale:Number=1.0,
  644. immediately:Boolean=false):void
  645. {
  646. viewport.fitToBounds(bounds, scale, immediately)
  647. }
  648. /**
  649. * @copy org.openzoom.flash.viewport.IViewport#showAll()
  650. */
  651. public function showAll(immediately:Boolean=false):void
  652. {
  653. viewport.showAll(immediately)
  654. }
  655. /**
  656. * @copy org.openzoom.flash.viewport.IViewport#localToScene()
  657. */
  658. public function localToScene(point:Point):Point
  659. {
  660. return viewport.localToScene(point)
  661. }
  662. /**
  663. * @copy org.openzoom.flash.viewport.IViewport#sceneToLocal()
  664. */
  665. public function sceneToLocal(point:Point):Point
  666. {
  667. return viewport.sceneToLocal(point)
  668. }
  669. //--------------------------------------------------------------------------
  670. //
  671. // Methods: IDisposable
  672. //
  673. //--------------------------------------------------------------------------
  674. public function dispose():void
  675. {
  676. removeEventListener(Event.ENTER_FRAME,
  677. enterFrameHandler)
  678. _transformer = null
  679. controllers = []
  680. _constraint = null
  681. while (super.numChildren > 0)
  682. super.removeChildAt(0)
  683. mouseCatcher = null
  684. contentMask = null
  685. _viewport.removeEventListener(ViewportEvent.TRANSFORM_START,
  686. viewport_transformStartHandler)
  687. _viewport.removeEventListener(ViewportEvent.TRANSFORM_UPDATE,
  688. viewport_transformUpdateHandler)
  689. _viewport.removeEventListener(ViewportEvent.TRANSFORM_END,
  690. viewport_transformEndHandler)
  691. _viewport.dispose()
  692. _viewport = null
  693. _scene.dispose()
  694. _scene = null
  695. _loader.dispose()
  696. _loader = null
  697. }
  698. }
  699. }