Gridarta Editor
DelayedMapModelListenerManager.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2015 The Gridarta Developers.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package net.sf.gridarta.gui.delayedmapmodel;
21 
22 import java.lang.reflect.InvocationTargetException;
23 import java.util.Collection;
24 import java.util.IdentityHashMap;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import java.util.Set;
28 import java.util.concurrent.CopyOnWriteArrayList;
29 import javax.swing.SwingUtilities;
42 import net.sf.gridarta.utils.Exiter;
44 import net.sf.gridarta.utils.Size2D;
45 import org.apache.log4j.Category;
46 import org.apache.log4j.Logger;
47 import org.jetbrains.annotations.NotNull;
48 import org.jetbrains.annotations.Nullable;
49 
54 public class DelayedMapModelListenerManager<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> {
55 
59  @NotNull
60  private static final Category LOG = Logger.getLogger(DelayedMapModelListenerManager.class);
61 
66  private static final long DELAY = 500L;
67 
71  @NotNull
73 
78  @NotNull
79  private final Map<MapModel<G, A, R>, MapModelListenerImpl> mapModelListeners = new IdentityHashMap<>();
80 
85  @NotNull
86  private final Map<MapModel<G, A, R>, MapArchObjectListenerImpl> mapArchObjectListeners = new IdentityHashMap<>();
87 
92  private long timeout;
93 
97  @NotNull
98  private final Object sync = new Object();
99 
104  @NotNull
105  private final Map<MapModel<G, A, R>, Void> scheduledMapModels = new IdentityHashMap<>();
106 
110  @NotNull
111  private final Collection<DelayedMapModelListener<G, A, R>> listeners = new CopyOnWriteArrayList<>();
112 
117  @NotNull
119 
120  @Override
121  public void currentMapChanged(@Nullable final MapControl<G, A, R> mapControl) {
122  // ignore
123  }
124 
125  @Override
126  public void mapCreated(@NotNull final MapControl<G, A, R> mapControl, final boolean interactive) {
127  final MapModel<G, A, R> mapModel = mapControl.getMapModel();
128  final MapModelListenerImpl mapModelListener = new MapModelListenerImpl(mapModel);
129  mapModel.addMapModelListener(mapModelListener);
130  mapModelListeners.put(mapModel, mapModelListener);
131  final MapArchObjectListenerImpl mapArchObjectListener = new MapArchObjectListenerImpl(mapModel);
132  mapModel.getMapArchObject().addMapArchObjectListener(mapArchObjectListener);
133  mapArchObjectListeners.put(mapModel, mapArchObjectListener);
134  scheduleMapModel(mapModel);
135  }
136 
137  @Override
138  public void mapClosing(@NotNull final MapControl<G, A, R> mapControl) {
139  // ignore
140  }
141 
142  @Override
143  public void mapClosed(@NotNull final MapControl<G, A, R> mapControl) {
144  final MapModel<G, A, R> mapModel = mapControl.getMapModel();
145  final MapModelListener<G, A, R> mapModelListener = mapModelListeners.remove(mapModel);
146  if (mapModelListener != null) {
147  mapModel.removeMapModelListener(mapModelListener);
148  }
149  final MapArchObjectListener mapArchObjectListener = mapArchObjectListeners.remove(mapModel);
150  if (mapArchObjectListener != null) {
151  mapModel.getMapArchObject().removeMapArchObjectListener(mapArchObjectListener);
152  }
153  synchronized (sync) {
154  scheduledMapModels.remove(mapControl.getMapModel());
155  }
156  }
157 
158  };
159 
163  private final Thread thread = new Thread(new Runnable() {
164 
165  @Override
166  public void run() {
167  try {
168  final Map<MapModel<G, A, R>, Void> mapModels = new IdentityHashMap<>();
169  while (!Thread.currentThread().isInterrupted()) {
170  while (true) {
171  final long now = System.currentTimeMillis();
172  synchronized (sync) {
173  if (timeout == 0L) {
174  sync.wait();
175  } else {
176  final long diff = timeout - now;
177  if (diff <= 0L) {
178  timeout = 0L;
179  mapModels.putAll(scheduledMapModels);
180  scheduledMapModels.clear();
181  break;
182  }
183 
184  sync.wait(diff);
185  }
186  }
187  }
188 
189  try {
190  SwingUtilities.invokeAndWait(new Runnable() {
191 
192  @Override
193  public void run() {
194  for (final Entry<MapModel<G, A, R>, Void> e : mapModels.entrySet()) {
195  final MapModel<G, A, R> mapModel = e.getKey();
196  for (final DelayedMapModelListener<G, A, R> listener : listeners) {
197  listener.mapModelChanged(mapModel);
198  }
199  }
200  }
201  });
202  } catch (final InvocationTargetException ex) {
203  LOG.error("InvocationTargetException: " + ex.getMessage(), ex);
204  }
205  mapModels.clear();
206  }
207  } catch (final InterruptedException ignored) {
208  Thread.currentThread().interrupt();
209  }
210  }
211 
212  });
213 
219  public DelayedMapModelListenerManager(@NotNull final MapManager<G, A, R> mapManager, @NotNull final Exiter exiter) {
220  this.mapManager = mapManager;
222 
223  final ExiterListener exiterListener = new ExiterListener() {
224 
225  @Override
226  public void preExitNotify() {
227  thread.interrupt();
228  try {
229  thread.join();
230  } catch (final InterruptedException ignored) {
231  Thread.currentThread().interrupt();
232  LOG.warn("DelayedMapModelListenerManager was interrupted");
233  }
234  }
235 
236  @Override
237  public void appExitNotify() {
238  // ignore
239  }
240 
241  @Override
242  public void waitExitNotify() {
243  // ignore
244  }
245 
246  };
247  exiter.addExiterListener(exiterListener);
248  }
249 
253  public void start() {
254  thread.start();
256  }
257 
262  public void addDelayedMapModelListener(@NotNull final DelayedMapModelListener<G, A, R> listener) {
263  listeners.add(listener);
264  for (final MapControl<G, A, R> mapControl : mapManager.getOpenedMaps()) {
265  listener.mapModelChanged(mapControl.getMapModel());
266  }
267  }
268 
274  listeners.remove(listener);
275  }
276 
281  private void scheduleMapModel(@NotNull final MapModel<G, A, R> mapModel) {
282  final long now = System.currentTimeMillis();
283  synchronized (sync) {
284  scheduledMapModels.put(mapModel, null);
285  timeout = now + DELAY;
286  sync.notifyAll();
287  }
288  }
289 
293  public void scheduleAllMapModels() {
294  final long now = System.currentTimeMillis();
295  synchronized (sync) {
296  for (final MapControl<G, A, R> mapControl : mapManager.getOpenedMaps()) {
297  scheduledMapModels.put(mapControl.getMapModel(), null);
298  }
299  timeout = now + DELAY;
300  sync.notifyAll();
301  }
302  }
303 
309  private class MapModelListenerImpl implements MapModelListener<G, A, R> {
310 
315 
321  this.mapModel = mapModel;
322  }
323 
324  @Override
325  public void mapSizeChanged(@NotNull final Size2D newSize) {
327  }
328 
329  @Override
330  public void mapSquaresChanged(@NotNull final Set<MapSquare<G, A, R>> mapSquares) {
332  }
333 
334  @Override
335  public void mapObjectsChanged(@NotNull final Set<G> gameObjects, @NotNull final Set<G> transientGameObjects) {
337  }
338 
339  @Override
340  public void errorsChanged(@NotNull final ErrorCollector<G, A, R> errors) {
341  // ignore
342  }
343 
344  @Override
345  public void mapFileChanged(@Nullable final MapFile oldMapFile) {
347  }
348 
349  @Override
350  public void modifiedChanged() {
351  // ignore
352  }
353 
354  }
355 
362 
367 
373  this.mapModel = mapModel;
374  }
375 
376  @Override
377  public void mapMetaChanged() {
379  }
380 
381  @Override
382  public void mapSizeChanged(@NotNull final Size2D mapSize) {
383  // ignore
384  }
385 
386  }
387 
388 }
net.sf.gridarta.model.mapmanager
Definition: AbstractMapManager.java:20
net.sf.gridarta.model.mapmodel.MapModel
Definition: MapModel.java:75
net.sf.gridarta.model.mapmodel.MapModel.getMapArchObject
A getMapArchObject()
net.sf.gridarta.model.mapmanager.MapManager
Definition: MapManager.java:37
net.sf.gridarta
net.sf.gridarta.model.mapmodel.MapSquare
Definition: MapSquare.java:45
net.sf
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapModelListenerImpl.mapSizeChanged
void mapSizeChanged(@NotNull final Size2D newSize)
Definition: DelayedMapModelListenerManager.java:325
net.sf.gridarta.model.maparchobject.MapArchObjectListener
Definition: MapArchObjectListener.java:30
net.sf.gridarta.model.mapmanager.MapManagerListener
Definition: MapManagerListener.java:42
net.sf.gridarta.model.mapmodel
Definition: AboveFloorInsertionMode.java:20
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapModelListenerImpl.modifiedChanged
void modifiedChanged()
Definition: DelayedMapModelListenerManager.java:350
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.addDelayedMapModelListener
void addDelayedMapModelListener(@NotNull final DelayedMapModelListener< G, A, R > listener)
Definition: DelayedMapModelListenerManager.java:262
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.listeners
final Collection< DelayedMapModelListener< G, A, R > > listeners
Definition: DelayedMapModelListenerManager.java:111
net.sf.gridarta.model.mapmanager.MapManager.addMapManagerListener
void addMapManagerListener(@NotNull MapManagerListener< G, A, R > listener)
net.sf.gridarta.model.archetype
Definition: AbstractArchetype.java:20
net.sf.gridarta.model.gameobject.GameObject
Definition: GameObject.java:36
net.sf.gridarta.model.mapcontrol
Definition: DefaultMapControl.java:20
net.sf.gridarta.model.mapmodel.MapModel.addMapModelListener
void addMapModelListener(@NotNull MapModelListener< G, A, R > listener)
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapModelListenerImpl.mapSquaresChanged
void mapSquaresChanged(@NotNull final Set< MapSquare< G, A, R >> mapSquares)
Definition: DelayedMapModelListenerManager.java:330
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapModelListenerImpl
Definition: DelayedMapModelListenerManager.java:309
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapArchObjectListenerImpl.mapSizeChanged
void mapSizeChanged(@NotNull final Size2D mapSize)
Definition: DelayedMapModelListenerManager.java:382
net.sf.gridarta.model.mapmanager.MapManager.getOpenedMaps
List< MapControl< G, A, R > > getOpenedMaps()
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.mapManager
final MapManager< G, A, R > mapManager
Definition: DelayedMapModelListenerManager.java:72
net.sf.gridarta.model.gameobject
Definition: AbstractGameObject.java:20
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.scheduleAllMapModels
void scheduleAllMapModels()
Definition: DelayedMapModelListenerManager.java:293
net
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.removeDelayedMapModelListener
void removeDelayedMapModelListener(@NotNull final DelayedMapModelListener< G, A, R > listener)
Definition: DelayedMapModelListenerManager.java:273
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.sync
final Object sync
Definition: DelayedMapModelListenerManager.java:98
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.mapArchObjectListeners
final Map< MapModel< G, A, R >, MapArchObjectListenerImpl > mapArchObjectListeners
Definition: DelayedMapModelListenerManager.java:86
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.DelayedMapModelListenerManager
DelayedMapModelListenerManager(@NotNull final MapManager< G, A, R > mapManager, @NotNull final Exiter exiter)
Definition: DelayedMapModelListenerManager.java:219
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.scheduledMapModels
final Map< MapModel< G, A, R >, Void > scheduledMapModels
Definition: DelayedMapModelListenerManager.java:105
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.mapModelListeners
final Map< MapModel< G, A, R >, MapModelListenerImpl > mapModelListeners
Definition: DelayedMapModelListenerManager.java:79
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.timeout
long timeout
Definition: DelayedMapModelListenerManager.java:92
net.sf.gridarta.model.mapmodel.MapModel.removeMapModelListener
void removeMapModelListener(@NotNull MapModelListener< G, A, R > listener)
net.sf.gridarta.model.maparchobject.MapArchObject
Definition: MapArchObject.java:40
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.scheduleMapModel
void scheduleMapModel(@NotNull final MapModel< G, A, R > mapModel)
Definition: DelayedMapModelListenerManager.java:281
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.DELAY
static final long DELAY
Definition: DelayedMapModelListenerManager.java:66
net.sf.gridarta.model.validation.ErrorCollector
Definition: ErrorCollector.java:33
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.thread
final Thread thread
Definition: DelayedMapModelListenerManager.java:163
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapArchObjectListenerImpl
Definition: DelayedMapModelListenerManager.java:361
net.sf.gridarta.model.validation
Definition: AbstractValidator.java:20
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapArchObjectListenerImpl.mapModel
final MapModel< G, A, R > mapModel
Definition: DelayedMapModelListenerManager.java:366
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapModelListenerImpl.mapFileChanged
void mapFileChanged(@Nullable final MapFile oldMapFile)
Definition: DelayedMapModelListenerManager.java:345
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapModelListenerImpl.errorsChanged
void errorsChanged(@NotNull final ErrorCollector< G, A, R > errors)
Definition: DelayedMapModelListenerManager.java:340
net.sf.gridarta.model.mapmodel.MapFile
Definition: MapFile.java:31
net.sf.gridarta.model.mapmodel.MapModelListener
Definition: MapModelListener.java:36
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapModelListenerImpl.mapObjectsChanged
void mapObjectsChanged(@NotNull final Set< G > gameObjects, @NotNull final Set< G > transientGameObjects)
Definition: DelayedMapModelListenerManager.java:335
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager
Definition: DelayedMapModelListenerManager.java:54
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.mapManagerListener
final MapManagerListener< G, A, R > mapManagerListener
Definition: DelayedMapModelListenerManager.java:118
net.sf.gridarta.model
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.start
void start()
Definition: DelayedMapModelListenerManager.java:253
net.sf.gridarta.model.archetype.Archetype
Definition: Archetype.java:41
net.sf.gridarta.model.mapcontrol.MapControl
Definition: MapControl.java:35
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapArchObjectListenerImpl.MapArchObjectListenerImpl
MapArchObjectListenerImpl(@NotNull final MapModel< G, A, R > mapModel)
Definition: DelayedMapModelListenerManager.java:372
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.LOG
static final Category LOG
Definition: DelayedMapModelListenerManager.java:60
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListener< G, A, R >
net.sf.gridarta.model.maparchobject
Definition: AbstractMapArchObject.java:20
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapArchObjectListenerImpl.mapMetaChanged
void mapMetaChanged()
Definition: DelayedMapModelListenerManager.java:377
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapModelListenerImpl.MapModelListenerImpl
MapModelListenerImpl(@NotNull final MapModel< G, A, R > mapModel)
Definition: DelayedMapModelListenerManager.java:320
net.sf.gridarta.gui.delayedmapmodel.DelayedMapModelListenerManager.MapModelListenerImpl.mapModel
final MapModel< G, A, R > mapModel
Definition: DelayedMapModelListenerManager.java:314
net.sf.gridarta.utils.Size2D
Definition: Size2D.java:30
net.sf.gridarta.utils.ExiterListener
Definition: ExiterListener.java:28
net.sf.gridarta.utils
Definition: ActionBuilderUtils.java:20
net.sf.gridarta.utils.Exiter
Definition: Exiter.java:28