001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.form;
043:
044: import java.awt.*;
045: import java.awt.event.*;
046: import javax.swing.*;
047: import javax.swing.event.*;
048: import javax.swing.text.JTextComponent;
049: import java.util.ArrayList;
050:
051: /** A layer used by FormDesigner for in-place editing of components'
052: * labels and text. Can be used in two modes - layer editing or
053: * direct editing. In layer editing mode, a JTextField-based component
054: * is set up on the layer for editing labels and buttons. In direct editing
055: * mode, the edited component is used also for editing, the layer just
056: * ensures that other components are inaccessible.
057: *
058: * @author Tomas Pavek
059: */
060: public class InPlaceEditLayer extends JPanel {
061: private boolean layerEditing = true;
062:
063: private boolean changeDone = false;
064:
065: private String editedText;
066: private String oldText;
067: private boolean enabled;
068: private boolean madeEditable;
069:
070: private Component editedComp;
071: private Container super Container;
072: private JTextComponent editingTextComp;
073: private InPlaceTextField inPlaceField;
074:
075: private ComponentListener layerResizeListener;
076: private KeyListener compKeyListener;
077: private FocusListener compFocusListener;
078: private ActionListener compActionListener;
079:
080: private java.util.List<FinishListener> listeners;
081:
082: private Cursor defaultCursor;
083:
084: // ---------
085:
086: InPlaceEditLayer() {
087: setLayout(null);
088: defaultCursor = getCursor();
089: }
090:
091: void setEditedComponent(Component comp, String text) {
092: if (!comp.isShowing() || comp.getParent() == null)
093: throw new IllegalArgumentException();
094:
095: editedComp = comp;
096: editedText = text;
097: if (inPlaceField != null) {
098: remove(inPlaceField);
099: inPlaceField = null;
100: }
101:
102: if (comp instanceof JLabel || comp instanceof AbstractButton
103: || comp instanceof JTabbedPane) {
104: layerEditing = true;
105: super Container = null;
106: createInPlaceField();
107: } else if (comp instanceof JTextField
108: || comp instanceof JTextArea) {
109: layerEditing = false;
110: super Container = comp.getParent();
111:
112: Container cont = super Container;
113: do {
114: if (cont.getParent() instanceof JLayeredPane) {
115: super Container = cont;
116: break;
117: } else
118: cont = cont.getParent();
119: } while (cont != null);
120:
121: editingTextComp = (JTextComponent) editedComp;
122: oldText = editingTextComp.getText();
123: editingTextComp.setText(editedText);
124:
125: // enable focus on component in component layer
126: editingTextComp.setFocusable(true);
127: if (!editingTextComp.isEnabled()) {
128: editingTextComp.setEnabled(true);
129: enabled = true;
130: }
131: if (!editingTextComp.isEditable()) {
132: editingTextComp.setEditable(true);
133: madeEditable = true;
134: }
135: } else
136: throw new IllegalArgumentException();
137:
138: if (editingTextComp != null) {
139: FormUtils.setupTextUndoRedo(editingTextComp);
140: }
141:
142: attachListeners();
143: }
144:
145: // ------------
146:
147: static boolean supportsEditingFor(Class compClass,
148: boolean layerRequired) {
149: return JLabel.class.isAssignableFrom(compClass)
150: || AbstractButton.class.isAssignableFrom(compClass)
151: || JTabbedPane.class.isAssignableFrom(compClass)
152: || (!layerRequired && (JTextField.class
153: .isAssignableFrom(compClass) || JTextArea.class
154: .isAssignableFrom(compClass)));
155: }
156:
157: boolean isEditingInitialized() {
158: return editingTextComp != null;
159: }
160:
161: boolean isLayerEditing() {
162: return layerEditing;
163: }
164:
165: String getEditedText() {
166: return editedText;
167: }
168:
169: boolean isTextChanged() {
170: return changeDone;
171: }
172:
173: void finishEditing(boolean applyChanges) {
174: if (applyChanges) {
175: String text = editingTextComp.getText();
176: if (text.equals(editedText))
177: applyChanges = false;
178: else
179: editedText = text;
180: } else if (!isLayerEditing()) {
181: editingTextComp.setText(oldText);
182: editingTextComp.setFocusable(false);
183: }
184:
185: editingTextComp.removeKeyListener(compKeyListener);
186: editingTextComp.removeFocusListener(compFocusListener);
187: if (editingTextComp instanceof JTextField)
188: ((JTextField) editingTextComp)
189: .removeActionListener(compActionListener);
190: if (editingTextComp == editedComp) {
191: if (enabled) {
192: editingTextComp.setEnabled(false);
193: enabled = false;
194: }
195: if (madeEditable) {
196: editingTextComp.setEditable(false);
197: madeEditable = false;
198: }
199: }
200: editingTextComp = null;
201:
202: changeDone = applyChanges;
203: fireEditingFinished();
204: }
205:
206: // ----------------
207:
208: private void createInPlaceField() {
209: if (editedComp instanceof JLabel) {
210: JLabel label = (JLabel) editedComp;
211: inPlaceField = new InPlaceTextField(editedText);
212: inPlaceField.setFont(label.getFont());
213: inPlaceField.setHorizontalAlignment(label
214: .getHorizontalAlignment());
215: // inPlaceField.setNextFocusableComponent(this);
216: // inPlaceField.setBorder(new javax.swing.border.EmptyBorder(0,0,0,0));
217: // inPlaceField.setBackground(label.getBackground());
218: // inPlaceField.setForeground(label.getForeground());
219: // inPlaceField.setSelectedTextColor(label.getForeground());
220: } else if (editedComp instanceof AbstractButton) {
221: AbstractButton button = (AbstractButton) editedComp;
222: inPlaceField = new InPlaceTextField(editedText);
223: inPlaceField.setFont(button.getFont());
224: inPlaceField.setHorizontalAlignment(button
225: .getHorizontalAlignment());
226: // inPlaceField.setNextFocusableComponent(this);
227: } else if (editedComp instanceof JTabbedPane) {
228: inPlaceField = new InPlaceTextField(editedText);
229: inPlaceField.setFont(((JTabbedPane) editedComp).getFont());
230: inPlaceField.setHorizontalAlignment(SwingConstants.CENTER);
231: Insets insets = inPlaceField.getInsets();
232: inPlaceField.setMargin(new Insets(0, insets.left, 0,
233: insets.right));
234: } else
235: return; // should not happen
236: /* else if (editedComp instanceof JTextField) {
237: JTextField field = (JTextField)editedComp;
238: JTextField textField = new InPlaceTextField(editedText);
239: textField.setFont(field.getFont());
240: textField.setHorizontalAlignment(field.getHorizontalAlignment());
241:
242: editingComp = textField;
243: editingTextComp = textField;
244: }
245: else if (editedComp instanceof JTextArea) {
246: JTextArea textA = (JTextArea)editedComp;
247: JTextArea textArea = new JTextArea(editedText);
248: textArea.setFont(textA.getFont());
249: textArea.setTabSize(textA.getTabSize());
250: textArea.setRows(textA.getRows());
251: textArea.setColumns(textA.getColumns());
252: textArea.setLineWrap(textA.getLineWrap());
253: // textArea.setBorder(new javax.swing.border.LineBorder(Color.black));
254: // TODO: scrollpane, resizing
255: JScrollPane scroll = new JScrollPane(textArea);
256:
257: editingComp = scroll; //textArea;
258: editingTextComp = textArea;
259: } */
260:
261: editingTextComp = inPlaceField;
262: add(inPlaceField);
263: placeInPlaceField();
264: }
265:
266: private void attachListeners() {
267: if (layerResizeListener != null)
268: removeComponentListener(layerResizeListener);
269: else
270: createListeners();
271:
272: if (isLayerEditing())
273: addComponentListener(layerResizeListener);
274:
275: editingTextComp.addKeyListener(compKeyListener);
276: editingTextComp.addFocusListener(compFocusListener);
277: if (editingTextComp instanceof JTextField)
278: ((JTextField) editingTextComp)
279: .addActionListener(compActionListener);
280: }
281:
282: private void createListeners() {
283: // listening for mouse events
284: MouseInputListener layerMouseListener = new MouseInputListener() {
285: public void mouseClicked(MouseEvent e) {
286: processMouse(e);
287: }
288:
289: public void mousePressed(MouseEvent e) {
290: processMouse(e);
291: }
292:
293: public void mouseReleased(MouseEvent e) {
294: processMouse(e);
295: }
296:
297: public void mouseEntered(MouseEvent e) {
298: processMouse(e);
299: }
300:
301: public void mouseExited(MouseEvent e) {
302: processMouse(e);
303: }
304:
305: public void mouseDragged(MouseEvent e) {
306: processMouse(e);
307: }
308:
309: public void mouseMoved(MouseEvent e) {
310: processMouse(e);
311: }
312: };
313: addMouseListener(layerMouseListener);
314: addMouseMotionListener(layerMouseListener);
315:
316: // listening for layer resizing
317: layerResizeListener = new ComponentAdapter() {
318: @Override
319: public void componentResized(ComponentEvent e) {
320: if (InPlaceEditLayer.this .isVisible())
321: placeInPlaceField();
322: }
323: };
324:
325: // listening for Escape and Ctrl+Enter
326: compKeyListener = new KeyAdapter() {
327: @Override
328: public void keyPressed(KeyEvent e) {
329: if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
330: finishEditing(false);
331: else if (e.getModifiers() == InputEvent.CTRL_MASK
332: && (e.getKeyCode() == 10 || e.getKeyCode() == KeyEvent.VK_ENTER))
333: finishEditing(true);
334: }
335: };
336:
337: // listening for focus lost
338: compFocusListener = new FocusAdapter() {
339: @Override
340: public void focusLost(FocusEvent event) {
341: finishEditing(true);
342: }
343: };
344:
345: // listening for Enter
346: compActionListener = new ActionListener() {
347: public void actionPerformed(ActionEvent evt) {
348: finishEditing(true);
349: }
350: };
351: }
352:
353: private void processMouse(MouseEvent e) {
354: if (!isEditingInitialized())
355: return;
356:
357: if (isLayerEditing()) {
358: if (e.getID() == MouseEvent.MOUSE_PRESSED)
359: finishEditing(true); // or false?
360: } else {
361: Point p = SwingUtilities.convertPoint(this , e.getPoint(),
362: super Container);
363: Component comp = SwingUtilities.getDeepestComponentAt(
364: super Container, p.x, p.y);
365: if (comp != editedComp) {
366: Container cont = editedComp.getParent();
367: if (comp != cont || !(cont instanceof JScrollPane))
368: comp = null;
369: }
370: if (comp != null) {
371: comp.dispatchEvent(SwingUtilities.convertMouseEvent(
372: this , e, comp));
373:
374: if (e.getID() == MouseEvent.MOUSE_MOVED) {
375: Cursor cursor = comp.getCursor();
376: if (getCursor() != cursor)
377: setCursor(cursor);
378: }
379: } else {
380: if (e.getID() == MouseEvent.MOUSE_PRESSED)
381: finishEditing(true); // or false?
382: else if (e.getID() == MouseEvent.MOUSE_MOVED)
383: if (getCursor() != defaultCursor)
384: setCursor(defaultCursor);
385: }
386: }
387: }
388:
389: private void placeInPlaceField() {
390: // if (!(editedComp instanceof JLabel) && !(editedComp instanceof AbstractButton))
391: // return;
392: Rectangle bounds = SwingUtilities.convertRectangle(editedComp
393: .getParent(), editedComp.getBounds(), this );
394: Insets editedIns = ((JComponent) editedComp).getInsets();
395: Insets editingIns = inPlaceField.getInsets();
396:
397: int hA, hTP, vA, vTP;
398: Icon icon;
399: int itGap;
400: String text;
401:
402: if (editedComp instanceof JLabel) {
403: JLabel label = (JLabel) editedComp;
404:
405: hA = label.getHorizontalAlignment();
406: hTP = label.getHorizontalTextPosition();
407: vA = label.getVerticalAlignment();
408: vTP = label.getVerticalTextPosition();
409:
410: icon = label.getIcon();
411: itGap = icon != null ? label.getIconTextGap() : 0;
412: text = label.getText();
413: } else if (editedComp instanceof AbstractButton) {
414: AbstractButton button = (AbstractButton) editedComp;
415:
416: hA = button.getHorizontalAlignment();
417: hTP = button.getHorizontalTextPosition();
418: vA = button.getVerticalAlignment();
419: vTP = button.getVerticalTextPosition();
420:
421: icon = button.getIcon();
422: if (icon != null || editedComp instanceof JMenuItem) {
423: Integer gap = (Integer) UIManager
424: .get("Button.textIconGap"); // NOI18N
425: itGap = gap != null ? gap.intValue() : 4;
426: } else
427: itGap = 0;
428: text = button.getText();
429:
430: if (editedComp instanceof JCheckBox
431: || editedComp instanceof JRadioButton) {
432: if (icon == null) {
433: javax.swing.plaf.ComponentUI cui = UIManager
434: .getUI((JComponent) editedComp);
435: if (cui instanceof javax.swing.plaf.basic.BasicRadioButtonUI) {
436: icon = ((javax.swing.plaf.basic.BasicRadioButtonUI) cui)
437: .getDefaultIcon();
438: itGap = ((javax.swing.plaf.basic.BasicRadioButtonUI) cui)
439: .getDefaultTextIconGap(button);
440: }
441: }
442: // hack: border at the aligned side is always 0 (bug?)
443: if (hA == SwingConstants.LEFT
444: || hA == SwingConstants.LEADING) {
445: editedIns.right += editedIns.left;
446: editedIns.left = 0;
447: } else if (hA == SwingConstants.RIGHT
448: || hA == SwingConstants.TRAILING) {
449: editedIns.left += editedIns.right;
450: editedIns.right = 0;
451: }
452: if (vA == SwingConstants.TOP) {
453: editedIns.bottom += editedIns.top;
454: editedIns.top = 0;
455: } else if (vA == SwingConstants.BOTTOM) {
456: editedIns.top += editedIns.bottom;
457: editedIns.bottom = 0;
458: }
459: }
460: } else if (editedComp instanceof JTabbedPane) {
461: JTabbedPane tabbedPane = (JTabbedPane) editedComp;
462: int index = tabbedPane.getSelectedIndex();
463: text = tabbedPane.getTitleAt(index);
464: Rectangle relBounds = tabbedPane.getBoundsAt(index);
465: relBounds.x += bounds.x + 4;
466: relBounds.y += bounds.y;
467: bounds = relBounds;
468: bounds.width -= 8;
469: icon = tabbedPane.getIconAt(index);
470: itGap = UIManager.getInt("TabbedPane.textIconGap"); // NOI18N
471: vA = hA = vTP = SwingConstants.CENTER;
472: hTP = SwingConstants.TRAILING;
473: editedIns = new Insets(0, 0, 0, 0);
474: } else
475: return; // should not happen
476:
477: bounds.x += editedIns.left;
478: bounds.y += editedIns.top;
479: bounds.width -= editedIns.left + editedIns.right;
480: bounds.height -= editedIns.top + editedIns.bottom;
481: Rectangle iR = new Rectangle(); // icon rectangle
482: Rectangle tR = new Rectangle(); // text rectangle
483:
484: //HACK: a hack to account for the extra space on the right edge of the menu item
485: //we should derive this value instead of hard coding it
486: //don't set this value if it's really a toplevel jmenu
487: if (editedComp instanceof JMenuItem
488: && editedComp.getParent() != null
489: && !(editedComp.getParent() instanceof JMenuBar)) {
490: int menugap = 13;
491: bounds.x += menugap;
492: bounds.width -= menugap;
493: }
494:
495: SwingUtilities.layoutCompoundLabel((JComponent) editedComp,
496: editedComp.getGraphics().getFontMetrics(), text, icon,
497: vA, hA, vTP, hTP, bounds, iR, tR, itGap);
498:
499: if (icon != null && hTP != SwingConstants.CENTER) {
500: if (hA == SwingConstants.LEFT
501: || hA == SwingConstants.LEADING) {
502: if (hTP == SwingConstants.RIGHT
503: || hTP == SwingConstants.TRAILING) {
504: bounds.width -= tR.x - bounds.x;
505: bounds.x = tR.x;
506: inPlaceField
507: .setHorizontalAlignment(SwingConstants.LEFT);
508: } else if (hTP == SwingConstants.LEFT
509: || hTP == SwingConstants.LEADING) {
510: bounds.width = tR.width;
511: inPlaceField
512: .setHorizontalAlignment(SwingConstants.RIGHT);
513: }
514: } else if (hA == SwingConstants.RIGHT
515: || hA == SwingConstants.TRAILING) {
516: if (hTP == SwingConstants.RIGHT
517: || hTP == SwingConstants.TRAILING) {
518: bounds.x = tR.x;
519: bounds.width = tR.width;
520: inPlaceField
521: .setHorizontalAlignment(SwingConstants.LEFT);
522: }
523: if (hTP == SwingConstants.LEFT
524: || hTP == SwingConstants.LEADING) {
525: bounds.width = tR.x - bounds.x + tR.width;
526: inPlaceField
527: .setHorizontalAlignment(SwingConstants.RIGHT);
528: }
529: } else { // hA == SwingConstants.CENTER
530: if (hTP == SwingConstants.RIGHT
531: || hTP == SwingConstants.TRAILING) {
532: bounds.width -= tR.x - bounds.x;
533: bounds.x = tR.x;
534: inPlaceField
535: .setHorizontalAlignment(SwingConstants.LEFT);
536: } else if (hTP == SwingConstants.LEFT
537: || hTP == SwingConstants.LEADING) {
538: bounds.width = tR.x - bounds.x + tR.width;
539: inPlaceField
540: .setHorizontalAlignment(SwingConstants.RIGHT);
541: } else if (bounds.width > tR.width) {
542: bounds.x++;
543: bounds.width--;
544: }
545: }
546: } else if (hA == SwingConstants.CENTER
547: && bounds.width > tR.width) {
548: bounds.x++;
549: bounds.width--;
550: }
551:
552: bounds.x -= editingIns.left;
553: bounds.width += editingIns.left + editingIns.right + 1;
554: if (bounds.width < 10)
555: bounds.width = 10;
556:
557: bounds.y = tR.y - editingIns.top;
558: bounds.height = inPlaceField.getPreferredSize().height;
559:
560: /* else if (editedComp instanceof JTextField) {
561: // JTextField field = (JTextField)editedComp;
562: int height = editingTextComp.getPreferredSize().height;
563:
564: bounds.x += editedIns.left - editingIns.left;
565: bounds.y += bounds.height/2 - height/2;
566: bounds.width -= editedIns.left + editedIns.right - editingIns.left - editingIns.right - 1;
567: if (bounds.width < 32)
568: bounds.width = 32;
569: bounds.height = height;
570: }
571: else if (editedComp instanceof JTextArea) {
572: bounds.x += editedIns.left - editingIns.left;
573: bounds.y += editedIns.top - editingIns.top;
574: bounds.width -= editedIns.left + editedIns.right - editingIns.left - editingIns.right - 1;
575: if (bounds.width < 64)
576: bounds.width = 64;
577: int height = editingTextComp.getPreferredSize().height;
578: // System.out.println("height: "+height);
579: if (((JTextArea)editingTextComp).getRows() == 0 && ((JTextArea)editingTextComp).getLineCount() < 2) {
580: height *= 2;
581: }
582: // System.out.println("zvetsit? "+(((JTextArea)editingTextComp).getRows() == 0 && ((JTextArea)editingTextComp).getLineCount() < 2));
583: if (bounds.height < height)
584: bounds.height = height; //editingTextComp.getPreferredSize().height; // + editingIns.top + editingIns.bottom;
585: // bounds.height -= editedIns.top + editedIns.bottom - editingIns.top - editingIns.bottom;
586: // TODO: scrollpane?
587: editingTextComp.setSize(bounds.width, bounds.height);
588: editingComp.setBounds(bounds.x-1, bounds.y-1, bounds.width+3, bounds.height+3);
589: } */
590:
591: // if (!(editedComp instanceof JTextArea))
592: inPlaceField.setBounds(bounds);
593: inPlaceField.baseBounds = bounds;
594: if (!(inPlaceField.getText().equals(editedText)))
595: inPlaceField.adjustSize();
596: }
597:
598: // ----------------
599:
600: @Override
601: public void requestFocus() {
602: if (editingTextComp != null) {
603: // System.out.println("bounds: "+editingTextComp.getBounds()
604: // +", visible: "+editingTextComp.isVisible()
605: // +", valid: "+editingTextComp.isValid()
606: // +", showing: "+editingTextComp.isShowing());
607: editingTextComp.requestFocus();
608: int n = editingTextComp.getText().length();
609: editingTextComp.setCaretPosition(n);
610: editingTextComp.moveCaretPosition(0);
611: } else
612: super .requestFocus();
613: }
614:
615: @Override
616: public boolean isOpaque() {
617: return false;
618: }
619:
620: // -------------
621:
622: public interface FinishListener extends java.util.EventListener {
623: public void editingFinished(boolean changed);
624: }
625:
626: public synchronized void addFinishListener(FinishListener l) {
627: if (listeners == null)
628: listeners = new ArrayList<FinishListener>();
629: listeners.add(l);
630: }
631:
632: public synchronized void removeFinishListener(FinishListener l) {
633: if (listeners != null)
634: listeners.remove(l);
635: }
636:
637: private void fireEditingFinished() {
638: java.util.List<FinishListener> targets;
639: synchronized (this ) {
640: if (listeners == null)
641: return;
642: targets = new ArrayList<FinishListener>(listeners);
643: }
644: for (int i = 0, n = targets.size(); i < n; i++)
645: targets.get(i).editingFinished(changeDone);
646: }
647:
648: // -----------
649:
650: /** Custom JTextField used as editing component on the layer.
651: * It prevents focus manager from switching to another components
652: * (using TAB and Shift+TAB). It also changes its size according to
653: * entered text, with respect to underlying (edited) component's size.
654: */
655: class InPlaceTextField extends JTextField {
656: Rectangle baseBounds;
657:
658: public InPlaceTextField() {
659: super ();
660: }
661:
662: public InPlaceTextField(String text) {
663: super (text);
664: }
665:
666: @Override
667: protected void processKeyEvent(KeyEvent e) {
668: if (e.getKeyCode() == KeyEvent.VK_TAB
669: || e.getKeyChar() == '\t') {
670: e.consume();
671: } else {
672: super .processKeyEvent(e);
673: if (e.getID() == KeyEvent.KEY_TYPED)
674: adjustSize();
675: }
676: }
677:
678: void adjustSize() {
679: int prefWidth = getPreferredSize().width + 1;
680: if (prefWidth < baseBounds.width)
681: prefWidth = baseBounds.width;
682: Rectangle bounds = getBounds();
683:
684: if (prefWidth != bounds.width) {
685: Rectangle newBounds;
686: if (prefWidth == baseBounds.width)
687: newBounds = baseBounds;
688: else {
689: int layerWidth = InPlaceEditLayer.this .getSize().width;
690: int leftX = baseBounds.x < 0 ? baseBounds.x : 0;
691: int rightX = baseBounds.x + baseBounds.width > layerWidth ? baseBounds.x
692: + baseBounds.width
693: : layerWidth;
694:
695: newBounds = new Rectangle(bounds);
696:
697: int hA = getHorizontalAlignment();
698: if (hA == SwingConstants.LEFT
699: || hA == SwingConstants.LEADING) {
700: newBounds.x = rightX - prefWidth;
701: if (newBounds.x < baseBounds.x) { // can't grow to right
702: if (newBounds.x < leftX)
703: newBounds.x = leftX;
704: newBounds.width = rightX - newBounds.x;
705: } else {
706: newBounds.x = baseBounds.x;
707: newBounds.width = prefWidth;
708: }
709: } else if (hA == SwingConstants.RIGHT
710: || hA == SwingConstants.TRAILING) {
711: newBounds.x = baseBounds.x + baseBounds.width
712: - prefWidth;
713: if (newBounds.x < leftX) {
714: newBounds.x = leftX;
715: newBounds.width = prefWidth > rightX
716: - leftX ? rightX - leftX
717: : prefWidth;
718: } else
719: newBounds.width = prefWidth;
720: } else { // CENTER
721: int cX = baseBounds.x + baseBounds.width / 2;
722: int dX1 = prefWidth / 2;
723: int dX2 = prefWidth - dX1;
724:
725: int over1, over2;
726: if (cX - leftX < dX1)
727: over2 = dX1 - (cX - leftX);
728: else
729: over2 = 0;
730: if (rightX - cX < dX2)
731: over1 = dX2 - (rightX - cX);
732: else
733: over1 = 0;
734:
735: if (cX - leftX < dX1 + over1)
736: dX1 = cX - leftX;
737: else
738: dX1 += over1;
739: if (rightX - cX < dX2 + over2)
740: dX2 = rightX - cX;
741: else
742: dX2 += over2;
743:
744: newBounds.x = cX - dX1;
745: newBounds.width = dX1 + dX2;
746: }
747: }
748:
749: if (!(newBounds.equals(bounds)))
750: setBounds(newBounds);
751: }
752: }
753: }
754: }
|