/**
* Copyright 1999-2009 The Pegadi Team
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This is the main editor for articles. As it is a state-of-the-art
* editor, it will subcontract out most of the work.
* <p>The class will use editors derived from {@link
* pegadi.artis.Editor Editor} to to the editing, Artis' task then is to
* provide a common framework for these editors.
*
* @author Håvard Wigtil <havardw at pvv.org>
* @author Jørgen Binningsbø <jb@underdusken.no>
*/
package org.pegadi.artis;
import com.kitfox.svg.SVGCache;
import com.kitfox.svg.app.beans.SVGIcon;
import no.dusken.common.model.Person;
import org.pegadi.client.ApplicationLauncher;
import org.pegadi.client.ClientContext;
import org.pegadi.maildialog.MailDialog;
import org.pegadi.model.*;
import org.pegadi.publisher.FOPAWTPublisher;
import org.pegadi.publisher.FOPPDFPublisher;
import org.pegadi.publisher.FOPPrintPublisher;
import org.pegadi.server.NoAccessException;
import org.pegadi.xml.PegadiErrorHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.swing.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.text.MessageFormat;
import java.util.*;
import java.util.List;
import java.util.Timer;
public class Artis extends JFrame {
/** All static declarations and functions first * */
public static java.util.Map<Integer, Artis> openArtises = new java.util.HashMap<Integer, Artis>(6);
private static final String PREF_DOMAIN = "artis";
private final Logger log = LoggerFactory.getLogger(getClass());
/**
* Returns true if the article is currently open in Artis.
*
*/
public static boolean isOpen(Article art) {
return openArtises.containsKey(art.getId());
}
public static Artis fetchUniqueArtis(Article art, ArticleLock lock) {
Integer articleid = art.getId();
if (openArtises.containsKey(articleid)) {
return openArtises.get(articleid);
} else {
Artis newArtis = new Artis(lock);
openArtises.put(articleid, newArtis);
newArtis.openArticle(art);
return newArtis;
}
}
Timer autoSaveTimer;
/** List of currently active editors. */
Vector<Editor> editors;
/** Tries to get the article lock */
LockChecker lockChecker;
/** Application properties. Loaded on startup. */
ResourceBundle appProps;
/** Editor properties. Loaded on startup. */
ResourceBundle editorProps;
/** Article properties. Loaded with each article. */
ResourceBundle articleProps;
/** All user-visible strings. */
ResourceBundle strings;
/** Preferences for different settings **/
Properties preferences;
/** The global editor toolbar. */
JToolBar toolBar;
/** Sows status items at the bottom of the window. */
JPanel statusPanel;
/** The label showing the current character count. */
JLabel charCountLabel;
/** int containing the curret text selection count */
int charsSelected;
/** int containing the total number of characters */
int chars;
/** Tabbed pane to hold the left/top editors. */
JTabbedPane leftPane;
/** Tabbed pane to hold the right/bottom editors. */
JTabbedPane rightPane;
/** Split pane to hold leftPane and rightPane */
JSplitPane splitPane;
/** List of menu items for the current editor. */
JMenuItem[] editorMenuItems, editorMenuItems2;
JMenuItem[] characterMenuItems;
JMenuItem[] formatMenuItems;
/** The 'Edit' menu item. */
JMenu editMenu;
JMenu insertMenu;
JMenu characterMenu;
JMenu statusMenu;
JMenu formatMenu;
/** Array of all articlestatuses */
List<ArticleStatus> statuses;
/** The menu spesific to each editor. */
JMenu editorMenu;
/** Action for exiting editor. */
AbstractAction exitAction;
AbstractAction showSettingsAction;
/** Action for saving articles. */
AbstractAction saveAction;
/** Action for printing articles. */
AbstractAction printAction;
/** Action for previewing articles. */
AbstractAction previewAction;
/** Action for generating PDF from articles. */
AbstractAction pdfAction;
/** Action for importing XML files */
AbstractAction importAction;
/** Action for exporting XML files */
AbstractAction exportAction;
/** Action for copying. */
AbstractAction copyAction;
/** Action for pasting. */
AbstractAction pasteAction;
/** Action for pasting. */
AbstractAction cutAction;
/** cut copy paste buttons */
JButton pasteB;
JButton copyB;
JButton cutB;
/** Action for sending article text as mail */
AbstractAction sendMailAction;
/** The article the editor is editing. */
Article article;
private String xmlpath;
/** When the lock was first created */
long firstLockTime = -1;
boolean canEditArticle = true;
EasterGlassPane easter = new EasterGlassPane();
public void dispose() {
super.dispose();
if (this.article != null) {
openArtises.remove(article.getId());
}
}
public Artis() {
super();
strings = ResourceBundle.getBundle("org.pegadi.artis.ArtisStrings");
appProps = ResourceBundle.getBundle("org.pegadi.artis.ArtisApp");
editorProps = ResourceBundle
.getBundle("org.pegadi.artis.EditorStrings");
editors = new Vector<Editor>();
loadPreferences();
try {
xmlpath = LoginContext.server.getWebXMLRoot(LoginContext.sessionKey);
} catch (NoAccessException e) {
log.error("Cannot set xmlpath", e);
}
createUI();
}
public Artis(ArticleLock lock) {
this();
firstLockTime = lock.getFirstLocked();
}
/**
* Loads an <code>Article</code> into the editor.
*
* @param art
* The <code>Article</code> to open.
* @return <code>true</code> if the <code>Article</code> was
* successfully opened.
*/
public boolean openArticle(Article art) {
article = art;
String docType;
this.setTitle(art.getName() + " - " + getTitle());
// Update article status combo buttons
for (int i = 0; i < statusMenu.getItemCount(); i++) {
JRadioButtonMenuItem rbmi = (JRadioButtonMenuItem) statusMenu
.getItem(i);
if (art.getArticleStatus().getName().equals(rbmi.getText()))
rbmi.setSelected(true);
else
rbmi.setSelected(false);
}
// if the article haven't got any text yet, we insert a the
// template for this article type.
if (!article.hasText()) {
try {
String template = LoginContext.server.getTemplate(article
.getId(), LoginContext.sessionKey);
if (template != null) {
article.setText(template);
} else {
log.error("Template is NULL, check server log for errors.");
return false;
}
} catch (RemoteException re) {
log.error("Exception while getting template", re);
return false;
}
}
// if validation is active, parse the article with a validating parser
Document doc;
if (ClientContext.includeUnstable &&
article.getArticleType().getName().equals("Nyhetsartikkel")) // @todo: This should check the DOCTYPE of the article, to verify if validation is supported by this article type.
{
// if (false) {
log.debug("Re-parsing article with validation turned on.");
try {
DocumentBuilderFactory vdbf = DocumentBuilderFactory.newInstance();
vdbf.setNamespaceAware(true);
vdbf.setValidating(true);
vdbf.setAttribute(
"http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
// @todo: ouch - another hardcoded location...
String[] schemaSources = {"file:///Users/jb/pegadi/trunk/xml/schema/pegadi.xsd",
"file:///Users/jb/pegadi/trunk/xml/schema/ud1.xsd"};
vdbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", schemaSources);
DocumentBuilder validatingDocBuilder = vdbf.newDocumentBuilder();
PegadiErrorHandler handler = new PegadiErrorHandler();
validatingDocBuilder.setErrorHandler(handler);
doc = validatingDocBuilder.parse(new InputSource(new StringReader(article.getText())));
if (handler.isValidationError() ) {
log.error("Error valiating article.");
return false;
}
} catch (Exception eeee) {
log.error("Error parsing article with validation turned on", eeee);
return false;
}
} else {
// if the article is not yet parsed, then parse it.
if (article.getDocument() == null)
if (!article.parseText())
return false;
doc = article.getDocument();
}
docType = doc.getDocumentElement().getTagName();
String props;
try {
props = appProps.getString(docType);
} catch (MissingResourceException mre) {
log.error("Can't find properties for type {}", docType, mre);
return false;
}
if (props == null) {
log.error("Can't find article properties.");
JOptionPane.showMessageDialog(this, strings
.getString("file_open_error"), strings
.getString("file_property_error"),
JOptionPane.ERROR_MESSAGE);
return false;
}
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
factory.setIgnoringElementContentWhitespace(false);
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException pce) {
log.error("Parser configuration exception", pce);
return false;
}
Document confDoc = null;
try {
confDoc = builder.parse(new InputSource(getClass()
.getResourceAsStream(props)));
} catch (SAXException e) {
log.error("SAXException parsing article", e);
} catch (IOException e) {
log.error("IOException parsing article", e);
}
NodeList left = confDoc.getElementsByTagName("left");
NodeList top = confDoc.getElementsByTagName("top");
if (left.getLength() > 0) {
splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
addEditorsToPane(leftPane, (Element) left.item(0), doc);
NodeList right = confDoc.getElementsByTagName("right");
addEditorsToPane(rightPane, (Element) right.item(0), doc);
} else if (top.getLength() > 0) {
splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
addEditorsToPane(leftPane, (Element) top.item(0), doc);
Element bottom = (Element) confDoc.getElementsByTagName("bottom")
.item(0);
addEditorsToPane(rightPane, bottom, doc);
}
rightPane.setMinimumSize(new Dimension(0, 0));
leftPane.setMinimumSize(new Dimension(790 - 300, 0));
splitPane.setTopComponent(leftPane);
splitPane.setBottomComponent(rightPane);
splitPane.setContinuousLayout(false);
splitPane.setDividerLocation(600);
editorChanged((Editor) leftPane.getSelectedComponent());
updateCharCount(null);
saveAction.setEnabled(true);
return true;
}
/**
* Alternative version of disableAllEditors() made to let you keep text selection and copy in locked article view.
*/
public void disableAllEditors_butKeepOptionsRelevantToTextCopying(){
for(Editor editor : editors) {
editor.disableEditor_butKeepOptionsRelevantToTextCopying();
editor.pasteAction.setEnabled(false);
editor.cutAction.setEnabled(false);
}
saveAction.setEnabled(false);
insertMenu.setEnabled(false);
pasteB.setEnabled(false);
cutB.setEnabled(false);
}
// Called if the article lock is not yours when opening a new article
public void checkForLock() {
canEditArticle = false;
if(lockChecker == null) {
lockChecker = new LockChecker(this);
new Thread(lockChecker).start();
}
else if(!lockChecker.isRunning()) {
lockChecker.setRunCheck(true);
}
}
public void startAutoSaver() {
if(autoSaveTimer != null) {
autoSaveTimer.cancel();
}
Integer savePeriodMinutes;
try {
savePeriodMinutes = Integer.parseInt(preferences.getProperty(ArtisPrefsDialog.AUTO_SAVE_PREF));
} catch(NumberFormatException e) {
log.debug("No preference found for autoSave");
savePeriodMinutes = 10;
}
long savePeriod = (1000 * 60) * savePeriodMinutes;
autoSaveTimer = new Timer();
autoSaveTimer.scheduleAtFixedRate(new AutoSaver(), savePeriod, savePeriod);
}
public void addEditorsToPane(JTabbedPane pane, Element editorList,
Document doc) {
NodeList editorElements = editorList.getElementsByTagName("editor");
for (int i = 0; i < editorElements.getLength(); i++) {
Element editorElement = (Element) editorElements.item(i);
String tagName = editorElement.getAttribute("tag");
long start = System.currentTimeMillis();
NodeList nl = doc.getElementsByTagName(tagName);
Object[] param = new Object[2]; // The parameter for the constructor
param[1] = this;
if (nl.getLength() > 0) {
param[0] = nl.item(0);
} else {
// The element isn't found, so we have to create it.
log.debug("The element '{}' was not found.", tagName);
Element elem = doc.createElement(tagName);
doc.getDocumentElement().appendChild(elem);
param[0] = elem;
}
log.debug("Element: {}", ((Element) param[0]).getTagName());
Editor editor = null;
String className = ((Element) editorElements.item(i))
.getAttribute("class");
try {
Class editorClass = Class.forName(className);
Constructor[] editorConstructors = editorClass
.getConstructors();
// Search for a constructor
for (Constructor editorConstructor : editorConstructors) {
Class[] types = editorConstructor.getParameterTypes();
if (types.length == 2 && types[0] == Element.class
&& types[1] == Artis.class) {
// Found it!
editor = (Editor) editorConstructor
.newInstance(param);
}
}
if (editor == null) {
log.warn("WARNING! No constructor matching spec. found for {}", className);
}
} catch (InvocationTargetException e) {
log.error("InvokationtargetException {}", className, e);
} catch (Exception ex) {
log.error("EXCEPTION creating class {}", className, ex);
}
if (editor != null) {
editor.addEasterListener(new EasterListener() {
public void easterEventHappened() {
runEaster();
}
});
editor.addTextListener(new TextListener() {
public void textValueChanged(TextEvent e) {
updateCharCount(e);
}
});
editor.addCaretListener(new CaretListener() {
public void caretUpdate(CaretEvent e) {
updateCaretSelection(e);
}
});
pane.addTab(editor.getDisplayName(), editor.getDisplayIcon(),
editor);
editors.addElement(editor);
}
}
// While article has more properties
}
/**
* Creates the user interface for the editor.
*/
protected void createUI() {
createActions();
setJMenuBar(createMenu());
setGlassPane(easter);
// toolBar.setFont(new Font("sans-serif", 9, Font.PLAIN));
leftPane = new JTabbedPane(JTabbedPane.TOP);
rightPane = new JTabbedPane(JTabbedPane.TOP);
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setOneTouchExpandable(true);
// splitPane.setContinuousLayout(true);
charCountLabel = new JLabel(strings.getString("status_charcount"));
statusPanel = new JPanel();
FlowLayout statusLayout = new FlowLayout(FlowLayout.LEFT);
statusLayout.setHgap(10);
statusPanel.setLayout(statusLayout);
statusPanel.add(charCountLabel);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(splitPane, BorderLayout.CENTER);
getContentPane().add(statusPanel, BorderLayout.SOUTH);
// Set the frame's icon
ImageIcon icon = new ImageIcon(getClass().getResource(
strings.getString("icon_artis")));
setIconImage(icon.getImage());
setTitle(strings.getString("application_title") + " "
+ ApplicationLauncher.getVersion());
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
exitAction(null);
}
});
leftPane.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
editorChanged((Editor) leftPane.getSelectedComponent());
}
});
splitPane.setDividerLocation(1.0);
}
/**
* Creates the global toolbar for the editor.
*/
protected JToolBar createToolBar() {
JToolBar tb = new JToolBar();
JButton sb = tb.add(saveAction);
sb.setToolTipText(strings.getString("tip_save"));
JButton pb = tb.add(printAction);
pb.setToolTipText(strings.getString("tip_print"));
// Only enable preview and PDF if java.version>1.1
if (!System.getProperty("java.version").startsWith("1.1")) {
JButton pvb = tb.add(previewAction);
pvb.setToolTipText(strings.getString("tip_preview"));
JButton pdfb = tb.add(pdfAction);
pdfb.setToolTipText(strings.getString("tip_pdf"));
}
tb.addSeparator();
if (copyAction != null) {
copyB = tb.add(copyAction);
copyB.setToolTipText(editorProps.getString("tip_copy"));
SVGIcon copyIcon = initSvgIcon(getClass().getResource(strings.getString("icon_copy")));
SVGIcon copyIconDisabled = initSvgIcon(getClass().getResource(strings.getString("icon_copy_disabled")));
copyB.setIcon(copyIcon);
copyB.setIcon(copyIconDisabled);
}
if (pasteAction != null) {
pasteB = tb.add(pasteAction);
pasteB.setToolTipText(editorProps.getString("tip_paste"));
SVGIcon pasteIcon = initSvgIcon(getClass().getResource(strings.getString("icon_paste")));
SVGIcon pasteIconDisabled = initSvgIcon(getClass().getResource(strings.getString("icon_paste_disabled")));
pasteB.setIcon(pasteIcon);
pasteB.setDisabledIcon(pasteIconDisabled);
}
if (cutAction != null) {
cutB = tb.add(cutAction);
cutB.setToolTipText(editorProps.getString("tip_cut"));
SVGIcon cutIcon = initSvgIcon(getClass().getResource(strings.getString("icon_cut")));
SVGIcon cutIconDisabled = initSvgIcon(getClass().getResource(strings.getString("icon_cut_disabled")));
cutB.setIcon(cutIcon);
cutB.setDisabledIcon(cutIconDisabled);
}
tb.addSeparator();
JButton eb = tb.add(exitAction);
eb.setToolTipText(strings.getString("tip_exit"));
return tb;
}
/**
* Creates the global menu for the editor.
*/
protected JMenuBar createMenu() {
JMenuBar menu = new JMenuBar();
JMenu file = new JMenu(strings.getString("menu_file"));
menu.add(file);
JMenuItem saveItem = file.add(saveAction);
saveItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(83,
java.awt.event.KeyEvent.CTRL_MASK, false));
JMenuItem printItem = file.add(printAction);
printItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(80,
java.awt.event.KeyEvent.CTRL_MASK, false));
file.add(sendMailAction);
file.add(showSettingsAction);
file.addSeparator();
file.add(importAction);
file.add(exportAction);
file.addSeparator();
statusMenu = new JMenu(strings.getString("menu_file_save_status"));
SVGIcon statusIcon = initSvgIcon(getClass().getResource(strings.getString("icon_status")));
//statusMenu.setIcon(new ImageIcon(getClass().getResource(
// strings.getString("icon_status"))));
statusMenu.setIcon(statusIcon);
statuses = null;
try {
statuses = LoginContext.server
.getArticleStatuses(LoginContext.sessionKey);
} catch (Exception e) {
JOptionPane.showMessageDialog(this,
"Error fetching article statuses from server.",
"FATAL ERROR", JOptionPane.ERROR_MESSAGE);
}
ButtonGroup statusGroup = new ButtonGroup();
for (ArticleStatus statuse : statuses) {
JRadioButtonMenuItem rbMenuItem = new JRadioButtonMenuItem(
statuse.getName());
rbMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
statusChanged();
}
});
statusGroup.add(rbMenuItem);
statusMenu.add(rbMenuItem);
}
file.add(statusMenu);
file.addSeparator();
JMenuItem exitItem = file.add(exitAction);
exitItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(87,
java.awt.event.KeyEvent.CTRL_MASK, false));
file.add(exitItem);
editMenu = new JMenu(strings.getString("menu_edit"));
menu.add(editMenu);
// FIXME: This menu is empty for the time beeing.
// JMenu show = new JMenu(strings.getString("menu_show"));
// menu.add(show);
insertMenu = new JMenu(strings.getString("menu_insert"));
characterMenu = new JMenu(strings.getString("menu_chars"));
insertMenu.add(characterMenu);
menu.add(insertMenu);
editorMenuItems = new JMenuItem[0];
editorMenuItems2 = new JMenuItem[0];
editorMenu = new JMenu();
editorMenu.setVisible(false);
menu.add(editorMenu);
JMenu help = new JMenu(strings.getString("menu_help"));
// FIXME: Not implemented
// menu.add(help);
help.add(strings.getString("menu_about"));
formatMenu = new JMenu(strings.getString("menu_format"));
menu.add(formatMenu);
return menu;
}
private void showSettingsDialog() {
ArtisPrefsDialog dialog = new ArtisPrefsDialog(this, preferences);
dialog.setVisible(true);
if(dialog.okResult()) {
saveChangedSettings(dialog.getChangedPreferences());
}
}
private void saveChangedSettings(Properties changed) {
Enumeration<?> keys = changed.keys();
while(keys.hasMoreElements()) {
String key = keys.nextElement().toString();
String value = changed.getProperty(key);
log.info("updating pref-key: " + key + "= " + value);
preferences.put(key, value);
try {
LoginContext.server.savePreference(PREF_DOMAIN, key, value, LoginContext.sessionKey);
} catch(Exception e) {
log.error("Unable to save pref: {}={}", new Object[]{key, value, e});
}
if(key.equals(ArtisPrefsDialog.AUTO_SAVE_PREF)) {
startAutoSaver();
}
}
}
private void loadPreferences() {
try {
preferences = LoginContext.server.getPreferences(PREF_DOMAIN, LoginContext.sessionKey);
} catch (Exception e) {
log.error(
"Exception getting preferences for domain " + PREF_DOMAIN, e);
preferences = new Properties();
}
}
public void statusChanged() {
for (int i = 0; i < statusMenu.getItemCount(); i++) {
JRadioButtonMenuItem rbmi = (JRadioButtonMenuItem) statusMenu
.getItem(i);
if (rbmi.isSelected()) {
article.setArticleStatus(statuses.get(i));
}
}
}
public void runEaster() {
easter.go();
}
/**
* Creates an SVGIcon that can be used by the UI.
* @param iconPath the path of the svg file
* @return an SVGIcon
*/
protected SVGIcon initSvgIcon(URL iconPath) {
URI iconURI = SVGCache.getSVGUniverse().loadSVG(iconPath);
SVGIcon icon = new SVGIcon();
icon.setSvgURI(iconURI);
icon.setAntiAlias(true);
icon.setPreferredSize(new Dimension(32,32));
icon.setScaleToFit(true);
return icon;
}
/**
* Creates the actions used by the toolbar and the menu.
*/
protected void createActions() {
SVGIcon settingsIcon = initSvgIcon(getClass().getResource(strings.getString("icon_settings")));
showSettingsAction = new AbstractAction(strings.getString("action_settings"), settingsIcon) {
public void actionPerformed(ActionEvent e) {
showSettingsDialog();
}
};
showSettingsAction.setEnabled(true);
SVGIcon saveIcon = initSvgIcon(getClass().getResource(strings.getString("icon_save")));
saveAction = new AbstractAction(strings.getString("action_save"), saveIcon) {
//new ImageIcon(getClass().getResource(
// strings.getString("icon_save")))) {
public void actionPerformed(ActionEvent e) {
saveAction();
}
};
saveAction.setEnabled(false);
SVGIcon importIcon = initSvgIcon(getClass().getResource(strings.getString("icon_import")));
importAction = new AbstractAction(strings.getString("action_import"), importIcon) {
//new ImageIcon(getClass().getResource(
// strings.getString("icon_import")))) {
public void actionPerformed(ActionEvent e) {
importAction(e);
}
};
SVGIcon exportIcon = initSvgIcon(getClass().getResource(strings.getString("icon_export")));
exportAction = new AbstractAction(strings.getString("action_export"), exportIcon) {
//new ImageIcon(getClass().getResource(
// strings.getString("icon_export")))) {
public void actionPerformed(ActionEvent e) {
exportAction(e);
}
};
SVGIcon printIcon = initSvgIcon(getClass().getResource(strings.getString("icon_print")));
printAction = new AbstractAction(strings.getString("action_print"), printIcon) {
//new ImageIcon(getClass().getResource(
// strings.getString("icon_print")))) {
public void actionPerformed(ActionEvent e) {
printAction(e);
}
};
SVGIcon previewIcon = initSvgIcon(getClass().getResource(strings.getString("icon_preview")));
previewAction = new AbstractAction(strings.getString("action_preview"), previewIcon) {
//new ImageIcon(getClass().getResource(
// strings.getString("icon_preview")))) {
public void actionPerformed(ActionEvent e) {
previewArticleFOP();
}
};
SVGIcon pdfIcon = initSvgIcon(getClass().getResource(strings.getString("icon_pdf")));
pdfAction = new AbstractAction(strings.getString("action_pdf"), pdfIcon) {
//new ImageIcon(getClass().getResource(
// strings.getString("icon_pdf")))) {
public void actionPerformed(ActionEvent e) {
saveArticleAsPDF();
}
};
SVGIcon mailIcon = initSvgIcon(getClass().getResource(strings.getString("icon_sendmail")));
sendMailAction = new AbstractAction(strings.getString("action_sendmail"), mailIcon) {
//new ImageIcon(getClass().getResource(
// strings.getString("icon_sendmail")))) {
public void actionPerformed(ActionEvent e) {
mailArticleText();
}
};
SVGIcon exitIcon = initSvgIcon(getClass().getResource(strings.getString("icon_exit")));
exitAction = new AbstractAction(strings.getString("action_exit"), exitIcon) {
//new ImageIcon(getClass().getResource(
// strings.getString("icon_exit")))) {
public void actionPerformed(ActionEvent e) {
exitAction(e);
}
};
}
/**
* Called when the current tab changes.
*/
protected void editorChanged(Editor ed) {
log.debug("Ed: {}", ed);
if (ed == null) {
log.warn("The new tab is NULL, returning...");
return;
}
// Remove old menu items
editMenu.removeAll();
formatMenu.removeAll();
// Insert new menu items
AbstractAction[] actions = ed.getEditActions();
AbstractAction[] actions2 = ed.getEditActions2();
AbstractAction[] styleActions = ed.getStyleActions();
AbstractAction[] formatActions = ed.getFormatActions();
AbstractAction autoCorrectAction = ed.getAutoCorrectAction();
editorMenuItems = new JMenuItem[actions.length];
editorMenuItems2 = new JMenuItem[actions2.length + 1];
formatMenuItems = new JMenuItem[styleActions.length];
// Add edit actions
for (int i = 0; i < actions.length; i++) {
editorMenuItems[i] = editMenu.add(actions[i]);
editorMenuItems[i].setAccelerator((KeyStroke) actions[i]
.getValue(AbstractAction.ACCELERATOR_KEY));
if (actions[i].getValue(Action.NAME).equals(
editorProps.getString("action_copy"))) {
copyAction = actions[i];
} else if (actions[i].getValue(Action.NAME).equals(
editorProps.getString("action_paste"))) {
pasteAction = actions[i];
} else if (actions[i].getValue(Action.NAME).equals(
editorProps.getString("action_cut"))) {
cutAction = actions[i];
}
}
if (actions2.length != 0) {
editMenu.add(new JSeparator());
for (int i = 0; i < actions2.length; i++) {
editorMenuItems2[i] = editMenu.add(actions2[i]);
editorMenuItems2[i].setAccelerator((KeyStroke) actions2[i]
.getValue(AbstractAction.ACCELERATOR_KEY));
}
}
if (autoCorrectAction != null) {
editMenu.add(new JSeparator());
JCheckBoxMenuItem item = new JCheckBoxMenuItem(autoCorrectAction);
item.setState(((AbstractTextEditor) (ed)).getAutoCorrectionState());
editMenu.add(item);
}
if (formatActions.length != 0) {
formatMenu.setEnabled(true);
for (int i = 0; i < formatActions.length; i++) {
log.debug("fmi: " + i + " " + formatActions[i]);
formatMenuItems[i] = formatMenu.add(formatActions[i]);
// formatMenuItems[i].setAccelerator((KeyStroke)styleActions[i].getValue(AbstractAction.ACCELERATOR_KEY));
}
} else {
formatMenu.setEnabled(false);
}
// Add style actions
if (styleActions.length != 0) {
formatMenu.add(new JSeparator());
for (int i = 0; i < styleActions.length; ++i) {
formatMenuItems[i] = formatMenu.add(styleActions[i]);
formatMenuItems[i].setAccelerator((KeyStroke) styleActions[i]
.getValue(AbstractAction.ACCELERATOR_KEY));
}
}
if (characterMenuItems == null) {
AbstractAction[] specialChars = ed.getCharacterActions();
characterMenuItems = new JMenuItem[specialChars.length];
for (int i = 0; i < specialChars.length; i++) {
characterMenuItems[i] = characterMenu.add(specialChars[i]);
characterMenuItems[i]
.setAccelerator((KeyStroke) specialChars[i]
.getValue(AbstractAction.ACCELERATOR_KEY));
}
}
if (toolBar != null)
getContentPane().remove(toolBar);
toolBar = createToolBar();
getContentPane().add(toolBar, BorderLayout.NORTH);
validate(); // Needed or the toolbar becomes inaccessible until window
// is resized.
}
public void mailArticleText() {
mailArticleText("");
}
public void mailArticleText(String to) {
String articleText, fullName, emailAddress;
articleText = "";
fullName = "";
emailAddress = "";
for (int i = 0; i < editors.size(); i++) {
if (editors.elementAt(i) instanceof AbstractTextEditor) {
articleText = ((AbstractTextEditor) editors.elementAt(i)).getText();
articleText = articleText.replace('\u2013', '-'); // Dash
articleText = articleText.replace('\u2022', '*'); // Bullet
break;
}
}
try {
Person u = LoginContext.server
.getSessionUser(LoginContext.sessionKey);
fullName = u.getName();
emailAddress = u.getEmailAddress();
} catch (RemoteException e) {
log.error("Could not get user data from server", e);
}
String url;
try {
url = LoginContext.server.getWebXMLRoot(LoginContext.sessionKey);
url += "/templates/articlemail.template";
} catch (RemoteException e) {
log.error("Error getting mailtemplate from server", e);
return;
}
Object[] replaceWith = { fullName, emailAddress, articleText, to };
MailDialog dialog = new MailDialog(this, "", false);
dialog.loadTemplate(url, replaceWith);
dialog.setFromFieldEditable(false);
dialog.setToFieldEditable(true);
dialog.setToLabelActive(true);
dialog.pack();
dialog.setVisible(true);
}
private void handleException(Exception e){
log.error("Error during transformation.", e);
if (e instanceof IOException) {
JOptionPane.showMessageDialog(this, strings.getString("transform_error_save"), strings.getString("transform_error_save_captition"), JOptionPane.ERROR_MESSAGE);
}else {
JOptionPane.showMessageDialog(this, strings.getString("transform_error_general"), strings.getString("transform_error_captition"), JOptionPane.ERROR_MESSAGE);
}
}
public void saveArticleAsPDF() {
setCursor(new Cursor(Cursor.WAIT_CURSOR));
Properties p = getPrintProperties();
JFileChooser chooser = new JFileChooser();
chooser.setSelectedFile(new File(article.suggestFileName(16) +".pdf"));
File file;
int returnVal = chooser.showSaveDialog(this);
if(returnVal == JFileChooser.APPROVE_OPTION) {
file = chooser.getSelectedFile();
}
else{
return;
}
if (p == null) {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
return;
}
updateXML();
FOPPDFPublisher pdf = new FOPPDFPublisher();
pdf.setTransformerProperties(p);
try {
pdf.publish(article, file, PublishingMediaEnum.PDF);
} catch (Exception e) {
handleException(e);
}
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
public void previewArticleFOP() {
setCursor(new Cursor(Cursor.WAIT_CURSOR));
Properties p = getPrintProperties();
if (p == null) {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
return;
}
updateXML();
FOPAWTPublisher fpp = new FOPAWTPublisher();
fpp.setTransformerProperties(p);
try {
fpp.publish(article, null, PublishingMediaEnum.PDF);
} catch (Exception e) {
handleException(e);
}
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
public void printArticleFOP() {
setCursor(new Cursor(Cursor.WAIT_CURSOR));
FOPPrintPublisher fpp = new FOPPrintPublisher();
Properties p = getPrintProperties();
if (p == null) {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
return;
}
updateXML();
fpp.setTransformerProperties(p);
try {
fpp.publish(article, null, PublishingMediaEnum.PDF);
} catch (Exception e) {
handleException(e);
}
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
public Properties getPrintProperties() {
PrintDialog printDialog = new PrintDialog(this, strings);
printDialog.pack();
printDialog.setVisible(true);
if (!printDialog.wasAccepted()) // Was cancel pressed?
return null;
return printDialog.getPrintProperties();
}
/**
* Called when "print" is selected from the toolbar or the menu.
*
* @param e
* The action that triggered this event.
*/
protected void printAction(ActionEvent e) {
if (article.getDocument() == null)
article.parseText();
printArticleFOP();
}
public void updateXML() {
for(Editor editor : editors) {
editor.updateXML();
}
}
/**
* Called when "import" is selected for the toolbar menu
*
* @param e
* The action that triggered this event.
*/
protected void importAction(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
int returnVal = chooser.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
// FIXME: Due to trouble when fetching text only and not
// notes, the option to not import notes have temporarily
// been disabled (handegar)
boolean importNotes = true;
// Ask user if notes should be imported as well.
/*
* boolean importNotes = false; int answer =
* JOptionPane.showConfirmDialog(this,
* strings.getString("import_elements_query"),
* strings.getString("action_import"),JOptionPane.YES_NO_OPTION);
* if(answer == JOptionPane.YES_OPTION) importNotes = true;
*/
// Start file loading
setCursor(new Cursor(Cursor.WAIT_CURSOR));
File file;
file = chooser.getSelectedFile();
if (!file.exists()) {
log.error("Could not find specified file '"
+ chooser.getSelectedFile().getName() + "'");
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog(this, strings
.getString("import_filenotfound"));
return;
}
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = null;
try {
factory.setIgnoringElementContentWhitespace(false);
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException pce) {
log.error("Parser configuration exception", pce);
}
FileInputStream stringReader;
try {
stringReader = new FileInputStream(file);
} catch (FileNotFoundException ex) {
log.error("Could not find specified file", ex);
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog(this, strings
.getString("import_filenotfound"));
return;
}
Document importDoc;
try {
importDoc = builder.parse(new InputSource(stringReader));
} catch (SAXException se) {
log.error("couldn't parse text", se);
return;
} catch (java.io.IOException ioe) {
log.error("io-exc", ioe);
return;
}
NotesEditor notesEditor = null;
// Lookup the notes editor
for (int i = 0; i < editors.size(); i++) {
Object ed = editors.elementAt(i);
if (ed instanceof NotesEditor) {
notesEditor = (NotesEditor) ed;
break;
}
}
if (notesEditor == null)
return;
notesEditor.closeAllNotes();
// === Process new XML content
Element notesElem;
NodeList notesElements = importDoc.getDocumentElement()
.getElementsByTagName("notes");
if (notesElements.getLength() != 0) {
notesElem = (Element) notesElements.item(0);
} else { // Create the notes element
notesElem = article.getDocument().createElement("notes");
article.getDocument().getDocumentElement().appendChild(
notesElem);
}
NodeList nodelist = importDoc.getDocumentElement()
.getElementsByTagName("text");
if (nodelist.getLength() != 0) {
Element xmlElem = (Element) nodelist.item(0);
for (int i = 0; i < editors.size(); i++) {
if (editors.elementAt(i).getClass() == AbstractTextEditor.class) {
editors.elementAt(i).setXML(xmlElem);
}
// Only add XML for notes if user agree
if (editors.elementAt(i).getClass() == NotesEditor.class) {
editors.elementAt(i).setXML(notesElem);
}
}
} else {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog(this, strings
.getString("import_failed")); // Failure
return;
}
// FIXME: This does not separate notes and text. Must be
// changed later (handegar)
article.setDoc(importDoc);
updateCharCount(null);
for (int i = 0; i < editors.size(); i++)
editors.elementAt(i).setChanged(true);
updateXML();
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
/**
* Called when "export" is selected for the toolbar menu
*
* @param e
* The action that triggered this event.
*/
public void exportAction(ActionEvent e) {
// Giving 'null' as argument forcing a FileDialog to be created.
updateXML();
try {
fileSave(null);
} catch (IOException ex) {
JOptionPane.showMessageDialog(this, strings
.getString("export_failed")); // Failure
log.error("Cannot export article", ex);
}
}
/**
* Return the article that is open in this Artis
*/
public Article getArticle() {
return article;
}
/**
* Called when "save" is selected from the toolbar or the menu.
*
*/
protected void saveAction() {
this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
ArticleLock lock = null;
try {
lock = LoginContext.server.getArticleLock(article.getId(), false,
LoginContext.sessionKey);
} catch (RemoteException rme) {
log.error("Error getting article lock", rme);
}
if (firstLockTime == lock.getFirstLocked()) {
article.setLastSaved(new Date());
updateXML();
for (int i = 0; i < editors.size(); i++) {
editors.elementAt(i).setChanged(false);
}
try {
article.serialize();
LoginContext.server.ping();
LoginContext.server.saveArticle((Article) article.clone(),
LoginContext.sessionKey);
LoginContext.server.saveArticleText(article.getId(), article
.getText(), article.getCurrentNumberOfCharacters(),
LoginContext.sessionKey);
} catch (Exception rme) {
log.error("Error saving to database", rme);
// Prompt for file save
int fileSave;
fileSave = JOptionPane.showConfirmDialog(this, strings
.getString("server_save_error"), strings
.getString("server_error"), JOptionPane.YES_NO_OPTION,
JOptionPane.ERROR_MESSAGE);
if (fileSave == JOptionPane.YES_OPTION) {
// Try to save to file
try {
fileSave(article.suggestFileName(20) + ".xml");
} catch (IOException ioe) {
this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
log.error("ERROR saving article!", ioe);
JOptionPane.showMessageDialog(this, strings
.getString("file_save_error"), strings
.getString("file_error"),
JOptionPane.ERROR_MESSAGE);
}
}
}
log.info("Article saved.");
this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
} else {
// Fetched lock was not original lock! We will NOT save!
String hostname;
try {
InetAddress address = InetAddress.getByName(lock.getHost());
hostname = address.getHostName();
} catch (UnknownHostException ex) {
hostname = lock.getHost();
}
String rawmessage = strings.getString("locked_error_long");
Object[] args = { hostname };
String message = MessageFormat.format(rawmessage, args);
int fileSave;
fileSave = JOptionPane.showConfirmDialog(this, message, strings
.getString("locked_error"), JOptionPane.YES_NO_OPTION,
JOptionPane.ERROR_MESSAGE);
if (fileSave == JOptionPane.YES_OPTION) {
// Try to save to file
try {
fileSave(null);
} catch (IOException ioe) {
this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
log.error("ERROR saving article!", ioe);
JOptionPane
.showMessageDialog(this, strings
.getString("file_save_error"), strings
.getString("file_error"),
JOptionPane.ERROR_MESSAGE);
}
}
this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
/**
* Saves this article to a file. If filename is <code>null</code> the user
* will be presented with a filedialog.
*
* @return <code>true</code> if the saving was successfull.
* @throws IOException
* Any error during file handling.
*/
protected boolean fileSave(String fileName) throws IOException {
if (fileName == null) {
fileName = getFileName();
if (fileName == null) {
return false;
}
}
FileOutputStream fos;
try {
log.info("Saving file to: " + fileName);
fos = new FileOutputStream(fileName);
} catch (FileNotFoundException fnfe) {
log.error("File not found (illegal file name?)");
return false;
}
try {
Transformer t = TransformerFactory.newInstance().newTransformer();
t.transform(new DOMSource(article.getDocument()), new StreamResult(
fos));
} catch (TransformerException e) {
log.error("Error transforming article", e);
}
return true;
}
/**
* Called to get a possibly new file name for an article.
*
* @return A file name, or <code>null</code> if the user pressed cancel in
* the file dialog.
*/
protected String getFileName() {
JFileChooser chooser = new JFileChooser();
int returnVal = chooser.showSaveDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
return file.getAbsolutePath();
} else {
return null;
}
}
/**
* Called when "exit" is selected from the toolbar or the menu.
*
* @param e
* The event for the action.
*/
protected void exitAction(ActionEvent e) {
if(autoSaveTimer != null)
autoSaveTimer.cancel();
boolean articleChanged = false;
for (int i = 0; i < editors.size(); ++i) {
Editor ed = editors.elementAt(i);
if (ed.isChanged())
articleChanged = true;
}
if(lockChecker != null && lockChecker.isRunning()) {
lockChecker.setRunCheck(false);
articleChanged = false; // There should never be any changes in preview mode, but just is case..
}
if (articleChanged) {
int save = JOptionPane.showConfirmDialog(this, strings
.getString("confirm_exit_save"), strings
.getString("confirm_exit"),
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (save == JOptionPane.NO_OPTION) {
// Set document to null to ensure unsaved changes are not cached
article.setDoc(null);
try {
LoginContext.server.releaseArticleLock(article.getId(),
LoginContext.sessionKey);
} catch (RemoteException rex) {
log.error("Cannot release article lock", rex);
}
dispose();
} else if (save == JOptionPane.YES_OPTION) {
saveAction();
try {
LoginContext.server.releaseArticleLock(article.getId(),
LoginContext.sessionKey);
} catch (RemoteException rex) {
log.error("Error releasing article lock", rex);
}
dispose();
}
} else {
try {
LoginContext.server.releaseArticleLock(article.getId(),
LoginContext.sessionKey);
} catch (RemoteException rex) {
log.error("Error releasing article lock", rex);
}
dispose();
}
}
/**
* Updates the character count status display. This method is called when
* the text in one of the editors change.
*
* @param e
* The event from the editor.
*/
protected void updateCharCount(TextEvent e) {
chars = 0;
for (int i = 0; i < editors.size(); i++) {
chars += editors.elementAt(i).getLength();
}
article.setCurrentNumberOfCharacters(chars);
updateCharCountLabel();
}
protected void updateCharCountLabel() {
String text = strings.getString("status_charcount") + " " + chars;
if (charsSelected > 0)
text = text + " (" + charsSelected + ")";
charCountLabel.setText(text);
}
protected void updateCaretSelection(CaretEvent e) {
int dot = e.getDot();
int mark = e.getMark();
charsSelected = Math.abs(dot - mark);
updateCharCountLabel();
}
public static class PrintDialog extends JDialog {
JFrame frame;
ResourceBundle strings;
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints constraints = new GridBagConstraints();
Container container = this.getContentPane();
boolean accepted = false;
JCheckBox[] checkBox = new JCheckBox[3];
public PrintDialog(JFrame frame, ResourceBundle strings) {
super(frame, strings.getString("print_dialog_title"), true);
this.strings = strings;
createUI();
// FIXME: this breaks JVM 1.1 support. bjorsnos
// setLocationRelativeTo(frame);
Point p = frame.getLocation();
this.setLocation(p.x + 50, p.y + 50);
}
private void createUI() {
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
checkBox[0] = new JCheckBox();
checkBox[1] = new JCheckBox();
checkBox[2] = new JCheckBox();
checkBox[0].setText(strings.getString("print_element_article"));
checkBox[0].setSelected(true);
checkBox[1].setText(strings.getString("print_element_notes"));
checkBox[2].setText(strings.getString("print_element_storysketch"));
JButton okButton = new JButton(strings.getString("button_ok"));
JButton cancelButton = new JButton(strings
.getString("button_cancel"));
container.setLayout(gridbag);
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.insets = new Insets(5, 5, 0, 5);
add(checkBox[0], 0, 0, 0);
add(checkBox[1], 0, 1, 1);
add(checkBox[2], 0, 2, 1);
constraints.insets = new Insets(5, 5, 5, 5);
constraints.anchor = GridBagConstraints.WEST;
add(okButton, 0, 3, 0);
constraints.anchor = GridBagConstraints.EAST;
add(cancelButton, 1, 3, 0);
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
okPerformed();
}
});
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cancelPerformed();
}
});
}
private void add(Component component, int x, int y, int weight) {
constraints.gridx = x;
constraints.gridy = y;
constraints.weightx = weight;
gridbag.setConstraints(component, constraints);
container.add(component);
}
private void cancelPerformed() {
this.accepted = false;
PrintDialog.this.dispose();
}
private void okPerformed() {
this.accepted = true;
PrintDialog.this.dispose();
}
public boolean wasAccepted() {
return this.accepted;
}
public Properties getPrintProperties() {
Properties p = new Properties();
if (checkBox[0].isSelected())
p.put("printarticle", "true");
if (checkBox[1].isSelected()) {
p.put("printnotes", "true");
}
if (checkBox[2].isSelected()) {
p.put("printstorysketch", "true");
}
return p;
}
}
private class AutoSaver extends TimerTask {
static final long oneMinute = 60 * 1000;
public void run() {
if(System.currentTimeMillis() - article.getLastSaved().getTime() > oneMinute) {
log.info("auto-saving");
saveAction();
}
}
}
public boolean canEditArticle() {
return canEditArticle;
}
private class LockChecker implements Runnable {
private boolean runCheck;
private Artis artis;
public LockChecker(Artis artis) {
this.artis = artis;
}
public void run() {
runCheck = true;
ArticleLock lock = null;
int articleId = article.getId();
try {
lock = LoginContext.server.getArticleLock(articleId , false, LoginContext.sessionKey);
} catch (RemoteException rme) {
log.error("Could not get lock", rme);
}
boolean sameSessionKey = lock.getSessionKey().equals(LoginContext.sessionKey);
while(!sameSessionKey) {
try {
Thread.sleep(10000); // 10 sec
if(!runCheck) {
return;
}
lock = LoginContext.server.getArticleLock(articleId , false, LoginContext.sessionKey);
sameSessionKey = lock.getSessionKey().equals(LoginContext.sessionKey);
} catch(InterruptedException ie) {
log.error("Interrupted", ie);
return;
} catch(RemoteException rme) {
log.error("ConnectionError", rme);
}
}
log.debug("same session key detected");
artis.requestFocus();
int openNew = JOptionPane.showConfirmDialog(artis,
strings.getString("lock_acquired_long"),
strings.getString("lock_acquired"),
JOptionPane.YES_NO_OPTION);
if(openNew == JOptionPane.NO_OPTION) {
try {
LoginContext.server.releaseArticleLock(article.getId(),
LoginContext.sessionKey);
} catch (RemoteException rex) {
log.error("Cannot release article lock", rex);
}
}
else if(openNew == JOptionPane.YES_OPTION) {
Article fresh;
try {
fresh = LoginContext.server.getArticleByID(article.getId(), LoginContext.sessionKey);
}
catch (Exception e) {
log.error("Could not get article from server!", e);
return;
}
Artis anArtis = new Artis(lock);
anArtis.openArticle(fresh);
anArtis.setSize(new Dimension((int) (getSize().getWidth()), (int) (getSize().getHeight())));
Point location = getLocation();
location.translate(20, 20);
anArtis.setLocation(location);
dispose();
anArtis.startAutoSaver();
anArtis.setVisible(true);
}
}
void setRunCheck(boolean run) {
runCheck = run;
}
boolean isRunning() {
return runCheck;
}
}
}