blob: 90714f9722ade73b7e9f01af26f85de3b5ac45f7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.netbeans.modules.xml.multiview;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import javax.swing.text.PlainDocument;
/**
* The class provides link between editor text component and related data model
* to make easier implementation of item editors
*
* @author pfiala
*/
public class ItemEditorHelper implements Refreshable {
ItemEditorHelper.ItemDocument doc;
/**
* Model of item providing unified interface between text component and item data
*/
public abstract static class ItemEditorModel {
private ItemEditorHelper itemEditorHelper;
/**
* Retrieves edited text from editor component
*
* @return text
*/
public final String getEditorText() {
return itemEditorHelper == null ? null : itemEditorHelper.getEditorText();
}
/**
* Editor component getter
*
* @return editor component
*/
public final JTextComponent getEditorComponent() {
return itemEditorHelper == null ? null : itemEditorHelper.getEditorComponent();
}
/**
* Called by editor helper to retrieve item value from model
*
* @return value of edited item
*/
public abstract String getItemValue();
/**
* Called by the editor helper when finished editing of the text component.
* An implementation can perform validation, update item value by the editor text
* or define behavior in case of fail
*
* @param value a new value of edited item
* @return true - the new value is accepted, false - the new value is invalid
*/
public abstract boolean setItemValue(String value);
/**
* Called by the editor support whenever edited text is changed.
* An implementation can perform immediate validation
* or update of item value in the model
*/
public abstract void documentUpdated();
}
private JTextComponent getEditorComponent() {
return editorComponent;
}
private final JTextComponent editorComponent;
private ItemEditorModel model;
/**
* Creates item editor helper for given text component with default implementation of data model.
*
* @param textComponent editor component
*/
public ItemEditorHelper(final JTextComponent textComponent) {
this(textComponent, null);
}
/**
* Creates item editor helper for given text component using user defined data model.
* Various implementations of model's methods {@link ItemEditorHelper.ItemEditorModel#getItemValue()},
* {@link ItemEditorHelper.ItemEditorModel#setItemValue(String)} and
* {@link ItemEditorHelper.ItemEditorModel#documentUpdated()} can define required behavior of the editor.
*
* @param textComponent editor component
* @param model item data model defining behavior
*/
public ItemEditorHelper(final JTextComponent textComponent, ItemEditorModel model) {
this.editorComponent = textComponent;
doc = new ItemDocument();
setModel(model);
editorComponent.setDocument(doc);
refresh();
}
/**
* Gets item data model of the item editor helper
*
* @return item data model
*/
public ItemEditorModel getModel() {
return model;
}
private void setModel(ItemEditorModel model) {
this.model = model != null ? model : createDefaultModel();
this.model.itemEditorHelper = this;
}
private static ItemEditorModel createDefaultModel() {
return new ItemEditorModel() {
private String value;
public String getItemValue() {
return value;
}
public boolean setItemValue(String value) {
this.value = value;
return true;
}
public void documentUpdated() {
}
};
}
/**
* Updates editor text by item value from model
*/
public void refresh() {
doc.refresh();
}
/**
* Retrieves edited text from editor component
*
* @return text of editor component
*/
public String getEditorText() {
return editorComponent.getText();
}
private class ItemDocument extends PlainDocument {
boolean refreshing = false;
public void remove(int offs, int len) throws BadLocationException {
super.remove(offs, len);
updateModel();
}
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
super.insertString(offs, str, a);
updateModel();
}
private void updateModel() {
if (!refreshing) {
model.documentUpdated();
refresh();
}
}
public void refresh() {
refreshing = true;
try {
String itemValue = model.getItemValue();
String text;
try {
text = getText(0, getLength());
} catch (BadLocationException e) {
text = "";
e.printStackTrace();
}
if (!text.equals(itemValue)) {
try {
super.remove(0, getLength());
} catch (BadLocationException e) {
e.printStackTrace();
}
try {
super.insertString(0, itemValue, null);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
} finally {
refreshing = false;
}
}
}
}