/* Author: Clauirton Siebra
 * Updated: Fri Dec 03 18:44:02 2004 by Clauirton Siebra
 * Copyright: (c) 2001 - 2004, AIAI, University of Edinburgh
 */

package ix.ip2.map;

import java.util.*;
import java.io.File;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.MediaTracker;
import java.awt.Robot;
import java.awt.event.*;
import javax.swing.JPopupMenu;
import javax.swing.JMenuItem;
import javax.swing.ImageIcon;

import com.bbn.openmap.layer.*;
import com.bbn.openmap.event.*;
import com.bbn.openmap.omGraphics.*;
import com.bbn.openmap.proj.Projection;
import com.bbn.openmap.LatLonPoint;

import ix.util.Util;
import ix.util.lisp.*;
import ix.util.Parameters;
import ix.ip2.*;
import ix.iface.util.CatchingActionListener;
import ix.icore.domain.PatternAssignment;

import java.awt.*;
import javax.swing.SwingUtilities;
import javax.swing.JPanel;

import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.JComboBox;
import javax.swing.AbstractAction;
import javax.swing.JButton;


/**
 * Class that creates a new layer based on the I-X state format. Objects to appear in this layer need to have  
 * two attributes at least: latitude and longitude.
 */

public class WorldStateLayer extends OMGraphicHandlerLayer implements MapMouseListener {

    // A list of graphics to be painted on the map. */
    private OMGraphicList omgraphics;

    Projection proj;
    protected StateViewer sv;

    //Object dragging stuff
    OMGraphic objSelected;
    OMText texSelected;
    LatLonPoint p;
    float latOld = 0;
    float lonOld = 0;
    boolean dragOn = false;
    boolean drag = false;

    // To keep the objects
    Hashtable world;

    String defaultPath = "/resources/map/";

    /**
     * The default constructor for the layer. It starts a list of graphic objects that will be placed on the map,
     * and a hashtable that keeps all the objects that appear or not on the map.
     */
    public WorldStateLayer(StateViewer sv) {
        setName("World Objects");
        this.sv = sv;
        omgraphics = (OMGraphicList)getList();
        world = new Hashtable();
    }

    /**
     * Clears both the list of graphic objects and the hashtable that contains the objects of the environment
     */
    public void reset(){
        for(int i=omgraphics.size()-1;i>=0;i--){
            omgraphics.removeOMGraphicAt(i);
        }
        getList().generate(proj);
        repaint();
        world.clear();
    }

    /**
     * Adds a pattern-value pair. If the object does not exist, it will be created. If the pattern contains a latitude
     * or longitude property, a special method that manipulates the location of the object on the map is called.
     */
    public void addPatternValue(LList pattern, Object value){
        LList property = ((LList)pattern.clone()).delete(pattern.get(1));
        if(world.containsKey(pattern.get(1))) {
            if( !(((Hashtable)world.get(pattern.get(1))).containsKey(property)) ) {
                ((Hashtable)world.get(pattern.get(1))).put(property,value);
                if( (Lisp.elementsToString(property)).equals("latitude") ||
                    (Lisp.elementsToString(property)).equals("longitude") )

                    loadObjectImage(pattern.get(1),(Hashtable)world.get(pattern.get(1)));
            }
        }
        else {
            Hashtable wo = new Hashtable();
            wo.put(property,value);
            world.put(pattern.get(1),wo);
        }
    }

