1 | // Copyright 2004-2007 Jean-Francois Poilpret |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | package net.sourceforge.hiveboard.drawing; |
16 | |
17 | import java.awt.Cursor; |
18 | import java.util.HashMap; |
19 | import java.util.List; |
20 | import java.util.Map; |
21 | |
22 | import javax.swing.JComponent; |
23 | import javax.swing.JToolBar; |
24 | |
25 | import org.apache.commons.logging.Log; |
26 | |
27 | import net.sourceforge.hiveboard.Board; |
28 | import net.sourceforge.hiveboard.Event; |
29 | import net.sourceforge.hiveboard.EventType; |
30 | import net.sourceforge.hiveboard.event.ConstraintEventFilter; |
31 | import net.sourceforge.hiveboard.event.Constraints; |
32 | import net.sourceforge.hiveboard.event.EventsPriorities; |
33 | import net.sourceforge.hiveboard.event.PersistentDeferredConsumer; |
34 | import net.sourceforge.hiveboard.main.IdentityHolder; |
35 | import net.sourceforge.hiveboard.view.DrawingArea; |
36 | import net.sourceforge.hiveboard.view.DrawingAreaHolder; |
37 | import net.sourceforge.hiveevents.Channel; |
38 | import net.sourceforge.hiveevents.PersistentConsumer; |
39 | |
40 | /** |
41 | * Handles all drawing tools, one-shot or mouse-driven. For mouse-driven tools, |
42 | * only one such tool can be active at a time. |
43 | * @author Jean-Francois Poilpret |
44 | */ |
45 | public class ToolHandlerImpl implements ToolHandler |
46 | { |
47 | public ToolHandlerImpl( Log logger, |
48 | ToolHandler thisHandler, |
49 | IdentityHolder holder, |
50 | Channel<Event> eventChannel, |
51 | Channel<DrawingAreaHolder> selectedBoardChannel, |
52 | DrawingActionSender sender, |
53 | List<ToolContribution> config) |
54 | { |
55 | _logger = logger; |
56 | _identity = holder; |
57 | _sender = sender; |
58 | |
59 | _display = new ToolDisplayHandler(thisHandler, config); |
60 | _mouseListener = new ToolMouseListener(_identity, _sender); |
61 | |
62 | // Register all tools |
63 | for (ToolContribution contrib: config) |
64 | { |
65 | _tools.put(contrib.getName(), contrib.getObject()); |
66 | } |
67 | |
68 | // Listen to changes in the current Board |
69 | int priority = EventsPriorities.SELECTED_IMAGE_LISTENERS_UPDATE; |
70 | selectedBoardChannel.registerPushConsumer(priority, new BoardSelectionConsumer()); |
71 | |
72 | // Listen to changes in the writer for current Board |
73 | priority = EventsPriorities.MENUS_UPDATE; |
74 | ConstraintEventFilter filter = |
75 | new ConstraintEventFilter(Constraints.eventType(EventType.EVT_GIVE_TOKEN)); |
76 | eventChannel.registerPushConsumer(priority, filter, new PersistentDeferredConsumer() |
77 | { |
78 | @Override protected void pushEvent(Event event) |
79 | { |
80 | // Important: do not put this test in the filter because the |
81 | // filter is called too soon (while _idBoard might have not been |
82 | // updated yet by the selectedBoardChannel consumer above. |
83 | if (event.getWhere() == _idBoard) |
84 | { |
85 | updateEnabling(); |
86 | } |
87 | } |
88 | }); |
89 | } |
90 | |
91 | public JToolBar getToolBar() |
92 | { |
93 | return _display.getToolBar(); |
94 | } |
95 | |
96 | public void execute(String id) |
97 | { |
98 | // Get configuration for tool |
99 | Tool tool = _tools.get(id); |
100 | if (tool == null) |
101 | { |
102 | _logger.error("execute() unknown command id <" + id + ">"); |
103 | return; |
104 | } |
105 | |
106 | // Try to execute depending on the actual kind of tool |
107 | _cursor = tool.getCursor(); |
108 | if (tool instanceof OneShotTool) |
109 | { |
110 | _logger.debug("execute() OneShotTool id <" + id + ">"); |
111 | // Unselect previous tool |
112 | _display.clearSelection(); |
113 | _cursor = null; |
114 | // Execute one shot tool |
115 | DrawingAction action = ((OneShotTool) tool).execute(_area); |
116 | // Send the action to the server asynchroneously |
117 | _sender.send(action, _idBoard, _area); |
118 | } |
119 | _mouseListener.setCurrentTool(tool); |
120 | updateCursor(_cursor); |
121 | } |
122 | |
123 | private void updateEnabling() |
124 | { |
125 | boolean enabled = (_board != null && _board.getWriter() == _identity.getId()); |
126 | _display.setEnabled(enabled); |
127 | updateCursor(enabled ? _cursor : null); |
128 | } |
129 | |
130 | private void updateCursor(Cursor cursor) |
131 | { |
132 | if (_area != null) |
133 | { |
134 | _area.setCursor(cursor); |
135 | } |
136 | } |
137 | |
138 | private void addListeners(JComponent area) |
139 | { |
140 | if (area != null) |
141 | { |
142 | area.addMouseListener(_mouseListener); |
143 | area.addMouseMotionListener(_mouseListener); |
144 | } |
145 | } |
146 | |
147 | private void removeListeners(JComponent area) |
148 | { |
149 | if (area != null) |
150 | { |
151 | area.removeMouseListener(_mouseListener); |
152 | area.removeMouseMotionListener(_mouseListener); |
153 | } |
154 | } |
155 | |
156 | private class BoardSelectionConsumer implements PersistentConsumer<DrawingAreaHolder> |
157 | { |
158 | public void push(DrawingAreaHolder holder) |
159 | { |
160 | removeListeners(_area); |
161 | if (holder == null) |
162 | { |
163 | _area = null; |
164 | _board = null; |
165 | _idBoard = -1; |
166 | } |
167 | else |
168 | { |
169 | _area = holder.getDrawingArea(); |
170 | _board = ((DrawingArea) _area).getBoardImageModel().getBoard(); |
171 | _idBoard = _board.getId(); |
172 | addListeners(_area); |
173 | } |
174 | _mouseListener.setArea(_area); |
175 | _mouseListener.setBoard(_idBoard, _board); |
176 | updateEnabling(); |
177 | } |
178 | } |
179 | |
180 | final private Log _logger; |
181 | |
182 | // Reference to this (but through HiveMind proxies) |
183 | final private IdentityHolder _identity; |
184 | final private ToolDisplayHandler _display; |
185 | final private DrawingActionSender _sender; |
186 | |
187 | // List of all registered tools by id |
188 | final private Map<String, Tool> _tools = new HashMap<String, Tool>(); |
189 | |
190 | final private ToolMouseListener _mouseListener; |
191 | |
192 | // The cursor for the current user-chosen tool |
193 | private Cursor _cursor; |
194 | // The current target board for all drawing actions |
195 | private Board _board = null; |
196 | private int _idBoard = -1; |
197 | // The board drawing area that is the current target of all actions |
198 | private JComponent _area; |
199 | } |