Package com.mapmidlet.tile.provider

Source Code of com.mapmidlet.tile.provider.Tile$TileLoader

/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* Author: Damian Waradzyn
*/
package com.mapmidlet.tile.provider;

import java.io.IOException;

import javax.microedition.lcdui.*;

import com.mapmidlet.CloudGps;
import com.mapmidlet.misc.*;
import com.mapmidlet.options.Options;

/**
* Class representing tile - square map fragment. All it does is load (from HTTP
* or from file) and paint itself.
*
* @author Damian Waradzyn
*/
public abstract class Tile {

    public static final int STATE_EMPTY = 0;
    public static final int STATE_LOADING = 1;
    public static final int STATE_ERROR = 2;
    public static final int STATE_LOADED = 3;
    public static final int STATE_SCALED_DOWN = 4;
    public static final int STATE_SCALED_UP = 4;

    public int state;
    protected int width, height;
    protected double latitude, longitude;

    public double getLatitude() {
        return latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    protected int zoom;

    private Image image;
    private long imageLoadTime;

    private Thread backgroundJob = null;
    private String error;

    private static Worker downloader = new Worker("downloader_", true, 64, 4);

    public Tile(int zoom, int width, int height, double latitude, double longitude) {
        this.zoom = zoom;
        this.width = width;
        this.height = height;
        this.latitude = latitude;
        this.longitude = longitude;
    }

    public void load() {
        state = STATE_LOADING;

        int mapSize = 1 << zoom;

        if (latitude < 0 || longitude < 0 || latitude >= mapSize || longitude >= mapSize) {
            state = STATE_EMPTY;
            return;
        }
        Options options = Options.getInstance();
        if (options.useFileApi && !options.fileReadInSeparateThread) {
            loadFromFile();
        }
        if (image == null) {
            downloader.addTask(new TileLoader(this));
            // backgroundJob = new Thread();
            // backgroundJob.start();
        }
    }

    private void loadFromFile() {
        try {
            // long time = System.currentTimeMillis();
            String fileUrl = getFileUrl();
            image = IOTool.readFile(fileUrl);
            // System.out.println("read file time " +
            // (System.currentTimeMillis() - time) + " ms");
            imageLoadTime = System.currentTimeMillis();
            if (image != null) {
                state = STATE_LOADED;
            }
        } catch (Exception e) {
            error = e.getClass().getName() + ": " + e.getMessage();
            state = STATE_ERROR;
        }
    }

    public void paint(Graphics g, int screenWidth, int screenHeight) {
        switch (state) {
        case STATE_LOADED:
            paintLoaded(g, screenWidth, screenHeight);
            break;
        case STATE_LOADING:
            paintLoading(g);
            break;
        case STATE_ERROR:
            paintError(g);
            break;
        default:
            paintEmpty(g, width, height);
        }
    }

    private static void clear(Graphics g, int width, int height) {
        g.setColor(0, 0, 0);
        g.fillRect(0, 0, width, height);
    }

    private void clear(Graphics g) {
        g.setColor(0, 0, 0);
        g.fillRect(0, 0, width, height);
    }

    private void paintLoading(Graphics g) {
        clear(g);
        int loadingFrame = (int) ((System.currentTimeMillis() / 80) % 8);
        Image img = Options.getInstance().skin.getImage("loading" + loadingFrame + ".png");
        g.drawImage(img, width / 2, height / 2, Graphics.HCENTER | Graphics.VCENTER);
    }

    private void paintError(Graphics g) {
        clear(g);
        Image img = Options.getInstance().skin.getImage("error.png");
        g.drawImage(img, width / 2, height / 2, Graphics.HCENTER | Graphics.VCENTER);
        g.setColor(255, 0, 0);
        if (error != null) {
            g.drawString(error, width / 2, height / 2, Graphics.HCENTER | Graphics.BASELINE);
        }
    }

    private void paintLoaded(Graphics g, int screenWidth, int screenHeight) {
        Image tmp = image;

        if (tmp != null) {

            long currentTime = System.currentTimeMillis();
            if (Options.getInstance().fadeEffect && currentTime - imageLoadTime < 2550) {
                int[] subImageData = new int[tmp.getWidth() * tmp.getHeight()];
                tmp.getRGB(subImageData, 0, tmp.getWidth(), 0, 0, tmp.getWidth(), tmp.getHeight());
                int len = subImageData.length;

                for (int i = 0; i < len; i++) {
                    int a = 0;
                    int color = (subImageData[i] & 0x00FFFFFF);
                    a = (int) ((currentTime - imageLoadTime) / 10);
                    color += a << 24;
                    subImageData[i] = color;
                }

                g.drawImage(Image.createRGBImage(subImageData, tmp.getWidth(), tmp.getHeight(), true), 0, 0,
                        Graphics.TOP | Graphics.LEFT);
            } else {
                g.drawImage(tmp, 0, 0, Graphics.TOP | Graphics.LEFT);
            }
        } else {
            paintEmpty(g, width, height);
        }
    }

    public static void paintEmpty(Graphics g, int width, int height) {
        clear(g, width, height);
    }

    public String toString() {
        return "(" + latitude + ", " + longitude + ", " + (image == null) + ")";
    }

    public void deallocate() {
        image = null;
        if (backgroundJob != null) {
            try {
                backgroundJob.interrupt();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    abstract protected String getFileUrl();

    abstract protected String getHttpUrl();

    public static class TileLoader implements Runnable {

        private Tile tile;

        public TileLoader(Tile tile) {
            this.tile = tile;
        }

        public void run() {
            final Options opts = Options.getInstance();
            try {
                if (opts.useFileApi && opts.fileReadInSeparateThread) {
                    tile.loadFromFile();
                }
                if (tile.image == null && opts.onlineMode) {
                    tile.state = STATE_LOADING;
                    int retries = 0;

                    while (tile.image == null && retries < opts.maxRetries) {
                        try {
                            tile.image = IOTool.downloadAndSaveImage(tile.getHttpUrl(), tile.getFileUrl());
                            if (tile.image != null) {
                                tile.state = STATE_LOADED;
                            } else {
                                retries++;
                                tile.state = STATE_ERROR;
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                            retries++;
                            tile.error = e.getClass().getName() + ": " + e.getMessage();
                        }
                    }
                }
                if (tile.image == null) {
                    tile.state = STATE_ERROR;
                    if (tile.error == null) {
                        tile.error = "Load failed";
                    }
                }
            } catch (Throwable e) {
                if (e instanceof InterruptedException) {
                    return;
                }
                CloudGps.setError(e);

                tile.error = e.getClass().getName() + ": " + e.getMessage();
                tile.state = STATE_ERROR;
            }
        }
    }
}
TOP

Related Classes of com.mapmidlet.tile.provider.Tile$TileLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.