/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2005-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2012, Geomatys
*
* This library 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;
* version 2.1 of the License.
*
* This library 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.
*/
package org.geotoolkit.gui.swing.referencing;
import java.util.Locale;
import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import org.jdesktop.swingx.JXLabel;
import org.opengis.util.InternationalString;
import org.opengis.metadata.citation.Citation;
import org.opengis.referencing.IdentifiedObject;
import org.opengis.metadata.Identifier;
import org.geotoolkit.io.X364;
import org.apache.sis.io.wkt.Colors;
import org.geotoolkit.io.wkt.WKTFormat;
import org.geotoolkit.resources.Vocabulary;
import org.apache.sis.io.wkt.Warnings;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.StringBuilders;
/**
* Displays informations about an {@linkplain IdentifiedObject Identified Object}.
* This widget displays the following tabs:
* <p>
* <ul>
* <li>An information tab with the object {@linkplain IdentifiedObject#getName() name} and
* {@linkplain IdentifiedObject#getIdentifiers() identifiers}.</li>
* <li>A <cite>Well Known Text</cite> (WKT) tab.</li>
* </ul>
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @version 3.12
*
* @since 2.3
* @module
*/
@SuppressWarnings("serial")
public class PropertiesSheet extends JComponent {
/**
* The object name, identifier.
*/
private final JTextField name, authority, identifier, type;
/**
* The remarks.
*/
private final JXLabel remarks;
/**
* The <cite>Well Known Text</cite> area.
*/
private final JEditorPane wktArea;
/**
* The formatter to use for formatting WKT objects.
*/
private final WKTFormat formatter;
/**
* Creates a new, initially empty, property sheet.
*/
public PropertiesSheet() {
final Vocabulary resources = Vocabulary.getResources(getLocale());
final JPanel info = new JPanel(new GridBagLayout());
final GridBagConstraints c = new GridBagConstraints();
c.gridy=0; c.fill=GridBagConstraints.HORIZONTAL;
name = addField(info, resources.getLabel(Vocabulary.Keys.Name), c);
authority = addField(info, resources.getLabel(Vocabulary.Keys.Authority), c);
identifier = addField(info, resources.getLabel(Vocabulary.Keys.Identifier), c);
type = addField(info, resources.getLabel(Vocabulary.Keys.Type), c);
info.setBorder(BorderFactory.createTitledBorder(resources.getString(Vocabulary.Keys.Identification)));
info.setOpaque(false);
remarks = new JXLabel();
remarks.setLineWrap(true);
remarks.setVerticalAlignment(JLabel.TOP);
remarks.setBorder(BorderFactory.createEmptyBorder(0, 18, 0, 0));
final Box rem = Box.createVerticalBox();
rem.add(remarks);
rem.setBorder(BorderFactory.createTitledBorder(resources.getString(Vocabulary.Keys.Remarks)));
final JPanel general = new JPanel(new BorderLayout(0, 6));
general.add(info, BorderLayout.BEFORE_FIRST_LINE);
general.add(rem, BorderLayout.CENTER);
general.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
general.setOpaque(false);
/*
* Build the WKT tab.
*/
wktArea = new JEditorPane();
wktArea.setEditable(false);
wktArea.setContentType("text/html");
formatter = new WKTFormat();
formatter.setColors(Colors.DEFAULT);
/*
* Add the tabs.
*/
final JTabbedPane tabs = new JTabbedPane();
tabs.addTab(resources.getString(Vocabulary.Keys.General), general);
tabs.addTab("WKT", new JScrollPane(wktArea));
setLayout(new BorderLayout());
add(tabs, BorderLayout.CENTER);
}
/**
* Adds a field with the given label in front of it.
*/
private static JTextField addField(final JPanel panel, final String text, final GridBagConstraints c) {
final JLabel label = new JLabel(text);
final JTextField value = new JTextField();
value.setEditable(false);
label.setLabelFor(value);
c.gridx=0; c.weightx=0; c.insets.left=18; c.insets.right=3; panel.add(label, c);
c.gridx++; c.weightx=1; c.insets.left= 0; c.insets.right=0; panel.add(value, c);
c.gridy++;
return value;
}
/**
* Gets the name of the GeoAPI interface implemented by the given object, or
* {@code null} if none. This is used for providing a value to {@link #type}.
*/
private static String getTypeName(Class<?> classe) {
while (classe != null) {
for (final Class<?> inter : classe.getInterfaces()) {
if (IdentifiedObject.class.isAssignableFrom(inter)) {
return CharSequences.camelCaseToSentence(inter.getSimpleName()).toString();
}
}
classe = classe.getSuperclass();
}
return null;
}
/**
* Sets the object to display in this property sheet.
*
* @param item The object to display info about.
*/
public void setIdentifiedObject(final IdentifiedObject item) {
final Locale locale = getLocale();
final Identifier oid = item.getName();
name.setText(oid.getCode());
final Citation authorityCitation = oid.getAuthority();
String authorityText = null;
if (authorityCitation != null) {
final InternationalString title = authorityCitation.getTitle();
if (title != null) {
authorityText = title.toString(locale);
}
}
authority.setText(authorityText);
final StringBuilder buffer = new StringBuilder();
for (final Identifier id : item.getIdentifiers()) {
if (buffer.length() != 0) {
buffer.append(", ");
}
final String codespace = id.getCodeSpace();
if (codespace != null) {
buffer.append(codespace).append(':');
}
buffer.append(id.getCode());
}
identifier.setText(buffer.toString());
type.setText(getTypeName(item.getClass()));
InternationalString i18n = item.getRemarks();
remarks.setText(i18n != null ? i18n.toString(locale) : null);
/*
* Set the Well Known Text (WKT) panel using the following steps:
*
* 1) Write the warning if there is one.
* 2) Replace the X3.64 escape sequences by HTML colors.
* 3) Turn quoted WKT names ("foo") in italic characters.
*/
buffer.setLength(0);
buffer.append("<html>");
String text, warning;
try {
text = formatter.format(item);
Warnings w = formatter.getWarnings();
warning = (w != null) ? w.toString() : null;
} catch (RuntimeException e) {
text = String.valueOf(item.getName());
warning = e.getLocalizedMessage();
}
if (warning != null) {
buffer.append("<p><b>").append(Vocabulary.getResources(locale).getString(Vocabulary.Keys.Warning))
.append(":</b> ").append(warning).append("</p><hr>\n");
}
buffer.append("<pre>");
// '\u001A' is the SUBSTITUTE character. We use it as a temporary replacement for avoiding
// confusion between WKT quotes and HTML quotes while we search for text to make italic.
makeItalic(X364.toHTML(text.replace('"', '\u001A')), buffer, '\u001A');
wktArea.setText(buffer.append("</pre></html>").toString());
}
/**
* Copies the given text in the given buffer, while putting the quoted text in italic.
* The quote character is given by the {@code quote} argument and will be replaced by
* the usual {@code "} character.
*/
private static void makeItalic(final String text, final StringBuilder buffer, final char quote) {
boolean isQuoting = false;
int last = 0;
for (int i=text.indexOf(quote); i>=0; i=text.indexOf(quote, last)) {
buffer.append(text, last, i).append(isQuoting ? "</cite>\"" : "\"<cite>");
isQuoting = !isQuoting;
last = i+1;
}
buffer.append(text, last, text.length());
}
/**
* Sets an error message to display instead of the current identified object.
*
* @param message The error message.
*/
public void setErrorMessage(String message) {
name .setText(null);
authority .setText(null);
identifier.setText(null);
type .setText(null);
remarks .setText(null);
final StringBuilder buffer = new StringBuilder(message);
StringBuilders.replace(buffer, "&", "&");
StringBuilders.replace(buffer, "<", "<");
StringBuilders.replace(buffer, ">", ">");
message = buffer.toString();
buffer.setLength(0);
buffer.append("<html><p><b>")
.append(Vocabulary.getResources(getLocale()).getString(Vocabulary.Keys.Error))
.append(":</b> ");
makeItalic(message, buffer, '"');
wktArea.setText(buffer.append("</p></html>").toString());
}
}