/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.fib.view.widget;
import java.awt.BorderLayout;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import org.openflexo.antar.binding.AbstractBinding;
import org.openflexo.fib.controller.FIBController;
import org.openflexo.fib.model.FIBEditorPane;
import org.openflexo.fib.view.FIBWidgetView;
import org.openflexo.toolbox.ToolBox;
/**
* Represents a widget able to edit a Text (more than one line) object
*
* @author bmangez,sguerin
*/
public class FIBEditorPaneWidget extends FIBWidgetView<FIBEditorPane, JEditorPane, String> {
private static final Logger logger = Logger.getLogger(FIBEditorPaneWidget.class.getPackage().getName());
private JPanel panel;
private final JEditorPane editorPane;
private JScrollPane scrollPane;
boolean validateOnReturn;
public FIBEditorPaneWidget(FIBEditorPane model, FIBController controller) {
super(model, controller);
editorPane = new JEditorPane();
panel = new JPanel(new BorderLayout());
panel.setOpaque(false);
panel.add(editorPane, BorderLayout.CENTER);
validateOnReturn = model.isValidateOnReturn();
Border border;
if (!ToolBox.isMacOSLaf()) {
border = BorderFactory.createEmptyBorder(TOP_COMPENSATING_BORDER, LEFT_COMPENSATING_BORDER, BOTTOM_COMPENSATING_BORDER,
RIGHT_COMPENSATING_BORDER);
} else {
border = BorderFactory.createEmptyBorder(2, 3, 2, 3);
}
panel.setBorder(border);
editorPane.setEditable(!isReadOnly());
if (model.getText() != null) {
editorPane.setText(model.getText());
}
editorPane.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
if (!validateOnReturn && !widgetUpdating) {
updateModelFromWidget();
}
}
@Override
public void insertUpdate(DocumentEvent e) {
if (!validateOnReturn && !widgetUpdating) {
updateModelFromWidget();
}
}
@Override
public void removeUpdate(DocumentEvent e) {
if (!validateOnReturn && !widgetUpdating) {
updateModelFromWidget();
}
}
});
editorPane.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
updateModelFromWidget();
}
}
});
updateContentType();
editorPane.addFocusListener(this);
editorPane.setAutoscrolls(true);
editorPane.setEnabled(true);
updateFont();
}
protected void updateContentType() {
if (getComponent().getContentType() != null) {
editorPane.setContentType(getComponent().getContentType().getContentType());
} else {
editorPane.setContentType("text/html");
}
}
@Override
public List<AbstractBinding> getDependencyBindings() {
List<AbstractBinding> returned = super.getDependencyBindings();
appendToDependingObjects(getWidget().getEditable(), returned);
return returned;
}
@Override
public void focusGained(FocusEvent event) {
super.focusGained(event);
editorPane.selectAll();
}
@Override
public void updateDataObject(final Object dataObject) {
if (!SwingUtilities.isEventDispatchThread()) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Update data object invoked outside the EDT!!! please investigate and make sure this is no longer the case. \n\tThis is a very SERIOUS problem! Do not let this pass.");
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
updateDataObject(dataObject);
}
});
return;
}
super.updateDataObject(dataObject);
editorPane.setEditable(!isReadOnly());
}
@Override
public synchronized boolean updateWidgetFromModel() {
if (notEquals(getValue(), editorPane.getText())) {
if (modelUpdating) {
return false;
}
if (getValue() != null && (getValue() + "\n").equals(editorPane.getText())) {
return false;
}
widgetUpdating = true;
try {
editorPane.setText(getValue());
updateFont();
} finally {
widgetUpdating = false;
}
return true;
}
return false;
}
/**
* Update the model given the actual state of the widget
*/
@Override
public synchronized boolean updateModelFromWidget() {
if (notEquals(getValue(), editorPane.getText())) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("updateModelFromWidget() in TextAreaWidget");
}
modelUpdating = true;
try {
setValue(editorPane.getText());
} finally {
modelUpdating = false;
}
return true;
}
return false;
}
@Override
public JPanel getJComponent() {
return panel;
}
@Override
public JEditorPane getDynamicJComponent() {
return editorPane;
}
/**
* Return the effective component to be added to swing hierarchy This component may be the same as the one returned by
* {@link #getJComponent()} or a encapsulation in a JScrollPane
*
* @return JComponent
*/
@Override
public JComponent getResultingJComponent() {
if (getComponent().getUseScrollBar()) {
if (scrollPane == null) {
scrollPane = new JScrollPane(editorPane, getComponent().getVerticalScrollbarPolicy().getPolicy(), getComponent()
.getHorizontalScrollbarPolicy().getPolicy());
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
scrollPane.setBorder(BorderFactory.createEmptyBorder());
scrollPane.setViewportBorder(BorderFactory.createEmptyBorder());
}
panel.add(scrollPane);
return panel;
} else {
return getJComponent();
}
}
@Override
public void updateFont() {
super.updateFont();
if (getFont() != null) {
if (editorPane.getDocument() instanceof StyledDocument) {
SimpleAttributeSet sas = new SimpleAttributeSet();
StyleConstants.setFontFamily(sas, getFont().getFamily());
StyleConstants.setFontSize(sas, getFont().getSize());
((StyledDocument) editorPane.getDocument()).setParagraphAttributes(0, editorPane.getDocument().getLength(), sas, false);
}
}
}
}