    /**
     * Changes a pattern-value pair. There are three special cases when the pattern contains a latitude, a
     * longitude or a type.
     */
    public void changePatternValue(LList pattern, Object value){
        LList property = ((LList)pattern.clone()).delete(pattern.get(1));
	  value = testSpecialCases(property,pattern.get(1),value);
        (((Hashtable) world.get(pattern.get(1)))).put(property,value);
        if( (Lisp.elementsToString(property)).equals("latitude") ) {
            int index = getIndexImageObject(pattern.get(1));
            if(index>=0){
            try {
                ((ObjectImage)omgraphics.getOMGraphicAt(index)).setLat(Float.parseFloat(value.toString()));
                ((OMText)omgraphics.getOMGraphicAt(index+1)).setLat(Float.parseFloat(value.toString()));
            } catch (NumberFormatException nfe){
                omgraphics.remove((ObjectImage)omgraphics.getOMGraphicAt(index));
                omgraphics.remove((OMText)omgraphics.getOMGraphicAt(index));
                loadObjectImage((pattern.get(1)),(Hashtable)world.get(pattern.get(1)));
            }
            getList().generate(proj);
            repaint();
        }
        else
            loadObjectImage((pattern.get(1)),(Hashtable)world.get(pattern.get(1)));
        }

        else if( (Lisp.elementsToString(property)).equals("longitude") ) {
            int index = getIndexImageObject(pattern.get(1));

            if(index>=0){
                try {
                    ((ObjectImage)omgraphics.getOMGraphicAt(index)).setLon(Float.parseFloat(value.toString()));
                    ((OMText)omgraphics.getOMGraphicAt(index+1)).setLon(Float.parseFloat(value.toString()));
                } catch (NumberFormatException nfe){
                    omgraphics.remove((ObjectImage)omgraphics.getOMGraphicAt(index));
                    omgraphics.remove((OMText)omgraphics.getOMGraphicAt(index));
                    loadObjectImage((pattern.get(1)),(Hashtable)world.get(pattern.get(1)));
                }   
                getList().generate(proj);
                repaint();
            }
            else
                loadObjectImage((pattern.get(1)),(Hashtable)world.get(pattern.get(1)));
        }

        else if( (Lisp.elementsToString(property)).equalsIgnoreCase("type") ) {
            int index = getIndexImageObject(pattern.get(1));
            if(omgraphics.remove((ObjectImage)omgraphics.getOMGraphicAt(index))) {
                omgraphics.remove((OMText)omgraphics.getOMGraphicAt(index));
                loadObjectImage((pattern.get(1)),(Hashtable)world.get(pattern.get(1)));
                getList().generate(proj);
                repaint();
            }
        }
    }

   /**
    * Deletes a pattern-value pair. If a pattern that constains a latitude or longitude property is deleted, the object 
    * is removed of the map. If the type pattern is deleted, the gif that represents the object will 
    * be changed (in general).
    */
    public void deletePatternValue(LList pattern, Object value){
        LList property = ((LList)pattern.clone()).delete(pattern.get(1));
        Object removed = (((Hashtable) world.get(pattern.get(1)))).remove(property);
        if(removed != null) {
            if( (Lisp.elementsToString(property)).equals("latitude") ||
                (Lisp.elementsToString(property)).equals("longitude") ) {

                int index = getIndexImageObject(pattern.get(1));
                if(omgraphics.remove((ObjectImage)omgraphics.getOMGraphicAt(index))) {
                    omgraphics.remove((OMText)omgraphics.getOMGraphicAt(index));
                    getList().generate(proj);
                    repaint();
                }

            } else if( (Lisp.elementsToString(property)).equalsIgnoreCase("type") ) {
                int index = getIndexImageObject(pattern.get(1));
                if(omgraphics.remove((ObjectImage)omgraphics.getOMGraphicAt(index))) {
                    omgraphics.remove((OMText)omgraphics.getOMGraphicAt(index));
                    loadObjectImage((pattern.get(1)),(Hashtable)world.get(pattern.get(1)));
                    getList().generate(proj);
                    repaint();
                }
            }
        }
    }

    /**
     * Method from the ProjectionListener interface.
     */
    public void projectionChanged(com.bbn.openmap.event.ProjectionEvent pe) {
        //Projection proj = setProjection(pe);
        Projection oldProj = proj;
        proj = setProjection(pe);
        if (proj != null) {
            getList().generate(proj);
            repaint();
        }
        else
            proj = oldProj;
    
        fireStatusUpdate(LayerStatusEvent.FINISH_WORKING);
    }    

    /**
     * Overriding the OMGraphicHandlerMethod, creating a list if it's null.
     */
    public OMGraphicList getList() {
        OMGraphicList list = super.getList();
        if (list == null) {
            list = new OMGraphicList();
            super.setList(list);
        }
        return list;
    }

