/* ******************************************************************************
*
* Copyright 2008-2010 Hans Dijkema
*
* JRichTextEditor is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* JRichTextEditor 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JRichTextEditor. If not, see <http://www.gnu.org/licenses/>.
*
* ******************************************************************************/
package nl.dykema.jxmlnote.help;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.Semaphore;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.text.BadLocationException;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import nl.dykema.jxmlnote.JXMLNoteEditor;
import nl.dykema.jxmlnote.document.DocumentAdminEvent;
import nl.dykema.jxmlnote.document.DocumentAdminListener;
import nl.dykema.jxmlnote.document.DocumentPreListener;
import nl.dykema.jxmlnote.document.XMLNoteDocument;
import nl.dykema.jxmlnote.document.XMLNoteImageIcon;
import nl.dykema.jxmlnote.document.XMLNoteImageIconSize;
import nl.dykema.jxmlnote.document.XMLNoteMark;
import nl.dykema.jxmlnote.exceptions.BadDocumentException;
import nl.dykema.jxmlnote.exceptions.BadStyleException;
import nl.dykema.jxmlnote.exceptions.DefaultXMLNoteErrorHandler;
import nl.dykema.jxmlnote.exceptions.MarkNoExistException;
import nl.dykema.jxmlnote.exceptions.NoSelectionException;
import nl.dykema.jxmlnote.help.data.HelpEntry;
import nl.dykema.jxmlnote.help.data.HelpImage;
import nl.dykema.jxmlnote.help.data.HelpTopic;
import nl.dykema.jxmlnote.icons.AddImage;
import nl.dykema.jxmlnote.icons.AddTopic;
import nl.dykema.jxmlnote.icons.ChangeTopic;
import nl.dykema.jxmlnote.icons.FlamencoIconAdapter;
import nl.dykema.jxmlnote.icons.InsertHyperlink;
import nl.dykema.jxmlnote.icons.InsertLink;
import nl.dykema.jxmlnote.icons.RemoveHyperlink;
import nl.dykema.jxmlnote.icons.RemoveLink;
import nl.dykema.jxmlnote.icons.RemoveTopic;
import nl.dykema.jxmlnote.interfaces.MarkMarkupProvider;
import nl.dykema.jxmlnote.interfaces.MarkMarkupProviderMaker;
import nl.dykema.jxmlnote.interfaces.XMLNotePreferences;
import nl.dykema.jxmlnote.internationalization.DefaultXMLNoteTranslator;
import nl.dykema.jxmlnote.internationalization.XMLNoteTranslator;
import nl.dykema.jxmlnote.toolbar.JXMLNoteIcon;
import nl.dykema.jxmlnote.toolbar.JXMLNoteIconPainter;
import nl.dykema.jxmlnote.toolbar.JXMLNoteToolBar;
import nl.dykema.jxmlnote.utils.BufferedImageBuilder;
import nl.dykema.jxmlnote.widgets.JRecentlyUsedMenu;
import nl.dykema.jxmlnote.widgets.JSizeGroup;
import nl.dykema.jxmlnote.widgets.JTreeMovable;
import nl.dykema.jxmlnote.widgets.JXMLNoteSwingUtils;
import nl.dykema.jxmlnote.widgets.JRecentlyUsedMenu.RecentlyUsedProvider;
import nl.dykema.jxmlnote.widgets.marks.DefaultMarkMarkupProvider;
/**
* With this class, help can be edited in a given JarFile.
*
* @author Hans Dijkema
*
*/
public class JHelpEditor extends JPanel implements ActionListener,
TreeSelectionListener, RecentlyUsedProvider, XMLNoteImageIcon.Provider {
static public boolean NEW_READ = true;
// ////////////////////////////////////////////////////////////////////////////////
// Private variables
// ////////////////////////////////////////////////////////////////////////////////
private static final long serialVersionUID = 1L;
private File _helpjar;
private JXMLNoteEditor _editor;
private XMLNoteDocument _document;
private JXMLNoteToolBar _toolbar;
private JXMLNoteToolBar _helpToolbar;
private JTreeMovable _tree;
private DefaultTreeModel _treeModel;
private DefaultMutableTreeNode _topics;
private XMLNoteTranslator _tr;
private Hashtable<String, HelpEntry> _help;
private Hashtable<String, XMLNoteImageIcon> _images;
private Hashtable<String, XMLNoteImageIcon> _imageBackingStore;
private TreePath _selected;
private boolean _saved;
private boolean _newfile;
private int _next;
private JFrame _frame;
private JRecentlyUsedMenu _recent;
private JSplitPane _splitpane;
private MyIconPainter _painter;
private XMLNotePreferences _preferences;
private DefaultMarkMarkupProvider _markProvider;
private DefaultMarkMarkupProvider _hyperlinkProvider;
private Color _cTopic=Color.blue;
private Color _cHyperlink=new Color(101,0,168);
private class MyIconPainter implements JXMLNoteIconPainter {
public void paint(int x, int y, int w, int h, Graphics2D g,
Component u, String iconType) {
FlamencoIconAdapter fia = null;
if (iconType.equals("add-topic")) {
fia = new AddTopic();
} else if (iconType.equals("remove-topic")) {
fia = new RemoveTopic();
} else if (iconType.equals("change-topic")) {
fia = new ChangeTopic();
} else if (iconType.equals("add-image")) {
fia = new AddImage();
} else if (iconType.equals("insert-link")) {
fia = new InsertLink();
} else if (iconType.equals("remove-link")) {
fia = new RemoveLink();
} else if (iconType.equals("insert-hyperlink")) {
fia = new InsertHyperlink();
} else if (iconType.equals("remove-hyperlink")) {
fia = new RemoveHyperlink();
}
Graphics2D gg = JXMLNoteIcon.prepareG(x, y, w, h,
fia.getOrigWidth(), fia.getOrigHeight(), g);
fia.paint(gg);
}
}
// ////////////////////////////////////////////////////////////////////////////////
// interfaces
// ////////////////////////////////////////////////////////////////////////////////
interface DoSomethingWithNode {
public void anything(DefaultMutableTreeNode node);
}
// ////////////////////////////////////////////////////////////////////////////////
// Supporting methods
// ////////////////////////////////////////////////////////////////////////////////
private JMenu makeMenu(String label) {
return JRecentlyUsedMenu.makeMenu(label);
}
private JMenuItem makeItem(String label, Icon icon, String actionCommand) {
return JRecentlyUsedMenu.makeMenuItem(label, icon, actionCommand, this);
}
private void createIds(DefaultMutableTreeNode node, DefaultMutableTreeNode ids) {
ids.setUserObject((Object) ((HelpTopic) node.getUserObject()).getTopicId());
int i;
for(i = 0; i < node.getChildCount(); i++) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) node.getChildAt(i);
DefaultMutableTreeNode in = new DefaultMutableTreeNode();
ids.add(in);
createIds(n, in);
}
}
private void writeObject(JarOutputStream jout, Object obj)
throws IOException {
ObjectOutputStream oout = new ObjectOutputStream(jout);
if (obj instanceof HelpEntry) {
HelpEntry he = (HelpEntry) obj;
he.writeObject(oout);
} else if (obj instanceof DefaultMutableTreeNode) { // tree of HelpTopics
DefaultMutableTreeNode node = (DefaultMutableTreeNode) obj;
DefaultMutableTreeNode ids = new DefaultMutableTreeNode();
createIds(node, ids);
oout.writeObject(ids);
Enumeration<DefaultMutableTreeNode> en = (Enumeration<DefaultMutableTreeNode>) node.breadthFirstEnumeration();
while (en.hasMoreElements()) {
DefaultMutableTreeNode topic = en.nextElement();
HelpTopic ht = (HelpTopic) topic.getUserObject();
ht.writeObject(oout);
}
} else if (obj instanceof HelpTopic) {
HelpTopic ht = (HelpTopic) obj;
ht.writeObject(oout);
} else {
if (obj!=null) {
System.out.println("Writing "+obj.getClass().getName());
}
oout.writeObject(obj);
}
}
private Window getWindow(Component c) {
return SwingUtilities.getWindowAncestor(c);
}
// ////////////////////////////////////////////////////////////////////////////////
// Image handling
// ////////////////////////////////////////////////////////////////////////////////
private XMLNoteImageIcon nullImage = null;
public XMLNoteImageIcon getIcon(String id) {
if (nullImage == null) {
nullImage = new XMLNoteImageIcon(
new JXMLNoteIcon("NoImage", 50, 50));
nullImage.setId("__null__");
}
XMLNoteImageIcon img = _images.get(id);
if (img == null) {
img = _imageBackingStore.get(id); // To support undo/redo
if (img == null) {
_images.put("__null__", nullImage);
return nullImage;
} else {
_images.put(id, img);
_imageBackingStore.remove(id);
return img;
}
} else {
return img;
}
}
public XMLNoteImageIcon getIcon(URL url,String description,XMLNoteImageIconSize size) {
XMLNoteImageIcon icn=new XMLNoteImageIcon(url,description,size);
String id=UUID.randomUUID().toString();
icn.setId(id);
_images.put(id, icn);
return icn;
}
private Vector<XMLNoteImageIcon> _imagesToBeRemoved = null;
private void addImageDocListeners() {
_document.addDocumentPreListener(new DocumentPreListener() {
public boolean insertUpdate(DocumentEvent e) {
return false; // no veto
}
public boolean changeUpdate(DocumentEvent e) {
return false; // no veto
}
public boolean removeUpdate(DocumentEvent e) {
int offset = e.getOffset();
int len = e.getLength();
try {
_imagesToBeRemoved = _document.imagesInRange(offset, len);
return false;
} catch (BadLocationException e1) {
// unexpected
DefaultXMLNoteErrorHandler.exception(e1);
return true; // let nothing happen
}
}
});
_document.addDocumentPostListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
}
public void insertUpdate(DocumentEvent e) {
int offset=e.getOffset();
int length=e.getLength();
try {
Vector<XMLNoteImageIcon> v=_document.imagesInRange(offset, length);
Iterator<XMLNoteImageIcon> it = v.iterator();
while (it.hasNext()) {
XMLNoteImageIcon icn = it.next();
_imageBackingStore.remove(icn.getId());
_images.put(icn.getId(),icn);
}
} catch (BadLocationException E) {
DefaultXMLNoteErrorHandler.exception(E);
}
}
public void removeUpdate(DocumentEvent e) {
if (_imagesToBeRemoved != null) {
Iterator<XMLNoteImageIcon> it = _imagesToBeRemoved.iterator();
while (it.hasNext()) {
XMLNoteImageIcon icn = it.next();
_imageBackingStore.put(icn.getId(), icn);
_images.remove(icn.getId());
}
_imagesToBeRemoved=null;
}
}
});
}
// ////////////////////////////////////////////////////////////////////////////////
// GUI Creation
// ////////////////////////////////////////////////////////////////////////////////
public interface ToolsProvider {
public void addTools(JXMLNoteToolBar bar);
}
public int getMaxCount() {
return 6;
}
@SuppressWarnings("unchecked")
public Vector<String> getList() {
XMLNotePreferences prefs = _preferences;
Vector<String> vec = new Vector<String>();
String val = prefs.getString("recently_used_files", null);
if (val != null) {
ByteArrayInputStream bin = new ByteArrayInputStream(val.getBytes());
XMLDecoder dec = new XMLDecoder(bin);
vec = (Vector<String>) dec.readObject();
dec.close();
}
return vec;
}
public void putList(Vector<String> list) {
XMLNotePreferences prefs = _preferences;
ByteArrayOutputStream bout = new ByteArrayOutputStream();
XMLEncoder enc = new XMLEncoder(bout);
enc.writeObject(list);
enc.flush();
enc.close();
String xml = bout.toString();
prefs.put("recently_used_files", xml);
}
public String clearListText() {
return _tr._("Clear");
}
private void createGui(ToolsProvider toolprovider) {
BorderLayout layout = new BorderLayout();
layout.setVgap(3);
layout.setHgap(3);
super.setLayout(layout);
try {
_document = new XMLNoteDocument();
} catch (BadStyleException e) {
DefaultXMLNoteErrorHandler.fatal(e, -1,
"Unexpected: bad style exception");
}
_document.setXMLNoteImageIconProvider(this);
_document.addDocumentAdminListener(new DocumentAdminListener() {
public boolean documentWillBeReset(DocumentAdminEvent e) {
return false;
}
public void documentHasBeenReset(DocumentAdminEvent e) {
}
public boolean documentWillBeCleared(DocumentAdminEvent e) {
return false;
}
public void documentHasBeenCleared(DocumentAdminEvent e) {
}
public void documentChangedState(DocumentAdminEvent e) {
//System.out.println("document changed="+_document.changed());
}
});
_editor = new JXMLNoteEditor(_document,new MarkMarkupProviderMaker() {
public MarkMarkupProvider create(String markId, String markClass) {
if (markClass.startsWith("TopicLink:")) {
return _markProvider;
} else {
return _hyperlinkProvider;
}
}
});
_toolbar = _editor.toolbar();
_toolbar.initToolBar();
_treeModel = new DefaultTreeModel(null);
loadTopics();
_tree = new JTreeMovable(_treeModel);
_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
JPanel editPane = new JPanel();
editPane.setLayout(new BorderLayout());
editPane.add(_toolbar, BorderLayout.NORTH);
editPane.add(_editor, BorderLayout.CENTER);
JSplitPane pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
new JScrollPane(_tree), editPane);
_splitpane = pane;
pane.setContinuousLayout(true);
_helpToolbar = new JXMLNoteToolBar(this, null, 36);
_helpToolbar.removeAllSections();
_helpToolbar.addSection("file", _tr._("File operations"));
_helpToolbar.add("file", JXMLNoteToolBar.ACTION_NEW,
_tr._("Begin new Help File"), this);
_helpToolbar.add("file", JXMLNoteToolBar.ACTION_SAVE,
_tr._("Save a Help File"), this);
_helpToolbar.add("file", JXMLNoteToolBar.ACTION_LOAD,
_tr._("Open a Help File"), this);
_helpToolbar.addSection("topics", _tr._("Topic actions"));
_helpToolbar.add("topics", "add-topic", _tr._("Add a new topic"), this,
new JXMLNoteIcon("add-topic", _painter));
_helpToolbar.add("topics", "change-topic", _tr._("Change a topic"),
this, new JXMLNoteIcon("change-topic", _painter));
_helpToolbar.add("topics", "remove-topic", _tr._("Remove a topic"),
this, new JXMLNoteIcon("remove-topic", _painter));
_helpToolbar.add("topics", "insert-link", _tr._("Insert link"),
this, new JXMLNoteIcon("insert-link", _painter));
_helpToolbar.add("topics", "remove-link", _tr._("Remove link"),
this, new JXMLNoteIcon("remove-link", _painter));
_helpToolbar.add("topics", "insert-hyperlink", _tr._("Insert hyperlink"),
this, new JXMLNoteIcon("insert-hyperlink", _painter));
_helpToolbar.add("topics", "remove-hyperlink", _tr._("Remove hyperlink"),
this, new JXMLNoteIcon("remove-hyperlink", _painter));
_helpToolbar.addSection("image", _tr._("Image handling"));
_helpToolbar.add("image", "add-image", _tr._("Add an image"), this,
new JXMLNoteIcon("add-image", _painter));
_helpToolbar.addSection("test", _tr._("Test help"));
_helpToolbar.add("test",JXMLNoteToolBar.ACTION_HELP,_tr._("Test the help file"), this);
toolprovider.addTools(_helpToolbar);
_helpToolbar.initToolBar();
super.add(_helpToolbar, BorderLayout.NORTH);
super.add(pane, BorderLayout.CENTER);
_tree.addTreeSelectionListener(this);
}
private void setTitle() {
if (_frame != null) {
if (_helpjar == null) {
_frame.setTitle(_tr._("Help File Editor"));
} else {
String title = _tr._("Help File Editor: %s");
_frame.setTitle(String.format(title, _helpjar.getName()));
}
}
}
// ////////////////////////////////////////////////////////////////////////////////
// Loading and saving
// ////////////////////////////////////////////////////////////////////////////////
private void loadTopics() {
cleanup(false);
class R extends SwingWorker<String,String> {
private DefaultListModel _list;
private JDialog _dlg;
private boolean _finished;
public String doInBackground() {
try {
if (_helpjar != null && _helpjar.canRead()) {
publish(String.format(_tr._("Opening Help File %s"),_helpjar));
JarFile hj = new JarFile(_helpjar);
publish(String.format(_tr._("Reading Help Topics")));
ZipEntry ze = hj.getEntry("HelpTopics.xnhlp");
if (ze != null) {
try {
InputStream in = hj.getInputStream(ze);
ObjectInputStream dec = new ObjectInputStream(in);
if (NEW_READ) {
Hashtable<String, HelpTopic> htt = new Hashtable<String, HelpTopic>();
DefaultMutableTreeNode ids = (DefaultMutableTreeNode) dec.readObject();
Enumeration<DefaultMutableTreeNode> en = (Enumeration<DefaultMutableTreeNode>) ids.breadthFirstEnumeration();
while (en.hasMoreElements()) {
DefaultMutableTreeNode id = en.nextElement();
HelpTopic ht = new HelpTopic();
ht.readObject(dec);
htt.put(ht.getTopicId(), ht);
}
en = (Enumeration<DefaultMutableTreeNode>) ids.breadthFirstEnumeration();
while (en.hasMoreElements()) {
DefaultMutableTreeNode id = en.nextElement();
String t_id = (String) id.getUserObject();
id.setUserObject(htt.get(t_id));
}
_topics = ids;
} else {
_topics = (DefaultMutableTreeNode) dec.readObject();
}
in.close();
} catch (Exception e) {
DefaultXMLNoteErrorHandler.exception(e);
}
@SuppressWarnings("unchecked")
Enumeration<DefaultMutableTreeNode> en = (Enumeration<DefaultMutableTreeNode>) _topics.breadthFirstEnumeration();
while (en.hasMoreElements()) {
DefaultMutableTreeNode topic = en.nextElement();
HelpTopic ht = (HelpTopic) topic.getUserObject();
publish(String.format(_tr._("Help Topic %s (id=%s)"),ht.getName(),ht.getTopicId()));
ZipEntry hze = hj.getEntry(ht.getTopicId() + ".top");
try {
InputStream in = hj.getInputStream(hze);
ObjectInputStream dec = new ObjectInputStream(in);
HelpEntry he;
if (NEW_READ) {
he = new HelpEntry();
he.readObject(dec);
} else {
he = (HelpEntry) dec.readObject();
}
in.close();
if (he != null) {
_help.put(ht.getTopicId(), he);
}
} catch (Exception e) {
DefaultXMLNoteErrorHandler.exception(e);
}
}
{
ZipEntry kze = hj.getEntry("ImageIds.vec");
publish(String.format(_tr._("Reading Image Vector")));
try {
InputStream in = hj.getInputStream(kze);
ObjectInputStream dec = new ObjectInputStream(in);
@SuppressWarnings("unchecked")
Vector<String> keys = (Vector<String>) dec.readObject();
int nimg=keys.size();
int iimg=0;
Iterator<String> it = keys.iterator();
while (it.hasNext()) {
String id = it.next();
ZipEntry ize = hj.getEntry(id + ".img");
in = hj.getInputStream(ize);
//dec = new ObjectInputStream(in);
HelpImage himg = new HelpImage();
himg.read(in);
iimg+=1;
publish(String.format(_tr._("Reading Image %d of %d (size=%.1fkb) (%s)"),iimg,nimg,himg.sizeInKb(),id));
XMLNoteImageIcon img = new XMLNoteImageIcon(
himg.getId(), himg.getImageIcon(),
himg.getDescription(),
himg.getSize());
_images.put(img.getId(), img);
}
} catch (Exception e) {
DefaultXMLNoteErrorHandler.exception(e);
}
}
publish(String.format(_tr._("Done reading Help File")));
}
hj.close();
_newfile = false;
}
} catch (Exception E) {
DefaultXMLNoteErrorHandler.exception(E);
}
return "done" ;
}
protected void process(List<String> stuff) {
Iterator<String> it=stuff.iterator();
while (it.hasNext()) {
String s=it.next();
_list.insertElementAt(s,0);
}
}
protected void done() {
_finished=true;
try {
Thread.sleep(1000);
} catch (Exception E) {}
_dlg.setVisible(false);
}
public boolean finished() {
return _finished;
}
public R(DefaultListModel l,JDialog dlg) {
_list=l;
_dlg=dlg;
_finished=false;
}
}
JDialog dlg=new JDialog(SwingUtilities.getWindowAncestor(this),_tr._("Loading..."));
DefaultListModel model=new DefaultListModel();
JList list=new JList(model);
dlg.add(new JScrollPane(list));
dlg.setModal(true);
dlg.setMinimumSize(new Dimension(700,400));
R worker=new R(model,dlg);
worker.execute();
dlg.pack();
JXMLNoteSwingUtils.centerOnParent(SwingUtilities.getWindowAncestor(this), dlg);
if (!worker.finished()) {
dlg.setVisible(true);
}
_treeModel.setRoot(_topics);
if (_tree!=null && _tree.getRowCount()>1) {
_tree.setSelectionRow(1);
}
}
private void writeTopics() {
writeTopics(_helpjar);
}
private void writeTopics(File file) {
if (_newfile) {
File lastpath=new File(_preferences.getString("lastpath", "."));
JFileChooser chooser = new JFileChooser(lastpath);
FileNameExtensionFilter filter = new FileNameExtensionFilter(
"Help files", "xnhlp");
chooser.setFileFilter(filter);
int returnVal = chooser.showSaveDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
lastpath=chooser.getCurrentDirectory();
_preferences.put("lastpath", lastpath.getAbsolutePath());
file = chooser.getSelectedFile();
String fl = file.getAbsolutePath();
if (!fl.endsWith(".xnhlp")) {
file = new File(fl + ".xnhlp");
}
} else {
return;
}
}
String jarName = file.getAbsolutePath();
try {
FileOutputStream fout = new FileOutputStream(jarName);
JarOutputStream jout = new JarOutputStream(fout);
{
ZipEntry ze = new ZipEntry("HelpTopics.xnhlp");
jout.putNextEntry(ze);
writeObject(jout, _topics);
}
{
@SuppressWarnings("unchecked")
Enumeration<DefaultMutableTreeNode> en = _topics
.breadthFirstEnumeration();
while (en.hasMoreElements()) {
DefaultMutableTreeNode topic = en.nextElement();
HelpTopic ht = (HelpTopic) topic.getUserObject();
HelpEntry he = (HelpEntry) _help.get(ht.getTopicId());
ZipEntry hze = new ZipEntry(ht.getTopicId() + ".top");
jout.putNextEntry(hze);
if (he == null) { he = new HelpEntry(); }
writeObject(jout, he);
}
}
{
Set<String> skeys = _images.keySet();
Vector<String> keys = new Vector<String>();
Iterator<String> it = skeys.iterator();
while (it.hasNext()) {
String id = it.next();
XMLNoteImageIcon icn = _images.get(id);
if (icn.type() == XMLNoteImageIcon.Type.IMAGEICON) {
keys.add(id);
}
}
ZipEntry kze = new ZipEntry("ImageIds.vec");
jout.putNextEntry(kze);
writeObject(jout, keys);
it = keys.iterator();
while (it.hasNext()) {
XMLNoteImageIcon img = _images.get(it.next());
HelpImage himg = new HelpImage(img.getId(),
img.getOriginal(), img.getDescription(),
img.getSize());
ZipEntry ize = new ZipEntry(img.getId() + ".img");
jout.putNextEntry(ize);
himg.write(jout);
//writeObject(jout, himg);
}
}
jout.close();
fout.close();
_helpjar = new File(jarName);
setTitle();
_saved = true;
_newfile = false;
} catch (IOException e) {
DefaultXMLNoteErrorHandler.exception(e);
}
}
private void loadTopic(HelpTopic topic) {
_imageBackingStore.clear();
if (topic == null) {
_document.clear();
} else {
HelpEntry entry = (HelpEntry) _help.get(topic.getTopicId());
if (entry != null) {
try {
//String xml = XMLNoteUtils.prettyPrintXML(entry.getXmlnote());
//System.out.println(xml);
_document.resetFromXML(entry.getXmlnote());
} catch (BadDocumentException e) {
DefaultXMLNoteErrorHandler.exception(e);
}
} else {
_document.clear();
}
}
}
private void saveDocument() {
if (_selected!=null) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) _selected.getLastPathComponent();
HelpTopic t = (HelpTopic) node.getUserObject();
String id = t.getTopicId();
HelpEntry he = (HelpEntry) _help.get(id);
if (he != null) {
try {
he.setXmlnote(_document.toXML());
_document.setChanged(false);
_saved = false; // the helpfile needs saving
} catch (BadDocumentException e1) {
DefaultXMLNoteErrorHandler.exception(e1);
he.setXmlnote(XMLNoteDocument.emptyXML());
}
}
}
}
private HelpEntry getSelectedEntry() {
if (_selected == null) {
return null;
} else {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) _selected
.getLastPathComponent();
HelpTopic t = (HelpTopic) node.getUserObject();
String id = t.getTopicId();
HelpEntry he = (HelpEntry) _help.get(id);
return he;
}
}
public void checkDocumentSaved() {
if (_helpjar != null) {
if (_document.changed()) {
int result = JOptionPane
.showConfirmDialog(
this,
_tr._("Current topic is changed, do you want to store it?"),
_tr._("Save Topic"), JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION) {
saveDocument();
}
}
}
}
public void checkTopicsSaved() {
if (_helpjar != null) {
checkDocumentSaved();
if (!_saved) {
int result = JOptionPane.showConfirmDialog(this,
_tr._("This help file has changed, store it?"),
_tr._("Save Help File"), JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION) {
writeTopics();
}
}
}
}
public boolean cleanup(boolean affectHelpJar) {
if (_helpjar != null) {
checkTopicsSaved();
}
_topics = new DefaultMutableTreeNode(new HelpTopic("Help Topics",""));
_treeModel.setRoot(_topics);
if (affectHelpJar) {
_helpjar = null;
}
_selected = null;
_help = new Hashtable<String, HelpEntry>();
_images = new Hashtable<String, XMLNoteImageIcon>();
_imageBackingStore = new Hashtable<String, XMLNoteImageIcon>();
_document.clear();
if (_tree!=null) {
_tree.setSelectionRow(0);
}
return true;
}
// ////////////////////////////////////////////////////////////////////////////////
// Handle actions
// ////////////////////////////////////////////////////////////////////////////////
public void actionPerformed(ActionEvent e) {
//System.out.println(e);
String cmd = e.getActionCommand();
if (cmd.equals("load")) {
openHelp();
} else if (cmd.equals("new")) {
newHelp();
} else if (cmd.equals("save")) {
saveHelp();
} else if (cmd.equals("add-topic")) {
newTopic();
} else if (cmd.equals("remove-topic")) {
removeTopic();
} else if (cmd.equals("change-topic")) {
changeTopic();
} else if (cmd.equals("insert-link")) {
insertLink();
} else if (cmd.equals("remove-link")) {
removeLink();
} else if (cmd.equals("insert-hyperlink")) {
insertHyperLink();
} else if (cmd.equals("remove-hyperlink")) {
removeHyperLink();
} else if (cmd.startsWith("recent:")) {
openRecent(cmd.substring(7));
} else if (cmd.equals("add-image")) {
addImage();
} else if (cmd.equals("help")) {
testHelp();
}
}
public void valueChanged(TreeSelectionEvent e) {
TreePath path = e.getPath();
DefaultMutableTreeNode dnode = (DefaultMutableTreeNode) path
.getLastPathComponent();
if (_selected != null) {
checkDocumentSaved();
}
_selected = path;
if (dnode != _topics) {
loadTopic((HelpTopic) dnode.getUserObject());
_editor.setUnresponsive(false);
} else {
_document.clear();
_editor.setUnresponsive(true);
}
}
private void newHelp() {
if (!cleanup(true)) {
return;
}
_newfile = true;
_helpjar = new File(String.format("Help_%d.xnhlp", _next++));
setTitle();
}
private void saveHelp() {
if (_helpjar != null) {
saveDocument();
writeTopics();
if (_recent != null && _helpjar != null) {
_recent.addRecentUse(_helpjar.getAbsolutePath());
}
} else {
JOptionPane.showMessageDialog(this,
_tr._("Please open a help file or create a new one first"),
_tr._("Save Help"), JOptionPane.INFORMATION_MESSAGE);
}
}
private void openRecent(String file) {
File f = new File(file);
if (f.canRead()) {
if (!cleanup(true)) {
return;
}
_helpjar = f;
loadTopics();
setTitle();
if (_recent != null) {
_recent.addRecentUse(f.getAbsolutePath());
}
} else {
_recent.removeRecentUse(file);
}
}
private void openHelp() {
File lastpath=new File(_preferences.getString("lastpath", "."));
JFileChooser chooser = new JFileChooser(lastpath);
FileNameExtensionFilter filter = new FileNameExtensionFilter(
"Help files", "xnhlp");
chooser.setFileFilter(filter);
int returnVal = chooser.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
lastpath=chooser.getCurrentDirectory();
_preferences.put("lastpath", lastpath.getAbsolutePath());
File file = chooser.getSelectedFile();
String fl = file.getAbsolutePath();
if (!fl.endsWith(".xnhlp")) {
file = new File(fl + ".xnhlp");
}
if (file.canRead()) {
if (!cleanup(true)) {
return;
}
_helpjar = file;
loadTopics();
setTitle();
if (_recent != null) {
_recent.addRecentUse(file.getAbsolutePath());
}
}
}
}
private void newTopic() {
if (_selected == null) {
JOptionPane.showMessageDialog(this,
_tr._("Select a parent topic first"), _tr._("New Topic"),
JOptionPane.INFORMATION_MESSAGE);
return;
}
HelpTopic tp=TopicDlg.showDlg(getWindow(this), _tr._("Create a new Topic"));
if (tp!=null) {
if (!tp.getName().equals("")) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) _selected
.getLastPathComponent();
DefaultMutableTreeNode n = new DefaultMutableTreeNode(tp);
_treeModel.insertNodeInto(n, node, node.getChildCount());
HelpEntry he = new HelpEntry();
_help.put(tp.getTopicId(), he);
TreePath p = _selected.pathByAddingChild(n);
_tree.scrollPathToVisible(p);
_tree.setSelectionPath(p);
} else {
JOptionPane.showMessageDialog(this,
_tr._("Topic text may not be empty"),
_tr._("New Topic"), JOptionPane.INFORMATION_MESSAGE);
}
}
}
private void changeTopic() {
if (_selected == null) {
JOptionPane.showMessageDialog(this, _tr._("Select a topic first"),
_tr._("Change Topic"), JOptionPane.INFORMATION_MESSAGE);
return;
}
DefaultMutableTreeNode node = (DefaultMutableTreeNode) _selected
.getLastPathComponent();
HelpTopic topic = (HelpTopic) node.getUserObject();
HelpTopic tp=TopicDlg.showDlg(getWindow(this), _tr._("Change Topic"),topic);
if (tp != null) {
if (!tp.getName().equals("")) {
topic.setName(tp.getName());
topic.setKey(tp.getKey());
_treeModel.nodeChanged(node);
_saved = false;
} else {
JOptionPane.showMessageDialog(this,
_tr._("Topic text may not be empty"),
_tr._("Change Topic"), JOptionPane.INFORMATION_MESSAGE);
}
}
}
private void removeTopic() {
checkDocumentSaved();
if (_selected == null) {
JOptionPane.showMessageDialog(this, _tr._("Select a topic first"),
_tr._("Remove Topic"), JOptionPane.INFORMATION_MESSAGE);
return;
}
DefaultMutableTreeNode node = (DefaultMutableTreeNode) _selected.getLastPathComponent();
if (node.isLeaf()) {
int result = JOptionPane.showConfirmDialog(this,
_tr._("Do you want to remove the selected topic?"),
_tr._("Delete Topic"), JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION) {
_treeModel.removeNodeFromParent(node);
// Remove all associated images in the document
Vector<XMLNoteImageIcon> images=_document.getAllImages();
Iterator<XMLNoteImageIcon> it=images.iterator();
while (it.hasNext()) { _images.remove(it.next().getId()); }
_document.clear();
}
} else {
JOptionPane.showMessageDialog(this, _tr._("Remove the children of this topic first"),
_tr._("Remove Topic"), JOptionPane.INFORMATION_MESSAGE);
}
}
private void insertHyperLink() {
if (_editor.getSelectionEnd()>_editor.getSelectionStart()) {
String link=JOptionPane.showInputDialog(this, _tr._("Please input a hyperlink" ), _tr._("Insert Hyperlink"));
if (link!=null && !link.trim().equals("")) {
UUID newid=UUID.randomUUID();
try {
_editor.insertMark(newid.toString(),"HyperLink:"+link);
} catch (Exception e1) {
DefaultXMLNoteErrorHandler.exception(e1);
}
} else {
JOptionPane.showMessageDialog(this, _tr._("Please insert a hyperlink"),
_tr._("Insert Hyperlink"), JOptionPane.INFORMATION_MESSAGE);
}
} else {
JOptionPane.showMessageDialog(this, _tr._("You need to select text to be able to insert a hyperlink"),
_tr._("Insert Hyperlink"), JOptionPane.INFORMATION_MESSAGE);
}
}
private void removeHyperLink() {
removeLink();
}
private void insertLink() {
if (_editor.getSelectionEnd()>_editor.getSelectionStart()) {
final JJDialog dlg=new JJDialog(getWindow(this),_tr._("Insert link to Topic"));
final JTree tree = new JTree(_treeModel);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setMinimumSize(new Dimension(350,500));
JScrollPane pane=new JScrollPane(tree,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
JPanel pnl=new JPanel();
pnl.setLayout(new BorderLayout());
pnl.add(pane,BorderLayout.CENTER);
JButton cancel=new JButton(_tr._("Cancel"));
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tree.clearSelection();
dlg.setVisible(false);
}
});
JButton ok=new JButton(_tr._("Ok"));
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dlg.setVisible(false);
}
});
ok.setDefaultCapable(true);
JPanel p=new JPanel();
p.setLayout(new FlowLayout(FlowLayout.RIGHT));
p.add(cancel);p.add(ok);
this.getRootPane().setDefaultButton(ok);
pnl.add(p,BorderLayout.SOUTH);
dlg.add(pnl);
dlg.pack();
dlg.centerOnParent();
dlg.setModal(true);
dlg.setVisible(true);
if (tree.getSelectionPath()!=null) {
DefaultMutableTreeNode o=(DefaultMutableTreeNode) tree.getSelectionPath().getLastPathComponent();
HelpTopic tp=(HelpTopic) o.getUserObject();
UUID newid=UUID.randomUUID();
try {
_editor.insertMark(newid.toString(),"TopicLink:"+tp.getTopicId());
} catch (Exception e1) {
DefaultXMLNoteErrorHandler.exception(e1);
}
}
} else {
JOptionPane.showMessageDialog(this, _tr._("You need to select text to be able to insert a link to a topic"),
_tr._("Insert link"), JOptionPane.INFORMATION_MESSAGE);
}
}
public void removeLink() {
Vector<XMLNoteMark> marks;
if (_editor.getSelectionEnd()>_editor.getSelectionStart()) {
try {
marks=_editor.getMarksForSelection();
} catch (NoSelectionException e) {
// Unexpected
DefaultXMLNoteErrorHandler.exception(e);
marks=null;
}
} else {
marks=_editor.getMarksForCaret();
}
if (marks==null || marks.size()==0) {
JOptionPane.showMessageDialog(this, _tr._("You need to have the caret in a link or have a link selected to be able to remove it"),
_tr._("Remove link"), JOptionPane.INFORMATION_MESSAGE);
} else {
int i,n;
for(i=0,n=marks.size();i<n;i++) {
XMLNoteMark m=marks.get(i);
try {
_document.removeMark(m.id());
} catch (MarkNoExistException e) {
// again: unexpected
DefaultXMLNoteErrorHandler.exception(e);
}
}
}
}
private void addImage() {
if (_selected == null) {
return;
}
File lastPath=new File(_preferences.getString("imagedir","~"));
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(lastPath);
chooser.setAccessory(new ImagePreview(chooser));
FileNameExtensionFilter filter = new FileNameExtensionFilter("Images",
"jpg", "png", "gif");
chooser.setFileFilter(filter);
int returnVal = chooser.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
File dir=chooser.getCurrentDirectory();
_preferences.put("imagedir", dir.getAbsolutePath());
if (file.canRead()) {
String id = UUID.randomUUID().toString();
URL url;
String width = JOptionPane.showInputDialog(this, _tr
._("Please give the desired width of the image in cm"),
_tr._("3"));
if (width != null && !width.trim().equals("")) {
int widthInCm = Integer.parseInt(width);
if (widthInCm < 1) {
widthInCm = 1;
}
double points = ((72.0 / 2.54) * widthInCm);
int widthInPt = (int) Math.round(points);
try {
url = new URL("file:///" + file.getCanonicalPath());
XMLNoteImageIconSize sz=new XMLNoteImageIconSize(widthInPt,-1,XMLNoteImageIconSize.TYPE_PT);
XMLNoteImageIcon icon = new XMLNoteImageIcon(url,file.getName(), sz);
icon.setId(id);
_images.put(id, icon);
int offset = _editor.getCaretPosition();
_editor.getDocument().insertImage(offset, id);
} catch (Exception e) {
DefaultXMLNoteErrorHandler.exception(e);
}
}
}
}
}
private void testHelp() {
try {
final JDialog dlg=new JDialog(_frame,_tr._("Testing Help"),true);
JarFile jarfile;
jarfile = new JarFile(_helpjar.getAbsolutePath());
JHelpViewer viewer=new JHelpViewer(jarfile,_preferences);
JPanel panel=new JPanel();
BorderLayout layout=new BorderLayout();
layout.setHgap(3);layout.setVgap(3);
panel.setLayout(layout);
final ActionListener closeAction=new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
_preferences.put("testHelp.w", dlg.getSize().width);
_preferences.put("testHelp.h", dlg.getSize().height);
_preferences.put("testHelp.x", dlg.getLocation().x);
_preferences.put("testHelp.y", dlg.getLocation().y);
dlg.setVisible(false);
}
};
JMenuBar bar=new JMenuBar();
JMenu window=JRecentlyUsedMenu.makeMenu("_Window");
JMenuItem close=JRecentlyUsedMenu.makeMenuItem("_Close", null, "close", closeAction);
window.add(close);
bar.add(window);
JPanel menuAndTools=new JPanel();
menuAndTools.setLayout(new BorderLayout());
//menuAndTools.setLayout(new BoxLayout(menuAndTools,BoxLayout.Y_AXIS));
menuAndTools.add(bar,BorderLayout.NORTH);
JXMLNoteToolBar tbar=viewer.toolbar();
tbar.initToolBar();
menuAndTools.add(tbar,BorderLayout.SOUTH);
panel.add(menuAndTools,BorderLayout.NORTH);
panel.add(viewer,BorderLayout.CENTER);
dlg.add(panel);
dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dlg.setPreferredSize(new Dimension(_preferences.getInt("testHelp.w", 500),_preferences.getInt("testHelp.h",400)));
dlg.setLocation(_preferences.getInt("testHelp.x",_frame.getLocation().x+30),
_preferences.getInt("testHelp.y",_frame.getLocation().y+30)
);
dlg.pack();
dlg.setVisible(true);
} catch (Exception e) {
DefaultXMLNoteErrorHandler.exception(e);
}
}
// ////////////////////////////////////////////////////////////////////////////////
// Install menu on frame
// ////////////////////////////////////////////////////////////////////////////////
/**
* Instals the JHelpEditor menu on the frame.
*
* @param frame
*/
public void installMenu(JFrame frame) {
_frame = frame;
setTitle();
JMenuBar _bar = new JMenuBar();
JMenu file = makeMenu("_File");
_bar.add(file);
file.add(makeItem("_New help file", null, "new"));
file.add(makeItem("_Open help file", null, "load"));
file.add(makeItem("_Save help file", null, "save"));
_recent = new JRecentlyUsedMenu("_Recent help files", this, this);
file.add(_recent);
JMenu topics = makeMenu("_Topics");
_bar.add(topics);
topics.add(makeItem("_New topic", null, "add-topic"));
topics.add(makeItem("_Remove topic", null, "remove-topic"));
topics.add(makeItem("_Change topic", null, "change-topic"));
topics.addSeparator();
topics.add(makeItem("_Insert link", null, "insert-link"));
topics.add(makeItem("Remove _link", null, "remove-link"));
topics.add(makeItem("_Hyperlink", null, "insert-hyperlink"));
topics.add(makeItem("Remove hyperlink", null, "remove-hyperlink"));
topics.addSeparator();
topics.add(makeItem("_Add image", null, "add-image"));
frame.setJMenuBar(_bar);
}
// ////////////////////////////////////////////////////////////////////////////////
// Preferences
// ////////////////////////////////////////////////////////////////////////////////
public void storePrefs() {
XMLNotePreferences prefs = _preferences;
prefs.put("splitbar", _splitpane.getDividerLocation());
}
public void applyPrefs() {
XMLNotePreferences prefs = _preferences;
int div = prefs.getInt("splitbar", 150);
_splitpane.setDividerLocation(div);
}
// ////////////////////////////////////////////////////////////////////////////////
// Constructor
// ////////////////////////////////////////////////////////////////////////////////
public JHelpEditor(ToolsProvider prov,XMLNotePreferences prefs) {
_preferences=prefs;
_helpjar = null;
_tr = new DefaultXMLNoteTranslator();
_saved = true;
_next = 1;
_painter = new MyIconPainter();
_markProvider=new DefaultMarkMarkupProvider(MarkMarkupProvider.MarkupType.UNDERLINED,_cTopic);
_markProvider.setTextColor(_cTopic);
_hyperlinkProvider=new DefaultMarkMarkupProvider(MarkMarkupProvider.MarkupType.UNDERLINED,_cHyperlink);
_hyperlinkProvider.setTextColor(_cHyperlink);
createGui(prov);
addImageDocListeners();
applyPrefs();
newHelp();
}
}
class ImagePreview extends JComponent implements PropertyChangeListener {
ImageIcon thumbnail = null;
File file = null;
static int _iconWidth = 140;
public ImagePreview(JFileChooser fc) {
setPreferredSize(new Dimension(150, 150));
fc.addPropertyChangeListener(this);
super.setBorder(BorderFactory.createEtchedBorder());
}
public void loadImage() {
if (file == null) {
thumbnail = null;
return;
}
// Don't use createImageIcon (which is a wrapper for getResource)
// because the image we're trying to load is probably not one
// of this program's own resources.
ImageIcon tmpIcon = new ImageIcon(file.getPath());
if (tmpIcon != null) {
if (tmpIcon.getIconWidth() > _iconWidth) {
thumbnail = new ImageIcon(BufferedImageBuilder.getScaledInstance(tmpIcon.getImage(), _iconWidth, -1));
} else { // no need to miniaturize
thumbnail = tmpIcon;
}
}
}
public void propertyChange(PropertyChangeEvent e) {
boolean update = false;
String prop = e.getPropertyName();
// If the directory changed, don't show an image.
if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(prop)) {
file = null;
update = true;
// If a file became selected, find out which one.
} else if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(prop)) {
file = (File) e.getNewValue();
update = true;
}
// Update the preview accordingly.
if (update) {
thumbnail = null;
if (isShowing()) {
loadImage();
repaint();
}
}
}
protected void paintComponent(Graphics g) {
if (thumbnail == null) {
loadImage();
}
if (thumbnail != null) {
int x = getWidth() / 2 - thumbnail.getIconWidth() / 2;
int y = getHeight() / 2 - thumbnail.getIconHeight() / 2;
if (y < 0) {
y = 0;
}
if (x < 5) {
x = 5;
}
thumbnail.paintIcon(this, g, x, y);
}
}
}
class JJDialog extends JDialog {
private Window _parent=null;
public void centerOnParent () {
int x;
int y;
// Find out our parent
Point topLeft = _parent.getLocationOnScreen();
Dimension parentSize = _parent.getSize();
Dimension mySize = this.getSize();
if (parentSize.width > mySize.width)
x = ((parentSize.width - mySize.width)/2) + topLeft.x;
else
x = topLeft.x;
if (parentSize.height > mySize.height)
y = ((parentSize.height - mySize.height)/2) + topLeft.y;
else
y = topLeft.y;
this.setLocation (x, y);
}
public JJDialog(Window parent,String title) {
super(parent,title);
_parent=parent;
}
}
class TopicDlg extends JJDialog implements ActionListener {
private JTextField _topicName;
private JTextField _topicKey;
private JLabel _topicId;
private boolean _canceled=false;
public String topicName() {
return _topicName.getText().trim();
}
public String topicKey() {
return _topicKey.getText().trim();
}
public void actionPerformed(ActionEvent e) {
String c=e.getActionCommand();
if (c.equals("cancel")) {
_canceled=true;
this.setVisible(false);
} else {
this.setVisible(false);
}
}
public boolean canceled() {
return _canceled;
}
public static HelpTopic showDlg(Window parent,String title) {
return showDlg(parent,title,new HelpTopic("",""));
}
public static HelpTopic showDlg(Window parent,String title,HelpTopic tp) {
TopicDlg dlg=new TopicDlg(parent,title,tp);
dlg.pack();
dlg.centerOnParent();
dlg.setVisible(true);
if (!dlg.canceled()) {
HelpTopic top=new HelpTopic(dlg.topicName(),dlg.topicKey());
top.setTopicId(tp.getTopicId());
return top;
} else {
return null;
}
}
protected TopicDlg(Window parent,String title,HelpTopic ht) {
super(parent,title);
super.setModal(true);
super.setLocationRelativeTo(parent);
XMLNoteTranslator _tr=new DefaultXMLNoteTranslator();
JPanel dlgPane=new JPanel();
JSizeGroup labels=new JSizeGroup(JSizeGroup.HORIZONTAL);
BorderLayout bdr=new BorderLayout();
dlgPane.setLayout(bdr);
JLabel l;
JPanel f1=new JPanel();
f1.setLayout(new FlowLayout(FlowLayout.LEFT));
l=new JLabel(_tr._("Topic name :"));f1.add(l);labels.add(l);
_topicName=new JTextField(30);f1.add(_topicName);
_topicName.setText(ht.getName());
JPanel f2=new JPanel();
f2.setLayout(new FlowLayout(FlowLayout.LEFT));
l=new JLabel(_tr._("Topic key :"));f2.add(l);labels.add(l);
_topicKey=new JTextField(20);f2.add(_topicKey);
_topicKey.setText(ht.getKey());
JPanel p=new JPanel();
BoxLayout bl=new BoxLayout(p,BoxLayout.PAGE_AXIS);
p.setLayout(bl);
p.add(f1,BorderLayout.CENTER);
p.add(f2,BorderLayout.CENTER);
dlgPane.add(p,BorderLayout.CENTER);
labels.align();
JButton cancel=new JButton(_tr._("cancel"));cancel.addActionListener(this);
JButton ok=new JButton(_tr._("Ok"));ok.addActionListener(this);ok.setDefaultCapable(true);
this.getRootPane().setDefaultButton(ok);
JPanel buttons=new JPanel();
FlowLayout fll=new FlowLayout(FlowLayout.RIGHT);
buttons.setLayout(fll);
buttons.add(cancel);
buttons.add(ok);
dlgPane.add(buttons,BorderLayout.SOUTH);
this.add(dlgPane);
this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
}
}