/**
* 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.
*/
/**
* Editor for all information about the article, such as autor(s), language,
* keywords, etc.
*
* @see org.pegadi.artis.Artis
* @see org.pegadi.model.Article
* @author HÃ¥vard Wigtil <havardw at pvv.org>
* @version $Revision$, $Date$
*/
package org.pegadi.artis;
import no.dusken.common.model.Person;
import org.pegadi.model.LoginContext;
import org.pegadi.swing.PersonChooser;
import org.pegadi.util.XMLUtil;
import org.w3c.dom.*;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Vector;
public class MetaEditor extends Editor {
public static final String AUTHORGROUP_TAG = "authorgroup";
public static final String KEYWORDS_TAG = "keywords";
/** The panel that holds the author editing component. */
JPanel authorEdit;
/** The panel that holds the PersonPanes for the authors. */
JPanel innerAuthorPanel;
/** The panel that holds the keyword edit. */
JPanel keywordPanel;
JButton addAuthor;
JButton removeAuthorButton;
JTextField keywordField;
/** Holds all PersonChooser / remove button panels. */
Vector authorPanels;
ResourceBundle metaStr;
public MetaEditor(Element xml, Artis artis) {
super(xml, artis);
}
protected void createUI(Locale loc) {
super.createUI(loc);
this.setLayout(new BorderLayout());
metaStr = ResourceBundle.getBundle("org.pegadi.artis.MetaStrings", loc);
// This panel holds all author-related components
authorEdit = new JPanel();
authorEdit.setBorder(new TitledBorder(metaStr.getString("author_comp")));
authorEdit.setLayout(new BorderLayout());
// This holds the author panes
innerAuthorPanel = new JPanel();
innerAuthorPanel.setLayout(new GridBagLayout());
// Add all editors in a scrollpane
JScrollPane sp = new JScrollPane(innerAuthorPanel,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
authorEdit.add(sp, BorderLayout.CENTER);
addAuthor = new JButton(metaStr.getString("add_author"));
addAuthor.setIcon(new ImageIcon(getClass().getResource(metaStr.getString("add_author_icon"))));
JPanel addPanel = new JPanel();
addPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
addPanel.add(addAuthor);
authorEdit.add(addPanel, BorderLayout.SOUTH);
this.add(authorEdit, BorderLayout.CENTER);
addAuthor.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
addAuthorPanel(null);
}
});
keywordPanel = new JPanel();
keywordField = new JTextField();
keywordField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
fireTextChanged();
}
public void removeUpdate(DocumentEvent e) {
fireTextChanged();
}
public void changedUpdate(DocumentEvent e) {}
});
Border b = BorderFactory.createTitledBorder(metaStr.getString("keyword_comp"));
keywordPanel.setBorder(b);
keywordPanel.setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.fill = GridBagConstraints.HORIZONTAL;
gc.weightx = 1.0;
keywordPanel.add(keywordField, gc);
this.add(keywordPanel, BorderLayout.SOUTH);
}
public synchronized void updateXML() {
if (mElement == null) {
return;
}
Document doc = mElement.getOwnerDocument();
// Remove all old nodes from root XML element.
while (mElement.getChildNodes().getLength() > 0) {
mElement.removeChild(mElement.getFirstChild());
}
// update authors
if (authorPanels.size() > 0) {
Element authors = doc.createElement(AUTHORGROUP_TAG);
for (int i = 0; i < authorPanels.size(); i++) {
Container c = (Container)authorPanels.elementAt(i);
PersonChooser pc = (PersonChooser)c.getComponent(0);
Person u = pc.getSelectedUser();
if (u != null) {
authors.appendChild(XMLUtil.user2xml(u, doc));
}
else {
log.warn("User from PersonChooser was NULL, skipping...");
}
}
mElement.appendChild(authors);
}
// update keywords
String keywords = keywordField.getText().trim();
if (keywords.length() > 0) {
Element key = doc.createElement(KEYWORDS_TAG);
key.appendChild(doc.createTextNode(keywords));
mElement.appendChild(key);
}
}
/**
* Returns the text length of this editor. Authors and keywords don't count,
* so this method will always return <code>0</code>.
*
* @return The length
*/
public int getLength() {
return 0;
}
/**
* Returns an icon representing this editor.
*
* @return The icon.
* @see org.pegadi.artis.Editor#getDisplayIcon()
*/
public ImageIcon getDisplayIcon() {
return new ImageIcon(getClass().getResource(metaStr.getString("icon_meta")));
}
public void setXML(Element xml) {
mElement = xml;
NodeList agl = xml.getElementsByTagName(AUTHORGROUP_TAG);
authorPanels = new Vector();
if (agl.getLength() == 1) {
NodeList al = agl.item(0).getChildNodes();
for (int i = 0; i < al.getLength(); i++) {
if (al.item(i) instanceof Element &&
((Element)al.item(i)).getTagName().equals("person")) {
addAuthorPanel((Element)al.item(i));
}
else {
log.warn("{} is not a <person> element.", al.item(i).toString());
}
}
}
else {
log.warn("authorgroup count is {}, expected 1", agl.getLength());
}
// Keywords
NodeList kl = xml.getElementsByTagName(KEYWORDS_TAG);
keywordField.setText("");
if (kl.getLength() > 0) {
NodeList n = kl.item(0).getChildNodes();
for (int i = 0; i < n.getLength(); i++) {
if (n.item(i) instanceof Text) {
try {
String s = n.item(i).getNodeValue();
keywordField.setText(keywordField.getText() + s);
} catch (DOMException e) {
log.error("Error getting text from keyword node", e);
}
}
}
}
}
/**
* Try to isolate all the ugliness in one place.
*
* @param author A <person> tag, or <code>null</code> for an empty pane.
*/
protected void addAuthorPanel(Element author) {
JPanel l = new JPanel(new FlowLayout(FlowLayout.LEFT));
PersonChooser pc;
pc = new PersonChooser(PersonChooser.JOURNALISTS);
pc.addExternalOption();
if (author != null) {
Person tmp = XMLUtil.xml2user(author);
Person u;
log.debug("User from XML is {}, ID is {}", tmp.getName(), tmp.getId());
if (tmp.getId() == null) {
// External person
u = tmp;
}
else {
try {
u = LoginContext.server.getUser(tmp.getUsername(), LoginContext.sessionKey);
} catch (Exception e) {
log.error("Can't get user with ID " + tmp.getId(), e);
u = tmp;
}
}
pc.setSelectedUser(u);
}
pc.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
setChanged();
fireTextChanged();
}
});
removeAuthorButton = new JButton(metaStr.getString("remove_label"));
removeAuthorButton.setMargin(new Insets(0,10,0,10));
removeAuthorButton.setIcon(new ImageIcon(getClass().getResource(metaStr.getString("icon_remove"))));
removeAuthorButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
removeAuthorPanel(e);
}
});
l.add(pc);
l.add(removeAuthorButton);
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridwidth=GridBagConstraints.REMAINDER;
constraints.gridheight=1;
constraints.fill=GridBagConstraints.NONE;
constraints.anchor=GridBagConstraints.NORTHWEST;
constraints.ipadx=10;
innerAuthorPanel.add(l,constraints);
authorPanels.addElement(l);
this.validate();
setChanged(true);
}
// Tell the editor that a person is changed
public void setChanged() {
setChanged(true);
}
/**
* Called when a PersonPane is in the process of removing itself.
*
* @param e The event signalling removal.
*/
protected void removeAuthorPanel(ActionEvent e) {
Component b = (Component)e.getSource();
Container p = b.getParent();
if(authorPanels.size() == 1)
return;
if (authorPanels.removeElement(p)) {
innerAuthorPanel.remove(p);
fireTextChanged();
innerAuthorPanel.repaint();
}
else {
log.error("Container not found in panel list: {}", p);
}
this.validate();
setChanged(true);
}
/**
* Returns the menu spesific to this componenet. This method returns
* <code>null</code>, as this component has no menu.
*/
public JMenu getMenu() {
return null;
}
protected void cutPerformed(ActionEvent parm1) {
//TODO: implement this pegadi.artis.Editor abstract method
}
protected void pastePerformed(ActionEvent parm1) {
//TODO: implement this pegadi.artis.Editor abstract method
}
protected void copyPerformed(ActionEvent parm1) {
//TODO: implement this pegadi.artis.Editor abstract method
}
public Action getInsertAction() {
return null;
}
public String getDisplayName() {
return metaStr.getString("display_name");
}
}