    /**
     * Loads an image to represent an object. The condition is that the object has a position (latitude and longitude).
     * The relation object/icon follows the algorithm below:<p>
     * IF there is an icon in the directory specified in "map-object-icons" parameter with the same name 
     *    of the object (without extension), this icon will be used.
     * ELSE IF the object has a type pattern (e.g. Buckingham.type=palace) AND there is an icon in the 
     *    directory specified in "map-object-icons" parameter with the same name of the type value 
     *    (in the example, palace), this icon will be used.
     * ELSE IF the "map-default-icon" parameter was specified, the related icon will be used.
     * ELSE the system will use its default icon.
     */
    public void loadObjectImage(Object name, Hashtable wObject){

        if(hasPosition(wObject)){
            try {
                float lat = Float.parseFloat((wObject.get(Lisp.elementsFromString("latitude"))).toString());
                float lon = Float.parseFloat((wObject.get(Lisp.elementsFromString("longitude"))).toString());
                ImageIcon imageLoaded = new ImageIcon();        
                boolean lookingForImage = true;

                if(Parameters.haveParameter("map-object-icons")){
		    imageLoaded = tryImageFormats(Parameters.getParameter("map-object-icons")+name);
                    if( imageLoaded != null)
                        lookingForImage = false;
                }

                if ( (Parameters.haveParameter("map-type-icons")) && lookingForImage) { 

                    Object oType = wObject.get(Lisp.elementsFromString("type"));
                    if (oType != null) {
                        String sType = null;
                        if((oType.getClass().getName().equals("java.lang.String")))
                            sType = (String)wObject.get(Lisp.elementsFromString("type"));
                        else
                            sType = ((Symbol)wObject.get(Lisp.elementsFromString("type"))).toString();

		        imageLoaded = tryImageFormats(Parameters.getParameter("map-type-icons")+sType);
                        if(imageLoaded != null)
                            lookingForImage = false;
                    }
                }

                if ( (Parameters.haveParameter("map-default-icon")) && lookingForImage) {
                    if((new File(Parameters.getParameter("map-default-icon"))).exists()){
                        imageLoaded = new ImageIcon(Parameters.getParameter("map-default-icon"));
                        lookingForImage = false;
                    }
                }
        
                if (lookingForImage)
                    imageLoaded = Util.resourceImageIcon("resources/map/map-default-icon.gif");
                    //imageLoaded = loadObjectImageDefault(name, wObject);

                imageLoaded.setDescription(name.toString());
                ObjectImage icon = new ObjectImage(lat, lon, imageLoaded, name);
                omgraphics.addOMGraphic(icon);
                OMText text = new OMText(lat, lon, 0, icon.getTextLat(), name.toString(), OMText.JUSTIFY_CENTER);
                omgraphics.addOMGraphic(text);
            } catch (NumberFormatException nfe){
                System.out.println("Exception: Latitude/Longitude format error in "+name+" object"); 
            }
        }
    }

    /**
     * Returns TRUE if a object has latitude and longitude
     */    
    private boolean hasPosition(Hashtable wo){
        if(wo.containsKey(Lisp.elementsFromString("latitude")) && wo.containsKey(Lisp.elementsFromString("longitude")))
            return true;
        else
            return false;
    }
    
    /**
     * Returns the index of a object into the graphic list
     */

    private int getIndexImageObject(Object id) {
        Iterator it = omgraphics.iterator();
        OMGraphic aux;
        while(it.hasNext()) {
            aux = (OMGraphic) it.next();
            if((aux.getClass().getName().equals("ix.ip2.map.ObjectImage")))
                if( (((ObjectImage)aux).getName()).equals(id) )
                    return omgraphics.indexOf(aux);
        }
        return -1; //There isn't image yet.
    }

    public ImageIcon tryImageFormats(String name) {
	ImageIcon imageLoaded = new ImageIcon();
	if((new File(name+".gif")).exists())
	    return imageLoaded = new ImageIcon( name+".gif");
	else if((new File(name+".png")).exists())
	    return imageLoaded = new ImageIcon( name+".png");
	else if((new File(name+".jpg")).exists())
	    return imageLoaded = new ImageIcon( name+".jpg");
	return null;
    }

    // MOUSE STUFF

