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-2007 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: package org.netbeans.modules.visualweb.designer;
042:
043: import org.netbeans.modules.visualweb.api.designer.DomProvider;
044: import org.netbeans.modules.visualweb.api.designer.DomProvider.DomPosition;
045: import org.netbeans.modules.visualweb.api.designer.cssengine.CssProvider;
046: import java.awt.Color;
047: import java.awt.Component;
048: import java.awt.Dimension;
049: import java.awt.Font;
050: import java.awt.Rectangle;
051: import java.awt.datatransfer.StringSelection;
052: import java.awt.datatransfer.Transferable;
053: import java.awt.event.ActionEvent;
054: import java.awt.event.ActionListener;
055: import java.awt.event.FocusListener;
056: import java.awt.event.InputEvent;
057: import java.awt.event.KeyEvent;
058: import java.awt.event.MouseEvent;
059:
060: import java.util.logging.Level;
061: import java.util.logging.Logger;
062: import javax.swing.AbstractAction;
063: import javax.swing.Action;
064: import javax.swing.JComponent;
065: import javax.swing.JRootPane;
066: import javax.swing.JScrollPane;
067: import javax.swing.JTextArea;
068: import javax.swing.JTextField;
069: import javax.swing.KeyStroke;
070: import javax.swing.UIManager;
071: import javax.swing.event.DocumentListener;
072: import javax.swing.event.MouseInputAdapter;
073: import javax.swing.text.BadLocationException;
074: import javax.swing.text.DefaultEditorKit;
075: import javax.swing.text.JTextComponent;
076:
077: import org.w3c.dom.DocumentFragment;
078: import org.w3c.dom.Element;
079: import org.w3c.dom.Node;
080: import org.w3c.dom.NodeList;
081:
082: import org.netbeans.modules.visualweb.css2.CssBox;
083: import org.netbeans.modules.visualweb.css2.CustomButtonBox;
084: import org.netbeans.modules.visualweb.css2.FormComponentBox;
085: import org.netbeans.modules.visualweb.api.designer.cssengine.XhtmlCss;
086: import org.netbeans.modules.visualweb.designer.html.HtmlAttribute;
087: import org.netbeans.modules.visualweb.designer.html.HtmlTag;
088:
089: /**
090: * Editor for form components like buttons, text fields and text areas. These
091: * are similar to AttributeInlineEditor in that an attribute value is being
092: * edited (e.g. "value" for a button) but unlike AttributeInlineEditor components
093: * such as StaticText, these components also -render- to attributes rather than
094: * text nodes. Second, the visualization is a bit different; we cannot use the normal
095: * caret support etc. since this content is not flow editable and we don't know
096: * the internal position of a caret inside a text area for example. It uses an
097: * inplace JTextField instead (or in the case of a text area, a JTextArea)
098: *
099: * @author Tor Norbye
100: */
101: class FormComponentEditor extends InlineEditor {
102: /** Set whether we should try to place the text field on top of the regular component
103: * and attempt to emulate its font and colors rather than using a text field below it.
104: * (Text fields are always handled this way; this flag controls other components).
105: */
106: private static final boolean EDIT_ADJACENT = Boolean
107: .getBoolean("rave.edit-adjacent");
108:
109: /** The component being added to the designpane (temporarily) as an editing component -
110: * usually a JTextField or a JTextArea, but possibly wrapped inside a JScrollPane */
111: protected JComponent inlineEditor;
112:
113: /** The actual text component serving as the editor - always a JTextComponent such as
114: * a text field or a text area. This component may be wrapped in another in the
115: * design surface (such as a scroll pane) */
116: protected JTextComponent inlineTextEditor;
117: private final Handler handler = new Handler();
118: private CssBox box;
119: // private String xpath;
120: private boolean hasBeenEdited = false;
121:
122: // private DesignProperty property;
123:
124: private FormComponentEditor(WebForm webform, /*MarkupDesignBean bean, DesignProperty property,*/
125: CssBox box/*, String xpath*/,
126: DomProvider.InlineEditorSupport inlineEditorSupport) {
127: // super(webform, bean, property.getPropertyDescriptor().getName());
128: super (webform, /*bean,*/inlineEditorSupport);
129: if (DesignerUtils.DEBUG) {
130: DesignerUtils.debugLog(getClass().getName() + "()");
131: }
132: if (box == null) {
133: throw (new IllegalArgumentException("Null CSS box."));
134: }
135: // this.property = property;
136: this .box = box;
137: // this.xpath = xpath;
138: }
139:
140: public static FormComponentEditor get(WebForm webform, /*String xpath,*/
141: CssBox box, Element componentRootElement,
142: DomProvider.InlineEditorSupport inlineEditorSupport) {
143: // if (xpath != null) {
144: //// RaveElement sourceElement = (RaveElement)bean.getElement();
145: //// RaveElement root = sourceElement.getRendered();
146: //// Element sourceElement = bean.getElement();
147: //// Element root = MarkupService.getRenderedElementForElement(sourceElement);
148: //
149: // Element root = componentRootElement;
150: // if (root != null) {
151: //// Node node = findPropertyNode(root, xpath);
152: // Node node = WebForm.getDomProviderService().findPropertyNode(root, xpath);
153: //
154: // if ((node != null) && (node.getNodeType() == Node.ELEMENT_NODE)) {
155: // Element element = (Element)node;
156: // HtmlTag tag = HtmlTag.getTag(element.getTagName());
157: //
158: // if ((tag != null) && tag.isFormMemberTag()) {
159: //// CssBox b = CssBox.getBox(element);
160: // CssBox b = webform.findCssBoxForElement(element);
161: //
162: // if (b != null) {
163: // box = b;
164: // }
165: // }
166: // }
167: // }
168: // }
169: Node node = inlineEditorSupport
170: .findXPathNodeForComponentRootElement(componentRootElement);
171:
172: if ((node != null) && (node.getNodeType() == Node.ELEMENT_NODE)) {
173: Element element = (Element) node;
174: HtmlTag tag = HtmlTag.getTag(element.getTagName());
175:
176: if ((tag != null) && tag.isFormMemberTag()) {
177: // CssBox b = CssBox.getBox(element);
178: CssBox b = webform.findCssBoxForElement(element);
179:
180: if (b != null) {
181: box = b;
182: }
183: }
184: }
185:
186: if (!(box instanceof FormComponentBox || box instanceof CustomButtonBox)) {
187: return null;
188: }
189:
190: // Skip input-hiddens
191: if (box instanceof FormComponentBox
192: && (((FormComponentBox) box).getComponent() == null)) {
193: return null;
194: }
195:
196: // if (!isEditingAllowed(property)) {
197: if (!inlineEditorSupport.isEditingAllowed()) {
198: return null;
199: }
200:
201: // TODO - need metadata to specify the descriptor to use!
202: return new FormComponentEditor(webform, /*bean, property,*/
203: box/*, xpath*/, inlineEditorSupport);
204: }
205:
206: public void start(boolean selectText, String initialEdit) {
207: finish(true); // is cancelling the previous edit the right thing to do here?
208:
209: JComponent component = null;
210: Element element = null;
211:
212: if (box instanceof FormComponentBox) {
213: FormComponentBox formComp = (FormComponentBox) box;
214: component = formComp.getComponent();
215: element = formComp.getElement();
216: // } else {
217: //// element = bean.getElement();
218: ////
219: ////// RaveElement xel = (RaveElement)element;
220: ////// if (xel.getRendered() != null) {
221: ////// element = xel.getRendered();
222: ////// }
223: //// Element rendered = MarkupService.getRenderedElementForElement(element);
224: //// if (rendered != null) {
225: //// element = rendered;
226: //// }
227: // element = inlineEditorSupport.getRenderedElement();
228: // }
229: } else if (box instanceof CustomButtonBox) {
230: element = box.getElement();
231: } else {
232: info(new IllegalStateException(
233: "Unsupported box type used, box=" + box)); // NOI18N
234: return;
235: }
236:
237: int width;
238: int height;
239: boolean positionAdjacent = EDIT_ADJACENT;
240:
241: // XXX The font size should match the computed value including the stylesheet definitions.
242: // See stripDesignStyleClasses below.
243: // float fontSize = CssProvider.getValueService().getFontSizeForElement(element, DesignerSettings.getInstance().getDefaultFontSize());
244: float fontSize = CssProvider.getValueService()
245: .getFontSizeForElement(element,
246: webform.getDefaultFontSize());
247: if (component instanceof JTextField) {
248: // XXX #6491646 Don't use the rendered component for inline editing.
249: // It has problems with fonts.
250: JTextField renderedTextField = (JTextField) component;
251: // JTextField inlineTextField = new JTextField(renderedTextField.getText(), renderedTextField.getColumns());
252: JTextField inlineTextField = FormComponentBox
253: .createTextField(renderedTextField.getText(),
254: renderedTextField.getColumns());
255: Font font = UIManager.getFont("TextField.font"); // NOI18N
256: inlineTextField.setFont(font.deriveFont(fontSize));
257:
258: // inlineTextEditor = (JTextField)component;
259: inlineTextEditor = inlineTextField;
260: inlineEditor = inlineTextEditor;
261:
262: positionAdjacent = false;
263:
264: width = component.getWidth();
265: height = component.getHeight();
266:
267: Dimension prefSize = inlineEditor.getPreferredSize();
268:
269: if (width < 10) {
270: width = prefSize.width;
271: }
272:
273: if (height < 8) {
274: height = prefSize.height;
275: }
276: } else if (component instanceof JScrollPane
277: && ((JScrollPane) component).getViewport().getView() instanceof JTextArea) {
278: // XXX #6491646 Don't use the rendered component for inline editing.
279: // It has problems with fonts.
280: JScrollPane renderedScrollPane = (JScrollPane) component;
281: JTextArea renderedTextArea = (JTextArea) ((JScrollPane) component)
282: .getViewport().getView();
283: // JTextArea inlineTextArea = new JTextArea(renderedTextArea.getText(), renderedTextArea.getRows(), renderedTextArea.getColumns());
284: JTextArea inlineTextArea = FormComponentBox.createTextArea(
285: renderedTextArea.getText(), renderedTextArea
286: .getRows(), renderedTextArea.getColumns());
287: JScrollPane inlineScrollPane = new JScrollPane(
288: inlineTextArea, renderedScrollPane
289: .getVerticalScrollBarPolicy(),
290: renderedScrollPane.getHorizontalScrollBarPolicy());
291: Font font = UIManager.getFont("TextArea.font"); // NOI18N
292: inlineTextArea.setFont(font.deriveFont(fontSize));
293:
294: // inlineEditor = component;
295: // inlineTextEditor = (JTextArea)((JScrollPane)component).getViewport().getView();
296: inlineEditor = inlineScrollPane;
297: inlineTextEditor = inlineTextArea;
298: positionAdjacent = false;
299:
300: width = component.getWidth();
301: height = component.getHeight();
302:
303: Dimension prefSize = inlineEditor.getPreferredSize();
304:
305: if (width < 10) {
306: width = prefSize.width;
307: }
308:
309: if (height < 8) {
310: height = prefSize.height;
311: }
312: } else {
313: // JTextField field = new JTextField();
314: JTextField field = FormComponentBox.createTextField();
315: field.setColumns(9);
316: inlineTextEditor = field;
317: inlineEditor = inlineTextEditor;
318:
319: if (!positionAdjacent) { // For adjacent edits, use normal text field size, font, etc.
320:
321: // XXX This seems to be redundant here. The rendered element provides all needed info.
322: //// DocumentFragment fragment = webform.getDomSynchronizer().createSourceFragment(bean);
323: //// DocumentFragment fragment = webform.createSourceFragment(bean);
324: // DocumentFragment fragment = inlineEditorSupport.createSourceFragment();
325: //
326: // NodeList nl = fragment.getChildNodes();
327: //
328: // for (int i = 0, n = nl.getLength(); i < n; i++) {
329: // Node child = nl.item(i);
330: //
331: // if (child.getNodeType() == Node.ELEMENT_NODE) {
332: // Element e = (Element)child;
333: //
334: // HtmlTag tag = HtmlTag.getTag(e.getTagName());
335: //
336: // if ((tag != null) && tag.isFormMemberTag()) {
337: // if (e.getAttribute(HtmlAttribute.TYPE).equals("hidden")) { // NOI18N
338: //
339: // continue;
340: // }
341: //
342: // // XXX What is this for a hack? Revise.
343: // DesignerUtils.stripDesignStyleClasses(fragment);
344: // element = e;
345: //
346: // break;
347: // }
348: // }
349: // }
350:
351: // Color bg = CssLookup.getColor(element, XhtmlCss.BACKGROUND_COLOR_INDEX);
352: // Color fg = CssLookup.getColor(element, XhtmlCss.COLOR_INDEX);
353: Color bg = CssProvider.getValueService()
354: .getColorForElement(element,
355: XhtmlCss.BACKGROUND_COLOR_INDEX);
356: Color fg = CssProvider.getValueService()
357: .getColorForElement(element,
358: XhtmlCss.COLOR_INDEX);
359: // Font font = CssLookup.getFont(element, fontSize);
360: // Font font = CssProvider.getValueService().getFontForElement(element, DesignerSettings.getInstance().getDefaultFontSize(), Font.PLAIN);
361: // Font font = CssBoxUtilities.getDesignerFontForElement(element, initialEdit);
362: //
363: // // XXX The above returns the default size because of the stripped stylesheets. We need to adjust it to the original size.
364: // font = font.deriveFont((float)fontSize);
365:
366: if (bg != null) { // XXX TODO: find other background from ancestor hierarchy?
367: inlineEditor.setBackground(bg);
368: }
369:
370: if (fg != null) {
371: inlineEditor.setForeground(fg);
372: }
373:
374: // if (font != null) {
375: // inlineEditor.setFont(font);
376: // }
377: // XXX #6461942 Don't change the font, it might not be able to show multibyte chars.
378: // Now we adjust the size only.
379: Font oldFont = inlineEditor.getFont();
380: inlineEditor.setFont(oldFont.deriveFont(fontSize));
381: }
382:
383: Dimension prefSize = inlineEditor.getPreferredSize();
384:
385: if (box != null) {
386: width = box.getWidth();
387: height = box.getHeight();
388: } else {
389: // width = CssLookup.getLength(element, XhtmlCss.WIDTH_INDEX);
390: // height = CssLookup.getLength(element, XhtmlCss.HEIGHT_INDEX);
391: width = CssUtilities.getCssLength(element,
392: XhtmlCss.WIDTH_INDEX);
393: height = CssUtilities.getCssLength(element,
394: XhtmlCss.HEIGHT_INDEX);
395: }
396:
397: if (width == CssBox.AUTO) {
398: width = prefSize.width;
399: }
400:
401: if (positionAdjacent || (height == CssBox.AUTO)) {
402: height = prefSize.height;
403: }
404: }
405:
406: // String value = property.getValueSource();
407: String value = inlineEditorSupport.getValueSource();
408:
409: if ((initialEdit != null) && (initialEdit.length() > 0)) {
410: // If we have shadow text, replace the text. Otherwise, append at the end
411: if (selectText) {
412: // #6323571 It means the original text is replaced by the initial edit.
413: value = initialEdit;
414: } else {
415: if (value == null) {
416: value = initialEdit;
417: } else {
418: value = value + initialEdit;
419: }
420: }
421:
422: inlineTextEditor.setText(value);
423: } else if (value != null) {
424: inlineTextEditor.setText(value);
425:
426: if (selectText) {
427: inlineTextEditor.selectAll();
428: }
429: } else {
430: String tag = element.getTagName();
431:
432: // Start editing shadow text, if any
433: if (tag.equals(HtmlTag.INPUT.name)
434: || tag.equals(HtmlTag.TEXTAREA.name)) {
435: inlineTextEditor.setText(element
436: .getAttribute(HtmlAttribute.VALUE));
437:
438: // We want to set the shadow text as solid text even if the user just
439: // hits Return
440: hasBeenEdited = true;
441:
442: if (selectText) {
443: inlineTextEditor.selectAll();
444: }
445: } else {
446: inlineTextEditor.setText("");
447: }
448: }
449:
450: if (inlineTextEditor instanceof JTextField) {
451: ((JTextField) inlineTextEditor).addActionListener(handler);
452: } else if (inlineTextEditor instanceof JTextArea) {
453: ((JTextArea) inlineTextEditor)
454: .getKeymap()
455: .addActionForKeyStroke(
456: KeyStroke
457: .getKeyStroke(KeyEvent.VK_ENTER, 0),
458: new EnterAction());
459: ((JTextArea) inlineTextEditor).getKeymap()
460: .addActionForKeyStroke(
461: KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,
462: InputEvent.CTRL_MASK),
463: new FinishAction());
464: ((JTextArea) inlineTextEditor).getKeymap()
465: .addActionForKeyStroke(
466: KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,
467: InputEvent.SHIFT_MASK),
468: new FinishAction());
469: }
470:
471: inlineTextEditor.addFocusListener(handler);
472: inlineTextEditor.getDocument().addDocumentListener(handler);
473: inlineTextEditor.addMouseListener(handler);
474:
475: DesignerPane pane = webform.getPane();
476: pane.add(inlineEditor);
477:
478: int x = box.getAbsoluteX(); // TODO - adjust for borders?
479: int y = box.getAbsoluteY();
480:
481: if (positionAdjacent) {
482: y += box.getHeight();
483: }
484:
485: Rectangle bounds = new Rectangle(x, y, width, height);
486:
487: inlineEditor.setBounds(bounds);
488: inlineEditor.validate();
489: pane.scrollRectToVisible(new Rectangle(bounds));
490: pane.repaint();
491:
492: if (webform.getSelection().isNodeUpdatePending()) {
493: // Ensure that we handle node updates before requesting focus
494: // on the text field; otherwise the pending node update will do
495: // its own focus grab which will take focus away from the textfield
496: // (and since I listen for focus loss as commit, this will terminate
497: // inline editing!)
498: webform.getSelection().updateNodesImmediate();
499: }
500:
501: inlineTextEditor.requestFocus();
502: }
503:
504: public void finish(boolean cancel) {
505: if (inlineEditor == null) {
506: return;
507: }
508:
509: JComponent oldEditor = inlineEditor;
510: JTextComponent oldTextEditor = inlineTextEditor;
511:
512: // Don't apply changes if we haven't made any edits; that way,
513: // we won't change a null value (rendered into "Text") into "Text"
514: // which really has a "null" value
515: if (hasBeenEdited && !cancel) {
516: String value = getText();
517:
518: if ((value != null) && (value.length() == 0)) {
519: // property.unset();
520: inlineEditorSupport.unset();
521: } else {
522: // property.setValue(value);
523: inlineEditorSupport.setValue(value);
524: }
525: }
526:
527: DesignerPane pane = webform.getPane();
528:
529: // XXX #6475780 Possible NPE.
530: boolean requestFocus = (inlineTextEditor != null && inlineTextEditor
531: .hasFocus())
532: || pane.hasFocus();
533:
534: inlineEditor = null;
535: inlineTextEditor = null;
536: pane.repaint();
537: pane.remove(oldEditor);
538:
539: if (oldTextEditor instanceof JTextField) {
540: ((JTextField) oldTextEditor).removeActionListener(handler);
541: // #114965 The inlineTextEditor field is null, use oldTextEditor.
542: // } else if (inlineTextEditor instanceof JTextArea) {
543: // ((JTextArea)inlineTextEditor).getKeymap().removeKeyStrokeBinding(KeyStroke.getKeyStroke(
544: // KeyEvent.VK_ENTER, 0));
545: // ((JTextArea)inlineTextEditor).getKeymap().removeKeyStrokeBinding(KeyStroke.getKeyStroke(
546: // KeyEvent.VK_ENTER, InputEvent.SHIFT_MASK));
547: // ((JTextArea)inlineTextEditor).getKeymap().removeKeyStrokeBinding(KeyStroke.getKeyStroke(
548: // KeyEvent.VK_ENTER, InputEvent.CTRL_MASK));
549: // }
550: } else if (oldTextEditor instanceof JTextArea) {
551: JTextArea textArea = (JTextArea) oldTextEditor;
552: textArea.getKeymap().removeKeyStrokeBinding(
553: KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0));
554: textArea.getKeymap().removeKeyStrokeBinding(
555: KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,
556: InputEvent.SHIFT_MASK));
557: textArea.getKeymap().removeKeyStrokeBinding(
558: KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,
559: InputEvent.CTRL_MASK));
560: }
561:
562: // XXX #6475780 Possible NPE.
563: if (oldTextEditor != null) {
564: oldTextEditor.removeMouseListener(handler);
565: oldTextEditor.removeFocusListener(handler);
566: oldTextEditor.getDocument().removeDocumentListener(handler);
567: }
568:
569: if (requestFocus) {
570: pane.requestFocus();
571: }
572: }
573:
574: public boolean isDocumentEditor() {
575: return false;
576: }
577:
578: public boolean isEscaped() {
579: return true;
580: }
581:
582: public boolean isMultiLine() {
583: return !isEscaped();
584: }
585:
586: // public boolean checkPosition(Position pos) {
587: public boolean checkPosition(DomPosition pos) {
588: return true;
589: }
590:
591: private String getText() {
592: String value = inlineTextEditor.getText();
593:
594: if (isEscaped()) {
595: // value =
596: // // <markup_separation>
597: //// MarkupServiceProvider.getDefault().expandHtmlEntities(value, false,
598: //// bean.getElement());
599: // // ====
600: //// InSyncService.getProvider().expandHtmlEntities(value, false, bean.getElement());
601: // WebForm.getDomProviderService().expandHtmlEntities(value, false, bean.getElement());
602: // // </markup_separation>
603: value = inlineEditorSupport
604: .expandHtmlEntities(value, false);
605: }
606:
607: return value;
608: }
609:
610: public Transferable copyText(boolean cut) {
611: String text = inlineTextEditor.getSelectedText();
612:
613: Transferable transferable = new StringSelection(text);
614:
615: if (cut) {
616: inlineTextEditor.replaceSelection("");
617: }
618:
619: return transferable;
620: }
621:
622: public void invokeDeleteNextCharAction(ActionEvent evt) {
623: JTextComponent textComponent;
624: if (inlineEditor instanceof JTextComponent) {
625: textComponent = (JTextComponent) inlineEditor;
626: } else if (inlineEditor instanceof JScrollPane
627: && ((JScrollPane) inlineEditor).getViewport().getView() instanceof JTextComponent) {
628: textComponent = (JTextComponent) ((JScrollPane) inlineEditor)
629: .getViewport().getView();
630: } else {
631: textComponent = null;
632: }
633:
634: if (textComponent == null) {
635: return;
636: }
637:
638: Action deleteAction = textComponent.getActionMap().get(
639: DefaultEditorKit.deleteNextCharAction);
640: if (deleteAction != null) {
641: deleteAction.actionPerformed(evt);
642: }
643: }
644:
645: /**
646: * Handler class for focus, action, mouse, document, etc. events on the embedded text field
647: * or text area.
648: */
649: class Handler extends MouseInputAdapter implements FocusListener,
650: ActionListener, DocumentListener {
651: // -------------- implements ActionListener ------------------
652: public void actionPerformed(ActionEvent e) {
653: webform.getManager().finishInlineEditing(false);
654: }
655:
656: // -------------- implements FocusListener ------------------
657: public void focusGained(java.awt.event.FocusEvent evt) {
658: //if (!evt.isTemporary()) {
659: // ((JTextComponent)evt.getComponent()).selectAll();
660: //}
661: }
662:
663: public void focusLost(java.awt.event.FocusEvent evt) {
664: // if (!evt.isTemporary()) {
665: // webform.getManager().finishInlineEditing(false);
666: // }
667: // XXX See AttributeInlineEditor#AttributeInlineEditorFocusListener.
668: if (!evt.isTemporary()
669: || evt.getComponent() instanceof JRootPane) {
670: // attributeInlineEditor.finish(false);
671: webform.getManager().finishInlineEditing(false);
672: evt.getComponent().removeFocusListener(this );
673: return;
674: }
675:
676: if (evt.isTemporary()) {
677: Component oppositeComponent = evt
678: .getOppositeComponent();
679: // XXX #6480841 jdk transfering the focus to JRootPane when invoked popup.
680: if (oppositeComponent instanceof JRootPane) {
681: oppositeComponent.addFocusListener(this );
682: }
683: }
684: }
685:
686: // -------------- implements DocumentListener ------------------
687: public void removeUpdate(javax.swing.event.DocumentEvent e) {
688: hasBeenEdited = true;
689: }
690:
691: public void insertUpdate(javax.swing.event.DocumentEvent e) {
692: hasBeenEdited = true;
693: }
694:
695: public void changedUpdate(javax.swing.event.DocumentEvent e) {
696: }
697:
698: // -------------- implements MouseListener / Extends MouseInputAdapter -------
699: //public void mousePressed(java.awt.event.MouseEvent e) {
700: //}
701: public void mouseClicked(java.awt.event.MouseEvent e) {
702: checkInitialDoubleClick(e);
703: }
704:
705: public void mousePressed(MouseEvent e) {
706: if (e.isPopupTrigger()) {
707: doPopup(e);
708: }
709: }
710:
711: public void mouseReleased(MouseEvent e) {
712: if (e.isPopupTrigger()) {
713: doPopup(e);
714: }
715: }
716:
717: public void doPopup(MouseEvent e) {
718: // Point p =
719: // SwingUtilities.convertPoint(e.getComponent(), e.getX(), e.getY(), inlineTextEditor);
720: //
721: // org.openide.nodes.Node[] nodes = webform.getSelection().getSelectedNodes();
722: // webform.getActions().createPopup((int)p.getX(), (int)p.getY(), inlineTextEditor, nodes,
723: // false, null);
724:
725: // // #6442386
726: // DesignerTopComp designerTC = webform.getTopComponent();
727: // Point p =
728: // SwingUtilities.convertPoint(e.getComponent(), e.getX(), e.getY(), designerTC);
729: // designerTC.showPopupMenu(p.x, p.y);
730: // webform.tcShowPopupMenuForEvent(e);
731: webform
732: .fireUserPopupActionPerformed(new InteractionManager.DefaultDesignerPopupEvent(
733: webform, e.getComponent(), null, null, e
734: .getX(), e.getY()));
735: }
736: }
737:
738: class FinishAction extends AbstractAction {
739: public void actionPerformed(ActionEvent evt) {
740: webform.getManager().finishInlineEditing(false);
741: }
742: }
743:
744: class EnterAction extends AbstractAction {
745: public void actionPerformed(ActionEvent evt) {
746: // XXX #6373507 Possible NPE.
747: if (inlineTextEditor == null) {
748: return;
749: }
750:
751: javax.swing.text.Document doc = inlineTextEditor
752: .getDocument();
753:
754: try {
755: int caret = inlineTextEditor.getCaretPosition();
756: doc.insertString(caret, "\n", null);
757: } catch (BadLocationException ex) {
758: // ErrorManager.getDefault().notify(ble);
759: info(ex);
760: }
761: }
762: }
763:
764: private static Logger getLogger() {
765: return Logger.getLogger(FormComponentEditor.class.getName());
766: }
767:
768: private static void info(Exception ex) {
769: getLogger().log(Level.INFO, null, ex);
770: }
771: }
|