~eda-qa/dhlib/main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* <license>
 * This file is part of the dis-Emi-A HaXe Library. Copyright (c) edA-qa mort-ora-y
 * For full copyright and license information please refer to doc/license.txt.
 * </license> 
 */
package ui;

#if neko
import neash.events.Event;
#elseif flash
import flash.events.Event;
import flash.events.MouseEvent;
#end

class Events
{
	/**
	 * Use this to add global handlers since otherwise it is annoyting to try
	 * and wait for the stage in an added function to add these handlers.
	 */
	static public function addListener<T>( evt : String, func : T -> Void, ?priority : Null<Int> )
	{
		if( priority == null )
			priority = 0;
#if neko
		neash.Lib.current.stage.addEventListener( evt, func,false, priority, true /*weak*/ );
#elseif flash
		flash.Lib.current.stage.addEventListener( evt, func,false, priority, true /*weak*/ );
#end
	}
	
	static public function removeListener<T>( evt : String, func : T -> Void )
	{
#if neko
		neash.Lib.current.stage.removeEventListener( evt, func );
#elseif flash
		flash.Lib.current.stage.removeEventListener( evt, func );
#end
	}
	
	static public function dispatch( evt : Event )
	{
#if neko
		neash.Lib.current.stage.dispatchEvent( evt );
#elseif flash
		flash.Lib.current.stage.dispatchEvent( evt );
#end
	}
	
	/**
	 * Does the current VM support the ADDED_TO_STAGE and
	 * REMOVED_FROM_STAGE events.
	 */
	static public function supportsAddedToStage() : Bool
	{
#if neko
		//NEASH: unknown
		return null;
#elseif flash	
		if( _supportsAddedToStage == null )
			_supportsAddedToStage = system.Version.checkFlashVersion( "9.0.28" );
		return _supportsAddedToStage;
#end
	}
	//cache the result since it is called often by AnimatedWidget, and perhaps others
	static var _supportsAddedToStage : Null<Bool>;
	
#if flash	
	static var captureMouseEvents = [
		MouseEvent.MOUSE_DOWN, MouseEvent.MOUSE_UP, 
		MouseEvent.CLICK, MouseEvent.DOUBLE_CLICK,
		MouseEvent.MOUSE_WHEEL,
		MouseEvent.MOUSE_MOVE, MouseEvent.MOUSE_OVER, MouseEvent.MOUSE_OUT,
		MouseEvent.ROLL_OUT, MouseEvent.ROLL_OVER
		];
		
	/**
	 * Captures all mouse events and redispatches them to the provided object.
	 * This is a true capture, dispatching is then stopped in the main flow.
	 *
	 * NOTE: there are some potential caveats to how this works, to avoid them the
	 * receiver should follow these rules:
	 *		* Not dispatch an event subject to the capture
	 *		* call endCapture as soon as possible
	 *		* not change the display tree
	 *
	 * TODO: make Modal use this system, though heed warning about somethign wrong
	 * with capturing some mouse events
	 */
	static public function captureMouse( no : NativeObject )
	{
		capture( no, captureMouseEvents );
	}
	
	static var captureNO : NativeObject;
	static var captureEvents : Array<String>;
	static public var captureContProp : Bool; //continue propogation of the current event
	
	static function capture( no : NativeObject, events : Array<String> )
	{
		ASSERT_NULL( captureNO );
		captureNO = no;
		captureEvents = events;
		
		for( evt in captureEvents )
			flash.Lib.current.stage.addEventListener( evt, propagateEvent, true );
			
		//TODO: watch for object being removed and stop the capture
	}
	
	static public function endCapture( no : NativeObject )
	{
		ASSERT( no == captureNO );
		captureNO = null;
		
		for( evt in captureEvents )
			flash.Lib.current.stage.removeEventListener( evt, propagateEvent, true );
	}
	
	//used to stop the infinite recursion caused by the redispatch of the event
	static var inCapture : Bool = false;
	static function propagateEvent( evt : Event )
	{
		if( inCapture || !captureNO.hasEventListener( evt.type ) )
			return;
			
		inCapture = true;
		captureContProp = false;
		captureNO.dispatchEvent( evt.clone() );
		inCapture = false;
		
		if( !captureContProp )
			evt.stopPropagation();
	}
#end
}