/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.plugin.composer.mapedit;
import java.awt.*;
import java.applet.*;
import java.awt.image.*;
import java.net.URL;
import java.io.*;
import netscape.plugin.composer.*;
import netscape.plugin.composer.io.*;
import java.util.*; // For ResourceBundle, etc.
import netscape.security.PrivilegeManager;
/* ****************** The Plugin *************************************************/
public class MapEdit extends Plugin {
public static void main(String []args) {
Debug.println("in MapEdit.main()" + args);
netscape.test.plugin.composer.Test.perform(args,new MapEdit());
}
/** Returns whether resources are now loaded. */
boolean loadResources() {
if (!resLoaded) {
// Load resources. international.
try {
Debug.println("Loading resources");
// This method not supported in the Navigator yet.
// res = ResourceBundle.getResourceBundle("netscape.test.plugin.composer.MapEditResource",null);
res = new MapEditResource();
resLoaded = true;
}
catch (MissingResourceException e) {
}
}
return resLoaded;
}
private boolean resLoaded = false;
private ResourceBundle res = null;
public String getName() {
if (loadResources())
return res.getString("image_map_editor");
else
return "Image Map Editor";
}
public String getCategory() {
if (loadResources())
return res.getString("html_tools");
else
return "HTML Tools";
}
public String getHint() {
if (loadResources())
return res.getString("the_hint");
else
return super.getHint();
}
public boolean perform(Document document) throws IOException {
////// --------------------------------////
Debug.println("Image Map Editor test 8");
////// --------------------------------////
if (!loadResources()) {
System.err.println("Map Editor could not load resources.");
return false;
}
MapEditApp app = new MapEditApp(document,res);
// Catch any errors in init().
if (app.initSuccessful()) {
app.show();
}
boolean ret = app.waitForExit();
// Let Cafe users see the output before the window goes away.
if (false) {
// if (Debug.debug()) {
try {
if (true) {
Debug.println("Hit return");
System.in.read();
}
else {
Debug.println("SLEEP for a few seconds");
Thread.sleep(10000);
}
}
catch (Exception e) {}
}
return ret;
}
}
/* ********************* The actual Application ***************/
class MapEditApp extends Frame implements OkCallback {
private boolean initOk = false;
public boolean initSuccessful() {return initOk;}
public MapEditApp(Document d,ResourceBundle rB) {
super(rB.getString("frame_title"));
res = rB;
document = d;
areas = new Vector();
if (document == null) {
failure(res.getString("doc_is_null"));
return;
}
// Try to find the first image in the selection.
if (!parseDoc(true)) {
// Next, look for any image in the document.
if (!parseDoc(false)) {
// Give up, no images.
failure(res.getString("no_images_in_document"));
return;
}
}
// imageName, imageLocation, and mapName should now be valid.
// Security stuff
PrivilegeManager.getPrivilegeManager().enablePrivilege("UniversalFileAccess");
PrivilegeManager.getPrivilegeManager().enablePrivilege("UniversalConnect");
Debug.println("got privileges");
// Load image
URL imageURL = null;
try {
imageURL = new URL(document.getBase(),imageName);
} catch (java.net.MalformedURLException e) {
failure(e.toString());
return;
}
Debug.println("created dummy URL");
try {
image = Toolkit.getDefaultToolkit().getImage(imageURL);
}
catch (Exception e) {
failure(e.toString());
return;
}
Debug.println("start image load");
// Force image loading.
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(image,0);
try {
tracker.waitForID(0);
} catch (InterruptedException e) {
image = null;
}
if (image != null) {
imageDim = new Dimension(image.getWidth(this),image.getHeight(this));
imageRect = new Rectangle(imageDim);
}
if (image == null || imageDim.width < 0 || imageDim.height < 0) {
failure(Format.formatLookup(res,"could_not_load_image",imageName));
return;
}
Debug.println("finish image load");
createUI();
syncAreaList();
resize(MapEditApp.APP_WIDTH,MapEditApp.APP_HEIGHT);
initOk = true;
// Flag so we can stop running the app.
isRunning = true;
}
synchronized void failure(String message) {
if (failureDialog == null)
failureDialog = new InfoDialog(this,res,"Map Editor Error",message,this);
if (!failureDialog.isVisible())
failureDialog.show();
Debug.println("FAILURE:" + message);
}
private InfoDialog failureDialog = null;
// Callback from the failure InfoDialog. Quit the application.
public synchronized void ok() {
Debug.println("ok callback called");
if (isRunning) {
// success will be false.
stopRunning();
}
}
synchronized public boolean waitForExit() {
while ( isRunning ) {
try {
Debug.println("MapEditApp.waitForExit is wait()ing.");
wait();
} catch ( InterruptedException e){
}
}
hide();
return success;
}
synchronized void stopRunning() {
Debug.println("stop running");
isRunning = false;
notifyAll();
}
/*********************** PARSING/UNPARSING CODE *********************/
// Find first image in selection or in document.
// Sets imageName, mapName, imageLocation.
// Returns whether an image was found.
private boolean parseDoc(boolean onlyInSelection) {
// Start from beginning of document.
LexicalStream inStream = null;
try {
// Read entire document into a string and use the string
// for the LexicalStream.
Reader in = document.getInput();
StringBuffer b = new StringBuffer();
int bufSize = 1000;
char[] buf = new char[bufSize];
for(;;) {
int moved = in.read(buf);
if ( moved < 0 )
break;
b.append(buf, 0, moved);
}
in.close();
inStream = new LexicalStream(b.toString());
} catch (IOException e) {
failure(e.toString());
}
imageLocation = -1;
boolean inSelection = false;
Token token;
try {
while ((token = inStream.next()) != null) {
imageLocation++; // 0 for the first token.
// Keep track of selection start/end.
if (token instanceof Comment) {
Comment comment = (Comment)token;
if (!inSelection && comment.isSelectionStart())
inSelection = true;
if (inSelection && comment.isSelectionEnd())
inSelection = false;
}
// Find first IMG tag.
if ((!onlyInSelection || inSelection) &&
token instanceof Tag) {
Tag tag = (Tag)token;
if (tag.getName().equals("IMG")) {
// Image found.
if (!tag.isOpen() || !tag.containsAttribute("SRC")) {
failure(res.getString("first_img_invalid"));
}
String value = tag.lookupAttribute("USEMAP");
// If image has an image map, read in it's tags and
// use its name.
if (value != null && value.length() > 0) {
mapName = StripPound(value);
parseMap();
}
// Else, a new map, generate a map name.
else {
// NSMAP + 6 digits.
mapName = "NSMAP" + (int)Math.floor((Math.random() * 999999));
}
imageName = tag.lookupAttribute("SRC");
if (imageName == null || imageName.length() == 0) {
// failure(new MessageFormat(res.getString("invalid_img_tag")).format(args));
failure(Format.formatLookup(res,"invalid_img_tag",imageName));
}
return true;
} // if "IMG"
} // if Tag
} // while
} catch (IOException e) {
failure(e.toString());
}
return false;
}
/** Search from beginning of doc, find first map with name mapName. Use it
to construct the Vector areas. */
private void parseMap() {
// Note: Starting from the beginning.
LexicalStream stream = null;
try {
stream = new LexicalStream(document.getInput());
} catch (IOException e) {
failure(e.toString());
}
Token t;
try {
while ((t = stream.next()) != null) {
if (t instanceof Tag) {
Tag tag = (Tag)t;
if (tag.getName().equals("MAP") && tag.isOpen() &&
mapName.equals(tag.lookupAttribute("NAME"))) {
parseAreas(stream);
}
}
}
} catch (IOException e) {
failure(e.toString());
}
// If we don't find an image map corresponding to mapName, areas will just
// be an empty Vector.
}
/** Read in all tags until a closing tag is hit. */
private void parseAreas(LexicalStream stream) {
try {
Token token;
while ((token = stream.next()) != null) {
if (token instanceof Tag) {
Tag tag = (Tag)token;
if (tag.getName().equals("MAP") && tag.isClose())
return;
// Give each Area class a chance to parse the tag.
Area area;
if ((area = DefaultArea.fromTag(tag,document.getBase())) != null) {
// We could make the default area a real area, for now just store the
// default URL.
defaultURL.str = area.getURL();
continue;
}
if ((area = RectArea.fromTag(tag,document.getBase())) != null) {
// area.clip(imageRect);
areas.addElement(area);
continue;
}
if ((area = CircleArea.fromTag(tag,document.getBase())) != null) {
// area.clip(imageRect);
areas.addElement(area);
continue;
}
if ((area = PolyArea.fromTag(tag,document.getBase())) != null) {
// area.clip(imageRect);
areas.addElement(area);
continue;
}
} // if
} // while
} catch (IOException e) {
failure(e.toString());
}
}
/** Strips leading '#' if found. */
private String StripPound(String in) {
if (in.startsWith("#"))
return in.substring(1);
else
return in;
}
/** Write document to the Document output stream. */
private void writeDoc() {
// Start from beginning of document.
LexicalStream inStream = null;
Writer outStream = null;
try {
inStream = new LexicalStream(document.getInput());
outStream = document.getOutput();
} catch (IOException e) {
failure(e.toString());
}
// Between of the