blob: e2539abb1f18581903b2dc2940a82ad84a71246d [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 org.openide.ErrorManager;
import org.openide.text.NbDocument;
import org.openide.util.RequestProcessor;
import javax.swing.*;
import javax.swing.text.AbstractDocument;
import javax.swing.text.StyledDocument;
import javax.swing.text.BadLocationException;
import java.awt.*;
/**
* Utils.java
*
* Created on November 16, 2004, 3:21 PM
* @author mkuchtiak
*/
public class Utils {
private static final int WAIT_FINISHED_TIMEOUT = 10000;
/** This method update document in editor after change in beans hierarchy.
* It takes old document and new document in String.
* To preserve changes outside of root element only root element is replaced.
* To avoid regeneration of whole document in text editor following steps are done:
* 1) compare the begin of both documents (old one and new one)
* - find the first position where both documents differ
* 2) do the same from the ends of documents
* 3) remove old middle part of text (modified part) and insert new one
*
* @param doc original document
* @param newDoc new value of whole document
*/
public static boolean replaceDocument(final StyledDocument doc, final String newDoc) {
if (doc == null) {
return true;
}
Runnable runnable = new Runnable() {
public void run() {
try {
String origDocument = filterEndLines(doc.getText(0, doc.getLength()));
String newDocument = filterEndLines(newDoc);
if (origDocument.equals(newDocument)) {
// no change in document
return;
}
char[] origChars = origDocument.toCharArray();
char[] newcChars = newDocument.toCharArray();
int tailIndex = origChars.length;
int delta = newcChars.length - tailIndex;
int n = delta < 0 ? tailIndex + delta : tailIndex;
int offset;
for (offset = 0; offset < n; offset++) {
if (origChars[offset] != newcChars[offset]) {
break;
}
}
n = delta < 0 ? offset - delta : offset;
for (int i = tailIndex - 1; i >= n; i--) {
if (origChars[i] == newcChars[i + delta]) {
tailIndex = i;
} else {
break;
}
}
String s = newDocument.substring(offset, tailIndex + delta);
int length = tailIndex - offset;
if (doc instanceof AbstractDocument) {
((AbstractDocument) doc).replace(offset, length, s, null);
} else {
if (length > 0) {
doc.remove(offset, length);
}
if (s.length() > 0) {
doc.insertString(offset, s, null);
}
}
} catch (BadLocationException e) {
ErrorManager.getDefault().notify(e);
}
}
};
NbDocument.runAtomic(doc, runnable);
return true;
}
/** Filter characters #13 (CR) from the specified String
* @param str original string
* @return the string without #13 characters
*/
private static String filterEndLines(String str) {
char[] text = str.toCharArray();
if (text.length == 0) {
return "";
}
int pos = 0;
for (int i = 0; i < text.length; i++) {
char c = text[i];
if (c != 13) {
if (pos != i) {
text[pos] = c;
}
pos++;
}
}
return new String(text, 0, pos);
}
/**
* Sets focus to the next focusable component according to focus traversal policy
* @param component currently focused component
*/
public static void focusNextComponent(Component component) {
Container focusCycleRoot = component.getFocusCycleRootAncestor();
if (focusCycleRoot == null) {
return;
}
final FocusTraversalPolicy focusTraversalPolicy = focusCycleRoot.getFocusTraversalPolicy();
if (focusTraversalPolicy == null) {
return;
}
final Component componentAfter = focusTraversalPolicy.getComponentAfter(focusCycleRoot, component);
if (componentAfter != null) {
componentAfter.requestFocus();
}
}
/**
* Scroll panel to make the component visible
* @param component
*/
public static void scrollToVisible(final JComponent component) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
component.scrollRectToVisible(new Rectangle(10, component.getHeight()));
}
});
}
/**
* Make sure that the code will run in AWT dispatch thread
* @param runnable
*/
public static void runInAwtDispatchThread(Runnable runnable) {
if (SwingUtilities.isEventDispatchThread()) {
runnable.run();
} else {
SwingUtilities.invokeLater(runnable);
}
}
/**
* Utility that sets border and traversal keys for JTextArea in JTextField style
*/
public static void makeTextAreaLikeTextField(javax.swing.JTextArea ta, javax.swing.JTextField tf) {
ta.setBorder(tf.getBorder());
ta.setFocusTraversalKeys(java.awt.KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
tf.getFocusTraversalKeys(java.awt.KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
ta.setFocusTraversalKeys(java.awt.KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
tf.getFocusTraversalKeys(java.awt.KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
}
public static void waitFinished(RequestProcessor.Task task) {
if (task.getDelay() > 0 && !task.isFinished()) {
try {
task.waitFinished(WAIT_FINISHED_TIMEOUT);
} catch (InterruptedException e) {
ErrorManager.getDefault().notify(e);
}
}
}
}