    public String[] getMouseModeServiceList() {
        String[] services = {SelectMouseMode.modeID/*, NavMouseMode.modeID*/};// what are other possibilities in OpenMap
        return services;
    }

    
    public void mouseMoved() {} 
    public void mouseExited(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public boolean mouseMoved(MouseEvent e) { return false; }
    public boolean mouseClicked(MouseEvent e) {return false;}

    public boolean mousePressed(MouseEvent e) {

        drag = false;
	
        if(e.getButton()==e.BUTTON2){
        }

        else if(e.getButton()==e.BUTTON1) {

            //objSelected = omgraphics.findClosest(e.getX(), e.getY(), 10);
	    objSelected = this.findClosestObjectImage(omgraphics,e);

            if(objSelected != null) {
                if(objSelected.getClass().getName().equals("ix.ip2.map.ObjectImage") && !Fixed(objSelected)){

 		    try{
			Robot robot = new Robot();

			int x = Math.round(Math.round(((ObjectImage)objSelected).getMapLocation().getX()));
			int y = Math.round(Math.round(((ObjectImage)objSelected).getMapLocation().getY()));
			Point point = new Point(x,y);

			SwingUtilities.convertPointToScreen(point,this);

			x = Math.round(Math.round(point.getX()));
			y = Math.round(Math.round(point.getY()));

			x = x + (((ObjectImage)objSelected).getWidth()/2);
			y = y + (((ObjectImage)objSelected).getHeight()/2);

			e.translatePoint(x-e.getX(),y-e.getY());
			robot.mouseMove(x,y);

		    }catch(Exception ee){System.err.println(ee);}

                    texSelected = (OMText)omgraphics.getOMGraphicAt(omgraphics.indexOf(objSelected)+1);
                    Hashtable oSel = (Hashtable)world.get(((ObjectImage)objSelected).getName());
                    p = getCoordinates(e);
                    latOld = p.getLatitude();
                    lonOld = p.getLongitude();
                }
                else
                    objSelected = null;
            }
        }
 
        else {

            //final OMGraphic omgr = omgraphics.findClosest(e.getX(), e.getY(), 10);
	    final OMGraphic omgr = this.findClosestObjectImage(omgraphics,e);

            if (omgr != null && (omgr.getClass().getName().equals("ix.ip2.map.ObjectImage"))) {

                final JComboBox cb = new JComboBox();
		cb.addItem(((ObjectImage)omgr).getName());
                cb.addItem("   "+"Property = Value (ADD)");
                cb.addItem("=========================");
                final BasicComboPopup popup = new BasicComboPopup(cb);
                
                Hashtable obj = (Hashtable)world.get(((ObjectImage)omgr).getName());
                Enumeration enumer = this.sortHashtable(obj);
                                
                final Hashtable popMenu = new Hashtable();
                cb.addActionListener(new AbstractAction() {
                    public void actionPerformed(ActionEvent e) {
                      if(cb.getSelectedIndex() > 0) {
                        if(((MenuObjItem)popMenu.get((String)cb.getSelectedItem()))!=null) {
                            ((MenuObjItem)popMenu.get((String)cb.getSelectedItem())).callEditFrame(omgr);
                            popup.hide();
                        }
                        else if(((String)cb.getSelectedItem()).equals("   "+"Property = Value (ADD)")) {
                            new AddPropValFrame(sv,((ObjectImage)omgr).getName());
                            popup.hide();
                        }
		      }
                    }
                });

                while(enumer.hasMoreElements()){
                    Object patName = enumer.nextElement();
                    Object valName = (obj.get(patName));
                    MenuObjItem item = new MenuObjItem(sv,patName,((ObjectImage)omgr).getName(),valName);
                    popMenu.put(item.getText(),item);
                    cb.addItem(item.getText());
                }
                
                popup.show(e.getComponent(),e.getX(), e.getY());
                //this.showAdjustedPopup(popup, e.getComponent(),e.getX(), e.getY() );
               if(cb.getItemCount()<20)
                    popup.setPopupSize(popup.getWidth(),20*cb.getItemCount());
                else
                    popup.setPopupSize(popup.getWidth(),440);
            }

            else if (omgr == null) {
            
                new InsertFrame(sv,(getCoordinates(e)).getLatitude(),(getCoordinates(e)).getLongitude(),world);
            }
            else {
                return false;
            }
        }
        return true;
    }

    public boolean mouseDragged(MouseEvent e) {

        if (objSelected != null) {
            p = getCoordinates(e);
	    if(drag) {
		((ObjectImage)objSelected).setLat(p.getLatitude()-latOld+((ObjectImage)objSelected).getLat());
		((ObjectImage)objSelected).setLon(p.getLongitude()-lonOld+((ObjectImage)objSelected).getLon());
		texSelected.setLat(((ObjectImage)objSelected).getLat());
		texSelected.setLon(((ObjectImage)objSelected).getLon());            
		dragOn = true;
	    }
            latOld = p.getLatitude();
            lonOld = p.getLongitude();
            getList().generate(proj);
            repaint();
            //dragOn = true;
        }
	drag = true;
        return true; 
    } 

    public boolean mouseReleased(MouseEvent e) { 
        if(e.getButton()==e.BUTTON1) {
            if ( (objSelected!=null) && (objSelected.getClass().getName().equals("ix.ip2.map.ObjectImage")) && dragOn) {
                sendConstraint(new PatternAssignment(Lisp.list(Symbol.intern("latitude"),
                                                    ((ObjectImage)objSelected).getName()),
                                                    new Float(((ObjectImage)objSelected).getLat())));

                sendConstraint(new PatternAssignment(Lisp.list(Symbol.intern("longitude"),
                                                    ((ObjectImage)objSelected).getName()),
                                                    new Float(((ObjectImage)objSelected).getLon())));
                objSelected = null;
                dragOn = false;
            }
        }
        return true;  
    }

    public synchronized MapMouseListener getMapMouseListener() {
        return this;
    }

    /**
     * Resets the map and replace the objects.
     */
    public void refresh() {
        Hashtable backup = new Hashtable(world);
        Hashtable tmp;
        reset();
        Enumeration enumer = backup.keys();
        Enumeration e;
        Object objectId,pat;
        while(enumer.hasMoreElements()){
            objectId = enumer.nextElement();
            tmp = (Hashtable) backup.get(objectId);
            e = tmp.keys();
            while(e.hasMoreElements()){
                pat = e.nextElement();
                addPatternValue(returnPattern(pat,objectId), tmp.get(pat));
                changePatternValue(returnPattern(pat,objectId), tmp.get(pat));
            }
        } 
    }

    /**
     * Sorts alphabetically the properties related to a object.
     * @param h hastable with the properties of a object.
     * @return enumeration that contains the sorted properties. 
     */
    private Enumeration sortHashtable(Hashtable h) {
        Vector vLList = new Vector (h.keySet());
        Vector vString = new Vector();
        for(Enumeration e = vLList.elements();e.hasMoreElements();)
            vString.add(Lisp.elementsToString((LList)e.nextElement()));

        Collections.sort(vString);
        vLList.clear();
        for(Enumeration e = vString.elements();e.hasMoreElements();)
            vLList.add(Lisp.elementsFromString((String)e.nextElement()));

        return(vLList.elements());
    }

    private boolean Fixed(OMGraphic omgr) {
	
	Hashtable oSel = (Hashtable)world.get(((ObjectImage)omgr).getName());
	Object oFixed = oSel.get(Lisp.elementsFromString("geo-fixed"));
	if(oFixed != null) {
	    	String sFixed = null;
            if((oFixed.getClass().getName().equals("java.lang.String")))
                sFixed = (String)oSel.get(Lisp.elementsFromString("geo-fixed"));
            else
                sFixed = ((Symbol)oSel.get(Lisp.elementsFromString("geo-fixed"))).toString();

	    	if(sFixed.equals("true")) {
		    return true;
	      }
	}
	return false;
    }

    /**
      * Method auxiliar to find objects on the map.
      */
    private OMGraphic findClosestObjectImage(OMGraphicList omgraphics,MouseEvent e) {

        Iterator it1 = omgraphics.iterator();
        OMGraphic aux1;
        while(it1.hasNext()) {
            aux1 = (OMGraphic) it1.next();
            if(!(aux1.getClass().getName().equals("ix.ip2.map.ObjectImage")))
	        aux1.setVisible(false);
        }

        final OMGraphic omgr = omgraphics.findClosest(e.getX(), e.getY(), 10); //25

	Iterator it2 = omgraphics.iterator();
        while(it2.hasNext()) {
            ((OMGraphic) it2.next()).setVisible(true);
        }
	return omgr;
    }

    /**
     * Method auxiliar to put a object in the correct place inside the pattern format.
     */
    static public LList returnPattern(Object property, Object object){  
        LList prop = (LList)property;
        LList pattern = Lisp.NIL;
        for(int x=prop.size()-1;x>0;x--)
            pattern = Lisp.cons(prop.get(x),pattern);
        pattern = Lisp.cons(object,pattern);
        pattern = Lisp.cons(prop.get(0),pattern);
        return pattern;
    }
    
    /**
     * Method auxiliar to put a tilde in the place of the. Just to improve the output format.
     */
    static public String addTilde(Object property) {
        LList prop = (LList) property;
        Object aux = prop.get(0);
        prop = prop.delete(aux);
        prop = Lisp.cons(Symbol.intern(" ~ "),prop);
        prop = Lisp.cons(aux,prop);
        return Lisp.elementsToString(prop);
    }
    
    class MenuObjItem {

        Object obj,val,pat;
        StateViewer sv;
        String text;

        public MenuObjItem(StateViewer sv, Object patName, Object objName, Object valName){
            text = addTilde(patName)+" = "+valName.toString();
            this.sv = sv;
            pat = patName;
            obj = objName;
            val = valName;
        }

        public String getText() {
            return text;
        }

        public void callEditFrame(OMGraphic omgr){
	    boolean enabled = true;
	    System.out.println(pat);
	    if(pat.toString().equals("(latitude)") || pat.toString().equals("(longitude)") )
	    	if(Fixed(omgr)) enabled = false;
            new EditFrame(sv,pat,obj,val,enabled);
        }
    }

    private Object testSpecialCases(LList prop,Object obj,Object value) {
	  if( (Lisp.elementsToString(prop)).equals("geo-fixed")) {
	      if( !((value.toString()).equals("true")||(value.toString()).equals("false")) ) {
		    Util.displayAndWait(this,"The 'geo-fixed "+obj+"' pattern should have a boolean value. The system \n is setting it to 'true'. You can change this value on the panel if you want." );
		     sendConstraint(new PatternAssignment(WorldStateLayer.returnPattern(prop,obj),Symbol.intern("true")));
		    return Symbol.intern("true");
		}
	  } 
	  return value;
    }

    protected void sendConstraint(PatternAssignment pa) {
	if(sv instanceof ix.ip2.map.MapWhiteboard)
	    ((MapWhiteboard)sv).sendConstraint(pa);
	else
	   ((StateViewMap)sv).sendConstraint(pa);
    }

    protected LatLonPoint getCoordinates(MouseEvent e) {
	if(sv instanceof ix.ip2.map.MapWhiteboard)
	    return ((MapWhiteboard)sv).getCoordinates(e);
	else
	   return ((StateViewMap)sv).mapTool.getCoordinates(e);
    }

    /* METHODS NOT USED IN THIS VERSION
    static public void showAdjustedPopup( JPopupMenu popup, Component comp,int x, int y ) {
        Dimension popupSize = popup.getPreferredSize();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Point pt = new Point( x,y);
        SwingUtilities.convertPointToScreen(pt,comp);

        // Is the popup going past the screen height? If so adjust
        if ( (pt.y+popupSize.height) > screenSize.height ) {
            // 40 below for toolbar at bottom
            y -= (pt.y+popupSize.height) - screenSize.height + 40;
        }

        // Is the popup going past the screen height? If so adjust
        if ( (pt.x+popupSize.width) > screenSize.width ) {
            x -= (pt.x+popupSize.width) - screenSize.width + 40;
        }

        // Show the popup now
        popup.show(comp, x, y) ;
    }  

    public ImageIcon loadObjectImageDefault(String name, Hashtable wObject){
        ImageIcon imageLoaded = new ImageIcon();
        imageLoaded = new ImageIcon(defaultPath+"object-icons/"+name+".gif");
        if(imageLoaded.getImageLoadStatus()==MediaTracker.ERRORED) {
            String type = (String)wObject.get(Symbol.intern("type"));
            if (type == null) type = (String)wObject.get(Symbol.intern("type")); 
            if (type != null) 
                imageLoaded = new ImageIcon(defaultPath+"type-icons/"+type+".gif");
            if(imageLoaded.getImageLoadStatus()==MediaTracker.ERRORED)
                imageLoaded = new ImageIcon(defaultPath+"map-default-icon.gif");
        }
        return imageLoaded;
    } */

}
