X-Git-Url: http://source.jalview.org/gitweb/?p=jalviewjs.git;a=blobdiff_plain;f=site%2Fj2s%2Fswingjs%2Fplaf%2FJSTextUI.java;h=4049f2675ed11df5ea2dd68174c20ec28486c009;hp=2cff1004a8f3207b766eb4be316a7412a2ca66ff;hb=7301a2415adab88038b291fc54caeeb3a5a47a44;hpb=6154cb57a6eac3bb1344b8342495f5bb701ee921 diff --git a/site/j2s/swingjs/plaf/JSTextUI.java b/site/j2s/swingjs/plaf/JSTextUI.java index 2cff100..4049f26 100644 --- a/site/j2s/swingjs/plaf/JSTextUI.java +++ b/site/j2s/swingjs/plaf/JSTextUI.java @@ -1,2795 +1,2795 @@ -/* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code 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 - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package swingjs.plaf; - -import swingjs.JSToolkit; -import swingjs.api.DOMNode; -import swingjs.api.JQueryObject; -import swingjs.api.JSFunction; -import jsjava.awt.Dimension; -import jsjava.awt.Insets; -import jsjava.awt.LayoutManager; -import jsjava.awt.event.ActionEvent; -import jsjavax.swing.AbstractAction; -import jsjavax.swing.Action; -import jsjavax.swing.ActionMap; -import jsjavax.swing.InputMap; -import jsjavax.swing.JComponent; -import jsjavax.swing.SwingUtilities; -import jsjavax.swing.UIManager; -import jsjavax.swing.plaf.ActionMapUIResource; -import jsjavax.swing.plaf.ComponentUI; -import jsjavax.swing.plaf.InputMapUIResource; -import jsjavax.swing.plaf.TextUI; -import jsjavax.swing.plaf.UIResource; -import jsjavax.swing.text.Caret; -import jsjavax.swing.text.DefaultEditorKit; -import jsjavax.swing.text.EditorKit; -import jsjavax.swing.text.JTextComponent; -import jsjavax.swing.text.TextAction; -//import jsjava.awt.KeyboardFocusManager; -//import jsjava.awt.datatransfer.DataFlavor; -//import jsjava.awt.datatransfer.Transferable; -//import jsjava.awt.datatransfer.UnsupportedFlavorException; -//import jsjava.awt.im.InputContext; -//import jsjava.io.IOException; -//import jsjava.io.InputStream; -//import jsjava.io.Reader; -//import jsjava.io.StringBufferInputStream; -//import jsjava.io.StringReader; -//import jsjava.io.StringWriter; -//import jsjavax.swing.plaf.basic.DragRecognitionSupport.BeforeDrag; - -/** - *

- * Basis of a text components look-and-feel. This provides the basic editor view - * and controller services that may be useful when creating a look-and-feel for - * an extension of JTextComponent. - *

- * Most state is held in the associated JTextComponent as bound - * properties, and the UI installs default values for the various properties. - * This default will install something for all of the properties. Typically, a - * LAF implementation will do more however. At a minimum, a LAF would generally - * install key bindings. - *

- * This class also provides some concurrency support if the - * Document associated with the JTextComponent is a subclass of - * AbstractDocument. Access to the View (or View hierarchy) is - * serialized between any thread mutating the model and the Swing event thread - * (which is expected to render, do model/view coordinate translation, etc). - * Any access to the root view should first - * acquire a read-lock on the AbstractDocument and release that lock - * in a finally block. - *

