GMAO2k Great Manga Application Onidzuka 2k An application to annotate scans from Manga with multiple languages marked up. Now using XML! ======== List of classes / source files ======== AnnotatePanel.java This is the main heart of GMAO. It implements a JPanel that we can throw a background image up on and paint annotations on. Also has a lot of support for creating DOM fragments and reading DOM fragments, converting them from the internal representation of Annotations/Notes and back. A big ungainly class really. Annotation.java A class that represents what I call a "bubble" in the XML file. It is a shape on screen and contains lots of Note objects (which correspond to Translations in the XML file.) AnnotationInformationPanel.java The class that shows the content of the different Annotations. It is told which Annotation to show by the AnnotatePanel. Also has all the code for entering new Annotations, and has a bit of mucking for the character name completion. Annotator.java A simple class that holds information about the Annotator. Just two strings right now, should get smarter in the future. FontSelector.java A widget for selecting a font, size, and style. GIFEncoder.java A class that encodes an image to a GIF file. GMAOAboutBox.java A simple class that contains an GMAOCreditsBox and an OK button. GMAOApplet.java A really simple class that extends JApplet and then creates a GMAOGUI. Well, does a little more than that, wrapping some PARAM tags and stuff, but anyway. Mostly a wrapper. GMAOBannedAnnotatorException.java This exception is thrown when a Annotator attemps to log in and the maintainer of the server they are logging in to has banned them. Man, either this Annotator sucks, or the maintainer is a mean guy. GMAOCacheWatcher.java A class that watches memory resources in a thread, and if we are low on mem, starts to delete images from the cache. Deletes them in lexicographic order on the file name, so if you are reading the manga backwards (why?) you will keep deleting the image from the cache that you are using... So don't read backwards! GMAOCreditsBox.java A simple panel that scrolls up text. GMAOGUI.java The main class used to drive the program. Makes a GUI. Does a lot of work with setting up files, reads the main XML file, etc. GMAOHTMLExport.java Factors out HTML exporting. This handles creating a single "contents.html" file for an XML file, and the individual "pageX.html" files. I put this in a separate class so that GMAOGUI and GMAOServer could use it without duplicating code between them... GMAOJNLP.java Class that is a stub to load up a GMAOGUI from the Java Web Start (JNLP protocol) environment. GMAOLanguagePairs.java Not well named. This class tracks the annotators and languages used in a given DOM. We also use it to set the options on what language/annotator to view... GMAOOptionsFramee.java A class that throws up an Frame that has options in it, and lets the user modify them. Yay! GMAORemote.java This is the Remote interface (I could not think of a good name - sorry) that the Server and Client use to communicate updates to the main DOM over the RMI connection. Has only two methods really, one to log in an Annotator (make sure the passwords match, and that the user is a good citizen) and one to update the DOM one page at a time. GMAOServer.java This is the Server that runs and accepts updates to DOM files over RMI connections. Right now it is a pretty lame CLI based guy, but I might make it graphical in the future. ImageFileFilter.java Support class for just showing image file types in a JFileDialog. Note.java Simple class that contains a note that is attached to an Annotation. Can have an arbitrary number of NoteCustomFields. NoteCustomField.java A simple class that is just a name of a custom field, and its value. Used to store "Language" and "Character" data. PercentComboBoxEditor.java A ComboBoxEditor that uses a PercentDocument so that the user can only type in percentages. PercentDocument.java A Document Model that only allows the user to type in numbers. (Percentages.) TextCompleter.java A class that does text completions. There is a big hack regarding this. It should probably be a normal class, but I made the whole thing static just so I can use it like a global variable, and not have to pass references like 10 levels deep. A good class otherwise though. TextCompletionDocument.java Custom Document that implements text completion. TextCompletionField.java Subclass of JTextField that implements text completion in conjunction with TextCompletionDocument. Has an annoying bug regarding focus and setting the selection that prevents me from making it exactly what I want. XMLFileFilter.java Another support class that lets us just show .xml files in a JFileDialog. XMLTreeDisplay.java This implements a JTree display of the XML file and sticks a AnnotatePanel in the right. It then tells the AnnotatePanel to show stuff when the user selects different nodes in the JTree. ======== Notes to self on how to compiler the Server files. ======== Had to add some code to c:/jdk1.3/jre/lib/sercurity/java.policy to support RMI: // Try to let all people look at all ports for RMI stuff grant { permission java.net.SocketPermission "*:1024-65535", "listen, accept, connect, resolve"; }; Compile files as normal. Then we get to the fun stuff. Have to use the rmic compiler on the generated class files. Also, use the -v1.2 option since we are requiring at least Java 1.2 for swing. Don't need the skeleton class files in that case. rmic -v1.2 -d . GMAOServer The resulting class files have to be network accessible. No problem, we'll throw them all into the .jar file. NOT THE GMAOServer.class FILE THOUGH! Compile the client as normal. debug easier with java -Djava.compiler=none ======== JAR stuff ======== To indicate which class is the application's entry point, you must add a Main-Class header to the JAR file's manifest. The header takes the form: Main-Class: classname The header's value, classname, is the name of the class that's the application's entry point. To create a JAR file having a manifest with the appropriate Main-Class header, you can use the Jar tool's m flag as described in the Modifying a Manifest section. You would first prepare a text file consisting of single line with the Main-Class header and value. For example, if your application was the single-class HelloWorld application, the entry point would of course be the HelloWorld class, and your text file would have this line: Main-Class: HelloWorld Assuming your text file was in a file called mainClass, you could merge it into a JAR file's manifest with a command such as this: jar cvmf mainclass.txt GMAO.jar *.class With your JAR file prepared in this way, you can run the HelloWorld application from the command line: java -jar app.jar ======== Transforming to HTML: ======== Notes: Using alphaworks' lotusxsl, have to change encoding on xml file to "EUC-JP" instead of "EUC_JP". Hence the t for temp in there... java org.apache.xalan.xslt.Process -in GTO01t.xml -xsl MangaDocToHTML.xml -out GTO01_Trans.html automated this process in GMAOServer now. It automatically does the XSLT stuff. Doesn't do it very well though. ======== List of things to do: ======== * "Targeting lines" for drawing stuff * Make it work when we are off-line. * Check return value for HTTP size check - might be negative, means not available, don't try to load. * Add DTD to document instead of referring to a DTD over http - prevents us from working offline. * Add an option for auto-loading XML file, and whether to auto-load or not. * Use the GMAOLanguagePairs object to return a reference to the same annotator instead of creating multiple annotators? * Should clear out the TextCompleter when we load in a new DOM. * Put up a progress display on the Applet panel for GMAO Loading. * Allow for % signs in the JComboBox. * Fix zoom-ify so that we don't always default to 100% on first image display. * Create new entries on the JToolBar for moving and reshaping existing nodes. * Allow the user to define custom fields for each annotation in the properties file. * Allow user to set the output xml file encoding in the properties. ======== List of things done ======== * Fixed a bug that was completing "English" to "English " all the time. * Dynamically resize fonts. * Added support for changing font based on Character. * Added exporting to a GIF image. * Added background color changing based on Character, alpha blends. * In GMAOOptionsFrame set up who the current annotator / language is based on the props settings. * Add buttons for choosing directories in options. I did that at some point. * Also, changed drawing code for Strings. More robust now, and text is centered instead of upper left justified. * Have GMAOServer choose a XSL file to use based on the manga that is being transformed. * Prevent the user from switching to loading a new image while one is already loading. Maybe put up a modal dialog box? Better would be to try to cache the next image in the background - which means that we have to be able to track loading multiple images at the same time... Done, finally. Put up a JProgressBar, and shows progress on it. If they press cancel, image loading is cancelled. Since it is a modal dialog, user has to either wait or cancel. Yay. (8/15/2001) * Added a progress dialog when loading up a XML file from the web. * Added HTML page creation support in GMAOGUI. (8/8/2001) * Added initial support for JNLP Java Web Start launching protocol. * Added icon to GMAOGUI. (7/30/2001) * Fixed the "Copy from Last translation" option so that it works as expected - copies from the last Annotation that has some contents (instead of using ones that didn't have any content...) (7/30/2001) * Added a new menu option "Copy from Last translation" which copies the contents of the last annotation to the current annotation. Useful for stuff like making lots of "haaa" "haaa" "haaa" bubbles. (7/27/2001) * Added support for skinning. Took like, 20 minutes. It is optional, and off by default. See GMAO.props.doc for information on how to turn it on... Looks really pretty, but actually seems to mess up the "default button" (it is not default anymore) and size of some windows. (7/23/2001) * Made us load things in using getResource from classloader. This is to prepare for moving to a Java web start application at some point. Added a note if we are using a http file as well. (7/23/2001) * Made the log-in dialog better finally. Used a password field. Yay. (6/19/2001) * The Character field is only editable if it is the first note. Otherwise, it is not editable, and the value is taken from the first note. (6/12/2001) * Made a button to delete a Note from a bubble (6/12/2001). * Fix focus bug in TextCompletionField that prevents us from setting up the selection nice for easy type-on. Totally got this fixed. It was pretty hard though. Had to kick up some extra threads. Anyway, I also put the possible completions down in the status line when there are multiple completions as well. (6/10/2001) * Added a little thing to collapse the split pane easier. * First changes in a long time. Now the "New" option under the file menu actually works. Also, check to make sure we are logged in before we create a new chapter (!!) and we can now create chapters if there weren't any before. Basically, you can now use the GUI completely to create a new MangaTranslation XML file. yay! Since I'm the only one using this though, I guess that isn't a big deal. (5/11/2001) * Fix update problem: If you annotate a page, then create a new page and go to that new page, the annotations on the old page are *not* updated to the server. When you go back to that page again, they are not sent because they are not "new". (You can work around this by "Edit"ing each annotation and just clicking ok immediately.) This has more or less been taken care of by adding the "Send page to server" menu item. * Better interface for sending updates to remote server * Some big changes. The GMAOServer now creates individual html pages for each page on the fly. Also, added code to make the icon for GMAOServer nice. (If GMAOServer.gif exists, it will use that.) * Added a few more params to the applet to give better control of it. Sensible defaults. (8/21/2000) * Now I draw the text of the annotation in the bubble. But it is ugly. Should let the user change fonts and stuff too. (8/21/2000) * Now I put up a dialog if the user's environment doesn't support Japanese File Encoding methods. The only real problem is that the dialog looks really bad. Too much text. Not enough room. * Fixed a null pointer error in the applet when loading an XML file and scanning for annotator / language pairs. Also fixed an error with setting the annotator / language pair in the options (string bounds error.) * Add language / annotator display to prefs box. (8/18/2000) * Need to be able to scan the dom and list annotators and language pairs that are available. (8/18/2000) * Fixed a bug or two that prevented GMAOApplet version from working with the new options settings (had to set the option defaults in GMAOApplet.java) * Fixed problem with OBJECT tag for IE that prevented the right .jars from being loaded. yay! * Really need a "Preferences" box that lets people set preferences... In this there should be a setting for "view annotation outlines" and "select Annotator / Language pair to display" at least. Also could add colors for Annotation fg/bg. (8/9/2000) Made a preferences box. Did not make a thing to let you select language and annotator display though. * When zooming to "Fit Window" we use the size of the current background to compute the zoomed background size. So it only works when we are zoomed in to 100%. Other times, it just changes the size around... (Fixed) * Made control-e and control-n edit a current translation and create a new one. Added menu items for that to do it. Interface is getting hacky. Should also enable/disable the menu items accordingly at some point. * About box! Added a simple about box. 8/4/2000. * Added some code to de-couple a loaded image from the real image that loaded it - this is in an attempt to prevent the image from re-loading from the server when it is re-sized. Should work, haven't tested (need a slow line to test on...) Tested it, it doesn't work. Dang. Back to the old code (which does work, but re-loads) and maybe send a note out... (8/6/2000) * Yay! Used XSL to transform XML into HTML. Yay! * Tell people that if they edit a note that is not theirs, it will not be updated on the remote server. (But it will look like it had been to them.) Also, a slew of other warnings and notes are sent to the user when appropriate. (8/2/2000) * Fix polygons on saving. (8/2/2000) * Added an property setting for Adam - you can turn off the display of the outlines for annotations now. 7/31/2000 * Fixed a bug where we weren't doing the letter part of the next file name suggestion quite right. * Fixed a bug where GMAOApplet.java was not picking up the "imageHttpLocation" parameter. * Made the new page file choosing method a bit more stable. Works now with files of the type "PrefixNumberLetter.ext". Right now, it will switch an a to a b, and a b to an a and increment the number. * Added a new property "memoryLimit" that lets you set the number of bytes that you want to try to have the GMAOCacheWatcher free. Defaults maybe to a meg now, since we have the number of images setting around also. * Fix bug where new chapters are always numbered "0". Done. I think - I made the code change, but haven't tested it. Should work though. * Fix bug where page # reverts to 0 on new chapters, can't get last image name for a new chapter. Fixed it by accident while fixing other bugs relating to remote server update. 7/28/2000. * Change AnnotePanel in such a way that it tracks which annotations are new, and which are not. This will allow us to, instead of returning a new dom document fragment for each page on page switches to just return the new nodes that were added. --> Have to think a bit about what happens when we are deleting nodes or changing nodes...! Actually, I think what needs to be done is a general method for updating one tree with the contents of another (a diff of sorts.) This will prove to be useful in the case of RMI server updates too. * The holy grail of using RMI and a server application to update the annotations over the network. Both of the above done 7/28/2000. Mostly debugged, works just great. * Make new chapters update work over the web as well. Add a new method to the remote interface for updating chapters (number, and title - should be easy) (Fixed 7/28/2000). Added a method in GMAORemote.java to do just that. * Fix the "changes" Vector so that when someone adds a new Translation to a note, it gets added on as a new change. Right now we only catch entire new Annotations. (7/27/2000) We now will add in an Annotation to changes if either a note is edited, or if a new note is added. * When zoomed to a different level, for some reason doesn't track the cursor well when putting up the annotations. Check into it. (Fixed. 7/19/2000) * Fix zoom-JComboBox so that we can only type in numbers (possibly with a percentage sign after them.) Done. 7/19/2000. Lots of work. Haven't done the percent sign yet. Have to work a bit to fix that up. * Add a "fit to window" option in the zoom control. * When we run out of memory, clean up the imgCache. Probably check this with a thread that runs and checks Runtime.freeMemory(). When there isn't very much memory around (how much is "not very much"?) clean up the image cache. (Done 7/18/2000.) Actually, I tried to use Runtime.freeMemory() but it reported really odd numbers. Like, that I had 10 meg free, when it just threw an out of memory exception. Ok. So while we do look at free memory (we don't take it seriously) and also limit the cache to a small number of images. Defaults to 2. Can be set in GMAO.props using "cacheSize". * Fix page 42. Looks like I annotated under a different zoom, and it scaled everything wrong. (also, check to make sure that annotation at a different scale works! Actually, the problem is almost assuredly that saving at a scale other than 100 saves the SCALED coords. I bet that is what happened.) 7/18/2000. Fixed the one page - everything was off by 200%, and it was what I thought - when scaled in, if we switched to another page, we saved the locations of the scaled bubbles. * Fix zoom-ify so that when we are at non-native scales, the erase button works. Fixed that minor problem. (7/17/2000) * Look into making a JAR file with JAXP included so user can just DL and go. Made jar files. (put command line arg here so I remember) Also, can include jaxp.jar and parser.jar on archive option. yay! * Applet-ify. 7/14/2000 Done. Took about a day's worth of work, a lot of it because I haven't done applet coding in a while. Tested, works with NN and IE using sun java plugin 1.2.2. I don't know if the user has to have JAXP installed or not. It is likely. I haven't looked into making a JAR file yet. It is on the list. * Zoom-control. (In the ToolBar, view at 150%, 100%, 75%, 50%, 25%) Added a zoom control that lets the users zoom to an arbitrary scale. This is only the initial pass at zooming - we have to do some clean-up related to it. (See above in the list of features/bugs to track.) However, as things stand right now, it is pretty bad-ass. We can scale to an arbitrary size. The Annotations scale up with us. We can also Annotate at an arbitrary scale, and it works. (Well, I have not tested the Polygon annotation, but I don't use that anyway.) The only issue is that erase won't work at non-native (scale 100) levels, and right now the zoomLevel box is really broken. You can cause exceptions and stuff by typing "My Mom Rules!" and other non-integer-followed-by-% sign strings. Will fix at some point. * In TextCompleter.java add a call to return longest common substring of a set of ambigious completions. (Did that 7/10/2000. Also fixed a bug that might have caused an exception in certain cases when text completing. Also made new text completions go into the completer as new characters are entered.) * Add something that helps fill in the character names. This would be something that reads in all the names of the characters from the DOM and then creates a structure that allows us to predict the names of characters as they are typed in. Character-name completion essentially. (Did that. 7/9/2000. There are some bugs to work out though. Can't set the selection up right on the TextCompletionField. It loses focus.) * Fixed a minor error where if someone performed some annotations and then did a "New Page" or a "New Chapter" they would lose all the new annotations on the current page. * Add dates to the translations in the DTD and the XML so that we can actually track that... (Did that.) * Added a toolbar button for deleting bubbles * Change the AnnotationInformationDisplay so that it has a single JHTMLPane or whatever that is, and just gets HTML strings from each Note. This will get rid of a lot of creating displayPanels that get thown out. (Did that. There are some interesting points with this. Might be able to add HTML markup to the text entry and then it would be reflected in the text. Don't know how that would gel with the XML saving though - I have some feeling that it would not work well... Initial tests have shown that the formatting is lost.) * Make a better image file load process. Right now we just take the name of the last file referenced in the XML file and add one to the number for it. What we should do is this: * If we are using the local file system, get a listing of the directory that the files are in, and get the next file after the name of the last file referenced in the XML file. (Did that.) * Put up a dialog box that has the above default name, and a browse button to bring up a file chooser to let the choose a different file. (Did not do this - don't want to let the user select files from outside the image directory) * If we are using URLs to load the images, we can't get a listing of the directory, so we should keep the "increment by one" method that we already have. Also put up a dialog box that allows them to type in a different name. No browse button, of course. (Did that.) * Add file filters for .jpg, .gif, and .xml when appropriate (Did that.)