diff --git a/src/mahomaps/MahoMapsApp.java b/src/mahomaps/MahoMapsApp.java index f0f0230..c2d3532 100644 --- a/src/mahomaps/MahoMapsApp.java +++ b/src/mahomaps/MahoMapsApp.java @@ -104,7 +104,7 @@ protected void destroyApp(boolean arg0) { if (thread != null) thread.interrupt(); if (tiles != null) - tiles.Stop(); + tiles.Stop(false); if (canvas != null) canvas.dispose(); } @@ -120,7 +120,7 @@ public void run() { // just in case } try { - tiles = new TilesProvider(Settings.GetLangString()); // wrong lang in settings + tiles = new TilesProvider(Settings.GetLangString(), thread); // wrong lang in settings } catch (RuntimeException e) { Form f = new Form(MahoMapsApp.text[88], new Item[] { new StringItem(MahoMapsApp.text[91], MahoMapsApp.text[92]) }); diff --git a/src/mahomaps/map/TilesProvider.java b/src/mahomaps/map/TilesProvider.java index 6198dbf..e77b20a 100644 --- a/src/mahomaps/map/TilesProvider.java +++ b/src/mahomaps/map/TilesProvider.java @@ -54,6 +54,7 @@ public class TilesProvider implements Runnable { private Thread networkTh; private Thread cacheTh; + private Thread accessTh; public static final String[] tilesUrls = new String[] { // scheme @@ -61,16 +62,18 @@ public class TilesProvider implements Runnable { // sat "https://core-sat.maps.yandex.net/tiles?l=sat&lang=", // hybrid - "http://nnp.nnchan.ru/mergedtile.php?lang=" - }; + "http://nnp.nnchan.ru/mergedtile.php?lang=" }; - public TilesProvider(String lang) { + public TilesProvider(String lang, Thread accesser) { if (lang == null) throw new NullPointerException("Language must be non-null!"); this.lang = lang; + accessTh = accesser; } public void Start() { + if (accessTh == null) + throw new IllegalStateException("Tiles provider must be bound to a thread!"); if (networkTh != null || cacheTh != null) throw new IllegalStateException("Can't start already running tiles provider!"); networkTh = new Thread(this, "Tiles downloader"); @@ -79,12 +82,24 @@ public void Start() { cacheTh.start(); } - public void Stop() { - if (networkTh != null) + public void Stop(boolean blocking) { + if (networkTh != null) { networkTh.interrupt(); + try { + if (blocking) + networkTh.join(); + } catch (InterruptedException e) { + } + } networkTh = null; - if (cacheTh != null) + if (cacheTh != null) { cacheTh.interrupt(); + try { + if (blocking) + cacheTh.join(); + } catch (InterruptedException e) { + } + } cacheTh = null; } @@ -466,7 +481,7 @@ private Image tryLoadFromRMS(TileId id) { * Выполняет операции, необходимые перед очередной отрисовкой. */ public void BeginMapPaint() { - if (Thread.currentThread() != MahoMapsApp.thread) + if (Thread.currentThread() != accessTh) throw new IllegalThreadStateException(INVALID_THREAD_ERR); if (paintState) throw new IllegalStateException("Paint is already in progress."); @@ -483,11 +498,7 @@ public void BeginMapPaint() { * Выполняет операции, необходимые после очередной отрисовки. */ public void EndMapPaint(MapState ms) { - if (Thread.currentThread() != MahoMapsApp.thread) - throw new IllegalThreadStateException(INVALID_THREAD_ERR); - if (!paintState) - throw new IllegalStateException("Paint was not performed."); - paintState = false; + exitPaintState(); final int reqZoom = ms.zoom; @@ -517,6 +528,36 @@ public void EndMapPaint(MapState ms) { cacheGate.Reset(); } + public void EndMapPaintThenDiscardAll() { + exitPaintState(); + + synchronized (cache) { + for (int i = cache.size() - 1; i > -1; i--) { + TileCache t = (TileCache) cache.elementAt(i); + synchronized (t) { + switch (t.state) { + case TileCache.STATE_CACHE_LOADING: + case TileCache.STATE_SERVER_LOADING: + // we can't remove this tile + continue; + default: + t.state = TileCache.STATE_UNLOADED; + cache.removeElementAt(i); + break; + } + } + } + } + } + + private void exitPaintState() { + if (Thread.currentThread() != accessTh) + throw new IllegalThreadStateException(INVALID_THREAD_ERR); + if (!paintState) + throw new IllegalStateException("Paint was not performed."); + paintState = false; + } + /** * Возвращает объект кэша плитки для отрисовки. * @@ -525,10 +566,10 @@ public void EndMapPaint(MapState ms) { * null если координаты плитки не находятся в пределах карты * (например, Y отрицательный). */ - public TileCache getTile(TileId tileId) { + public TileCache GetTile(TileId tileId) { if (!paintState) throw new IllegalStateException("Paint was not performing now, can't get tile!"); - if (Thread.currentThread() != MahoMapsApp.thread) + if (Thread.currentThread() != accessTh) throw new IllegalThreadStateException(INVALID_THREAD_ERR); int max = 0x1 << tileId.zoom; @@ -573,8 +614,7 @@ public TileCache getTile(TileId tileId) { } private String getUrl(TileId tileId) { - String url = tilesUrls[tileId.map] + lang + "&x=" + tileId.x + "&y=" + tileId.y - + "&z=" + tileId.zoom; + String url = tilesUrls[tileId.map] + lang + "&x=" + tileId.x + "&y=" + tileId.y + "&z=" + tileId.zoom; if (Settings.proxyTiles && url.startsWith("https")) { return Settings.proxyServer + YmapsApiBase.EncodeUrl(url); } diff --git a/src/mahomaps/screens/MapCanvas.java b/src/mahomaps/screens/MapCanvas.java index 78aab9d..8013726 100644 --- a/src/mahomaps/screens/MapCanvas.java +++ b/src/mahomaps/screens/MapCanvas.java @@ -147,7 +147,7 @@ private void drawMap(Graphics g, int w, int h) { int x = xo - trX * 256; int xi = tx - trX; while (x < w / 2) { - TileCache tile = tiles.getTile(new TileId(xi, yi, ms.zoom, Settings.map)); + TileCache tile = tiles.GetTile(new TileId(xi, yi, ms.zoom, Settings.map)); if (tile != null) tile.paint(g, x, y); x += 256;