- * An important method to define is the {@link #getPropertyPrefix} method which - * is used as the basis of the keys used to fetch defaults from the UIManager. - * The string should reflect the type of TextUI (eg. TextField, TextArea, etc) - * without the particular LAF part of the name (eg Metal, Motif, etc). - *

- * To build a view of the model, one of the following strategies can be - * employed. - *

    - *
  1. - * One strategy is to simply redefine the ViewFactory interface in the UI. By - * default, this UI itself acts as the factory for View implementations. This is - * useful for simple factories. To do this reimplement the {@link #create} - * method. - *
  2. - * A common strategy for creating more complex types of documents is to have the - * EditorKit implementation return a factory. Since the EditorKit ties all of - * the pieces necessary to maintain a type of document, the factory is typically - * an important part of that and should be produced by the EditorKit - * implementation. - *
- *

- * Warning: Serialized objects of this class will not be - * compatible with future Swing releases. The current serialization support is - * appropriate for short term storage or RMI between applications running the - * same version of Swing. As of 1.4, support for long term storage of all - * JavaBeansTM has been added to the - * java.beans package. Please see {@link jsjava.beans.XMLEncoder}. - * - * @author Timothy Prinzing - * @author Shannon Hickey (drag and drop) - */ -public abstract class JSTextUI extends JSComponentUI {// implements {ViewFactory - // { - @SuppressWarnings("unused") - protected void setFocusable() { - JQueryObject node = $(focusNode); - Object me = this; - - /** - * @j2sNative - * - * node.focus(function() {me.notifyFocus(true)}); - * node.blur(function() {me.notifyFocus(false)}); - */ - {} - } - - - protected String getComponentText() { - return currentText = ((JTextComponent) c).getText(); - } - - protected void bindKeys(DOMNode domNode) { - JSFunction f = null; - JSEventHandler me = this; - if (!((JTextComponent) c).isEditable()) - return; - /** - * @j2sNative - * - * f = function(event) { me.handleJSEvent(me.domNode, 401, event) - * } - */ - { - System.out.println(me); - } - $(domNode).bind("keydown keypress keyup", f); - - // TODO Auto-generated method stub - - } - - /** - * Initializes component properties, e.g. font, foreground, background, caret - * color, selection color, selected text color, disabled text color, and - * border color. The font, foreground, and background properties are only set - * if their current value is either null or a UIResource, other properties are - * set if the current value is null. - * - * @see #uninstallDefaults - * @see #installUI - */ - protected void installDefaults() { - // String prefix = getPropertyPrefix(); - // Font f = editor.getFont(); - // if ((f == null) || (f instanceof UIResource)) { - // editor.setFont(UIManager.getFont(prefix + ".font")); - // } - // - // Color bg = editor.getBackground(); - // if ((bg == null) || (bg instanceof UIResource)) { - // editor.setBackground(UIManager.getColor(prefix + ".background")); - // } - // - // Color fg = editor.getForeground(); - // if ((fg == null) || (fg instanceof UIResource)) { - // editor.setForeground(UIManager.getColor(prefix + ".foreground")); - // } - // - // Color color = editor.getCaretColor(); - // if ((color == null) || (color instanceof UIResource)) { - // editor.setCaretColor(UIManager.getColor(prefix + ".caretForeground")); - // } - // - // Color s = editor.getSelectionColor(); - // if ((s == null) || (s instanceof UIResource)) { - // editor.setSelectionColor(UIManager.getColor(prefix + - // ".selectionBackground")); - // } - // - // Color sfg = editor.getSelectedTextColor(); - // if ((sfg == null) || (sfg instanceof UIResource)) { - // editor.setSelectedTextColor(UIManager.getColor(prefix + - // ".selectionForeground")); - // } - // - // Color dfg = editor.getDisabledTextColor(); - // if ((dfg == null) || (dfg instanceof UIResource)) { - // editor.setDisabledTextColor(UIManager.getColor(prefix + - // ".inactiveForeground")); - // } - // - // Border b = editor.getBorder(); - // if ((b == null) || (b instanceof UIResource)) { - // editor.setBorder(UIManager.getBorder(prefix + ".border")); - // } - // - // Insets margin = editor.getMargin(); - // if (margin == null || margin instanceof UIResource) { - // editor.setMargin(UIManager.getInsets(prefix + ".margin")); - // } - // - // updateCursor(); - } - - private void installDefaults2() { - // editor.addMouseListener(dragListener); - // editor.addMouseMotionListener(dragListener); - // - // String prefix = getPropertyPrefix(); - - Caret caret = editor.getCaret(); - if (caret == null || caret instanceof UIResource) { - editor.setCaret(new JSCaret()); - } - // - // Highlighter highlighter = editor.getHighlighter(); - // if (highlighter == null || highlighter instanceof UIResource) { - // editor.setHighlighter(createHighlighter()); - // } - // - // TransferHandler th = editor.getTransferHandler(); - // if (th == null || th instanceof UIResource) { - // editor.setTransferHandler(getTransferHandler()); - // } - } - - /** - * called by JmolCore.js - * - * @return handled - */ - public boolean handleJSEvent(Object target, int eventType, Object jQueryEvent) { - System.out.println("Handling for " + id + " " + eventType + " " - + jQueryEvent); - return updateHandler.handleJSEvent(this, eventType, jQueryEvent); - } - - /** - * Sets the component properties that haven't been explicitly overridden to - * null. A property is considered overridden if its current value is not a - * UIResource. - * - * @see #installDefaults - * @see #uninstallUI - */ - protected void uninstallDefaults() { - // editor.removeMouseListener(dragListener); - // editor.removeMouseMotionListener(dragListener); - // - if (editor.getCaretColor() instanceof UIResource) { - editor.setCaretColor(null); - } - - if (editor.getSelectionColor() instanceof UIResource) { - editor.setSelectionColor(null); - } - - if (editor.getDisabledTextColor() instanceof UIResource) { - editor.setDisabledTextColor(null); - } - - if (editor.getSelectedTextColor() instanceof UIResource) { - editor.setSelectedTextColor(null); - } - - if (editor.getBorder() instanceof UIResource) { - editor.setBorder(null); - } - - if (editor.getMargin() instanceof UIResource) { - editor.setMargin(null); - } - - // if (editor.getCaret() instanceof UIResource) { - // editor.setCaret(null); - // } - // - // if (editor.getHighlighter() instanceof UIResource) { - // editor.setHighlighter(null); - // } - // - // if (editor.getTransferHandler() instanceof UIResource) { - // editor.setTransferHandler(null); - // } - // - // if (editor.getCursor() instanceof UIResource) { - // editor.setCursor(null); - // } - } - - protected void installKeyboardActions() { - // backward compatibility support... keymaps for the UI - // are now installed in the more friendly input map. - // editor.setKeymap(createKeymap()); - - InputMap km = getInputMap(); - if (km != null) { - SwingUtilities.replaceUIInputMap(editor, JComponent.WHEN_FOCUSED, km); - } - - ActionMap map = getActionMap(); - if (map != null) { - SwingUtilities.replaceUIActionMap(editor, map); - } - - // updateFocusAcceleratorBinding(false); - } - - /** - * Get the InputMap to use for the UI. - */ - InputMap getInputMap() { - InputMap map = new InputMapUIResource(); - - // InputMap shared = - // (InputMap)DefaultLookup.get(editor, this, - // getPropertyPrefix() + ".focusInputMap"); - // if (shared != null) { - // map.setParent(shared); - // } - return map; - } - - // /** - // * Invoked when the focus accelerator changes, this will update the - // * key bindings as necessary. - // */ - // void updateFocusAcceleratorBinding(boolean changed) { - // char accelerator = editor.getFocusAccelerator(); - // - // if (changed || accelerator != '\0') { - // InputMap km = SwingUtilities.getUIInputMap - // (editor, JComponent.WHEN_IN_FOCUSED_WINDOW); - // - // if (km == null && accelerator != '\0') { - // km = new ComponentInputMapUIResource(editor); - // SwingUtilities.replaceUIInputMap(editor, JComponent. - // WHEN_IN_FOCUSED_WINDOW, km); - // ActionMap am = getActionMap(); - // SwingUtilities.replaceUIActionMap(editor, am); - // } - // if (km != null) { - // km.clear(); - // if (accelerator != '\0') { - // km.put(KeyStroke.getKeyStroke(accelerator, - // ActionEvent.ALT_MASK), - // "requestFocus"); - // } - // } - // } - // } - // - // - // /** - // * Invoked when editable property is changed. - // * - // * removing 'TAB' and 'SHIFT-TAB' from traversalKeysSet in case - // * editor is editable - // * adding 'TAB' and 'SHIFT-TAB' to traversalKeysSet in case - // * editor is non editable - // */ - // - // void updateFocusTraversalKeys() { - // /* - // * Fix for 4514331 Non-editable JTextArea and similar - // * should allow Tab to keyboard - accessibility - // */ - // EditorKit editorKit = getEditorKit(editor); - // if ( editorKit != null - // && editorKit instanceof DefaultEditorKit) { - // Set storedForwardTraversalKeys = editor. - // getFocusTraversalKeys(KeyboardFocusManager. - // FORWARD_TRAVERSAL_KEYS); - // Set storedBackwardTraversalKeys = editor. - // getFocusTraversalKeys(KeyboardFocusManager. - // BACKWARD_TRAVERSAL_KEYS); - // Set forwardTraversalKeys = - // new HashSet(storedForwardTraversalKeys); - // Set backwardTraversalKeys = - // new HashSet(storedBackwardTraversalKeys); - // if (editor.isEditable()) { - // forwardTraversalKeys. - // remove(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0)); - // backwardTraversalKeys. - // remove(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, - // InputEvent.SHIFT_MASK)); - // } else { - // forwardTraversalKeys.add(KeyStroke. - // getKeyStroke(KeyEvent.VK_TAB, 0)); - // backwardTraversalKeys. - // add(KeyStroke. - // getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK)); - // } - // LookAndFeel.installProperty(editor, - // "focusTraversalKeysForward", - // forwardTraversalKeys); - // LookAndFeel.installProperty(editor, - // "focusTraversalKeysBackward", - // backwardTraversalKeys); - // } - // - // } - - // /** - // * As needed updates cursor for the target editor. - // */ - // private void updateCursor() { - // if ((! editor.isCursorSet()) - // || editor.getCursor() instanceof UIResource) { - // Cursor cursor = (editor.isEditable()) ? textCursor : null; - // editor.setCursor(cursor); - // } - // } - // - // /** - // * Returns the TransferHandler that will be installed if - // * their isn't one installed on the JTextComponent. - // */ - // TransferHandler getTransferHandler() { - // return defaultTransferHandler; - // } - // - /** - * Fetch an action map to use. - */ - ActionMap getActionMap() { - String mapName = classID + ".actionMap"; - ActionMap map = (ActionMap) UIManager.get(mapName); - if (map == null) { - map = createActionMap(); - if (map != null) { - UIManager.getLookAndFeelDefaults().put(mapName, map); - } - } - return map; - } - // ActionMap componentMap = new ActionMapUIResource(); - // componentMap.put("requestFocus", new FocusAction()); - // /* - // * fix for bug 4515750 - // * JTextField & non-editable JTextArea bind return key - default btn not - // accessible - // * - // * Wrap the return action so that it is only enabled when the - // * component is editable. This allows the default button to be - // * processed when the text component has focus and isn't editable. - // * - // */ - // if (getEditorKit(editor) instanceof DefaultEditorKit) { - // if (map != null) { - // Object obj = map.get(DefaultEditorKit.insertBreakAction); - // if (obj != null - // && obj instanceof DefaultEditorKit.InsertBreakAction) { - // Action action = new TextActionWrapper((TextAction)obj); - // componentMap.put(action.getValue(Action.NAME),action); - // } - // } - // } - // if (map != null) { - // componentMap.setParent(map); - // } - // return componentMap; - // } - // - /** - * Create a default action map. This is basically the set of actions found - * exported by the component. - */ - /** - * @return - */ - ActionMap createActionMap() { - ActionMap map = new ActionMapUIResource(); - Action[] actions = editor.getActions();//defaultKit.getActions(); // SwingJS was editor.getEditorKit().getActions() - // System.out.println("building map for UI: " + getPropertyPrefix()); - int n = actions.length; - for (int i = 0; i < n; i++) { - Action a = actions[i]; - map.put(a.getValue(Action.NAME), a); - // System.out.println(" " + a.getValue(Action.NAME)); - } - // map.put(TransferHandler.getCutAction().getValue(Action.NAME), - // TransferHandler.getCutAction()); - // map.put(TransferHandler.getCopyAction().getValue(Action.NAME), - // TransferHandler.getCopyAction()); - // map.put(TransferHandler.getPasteAction().getValue(Action.NAME), - // TransferHandler.getPasteAction()); - return map; - } - - protected void uninstallKeyboardActions() { - editor.setKeymap(null); - SwingUtilities.replaceUIInputMap(editor, JComponent.WHEN_IN_FOCUSED_WINDOW, - null); - SwingUtilities.replaceUIActionMap(editor, null); - } - - // /** - // * Paints a background for the view. This will only be - // * called if isOpaque() on the associated component is - // * true. The default is to paint the background color - // * of the component. - // * - // * @param g the graphics context - // */ - // protected void paintBackground(Graphics g) { - // g.setColor(editor.getBackground()); - // g.fillRect(0, 0, editor.getWidth(), editor.getHeight()); - // } - // - /** - * Fetches the text component associated with this UI implementation. This - * will be null until the ui has been installed. - * - * @return the editor component - */ - protected final JTextComponent getComponent() { - return editor; - } - - // /** - // * Flags model changes. - // * This is called whenever the model has changed. - // * It is implemented to rebuild the view hierarchy - // * to represent the default root element of the - // * associated model. - // */ - // protected void modelChanged() { - // // create a view hierarchy - // ViewFactory f = rootView.getViewFactory(); - // Document doc = editor.getDocument(); - // Element elem = doc.getDefaultRootElement(); - // setView(f.create(elem)); - // } - // - // /** - // * Sets the current root of the view hierarchy and calls invalidate(). - // * If there were any child components, they will be removed (i.e. - // * there are assumed to have come from components embedded in views). - // * - // * @param v the root view - // */ - // protected final void setView(View v) { - // rootView.setView(v); - // painted = false; - // editor.revalidate(); - // editor.repaint(); - // } - // - // /** - // * Paints the interface safely with a guarantee that - // * the model won't change from the view of this thread. - // * This does the following things, rendering from - // * back to front. - // *

    - // *
  1. - // * If the component is marked as opaque, the background - // * is painted in the current background color of the - // * component. - // *
  2. - // * The highlights (if any) are painted. - // *
  3. - // * The view hierarchy is painted. - // *
  4. - // * The caret is painted. - // *
- // * - // * @param g the graphics context - // */ - // protected void paintSafely(Graphics g) { - // painted = true; - // Highlighter highlighter = editor.getHighlighter(); - // Caret caret = editor.getCaret(); - // - // // paint the background - // if (editor.isOpaque()) { - // paintBackground(g); - // } - // - // // paint the highlights - // if (highlighter != null) { - // highlighter.paint(g); - // } - // - // // paint the view hierarchy - // Rectangle alloc = getVisibleEditorRect(); - // if (alloc != null) { - // rootView.paint(g, alloc); - // } - // - // // paint the caret - // if (caret != null) { - // caret.paint(g); - // } - // - // if (dropCaret != null) { - // dropCaret.paint(g); - // } - // } - - // --- ComponentUI methods -------------------------------------------- - - TextListener updateHandler; - - /** - * Installs the UI for a component. This does the following things. - *
    - *
  1. - * Set the associated component to opaque (can be changed easily by a subclass - * or on JTextComponent directly), which is the most common case. This will - * cause the component's background color to be painted. - *
  2. - * Install the default caret and highlighter into the associated component. - *
  3. - * Attach to the editor and model. If there is no model, a default one is - * created. - *
  4. - * create the view factory and the view hierarchy used to represent the model. - *
- * - * @param c - * the editor component - * @see ComponentUI#installUI - */ - protected void installJSUI() { - editor = (JTextComponent) c; - updateHandler = new TextListener(this, editor); - - // install defaults - installDefaults(); - installDefaults2(); - - // // This is a workaround as these should not override what synth has - // // set them to - // if (!(this instanceof sun.swing.plaf.synth.SynthUI)){ - // // common case is background painted... this can - // // easily be changed by subclasses or from outside - // // of the component. - // LookAndFeel.installProperty(editor, "opaque", Boolean.TRUE); - // LookAndFeel.installProperty(editor, "autoscrolls", Boolean.TRUE); - // } - // - // attach to the model and editor - // Document doc = editor.getDocument(); - // if (doc == null) { - // // no model, create a default one. This will - // // fire a notification to the updateHandler - // // which takes care of the rest. - // editor.setDocument(getEditorKit(editor).createDefaultDocument()); - // } else { - // // doc.addDocumentListener(updateHandler); - // // modelChanged(); - // } - - // install keymap - installListeners(editor); - installKeyboardActions(); - - // LayoutManager oldLayout = editor.getLayout(); - // if ((oldLayout == null) || (oldLayout instanceof UIResource)) { - // // by default, use default LayoutManger implementation that - // // will position the components associated with a View object. - // editor.setLayout(updateHandler); - // } - // - // updateBackground(editor); - } - - /** - * Deinstalls the UI for a component. This removes the listeners, uninstalls - * the highlighter, removes views, and nulls out the keymap. - * - * @param c - * the editor component - * @see ComponentUI#uninstallUI - */ - public void uninstallJSUI() { - // detach from the model - // editor.removePropertyChangeListener(updateHandler); - // editor.getDocument().removeDocumentListener(updateHandler); - - // view part - // painted = false; - uninstallDefaults(); - // rootView.setView(null); - c.removeAll(); - LayoutManager lm = c.getLayout(); - if (lm instanceof UIResource) { - c.setLayout(null); - } - - // controller part - uninstallKeyboardActions(); - uninstallListeners(editor); - - editor = null; - updateHandler = null; - } - - protected void installListeners(JTextComponent b) { - TextListener listener = updateHandler; - b.addMouseListener(listener); - b.addMouseMotionListener(listener); - b.addFocusListener(listener); - b.addPropertyChangeListener(listener); - // SwingJS there won't be a document yet; this is in constructor - // b.getDocument().addDocumentListener(listener); - } - - protected void uninstallListeners(JTextComponent b) { - TextListener listener = updateHandler; - b.removeMouseListener(listener); - b.removeMouseMotionListener(listener); - b.removeFocusListener(listener); - b.removePropertyChangeListener(listener); - b.getDocument().removeDocumentListener(listener); - } - - // /** - // * Superclass paints background in an uncontrollable way - // * (i.e. one might want an image tiled into the background). - // * To prevent this from happening twice, this method is - // * reimplemented to simply paint. - // *

- // * NOTE: Superclass is also not thread-safe in - // * it's rendering of the background, although that's not - // * an issue with the default rendering. - // */ - // public void update(Graphics g, JComponent c) { - // paint(g, c); - // } - // - // /** - // * Paints the interface. This is routed to the - // * paintSafely method under the guarantee that - // * the model won't change from the view of this thread - // * while it's rendering (if the associated model is - // * derived from AbstractDocument). This enables the - // * model to potentially be updated asynchronously. - // * - // * @param g the graphics context - // * @param c the editor component - // */ - // public final void paint(Graphics g, JComponent c) { - // if ((rootView.getViewCount() > 0) && (rootView.getView(0) != null)) { - // Document doc = editor.getDocument(); - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readLock(); - // } - // try { - // paintSafely(g); - // } finally { - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readUnlock(); - // } - // } - // } - // } - - // /** - // * Gets the preferred size for the editor component. If the component - // * has been given a size prior to receiving this request, it will - // * set the size of the view hierarchy to reflect the size of the component - // * before requesting the preferred size of the view hierarchy. This - // * allows formatted views to format to the current component size before - // * answering the request. Other views don't care about currently formatted - // * size and give the same answer either way. - // * - // * @param c the editor component - // * @return the size - // */ - // public Dimension getPreferredSize(JComponent c) { - // Dimension d = c.getSize(); - // // Document doc = editor.getDocument(); - // // Insets i = c.getInsets(); - // // - // // if (doc instanceof AbstractDocument) { - // // ((AbstractDocument)doc).readLock(); - // // } - // // try { - // // if ((d.width > (i.left + i.right)) && (d.height > (i.top + i.bottom))) { - // // rootView.setSize(d.width - i.left - i.right, d.height - i.top - - // i.bottom); - // // } - // // else if (d.width == 0 && d.height == 0) { - // // // Probably haven't been layed out yet, force some sort of - // // // initial sizing. - // // rootView.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE); - // // } - // // d.width = (int) Math.min((long) rootView.getPreferredSpan(View.X_AXIS) + - // // (long) i.left + (long) i.right, Integer.MAX_VALUE); - // // d.height = (int) Math.min((long) rootView.getPreferredSpan(View.Y_AXIS) - // + - // // (long) i.top + (long) i.bottom, Integer.MAX_VALUE); - // // } finally { - // // if (doc instanceof AbstractDocument) { - // // ((AbstractDocument)doc).readUnlock(); - // // } - // // } - // return d; - // } - - /** - * Gets the minimum size for the editor component. - * - * @param c - * the editor component - * @return the size - */ - public Dimension getMinimumSize(JComponent c) { - Dimension d = getPreferredSize();// new Dimension(); - // Document doc = editor.getDocument(); - Insets i = c.getInsets(); - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readLock(); - // } - // try { - - d.width += i.left + i.right; - d.height += i.top + i.bottom; - - // d.width = (int) rootView.getMinimumSpan(View.X_AXIS) + i.left + i.right; - // d.height = (int) rootView.getMinimumSpan(View.Y_AXIS) + i.top + i.bottom; - // } finally { - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readUnlock(); - // } - // } - return d; - } - - /** - * Gets the maximum size for the editor component. - * - * @param c - * the editor component - * @return the size - */ - public Dimension getMaximumSize(JComponent c) { - // SwingJS TODO - return getMinimumSize(c); - - // Document doc = editor.getDocument(); - // Insets i = c.getInsets(); - // Dimension d = new Dimension(); - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readLock(); - // } - // try { - // d.width = (int) Math.min((long) rootView.getMaximumSpan(View.X_AXIS) + - // (long) i.left + (long) i.right, Integer.MAX_VALUE); - // d.height = (int) Math.min((long) rootView.getMaximumSpan(View.Y_AXIS) + - // (long) i.top + (long) i.bottom, Integer.MAX_VALUE); - // } finally { - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readUnlock(); - // } - // } - // return d; - } - - // ---- TextUI methods ------------------------------------------- - - // - // /** - // * Gets the allocation to give the root View. Due - // * to an unfortunate set of historical events this - // * method is inappropriately named. The Rectangle - // * returned has nothing to do with visibility. - // * The component must have a non-zero positive size for - // * this translation to be computed. - // * - // * @return the bounding box for the root view - // */ - // protected Rectangle getVisibleEditorRect() { - // Rectangle alloc = editor.getBounds(); - // if ((alloc.width > 0) && (alloc.height > 0)) { - // alloc.x = alloc.y = 0; - // Insets insets = editor.getInsets(); - // alloc.x += insets.left; - // alloc.y += insets.top; - // alloc.width -= insets.left + insets.right; - // alloc.height -= insets.top + insets.bottom; - // return alloc; - // } - // return null; - // } - // - // /** - // * Converts the given location in the model to a place in - // * the view coordinate system. - // * The component must have a non-zero positive size for - // * this translation to be computed. - // * - // * @param tc the text component for which this UI is installed - // * @param pos the local location in the model to translate >= 0 - // * @return the coordinates as a rectangle, null if the model is not painted - // * @exception BadLocationException if the given position does not - // * represent a valid location in the associated document - // * @see TextUI#modelToView - // */ - // public Rectangle modelToView(JTextComponent tc, int pos) throws - // BadLocationException { - // return modelToView(tc, pos, Position.Bias.Forward); - // } - // - // /** - // * Converts the given location in the model to a place in - // * the view coordinate system. - // * The component must have a non-zero positive size for - // * this translation to be computed. - // * - // * @param tc the text component for which this UI is installed - // * @param pos the local location in the model to translate >= 0 - // * @return the coordinates as a rectangle, null if the model is not painted - // * @exception BadLocationException if the given position does not - // * represent a valid location in the associated document - // * @see TextUI#modelToView - // */ - // public Rectangle modelToView(JTextComponent tc, int pos, Position.Bias - // bias) throws BadLocationException { - // Document doc = editor.getDocument(); - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readLock(); - // } - // try { - // Rectangle alloc = getVisibleEditorRect(); - // if (alloc != null) { - // rootView.setSize(alloc.width, alloc.height); - // Shape s = rootView.modelToView(pos, alloc, bias); - // if (s != null) { - // return s.getBounds(); - // } - // } - // } finally { - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readUnlock(); - // } - // } - // return null; - // } - // - // /** - // * Converts the given place in the view coordinate system - // * to the nearest representative location in the model. - // * The component must have a non-zero positive size for - // * this translation to be computed. - // * - // * @param tc the text component for which this UI is installed - // * @param pt the location in the view to translate. This - // * should be in the same coordinate system as the mouse events. - // * @return the offset from the start of the document >= 0, - // * -1 if not painted - // * @see TextUI#viewToModel - // */ - // public int viewToModel(JTextComponent tc, Point pt) { - // return viewToModel(tc, pt, discardBias); - // } - // - // /** - // * Converts the given place in the view coordinate system - // * to the nearest representative location in the model. - // * The component must have a non-zero positive size for - // * this translation to be computed. - // * - // * @param tc the text component for which this UI is installed - // * @param pt the location in the view to translate. This - // * should be in the same coordinate system as the mouse events. - // * @return the offset from the start of the document >= 0, - // * -1 if the component doesn't yet have a positive size. - // * @see TextUI#viewToModel - // */ - // public int viewToModel(JTextComponent tc, Point pt, - // Position.Bias[] biasReturn) { - // int offs = -1; - // Document doc = editor.getDocument(); - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readLock(); - // } - // try { - // Rectangle alloc = getVisibleEditorRect(); - // if (alloc != null) { - // rootView.setSize(alloc.width, alloc.height); - // offs = rootView.viewToModel(pt.x, pt.y, alloc, biasReturn); - // } - // } finally { - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readUnlock(); - // } - // } - // return offs; - // } - - // /** - // * {@inheritDoc} - // */ - // public int getNextVisualPositionFrom(JTextComponent t, int pos, - // Position.Bias b, int direction, Position.Bias[] biasRet) - // throws BadLocationException{ - // Document doc = editor.getDocument(); - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readLock(); - // } - // try { - // if (painted) { - // Rectangle alloc = getVisibleEditorRect(); - // if (alloc != null) { - // rootView.setSize(alloc.width, alloc.height); - // } - // return rootView.getNextVisualPositionFrom(pos, b, alloc, direction, - // biasRet); - // } - // } finally { - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readUnlock(); - // } - // } - // return -1; - // } - // - // /** - // * Causes the portion of the view responsible for the - // * given part of the model to be repainted. Does nothing if - // * the view is not currently painted. - // * - // * @param tc the text component for which this UI is installed - // * @param p0 the beginning of the range >= 0 - // * @param p1 the end of the range >= p0 - // * @see TextUI#damageRange - // */ - // public void damageRange(JTextComponent tc, int p0, int p1) { - // damageRange(tc, p0, p1, Position.Bias.Forward, Position.Bias.Backward); - // } - // - // /** - // * Causes the portion of the view responsible for the - // * given part of the model to be repainted. - // * - // * @param p0 the beginning of the range >= 0 - // * @param p1 the end of the range >= p0 - // */ - // public void damageRange(JTextComponent t, int p0, int p1, - // Position.Bias p0Bias, Position.Bias p1Bias) { - // if (painted) { - // Rectangle alloc = getVisibleEditorRect(); - // if (alloc != null) { - // Document doc = t.getDocument(); - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readLock(); - // } - // try { - // rootView.setSize(alloc.width, alloc.height); - // Shape toDamage = rootView.modelToView(p0, p0Bias, - // p1, p1Bias, alloc); - // Rectangle rect = (toDamage instanceof Rectangle) ? - // (Rectangle)toDamage : toDamage.getBounds(); - // editor.repaint(rect.x, rect.y, rect.width, rect.height); - // } catch (BadLocationException e) { - // } finally { - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readUnlock(); - // } - // } - // } - // } - // } - - /** - * Fetches the EditorKit for the UI. - * - * @param tc - * the text component for which this UI is installed - * @return the editor capabilities - * @see TextUI#getEditorKit - */ - public EditorKit getEditorKit(JTextComponent tc) { - return defaultKit; - } - - // /** - // * Fetches a View with the allocation of the associated - // * text component (i.e. the root of the hierarchy) that - // * can be traversed to determine how the model is being - // * represented spatially. - // *

- // * NOTE:The View hierarchy can - // * be traversed from the root view, and other things - // * can be done as well. Things done in this way cannot - // * be protected like simple method calls through the TextUI. - // * Therefore, proper operation in the presence of concurrency - // * must be arranged by any logic that calls this method! - // * - // * - // * @param tc the text component for which this UI is installed - // * @return the view - // * @see TextUI#getRootView - // */ - // public View getRootView(JTextComponent tc) { - // return rootView; - // } - - // /** - // * Returns the string to be used as the tooltip at the passed in location. - // * This forwards the method onto the root View. - // * - // * @see jsjavax.swing.text.JTextComponent#getToolTipText - // * @see jsjavax.swing.text.View#getToolTipText - // * @since 1.4 - // */ - // public String getToolTipText(JTextComponent t, Point pt) { - // if (!painted) { - // return null; - // } - // Document doc = editor.getDocument(); - // String tt = null; - // Rectangle alloc = getVisibleEditorRect(); - // - // if (alloc != null) { - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readLock(); - // } - // try { - // tt = rootView.getToolTipText(pt.x, pt.y, alloc); - // } finally { - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readUnlock(); - // } - // } - // } - // return tt; - // } - // - // --- ViewFactory methods ------------------------------ - // - // /** - // * Creates a view for an element. - // * If a subclass wishes to directly implement the factory - // * producing the view(s), it should reimplement this - // * method. By default it simply returns null indicating - // * it is unable to represent the element. - // * - // * @param elem the element - // * @return the view - // */ - // public View create(Element elem) { - // return null; - // } - // - // /** - // * Creates a view for an element. - // * If a subclass wishes to directly implement the factory - // * producing the view(s), it should reimplement this - // * method. By default it simply returns null indicating - // * it is unable to represent the part of the element. - // * - // * @param elem the element - // * @param p0 the starting offset >= 0 - // * @param p1 the ending offset >= p0 - // * @return the view - // */ - // public View create(Element elem, int p0, int p1) { - // return null; - // } - // - // public static class BasicCaret extends DefaultCaret implements UIResource - // {} - // - // public static class BasicHighlighter extends DefaultHighlighter implements - // UIResource {} - // - // static class BasicCursor extends Cursor implements UIResource { - // BasicCursor(int type) { - // super(type); - // } - // - // BasicCursor(String name) { - // super(name); - // } - // } - // - // private static BasicCursor textCursor = new - // BasicCursor(Cursor.TEXT_CURSOR); - // ----- member variables --------------------------------------- - - private static final EditorKit defaultKit = new DefaultEditorKit(); - transient JTextComponent editor; - protected boolean editable = true; - - // transient boolean painted; - // transient RootView rootView = new RootView(); - // transient UpdateHandler updateHandler = new UpdateHandler(); - // private static final TransferHandler defaultTransferHandler = new - // TextTransferHandler(); - // private final DragListener dragListener = getDragListener(); - // private static final Position.Bias[] discardBias = new Position.Bias[1]; - // private DefaultCaret dropCaret; - - // /** - // * Root view that acts as a gateway between the component - // * and the View hierarchy. - // */ - // class RootView extends View { - // - // RootView() { - // super(null); - // } - // - // void setView(View v) { - // View oldView = view; - // view = null; - // if (oldView != null) { - // // get rid of back reference so that the old - // // hierarchy can be garbage collected. - // oldView.setParent(null); - // } - // if (v != null) { - // v.setParent(this); - // } - // view = v; - // } - // - // /** - // * Fetches the attributes to use when rendering. At the root - // * level there are no attributes. If an attribute is resolved - // * up the view hierarchy this is the end of the line. - // */ - // public AttributeSet getAttributes() { - // return null; - // } - // - // /** - // * Determines the preferred span for this view along an axis. - // * - // * @param axis may be either X_AXIS or Y_AXIS - // * @return the span the view would like to be rendered into. - // * Typically the view is told to render into the span - // * that is returned, although there is no guarantee. - // * The parent may choose to resize or break the view. - // */ - // public float getPreferredSpan(int axis) { - // if (view != null) { - // return view.getPreferredSpan(axis); - // } - // return 10; - // } - // - // /** - // * Determines the minimum span for this view along an axis. - // * - // * @param axis may be either X_AXIS or Y_AXIS - // * @return the span the view would like to be rendered into. - // * Typically the view is told to render into the span - // * that is returned, although there is no guarantee. - // * The parent may choose to resize or break the view. - // */ - // public float getMinimumSpan(int axis) { - // if (view != null) { - // return view.getMinimumSpan(axis); - // } - // return 10; - // } - // - // /** - // * Determines the maximum span for this view along an axis. - // * - // * @param axis may be either X_AXIS or Y_AXIS - // * @return the span the view would like to be rendered into. - // * Typically the view is told to render into the span - // * that is returned, although there is no guarantee. - // * The parent may choose to resize or break the view. - // */ - // public float getMaximumSpan(int axis) { - // return Integer.MAX_VALUE; - // } - // - // /** - // * Specifies that a preference has changed. - // * Child views can call this on the parent to indicate that - // * the preference has changed. The root view routes this to - // * invalidate on the hosting component. - // *

- // * This can be called on a different thread from the - // * event dispatching thread and is basically unsafe to - // * propagate into the component. To make this safe, - // * the operation is transferred over to the event dispatching - // * thread for completion. It is a design goal that all view - // * methods be safe to call without concern for concurrency, - // * and this behavior helps make that true. - // * - // * @param child the child view - // * @param width true if the width preference has changed - // * @param height true if the height preference has changed - // */ - // public void preferenceChanged(View child, boolean width, boolean height) { - // editor.revalidate(); - // } - // - // /** - // * Determines the desired alignment for this view along an axis. - // * - // * @param axis may be either X_AXIS or Y_AXIS - // * @return the desired alignment, where 0.0 indicates the origin - // * and 1.0 the full span away from the origin - // */ - // public float getAlignment(int axis) { - // if (view != null) { - // return view.getAlignment(axis); - // } - // return 0; - // } - // - // /** - // * Renders the view. - // * - // * @param g the graphics context - // * @param allocation the region to render into - // */ - // public void paint(Graphics g, Shape allocation) { - // if (view != null) { - // Rectangle alloc = (allocation instanceof Rectangle) ? - // (Rectangle)allocation : allocation.getBounds(); - // setSize(alloc.width, alloc.height); - // view.paint(g, allocation); - // } - // } - // - // /** - // * Sets the view parent. - // * - // * @param parent the parent view - // */ - // public void setParent(View parent) { - // throw new Error("Can't set parent on root view"); - // } - // - // /** - // * Returns the number of views in this view. Since - // * this view simply wraps the root of the view hierarchy - // * it has exactly one child. - // * - // * @return the number of views - // * @see #getView - // */ - // public int getViewCount() { - // return 1; - // } - // - // /** - // * Gets the n-th view in this container. - // * - // * @param n the number of the view to get - // * @return the view - // */ - // public View getView(int n) { - // return view; - // } - // - // /** - // * Returns the child view index representing the given position in - // * the model. This is implemented to return the index of the only - // * child. - // * - // * @param pos the position >= 0 - // * @return index of the view representing the given position, or - // * -1 if no view represents that position - // * @since 1.3 - // */ - // public int getViewIndex(int pos, Position.Bias b) { - // return 0; - // } - // - // /** - // * Fetches the allocation for the given child view. - // * This enables finding out where various views - // * are located, without assuming the views store - // * their location. This returns the given allocation - // * since this view simply acts as a gateway between - // * the view hierarchy and the associated component. - // * - // * @param index the index of the child - // * @param a the allocation to this view. - // * @return the allocation to the child - // */ - // public Shape getChildAllocation(int index, Shape a) { - // return a; - // } - // - // /** - // * Provides a mapping from the document model coordinate space - // * to the coordinate space of the view mapped to it. - // * - // * @param pos the position to convert - // * @param a the allocated region to render into - // * @return the bounding box of the given position - // */ - // public Shape modelToView(int pos, Shape a, Position.Bias b) throws - // BadLocationException { - // if (view != null) { - // return view.modelToView(pos, a, b); - // } - // return null; - // } - // - // /** - // * Provides a mapping from the document model coordinate space - // * to the coordinate space of the view mapped to it. - // * - // * @param p0 the position to convert >= 0 - // * @param b0 the bias toward the previous character or the - // * next character represented by p0, in case the - // * position is a boundary of two views. - // * @param p1 the position to convert >= 0 - // * @param b1 the bias toward the previous character or the - // * next character represented by p1, in case the - // * position is a boundary of two views. - // * @param a the allocated region to render into - // * @return the bounding box of the given position is returned - // * @exception BadLocationException if the given position does - // * not represent a valid location in the associated document - // * @exception IllegalArgumentException for an invalid bias argument - // * @see View#viewToModel - // */ - // public Shape modelToView(int p0, Position.Bias b0, int p1, Position.Bias - // b1, Shape a) throws BadLocationException { - // if (view != null) { - // return view.modelToView(p0, b0, p1, b1, a); - // } - // return null; - // } - // - // /** - // * Provides a mapping from the view coordinate space to the logical - // * coordinate space of the model. - // * - // * @param x x coordinate of the view location to convert - // * @param y y coordinate of the view location to convert - // * @param a the allocated region to render into - // * @return the location within the model that best represents the - // * given point in the view - // */ - // public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) { - // if (view != null) { - // int retValue = view.viewToModel(x, y, a, bias); - // return retValue; - // } - // return -1; - // } - // - // /** - // * Provides a way to determine the next visually represented model - // * location that one might place a caret. Some views may not be visible, - // * they might not be in the same order found in the model, or they just - // * might not allow access to some of the locations in the model. - // * - // * @param pos the position to convert >= 0 - // * @param a the allocated region to render into - // * @param direction the direction from the current position that can - // * be thought of as the arrow keys typically found on a keyboard. - // * This may be SwingConstants.WEST, SwingConstants.EAST, - // * SwingConstants.NORTH, or SwingConstants.SOUTH. - // * @return the location within the model that best represents the next - // * location visual position. - // * @exception BadLocationException - // * @exception IllegalArgumentException for an invalid direction - // */ - // public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, - // int direction, - // Position.Bias[] biasRet) - // throws BadLocationException { - // if( view != null ) { - // int nextPos = view.getNextVisualPositionFrom(pos, b, a, - // direction, biasRet); - // if(nextPos != -1) { - // pos = nextPos; - // } - // else { - // biasRet[0] = b; - // } - // } - // return pos; - // } - // - // /** - // * Gives notification that something was inserted into the document - // * in a location that this view is responsible for. - // * - // * @param e the change information from the associated document - // * @param a the current allocation of the view - // * @param f the factory to use to rebuild if the view has children - // */ - // public void insertUpdate(DocumentEvent e, Shape a, ViewFactory f) { - // if (view != null) { - // view.insertUpdate(e, a, f); - // } - // } - // - // /** - // * Gives notification that something was removed from the document - // * in a location that this view is responsible for. - // * - // * @param e the change information from the associated document - // * @param a the current allocation of the view - // * @param f the factory to use to rebuild if the view has children - // */ - // public void removeUpdate(DocumentEvent e, Shape a, ViewFactory f) { - // if (view != null) { - // view.removeUpdate(e, a, f); - // } - // } - // - // /** - // * Gives notification from the document that attributes were changed - // * in a location that this view is responsible for. - // * - // * @param e the change information from the associated document - // * @param a the current allocation of the view - // * @param f the factory to use to rebuild if the view has children - // */ - // public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) { - // if (view != null) { - // view.changedUpdate(e, a, f); - // } - // } - // - // /** - // * Returns the document model underlying the view. - // * - // * @return the model - // */ - // public Document getDocument() { - // return editor.getDocument(); - // } - // - // /** - // * Returns the starting offset into the model for this view. - // * - // * @return the starting offset - // */ - // public int getStartOffset() { - // if (view != null) { - // return view.getStartOffset(); - // } - // return getElement().getStartOffset(); - // } - // - // /** - // * Returns the ending offset into the model for this view. - // * - // * @return the ending offset - // */ - // public int getEndOffset() { - // if (view != null) { - // return view.getEndOffset(); - // } - // return getElement().getEndOffset(); - // } - // - // /** - // * Gets the element that this view is mapped to. - // * - // * @return the view - // */ - // public Element getElement() { - // if (view != null) { - // return view.getElement(); - // } - // return editor.getDocument().getDefaultRootElement(); - // } - // - // /** - // * Breaks this view on the given axis at the given length. - // * - // * @param axis may be either X_AXIS or Y_AXIS - // * @param len specifies where a break is desired in the span - // * @param the current allocation of the view - // * @return the fragment of the view that represents the given span - // * if the view can be broken, otherwise null - // */ - // public View breakView(int axis, float len, Shape a) { - // throw new Error("Can't break root view"); - // } - // - // /** - // * Determines the resizability of the view along the - // * given axis. A value of 0 or less is not resizable. - // * - // * @param axis may be either X_AXIS or Y_AXIS - // * @return the weight - // */ - // public int getResizeWeight(int axis) { - // if (view != null) { - // return view.getResizeWeight(axis); - // } - // return 0; - // } - // - // /** - // * Sets the view size. - // * - // * @param width the width - // * @param height the height - // */ - // public void setSize(float width, float height) { - // if (view != null) { - // view.setSize(width, height); - // } - // } - // - // /** - // * Fetches the container hosting the view. This is useful for - // * things like scheduling a repaint, finding out the host - // * components font, etc. The default implementation - // * of this is to forward the query to the parent view. - // * - // * @return the container - // */ - // public Container getContainer() { - // return editor; - // } - // - // /** - // * Fetches the factory to be used for building the - // * various view fragments that make up the view that - // * represents the model. This is what determines - // * how the model will be represented. This is implemented - // * to fetch the factory provided by the associated - // * EditorKit unless that is null, in which case this - // * simply returns the BasicTextUI itself which allows - // * subclasses to implement a simple factory directly without - // * creating extra objects. - // * - // * @return the factory - // */ - // public ViewFactory getViewFactory() { - // EditorKit kit = getEditorKit(editor); - // ViewFactory f = kit.getViewFactory(); - // if (f != null) { - // return f; - // } - // return BasicTextUI.this; - // } - // - // private View view; - // - // } - - // /** - // * Handles updates from various places. If the model is changed, - // * this class unregisters as a listener to the old model and - // * registers with the new model. If the document model changes, - // * the change is forwarded to the root view. If the focus - // * accelerator changes, a new keystroke is registered to request - // * focus. - // */ - // class UpdateHandler implements PropertyChangeListener, DocumentListener, - // LayoutManager2, UIResource { - // - // // --- PropertyChangeListener methods ----------------------- - // - // /** - // * This method gets called when a bound property is changed. - // * We are looking for document changes on the editor. - // */ - // public final void propertyChange(PropertyChangeEvent evt) { - // Object oldValue = evt.getOldValue(); - // Object newValue = evt.getNewValue(); - // String propertyName = evt.getPropertyName(); - // if ((oldValue instanceof Document) || (newValue instanceof Document)) { - // if (oldValue != null) { - // ((Document)oldValue).removeDocumentListener(this); - // i18nView = false; - // } - // if (newValue != null) { - // ((Document)newValue).addDocumentListener(this); - // if ("document" == propertyName) { - // setView(null); - // BasicTextUI.this.propertyChange(evt); - // modelChanged(); - // return; - // } - // } - // modelChanged(); - // } - // if ("focusAccelerator" == propertyName) { - // updateFocusAcceleratorBinding(true); - // } else if ("componentOrientation" == propertyName) { - // // Changes in ComponentOrientation require the views to be - // // rebuilt. - // modelChanged(); - // } else if ("font" == propertyName) { - // modelChanged(); - // } else if ("dropLocation" == propertyName) { - // dropIndexChanged(); - // } else if ("editable" == propertyName) { - // updateCursor(); - // modelChanged(); - // } - // BasicTextUI.this.propertyChange(evt); - // } - // - // private void dropIndexChanged() { - // if (editor.getDropMode() == DropMode.USE_SELECTION) { - // return; - // } - // - // JTextComponent.DropLocation dropLocation = editor.getDropLocation(); - // - // if (dropLocation == null) { - // if (dropCaret != null) { - // dropCaret.deinstall(editor); - // editor.repaint(dropCaret); - // dropCaret = null; - // } - // } else { - // if (dropCaret == null) { - // dropCaret = new BasicCaret(); - // dropCaret.install(editor); - // dropCaret.setVisible(true); - // } - // - // dropCaret.setDot(dropLocation.getIndex(), - // dropLocation.getBias()); - // } - // } - // - // // --- DocumentListener methods ----------------------- - // - // /** - // * The insert notification. Gets sent to the root of the view structure - // * that represents the portion of the model being represented by the - // * editor. The factory is added as an argument to the update so that - // * the views can update themselves in a dynamic (not hardcoded) way. - // * - // * @param e The change notification from the currently associated - // * document. - // * @see DocumentListener#insertUpdate - // */ - // public final void insertUpdate(DocumentEvent e) { - // Document doc = e.getDocument(); - // Object o = doc.getProperty("i18n"); - // if (o instanceof Boolean) { - // Boolean i18nFlag = (Boolean) o; - // if (i18nFlag.booleanValue() != i18nView) { - // // i18n flag changed, rebuild the view - // i18nView = i18nFlag.booleanValue(); - // modelChanged(); - // return; - // } - // } - // - // // normal insert update - // Rectangle alloc = (painted) ? getVisibleEditorRect() : null; - // rootView.insertUpdate(e, alloc, rootView.getViewFactory()); - // } - // - // /** - // * The remove notification. Gets sent to the root of the view structure - // * that represents the portion of the model being represented by the - // * editor. The factory is added as an argument to the update so that - // * the views can update themselves in a dynamic (not hardcoded) way. - // * - // * @param e The change notification from the currently associated - // * document. - // * @see DocumentListener#removeUpdate - // */ - // public final void removeUpdate(DocumentEvent e) { - // Rectangle alloc = (painted) ? getVisibleEditorRect() : null; - // rootView.removeUpdate(e, alloc, rootView.getViewFactory()); - // } - // - // /** - // * The change notification. Gets sent to the root of the view structure - // * that represents the portion of the model being represented by the - // * editor. The factory is added as an argument to the update so that - // * the views can update themselves in a dynamic (not hardcoded) way. - // * - // * @param e The change notification from the currently associated - // * document. - // * @see DocumentListener#changeUpdate - // */ - // public final void changedUpdate(DocumentEvent e) { - // Rectangle alloc = (painted) ? getVisibleEditorRect() : null; - // rootView.changedUpdate(e, alloc, rootView.getViewFactory()); - // } - // - // // --- LayoutManager2 methods -------------------------------- - // - // /** - // * Adds the specified component with the specified name to - // * the layout. - // * @param name the component name - // * @param comp the component to be added - // */ - // public void addLayoutComponent(String name, Component comp) { - // // not supported - // } - // - // /** - // * Removes the specified component from the layout. - // * @param comp the component to be removed - // */ - // public void removeLayoutComponent(Component comp) { - // if (constraints != null) { - // // remove the constraint record - // constraints.remove(comp); - // } - // } - // - // /** - // * Calculates the preferred size dimensions for the specified - // * panel given the components in the specified parent container. - // * @param parent the component to be laid out - // * - // * @see #minimumLayoutSize - // */ - // public Dimension preferredLayoutSize(Container parent) { - // // should not be called (JComponent uses UI instead) - // return null; - // } - // - // /** - // * Calculates the minimum size dimensions for the specified - // * panel given the components in the specified parent container. - // * @param parent the component to be laid out - // * @see #preferredLayoutSize - // */ - // public Dimension minimumLayoutSize(Container parent) { - // // should not be called (JComponent uses UI instead) - // return null; - // } - // - // /** - // * Lays out the container in the specified panel. This is - // * implemented to position all components that were added - // * with a View object as a constraint. The current allocation - // * of the associated View is used as the location of the - // * component. - // *

- // * A read-lock is acquired on the document to prevent the - // * view tree from being modified while the layout process - // * is active. - // * - // * @param parent the component which needs to be laid out - // */ - // public void layoutContainer(Container parent) { - // if ((constraints != null) && (! constraints.isEmpty())) { - // Rectangle alloc = getVisibleEditorRect(); - // if (alloc != null) { - // Document doc = editor.getDocument(); - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readLock(); - // } - // try { - // rootView.setSize(alloc.width, alloc.height); - // Enumeration components = constraints.keys(); - // while (components.hasMoreElements()) { - // Component comp = (Component) components.nextElement(); - // View v = (View) constraints.get(comp); - // Shape ca = calculateViewPosition(alloc, v); - // if (ca != null) { - // Rectangle compAlloc = (ca instanceof Rectangle) ? - // (Rectangle) ca : ca.getBounds(); - // comp.setBounds(compAlloc); - // } - // } - // } finally { - // if (doc instanceof AbstractDocument) { - // ((AbstractDocument)doc).readUnlock(); - // } - // } - // } - // } - // } - // - // /** - // * Find the Shape representing the given view. - // */ - // Shape calculateViewPosition(Shape alloc, View v) { - // int pos = v.getStartOffset(); - // View child = null; - // for (View parent = rootView; (parent != null) && (parent != v); parent = - // child) { - // int index = parent.getViewIndex(pos, Position.Bias.Forward); - // alloc = parent.getChildAllocation(index, alloc); - // child = parent.getView(index); - // } - // return (child != null) ? alloc : null; - // } - // - // /** - // * Adds the specified component to the layout, using the specified - // * constraint object. We only store those components that were added - // * with a constraint that is of type View. - // * - // * @param comp the component to be added - // * @param constraint where/how the component is added to the layout. - // */ - // public void addLayoutComponent(Component comp, Object constraint) { - // if (constraint instanceof View) { - // if (constraints == null) { - // constraints = new Hashtable(7); - // } - // constraints.put(comp, constraint); - // } - // } - // - // /** - // * Returns the maximum size of this component. - // * @see jsjava.awt.Component#getMinimumSize() - // * @see jsjava.awt.Component#getPreferredSize() - // * @see LayoutManager - // */ - // public Dimension maximumLayoutSize(Container target) { - // // should not be called (JComponent uses UI instead) - // return null; - // } - // - // /** - // * Returns the alignment along the x axis. This specifies how - // * the component would like to be aligned relative to other - // * components. The value should be a number between 0 and 1 - // * where 0 represents alignment along the origin, 1 is aligned - // * the furthest away from the origin, 0.5 is centered, etc. - // */ - // public float getLayoutAlignmentX(Container target) { - // return 0.5f; - // } - // - // /** - // * Returns the alignment along the y axis. This specifies how - // * the component would like to be aligned relative to other - // * components. The value should be a number between 0 and 1 - // * where 0 represents alignment along the origin, 1 is aligned - // * the furthest away from the origin, 0.5 is centered, etc. - // */ - // public float getLayoutAlignmentY(Container target) { - // return 0.5f; - // } - // - // /** - // * Invalidates the layout, indicating that if the layout manager - // * has cached information it should be discarded. - // */ - // public void invalidateLayout(Container target) { - // } - // - // /** - // * The "layout constraints" for the LayoutManager2 implementation. - // * These are View objects for those components that are represented - // * by a View in the View tree. - // */ - // private Hashtable constraints; - // - // private boolean i18nView = false; - // } - - /** - * Wrapper for text actions to return isEnabled false in case editor is non - * editable - */ - class TextActionWrapper extends TextAction { - public TextActionWrapper(TextAction action) { - super((String) action.getValue(Action.NAME)); - this.action = action; - } - - /** - * The operation to perform when this action is triggered. - * - * @param e - * the action event - */ - public void actionPerformed(ActionEvent e) { - action.actionPerformed(e); - } - - public boolean isEnabled() { - return (editor == null || editor.isEditable()) ? action.isEnabled() - : false; - } - - TextAction action = null; - } - - /** - * Registered in the ActionMap. - */ - class FocusAction extends AbstractAction { - - public void actionPerformed(ActionEvent e) { - editor.requestFocus(); - } - - public boolean isEnabled() { - return editor.isEditable(); - } - } - - boolean handleEnter(int eventType) { - return false; - } - - String bgcolor0; - - public void setEditable(boolean editable) { - - this.editable = editable; - if (domNode == null) - return; - if (c.isBackgroundSet()) - bgcolor0 = JSToolkit.getCSSColor(c.getBackground()); - if (editable) { - domNode.removeAttribute("readOnly"); - if (bgcolor0 != null) - DOMNode.setStyles(domNode, "background-color", bgcolor0); - } else { - DOMNode.setAttr(domNode, "readOnly", "true"); - if (c.isBackgroundSet()) { - bgcolor0 = JSToolkit.getCSSColor(c.getBackground()); - } else { - if (bgcolor0 == null) - bgcolor0 = domNode.getStyle("background-color"); - } - DOMNode.setStyles(domNode, "background-color", "rgba(0,0,0,0)"); - } - - } - - // private static DragListener getDragListener() { - // synchronized(DragListener.class) { - // DragListener listener = - // (DragListener)AppContext.getAppContext(). - // get(DragListener.class); - // - // if (listener == null) { - // listener = new DragListener(); - // AppContext.getAppContext().put(DragListener.class, listener); - // } - // - // return listener; - // } - // } - // - // /** - // * Listens for mouse events for the purposes of detecting drag gestures. - // * BasicTextUI will maintain one of these per AppContext. - // */ - // static class DragListener extends MouseInputAdapter - // implements BeforeDrag { - // - // private boolean dragStarted; - // - // public void dragStarting(MouseEvent me) { - // dragStarted = true; - // } - // - // public void mousePressed(MouseEvent e) { - // JTextComponent c = (JTextComponent)e.getSource(); - // if (c.getDragEnabled()) { - // dragStarted = false; - // if (isDragPossible(e) && DragRecognitionSupport.mousePressed(e)) { - // e.consume(); - // } - // } - // } - // - // public void mouseReleased(MouseEvent e) { - // JTextComponent c = (JTextComponent)e.getSource(); - // if (c.getDragEnabled()) { - // if (dragStarted) { - // e.consume(); - // } - // - // DragRecognitionSupport.mouseReleased(e); - // } - // } - // - // public void mouseDragged(MouseEvent e) { - // JTextComponent c = (JTextComponent)e.getSource(); - // if (c.getDragEnabled()) { - // if (dragStarted || DragRecognitionSupport.mouseDragged(e, this)) { - // e.consume(); - // } - // } - // } - // - // /** - // * Determines if the following are true: - // *

- // */ - // protected boolean isDragPossible(MouseEvent e) { - // JTextComponent c = (JTextComponent)e.getSource(); - // if (c.isEnabled()) { - // Caret caret = c.getCaret(); - // int dot = caret.getDot(); - // int mark = caret.getMark(); - // if (dot != mark) { - // Point p = new Point(e.getX(), e.getY()); - // int pos = c.viewToModel(p); - // - // int p0 = Math.min(dot, mark); - // int p1 = Math.max(dot, mark); - // if ((pos >= p0) && (pos < p1)) { - // return true; - // } - // } - // } - // return false; - // } - // } - - // static class TextTransferHandler extends TransferHandler implements - // UIResource { - // - // private JTextComponent exportComp; - // private boolean shouldRemove; - // private int p0; - // private int p1; - // - // /** - // * Whether or not this is a drop using - // * DropMode.INSERT. - // */ - // private boolean modeBetween = false; - // - // /** - // * Whether or not this is a drop. - // */ - // private boolean isDrop = false; - // - // /** - // * The drop action. - // */ - // private int dropAction = MOVE; - // - // /** - // * The drop bias. - // */ - // private Position.Bias dropBias; - // - // /** - // * Try to find a flavor that can be used to import a Transferable. - // * The set of usable flavors are tried in the following order: - // *
    - // *
  1. First, an attempt is made to find a flavor matching the content type - // * of the EditorKit for the component. - // *
  2. Second, an attempt to find a text/plain flavor is made. - // *
  3. Third, an attempt to find a flavor representing a String reference - // * in the same VM is made. - // *
  4. Lastly, DataFlavor.stringFlavor is searched for. - // *
- // */ - // protected DataFlavor getImportFlavor(DataFlavor[] flavors, JTextComponent - // c) { - // DataFlavor plainFlavor = null; - // DataFlavor refFlavor = null; - // DataFlavor stringFlavor = null; - // - // if (c instanceof JEditorPane) { - // for (int i = 0; i < flavors.length; i++) { - // String mime = flavors[i].getMimeType(); - // if (mime.startsWith(((JEditorPane)c).getEditorKit().getContentType())) { - // return flavors[i]; - // } else if (plainFlavor == null && mime.startsWith("text/plain")) { - // plainFlavor = flavors[i]; - // } else if (refFlavor == null && - // mime.startsWith("application/x-java-jvm-local-objectref") - // && flavors[i].getRepresentationClass() == jsjava.lang.String.class) { - // refFlavor = flavors[i]; - // } else if (stringFlavor == null && - // flavors[i].equals(DataFlavor.stringFlavor)) { - // stringFlavor = flavors[i]; - // } - // } - // if (plainFlavor != null) { - // return plainFlavor; - // } else if (refFlavor != null) { - // return refFlavor; - // } else if (stringFlavor != null) { - // return stringFlavor; - // } - // return null; - // } - // - // - // for (int i = 0; i < flavors.length; i++) { - // String mime = flavors[i].getMimeType(); - // if (mime.startsWith("text/plain")) { - // return flavors[i]; - // } else if (refFlavor == null && - // mime.startsWith("application/x-java-jvm-local-objectref") - // && flavors[i].getRepresentationClass() == jsjava.lang.String.class) { - // refFlavor = flavors[i]; - // } else if (stringFlavor == null && - // flavors[i].equals(DataFlavor.stringFlavor)) { - // stringFlavor = flavors[i]; - // } - // } - // if (refFlavor != null) { - // return refFlavor; - // } else if (stringFlavor != null) { - // return stringFlavor; - // } - // return null; - // } - // - // /** - // * Import the given stream data into the text component. - // */ - // protected void handleReaderImport(Reader in, JTextComponent c, boolean - // useRead) - // throws BadLocationException, IOException { - // if (useRead) { - // int startPosition = c.getSelectionStart(); - // int endPosition = c.getSelectionEnd(); - // int length = endPosition - startPosition; - // EditorKit kit = c.getUI().getEditorKit(c); - // Document doc = c.getDocument(); - // if (length > 0) { - // doc.remove(startPosition, length); - // } - // kit.read(in, doc, startPosition); - // } else { - // char[] buff = new char[1024]; - // int nch; - // boolean lastWasCR = false; - // int last; - // StringBuffer sbuff = null; - // - // // Read in a block at a time, mapping \r\n to \n, as well as single - // // \r to \n. - // while ((nch = in.read(buff, 0, buff.length)) != -1) { - // if (sbuff == null) { - // sbuff = new StringBuffer(nch); - // } - // last = 0; - // for(int counter = 0; counter < nch; counter++) { - // switch(buff[counter]) { - // case '\r': - // if (lastWasCR) { - // if (counter == 0) { - // sbuff.append('\n'); - // } else { - // buff[counter - 1] = '\n'; - // } - // } else { - // lastWasCR = true; - // } - // break; - // case '\n': - // if (lastWasCR) { - // if (counter > (last + 1)) { - // sbuff.append(buff, last, counter - last - 1); - // } - // // else nothing to do, can skip \r, next write will - // // write \n - // lastWasCR = false; - // last = counter; - // } - // break; - // default: - // if (lastWasCR) { - // if (counter == 0) { - // sbuff.append('\n'); - // } else { - // buff[counter - 1] = '\n'; - // } - // lastWasCR = false; - // } - // break; - // } - // } - // if (last < nch) { - // if (lastWasCR) { - // if (last < (nch - 1)) { - // sbuff.append(buff, last, nch - last - 1); - // } - // } else { - // sbuff.append(buff, last, nch - last); - // } - // } - // } - // if (lastWasCR) { - // sbuff.append('\n'); - // } - // c.replaceSelection(sbuff != null ? sbuff.toString() : ""); - // } - // } - // - // // --- TransferHandler methods ------------------------------------ - // - // /** - // * This is the type of transfer actions supported by the source. Some models - // are - // * not mutable, so a transfer operation of COPY only should - // * be advertised in that case. - // * - // * @param c The component holding the data to be transfered. This - // * argument is provided to enable sharing of TransferHandlers by - // * multiple components. - // * @return This is implemented to return NONE if the component is a - // JPasswordField - // * since exporting data via user gestures is not allowed. If the text - // component is - // * editable, COPY_OR_MOVE is returned, otherwise just COPY is allowed. - // */ - // public int getSourceActions(JComponent c) { - // if (c instanceof JPasswordField && - // c.getClientProperty("JPasswordField.cutCopyAllowed") != - // Boolean.TRUE) { - // return NONE; - // } - // - // return ((JTextComponent)c).isEditable() ? COPY_OR_MOVE : COPY; - // } - // - // /** - // * Create a Transferable to use as the source for a data transfer. - // * - // * @param comp The component holding the data to be transfered. This - // * argument is provided to enable sharing of TransferHandlers by - // * multiple components. - // * @return The representation of the data to be transfered. - // * - // */ - // protected Transferable createTransferable(JComponent comp) { - // exportComp = (JTextComponent)comp; - // shouldRemove = true; - // p0 = exportComp.getSelectionStart(); - // p1 = exportComp.getSelectionEnd(); - // return (p0 != p1) ? (new TextTransferable(exportComp, p0, p1)) : null; - // } - // - // /** - // * This method is called after data has been exported. This method should - // remove - // * the data that was transfered if the action was MOVE. - // * - // * @param source The component that was the source of the data. - // * @param data The data that was transferred or possibly null - // * if the action is NONE. - // * @param action The actual action that was performed. - // */ - // protected void exportDone(JComponent source, Transferable data, int action) - // { - // // only remove the text if shouldRemove has not been set to - // // false by importData and only if the action is a move - // if (shouldRemove && action == MOVE) { - // TextTransferable t = (TextTransferable)data; - // t.removeText(); - // } - // - // exportComp = null; - // } - // - // public boolean importData(TransferSupport support) { - // isDrop = support.isDrop(); - // - // if (isDrop) { - // modeBetween = - // ((JTextComponent)support.getComponent()).getDropMode() == DropMode.INSERT; - // - // dropBias = - // ((JTextComponent.DropLocation)support.getDropLocation()).getBias(); - // - // dropAction = support.getDropAction(); - // } - // - // try { - // return super.importData(support); - // } finally { - // isDrop = false; - // modeBetween = false; - // dropBias = null; - // dropAction = MOVE; - // } - // } - // - // /** - // * This method causes a transfer to a component from a clipboard or a - // * DND drop operation. The Transferable represents the data to be - // * imported into the component. - // * - // * @param comp The component to receive the transfer. This - // * argument is provided to enable sharing of TransferHandlers by - // * multiple components. - // * @param t The data to import - // * @return true if the data was inserted into the component, false - // otherwise. - // */ - // public boolean importData(JComponent comp, Transferable t) { - // JTextComponent c = (JTextComponent)comp; - // - // int pos = modeBetween - // ? ((JTextComponent.DropLocation)c.getDropLocation()).getIndex() - // : c.getCaretPosition(); - // - // // if we are importing to the same component that we exported from - // // then don't actually do anything if the drop location is inside - // // the drag location and set shouldRemove to false so that exportDone - // // knows not to remove any data - // if (dropAction == MOVE && c == exportComp && pos >= p0 && pos <= p1) { - // shouldRemove = false; - // return true; - // } - // - // boolean imported = false; - // DataFlavor importFlavor = getImportFlavor(t.getTransferDataFlavors(), c); - // if (importFlavor != null) { - // try { - // boolean useRead = false; - // if (comp instanceof JEditorPane) { - // JEditorPane ep = (JEditorPane)comp; - // if (!ep.getContentType().startsWith("text/plain") && - // importFlavor.getMimeType().startsWith(ep.getContentType())) { - // useRead = true; - // } - // } - // InputContext ic = c.getInputContext(); - // if (ic != null) { - // ic.endComposition(); - // } - // Reader r = importFlavor.getReaderForText(t); - // - // if (modeBetween) { - // Caret caret = c.getCaret(); - // if (caret instanceof DefaultCaret) { - // ((DefaultCaret)caret).setDot(pos, dropBias); - // } else { - // c.setCaretPosition(pos); - // } - // } - // - // handleReaderImport(r, c, useRead); - // - // if (isDrop) { - // c.requestFocus(); - // Caret caret = c.getCaret(); - // if (caret instanceof DefaultCaret) { - // int newPos = caret.getDot(); - // Position.Bias newBias = ((DefaultCaret)caret).getDotBias(); - // - // ((DefaultCaret)caret).setDot(pos, dropBias); - // ((DefaultCaret)caret).moveDot(newPos, newBias); - // } else { - // c.select(pos, c.getCaretPosition()); - // } - // } - // - // imported = true; - // } catch (UnsupportedFlavorException ufe) { - // } catch (BadLocationException ble) { - // } catch (IOException ioe) { - // } - // } - // return imported; - // } - // - // /** - // * This method indicates if a component would accept an import of the given - // * set of data flavors prior to actually attempting to import it. - // * - // * @param comp The component to receive the transfer. This - // * argument is provided to enable sharing of TransferHandlers by - // * multiple components. - // * @param flavors The data formats available - // * @return true if the data can be inserted into the component, false - // otherwise. - // */ - // public boolean canImport(JComponent comp, DataFlavor[] flavors) { - // JTextComponent c = (JTextComponent)comp; - // if (!(c.isEditable() && c.isEnabled())) { - // return false; - // } - // return (getImportFlavor(flavors, c) != null); - // } - // - // /** - // * A possible implementation of the Transferable interface - // * for text components. For a JEditorPane with a rich set - // * of EditorKit implementations, conversions could be made - // * giving a wider set of formats. This is implemented to - // * offer up only the active content type and text/plain - // * (if that is not the active format) since that can be - // * extracted from other formats. - // */ - // static class TextTransferable extends BasicTransferable { - // - // TextTransferable(JTextComponent c, int start, int end) { - // super(null, null); - // - // this.c = c; - // - // Document doc = c.getDocument(); - // - // try { - // p0 = doc.createPosition(start); - // p1 = doc.createPosition(end); - // - // plainData = c.getSelectedText(); - // - // if (c instanceof JEditorPane) { - // JEditorPane ep = (JEditorPane)c; - // - // mimeType = ep.getContentType(); - // - // if (mimeType.startsWith("text/plain")) { - // return; - // } - // - // StringWriter sw = new StringWriter(p1.getOffset() - p0.getOffset()); - // ep.getEditorKit().write(sw, doc, p0.getOffset(), p1.getOffset() - - // p0.getOffset()); - // - // if (mimeType.startsWith("text/html")) { - // htmlData = sw.toString(); - // } else { - // richText = sw.toString(); - // } - // } - // } catch (BadLocationException ble) { - // } catch (IOException ioe) { - // } - // } - // - // void removeText() { - // if ((p0 != null) && (p1 != null) && (p0.getOffset() != p1.getOffset())) { - // try { - // Document doc = c.getDocument(); - // doc.remove(p0.getOffset(), p1.getOffset() - p0.getOffset()); - // } catch (BadLocationException e) { - // } - // } - // } - // - // // ---- EditorKit other than plain or HTML text ----------------------- - // - // /** - // * If the EditorKit is not for text/plain or text/html, that format - // * is supported through the "richer flavors" part of BasicTransferable. - // */ - // protected DataFlavor[] getRicherFlavors() { - // if (richText == null) { - // return null; - // } - // - // try { - // DataFlavor[] flavors = new DataFlavor[3]; - // flavors[0] = new DataFlavor(mimeType + ";class=java.lang.String"); - // flavors[1] = new DataFlavor(mimeType + ";class=java.io.Reader"); - // flavors[2] = new DataFlavor(mimeType + - // ";class=java.io.InputStream;charset=unicode"); - // return flavors; - // } catch (ClassNotFoundException cle) { - // // fall through to unsupported (should not happen) - // } - // - // return null; - // } - // - // /** - // * The only richer format supported is the file list flavor - // */ - // protected Object getRicherData(DataFlavor flavor) throws - // UnsupportedFlavorException { - // if (richText == null) { - // return null; - // } - // - // if (String.class.equals(flavor.getRepresentationClass())) { - // return richText; - // } else if (Reader.class.equals(flavor.getRepresentationClass())) { - // return new StringReader(richText); - // } else if (InputStream.class.equals(flavor.getRepresentationClass())) { - // return new StringBufferInputStream(richText); - // } - // throw new UnsupportedFlavorException(flavor); - // } - // - // Position p0; - // Position p1; - // String mimeType; - // String richText; - // JTextComponent c; - // } - // - // } - - // /** - // * Creates a new UI. - // */ - // public JSTextUI() { - // // painted = false; - // } - // - // /** - // * Creates the object to use for a caret. By default an - // * instance of BasicCaret is created. This method - // * can be redefined to provide something else that implements - // * the InputPosition interface or a subclass of JCaret. - // * - // * @return the caret object - // */ - // protected Caret createCaret() { - // return new BasicCaret(); - // } - // - // /** - // * Creates the object to use for adding highlights. By default - // * an instance of BasicHighlighter is created. This method - // * can be redefined to provide something else that implements - // * the Highlighter interface or a subclass of DefaultHighlighter. - // * - // * @return the highlighter - // */ - // protected Highlighter createHighlighter() { - // return new BasicHighlighter(); - // } - // - // /** - // * Fetches the name of the keymap that will be installed/used - // * by default for this UI. This is implemented to create a - // * name based upon the classname. The name is the the name - // * of the class with the package prefix removed. - // * - // * @return the name - // */ - // protected String getKeymapName() { - // String nm = getClass().getName(); - // int index = nm.lastIndexOf('.'); - // if (index >= 0) { - // nm = nm.substring(index+1, nm.length()); - // } - // return nm; - // } - // - // /** - // * Creates the keymap to use for the text component, and installs - // * any necessary bindings into it. By default, the keymap is - // * shared between all instances of this type of TextUI. The - // * keymap has the name defined by the getKeymapName method. If the - // * keymap is not found, then DEFAULT_KEYMAP from JTextComponent is used. - // *

- // * The set of bindings used to create the keymap is fetched - // * from the UIManager using a key formed by combining the - // * {@link #getPropertyPrefix} method - // * and the string .keyBindings. The type is expected - // * to be JTextComponent.KeyBinding[]. - // * - // * @return the keymap - // * @see #getKeymapName - // * @see jsjavax.swing.text.JTextComponent - // */ - // protected Keymap createKeymap() { - // String nm = getKeymapName(); - // Keymap map = JTextComponent.getKeymap(nm); - // if (map == null) { - // Keymap parent = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP); - // map = JTextComponent.addKeymap(nm, parent); - // String prefix = getPropertyPrefix(); - // Object o = DefaultLookup.get(editor, this, - // prefix + ".keyBindings"); - // if ((o != null) && (o instanceof JTextComponent.KeyBinding[])) { - // JTextComponent.KeyBinding[] bindings = (JTextComponent.KeyBinding[]) o; - // JTextComponent.loadKeymap(map, bindings, getComponent().getActions()); - // } - // } - // return map; - // } - // - // /** - // * This method gets called when a bound property is changed - // * on the associated JTextComponent. This is a hook - // * which UI implementations may change to reflect how the - // * UI displays bound properties of JTextComponent subclasses. - // * This is implemented to do nothing (i.e. the response to - // * properties in JTextComponent itself are handled prior - // * to calling this method). - // * - // * This implementation updates the background of the text - // * component if the editable and/or enabled state changes. - // * - // * @param evt the property change event - // */ - // protected void propertyChange(PropertyChangeEvent evt) { - // if (evt.getPropertyName().equals("editable") || - // evt.getPropertyName().equals("enabled")) { - // - // updateBackground((JTextComponent)evt.getSource()); - // } - // } - // - // /** - // * Updates the background of the text component based on whether the - // * text component is editable and/or enabled. - // * - // * @param c the JTextComponent that needs its background color updated - // */ - // private void updateBackground(JTextComponent c) { - // // This is a temporary workaround. - // // This code does not correctly deal with Synth (Synth doesn't use - // // properties like this), nor does it deal with the situation where - // // the developer grabs the color from a JLabel and sets it as - // // the background for a JTextArea in all look and feels. The problem - // // scenario results if the Color obtained for the Label and TextArea - // // is ==, which is the case for the windows look and feel. - // // Until an appropriate solution is found, the code is being - // // reverted to what it was before the original fix. - // if (this instanceof sun.swing.plaf.synth.SynthUI || - // (c instanceof JTextArea)) { - // return; - // } - // Color background = c.getBackground(); - // if (background instanceof UIResource) { - // String prefix = getPropertyPrefix(); - // - // Color disabledBG = - // DefaultLookup.getColor(c, this, prefix + ".disabledBackground", null); - // Color inactiveBG = - // DefaultLookup.getColor(c, this, prefix + ".inactiveBackground", null); - // Color bg = - // DefaultLookup.getColor(c, this, prefix + ".background", null); - // - // /* In an ideal situation, the following check would not be necessary - // * and we would replace the color any time the previous color was a - // * UIResouce. However, it turns out that there is existing code that - // * uses the following inadvisable pattern to turn a text area into - // * what appears to be a multi-line label: - // * - // * JLabel label = new JLabel(); - // * JTextArea area = new JTextArea(); - // * area.setBackground(label.getBackground()); - // * area.setEditable(false); - // * - // * JLabel's default background is a UIResource. As such, just - // * checking for UIResource would have us always changing the - // * background away from what the developer wanted. - // * - // * Therefore, for JTextArea/JEditorPane, we'll additionally check - // * that the color we're about to replace matches one that was - // * installed by us from the UIDefaults. - // */ - // if ((c instanceof JTextArea || c instanceof JEditorPane) - // && background != disabledBG - // && background != inactiveBG - // && background != bg) { - // - // return; - // } - // - // Color newColor = null; - // if (!c.isEnabled()) { - // newColor = disabledBG; - // } - // if (newColor == null && !c.isEditable()) { - // newColor = inactiveBG; - // } - // if (newColor == null) { - // newColor = bg; - // } - // if (newColor != null && newColor != background) { - // c.setBackground(newColor); - // } - // } - // } - // - // /** - // * Gets the name used as a key to look up properties through the - // * UIManager. This is used as a prefix to all the standard - // * text properties. - // * - // * @return the name - // */ - // protected abstract String getPropertyPrefix(); - -} +/* + * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package swingjs.plaf; + +import swingjs.JSToolkit; +import swingjs.api.DOMNode; +import swingjs.api.JQueryObject; +import swingjs.api.JSFunction; +import jsjava.awt.Dimension; +import jsjava.awt.Insets; +import jsjava.awt.LayoutManager; +import jsjava.awt.event.ActionEvent; +import jsjavax.swing.AbstractAction; +import jsjavax.swing.Action; +import jsjavax.swing.ActionMap; +import jsjavax.swing.InputMap; +import jsjavax.swing.JComponent; +import jsjavax.swing.SwingUtilities; +import jsjavax.swing.UIManager; +import jsjavax.swing.plaf.ActionMapUIResource; +import jsjavax.swing.plaf.ComponentUI; +import jsjavax.swing.plaf.InputMapUIResource; +import jsjavax.swing.plaf.TextUI; +import jsjavax.swing.plaf.UIResource; +import jsjavax.swing.text.Caret; +import jsjavax.swing.text.DefaultEditorKit; +import jsjavax.swing.text.EditorKit; +import jsjavax.swing.text.JTextComponent; +import jsjavax.swing.text.TextAction; +//import jsjava.awt.KeyboardFocusManager; +//import jsjava.awt.datatransfer.DataFlavor; +//import jsjava.awt.datatransfer.Transferable; +//import jsjava.awt.datatransfer.UnsupportedFlavorException; +//import jsjava.awt.im.InputContext; +//import jsjava.io.IOException; +//import jsjava.io.InputStream; +//import jsjava.io.Reader; +//import jsjava.io.StringBufferInputStream; +//import jsjava.io.StringReader; +//import jsjava.io.StringWriter; +//import jsjavax.swing.plaf.basic.DragRecognitionSupport.BeforeDrag; + +/** + *

+ * Basis of a text components look-and-feel. This provides the basic editor view + * and controller services that may be useful when creating a look-and-feel for + * an extension of JTextComponent. + *

+ * Most state is held in the associated JTextComponent as bound + * properties, and the UI installs default values for the various properties. + * This default will install something for all of the properties. Typically, a + * LAF implementation will do more however. At a minimum, a LAF would generally + * install key bindings. + *

+ * This class also provides some concurrency support if the + * Document associated with the JTextComponent is a subclass of + * AbstractDocument. Access to the View (or View hierarchy) is + * serialized between any thread mutating the model and the Swing event thread + * (which is expected to render, do model/view coordinate translation, etc). + * Any access to the root view should first + * acquire a read-lock on the AbstractDocument and release that lock + * in a finally block. + *

+ * An important method to define is the {@link #getPropertyPrefix} method which + * is used as the basis of the keys used to fetch defaults from the UIManager. + * The string should reflect the type of TextUI (eg. TextField, TextArea, etc) + * without the particular LAF part of the name (eg Metal, Motif, etc). + *

+ * To build a view of the model, one of the following strategies can be + * employed. + *

    + *
  1. + * One strategy is to simply redefine the ViewFactory interface in the UI. By + * default, this UI itself acts as the factory for View implementations. This is + * useful for simple factories. To do this reimplement the {@link #create} + * method. + *
  2. + * A common strategy for creating more complex types of documents is to have the + * EditorKit implementation return a factory. Since the EditorKit ties all of + * the pieces necessary to maintain a type of document, the factory is typically + * an important part of that and should be produced by the EditorKit + * implementation. + *
+ *

+ * Warning: Serialized objects of this class will not be + * compatible with future Swing releases. The current serialization support is + * appropriate for short term storage or RMI between applications running the + * same version of Swing. As of 1.4, support for long term storage of all + * JavaBeansTM has been added to the + * java.beans package. Please see {@link jsjava.beans.XMLEncoder}. + * + * @author Timothy Prinzing + * @author Shannon Hickey (drag and drop) + */ +public abstract class JSTextUI extends JSComponentUI {// implements {ViewFactory + // { + @SuppressWarnings("unused") + protected void setFocusable() { + JQueryObject node = $(focusNode); + Object me = this; + + /** + * @j2sNative + * + * node.focus(function() {me.notifyFocus(true)}); + * node.blur(function() {me.notifyFocus(false)}); + */ + {} + } + + + protected String getComponentText() { + return currentText = ((JTextComponent) c).getText(); + } + + protected void bindKeys(DOMNode domNode) { + JSFunction f = null; + JSEventHandler me = this; + if (!((JTextComponent) c).isEditable()) + return; + /** + * @j2sNative + * + * f = function(event) { me.handleJSEvent(me.domNode, 401, event) + * } + */ + { + System.out.println(me); + } + $(domNode).bind("keydown keypress keyup", f); + + // TODO Auto-generated method stub + + } + + /** + * Initializes component properties, e.g. font, foreground, background, caret + * color, selection color, selected text color, disabled text color, and + * border color. The font, foreground, and background properties are only set + * if their current value is either null or a UIResource, other properties are + * set if the current value is null. + * + * @see #uninstallDefaults + * @see #installUI + */ + protected void installDefaults() { + // String prefix = getPropertyPrefix(); + // Font f = editor.getFont(); + // if ((f == null) || (f instanceof UIResource)) { + // editor.setFont(UIManager.getFont(prefix + ".font")); + // } + // + // Color bg = editor.getBackground(); + // if ((bg == null) || (bg instanceof UIResource)) { + // editor.setBackground(UIManager.getColor(prefix + ".background")); + // } + // + // Color fg = editor.getForeground(); + // if ((fg == null) || (fg instanceof UIResource)) { + // editor.setForeground(UIManager.getColor(prefix + ".foreground")); + // } + // + // Color color = editor.getCaretColor(); + // if ((color == null) || (color instanceof UIResource)) { + // editor.setCaretColor(UIManager.getColor(prefix + ".caretForeground")); + // } + // + // Color s = editor.getSelectionColor(); + // if ((s == null) || (s instanceof UIResource)) { + // editor.setSelectionColor(UIManager.getColor(prefix + + // ".selectionBackground")); + // } + // + // Color sfg = editor.getSelectedTextColor(); + // if ((sfg == null) || (sfg instanceof UIResource)) { + // editor.setSelectedTextColor(UIManager.getColor(prefix + + // ".selectionForeground")); + // } + // + // Color dfg = editor.getDisabledTextColor(); + // if ((dfg == null) || (dfg instanceof UIResource)) { + // editor.setDisabledTextColor(UIManager.getColor(prefix + + // ".inactiveForeground")); + // } + // + // Border b = editor.getBorder(); + // if ((b == null) || (b instanceof UIResource)) { + // editor.setBorder(UIManager.getBorder(prefix + ".border")); + // } + // + // Insets margin = editor.getMargin(); + // if (margin == null || margin instanceof UIResource) { + // editor.setMargin(UIManager.getInsets(prefix + ".margin")); + // } + // + // updateCursor(); + } + + private void installDefaults2() { + // editor.addMouseListener(dragListener); + // editor.addMouseMotionListener(dragListener); + // + // String prefix = getPropertyPrefix(); + + Caret caret = editor.getCaret(); + if (caret == null || caret instanceof UIResource) { + editor.setCaret(new JSCaret()); + } + // + // Highlighter highlighter = editor.getHighlighter(); + // if (highlighter == null || highlighter instanceof UIResource) { + // editor.setHighlighter(createHighlighter()); + // } + // + // TransferHandler th = editor.getTransferHandler(); + // if (th == null || th instanceof UIResource) { + // editor.setTransferHandler(getTransferHandler()); + // } + } + + /** + * called by JmolCore.js + * + * @return handled + */ + public boolean handleJSEvent(Object target, int eventType, Object jQueryEvent) { + System.out.println("Handling for " + id + " " + eventType + " " + + jQueryEvent); + return updateHandler.handleJSEvent(this, eventType, jQueryEvent); + } + + /** + * Sets the component properties that haven't been explicitly overridden to + * null. A property is considered overridden if its current value is not a + * UIResource. + * + * @see #installDefaults + * @see #uninstallUI + */ + protected void uninstallDefaults() { + // editor.removeMouseListener(dragListener); + // editor.removeMouseMotionListener(dragListener); + // + if (editor.getCaretColor() instanceof UIResource) { + editor.setCaretColor(null); + } + + if (editor.getSelectionColor() instanceof UIResource) { + editor.setSelectionColor(null); + } + + if (editor.getDisabledTextColor() instanceof UIResource) { + editor.setDisabledTextColor(null); + } + + if (editor.getSelectedTextColor() instanceof UIResource) { + editor.setSelectedTextColor(null); + } + + if (editor.getBorder() instanceof UIResource) { + editor.setBorder(null); + } + + if (editor.getMargin() instanceof UIResource) { + editor.setMargin(null); + } + + // if (editor.getCaret() instanceof UIResource) { + // editor.setCaret(null); + // } + // + // if (editor.getHighlighter() instanceof UIResource) { + // editor.setHighlighter(null); + // } + // + // if (editor.getTransferHandler() instanceof UIResource) { + // editor.setTransferHandler(null); + // } + // + // if (editor.getCursor() instanceof UIResource) { + // editor.setCursor(null); + // } + } + + protected void installKeyboardActions() { + // backward compatibility support... keymaps for the UI + // are now installed in the more friendly input map. + // editor.setKeymap(createKeymap()); + + InputMap km = getInputMap(); + if (km != null) { + SwingUtilities.replaceUIInputMap(editor, JComponent.WHEN_FOCUSED, km); + } + + ActionMap map = getActionMap(); + if (map != null) { + SwingUtilities.replaceUIActionMap(editor, map); + } + + // updateFocusAcceleratorBinding(false); + } + + /** + * Get the InputMap to use for the UI. + */ + InputMap getInputMap() { + InputMap map = new InputMapUIResource(); + + // InputMap shared = + // (InputMap)DefaultLookup.get(editor, this, + // getPropertyPrefix() + ".focusInputMap"); + // if (shared != null) { + // map.setParent(shared); + // } + return map; + } + + // /** + // * Invoked when the focus accelerator changes, this will update the + // * key bindings as necessary. + // */ + // void updateFocusAcceleratorBinding(boolean changed) { + // char accelerator = editor.getFocusAccelerator(); + // + // if (changed || accelerator != '\0') { + // InputMap km = SwingUtilities.getUIInputMap + // (editor, JComponent.WHEN_IN_FOCUSED_WINDOW); + // + // if (km == null && accelerator != '\0') { + // km = new ComponentInputMapUIResource(editor); + // SwingUtilities.replaceUIInputMap(editor, JComponent. + // WHEN_IN_FOCUSED_WINDOW, km); + // ActionMap am = getActionMap(); + // SwingUtilities.replaceUIActionMap(editor, am); + // } + // if (km != null) { + // km.clear(); + // if (accelerator != '\0') { + // km.put(KeyStroke.getKeyStroke(accelerator, + // ActionEvent.ALT_MASK), + // "requestFocus"); + // } + // } + // } + // } + // + // + // /** + // * Invoked when editable property is changed. + // * + // * removing 'TAB' and 'SHIFT-TAB' from traversalKeysSet in case + // * editor is editable + // * adding 'TAB' and 'SHIFT-TAB' to traversalKeysSet in case + // * editor is non editable + // */ + // + // void updateFocusTraversalKeys() { + // /* + // * Fix for 4514331 Non-editable JTextArea and similar + // * should allow Tab to keyboard - accessibility + // */ + // EditorKit editorKit = getEditorKit(editor); + // if ( editorKit != null + // && editorKit instanceof DefaultEditorKit) { + // Set storedForwardTraversalKeys = editor. + // getFocusTraversalKeys(KeyboardFocusManager. + // FORWARD_TRAVERSAL_KEYS); + // Set storedBackwardTraversalKeys = editor. + // getFocusTraversalKeys(KeyboardFocusManager. + // BACKWARD_TRAVERSAL_KEYS); + // Set forwardTraversalKeys = + // new HashSet(storedForwardTraversalKeys); + // Set backwardTraversalKeys = + // new HashSet(storedBackwardTraversalKeys); + // if (editor.isEditable()) { + // forwardTraversalKeys. + // remove(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0)); + // backwardTraversalKeys. + // remove(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, + // InputEvent.SHIFT_MASK)); + // } else { + // forwardTraversalKeys.add(KeyStroke. + // getKeyStroke(KeyEvent.VK_TAB, 0)); + // backwardTraversalKeys. + // add(KeyStroke. + // getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK)); + // } + // LookAndFeel.installProperty(editor, + // "focusTraversalKeysForward", + // forwardTraversalKeys); + // LookAndFeel.installProperty(editor, + // "focusTraversalKeysBackward", + // backwardTraversalKeys); + // } + // + // } + + // /** + // * As needed updates cursor for the target editor. + // */ + // private void updateCursor() { + // if ((! editor.isCursorSet()) + // || editor.getCursor() instanceof UIResource) { + // Cursor cursor = (editor.isEditable()) ? textCursor : null; + // editor.setCursor(cursor); + // } + // } + // + // /** + // * Returns the TransferHandler that will be installed if + // * their isn't one installed on the JTextComponent. + // */ + // TransferHandler getTransferHandler() { + // return defaultTransferHandler; + // } + // + /** + * Fetch an action map to use. + */ + ActionMap getActionMap() { + String mapName = classID + ".actionMap"; + ActionMap map = (ActionMap) UIManager.get(mapName); + if (map == null) { + map = createActionMap(); + if (map != null) { + UIManager.getLookAndFeelDefaults().put(mapName, map); + } + } + return map; + } + // ActionMap componentMap = new ActionMapUIResource(); + // componentMap.put("requestFocus", new FocusAction()); + // /* + // * fix for bug 4515750 + // * JTextField & non-editable JTextArea bind return key - default btn not + // accessible + // * + // * Wrap the return action so that it is only enabled when the + // * component is editable. This allows the default button to be + // * processed when the text component has focus and isn't editable. + // * + // */ + // if (getEditorKit(editor) instanceof DefaultEditorKit) { + // if (map != null) { + // Object obj = map.get(DefaultEditorKit.insertBreakAction); + // if (obj != null + // && obj instanceof DefaultEditorKit.InsertBreakAction) { + // Action action = new TextActionWrapper((TextAction)obj); + // componentMap.put(action.getValue(Action.NAME),action); + // } + // } + // } + // if (map != null) { + // componentMap.setParent(map); + // } + // return componentMap; + // } + // + /** + * Create a default action map. This is basically the set of actions found + * exported by the component. + */ + /** + * @return + */ + ActionMap createActionMap() { + ActionMap map = new ActionMapUIResource(); + Action[] actions = editor.getActions();//defaultKit.getActions(); // SwingJS was editor.getEditorKit().getActions() + // System.out.println("building map for UI: " + getPropertyPrefix()); + int n = actions.length; + for (int i = 0; i < n; i++) { + Action a = actions[i]; + map.put(a.getValue(Action.NAME), a); + // System.out.println(" " + a.getValue(Action.NAME)); + } + // map.put(TransferHandler.getCutAction().getValue(Action.NAME), + // TransferHandler.getCutAction()); + // map.put(TransferHandler.getCopyAction().getValue(Action.NAME), + // TransferHandler.getCopyAction()); + // map.put(TransferHandler.getPasteAction().getValue(Action.NAME), + // TransferHandler.getPasteAction()); + return map; + } + + protected void uninstallKeyboardActions() { + editor.setKeymap(null); + SwingUtilities.replaceUIInputMap(editor, JComponent.WHEN_IN_FOCUSED_WINDOW, + null); + SwingUtilities.replaceUIActionMap(editor, null); + } + + // /** + // * Paints a background for the view. This will only be + // * called if isOpaque() on the associated component is + // * true. The default is to paint the background color + // * of the component. + // * + // * @param g the graphics context + // */ + // protected void paintBackground(Graphics g) { + // g.setColor(editor.getBackground()); + // g.fillRect(0, 0, editor.getWidth(), editor.getHeight()); + // } + // + /** + * Fetches the text component associated with this UI implementation. This + * will be null until the ui has been installed. + * + * @return the editor component + */ + protected final JTextComponent getComponent() { + return editor; + } + + // /** + // * Flags model changes. + // * This is called whenever the model has changed. + // * It is implemented to rebuild the view hierarchy + // * to represent the default root element of the + // * associated model. + // */ + // protected void modelChanged() { + // // create a view hierarchy + // ViewFactory f = rootView.getViewFactory(); + // Document doc = editor.getDocument(); + // Element elem = doc.getDefaultRootElement(); + // setView(f.create(elem)); + // } + // + // /** + // * Sets the current root of the view hierarchy and calls invalidate(). + // * If there were any child components, they will be removed (i.e. + // * there are assumed to have come from components embedded in views). + // * + // * @param v the root view + // */ + // protected final void setView(View v) { + // rootView.setView(v); + // painted = false; + // editor.revalidate(); + // editor.repaint(); + // } + // + // /** + // * Paints the interface safely with a guarantee that + // * the model won't change from the view of this thread. + // * This does the following things, rendering from + // * back to front. + // *

    + // *
  1. + // * If the component is marked as opaque, the background + // * is painted in the current background color of the + // * component. + // *
  2. + // * The highlights (if any) are painted. + // *
  3. + // * The view hierarchy is painted. + // *
  4. + // * The caret is painted. + // *
+ // * + // * @param g the graphics context + // */ + // protected void paintSafely(Graphics g) { + // painted = true; + // Highlighter highlighter = editor.getHighlighter(); + // Caret caret = editor.getCaret(); + // + // // paint the background + // if (editor.isOpaque()) { + // paintBackground(g); + // } + // + // // paint the highlights + // if (highlighter != null) { + // highlighter.paint(g); + // } + // + // // paint the view hierarchy + // Rectangle alloc = getVisibleEditorRect(); + // if (alloc != null) { + // rootView.paint(g, alloc); + // } + // + // // paint the caret + // if (caret != null) { + // caret.paint(g); + // } + // + // if (dropCaret != null) { + // dropCaret.paint(g); + // } + // } + + // --- ComponentUI methods -------------------------------------------- + + TextListener updateHandler; + + /** + * Installs the UI for a component. This does the following things. + *
    + *
  1. + * Set the associated component to opaque (can be changed easily by a subclass + * or on JTextComponent directly), which is the most common case. This will + * cause the component's background color to be painted. + *
  2. + * Install the default caret and highlighter into the associated component. + *
  3. + * Attach to the editor and model. If there is no model, a default one is + * created. + *
  4. + * create the view factory and the view hierarchy used to represent the model. + *
+ * + * @param c + * the editor component + * @see ComponentUI#installUI + */ + protected void installJSUI() { + editor = (JTextComponent) c; + updateHandler = new TextListener(this, editor); + + // install defaults + installDefaults(); + installDefaults2(); + + // // This is a workaround as these should not override what synth has + // // set them to + // if (!(this instanceof sun.swing.plaf.synth.SynthUI)){ + // // common case is background painted... this can + // // easily be changed by subclasses or from outside + // // of the component. + // LookAndFeel.installProperty(editor, "opaque", Boolean.TRUE); + // LookAndFeel.installProperty(editor, "autoscrolls", Boolean.TRUE); + // } + // + // attach to the model and editor + // Document doc = editor.getDocument(); + // if (doc == null) { + // // no model, create a default one. This will + // // fire a notification to the updateHandler + // // which takes care of the rest. + // editor.setDocument(getEditorKit(editor).createDefaultDocument()); + // } else { + // // doc.addDocumentListener(updateHandler); + // // modelChanged(); + // } + + // install keymap + installListeners(editor); + installKeyboardActions(); + + // LayoutManager oldLayout = editor.getLayout(); + // if ((oldLayout == null) || (oldLayout instanceof UIResource)) { + // // by default, use default LayoutManger implementation that + // // will position the components associated with a View object. + // editor.setLayout(updateHandler); + // } + // + // updateBackground(editor); + } + + /** + * Deinstalls the UI for a component. This removes the listeners, uninstalls + * the highlighter, removes views, and nulls out the keymap. + * + * @param c + * the editor component + * @see ComponentUI#uninstallUI + */ + public void uninstallJSUI() { + // detach from the model + // editor.removePropertyChangeListener(updateHandler); + // editor.getDocument().removeDocumentListener(updateHandler); + + // view part + // painted = false; + uninstallDefaults(); + // rootView.setView(null); + c.removeAll(); + LayoutManager lm = c.getLayout(); + if (lm instanceof UIResource) { + c.setLayout(null); + } + + // controller part + uninstallKeyboardActions(); + uninstallListeners(editor); + + editor = null; + updateHandler = null; + } + + protected void installListeners(JTextComponent b) { + TextListener listener = updateHandler; + b.addMouseListener(listener); + b.addMouseMotionListener(listener); + b.addFocusListener(listener); + b.addPropertyChangeListener(listener); + // SwingJS there won't be a document yet; this is in constructor + // b.getDocument().addDocumentListener(listener); + } + + protected void uninstallListeners(JTextComponent b) { + TextListener listener = updateHandler; + b.removeMouseListener(listener); + b.removeMouseMotionListener(listener); + b.removeFocusListener(listener); + b.removePropertyChangeListener(listener); + b.getDocument().removeDocumentListener(listener); + } + + // /** + // * Superclass paints background in an uncontrollable way + // * (i.e. one might want an image tiled into the background). + // * To prevent this from happening twice, this method is + // * reimplemented to simply paint. + // *

+ // * NOTE: Superclass is also not thread-safe in + // * it's rendering of the background, although that's not + // * an issue with the default rendering. + // */ + // public void update(Graphics g, JComponent c) { + // paint(g, c); + // } + // + // /** + // * Paints the interface. This is routed to the + // * paintSafely method under the guarantee that + // * the model won't change from the view of this thread + // * while it's rendering (if the associated model is + // * derived from AbstractDocument). This enables the + // * model to potentially be updated asynchronously. + // * + // * @param g the graphics context + // * @param c the editor component + // */ + // public final void paint(Graphics g, JComponent c) { + // if ((rootView.getViewCount() > 0) && (rootView.getView(0) != null)) { + // Document doc = editor.getDocument(); + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readLock(); + // } + // try { + // paintSafely(g); + // } finally { + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readUnlock(); + // } + // } + // } + // } + + // /** + // * Gets the preferred size for the editor component. If the component + // * has been given a size prior to receiving this request, it will + // * set the size of the view hierarchy to reflect the size of the component + // * before requesting the preferred size of the view hierarchy. This + // * allows formatted views to format to the current component size before + // * answering the request. Other views don't care about currently formatted + // * size and give the same answer either way. + // * + // * @param c the editor component + // * @return the size + // */ + // public Dimension getPreferredSize(JComponent c) { + // Dimension d = c.getSize(); + // // Document doc = editor.getDocument(); + // // Insets i = c.getInsets(); + // // + // // if (doc instanceof AbstractDocument) { + // // ((AbstractDocument)doc).readLock(); + // // } + // // try { + // // if ((d.width > (i.left + i.right)) && (d.height > (i.top + i.bottom))) { + // // rootView.setSize(d.width - i.left - i.right, d.height - i.top - + // i.bottom); + // // } + // // else if (d.width == 0 && d.height == 0) { + // // // Probably haven't been layed out yet, force some sort of + // // // initial sizing. + // // rootView.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE); + // // } + // // d.width = (int) Math.min((long) rootView.getPreferredSpan(View.X_AXIS) + + // // (long) i.left + (long) i.right, Integer.MAX_VALUE); + // // d.height = (int) Math.min((long) rootView.getPreferredSpan(View.Y_AXIS) + // + + // // (long) i.top + (long) i.bottom, Integer.MAX_VALUE); + // // } finally { + // // if (doc instanceof AbstractDocument) { + // // ((AbstractDocument)doc).readUnlock(); + // // } + // // } + // return d; + // } + + /** + * Gets the minimum size for the editor component. + * + * @param c + * the editor component + * @return the size + */ + public Dimension getMinimumSize(JComponent c) { + Dimension d = getPreferredSize();// new Dimension(); + // Document doc = editor.getDocument(); + Insets i = c.getInsets(); + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readLock(); + // } + // try { + + d.width += i.left + i.right; + d.height += i.top + i.bottom; + + // d.width = (int) rootView.getMinimumSpan(View.X_AXIS) + i.left + i.right; + // d.height = (int) rootView.getMinimumSpan(View.Y_AXIS) + i.top + i.bottom; + // } finally { + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readUnlock(); + // } + // } + return d; + } + + /** + * Gets the maximum size for the editor component. + * + * @param c + * the editor component + * @return the size + */ + public Dimension getMaximumSize(JComponent c) { + // SwingJS TODO + return getMinimumSize(c); + + // Document doc = editor.getDocument(); + // Insets i = c.getInsets(); + // Dimension d = new Dimension(); + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readLock(); + // } + // try { + // d.width = (int) Math.min((long) rootView.getMaximumSpan(View.X_AXIS) + + // (long) i.left + (long) i.right, Integer.MAX_VALUE); + // d.height = (int) Math.min((long) rootView.getMaximumSpan(View.Y_AXIS) + + // (long) i.top + (long) i.bottom, Integer.MAX_VALUE); + // } finally { + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readUnlock(); + // } + // } + // return d; + } + + // ---- TextUI methods ------------------------------------------- + + // + // /** + // * Gets the allocation to give the root View. Due + // * to an unfortunate set of historical events this + // * method is inappropriately named. The Rectangle + // * returned has nothing to do with visibility. + // * The component must have a non-zero positive size for + // * this translation to be computed. + // * + // * @return the bounding box for the root view + // */ + // protected Rectangle getVisibleEditorRect() { + // Rectangle alloc = editor.getBounds(); + // if ((alloc.width > 0) && (alloc.height > 0)) { + // alloc.x = alloc.y = 0; + // Insets insets = editor.getInsets(); + // alloc.x += insets.left; + // alloc.y += insets.top; + // alloc.width -= insets.left + insets.right; + // alloc.height -= insets.top + insets.bottom; + // return alloc; + // } + // return null; + // } + // + // /** + // * Converts the given location in the model to a place in + // * the view coordinate system. + // * The component must have a non-zero positive size for + // * this translation to be computed. + // * + // * @param tc the text component for which this UI is installed + // * @param pos the local location in the model to translate >= 0 + // * @return the coordinates as a rectangle, null if the model is not painted + // * @exception BadLocationException if the given position does not + // * represent a valid location in the associated document + // * @see TextUI#modelToView + // */ + // public Rectangle modelToView(JTextComponent tc, int pos) throws + // BadLocationException { + // return modelToView(tc, pos, Position.Bias.Forward); + // } + // + // /** + // * Converts the given location in the model to a place in + // * the view coordinate system. + // * The component must have a non-zero positive size for + // * this translation to be computed. + // * + // * @param tc the text component for which this UI is installed + // * @param pos the local location in the model to translate >= 0 + // * @return the coordinates as a rectangle, null if the model is not painted + // * @exception BadLocationException if the given position does not + // * represent a valid location in the associated document + // * @see TextUI#modelToView + // */ + // public Rectangle modelToView(JTextComponent tc, int pos, Position.Bias + // bias) throws BadLocationException { + // Document doc = editor.getDocument(); + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readLock(); + // } + // try { + // Rectangle alloc = getVisibleEditorRect(); + // if (alloc != null) { + // rootView.setSize(alloc.width, alloc.height); + // Shape s = rootView.modelToView(pos, alloc, bias); + // if (s != null) { + // return s.getBounds(); + // } + // } + // } finally { + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readUnlock(); + // } + // } + // return null; + // } + // + // /** + // * Converts the given place in the view coordinate system + // * to the nearest representative location in the model. + // * The component must have a non-zero positive size for + // * this translation to be computed. + // * + // * @param tc the text component for which this UI is installed + // * @param pt the location in the view to translate. This + // * should be in the same coordinate system as the mouse events. + // * @return the offset from the start of the document >= 0, + // * -1 if not painted + // * @see TextUI#viewToModel + // */ + // public int viewToModel(JTextComponent tc, Point pt) { + // return viewToModel(tc, pt, discardBias); + // } + // + // /** + // * Converts the given place in the view coordinate system + // * to the nearest representative location in the model. + // * The component must have a non-zero positive size for + // * this translation to be computed. + // * + // * @param tc the text component for which this UI is installed + // * @param pt the location in the view to translate. This + // * should be in the same coordinate system as the mouse events. + // * @return the offset from the start of the document >= 0, + // * -1 if the component doesn't yet have a positive size. + // * @see TextUI#viewToModel + // */ + // public int viewToModel(JTextComponent tc, Point pt, + // Position.Bias[] biasReturn) { + // int offs = -1; + // Document doc = editor.getDocument(); + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readLock(); + // } + // try { + // Rectangle alloc = getVisibleEditorRect(); + // if (alloc != null) { + // rootView.setSize(alloc.width, alloc.height); + // offs = rootView.viewToModel(pt.x, pt.y, alloc, biasReturn); + // } + // } finally { + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readUnlock(); + // } + // } + // return offs; + // } + + // /** + // * {@inheritDoc} + // */ + // public int getNextVisualPositionFrom(JTextComponent t, int pos, + // Position.Bias b, int direction, Position.Bias[] biasRet) + // throws BadLocationException{ + // Document doc = editor.getDocument(); + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readLock(); + // } + // try { + // if (painted) { + // Rectangle alloc = getVisibleEditorRect(); + // if (alloc != null) { + // rootView.setSize(alloc.width, alloc.height); + // } + // return rootView.getNextVisualPositionFrom(pos, b, alloc, direction, + // biasRet); + // } + // } finally { + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readUnlock(); + // } + // } + // return -1; + // } + // + // /** + // * Causes the portion of the view responsible for the + // * given part of the model to be repainted. Does nothing if + // * the view is not currently painted. + // * + // * @param tc the text component for which this UI is installed + // * @param p0 the beginning of the range >= 0 + // * @param p1 the end of the range >= p0 + // * @see TextUI#damageRange + // */ + // public void damageRange(JTextComponent tc, int p0, int p1) { + // damageRange(tc, p0, p1, Position.Bias.Forward, Position.Bias.Backward); + // } + // + // /** + // * Causes the portion of the view responsible for the + // * given part of the model to be repainted. + // * + // * @param p0 the beginning of the range >= 0 + // * @param p1 the end of the range >= p0 + // */ + // public void damageRange(JTextComponent t, int p0, int p1, + // Position.Bias p0Bias, Position.Bias p1Bias) { + // if (painted) { + // Rectangle alloc = getVisibleEditorRect(); + // if (alloc != null) { + // Document doc = t.getDocument(); + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readLock(); + // } + // try { + // rootView.setSize(alloc.width, alloc.height); + // Shape toDamage = rootView.modelToView(p0, p0Bias, + // p1, p1Bias, alloc); + // Rectangle rect = (toDamage instanceof Rectangle) ? + // (Rectangle)toDamage : toDamage.getBounds(); + // editor.repaint(rect.x, rect.y, rect.width, rect.height); + // } catch (BadLocationException e) { + // } finally { + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readUnlock(); + // } + // } + // } + // } + // } + + /** + * Fetches the EditorKit for the UI. + * + * @param tc + * the text component for which this UI is installed + * @return the editor capabilities + * @see TextUI#getEditorKit + */ + public EditorKit getEditorKit(JTextComponent tc) { + return defaultKit; + } + + // /** + // * Fetches a View with the allocation of the associated + // * text component (i.e. the root of the hierarchy) that + // * can be traversed to determine how the model is being + // * represented spatially. + // *

+ // * NOTE:The View hierarchy can + // * be traversed from the root view, and other things + // * can be done as well. Things done in this way cannot + // * be protected like simple method calls through the TextUI. + // * Therefore, proper operation in the presence of concurrency + // * must be arranged by any logic that calls this method! + // * + // * + // * @param tc the text component for which this UI is installed + // * @return the view + // * @see TextUI#getRootView + // */ + // public View getRootView(JTextComponent tc) { + // return rootView; + // } + + // /** + // * Returns the string to be used as the tooltip at the passed in location. + // * This forwards the method onto the root View. + // * + // * @see jsjavax.swing.text.JTextComponent#getToolTipText + // * @see jsjavax.swing.text.View#getToolTipText + // * @since 1.4 + // */ + // public String getToolTipText(JTextComponent t, Point pt) { + // if (!painted) { + // return null; + // } + // Document doc = editor.getDocument(); + // String tt = null; + // Rectangle alloc = getVisibleEditorRect(); + // + // if (alloc != null) { + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readLock(); + // } + // try { + // tt = rootView.getToolTipText(pt.x, pt.y, alloc); + // } finally { + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readUnlock(); + // } + // } + // } + // return tt; + // } + // + // --- ViewFactory methods ------------------------------ + // + // /** + // * Creates a view for an element. + // * If a subclass wishes to directly implement the factory + // * producing the view(s), it should reimplement this + // * method. By default it simply returns null indicating + // * it is unable to represent the element. + // * + // * @param elem the element + // * @return the view + // */ + // public View create(Element elem) { + // return null; + // } + // + // /** + // * Creates a view for an element. + // * If a subclass wishes to directly implement the factory + // * producing the view(s), it should reimplement this + // * method. By default it simply returns null indicating + // * it is unable to represent the part of the element. + // * + // * @param elem the element + // * @param p0 the starting offset >= 0 + // * @param p1 the ending offset >= p0 + // * @return the view + // */ + // public View create(Element elem, int p0, int p1) { + // return null; + // } + // + // public static class BasicCaret extends DefaultCaret implements UIResource + // {} + // + // public static class BasicHighlighter extends DefaultHighlighter implements + // UIResource {} + // + // static class BasicCursor extends Cursor implements UIResource { + // BasicCursor(int type) { + // super(type); + // } + // + // BasicCursor(String name) { + // super(name); + // } + // } + // + // private static BasicCursor textCursor = new + // BasicCursor(Cursor.TEXT_CURSOR); + // ----- member variables --------------------------------------- + + private static final EditorKit defaultKit = new DefaultEditorKit(); + transient JTextComponent editor; + protected boolean editable = true; + + // transient boolean painted; + // transient RootView rootView = new RootView(); + // transient UpdateHandler updateHandler = new UpdateHandler(); + // private static final TransferHandler defaultTransferHandler = new + // TextTransferHandler(); + // private final DragListener dragListener = getDragListener(); + // private static final Position.Bias[] discardBias = new Position.Bias[1]; + // private DefaultCaret dropCaret; + + // /** + // * Root view that acts as a gateway between the component + // * and the View hierarchy. + // */ + // class RootView extends View { + // + // RootView() { + // super(null); + // } + // + // void setView(View v) { + // View oldView = view; + // view = null; + // if (oldView != null) { + // // get rid of back reference so that the old + // // hierarchy can be garbage collected. + // oldView.setParent(null); + // } + // if (v != null) { + // v.setParent(this); + // } + // view = v; + // } + // + // /** + // * Fetches the attributes to use when rendering. At the root + // * level there are no attributes. If an attribute is resolved + // * up the view hierarchy this is the end of the line. + // */ + // public AttributeSet getAttributes() { + // return null; + // } + // + // /** + // * Determines the preferred span for this view along an axis. + // * + // * @param axis may be either X_AXIS or Y_AXIS + // * @return the span the view would like to be rendered into. + // * Typically the view is told to render into the span + // * that is returned, although there is no guarantee. + // * The parent may choose to resize or break the view. + // */ + // public float getPreferredSpan(int axis) { + // if (view != null) { + // return view.getPreferredSpan(axis); + // } + // return 10; + // } + // + // /** + // * Determines the minimum span for this view along an axis. + // * + // * @param axis may be either X_AXIS or Y_AXIS + // * @return the span the view would like to be rendered into. + // * Typically the view is told to render into the span + // * that is returned, although there is no guarantee. + // * The parent may choose to resize or break the view. + // */ + // public float getMinimumSpan(int axis) { + // if (view != null) { + // return view.getMinimumSpan(axis); + // } + // return 10; + // } + // + // /** + // * Determines the maximum span for this view along an axis. + // * + // * @param axis may be either X_AXIS or Y_AXIS + // * @return the span the view would like to be rendered into. + // * Typically the view is told to render into the span + // * that is returned, although there is no guarantee. + // * The parent may choose to resize or break the view. + // */ + // public float getMaximumSpan(int axis) { + // return Integer.MAX_VALUE; + // } + // + // /** + // * Specifies that a preference has changed. + // * Child views can call this on the parent to indicate that + // * the preference has changed. The root view routes this to + // * invalidate on the hosting component. + // *

+ // * This can be called on a different thread from the + // * event dispatching thread and is basically unsafe to + // * propagate into the component. To make this safe, + // * the operation is transferred over to the event dispatching + // * thread for completion. It is a design goal that all view + // * methods be safe to call without concern for concurrency, + // * and this behavior helps make that true. + // * + // * @param child the child view + // * @param width true if the width preference has changed + // * @param height true if the height preference has changed + // */ + // public void preferenceChanged(View child, boolean width, boolean height) { + // editor.revalidate(); + // } + // + // /** + // * Determines the desired alignment for this view along an axis. + // * + // * @param axis may be either X_AXIS or Y_AXIS + // * @return the desired alignment, where 0.0 indicates the origin + // * and 1.0 the full span away from the origin + // */ + // public float getAlignment(int axis) { + // if (view != null) { + // return view.getAlignment(axis); + // } + // return 0; + // } + // + // /** + // * Renders the view. + // * + // * @param g the graphics context + // * @param allocation the region to render into + // */ + // public void paint(Graphics g, Shape allocation) { + // if (view != null) { + // Rectangle alloc = (allocation instanceof Rectangle) ? + // (Rectangle)allocation : allocation.getBounds(); + // setSize(alloc.width, alloc.height); + // view.paint(g, allocation); + // } + // } + // + // /** + // * Sets the view parent. + // * + // * @param parent the parent view + // */ + // public void setParent(View parent) { + // throw new Error("Can't set parent on root view"); + // } + // + // /** + // * Returns the number of views in this view. Since + // * this view simply wraps the root of the view hierarchy + // * it has exactly one child. + // * + // * @return the number of views + // * @see #getView + // */ + // public int getViewCount() { + // return 1; + // } + // + // /** + // * Gets the n-th view in this container. + // * + // * @param n the number of the view to get + // * @return the view + // */ + // public View getView(int n) { + // return view; + // } + // + // /** + // * Returns the child view index representing the given position in + // * the model. This is implemented to return the index of the only + // * child. + // * + // * @param pos the position >= 0 + // * @return index of the view representing the given position, or + // * -1 if no view represents that position + // * @since 1.3 + // */ + // public int getViewIndex(int pos, Position.Bias b) { + // return 0; + // } + // + // /** + // * Fetches the allocation for the given child view. + // * This enables finding out where various views + // * are located, without assuming the views store + // * their location. This returns the given allocation + // * since this view simply acts as a gateway between + // * the view hierarchy and the associated component. + // * + // * @param index the index of the child + // * @param a the allocation to this view. + // * @return the allocation to the child + // */ + // public Shape getChildAllocation(int index, Shape a) { + // return a; + // } + // + // /** + // * Provides a mapping from the document model coordinate space + // * to the coordinate space of the view mapped to it. + // * + // * @param pos the position to convert + // * @param a the allocated region to render into + // * @return the bounding box of the given position + // */ + // public Shape modelToView(int pos, Shape a, Position.Bias b) throws + // BadLocationException { + // if (view != null) { + // return view.modelToView(pos, a, b); + // } + // return null; + // } + // + // /** + // * Provides a mapping from the document model coordinate space + // * to the coordinate space of the view mapped to it. + // * + // * @param p0 the position to convert >= 0 + // * @param b0 the bias toward the previous character or the + // * next character represented by p0, in case the + // * position is a boundary of two views. + // * @param p1 the position to convert >= 0 + // * @param b1 the bias toward the previous character or the + // * next character represented by p1, in case the + // * position is a boundary of two views. + // * @param a the allocated region to render into + // * @return the bounding box of the given position is returned + // * @exception BadLocationException if the given position does + // * not represent a valid location in the associated document + // * @exception IllegalArgumentException for an invalid bias argument + // * @see View#viewToModel + // */ + // public Shape modelToView(int p0, Position.Bias b0, int p1, Position.Bias + // b1, Shape a) throws BadLocationException { + // if (view != null) { + // return view.modelToView(p0, b0, p1, b1, a); + // } + // return null; + // } + // + // /** + // * Provides a mapping from the view coordinate space to the logical + // * coordinate space of the model. + // * + // * @param x x coordinate of the view location to convert + // * @param y y coordinate of the view location to convert + // * @param a the allocated region to render into + // * @return the location within the model that best represents the + // * given point in the view + // */ + // public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) { + // if (view != null) { + // int retValue = view.viewToModel(x, y, a, bias); + // return retValue; + // } + // return -1; + // } + // + // /** + // * Provides a way to determine the next visually represented model + // * location that one might place a caret. Some views may not be visible, + // * they might not be in the same order found in the model, or they just + // * might not allow access to some of the locations in the model. + // * + // * @param pos the position to convert >= 0 + // * @param a the allocated region to render into + // * @param direction the direction from the current position that can + // * be thought of as the arrow keys typically found on a keyboard. + // * This may be SwingConstants.WEST, SwingConstants.EAST, + // * SwingConstants.NORTH, or SwingConstants.SOUTH. + // * @return the location within the model that best represents the next + // * location visual position. + // * @exception BadLocationException + // * @exception IllegalArgumentException for an invalid direction + // */ + // public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, + // int direction, + // Position.Bias[] biasRet) + // throws BadLocationException { + // if( view != null ) { + // int nextPos = view.getNextVisualPositionFrom(pos, b, a, + // direction, biasRet); + // if(nextPos != -1) { + // pos = nextPos; + // } + // else { + // biasRet[0] = b; + // } + // } + // return pos; + // } + // + // /** + // * Gives notification that something was inserted into the document + // * in a location that this view is responsible for. + // * + // * @param e the change information from the associated document + // * @param a the current allocation of the view + // * @param f the factory to use to rebuild if the view has children + // */ + // public void insertUpdate(DocumentEvent e, Shape a, ViewFactory f) { + // if (view != null) { + // view.insertUpdate(e, a, f); + // } + // } + // + // /** + // * Gives notification that something was removed from the document + // * in a location that this view is responsible for. + // * + // * @param e the change information from the associated document + // * @param a the current allocation of the view + // * @param f the factory to use to rebuild if the view has children + // */ + // public void removeUpdate(DocumentEvent e, Shape a, ViewFactory f) { + // if (view != null) { + // view.removeUpdate(e, a, f); + // } + // } + // + // /** + // * Gives notification from the document that attributes were changed + // * in a location that this view is responsible for. + // * + // * @param e the change information from the associated document + // * @param a the current allocation of the view + // * @param f the factory to use to rebuild if the view has children + // */ + // public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) { + // if (view != null) { + // view.changedUpdate(e, a, f); + // } + // } + // + // /** + // * Returns the document model underlying the view. + // * + // * @return the model + // */ + // public Document getDocument() { + // return editor.getDocument(); + // } + // + // /** + // * Returns the starting offset into the model for this view. + // * + // * @return the starting offset + // */ + // public int getStartOffset() { + // if (view != null) { + // return view.getStartOffset(); + // } + // return getElement().getStartOffset(); + // } + // + // /** + // * Returns the ending offset into the model for this view. + // * + // * @return the ending offset + // */ + // public int getEndOffset() { + // if (view != null) { + // return view.getEndOffset(); + // } + // return getElement().getEndOffset(); + // } + // + // /** + // * Gets the element that this view is mapped to. + // * + // * @return the view + // */ + // public Element getElement() { + // if (view != null) { + // return view.getElement(); + // } + // return editor.getDocument().getDefaultRootElement(); + // } + // + // /** + // * Breaks this view on the given axis at the given length. + // * + // * @param axis may be either X_AXIS or Y_AXIS + // * @param len specifies where a break is desired in the span + // * @param the current allocation of the view + // * @return the fragment of the view that represents the given span + // * if the view can be broken, otherwise null + // */ + // public View breakView(int axis, float len, Shape a) { + // throw new Error("Can't break root view"); + // } + // + // /** + // * Determines the resizability of the view along the + // * given axis. A value of 0 or less is not resizable. + // * + // * @param axis may be either X_AXIS or Y_AXIS + // * @return the weight + // */ + // public int getResizeWeight(int axis) { + // if (view != null) { + // return view.getResizeWeight(axis); + // } + // return 0; + // } + // + // /** + // * Sets the view size. + // * + // * @param width the width + // * @param height the height + // */ + // public void setSize(float width, float height) { + // if (view != null) { + // view.setSize(width, height); + // } + // } + // + // /** + // * Fetches the container hosting the view. This is useful for + // * things like scheduling a repaint, finding out the host + // * components font, etc. The default implementation + // * of this is to forward the query to the parent view. + // * + // * @return the container + // */ + // public Container getContainer() { + // return editor; + // } + // + // /** + // * Fetches the factory to be used for building the + // * various view fragments that make up the view that + // * represents the model. This is what determines + // * how the model will be represented. This is implemented + // * to fetch the factory provided by the associated + // * EditorKit unless that is null, in which case this + // * simply returns the BasicTextUI itself which allows + // * subclasses to implement a simple factory directly without + // * creating extra objects. + // * + // * @return the factory + // */ + // public ViewFactory getViewFactory() { + // EditorKit kit = getEditorKit(editor); + // ViewFactory f = kit.getViewFactory(); + // if (f != null) { + // return f; + // } + // return BasicTextUI.this; + // } + // + // private View view; + // + // } + + // /** + // * Handles updates from various places. If the model is changed, + // * this class unregisters as a listener to the old model and + // * registers with the new model. If the document model changes, + // * the change is forwarded to the root view. If the focus + // * accelerator changes, a new keystroke is registered to request + // * focus. + // */ + // class UpdateHandler implements PropertyChangeListener, DocumentListener, + // LayoutManager2, UIResource { + // + // // --- PropertyChangeListener methods ----------------------- + // + // /** + // * This method gets called when a bound property is changed. + // * We are looking for document changes on the editor. + // */ + // public final void propertyChange(PropertyChangeEvent evt) { + // Object oldValue = evt.getOldValue(); + // Object newValue = evt.getNewValue(); + // String propertyName = evt.getPropertyName(); + // if ((oldValue instanceof Document) || (newValue instanceof Document)) { + // if (oldValue != null) { + // ((Document)oldValue).removeDocumentListener(this); + // i18nView = false; + // } + // if (newValue != null) { + // ((Document)newValue).addDocumentListener(this); + // if ("document" == propertyName) { + // setView(null); + // BasicTextUI.this.propertyChange(evt); + // modelChanged(); + // return; + // } + // } + // modelChanged(); + // } + // if ("focusAccelerator" == propertyName) { + // updateFocusAcceleratorBinding(true); + // } else if ("componentOrientation" == propertyName) { + // // Changes in ComponentOrientation require the views to be + // // rebuilt. + // modelChanged(); + // } else if ("font" == propertyName) { + // modelChanged(); + // } else if ("dropLocation" == propertyName) { + // dropIndexChanged(); + // } else if ("editable" == propertyName) { + // updateCursor(); + // modelChanged(); + // } + // BasicTextUI.this.propertyChange(evt); + // } + // + // private void dropIndexChanged() { + // if (editor.getDropMode() == DropMode.USE_SELECTION) { + // return; + // } + // + // JTextComponent.DropLocation dropLocation = editor.getDropLocation(); + // + // if (dropLocation == null) { + // if (dropCaret != null) { + // dropCaret.deinstall(editor); + // editor.repaint(dropCaret); + // dropCaret = null; + // } + // } else { + // if (dropCaret == null) { + // dropCaret = new BasicCaret(); + // dropCaret.install(editor); + // dropCaret.setVisible(true); + // } + // + // dropCaret.setDot(dropLocation.getIndex(), + // dropLocation.getBias()); + // } + // } + // + // // --- DocumentListener methods ----------------------- + // + // /** + // * The insert notification. Gets sent to the root of the view structure + // * that represents the portion of the model being represented by the + // * editor. The factory is added as an argument to the update so that + // * the views can update themselves in a dynamic (not hardcoded) way. + // * + // * @param e The change notification from the currently associated + // * document. + // * @see DocumentListener#insertUpdate + // */ + // public final void insertUpdate(DocumentEvent e) { + // Document doc = e.getDocument(); + // Object o = doc.getProperty("i18n"); + // if (o instanceof Boolean) { + // Boolean i18nFlag = (Boolean) o; + // if (i18nFlag.booleanValue() != i18nView) { + // // i18n flag changed, rebuild the view + // i18nView = i18nFlag.booleanValue(); + // modelChanged(); + // return; + // } + // } + // + // // normal insert update + // Rectangle alloc = (painted) ? getVisibleEditorRect() : null; + // rootView.insertUpdate(e, alloc, rootView.getViewFactory()); + // } + // + // /** + // * The remove notification. Gets sent to the root of the view structure + // * that represents the portion of the model being represented by the + // * editor. The factory is added as an argument to the update so that + // * the views can update themselves in a dynamic (not hardcoded) way. + // * + // * @param e The change notification from the currently associated + // * document. + // * @see DocumentListener#removeUpdate + // */ + // public final void removeUpdate(DocumentEvent e) { + // Rectangle alloc = (painted) ? getVisibleEditorRect() : null; + // rootView.removeUpdate(e, alloc, rootView.getViewFactory()); + // } + // + // /** + // * The change notification. Gets sent to the root of the view structure + // * that represents the portion of the model being represented by the + // * editor. The factory is added as an argument to the update so that + // * the views can update themselves in a dynamic (not hardcoded) way. + // * + // * @param e The change notification from the currently associated + // * document. + // * @see DocumentListener#changeUpdate + // */ + // public final void changedUpdate(DocumentEvent e) { + // Rectangle alloc = (painted) ? getVisibleEditorRect() : null; + // rootView.changedUpdate(e, alloc, rootView.getViewFactory()); + // } + // + // // --- LayoutManager2 methods -------------------------------- + // + // /** + // * Adds the specified component with the specified name to + // * the layout. + // * @param name the component name + // * @param comp the component to be added + // */ + // public void addLayoutComponent(String name, Component comp) { + // // not supported + // } + // + // /** + // * Removes the specified component from the layout. + // * @param comp the component to be removed + // */ + // public void removeLayoutComponent(Component comp) { + // if (constraints != null) { + // // remove the constraint record + // constraints.remove(comp); + // } + // } + // + // /** + // * Calculates the preferred size dimensions for the specified + // * panel given the components in the specified parent container. + // * @param parent the component to be laid out + // * + // * @see #minimumLayoutSize + // */ + // public Dimension preferredLayoutSize(Container parent) { + // // should not be called (JComponent uses UI instead) + // return null; + // } + // + // /** + // * Calculates the minimum size dimensions for the specified + // * panel given the components in the specified parent container. + // * @param parent the component to be laid out + // * @see #preferredLayoutSize + // */ + // public Dimension minimumLayoutSize(Container parent) { + // // should not be called (JComponent uses UI instead) + // return null; + // } + // + // /** + // * Lays out the container in the specified panel. This is + // * implemented to position all components that were added + // * with a View object as a constraint. The current allocation + // * of the associated View is used as the location of the + // * component. + // *

+ // * A read-lock is acquired on the document to prevent the + // * view tree from being modified while the layout process + // * is active. + // * + // * @param parent the component which needs to be laid out + // */ + // public void layoutContainer(Container parent) { + // if ((constraints != null) && (! constraints.isEmpty())) { + // Rectangle alloc = getVisibleEditorRect(); + // if (alloc != null) { + // Document doc = editor.getDocument(); + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readLock(); + // } + // try { + // rootView.setSize(alloc.width, alloc.height); + // Enumeration components = constraints.keys(); + // while (components.hasMoreElements()) { + // Component comp = (Component) components.nextElement(); + // View v = (View) constraints.get(comp); + // Shape ca = calculateViewPosition(alloc, v); + // if (ca != null) { + // Rectangle compAlloc = (ca instanceof Rectangle) ? + // (Rectangle) ca : ca.getBounds(); + // comp.setBounds(compAlloc); + // } + // } + // } finally { + // if (doc instanceof AbstractDocument) { + // ((AbstractDocument)doc).readUnlock(); + // } + // } + // } + // } + // } + // + // /** + // * Find the Shape representing the given view. + // */ + // Shape calculateViewPosition(Shape alloc, View v) { + // int pos = v.getStartOffset(); + // View child = null; + // for (View parent = rootView; (parent != null) && (parent != v); parent = + // child) { + // int index = parent.getViewIndex(pos, Position.Bias.Forward); + // alloc = parent.getChildAllocation(index, alloc); + // child = parent.getView(index); + // } + // return (child != null) ? alloc : null; + // } + // + // /** + // * Adds the specified component to the layout, using the specified + // * constraint object. We only store those components that were added + // * with a constraint that is of type View. + // * + // * @param comp the component to be added + // * @param constraint where/how the component is added to the layout. + // */ + // public void addLayoutComponent(Component comp, Object constraint) { + // if (constraint instanceof View) { + // if (constraints == null) { + // constraints = new Hashtable(7); + // } + // constraints.put(comp, constraint); + // } + // } + // + // /** + // * Returns the maximum size of this component. + // * @see jsjava.awt.Component#getMinimumSize() + // * @see jsjava.awt.Component#getPreferredSize() + // * @see LayoutManager + // */ + // public Dimension maximumLayoutSize(Container target) { + // // should not be called (JComponent uses UI instead) + // return null; + // } + // + // /** + // * Returns the alignment along the x axis. This specifies how + // * the component would like to be aligned relative to other + // * components. The value should be a number between 0 and 1 + // * where 0 represents alignment along the origin, 1 is aligned + // * the furthest away from the origin, 0.5 is centered, etc. + // */ + // public float getLayoutAlignmentX(Container target) { + // return 0.5f; + // } + // + // /** + // * Returns the alignment along the y axis. This specifies how + // * the component would like to be aligned relative to other + // * components. The value should be a number between 0 and 1 + // * where 0 represents alignment along the origin, 1 is aligned + // * the furthest away from the origin, 0.5 is centered, etc. + // */ + // public float getLayoutAlignmentY(Container target) { + // return 0.5f; + // } + // + // /** + // * Invalidates the layout, indicating that if the layout manager + // * has cached information it should be discarded. + // */ + // public void invalidateLayout(Container target) { + // } + // + // /** + // * The "layout constraints" for the LayoutManager2 implementation. + // * These are View objects for those components that are represented + // * by a View in the View tree. + // */ + // private Hashtable constraints; + // + // private boolean i18nView = false; + // } + + /** + * Wrapper for text actions to return isEnabled false in case editor is non + * editable + */ + class TextActionWrapper extends TextAction { + public TextActionWrapper(TextAction action) { + super((String) action.getValue(Action.NAME)); + this.action = action; + } + + /** + * The operation to perform when this action is triggered. + * + * @param e + * the action event + */ + public void actionPerformed(ActionEvent e) { + action.actionPerformed(e); + } + + public boolean isEnabled() { + return (editor == null || editor.isEditable()) ? action.isEnabled() + : false; + } + + TextAction action = null; + } + + /** + * Registered in the ActionMap. + */ + class FocusAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + editor.requestFocus(); + } + + public boolean isEnabled() { + return editor.isEditable(); + } + } + + boolean handleEnter(int eventType) { + return false; + } + + String bgcolor0; + + public void setEditable(boolean editable) { + + this.editable = editable; + if (domNode == null) + return; + if (c.isBackgroundSet()) + bgcolor0 = JSToolkit.getCSSColor(c.getBackground()); + if (editable) { + domNode.removeAttribute("readOnly"); + if (bgcolor0 != null) + DOMNode.setStyles(domNode, "background-color", bgcolor0); + } else { + DOMNode.setAttr(domNode, "readOnly", "true"); + if (c.isBackgroundSet()) { + bgcolor0 = JSToolkit.getCSSColor(c.getBackground()); + } else { + if (bgcolor0 == null) + bgcolor0 = domNode.getStyle("background-color"); + } + DOMNode.setStyles(domNode, "background-color", "rgba(0,0,0,0)"); + } + + } + + // private static DragListener getDragListener() { + // synchronized(DragListener.class) { + // DragListener listener = + // (DragListener)AppContext.getAppContext(). + // get(DragListener.class); + // + // if (listener == null) { + // listener = new DragListener(); + // AppContext.getAppContext().put(DragListener.class, listener); + // } + // + // return listener; + // } + // } + // + // /** + // * Listens for mouse events for the purposes of detecting drag gestures. + // * BasicTextUI will maintain one of these per AppContext. + // */ + // static class DragListener extends MouseInputAdapter + // implements BeforeDrag { + // + // private boolean dragStarted; + // + // public void dragStarting(MouseEvent me) { + // dragStarted = true; + // } + // + // public void mousePressed(MouseEvent e) { + // JTextComponent c = (JTextComponent)e.getSource(); + // if (c.getDragEnabled()) { + // dragStarted = false; + // if (isDragPossible(e) && DragRecognitionSupport.mousePressed(e)) { + // e.consume(); + // } + // } + // } + // + // public void mouseReleased(MouseEvent e) { + // JTextComponent c = (JTextComponent)e.getSource(); + // if (c.getDragEnabled()) { + // if (dragStarted) { + // e.consume(); + // } + // + // DragRecognitionSupport.mouseReleased(e); + // } + // } + // + // public void mouseDragged(MouseEvent e) { + // JTextComponent c = (JTextComponent)e.getSource(); + // if (c.getDragEnabled()) { + // if (dragStarted || DragRecognitionSupport.mouseDragged(e, this)) { + // e.consume(); + // } + // } + // } + // + // /** + // * Determines if the following are true: + // *

+ // */ + // protected boolean isDragPossible(MouseEvent e) { + // JTextComponent c = (JTextComponent)e.getSource(); + // if (c.isEnabled()) { + // Caret caret = c.getCaret(); + // int dot = caret.getDot(); + // int mark = caret.getMark(); + // if (dot != mark) { + // Point p = new Point(e.getX(), e.getY()); + // int pos = c.viewToModel(p); + // + // int p0 = Math.min(dot, mark); + // int p1 = Math.max(dot, mark); + // if ((pos >= p0) && (pos < p1)) { + // return true; + // } + // } + // } + // return false; + // } + // } + + // static class TextTransferHandler extends TransferHandler implements + // UIResource { + // + // private JTextComponent exportComp; + // private boolean shouldRemove; + // private int p0; + // private int p1; + // + // /** + // * Whether or not this is a drop using + // * DropMode.INSERT. + // */ + // private boolean modeBetween = false; + // + // /** + // * Whether or not this is a drop. + // */ + // private boolean isDrop = false; + // + // /** + // * The drop action. + // */ + // private int dropAction = MOVE; + // + // /** + // * The drop bias. + // */ + // private Position.Bias dropBias; + // + // /** + // * Try to find a flavor that can be used to import a Transferable. + // * The set of usable flavors are tried in the following order: + // *
    + // *
  1. First, an attempt is made to find a flavor matching the content type + // * of the EditorKit for the component. + // *
  2. Second, an attempt to find a text/plain flavor is made. + // *
  3. Third, an attempt to find a flavor representing a String reference + // * in the same VM is made. + // *
  4. Lastly, DataFlavor.stringFlavor is searched for. + // *
+ // */ + // protected DataFlavor getImportFlavor(DataFlavor[] flavors, JTextComponent + // c) { + // DataFlavor plainFlavor = null; + // DataFlavor refFlavor = null; + // DataFlavor stringFlavor = null; + // + // if (c instanceof JEditorPane) { + // for (int i = 0; i < flavors.length; i++) { + // String mime = flavors[i].getMimeType(); + // if (mime.startsWith(((JEditorPane)c).getEditorKit().getContentType())) { + // return flavors[i]; + // } else if (plainFlavor == null && mime.startsWith("text/plain")) { + // plainFlavor = flavors[i]; + // } else if (refFlavor == null && + // mime.startsWith("application/x-java-jvm-local-objectref") + // && flavors[i].getRepresentationClass() == jsjava.lang.String.class) { + // refFlavor = flavors[i]; + // } else if (stringFlavor == null && + // flavors[i].equals(DataFlavor.stringFlavor)) { + // stringFlavor = flavors[i]; + // } + // } + // if (plainFlavor != null) { + // return plainFlavor; + // } else if (refFlavor != null) { + // return refFlavor; + // } else if (stringFlavor != null) { + // return stringFlavor; + // } + // return null; + // } + // + // + // for (int i = 0; i < flavors.length; i++) { + // String mime = flavors[i].getMimeType(); + // if (mime.startsWith("text/plain")) { + // return flavors[i]; + // } else if (refFlavor == null && + // mime.startsWith("application/x-java-jvm-local-objectref") + // && flavors[i].getRepresentationClass() == jsjava.lang.String.class) { + // refFlavor = flavors[i]; + // } else if (stringFlavor == null && + // flavors[i].equals(DataFlavor.stringFlavor)) { + // stringFlavor = flavors[i]; + // } + // } + // if (refFlavor != null) { + // return refFlavor; + // } else if (stringFlavor != null) { + // return stringFlavor; + // } + // return null; + // } + // + // /** + // * Import the given stream data into the text component. + // */ + // protected void handleReaderImport(Reader in, JTextComponent c, boolean + // useRead) + // throws BadLocationException, IOException { + // if (useRead) { + // int startPosition = c.getSelectionStart(); + // int endPosition = c.getSelectionEnd(); + // int length = endPosition - startPosition; + // EditorKit kit = c.getUI().getEditorKit(c); + // Document doc = c.getDocument(); + // if (length > 0) { + // doc.remove(startPosition, length); + // } + // kit.read(in, doc, startPosition); + // } else { + // char[] buff = new char[1024]; + // int nch; + // boolean lastWasCR = false; + // int last; + // StringBuffer sbuff = null; + // + // // Read in a block at a time, mapping \r\n to \n, as well as single + // // \r to \n. + // while ((nch = in.read(buff, 0, buff.length)) != -1) { + // if (sbuff == null) { + // sbuff = new StringBuffer(nch); + // } + // last = 0; + // for(int counter = 0; counter < nch; counter++) { + // switch(buff[counter]) { + // case '\r': + // if (lastWasCR) { + // if (counter == 0) { + // sbuff.append('\n'); + // } else { + // buff[counter - 1] = '\n'; + // } + // } else { + // lastWasCR = true; + // } + // break; + // case '\n': + // if (lastWasCR) { + // if (counter > (last + 1)) { + // sbuff.append(buff, last, counter - last - 1); + // } + // // else nothing to do, can skip \r, next write will + // // write \n + // lastWasCR = false; + // last = counter; + // } + // break; + // default: + // if (lastWasCR) { + // if (counter == 0) { + // sbuff.append('\n'); + // } else { + // buff[counter - 1] = '\n'; + // } + // lastWasCR = false; + // } + // break; + // } + // } + // if (last < nch) { + // if (lastWasCR) { + // if (last < (nch - 1)) { + // sbuff.append(buff, last, nch - last - 1); + // } + // } else { + // sbuff.append(buff, last, nch - last); + // } + // } + // } + // if (lastWasCR) { + // sbuff.append('\n'); + // } + // c.replaceSelection(sbuff != null ? sbuff.toString() : ""); + // } + // } + // + // // --- TransferHandler methods ------------------------------------ + // + // /** + // * This is the type of transfer actions supported by the source. Some models + // are + // * not mutable, so a transfer operation of COPY only should + // * be advertised in that case. + // * + // * @param c The component holding the data to be transfered. This + // * argument is provided to enable sharing of TransferHandlers by + // * multiple components. + // * @return This is implemented to return NONE if the component is a + // JPasswordField + // * since exporting data via user gestures is not allowed. If the text + // component is + // * editable, COPY_OR_MOVE is returned, otherwise just COPY is allowed. + // */ + // public int getSourceActions(JComponent c) { + // if (c instanceof JPasswordField && + // c.getClientProperty("JPasswordField.cutCopyAllowed") != + // Boolean.TRUE) { + // return NONE; + // } + // + // return ((JTextComponent)c).isEditable() ? COPY_OR_MOVE : COPY; + // } + // + // /** + // * Create a Transferable to use as the source for a data transfer. + // * + // * @param comp The component holding the data to be transfered. This + // * argument is provided to enable sharing of TransferHandlers by + // * multiple components. + // * @return The representation of the data to be transfered. + // * + // */ + // protected Transferable createTransferable(JComponent comp) { + // exportComp = (JTextComponent)comp; + // shouldRemove = true; + // p0 = exportComp.getSelectionStart(); + // p1 = exportComp.getSelectionEnd(); + // return (p0 != p1) ? (new TextTransferable(exportComp, p0, p1)) : null; + // } + // + // /** + // * This method is called after data has been exported. This method should + // remove + // * the data that was transfered if the action was MOVE. + // * + // * @param source The component that was the source of the data. + // * @param data The data that was transferred or possibly null + // * if the action is NONE. + // * @param action The actual action that was performed. + // */ + // protected void exportDone(JComponent source, Transferable data, int action) + // { + // // only remove the text if shouldRemove has not been set to + // // false by importData and only if the action is a move + // if (shouldRemove && action == MOVE) { + // TextTransferable t = (TextTransferable)data; + // t.removeText(); + // } + // + // exportComp = null; + // } + // + // public boolean importData(TransferSupport support) { + // isDrop = support.isDrop(); + // + // if (isDrop) { + // modeBetween = + // ((JTextComponent)support.getComponent()).getDropMode() == DropMode.INSERT; + // + // dropBias = + // ((JTextComponent.DropLocation)support.getDropLocation()).getBias(); + // + // dropAction = support.getDropAction(); + // } + // + // try { + // return super.importData(support); + // } finally { + // isDrop = false; + // modeBetween = false; + // dropBias = null; + // dropAction = MOVE; + // } + // } + // + // /** + // * This method causes a transfer to a component from a clipboard or a + // * DND drop operation. The Transferable represents the data to be + // * imported into the component. + // * + // * @param comp The component to receive the transfer. This + // * argument is provided to enable sharing of TransferHandlers by + // * multiple components. + // * @param t The data to import + // * @return true if the data was inserted into the component, false + // otherwise. + // */ + // public boolean importData(JComponent comp, Transferable t) { + // JTextComponent c = (JTextComponent)comp; + // + // int pos = modeBetween + // ? ((JTextComponent.DropLocation)c.getDropLocation()).getIndex() + // : c.getCaretPosition(); + // + // // if we are importing to the same component that we exported from + // // then don't actually do anything if the drop location is inside + // // the drag location and set shouldRemove to false so that exportDone + // // knows not to remove any data + // if (dropAction == MOVE && c == exportComp && pos >= p0 && pos <= p1) { + // shouldRemove = false; + // return true; + // } + // + // boolean imported = false; + // DataFlavor importFlavor = getImportFlavor(t.getTransferDataFlavors(), c); + // if (importFlavor != null) { + // try { + // boolean useRead = false; + // if (comp instanceof JEditorPane) { + // JEditorPane ep = (JEditorPane)comp; + // if (!ep.getContentType().startsWith("text/plain") && + // importFlavor.getMimeType().startsWith(ep.getContentType())) { + // useRead = true; + // } + // } + // InputContext ic = c.getInputContext(); + // if (ic != null) { + // ic.endComposition(); + // } + // Reader r = importFlavor.getReaderForText(t); + // + // if (modeBetween) { + // Caret caret = c.getCaret(); + // if (caret instanceof DefaultCaret) { + // ((DefaultCaret)caret).setDot(pos, dropBias); + // } else { + // c.setCaretPosition(pos); + // } + // } + // + // handleReaderImport(r, c, useRead); + // + // if (isDrop) { + // c.requestFocus(); + // Caret caret = c.getCaret(); + // if (caret instanceof DefaultCaret) { + // int newPos = caret.getDot(); + // Position.Bias newBias = ((DefaultCaret)caret).getDotBias(); + // + // ((DefaultCaret)caret).setDot(pos, dropBias); + // ((DefaultCaret)caret).moveDot(newPos, newBias); + // } else { + // c.select(pos, c.getCaretPosition()); + // } + // } + // + // imported = true; + // } catch (UnsupportedFlavorException ufe) { + // } catch (BadLocationException ble) { + // } catch (IOException ioe) { + // } + // } + // return imported; + // } + // + // /** + // * This method indicates if a component would accept an import of the given + // * set of data flavors prior to actually attempting to import it. + // * + // * @param comp The component to receive the transfer. This + // * argument is provided to enable sharing of TransferHandlers by + // * multiple components. + // * @param flavors The data formats available + // * @return true if the data can be inserted into the component, false + // otherwise. + // */ + // public boolean canImport(JComponent comp, DataFlavor[] flavors) { + // JTextComponent c = (JTextComponent)comp; + // if (!(c.isEditable() && c.isEnabled())) { + // return false; + // } + // return (getImportFlavor(flavors, c) != null); + // } + // + // /** + // * A possible implementation of the Transferable interface + // * for text components. For a JEditorPane with a rich set + // * of EditorKit implementations, conversions could be made + // * giving a wider set of formats. This is implemented to + // * offer up only the active content type and text/plain + // * (if that is not the active format) since that can be + // * extracted from other formats. + // */ + // static class TextTransferable extends BasicTransferable { + // + // TextTransferable(JTextComponent c, int start, int end) { + // super(null, null); + // + // this.c = c; + // + // Document doc = c.getDocument(); + // + // try { + // p0 = doc.createPosition(start); + // p1 = doc.createPosition(end); + // + // plainData = c.getSelectedText(); + // + // if (c instanceof JEditorPane) { + // JEditorPane ep = (JEditorPane)c; + // + // mimeType = ep.getContentType(); + // + // if (mimeType.startsWith("text/plain")) { + // return; + // } + // + // StringWriter sw = new StringWriter(p1.getOffset() - p0.getOffset()); + // ep.getEditorKit().write(sw, doc, p0.getOffset(), p1.getOffset() - + // p0.getOffset()); + // + // if (mimeType.startsWith("text/html")) { + // htmlData = sw.toString(); + // } else { + // richText = sw.toString(); + // } + // } + // } catch (BadLocationException ble) { + // } catch (IOException ioe) { + // } + // } + // + // void removeText() { + // if ((p0 != null) && (p1 != null) && (p0.getOffset() != p1.getOffset())) { + // try { + // Document doc = c.getDocument(); + // doc.remove(p0.getOffset(), p1.getOffset() - p0.getOffset()); + // } catch (BadLocationException e) { + // } + // } + // } + // + // // ---- EditorKit other than plain or HTML text ----------------------- + // + // /** + // * If the EditorKit is not for text/plain or text/html, that format + // * is supported through the "richer flavors" part of BasicTransferable. + // */ + // protected DataFlavor[] getRicherFlavors() { + // if (richText == null) { + // return null; + // } + // + // try { + // DataFlavor[] flavors = new DataFlavor[3]; + // flavors[0] = new DataFlavor(mimeType + ";class=java.lang.String"); + // flavors[1] = new DataFlavor(mimeType + ";class=java.io.Reader"); + // flavors[2] = new DataFlavor(mimeType + + // ";class=java.io.InputStream;charset=unicode"); + // return flavors; + // } catch (ClassNotFoundException cle) { + // // fall through to unsupported (should not happen) + // } + // + // return null; + // } + // + // /** + // * The only richer format supported is the file list flavor + // */ + // protected Object getRicherData(DataFlavor flavor) throws + // UnsupportedFlavorException { + // if (richText == null) { + // return null; + // } + // + // if (String.class.equals(flavor.getRepresentationClass())) { + // return richText; + // } else if (Reader.class.equals(flavor.getRepresentationClass())) { + // return new StringReader(richText); + // } else if (InputStream.class.equals(flavor.getRepresentationClass())) { + // return new StringBufferInputStream(richText); + // } + // throw new UnsupportedFlavorException(flavor); + // } + // + // Position p0; + // Position p1; + // String mimeType; + // String richText; + // JTextComponent c; + // } + // + // } + + // /** + // * Creates a new UI. + // */ + // public JSTextUI() { + // // painted = false; + // } + // + // /** + // * Creates the object to use for a caret. By default an + // * instance of BasicCaret is created. This method + // * can be redefined to provide something else that implements + // * the InputPosition interface or a subclass of JCaret. + // * + // * @return the caret object + // */ + // protected Caret createCaret() { + // return new BasicCaret(); + // } + // + // /** + // * Creates the object to use for adding highlights. By default + // * an instance of BasicHighlighter is created. This method + // * can be redefined to provide something else that implements + // * the Highlighter interface or a subclass of DefaultHighlighter. + // * + // * @return the highlighter + // */ + // protected Highlighter createHighlighter() { + // return new BasicHighlighter(); + // } + // + // /** + // * Fetches the name of the keymap that will be installed/used + // * by default for this UI. This is implemented to create a + // * name based upon the classname. The name is the the name + // * of the class with the package prefix removed. + // * + // * @return the name + // */ + // protected String getKeymapName() { + // String nm = getClass().getName(); + // int index = nm.lastIndexOf('.'); + // if (index >= 0) { + // nm = nm.substring(index+1, nm.length()); + // } + // return nm; + // } + // + // /** + // * Creates the keymap to use for the text component, and installs + // * any necessary bindings into it. By default, the keymap is + // * shared between all instances of this type of TextUI. The + // * keymap has the name defined by the getKeymapName method. If the + // * keymap is not found, then DEFAULT_KEYMAP from JTextComponent is used. + // *

+ // * The set of bindings used to create the keymap is fetched + // * from the UIManager using a key formed by combining the + // * {@link #getPropertyPrefix} method + // * and the string .keyBindings. The type is expected + // * to be JTextComponent.KeyBinding[]. + // * + // * @return the keymap + // * @see #getKeymapName + // * @see jsjavax.swing.text.JTextComponent + // */ + // protected Keymap createKeymap() { + // String nm = getKeymapName(); + // Keymap map = JTextComponent.getKeymap(nm); + // if (map == null) { + // Keymap parent = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP); + // map = JTextComponent.addKeymap(nm, parent); + // String prefix = getPropertyPrefix(); + // Object o = DefaultLookup.get(editor, this, + // prefix + ".keyBindings"); + // if ((o != null) && (o instanceof JTextComponent.KeyBinding[])) { + // JTextComponent.KeyBinding[] bindings = (JTextComponent.KeyBinding[]) o; + // JTextComponent.loadKeymap(map, bindings, getComponent().getActions()); + // } + // } + // return map; + // } + // + // /** + // * This method gets called when a bound property is changed + // * on the associated JTextComponent. This is a hook + // * which UI implementations may change to reflect how the + // * UI displays bound properties of JTextComponent subclasses. + // * This is implemented to do nothing (i.e. the response to + // * properties in JTextComponent itself are handled prior + // * to calling this method). + // * + // * This implementation updates the background of the text + // * component if the editable and/or enabled state changes. + // * + // * @param evt the property change event + // */ + // protected void propertyChange(PropertyChangeEvent evt) { + // if (evt.getPropertyName().equals("editable") || + // evt.getPropertyName().equals("enabled")) { + // + // updateBackground((JTextComponent)evt.getSource()); + // } + // } + // + // /** + // * Updates the background of the text component based on whether the + // * text component is editable and/or enabled. + // * + // * @param c the JTextComponent that needs its background color updated + // */ + // private void updateBackground(JTextComponent c) { + // // This is a temporary workaround. + // // This code does not correctly deal with Synth (Synth doesn't use + // // properties like this), nor does it deal with the situation where + // // the developer grabs the color from a JLabel and sets it as + // // the background for a JTextArea in all look and feels. The problem + // // scenario results if the Color obtained for the Label and TextArea + // // is ==, which is the case for the windows look and feel. + // // Until an appropriate solution is found, the code is being + // // reverted to what it was before the original fix. + // if (this instanceof sun.swing.plaf.synth.SynthUI || + // (c instanceof JTextArea)) { + // return; + // } + // Color background = c.getBackground(); + // if (background instanceof UIResource) { + // String prefix = getPropertyPrefix(); + // + // Color disabledBG = + // DefaultLookup.getColor(c, this, prefix + ".disabledBackground", null); + // Color inactiveBG = + // DefaultLookup.getColor(c, this, prefix + ".inactiveBackground", null); + // Color bg = + // DefaultLookup.getColor(c, this, prefix + ".background", null); + // + // /* In an ideal situation, the following check would not be necessary + // * and we would replace the color any time the previous color was a + // * UIResouce. However, it turns out that there is existing code that + // * uses the following inadvisable pattern to turn a text area into + // * what appears to be a multi-line label: + // * + // * JLabel label = new JLabel(); + // * JTextArea area = new JTextArea(); + // * area.setBackground(label.getBackground()); + // * area.setEditable(false); + // * + // * JLabel's default background is a UIResource. As such, just + // * checking for UIResource would have us always changing the + // * background away from what the developer wanted. + // * + // * Therefore, for JTextArea/JEditorPane, we'll additionally check + // * that the color we're about to replace matches one that was + // * installed by us from the UIDefaults. + // */ + // if ((c instanceof JTextArea || c instanceof JEditorPane) + // && background != disabledBG + // && background != inactiveBG + // && background != bg) { + // + // return; + // } + // + // Color newColor = null; + // if (!c.isEnabled()) { + // newColor = disabledBG; + // } + // if (newColor == null && !c.isEditable()) { + // newColor = inactiveBG; + // } + // if (newColor == null) { + // newColor = bg; + // } + // if (newColor != null && newColor != background) { + // c.setBackground(newColor); + // } + // } + // } + // + // /** + // * Gets the name used as a key to look up properties through the + // * UIManager. This is used as a prefix to all the standard + // * text properties. + // * + // * @return the name + // */ + // protected abstract String getPropertyPrefix(); + +}