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.jsf.text;
043:
044: import java.util.logging.Level;
045: import java.util.logging.Logger;
046: import org.netbeans.modules.visualweb.api.designer.DomProvider;
047: import org.netbeans.modules.visualweb.api.designer.DomProvider.DomPosition;
048: import org.netbeans.modules.visualweb.api.designer.DomProvider.DomPosition.Bias;
049:
050: import org.netbeans.modules.visualweb.api.designer.DomProvider.DomRange;
051: import org.openide.util.Exceptions;
052: import org.w3c.dom.Node;
053: import org.w3c.dom.ranges.DocumentRange;
054:
055: /**
056: * XXX Moved from designer/../Range.
057: *
058: * Represents a range: two positions, where one position
059: * is considered the "dot" (current location). E.g. if you
060: * swipe select out a range, the "start" point of the selection
061: * is the mark, and the "end" point is the mark.
062: *
063: * <p> Implementation notes: I first used DOM Range directly,
064: * but that doesn't work well for example within rendered jsf
065: * fragments, since the Range can only be attached to the Document
066: * itself; it also had no concept of dot and mark, so I was having
067: * to track this state separately along with the range, and there's
068: * some cleanup logic to be done, so all this is now managed by
069: * this class.
070: *
071: * @todo Rename class to SelectionRange, since it's not a generic Range
072: * class (like Position is a generic Position class), it's really tied
073: * to selection, both in its "dot" and "mark" distinctions as well as
074: * its synchronization to the system clipboard etc.
075: *
076: * @author Tor Norbye
077: */
078: /*public*/class DomRangeImpl implements DomProvider.DomRange {
079: // private WebForm webform;
080: // private final JsfForm jsfForm;
081: private final DomDocumentImpl domDocumentImpl;
082:
083: /** Associated DOM range. Will be null for e.g. document
084: * ranges.
085: */
086: private org.w3c.dom.ranges.Range domRange;
087:
088: /** Tracks whether or not the domRange has the dot as the start
089: * container or the end container (true means start container) */
090: private boolean dotIsFirst;
091:
092: // Should these be static? Means we can't have multiple simultaneous
093: // ranges - but that's currently how it's used anyway.... perhaps I
094: // should ENFORCE that by making this a singleton class!
095: // Yes, ... but for now just unstatic it 'til I get time to address this
096: // private /* static */ Position cachedDot = new Position(null, 0, Bias.FORWARD);
097: // private /* static */ Position cachedMark = new Position(null, 0, Bias.FORWARD);
098: // private /* static */ Position cachedDot = Position.create(null, 0, Bias.FORWARD);
099: // private /* static */ Position cachedMark = Position.create(null, 0, Bias.FORWARD);
100: // private DomPosition cachedDot = DomPositionImpl.create(null, null, 0, Bias.FORWARD);
101: // private DomPosition cachedMark = DomPositionImpl.create(null, null, 0, Bias.FORWARD);
102: private DomPosition cachedDot = DomPosition.NONE;
103: private DomPosition cachedMark = DomPosition.NONE;
104:
105: private Bias dotBias = Bias.FORWARD;
106: private Bias markBias = Bias.FORWARD;
107:
108: public static DomRange create(DomDocumentImpl domDocumentImpl,
109: Node dotNode, int dotOffset, Node markNode, int markOffset) {
110: // XXX #113141 Fixing possible NPE (returning DomRange.NONE instead).
111: // XXX #102048 If the owner is the source doc, get the range.
112: if (dotNode.getOwnerDocument() == domDocumentImpl.getJsfForm()
113: .getJspDom()) {
114: return new DomRangeImpl(domDocumentImpl, dotNode,
115: dotOffset, markNode, markOffset);
116: } else {
117: Logger logger = Logger.getLogger(DomRangeImpl.class
118: .getName());
119: logger
120: .log(Level.INFO, null, new IllegalStateException(
121: "Can not create dom range for provided node in source DOM" // NOI18N
122: + ", dotNode="
123: + dotNode // NOI18N
124: + ", dotNode owner="
125: + dotNode.getOwnerDocument() // NOI18N
126: + ", jsp dom="
127: + domDocumentImpl.getJsfForm()
128: .getJspDom())); // NOI18N
129:
130: return DomRange.NONE;
131: }
132: }
133:
134: private DomRangeImpl(DomDocumentImpl domDocumentImpl, Node dotNode,
135: int dotOffset, Node markNode, int markOffset) {
136: // this.webform = webform;
137: // this.jsfForm = jsfForm;
138: this .domDocumentImpl = domDocumentImpl;
139:
140: // // Determine if this node is in a DocumentFragment which means
141: // // it's read only
142: // Node curr = dotNode;
143: //
144: // while (curr.getParentNode() != null) {
145: // curr = curr.getParentNode();
146: // }
147: //
148: //// if (curr == webform.getJspDom()) {
149: // if (curr == domDocumentImpl.getJsfForm().getJspDom()) {
150: // // It's below the main document dom node so it's part of
151: // // the writable document portion
152: //// DocumentRange dom = (DocumentRange)webform.getJspDom();
153: // DocumentRange dom = (DocumentRange)domDocumentImpl.getJsfForm().getJspDom();
154: //
155: // domRange = dom.createRange();
156: // domRange.setStart(markNode, markOffset);
157: // domRange.setEnd(dotNode, dotOffset);
158: //// } else if (webform.getManager().isInlineEditing()) {
159: // } else if (domDocumentImpl.getJsfForm().isInlineEditing()) {
160: // // Handle regions in generated dom
161: // assert curr instanceof DocumentFragment;
162: //
163: // //assert webform.getSelection().getInlineEditor().getFragment() == curr;
164: // DocumentRange dom = (DocumentRange)curr.getOwnerDocument();
165: // domRange = dom.createRange();
166: // domRange.setStart(markNode, markOffset);
167: // domRange.setEnd(dotNode, dotOffset);
168: // } else {
169: //// assert false : dotNode + "; " + curr + "; " + webform.getJspDom(); // NOI18N
170: // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
171: //// new IllegalStateException("dotNode=" + dotNode + ", curr=" + curr + ", jsp dom=" + webform.getJspDom())); // NOI18N
172: // new IllegalStateException("dotNode=" + dotNode + ", curr=" + curr + ", jsp dom=" + domDocumentImpl.getJsfForm().getJspDom())); // NOI18N
173: // }
174: // // XXX #102048 If the owner is the source doc, get the range.
175: // if (dotNode.getOwnerDocument() == domDocumentImpl.getJsfForm().getJspDom()) {
176: // // It's below the main document dom node so it's part of
177: // // the writable document portion
178: // DocumentRange dom = (DocumentRange)domDocumentImpl.getJsfForm().getJspDom();
179: //
180: // domRange = dom.createRange();
181: // domRange.setStart(markNode, markOffset);
182: // domRange.setEnd(dotNode, dotOffset);
183: // } else {
184: // Logger logger = Logger.getLogger(DomRangeImpl.class.getName());
185: // logger.log(Level.INFO, null,
186: // new IllegalStateException("dotNode=" + dotNode // NOI18N
187: // + ", dotNode owner=" + dotNode.getOwnerDocument() // NOI18N
188: // + ", jsp dom=" + domDocumentImpl.getJsfForm().getJspDom())); // NOI18N
189: //
190: // }
191: // It's below the main document dom node so it's part of
192: // the writable document portion
193: DocumentRange dom = (DocumentRange) domDocumentImpl
194: .getJsfForm().getJspDom();
195: domRange = dom.createRange();
196: domRange.setStart(markNode, markOffset);
197: domRange.setEnd(dotNode, dotOffset);
198:
199: dotIsFirst = false;
200: ensureMarkIsFirst();
201: }
202:
203: /** Free up resources associated with this range */
204: public void detach() {
205: if (domRange != null) {
206: domRange.detach();
207: domRange = null;
208: }
209: }
210:
211: public void setRange(Node start, int startOffset, Node end,
212: int endOffset) {
213: // Is it safe to reuse the range? If it isn't, we try
214: // to change the caret over from a DocumentFragment to a Document
215: // or vice versa, after setting one end point, xerces throws an
216: // exception because the range straddles documents. There's no Range
217: // method to set both points unfortunately so we've gotta work around
218: // as follows.
219: if (start == end) {
220: domRange.setEnd(end, endOffset);
221: domRange.setStart(start, startOffset);
222: } else {
223: domRange.detach();
224:
225: // DocumentRange dom = (DocumentRange)webform.getJspDom();
226: DocumentRange dom = (DocumentRange) domDocumentImpl
227: .getJsfForm().getJspDom();
228: domRange = dom.createRange();
229: domRange.setStart(end, endOffset);
230: domRange.setEnd(start, startOffset);
231: dotIsFirst = false;
232: }
233:
234: ensureMarkIsFirst();
235:
236: if (dotIsFirst) {
237: dotBias = Bias.FORWARD;
238: markBias = Bias.BACKWARD;
239: } else {
240: markBias = Bias.FORWARD;
241: dotBias = Bias.BACKWARD;
242: }
243: }
244:
245: public void setDot(Node dotNode, int dotOffset, Bias bias) {
246: // XXX It seems this RangeImpl.setEnd will also reset the start if the new
247: // end is before the old start.
248: Node markNode;
249: int markOffset;
250: if (dotIsFirst) {
251: markNode = domRange.getEndContainer();
252: markOffset = domRange.getEndOffset();
253: } else {
254: markNode = domRange.getStartContainer();
255: markOffset = domRange.getStartOffset();
256: }
257:
258: int result = DomPositionImpl.compareBoundaryPoints(markNode,
259: markOffset, dotNode, dotOffset);
260: boolean oldDotIsFirst = dotIsFirst;
261: dotIsFirst = result < 0;
262:
263: if (dotIsFirst) {
264: domRange.setStart(dotNode, dotOffset);
265: if (oldDotIsFirst != dotIsFirst) {
266: domRange.setEnd(markNode, markOffset);
267: }
268: } else {
269: domRange.setEnd(dotNode, dotOffset);
270: if (oldDotIsFirst != dotIsFirst) {
271: domRange.setStart(markNode, markOffset);
272: }
273: }
274:
275: dotBias = bias;
276: ensureMarkIsFirst();
277: }
278:
279: public void setMark(Node markNode, int markOffset, Bias bias) {
280: // XXX It seems this RangeImpl.setEnd will also reset the start if the new
281: // end is before the old start.
282: Node dotNode;
283: int dotOffset;
284: if (dotIsFirst) {
285: dotNode = domRange.getStartContainer();
286: dotOffset = domRange.getStartOffset();
287: } else {
288: dotNode = domRange.getEndContainer();
289: dotOffset = domRange.getEndOffset();
290: }
291:
292: int result = DomPositionImpl.compareBoundaryPoints(markNode,
293: markOffset, dotNode, dotOffset);
294: boolean oldDotIsFirst = dotIsFirst;
295: dotIsFirst = result < 0;
296:
297: if (dotIsFirst) {
298: domRange.setEnd(markNode, markOffset);
299: if (oldDotIsFirst != dotIsFirst) {
300: domRange.setStart(dotNode, dotOffset);
301: }
302: } else {
303: domRange.setStart(markNode, markOffset);
304: if (oldDotIsFirst != dotIsFirst) {
305: domRange.setEnd(dotNode, dotOffset);
306: }
307: }
308:
309: markBias = bias;
310: ensureMarkIsFirst();
311: }
312:
313: // XXX This is very suspicoius.
314: // There is not check whether the start or the end is the mark or the dot.
315: // Get rid of it.
316: /** Ensure that the mark location is before the dot location in
317: * the range. If not, it will swap the two and flip the "dotIsFirst"
318: * flag. (So getMark() will correctly return a mark location after the
319: * dot location, if you've swiped selection towards the left, but
320: * internally the range end container is now representing the mark.)
321: */
322: private void ensureMarkIsFirst() {
323: int result = DomPositionImpl.compareBoundaryPoints(domRange
324: .getStartContainer(), domRange.getStartOffset(),
325: domRange.getEndContainer(), domRange.getEndOffset());
326:
327: if (result < 0) {
328: // Swap
329: Node tempNode = domRange.getStartContainer();
330: int tempOffset = domRange.getStartOffset();
331: domRange.setStart(domRange.getEndContainer(), domRange
332: .getEndOffset());
333: domRange.setEnd(tempNode, tempOffset);
334: dotIsFirst = !dotIsFirst;
335: }
336: }
337:
338: /** Return true iff the given position coincides with the dot position */
339: // public boolean isDot(Position dot) {
340: public boolean isDot(DomPosition dot) {
341: if (dotIsFirst) {
342: return (dot.getNode() == domRange.getStartContainer())
343: && (dot.getOffset() == domRange.getStartOffset());
344: } else {
345: return (dot.getNode() == domRange.getEndContainer())
346: && (dot.getOffset() == domRange.getEndOffset());
347: }
348: }
349:
350: /** Return true iff the range is empty, e.g. the dot and mark are the same */
351: public boolean isEmpty() {
352: return (domRange.getStartContainer() == domRange
353: .getEndContainer())
354: && (domRange.getStartOffset() == domRange
355: .getEndOffset());
356: }
357:
358: public String toString() {
359: return "Range(dot=" + getDot() + ";" + getMark() + ")"; // NOI18N
360: }
361:
362: /**
363: * Fetches the current position of the caret.
364: *
365: * @return the position >= 0
366: */
367: // public Position getDot() {
368: public DomPosition getDot() {
369: //boolean empty = isEmpty();
370: boolean empty = true;
371:
372: if (dotIsFirst) {
373: // cachedDot.setLocation(domRange.getStartContainer(), domRange.getStartOffset(),
374: // empty ? dotBias : Bias.FORWARD);
375: cachedDot = domDocumentImpl.createDomPosition(domRange
376: .getStartContainer(), domRange.getStartOffset(),
377: empty ? dotBias : Bias.FORWARD);
378: } else {
379: // cachedDot.setLocation(domRange.getEndContainer(), domRange.getEndOffset(),
380: // empty ? dotBias : Bias.BACKWARD);
381: cachedDot = domDocumentImpl.createDomPosition(domRange
382: .getEndContainer(), domRange.getEndOffset(),
383: empty ? dotBias : Bias.FORWARD);
384: }
385:
386: return cachedDot;
387: }
388:
389: /** Return the first endpoint of the range in the document. */
390: // public Position getFirstPosition() {
391: public DomPosition getFirstPosition() {
392: if (dotIsFirst) {
393: return getDot();
394: } else {
395: return getMark();
396: }
397: }
398:
399: /** Return the second/last endpoint of the range in the document. */
400: // public Position getLastPosition() {
401: public DomPosition getLastPosition() {
402: if (dotIsFirst) {
403: return getMark();
404: } else {
405: return getDot();
406: }
407: }
408:
409: /**
410: * Fetches the current position of the caret.
411: *
412: * @return the position >= 0
413: */
414: // public Position getMark() {
415: public DomPosition getMark() {
416: //boolean empty = isEmpty();
417: boolean empty = true;
418:
419: if (dotIsFirst) {
420: // cachedMark.setLocation(domRange.getEndContainer(), domRange.getEndOffset(),
421: // empty ? markBias : Bias.BACKWARD);
422: cachedMark = domDocumentImpl.createDomPosition(domRange
423: .getEndContainer(), domRange.getEndOffset(),
424: empty ? markBias : Bias.FORWARD);
425: } else {
426: // cachedMark.setLocation(domRange.getStartContainer(), domRange.getStartOffset(),
427: // empty ? markBias : Bias.FORWARD);
428: cachedMark = domDocumentImpl.createDomPosition(domRange
429: .getStartContainer(), domRange.getStartOffset(),
430: empty ? markBias : Bias.FORWARD);
431: }
432:
433: return cachedMark;
434: }
435:
436: // ---- Mutation Events
437:
438: /** Delete the contents of the selection. Beep if the range is read-only.
439: * @return true iff the deletion succeeded (an empty selection can always
440: * be successfully deleted)
441: */
442: public boolean deleteRangeContents() {
443: if (isEmpty()) {
444: return true;
445: }
446:
447: if (domRange != null) {
448: // Somehow the range does "bad" stuff with deletion - sometimes
449: // the start container ends up being set back up to the parent!
450: // Notagood. So we try to preserve it instead.
451: Node sc = domRange.getStartContainer();
452: int so = domRange.getStartOffset();
453: Node ec = domRange.getEndContainer();
454: int eo = domRange.getEndOffset();
455:
456: //// if (webform.getManager().isInlineEditing() ||
457: // if (jsfForm.isInlineEditing() ||
458: //// (Position.isSourceNode(sc, webform.getDom()) &&
459: //// Position.isSourceNode(ec, webform.getDom()))) {
460: // (!MarkupService.isRenderedNode(sc)
461: // && !MarkupService.isRenderedNode(ec))) {
462: // deleteComponents();
463: // domRange.deleteContents();
464: // } else {
465: // Node sourceStart = null;
466: // int sourceOffset = so;
467: //
468: //// if (Position.isRenderedNode(sc)) {
469: // if (MarkupService.isRenderedNode(sc)) {
470: //// Position source = new Position(sc, so, Bias.FORWARD);
471: // DomPositionImpl source = DomPositionImpl.create(sc, so, Bias.FORWARD);
472: //
473: // if (source != DomPositionImpl.NONE) {
474: // sourceStart = source.getNode();
475: // sourceOffset = source.getOffset();
476: // }
477: // }
478: //
479: // Node sourceEnd = null;
480: // int sourceEndOffset = eo;
481: //
482: //// if (Position.isRenderedNode(ec)) {
483: // if (MarkupService.isRenderedNode(ec)) {
484: //// Position source = new Position(ec, eo, Bias.FORWARD);
485: // DomPositionImpl source = DomPositionImpl.create(ec, eo, Bias.FORWARD);
486: //
487: // if (source != DomPositionImpl.NONE) {
488: // sourceEnd = source.getNode();
489: // sourceEndOffset = source.getOffset();
490: // }
491: // }
492: //
493: // if ((sourceStart != null) && (sourceEnd != null)) {
494: // setRange(sourceStart, sourceOffset, sourceEnd, sourceEndOffset);
495: // deleteComponents();
496: // domRange.deleteContents();
497: // }
498: // }
499:
500: // XXX Moved to DomDocumentImpl.
501: // // XXX For now it works only over the source nodes. That has to be changes.
502: // if (!jsfForm.isInlineEditing() && (MarkupService.isRenderedNode(sc) || MarkupService.isRenderedNode(ec))) {
503: // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,
504: // new IllegalStateException("It is not inline editing, nor both nodes are source ones," // NOI18N
505: // + "\nstartNode=" + sc // NOI18N
506: // + "\nendNode=" + ec)); // NOI18N
507: // return false;
508: // }
509: // deleteComponents();
510: domRange.deleteContents();
511:
512: domRange.setStart(sc, so);
513: domRange.setEnd(sc, so);
514:
515: return true;
516: } else {
517: return false;
518: }
519: }
520:
521: // /** Delete all the JSF components found in the given range */
522: // private void deleteComponents() {
523: // // This will require a traversal, but probably not using the
524: // // DomTraversal class since we'll be deleting elements as
525: // // we're traversing
526: //// Position second = getLastPosition();
527: // DomPosition second = getLastPosition();
528: //
529: //// if (second == Position.NONE) {
530: // if (second == DomPosition.NONE) {
531: // return;
532: // }
533: //
534: //// Position first = getFirstPosition();
535: // DomPosition first = getFirstPosition();
536: // assert first.isEarlierThan(first);
537: //
538: // Node firstNode = first.getNode();
539: //
540: // if (firstNode instanceof Element) {
541: // if (first.getOffset() < firstNode.getChildNodes().getLength()) {
542: // firstNode = firstNode.getChildNodes().item(first.getOffset());
543: // }
544: // }
545: //
546: // Node secondNode = second.getNode();
547: //
548: // if (first.equals(second)) {
549: // secondNode = firstNode;
550: // } else if (secondNode instanceof Element) {
551: // if ((second.getOffset() > 0) &&
552: // (second.getOffset() <= secondNode.getChildNodes().getLength())) {
553: // secondNode = secondNode.getChildNodes().item(second.getOffset() - 1);
554: // } else if (second.getOffset() == 0) {
555: // // Gotta locate immediate inorder traversal neighbor to the left
556: // while ((secondNode != null) && (secondNode.getPreviousSibling() == null)) {
557: // secondNode = secondNode.getParentNode();
558: // }
559: //
560: // if (secondNode == null) {
561: // ErrorManager.getDefault().log("Unexpected second position " + second); // NOI18N
562: //
563: // return;
564: // }
565: //
566: // secondNode = secondNode.getPreviousSibling();
567: //
568: // while (true) {
569: // NodeList nl = secondNode.getChildNodes();
570: //
571: // if (nl.getLength() > 0) {
572: // secondNode = nl.item(nl.getLength() - 1);
573: // } else {
574: // break;
575: // }
576: // }
577: // }
578: // }
579: //
580: // // Insert content for the first node
581: // if ((firstNode == secondNode) && firstNode instanceof Text) {
582: // // Common case - and we're done; no components to be deleted here
583: // return;
584: // }
585: //
586: // // Iterate over the range building up all the DesignBeans to be
587: // // destroyed
588: //// ArrayList beans = new ArrayList();
589: // List<Element> components = new ArrayList<Element>();
590: //
591: //// org.w3c.dom.Document dom = webform.getJspDom();
592: // org.w3c.dom.Document dom = jsfForm.getJspDom();
593: //
594: // if (!(dom instanceof DocumentTraversal)) {
595: // return;
596: // }
597: //
598: // DocumentTraversal trav = (DocumentTraversal)dom;
599: //
600: // // Iterating over all since we can't just limit ourselves to text nodes
601: // // in case the target node is not necessarily a text node!
602: // NodeIterator iterator = trav.createNodeIterator(dom, NodeFilter.SHOW_ALL, null, false);
603: //
604: // // The node iterator doesn't seem to have a way to jump to a
605: // // particular node, so we search for it ourselves
606: // Node curr = firstNode;
607: //
608: // while (curr != null) {
609: // try {
610: // curr = iterator.nextNode();
611: //
612: // if (curr == firstNode) {
613: // break;
614: // }
615: // } catch (DOMException ex) {
616: // ErrorManager.getDefault().notify(ex);
617: //
618: // break;
619: // }
620: // }
621: //
622: // Node last = secondNode;
623: //
624: // while (curr != null) {
625: //// if (curr instanceof RaveElement) {
626: //// RaveElement element = (RaveElement)curr;
627: // if (curr instanceof Element) {
628: // Element element = (Element)curr;
629: //// DesignBean bean = element.getDesignBean();
630: //// DesignBean bean = InSyncService.getProvider().getMarkupDesignBeanForElement(element);
631: //// DesignBean bean = WebForm.getDomProviderService().getMarkupDesignBeanForElement(element);
632: // Element componentRootElement = MarkupService.getRenderedElementForElement(element);
633: //
634: //// if ((bean != null) &&
635: // if ((componentRootElement != null) &&
636: // ((element.getParentNode() == null) ||
637: //// (element.getParentNode() instanceof RaveElement &&
638: //// (((RaveElement)element.getParentNode()).getDesignBean() != bean)))) {
639: // (element.getParentNode() instanceof Element
640: //// && InSyncService.getProvider().getMarkupDesignBeanForElement((Element)element.getParentNode()) != bean))) {
641: //// && WebForm.getDomProviderService().getMarkupDesignBeanForElement((Element)element.getParentNode()) != bean))) {
642: // && MarkupService.getRenderedElementForElement((Element)element.getParentNode()) != componentRootElement))) {
643: //// if (!beans.contains(bean)) {
644: //// beans.add(bean);
645: //// }
646: // if (!components.contains(componentRootElement)) {
647: // components.add(componentRootElement);
648: // }
649: // }
650: // }
651: //
652: // if ((curr == null) || (curr == last)) {
653: // break;
654: // }
655: //
656: // try {
657: // curr = iterator.nextNode();
658: // } catch (DOMException ex) {
659: // ErrorManager.getDefault().notify(ex);
660: //
661: // break;
662: // }
663: // }
664: //
665: // iterator.detach();
666: //
667: //// FacesModel model = webform.getModel();
668: //// Document doc = webform.getDocument();
669: //
670: //// UndoEvent undoEvent = webform.getModel().writeLock(NbBundle.getMessage(DeleteNextCharAction.class, "DeleteText")); // NOI18N
671: //// DomProvider.WriteLock writeLock = webform.writeLock(NbBundle.getMessage(DeleteNextCharAction.class, "DeleteText")); // NOI18N
672: // DomProvider.WriteLock writeLock = jsfForm.writeLock(NbBundle.getMessage(DomRangeImpl.class, "LBL_DeleteText")); // NOI18N
673: // try {
674: //// doc.writeLock(NbBundle.getMessage(DeleteNextCharAction.class, "DeleteText")); // NOI18N
675: //
676: //// for (int i = 0; i < beans.size(); i++) {
677: //// DesignBean bean = (DesignBean)beans.get(i);
678: // for (Element componentRootElement : components) {
679: //
680: //// if (!FacesSupport.isSpecialBean(/*webform, */bean)) {
681: //// if (!Util.isSpecialBean(bean)) {
682: //// if (bean instanceof MarkupDesignBean && !WebForm.getDomProviderService().isSpecialComponent(
683: //// WebForm.getDomProviderService().getComponentRootElementForMarkupDesignBean((MarkupDesignBean)bean))) {
684: //// if (!WebForm.getDomProviderService().isSpecialComponent(componentRootElement)) {
685: // if (!JsfSupportUtilities.isSpecialComponent(componentRootElement)) {
686: //// model.getLiveUnit().deleteBean(bean);
687: //// webform.deleteBean(bean);
688: //// webform.deleteComponent(componentRootElement);
689: // jsfForm.deleteComponent(componentRootElement);
690: // }
691: // }
692: // } finally {
693: //// doc.writeUnlock();
694: //// webform.getModel().writeUnlock(undoEvent);
695: //// webform.writeUnlock(writeLock);
696: // jsfForm.writeUnlock(writeLock);
697: // }
698: // }
699:
700: /** Return true iff the range is in a read-only region */
701: public boolean isReadOnlyRegion() {
702: return domRange == null;
703: }
704:
705: // XXX Moved to DomDocumentImpl.
706: // /** Return the text in the range (linearized to a String); this is only the
707: // * text nodes, not comment nodes, not markup, etc.
708: // */
709: // public String getText() {
710: // // Since we'll be iterating forwards, gotta make sure we know
711: // // which point is first
712: //// Position second = getLastPosition();
713: // DomPosition second = getLastPosition();
714: //
715: //// if (second == Position.NONE) {
716: // if (second == DomPosition.NONE) {
717: // return "";
718: // }
719: //
720: //// Position first = getFirstPosition();
721: // DomPosition first = getFirstPosition();
722: // assert first.isEarlierThan(first);
723: //
724: // StringBuffer sb = new StringBuffer();
725: //
726: // Node firstNode = first.getNode();
727: //
728: // if (firstNode instanceof Element) {
729: // if (first.getOffset() < firstNode.getChildNodes().getLength()) {
730: // firstNode = firstNode.getChildNodes().item(first.getOffset());
731: // }
732: // }
733: //
734: // Node secondNode = second.getNode();
735: //
736: // if (first.equals(second)) {
737: // secondNode = firstNode;
738: // } else if (secondNode instanceof Element) {
739: // if ((second.getOffset() > 0) &&
740: // (second.getOffset() <= secondNode.getChildNodes().getLength())) {
741: // secondNode = secondNode.getChildNodes().item(second.getOffset() - 1);
742: // } else if (second.getOffset() == 0) {
743: // // Gotta locate immediate inorder traversal neighbor to the left
744: // while ((secondNode != null) && (secondNode.getPreviousSibling() == null)) {
745: // secondNode = secondNode.getParentNode();
746: // }
747: //
748: // if (secondNode == null) {
749: // ErrorManager.getDefault().log("Unexpected second position " + second); // NOI18N
750: //
751: // return "";
752: // }
753: //
754: // secondNode = secondNode.getPreviousSibling();
755: //
756: // while (true) {
757: // NodeList nl = secondNode.getChildNodes();
758: //
759: // if (nl.getLength() > 0) {
760: // secondNode = nl.item(nl.getLength() - 1);
761: // } else {
762: // break;
763: // }
764: // }
765: // }
766: // }
767: //
768: // // Insert content for the first node
769: // if (firstNode instanceof Text) {
770: // if (secondNode == firstNode) {
771: // String s = firstNode.getNodeValue();
772: //
773: // for (int i = first.getOffset(); i < second.getOffset(); i++) {
774: // sb.append(s.charAt(i));
775: // }
776: //
777: // return sb.toString();
778: // } else {
779: // String s = firstNode.getNodeValue();
780: //
781: // for (int i = first.getOffset(), n = s.length(); i < n; i++) {
782: // sb.append(s.charAt(i));
783: // }
784: // }
785: // }
786: //
787: // // Append content for all the nodes between first and second
788: //// org.w3c.dom.Document dom = webform.getJspDom();
789: // org.w3c.dom.Document dom = jsfForm.getJspDom();
790: //
791: // if (!(dom instanceof DocumentTraversal)) {
792: // return "";
793: // }
794: //
795: // DocumentTraversal trav = (DocumentTraversal)dom;
796: //
797: // // Iterating over all since we can't just limit ourselves to text nodes
798: // // in case the target node is not necessarily a text node!
799: // NodeIterator iterator = trav.createNodeIterator(dom, NodeFilter.SHOW_ALL, null, false);
800: // Node curr = firstNode;
801: //
802: // // The node iterator doesn't seem to have a way to jump to a particular node,
803: // // so we search for it ourselves
804: // while (curr != null) {
805: // try {
806: // curr = iterator.nextNode();
807: //
808: // if (curr == firstNode) {
809: // break;
810: // }
811: // } catch (DOMException ex) {
812: // ErrorManager.getDefault().notify(ex);
813: //
814: // break;
815: // }
816: // }
817: //
818: // Node last = secondNode;
819: //
820: // while (curr != null) {
821: // try {
822: // curr = iterator.nextNode();
823: // } catch (DOMException ex) {
824: // ErrorManager.getDefault().notify(ex);
825: //
826: // break;
827: // }
828: //
829: // if ((curr == null) || (curr == last)) {
830: // break;
831: // }
832: //
833: // if (curr instanceof Text) {
834: // sb.append(curr.getNodeValue());
835: // }
836: // }
837: //
838: // iterator.detach();
839: //
840: // // Append content for the last node
841: // if (secondNode instanceof Text) {
842: // String s = secondNode.getNodeValue();
843: //
844: // for (int i = 0; i < second.getOffset(); i++) {
845: // sb.append(s.charAt(i));
846: // }
847: // }
848: //
849: // return sb.toString();
850: // }
851: }
|