|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.form; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.JTextComponent; import java.util.ArrayList; /** A layer used by FormDesigner for in-place editing of components' * labels and text. Can be used in two modes - layer editing or * direct editing. In layer editing mode, a JTextField-based component * is set up on the layer for editing labels and buttons. In direct editing * mode, the edited component is used also for editing, the layer just * ensures that other components are inaccessible. * * @author Tomas Pavek */ class InPlaceEditLayer extends JPanel { private boolean layerEditing = true; private boolean changeDone = false; private String editedText; private String oldText; private Component editedComp; private Container superContainer; private JTextComponent editingTextComp; private InPlaceTextField inPlaceField; // private MouseInputListener layerMouseListener; private ComponentListener layerResizeListener; private KeyListener compKeyListener; private ActionListener compActionListener; private ArrayList listeners; private Cursor defaultCursor; // --------- InPlaceEditLayer() { setLayout(null); defaultCursor = getCursor(); } void setEditedComponent(Component comp, String text) { if (!comp.isShowing() || comp.getParent() == null) throw new IllegalArgumentException(); editedComp = comp; editedText = text; if (inPlaceField != null) { remove(inPlaceField); inPlaceField = null; } if (comp instanceof JLabel || comp instanceof AbstractButton) { layerEditing = true; superContainer = null; createInPlaceField(); } else if (comp instanceof JTextField || comp instanceof JTextArea) { layerEditing = false; superContainer = comp.getParent(); Container cont = superContainer; do { if (cont.getParent() instanceof JLayeredPane) { superContainer = cont; break; } else cont = cont.getParent(); } while (cont != null); editingTextComp = (JTextComponent)editedComp; oldText = editingTextComp.getText(); editingTextComp.setText(editedText); // enable focus on component in component layer editingTextComp.setFocusable(true); } else throw new IllegalArgumentException(); attachListeners(); } // ------------ static boolean supportsEditingFor(Class compClass, boolean layerRequired) { return JLabel.class.isAssignableFrom(compClass) || AbstractButton.class.isAssignableFrom(compClass) || (!layerRequired && (JTextField.class.isAssignableFrom(compClass) || JTextArea.class.isAssignableFrom(compClass))); } boolean isEditingInitialized() { return editingTextComp != null; } boolean isLayerEditing() { return layerEditing; } String getEditedText() { return editedText; } boolean isTextChanged() { return changeDone; } void finishEditing(boolean applyChanges) { if (applyChanges) { String text = editingTextComp.getText(); if (text.equals(editedText)) applyChanges = false; else editedText = text; } else if (!isLayerEditing()) { editingTextComp.setText(oldText); editingTextComp.setFocusable(false); } editingTextComp.removeKeyListener(compKeyListener); if (editingTextComp instanceof JTextField) ((JTextField)editingTextComp).removeActionListener(compActionListener); editingTextComp = null; changeDone = applyChanges; fireEditingFinished(); } // ---------------- private void createInPlaceField() { if (editedComp instanceof JLabel) { JLabel label = (JLabel)editedComp; inPlaceField = new InPlaceTextField(editedText); inPlaceField.setFont(label.getFont()); inPlaceField.setHorizontalAlignment(label.getHorizontalAlignment()); // inPlaceField.setNextFocusableComponent(this); // inPlaceField.setBorder(new javax.swing.border.EmptyBorder(0,0,0,0)); // inPlaceField.setBackground(label.getBackground()); // inPlaceField.setForeground(label.getForeground()); // inPlaceField.setSelectedTextColor(label.getForeground()); } else if (editedComp instanceof AbstractButton) { AbstractButton button = (AbstractButton)editedComp; inPlaceField = new InPlaceTextField(editedText); inPlaceField.setFont(button.getFont()); inPlaceField.setHorizontalAlignment(button.getHorizontalAlignment()); // inPlaceField.setNextFocusableComponent(this); } else return; // should not happen /* else if (editedComp instanceof JTextField) { JTextField field = (JTextField)editedComp; JTextField textField = new InPlaceTextField(editedText); textField.setFont(field.getFont()); textField.setHorizontalAlignment(field.getHorizontalAlignment()); editingComp = textField; editingTextComp = textField; } else if (editedComp instanceof JTextArea) { JTextArea textA = (JTextArea)editedComp; JTextArea textArea = new JTextArea(editedText); textArea.setFont(textA.getFont()); textArea.setTabSize(textA.getTabSize()); textArea.setRows(textA.getRows()); textArea.setColumns(textA.getColumns()); textArea.setLineWrap(textA.getLineWrap()); // textArea.setBorder(new javax.swing.border.LineBorder(Color.black)); // TODO: scrollpane, resizing JScrollPane scroll = new JScrollPane(textArea); editingComp = scroll; //textArea; editingTextComp = textArea; } */ editingTextComp = inPlaceField; add(inPlaceField); placeInPlaceField(); } private void attachListeners() { if (layerResizeListener != null) removeComponentListener(layerResizeListener); else createListeners(); if (isLayerEditing()) addComponentListener(layerResizeListener); editingTextComp.addKeyListener(compKeyListener); if (editingTextComp instanceof JTextField) ((JTextField)editingTextComp).addActionListener(compActionListener); } private void createListeners() { // listening for mouse events MouseInputListener layerMouseListener = new MouseInputListener() { public void mouseClicked(MouseEvent e) { processMouse(e); } public void mousePressed(MouseEvent e) { processMouse(e); } public void mouseReleased(MouseEvent e) { processMouse(e); } public void mouseEntered(MouseEvent e) { processMouse(e); } public void mouseExited(MouseEvent e) { processMouse(e); } public void mouseDragged(MouseEvent e) { processMouse(e); } public void mouseMoved(MouseEvent e) { processMouse(e); } }; addMouseListener(layerMouseListener); addMouseMotionListener(layerMouseListener); // listening for layer resizing layerResizeListener = new ComponentAdapter() { public void componentResized(ComponentEvent e) { if (InPlaceEditLayer.this.isVisible()) placeInPlaceField(); } }; // listening for Escape and Ctrl+Enter compKeyListener = new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE) finishEditing(false); else if (e.getModifiers() == InputEvent.CTRL_MASK && (e.getKeyCode() == 10 || e.getKeyCode() == KeyEvent.VK_ENTER)) finishEditing(true); } }; // listening for Enter compActionListener = new ActionListener() { public void actionPerformed(ActionEvent evt) { finishEditing(true); } }; } private void processMouse(MouseEvent e) { if (!isEditingInitialized()) return; if (isLayerEditing()) { if (e.getID() == MouseEvent.MOUSE_PRESSED) finishEditing(true); // or false? } else { Point p = SwingUtilities.convertPoint(this, e.getPoint(), superContainer); Component comp = SwingUtilities.getDeepestComponentAt(superContainer, p.x, p.y); if (comp != editedComp) { Container cont = editedComp.getParent(); if (comp != cont || !(cont instanceof JScrollPane)) comp = null; } if (comp != null) { comp.dispatchEvent(SwingUtilities.convertMouseEvent(this, e, comp)); if (e.getID() == MouseEvent.MOUSE_MOVED) { Cursor cursor = comp.getCursor(); if (getCursor() != cursor) setCursor(cursor); } } else { if (e.getID() == MouseEvent.MOUSE_PRESSED) finishEditing(true); // or false? else if (e.getID() == MouseEvent.MOUSE_MOVED) if (getCursor() != defaultCursor) setCursor(defaultCursor); } } } private void placeInPlaceField() { // if (!(editedComp instanceof JLabel) && !(editedComp instanceof AbstractButton)) // return; Rectangle bounds = SwingUtilities.convertRectangle(editedComp.getParent(), editedComp.getBounds(), this); Insets editedIns = ((JComponent)editedComp).getInsets(); Insets editingIns = inPlaceField.getInsets(); int hA, hTP, vA, vTP; Icon icon; int itGap; String text; if (editedComp instanceof JLabel) { JLabel label = (JLabel)editedComp; hA = label.getHorizontalAlignment(); hTP = label.getHorizontalTextPosition(); vA = label.getVerticalAlignment(); vTP = label.getVerticalTextPosition(); icon = label.getIcon(); itGap = icon != null ? label.getIconTextGap() : 0; text = label.getText(); } else if (editedComp instanceof AbstractButton) { AbstractButton button = (AbstractButton)editedComp; hA = button.getHorizontalAlignment(); hTP = button.getHorizontalTextPosition(); vA = button.getVerticalAlignment(); vTP = button.getVerticalTextPosition(); icon = button.getIcon(); if (icon != null) { Integer gap = (Integer)UIManager.get("Button.textIconGap"); // NOI18N itGap = gap != null ? gap.intValue() : 4; } else itGap = 0; text = button.getText(); if (editedComp instanceof JCheckBox || editedComp instanceof JRadioButton) { if (icon == null) { javax.swing.plaf.ComponentUI cui = UIManager.getUI((JComponent)editedComp); if (cui instanceof javax.swing.plaf.basic.BasicRadioButtonUI) { icon = ((javax.swing.plaf.basic.BasicRadioButtonUI)cui).getDefaultIcon(); itGap = ((javax.swing.plaf.basic.BasicRadioButtonUI)cui).getDefaultTextIconGap(button); } } // hack: border at the aligned side is always 0 (bug?) if (hA == SwingConstants.LEFT || hA == SwingConstants.LEADING) { editedIns.right += editedIns.left; editedIns.left = 0; } else if (hA == SwingConstants.RIGHT || hA == SwingConstants.TRAILING) { editedIns.left += editedIns.right; editedIns.right = 0; } if (vA == SwingConstants.TOP) { editedIns.bottom += editedIns.top; editedIns.top = 0; } else if (vA == SwingConstants.BOTTOM) { editedIns.top += editedIns.bottom; editedIns.bottom = 0; } } } else return; // should not happen bounds.x += editedIns.left; bounds.y += editedIns.top; bounds.width -= editedIns.left + editedIns.right; bounds.height -= editedIns.top + editedIns.bottom; Rectangle iR = new Rectangle(); // icon rectangle Rectangle tR = new Rectangle(); // text rectangle SwingUtilities.layoutCompoundLabel( (JComponent)editedComp, editedComp.getGraphics().getFontMetrics(), text, icon, vA, hA, vTP, hTP, bounds, iR, tR, itGap); if (icon != null && hTP != SwingConstants.CENTER) { if (hA == SwingConstants.LEFT || hA == SwingConstants.LEADING) { if (hTP == SwingConstants.RIGHT || hTP == SwingConstants.TRAILING) { bounds.width -= tR.x - bounds.x; bounds.x = tR.x; inPlaceField.setHorizontalAlignment(SwingConstants.LEFT); } else if (hTP == SwingConstants.LEFT || hTP == SwingConstants.LEADING) { bounds.width = tR.width; inPlaceField.setHorizontalAlignment(SwingConstants.RIGHT); } } else if (hA == SwingConstants.RIGHT || hA == SwingConstants.TRAILING) { if (hTP == SwingConstants.RIGHT || hTP == SwingConstants.TRAILING) { bounds.x = tR.x; bounds.width = tR.width; inPlaceField.setHorizontalAlignment(SwingConstants.LEFT); } if (hTP == SwingConstants.LEFT || hTP == SwingConstants.LEADING) { bounds.width = tR.x - bounds.x + tR.width; inPlaceField.setHorizontalAlignment(SwingConstants.RIGHT); } } else { // hA == SwingConstants.CENTER if (hTP == SwingConstants.RIGHT || hTP == SwingConstants.TRAILING) { bounds.width -= tR.x - bounds.x; bounds.x = tR.x; inPlaceField.setHorizontalAlignment(SwingConstants.LEFT); } else if (hTP == SwingConstants.LEFT || hTP == SwingConstants.LEADING) { bounds.width = tR.x - bounds.x + tR.width; inPlaceField.setHorizontalAlignment(SwingConstants.RIGHT); } else if (bounds.width > tR.width) { bounds.x++; bounds.width--; } } } else if (hA == SwingConstants.CENTER && bounds.width > tR.width) { bounds.x++; bounds.width--; } bounds.x -= editingIns.left; bounds.width += editingIns.left + editingIns.right + 1; if (bounds.width < 10) bounds.width = 10; bounds.y = tR.y - editingIns.top; bounds.height = inPlaceField.getPreferredSize().height; /* else if (editedComp instanceof JTextField) { // JTextField field = (JTextField)editedComp; int height = editingTextComp.getPreferredSize().height; bounds.x += editedIns.left - editingIns.left; bounds.y += bounds.height/2 - height/2; bounds.width -= editedIns.left + editedIns.right - editingIns.left - editingIns.right - 1; if (bounds.width < 32) bounds.width = 32; bounds.height = height; } else if (editedComp instanceof JTextArea) { bounds.x += editedIns.left - editingIns.left; bounds.y += editedIns.top - editingIns.top; bounds.width -= editedIns.left + editedIns.right - editingIns.left - editingIns.right - 1; if (bounds.width < 64) bounds.width = 64; int height = editingTextComp.getPreferredSize().height; // System.out.println("height: "+height); if (((JTextArea)editingTextComp).getRows() == 0 && ((JTextArea)editingTextComp).getLineCount() < 2) { height *= 2; } // System.out.println("zvetsit? "+(((JTextArea)editingTextComp).getRows() == 0 && ((JTextArea)editingTextComp).getLineCount() < 2)); if (bounds.height < height) bounds.height = height; //editingTextComp.getPreferredSize().height; // + editingIns.top + editingIns.bottom; // bounds.height -= editedIns.top + editedIns.bottom - editingIns.top - editingIns.bottom; // TODO: scrollpane? editingTextComp.setSize(bounds.width, bounds.height); editingComp.setBounds(bounds.x-1, bounds.y-1, bounds.width+3, bounds.height+3); } */ // if (!(editedComp instanceof JTextArea)) inPlaceField.setBounds(bounds); inPlaceField.baseBounds = bounds; if (!(inPlaceField.getText().equals(editedText))) inPlaceField.adjustSize(); } // ---------------- public void requestFocus() { if (editingTextComp != null) { // System.out.println("bounds: "+editingTextComp.getBounds() // +", visible: "+editingTextComp.isVisible() // +", valid: "+editingTextComp.isValid() // +", showing: "+editingTextComp.isShowing()); editingTextComp.requestFocus(); int n = editingTextComp.getText().length(); editingTextComp.setCaretPosition(n); editingTextComp.moveCaretPosition(0); } else super.requestFocus(); } public boolean isOpaque() { return false; } // ------------- interface FinishListener extends java.util.EventListener { public void editingFinished(boolean changed); } public synchronized void addFinishListener(FinishListener l) { if (listeners == null) listeners = new ArrayList(); listeners.add(l); } public synchronized void removeFinishListener(FinishListener l) { if (listeners != null) listeners.remove(l); } private void fireEditingFinished() { ArrayList targets; synchronized (this) { if (listeners == null) return; targets = (ArrayList)listeners.clone(); } for (int i=0, n=targets.size(); i < n; i++) ((FinishListener)targets.get(i)).editingFinished(changeDone); } // ----------- /** Custom JTextField used as editing component on the layer. * It prevents focus manager from switching to another components * (using TAB and Shift+TAB). It also changes its size according to * entered text, with respect to underlying (edited) component's size. */ class InPlaceTextField extends JTextField { Rectangle baseBounds; public InPlaceTextField() { super(); } public InPlaceTextField(String text) { super(text); } protected void processKeyEvent(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_TAB || e.getKeyChar() == '\t') { e.consume(); } else { super.processKeyEvent(e); if (e.getID() == KeyEvent.KEY_TYPED) adjustSize(); } } void adjustSize() { int prefWidth = getPreferredSize().width + 1; if (prefWidth < baseBounds.width) prefWidth = baseBounds.width; Rectangle bounds = getBounds(); if (prefWidth != bounds.width) { Rectangle newBounds; if (prefWidth == baseBounds.width) newBounds = baseBounds; else { int layerWidth = InPlaceEditLayer.this.getSize().width; int leftX = baseBounds.x < 0 ? baseBounds.x : 0; int rightX = baseBounds.x + baseBounds.width > layerWidth ? baseBounds.x + baseBounds.width : layerWidth; newBounds = new Rectangle(bounds); int hA = getHorizontalAlignment(); if (hA == SwingConstants.LEFT || hA == SwingConstants.LEADING) { newBounds.x = rightX - prefWidth; if (newBounds.x < baseBounds.x) { // can't grow to right if (newBounds.x < leftX) newBounds.x = leftX; newBounds.width = rightX - newBounds.x; } else { newBounds.x = baseBounds.x; newBounds.width = prefWidth; } } else if (hA == SwingConstants.RIGHT || hA == SwingConstants.TRAILING) { newBounds.x = baseBounds.x + baseBounds.width - prefWidth; if (newBounds.x < leftX) { newBounds.x = leftX; newBounds.width = prefWidth > rightX - leftX ? rightX - leftX : prefWidth; } else newBounds.width = prefWidth; } else { // CENTER int cX = baseBounds.x + baseBounds.width/2; int dX1 = prefWidth/2; int dX2 = prefWidth - dX1; int over1, over2; if (cX - leftX < dX1) over2 = dX1 - (cX - leftX); else over2 = 0; if (rightX - cX < dX2) over1 = dX2 - (rightX - cX); else over1 = 0; if (cX - leftX < dX1 + over1) dX1 = cX - leftX; else dX1 += over1; if (rightX - cX < dX2 + over2) dX2 = rightX - cX; else dX2 += over2; newBounds.x = cX - dX1; newBounds.width = dX1 + dX2; } } if (!(newBounds.equals(bounds))) setBounds(newBounds); } } } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.