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:
042: package org.netbeans.modules.visualweb.designer;
043:
044: import org.netbeans.modules.visualweb.api.designer.DomProvider;
045: import org.netbeans.modules.visualweb.api.designer.DomProvider.DomPosition;
046: import org.netbeans.modules.visualweb.css2.ModelViewMapper;
047: import java.awt.Graphics2D;
048: import java.awt.Rectangle;
049: import java.awt.datatransfer.Transferable;
050: import java.awt.event.ActionEvent;
051: import java.awt.event.MouseEvent;
052: import java.util.Arrays;
053: import java.util.List;
054: import java.util.logging.Level;
055: import java.util.logging.Logger;
056: import org.netbeans.modules.visualweb.api.designer.Designer.DesignerEvent;
057:
058: import org.openide.awt.MouseUtils;
059: import org.w3c.dom.Element;
060: import org.w3c.dom.Node;
061:
062: import org.netbeans.modules.visualweb.css2.CssBox;
063: import org.netbeans.modules.visualweb.designer.WebForm.DefaultDesignerEvent;
064: import org.netbeans.modules.visualweb.designer.html.HtmlTag;
065:
066: /**
067: * <p>
068: * Editor for inline-editing text of components.
069: * The UI for this is specified in
070: * http://ucsd.sfbay/projects/developer-tools/projects/RAVE/reef/UISpecs/designer-03.html
071: * </p>
072: * <p>
073: * One of the complications of inline editing is that (as the above spec calls for)
074: * it is invoked if you click on an already selected component. However, DOUBLE
075: * clicking on such a component should instead open the default event handler of
076: * the component. But note that a double click includes a single click, so if you
077: * double click on a selected component you immediately enter inline
078: * editing and the second click is then handled by the inline editor. At this point
079: * it needs to see if this click is a double click that was initiated before inline
080: * editing started, and if so, attempt to do event edits.
081: * </p>
082: *
083: * @todo Support editing unescaped properties. Currently disabled in
084: * factory method, since the code which needs to identify the editable
085: * text underneath the wrapping elements (e.g. <span> for an output
086: * text) needs to be enhanced since the value no longer corresponds
087: * to a single text node (and entities have to be expanded, etc.) Also,
088: * the newline handling in Document.insertString needs to be fixed; it's
089: * currently going through the design time apis to add a <br> but
090: * that's not right for a temporary DocumentFragment model.
091: *
092: * @todo If you press Tab while editing a component with multiple inline editable
093: * properties, can I automatically switch to the next?
094: * @todo The context menu should list each eligible property
095: * @todo Clicking in an area should pick the appropriate inline editable property (if none,
096: * use the default)
097: *
098: * @author Tor Norbye
099: */
100: public abstract class InlineEditor {
101: // /**
102: // * Flag to turn off vb expression editing in inline editing mode
103: // */
104: // protected static final boolean NO_EDIT_VB_EXPR = !Boolean.getBoolean("rave.allow-vb-editing");
105: protected WebForm webform;
106: // protected MarkupDesignBean bean;
107: // protected DesignProperty property;
108: // protected Position begin;
109: // protected Position end;
110: // protected DomPosition begin;
111: // protected DomPosition end;
112:
113: protected final DomProvider.InlineEditorSupport inlineEditorSupport;
114: // protected String propertyName;
115:
116: /** Timestamp when we last entered inline editing. */
117: private long editingStarted = 0L;
118:
119: /** Timestamp for the last mouse click received */
120: private long lastClick = 0L;
121:
122: // protected InlineEditor(WebForm webform, MarkupDesignBean bean, String propertyName) {
123: protected InlineEditor(WebForm webform,
124: DomProvider.InlineEditorSupport inlineEditorSupport) {
125: this .webform = webform;
126: // this.bean = bean;
127: // this.propertyName = propertyName;
128: // this.property = property;
129:
130: this .inlineEditorSupport = inlineEditorSupport;
131:
132: // assert bean.getElement() != null;
133: }
134:
135: /**
136: * Return an inline editor for the given bean, if it supports one.
137: * Returns null otherwise.
138: *
139: * @param webform The webform being edited
140: * @param box The box corresponding to the component click, if any
141: * @param bean The component to be inline edited
142: * @param propertyName May be null; if so, either the property corresponding to the box clicked should be edited,
143: * or the default property provided allow default is true
144: * @param useDefault If true, start editing the property marked default (if any) (marked with a "*" in the metadata)
145: * @return An InlineEditor for editing the chosen property, or null if none apply
146: */
147: static InlineEditor getInlineEditor(WebForm webform, CssBox box,
148: Element componentRootElement, /*DesignBean bean,*/
149: String propertyName, boolean useDefault) {
150: // if (!(bean instanceof MarkupDesignBean)) {
151: // return null;
152: // }
153: //
154: // MarkupDesignBean markupBean = (MarkupDesignBean)bean;
155: if (componentRootElement == null) {
156: return null;
157: }
158:
159: // String[] properties = getEditableProperties(markupBean);
160: WebForm webForm = box == null ? null : box.getWebForm();
161: if (webForm == null) {
162: return null;
163: }
164: String[] properties = webForm.getDomProviderService()
165: .getEditableProperties(componentRootElement);
166:
167: if ((properties == null) || (properties.length == 0)) {
168: return null;
169: }
170:
171: InlineEditor editor = null;
172: String[] propertyNames = new String[properties.length];
173: String[] xpaths = new String[properties.length];
174: int chosenProperty = -1;
175: int matchDepth = Integer.MAX_VALUE;
176:
177: // Try to find out which of the properties (if more than one) is the
178: // one we want - by seeing if the clicked box rendered under an element
179: // corresponding to the xpaths for the properties
180: if ((box != null) && (box.getElement() != null)) {
181: Element boxElement = box.getElement();
182:
183: for (int i = 0; i < properties.length; i++) {
184: String name = properties[i];
185: int xpathIndex = name.indexOf(':');
186:
187: if (xpathIndex != -1) {
188: xpaths[i] = name.substring(xpathIndex + 1);
189: name = name.substring(0, xpathIndex);
190: }
191:
192: if ((name.length() > 0) && (name.charAt(0) == '*')) {
193: name = name.substring(1);
194:
195: if ((useDefault || (xpaths[i] == null))
196: && (chosenProperty == -1)) {
197: chosenProperty = i;
198: }
199: }
200:
201: propertyNames[i] = name;
202:
203: // If a specific property was requested and this is it, mark
204: // it as the target property, otherwise, if we've clicked at a particular
205: // mouse position, see if that corresponds to this particular property
206: if (useDefault) {
207: assert propertyName == null;
208: } else if (propertyName != null) {
209: if (name.equals(propertyName)) {
210: chosenProperty = i;
211:
212: break;
213: }
214: } else if (xpaths[i] != null) {
215: // RaveElement sourceElement = (RaveElement)markupBean.getElement();
216: // RaveElement root = sourceElement.getRendered();
217: // Element sourceElement = markupBean.getElement();
218: // Element root = MarkupService.getRenderedElementForElement(sourceElement);
219: Element root = componentRootElement;
220:
221: if (root != null) {
222: // Node node = findPropertyNode(root, xpaths[i]);
223: Node node = webForm.getDomProviderService()
224: .findPropertyNode(root, xpaths[i]);
225:
226: // Is boxElement under the given node?
227: Node curr = boxElement;
228: int depth = 0;
229:
230: while (curr != null) {
231: if ((curr == node) && (depth < matchDepth)) {
232: chosenProperty = i;
233: matchDepth = depth;
234:
235: break;
236: }
237:
238: curr = curr.getParentNode();
239: depth++;
240: }
241: }
242: }
243: }
244: }
245:
246: if (chosenProperty == -1) {
247: if (!useDefault) {
248: // #104462 No default inline editable property specified.
249: // XXX #118293.
250: warn("There is no value found for specified inline editable properties, properties="
251: + Arrays.asList(properties) // NOI18N
252: + ", component root element="
253: + componentRootElement); // NOI18N
254: }
255: return null;
256: }
257:
258: try {
259: String name = propertyNames[chosenProperty];
260: String xpath = xpaths[chosenProperty];
261:
262: // DesignProperty property = bean.getProperty(name);
263: //
264: // if (property == null) {
265: // assert false : property;
266: //
267: // return null;
268: // }
269:
270: // DomProvider.InlineEditorSupport inlineEditorSupport = webform.createInlineEditorSupport(
271: // componentRootElement,
272: // name);
273: // if (inlineEditorSupport == null) {
274: // log(new NullPointerException("Missing inline editor support, componentRootElement=" + componentRootElement + ", propertyName=" + name)); // NOI18N
275: // return null;
276: // }
277:
278: HtmlTag tag = null;
279:
280: if (xpath != null) {
281: // See if I can figure it out from the xpath expression
282: if (xpath.startsWith("//")) {
283: int max = xpath.length();
284: int j = 2;
285:
286: while ((j < max)
287: && Character.isLetter(xpath.charAt(j))) {
288: j++;
289: }
290:
291: tag = HtmlTag.getTag(xpath.substring(2, j));
292: }
293: }
294:
295: DomProvider.InlineEditorSupport inlineEditorSupport = webform
296: .createInlineEditorSupport(componentRootElement,
297: name, xpath);
298: if (inlineEditorSupport == null) {
299: log(new NullPointerException(
300: "Missing inline editor support, componentRootElement="
301: + componentRootElement
302: + ", propertyName=" + name)); // NOI18N
303: return null;
304: }
305:
306: if ((tag == null) && (box != null)
307: && (box.getElement() != null)) {
308: tag = HtmlTag.getTag(box.getElement().getTagName());
309: }
310:
311: if ((tag != null) && tag.isFormMemberTag()) {
312: // editor = FormComponentEditor.get(webform, xpath, box, componentRootElement, /*markupBean, property,*/ inlineEditorSupport);
313: editor = FormComponentEditor.get(webform, /*xpath,*/
314: box, componentRootElement, /*markupBean, property,*/
315: inlineEditorSupport);
316:
317: if (editor != null) {
318: return editor;
319: }
320: }
321:
322: editor = AttributeInlineEditor.get(webform, /*xpath,*/
323: componentRootElement, /*markupBean, property,*/
324: inlineEditorSupport);
325:
326: if (editor != null) {
327: return editor;
328: }
329:
330: // Consider TextInlineEditor here when implemented (for editing
331: // direct JSP text inside html "components" like p, div etc.)
332: return null;
333: } finally {
334: if (editor != null) {
335: editor.editingStarted = System.currentTimeMillis();
336: editor.lastClick = editor.editingStarted;
337: }
338: }
339: }
340:
341: // /**
342: // * If the given component supports inline text editing, return the
343: // * String property name which stores the text that is inline
344: // * editable.
345: // */
346: // public static String[] getEditablePropertyNames(DesignBean bean) {
347: //// BeanInfo bi = bean.getBeanInfo();
348: ////
349: //// if (bi != null) {
350: //// BeanDescriptor bd = bi.getBeanDescriptor();
351: //// Object o = bd.getValue(Constants.BeanDescriptor.INLINE_EDITABLE_PROPERTIES);
352: ////
353: //// if (o instanceof String[]) {
354: //// String[] source = (String[])o;
355: // String[] source = getEditableProperties(bean);
356: // if (source != null) {
357: // List names = new ArrayList(source.length);
358: //
359: // for (int i = 0; i < source.length; i++) {
360: // String name;
361: // int index = source[i].indexOf(':');
362: //
363: // if (index == -1) {
364: // if ((source.length > 0) && (source[i].charAt(0) == '*')) {
365: // name = source[i].substring(1);
366: // } else {
367: // name = source[i];
368: // }
369: // } else {
370: // int start = 0;
371: //
372: // if ((source.length > 0) && (source[i].charAt(0) == '*')) {
373: // start = 1;
374: // }
375: //
376: // name = source[i].substring(start, index);
377: // }
378: //
379: // DesignProperty property = bean.getProperty(name);
380: //
381: // if ((property != null) && isEditingAllowed(property)) {
382: // names.add(name);
383: // }
384: // }
385: //
386: // return (String[])names.toArray(new String[names.size()]);
387: // }
388: //// }
389: //
390: // return new String[0];
391: // }
392: //
393: // private static String[] getEditableProperties(DesignBean bean) {
394: // BeanInfo bi = bean.getBeanInfo();
395: //
396: // if (bi != null) {
397: // BeanDescriptor bd = bi.getBeanDescriptor();
398: // Object o = bd.getValue(Constants.BeanDescriptor.INLINE_EDITABLE_PROPERTIES);
399: //
400: // if (o instanceof String[]) {
401: // return (String[])o;
402: // }
403: // }
404: //
405: // return null;
406: // }
407: //
408: // /**
409: // * Return true if inline editing is allowed for the given property (assuming it
410: // * has already been marked via metadata for inline editing; -that- is not checked here)
411: // */
412: // /*protected*/private static boolean isEditingAllowed(DesignProperty property) {
413: // // TODO: Change types above from DesignProperty to FacesDesignProperty, and
414: // // call property.isBound() instead of the below!
415: // if (NO_EDIT_VB_EXPR) {
416: // String value = property.getValueSource();
417: //
418: // // TODO: Change types above from DesignProperty to FacesDesignProperty, and
419: // // call property.isBound() instead of the below!
420: //// if ((value != null) && FacesSupport.isValueBindingExpression(value, false)) {
421: // if ((value != null) && WebForm.getDomProviderService().isValueBindingExpression(value, false)) {
422: // return false;
423: // }
424: // }
425: //
426: // return true;
427: // }
428:
429: // /**
430: // * Return the given node corresponding to the given xpath.
431: // * NOTE: The xpath parameter may actually contain multiple xpaths
432: // * separated by colons.
433: // * NOTE: Only a simple subset of XPATH is supported/implemented!!
434: // * I support EXACTLY the following formats:
435: // * //tagname
436: // * //tagname[@attribute='value']
437: // * and
438: // * /tagname1/tagname2/.../tagnameN
439: // * /tagname1/tagname2/.../tagnameN[@attribute='value']
440: // * Note - combinations of these (e.g. //foo/bar[@baz='boo']/nei are not valid yet).
441: // *
442: // * @todo Hook up to xalan or other XPATH parser to get this working properly
443: // */
444: // protected static Node findPropertyNode(Node root, String xpaths) {
445: // int next = 0;
446: // int xpathsLength = xpaths.length();
447: //
448: // while (next <= xpathsLength) {
449: // String xpath;
450: // int xpathEnd = xpaths.indexOf(':', next);
451: //
452: // if (xpathEnd == -1) {
453: // xpath = xpaths.substring(next);
454: // next = xpathsLength + 1;
455: // } else {
456: // xpath = xpaths.substring(next, xpathEnd);
457: // next = xpathEnd + 1;
458: // }
459: //
460: // // Dumb/simple parser algorithm for now
461: // if (xpath.startsWith("//")) { // NOI18N
462: //
463: // int length = xpath.length();
464: // int begin = 2;
465: // int end = begin;
466: //
467: // while ((end < length) && Character.isLetter(xpath.charAt(end))) {
468: // end++;
469: // }
470: //
471: // String attributeName = null;
472: // String attributeValue = null;
473: // String tagName = xpath.substring(begin, end);
474: //
475: // if ((end < length) && xpath.startsWith("[@", end)) { // NOI18N
476: // begin = end + 2;
477: // end = begin;
478: //
479: // while ((end < length) && Character.isLetter(xpath.charAt(end))) {
480: // end++;
481: // }
482: //
483: // attributeName = xpath.substring(begin, end);
484: //
485: // if ((end < length) && xpath.startsWith("='", end)) { // NOI18N
486: // begin = end + 2;
487: // end = begin;
488: //
489: // while ((end < length) && (xpath.charAt(end) != '\'')) {
490: // end++;
491: // }
492: //
493: // attributeValue = xpath.substring(begin, end);
494: // end++;
495: // }
496: // }
497: //
498: // // if (end != length) {
499: // // // Looks like the xpath expession is not of the simple form used
500: // // // for most of our own components... so do a fullblown
501: // // // xpath parse looking for the node instead...
502: // // // TODO
503: // // }
504: // Element element = findElement(root, tagName, attributeName, attributeValue);
505: //
506: // if (element != null) {
507: // return element;
508: // }
509: // } else {
510: // info("Inline editing xpath expression not understood: " + xpath); // NOI18N
511: // }
512: // }
513: //
514: // return null;
515: // }
516: //
517: // private static Element findElement(Node node, String tagName, String attribute, String value) {
518: // if (node.getNodeType() == Node.ELEMENT_NODE) {
519: // Element element = (Element)node;
520: //
521: // if (element.getTagName().equals(tagName)) {
522: // if (attribute != null) {
523: // if ((value == null) && element.hasAttribute(attribute)) {
524: // return element;
525: // } else if (element.getAttribute(attribute).indexOf(value) != -1) {
526: // //} else if (element.getAttribute(attribute).equals(value)) {
527: // // Match substring, not =: appropriate for class attribute only
528: // // PENDING: What is the correct xpath to express
529: // // element e has a class attribute which INCLUDES substring foo?
530: // return element;
531: // }
532: // } else {
533: // return element;
534: // }
535: // }
536: // }
537: //
538: // NodeList children = node.getChildNodes();
539: //
540: // for (int i = 0, n = children.getLength(); i < n; i++) {
541: // Node child = children.item(i);
542: // Element element = findElement(child, tagName, attribute, value);
543: //
544: // if (element != null) {
545: // return element;
546: // }
547: // }
548: //
549: // return null;
550: // }
551:
552: /** Initiate inline editing.
553: * @param selectText If true, select the text in the inline editing context,
554: * else it will simply put the caret at the end of the text range.
555: * @param initialEdit If a non empty string, set the edited value to this string
556: * as if the user had typed the characters at the beginning of the editing
557: * operation.
558: */
559: public abstract void start(boolean selectText, String initialEdit);
560:
561: /** If the edited bean supports multiple fields to be inline edited, switch to
562: * editing the next property
563: * @param cancel If true, cancel the current value before cycling. If false, commit value.
564: * @todo IMPLEMENT THIS
565: */
566: public void cycleEditableProperty(boolean cancel) {
567: }
568:
569: /**
570: * Stop inline editing. If cancel is true, throw away changes,
571: * otherwise commit them.
572: */
573: abstract void finish(boolean cancel);
574:
575: /** Return true iff the box passed in is within the box being edited
576: * by this inline editor.
577: */
578: public boolean isEdited(CssBox box) {
579: while (box != null) {
580: // if (box.getDesignBean() == bean) {
581: // if (CssBox.getMarkupDesignBeanForCssBox(box) == bean) {
582: // Element componentRootElement = WebForm.getDomProviderService().getRenderedElement(bean);
583: Element componentRootElement = inlineEditorSupport
584: .getRenderedElement();
585: if (componentRootElement != null
586: && componentRootElement == CssBox
587: .getElementForComponentRootCssBox(box)) {
588: return true;
589: }
590:
591: box = box.getParent();
592: }
593:
594: return false;
595: }
596:
597: /**
598: * Report the start position being edited in the inline editor
599: * (or Position.NONE if we're not inline editing.)
600: */
601: // public Position getBegin() {
602: public DomPosition getBegin() {
603: // return begin;
604: return inlineEditorSupport.getBeginPosition();
605: }
606:
607: /**
608: * Report the end position being edited in the inline editor
609: * (or Position.NONE if we're not inline editing.)
610: */
611: // public Position getEnd() {
612: public DomPosition getEnd() {
613: // return end;
614: return inlineEditorSupport.getEndPosition();
615: }
616:
617: /*
618: * Report whether the property being edited is "escaped" or not,
619: * meaning should the text shown in the browser be literally
620: * the same as in the value.
621: */
622: public abstract boolean isEscaped();
623:
624: /** Return true if this editor is editing document positions that our outside
625: * of the document (e.g. typically in a rendered fragment). If this is the
626: * case document positions won't be adjusted outwards to the nearest surrounding
627: * document position.
628: */
629: public boolean isDocumentEditor() {
630: return false;
631: }
632:
633: /**
634: * Report whether this inline editor is in multi line mode.
635: * Pressing Enter in a multiline mode should add a <br/> element,
636: * whereas in a single line editor it will complete input.
637: */
638: public abstract boolean isMultiLine();
639:
640: /** Paint the inline editing box */
641: public void paint(Graphics2D g2d) {
642: InteractionManager sm = webform.getManager();
643:
644: //Rectangle bounds = sm.getComponentBounds(bean);
645: //if (bounds != null) {
646: // ArrayList rectangles = webform.getMapper().getComponentRectangles(bean);
647: // List rectangles = ModelViewMapper.getComponentRectangles(webform.getPane().getPageBox(), bean);
648: List rectangles = ModelViewMapper.getComponentRectangles(
649: webform.getPane().getPageBox(),
650: // WebForm.getDomProviderService().getComponentRootElementForMarkupDesignBean(bean));
651: inlineEditorSupport.getRenderedElement());
652: int n = rectangles.size();
653:
654: if (n > 0) {
655: Rectangle bounds = (Rectangle) rectangles.get(n - 1);
656:
657: //sm.drawSelected(g2d, true, false, bounds, Constants.ResizeConstraints.ANY);
658: sm.drawInlineEditorBox(g2d, bounds);
659: }
660: }
661:
662: /** This method checks whether the given mouse event represents a double click
663: * that occurred immediately in an inline editor - if so, we should cancel out
664: * of inline editing and initiate event editing (if any) */
665: protected void checkInitialDoubleClick(MouseEvent e) {
666: // Lets say you have a selected button, and you want to
667: // double click on it to go to its event handler. The first
668: // click in the double click will cause inline editing to
669: // be entered. The second click just arrived. We need to detect
670: // that this is a double click that means our assumption about
671: // inline editing was wrong - in other words that it appeared
672: // shortly after the inline edit request, and if so
673: // if (MouseUtils_RAVE.isDoubleClick(e) && (lastClick <= editingStarted)) {
674: if (MouseUtils.isDoubleClick(e)
675: && (lastClick <= editingStarted)) {
676: // webform.getManager().notifyEditedDoubleClick();
677: DesignerEvent evt = new DefaultDesignerEvent(webform, null);
678: webform.fireUserActionPerformed(evt);
679: }
680:
681: lastClick = e.getWhen();
682: }
683:
684: /** Return true if the given position is a position within
685: * this editor's range.
686: */
687:
688: // TODO
689: // public abstract boolean checkPosition(Position pos);
690: public abstract boolean checkPosition(DomPosition pos);
691:
692: /** Get the currently edited & selected text in the editor */
693: public abstract Transferable copyText(boolean cut);
694:
695: /** Return true iff this inline editor is editing the given property on the given bean */
696: public boolean isEditing(
697: /*DesignBean bean,*/Element componentRootElement,
698: String propertyName) {
699: // return ((bean == this.bean) &&
700: // ((this.propertyName != null) && this.propertyName.equals(propertyName))) ||
701: // (this.propertyName == propertyName);
702: // String currPropertyName = property == null ? null : property.getPropertyDescriptor().getName();
703: String currPropertyName = inlineEditorSupport.getName();
704: // return ((bean == this.bean) &&
705: return ((componentRootElement == inlineEditorSupport
706: .getRenderedElement()) && ((currPropertyName != null) && currPropertyName
707: .equals(propertyName)))
708: || (currPropertyName == propertyName);
709: }
710:
711: /** XXX Invokes delete next char action.
712: * FIXME There shouldn't be an action invocation, but rather utility method call. */
713: public abstract void invokeDeleteNextCharAction(ActionEvent evt);
714:
715: private static void log(Exception ex) {
716: Logger logger = getLogger();
717: logger.log(Level.INFO, null, ex);
718: }
719:
720: private static void info(String message) {
721: Logger logger = getLogger();
722: logger.info(message);
723: }
724:
725: private static void warn(String message) {
726: Logger logger = getLogger();
727: logger.warning(message);
728: }
729:
730: private static Logger getLogger() {
731: return Logger.getLogger(InlineEditor.class.getName());
732: }
733: }
|