]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/MouseCursorContext.java
Merge "List the unsatisfied dependencies in CanvasContext"
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / canvas / impl / MouseCursorContext.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.g2d.canvas.impl;\r
13 \r
14 import java.awt.Cursor;\r
15 import java.lang.reflect.Method;\r
16 import java.util.HashMap;\r
17 import java.util.Map;\r
18 import java.util.Stack;\r
19 \r
20 import org.simantics.g2d.canvas.IMouseCursorContext;\r
21 import org.simantics.g2d.canvas.IMouseCursorHandle;\r
22 import org.simantics.g2d.canvas.IMouseCursorHandleListener;\r
23 import org.simantics.g2d.canvas.IMouseCursorListener;\r
24 import org.simantics.utils.datastructures.ListenerList;\r
25 import org.simantics.utils.threads.IThreadWorkQueue;\r
26 import org.simantics.utils.threads.SyncListenerList;\r
27 \r
28 /**\r
29  * @author Toni Kalajainen\r
30  */\r
31 public class MouseCursorContext implements IMouseCursorContext {\r
32 \r
33     protected Map<Integer, Stack<CursorReserve>> mouseCursorStack =\r
34         new HashMap<Integer, Stack<CursorReserve>>();\r
35 \r
36     protected SyncListenerList<IMouseCursorListener> cursorListeners =\r
37         new SyncListenerList<IMouseCursorListener>(IMouseCursorListener.class);\r
38     \r
39 \r
40     public void addCursorListener(IMouseCursorListener listener) {\r
41         cursorListeners.add(listener);\r
42     }\r
43     public void addCursorListener(IMouseCursorListener listener, IThreadWorkQueue thread) {\r
44         cursorListeners.add(thread, listener);\r
45     }    \r
46     public void removeCursorListener(IMouseCursorListener listener) {\r
47         cursorListeners.remove(listener);\r
48     }\r
49     public void removeCursorListener(IMouseCursorListener listener, IThreadWorkQueue thread) {\r
50         cursorListeners.remove(thread, listener);\r
51     }\r
52     \r
53     private final static Method onCursorSet = SyncListenerList.getMethod(IMouseCursorListener.class, "onCursorSet");\r
54     protected void fireSetCursor(int mouseId, Cursor cursor) {\r
55         cursorListeners.fireEventSync(onCursorSet, this, mouseId, cursor);\r
56     }\r
57     protected void fireAsyncSetCursor(int mouseId, Cursor cursor) {\r
58         cursorListeners.fireEventAsync(onCursorSet, this, mouseId, cursor);\r
59     }\r
60         \r
61     \r
62     class CursorReserve implements IMouseCursorHandle\r
63     {\r
64         Cursor cursor;\r
65         int mouseId;\r
66         ListenerList<IMouseCursorHandleListener> listeners;        \r
67         public CursorReserve(Cursor cursor, int mouseId)\r
68         {\r
69             this.cursor = cursor;\r
70             this.mouseId = mouseId;\r
71         }\r
72         @Override        \r
73         public void remove() {\r
74             synchronized(MouseCursorContext.this)\r
75             {\r
76                 Stack<CursorReserve> cursorStack = mouseCursorStack.get(mouseId);\r
77                 if (cursorStack == null || !cursorStack.contains(this))\r
78                     return;\r
79                 \r
80                 boolean wasLast = cursorStack.lastElement()==this;\r
81                 cursorStack.remove(this);\r
82                 if (cursorStack.isEmpty()) {\r
83                     _setCursor(mouseId, null);\r
84                     return;\r
85                 }\r
86                 // Select the second last cursor\r
87                 if (wasLast) {\r
88                     CursorReserve newLast = cursorStack.peek();\r
89                     if (newLast==null) {\r
90                         _setCursor(mouseId, null);\r
91                     } else {\r
92                         Cursor newCursor = newLast.cursor;\r
93                         if (!cursor.equals(newCursor))\r
94                             _setCursor(mouseId, newCursor);                        \r
95                     }\r
96                 }\r
97             }\r
98         }\r
99         @Override\r
100         public Cursor getCursor() {\r
101             return cursor;\r
102         }\r
103         @Override\r
104         public int getMouseId() {\r
105             return mouseId;\r
106         }\r
107         void fireOnRemoved() {\r
108             ListenerList<IMouseCursorHandleListener> lis;\r
109             synchronized(this) {\r
110                 lis = listeners;\r
111                 if (lis==null) return;\r
112             }\r
113             \r
114             for (IMouseCursorHandleListener l : lis.getListeners())\r
115                 l.onMouseCursorRemoved(this);\r
116         }\r
117         \r
118         @Override\r
119         public synchronized void addMouseCursorHandleListener(IMouseCursorHandleListener listener) {\r
120             if (listeners == null) {\r
121                 listeners = new ListenerList<IMouseCursorHandleListener>(IMouseCursorHandleListener.class);\r
122             }\r
123             listeners.add(listener);\r
124         }\r
125         @Override\r
126         public synchronized void removeMouseCursorHandleListener(IMouseCursorHandleListener listener) {\r
127             if (listeners == null) return;\r
128             listeners.remove(listener);\r
129         }      \r
130     }\r
131     \r
132     @Override\r
133     public synchronized IMouseCursorHandle setCursor(int mouseId, Cursor cursor) {\r
134         assert(cursor!=null);\r
135         Stack<CursorReserve> cursorStack = mouseCursorStack.get(mouseId);\r
136         if (cursorStack == null) {\r
137             cursorStack = new Stack<CursorReserve>();\r
138             mouseCursorStack.put(mouseId, cursorStack);\r
139         }\r
140         CursorReserve cr = new CursorReserve(cursor, mouseId);\r
141         cursorStack.push(cr);\r
142         _setCursor(mouseId, cursor);\r
143         return cr;\r
144     }\r
145     \r
146     protected void _setCursor(int mouseId, Cursor cursor)\r
147     {\r
148         fireAsyncSetCursor(mouseId, cursor);    \r
149     }\r
150     \r
151     \r
152 }\r