/** * 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"); } }