Source Code Cross Referenced for CustomFoldManager.java in  » IDE-Netbeans » editor » org » netbeans » editor » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » editor » org.netbeans.editor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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.editor;
043:
044:        import org.netbeans.lib.editor.util.swing.DocumentUtilities;
045:        import org.openide.ErrorManager;
046:
047:        import javax.swing.text.Document;
048:        import javax.swing.text.BadLocationException;
049:        import javax.swing.text.Position;
050:        import javax.swing.event.DocumentEvent;
051:        import java.util.*;
052:        import java.util.regex.Pattern;
053:        import java.util.regex.Matcher;
054:        import org.netbeans.api.editor.fold.Fold;
055:        import org.netbeans.api.editor.fold.FoldType;
056:        import org.netbeans.spi.editor.fold.FoldHierarchyTransaction;
057:        import org.netbeans.spi.editor.fold.FoldManager;
058:        import org.netbeans.spi.editor.fold.FoldManagerFactory;
059:        import org.netbeans.spi.editor.fold.FoldOperation;
060:
061:        /**
062:         * Fold maintainer that creates and updates custom folds.
063:         *
064:         * @author Dusan Balek, Miloslav Metelka
065:         * @version 1.00
066:         */
067:
068:        final class CustomFoldManager implements  FoldManager {
069:
070:            private static final boolean debug = false;
071:
072:            public static final FoldType CUSTOM_FOLD_TYPE = new FoldType(
073:                    "custom-fold"); // NOI18N
074:
075:            private FoldOperation operation;
076:            private Document doc;
077:            private org.netbeans.editor.GapObjectArray markArray = new org.netbeans.editor.GapObjectArray();
078:            private int minUpdateMarkOffset;
079:            private int maxUpdateMarkOffset;
080:            private List removedFoldList;
081:            private HashMap customFoldId = new HashMap();
082:
083:            public void init(FoldOperation operation) {
084:                this .operation = operation;
085:            }
086:
087:            private FoldOperation getOperation() {
088:                return operation;
089:            }
090:
091:            public void initFolds(FoldHierarchyTransaction transaction) {
092:                try {
093:                    doc = getOperation().getHierarchy().getComponent()
094:                            .getDocument();
095:                    updateFolds(SyntaxUpdateTokens.getTokenInfoList(doc),
096:                            transaction);
097:                } catch (BadLocationException e) {
098:                    ErrorManager.getDefault().notify(e);
099:                }
100:            }
101:
102:            public void insertUpdate(DocumentEvent evt,
103:                    FoldHierarchyTransaction transaction) {
104:                try {
105:                    processRemovedFolds(transaction);
106:                    updateFolds(SyntaxUpdateTokens.getTokenInfoList(evt),
107:                            transaction);
108:                } catch (BadLocationException e) {
109:                    ErrorManager.getDefault().notify(e);
110:                }
111:            }
112:
113:            public void removeUpdate(DocumentEvent evt,
114:                    FoldHierarchyTransaction transaction) {
115:                try {
116:                    processRemovedFolds(transaction);
117:                    removeAffectedMarks(evt, transaction);
118:                    updateFolds(SyntaxUpdateTokens.getTokenInfoList(evt),
119:                            transaction);
120:                } catch (BadLocationException e) {
121:                    ErrorManager.getDefault().notify(e);
122:                }
123:            }
124:
125:            public void changedUpdate(DocumentEvent evt,
126:                    FoldHierarchyTransaction transaction) {
127:            }
128:
129:            public void removeEmptyNotify(Fold emptyFold) {
130:                removeFoldNotify(emptyFold);
131:            }
132:
133:            public void removeDamagedNotify(Fold damagedFold) {
134:                removeFoldNotify(damagedFold);
135:            }
136:
137:            public void expandNotify(Fold expandedFold) {
138:
139:            }
140:
141:            public void release() {
142:
143:            }
144:
145:            private void removeFoldNotify(Fold removedFold) {
146:                if (removedFoldList == null) {
147:                    removedFoldList = new ArrayList(3);
148:                }
149:                removedFoldList.add(removedFold);
150:            }
151:
152:            private void removeAffectedMarks(DocumentEvent evt,
153:                    FoldHierarchyTransaction transaction) {
154:                int removeOffset = evt.getOffset();
155:                int markIndex = findMarkIndex(removeOffset);
156:                if (markIndex < getMarkCount()) {
157:                    FoldMarkInfo mark;
158:                    while (markIndex >= 0
159:                            && (mark = getMark(markIndex)).getOffset() == removeOffset) {
160:                        mark.release(false, transaction);
161:                        removeMark(markIndex);
162:                        markIndex--;
163:                    }
164:                }
165:            }
166:
167:            private void processRemovedFolds(
168:                    FoldHierarchyTransaction transaction) {
169:                if (removedFoldList != null) {
170:                    for (int i = removedFoldList.size() - 1; i >= 0; i--) {
171:                        Fold removedFold = (Fold) removedFoldList.get(i);
172:                        FoldMarkInfo startMark = (FoldMarkInfo) getOperation()
173:                                .getExtraInfo(removedFold);
174:                        if (startMark.getId() != null)
175:                            customFoldId.put(startMark.getId(), Boolean
176:                                    .valueOf(removedFold.isCollapsed())); // remember the last fold's state before remove
177:                        FoldMarkInfo endMark = startMark.getPairMark(); // get prior releasing
178:                        if (getOperation().isStartDamaged(removedFold)) { // start mark area was damaged
179:                            startMark.release(true, transaction); // forced remove
180:                        }
181:                        if (getOperation().isEndDamaged(removedFold)) {
182:                            endMark.release(true, transaction);
183:                        }
184:                    }
185:                }
186:                removedFoldList = null;
187:            }
188:
189:            private void markUpdate(FoldMarkInfo mark) {
190:                markUpdate(mark.getOffset());
191:            }
192:
193:            private void markUpdate(int offset) {
194:                if (offset < minUpdateMarkOffset) {
195:                    minUpdateMarkOffset = offset;
196:                }
197:                if (offset > maxUpdateMarkOffset) {
198:                    maxUpdateMarkOffset = offset;
199:                }
200:            }
201:
202:            private FoldMarkInfo getMark(int index) {
203:                return (FoldMarkInfo) markArray.getItem(index);
204:            }
205:
206:            private int getMarkCount() {
207:                return markArray.getItemCount();
208:            }
209:
210:            private void removeMark(int index) {
211:                if (debug) {
212:                    /*DEBUG*/System.err.println("Removing mark from ind="
213:                            + index // NOI18N
214:                            + ": " + getMark(index)); // NOI18N
215:                }
216:                markArray.remove(index, 1);
217:            }
218:
219:            private void insertMark(int index, FoldMarkInfo mark) {
220:                markArray.insertItem(index, mark);
221:                if (debug) {
222:                    /*DEBUG*/System.err.println("Inserted mark at ind="
223:                            + index // NOI18N
224:                            + ": " + mark); // NOI18N
225:                }
226:            }
227:
228:            private int findMarkIndex(int offset) {
229:                int markCount = getMarkCount();
230:                int low = 0;
231:                int high = markCount - 1;
232:
233:                while (low <= high) {
234:                    int mid = (low + high) / 2;
235:                    int midMarkOffset = getMark(mid).getOffset();
236:
237:                    if (midMarkOffset < offset) {
238:                        low = mid + 1;
239:                    } else if (midMarkOffset > offset) {
240:                        high = mid - 1;
241:                    } else {
242:                        // mark starting exactly at the given offset found
243:                        // If multiple -> find the one with highest index
244:                        mid++;
245:                        while (mid < markCount
246:                                && getMark(mid).getOffset() == offset) {
247:                            mid++;
248:                        }
249:                        mid--;
250:                        return mid;
251:                    }
252:                }
253:                return low; // return higher index (e.g. for insert)
254:            }
255:
256:            private List getMarkList(List tokenList) {
257:                List markList = null;
258:                int tokenListSize = tokenList.size();
259:                if (tokenListSize != 0) {
260:                    for (int i = 0; i < tokenListSize; i++) {
261:                        SyntaxUpdateTokens.TokenInfo tokenInfo = (SyntaxUpdateTokens.TokenInfo) tokenList
262:                                .get(i);
263:                        FoldMarkInfo info;
264:                        try {
265:                            info = scanToken(tokenInfo);
266:                        } catch (BadLocationException e) {
267:                            ErrorManager.getDefault().notify(e);
268:                            info = null;
269:                        }
270:
271:                        if (info != null) {
272:                            if (markList == null) {
273:                                markList = new ArrayList();
274:                            }
275:                            markList.add(info);
276:                        }
277:                    }
278:                }
279:                return markList;
280:            }
281:
282:            private void processTokenList(List tokenList,
283:                    FoldHierarchyTransaction transaction) {
284:                List markList = getMarkList(tokenList);
285:                int markListSize;
286:                if (markList != null && ((markListSize = markList.size()) > 0)) {
287:                    // Find the index for insertion
288:                    int offset = ((FoldMarkInfo) markList.get(0)).getOffset();
289:                    int arrayMarkIndex = findMarkIndex(offset);
290:                    // Remember the corresponding mark in the array as well
291:                    FoldMarkInfo arrayMark;
292:                    int arrayMarkOffset;
293:                    if (arrayMarkIndex < getMarkCount()) {
294:                        arrayMark = getMark(arrayMarkIndex);
295:                        arrayMarkOffset = arrayMark.getOffset();
296:                    } else { // at last mark
297:                        arrayMark = null;
298:                        arrayMarkOffset = Integer.MAX_VALUE;
299:                    }
300:
301:                    for (int i = 0; i < markListSize; i++) {
302:                        FoldMarkInfo listMark = (FoldMarkInfo) markList.get(i);
303:                        int listMarkOffset = listMark.getOffset();
304:                        if (i == 0 || i == markListSize - 1) {
305:                            // Update the update-offsets by the first and last marks in the list
306:                            markUpdate(listMarkOffset);
307:                        }
308:                        if (listMarkOffset >= arrayMarkOffset) {
309:                            if (listMarkOffset == arrayMarkOffset) {
310:                                // At the same offset - likely the same mark
311:                                //   -> retain the collapsed state
312:                                listMark.setCollapsed(arrayMark.isCollapsed());
313:                            }
314:                            if (!arrayMark.isReleased()) { // make sure that the mark is released
315:                                arrayMark.release(false, transaction);
316:                            }
317:                            removeMark(arrayMarkIndex);
318:                            if (debug) {
319:                                /*DEBUG*/System.err
320:                                        .println("Removed dup mark from ind="
321:                                                + arrayMarkIndex + ": "
322:                                                + arrayMark); // NOI18N
323:                            }
324:                            if (arrayMarkIndex < getMarkCount()) {
325:                                arrayMark = getMark(arrayMarkIndex);
326:                                arrayMarkOffset = arrayMark.getOffset();
327:                            } else { // no more marks
328:                                arrayMark = null;
329:                                arrayMarkOffset = Integer.MAX_VALUE;
330:                            }
331:                        }
332:                        // Insert the listmark
333:                        insertMark(arrayMarkIndex, listMark);
334:                        if (debug) {
335:                            /*DEBUG*/System.err
336:                                    .println("Inserted mark at ind=" // NOI18N
337:                                            + arrayMarkIndex + ": " + listMark); // NOI18N
338:                        }
339:                        arrayMarkIndex++;
340:                    }
341:                }
342:            }
343:
344:            private void updateFolds(List tokenList,
345:                    FoldHierarchyTransaction transaction)
346:                    throws BadLocationException {
347:
348:                if (tokenList.size() > 0) {
349:                    processTokenList(tokenList, transaction);
350:                }
351:
352:                if (maxUpdateMarkOffset == -1) { // no updates
353:                    return;
354:                }
355:
356:                // Find the first mark to update and init the prevMark and parentMark prior the loop
357:                int index = findMarkIndex(minUpdateMarkOffset);
358:                FoldMarkInfo prevMark;
359:                FoldMarkInfo parentMark;
360:                if (index == 0) { // start from begining
361:                    prevMark = null;
362:                    parentMark = null;
363:                } else {
364:                    prevMark = getMark(index - 1);
365:                    parentMark = prevMark.getParentMark();
366:                }
367:
368:                // Iterate through the changed marks in the mark array 
369:                int markCount = getMarkCount();
370:                while (index < markCount) { // process the marks
371:                    FoldMarkInfo mark = getMark(index);
372:
373:                    // If the mark was released then it must be removed
374:                    if (mark.isReleased()) {
375:                        if (debug) {
376:                            /*DEBUG*/System.err
377:                                    .println("Removing released mark at ind=" // NOI18N
378:                                            + index + ": " + mark); // NOI18N
379:                        }
380:                        removeMark(index);
381:                        markCount--;
382:                        continue;
383:                    }
384:
385:                    // Update mark's status (folds, parentMark etc.)
386:                    if (mark.isStartMark()) { // starting a new fold
387:                        if (prevMark == null || prevMark.isStartMark()) { // new level
388:                            mark.setParentMark(prevMark); // prevMark == null means root level
389:                            parentMark = prevMark;
390:
391:                        } // same level => parent to the parent of the prevMark
392:
393:                    } else { // end mark
394:                        if (prevMark != null) {
395:                            if (prevMark.isStartMark()) { // closing nearest fold
396:                                prevMark.setEndMark(mark, false, transaction);
397:
398:                            } else { // prevMark is end mark - closing its parent fold
399:                                if (parentMark != null) {
400:                                    // mark's parent gets set as well
401:                                    parentMark.setEndMark(mark, false,
402:                                            transaction);
403:                                    parentMark = parentMark.getParentMark();
404:
405:                                } else { // prevMark's parentMark is null (top level)
406:                                    mark.makeSolitaire(false, transaction);
407:                                }
408:                            }
409:
410:                        } else { // prevMark is null
411:                            mark.makeSolitaire(false, transaction);
412:                        }
413:                    }
414:
415:                    // Set parent mark of the mark
416:                    mark.setParentMark(parentMark);
417:
418:                    prevMark = mark;
419:                    index++;
420:                }
421:
422:                minUpdateMarkOffset = Integer.MAX_VALUE;
423:                maxUpdateMarkOffset = -1;
424:
425:                if (debug) {
426:                    /*DEBUG*/System.err.println("MARKS DUMP:\n" + this );
427:                }
428:            }
429:
430:            public String toString() {
431:                StringBuffer sb = new StringBuffer();
432:                int markCount = getMarkCount();
433:                int markCountDigitCount = Integer.toString(markCount).length();
434:                for (int i = 0; i < markCount; i++) {
435:                    sb.append("["); // NOI18N
436:                    String iStr = Integer.toString(i);
437:                    appendSpaces(sb, markCountDigitCount - iStr.length());
438:                    sb.append(iStr);
439:                    sb.append("]:"); // NOI18N
440:                    FoldMarkInfo mark = getMark(i);
441:
442:                    // Add extra indent regarding the depth in hierarchy
443:                    int indent = 0;
444:                    FoldMarkInfo parentMark = mark.getParentMark();
445:                    while (parentMark != null) {
446:                        indent += 4;
447:                        parentMark = parentMark.getParentMark();
448:                    }
449:                    appendSpaces(sb, indent);
450:
451:                    sb.append(mark);
452:                    sb.append('\n');
453:                }
454:                return sb.toString();
455:            }
456:
457:            private static void appendSpaces(StringBuffer sb, int spaces) {
458:                while (--spaces >= 0) {
459:                    sb.append(' ');
460:                }
461:            }
462:
463:            private static Pattern pattern = Pattern
464:                    .compile("(<\\s*editor-fold(?:\\s+(\\S+)=\"([\\S \\t&&[^\"]]*)\")?(?:\\s+(\\S+)=\"([\\S \\t&&[^\"]]*)\")?(?:\\s+(\\S+)=\"([\\S \\t&&[^\"]]*)\")?\\s*>)|(?:</\\s*editor-fold\\s*>)"); // NOI18N
465:
466:            private FoldMarkInfo scanToken(
467:                    SyntaxUpdateTokens.TokenInfo tokenInfo)
468:                    throws BadLocationException {
469:                Matcher matcher = pattern.matcher(DocumentUtilities.getText(
470:                        doc, tokenInfo.getOffset(), tokenInfo.getLength()));
471:                if (matcher.find()) {
472:                    if (matcher.group(1) != null) { // fold's start mark found
473:                        String id = null;
474:                        boolean state = false;
475:                        String description = null;
476:
477:                        for (int i = 0; i < 3; i++) {
478:                            String key = matcher.group(2 * (i + 1));
479:                            String value = matcher.group(2 * (i + 1) + 1);
480:
481:                            if (key == null || value == null) {
482:                                break;
483:                            }
484:
485:                            if (key.equals("id")) { //NOI18N
486:                                id = value;
487:                            } else if (key.equals("defaultstate")) { //NOI18N
488:                                state = "collapsed".equals(value); //NOI18N
489:                            } else if (key.equals("desc")) { //NOI18N
490:                                description = value;
491:                            }
492:                        }
493:
494:                        if (id != null) { // fold's id exists
495:                            Boolean collapsed = (Boolean) customFoldId.get(id);
496:                            if (collapsed != null) {
497:                                state = collapsed.booleanValue(); // fold's state is already known from the past
498:                            } else {
499:                                customFoldId.put(id, Boolean.valueOf(state));
500:                            }
501:                        }
502:
503:                        return new FoldMarkInfo(true, tokenInfo.getOffset(),
504:                                tokenInfo.getLength(), id, state, description); // NOI18N
505:                    } else { // fold's end mark found
506:                        return new FoldMarkInfo(false, tokenInfo.getOffset(),
507:                                tokenInfo.getLength(), null, false, null);
508:                    }
509:                }
510:                return null;
511:            }
512:
513:            private final class FoldMarkInfo {
514:
515:                private boolean startMark;
516:                private Position pos;
517:                private int length;
518:                private String id;
519:                private boolean collapsed;
520:                private String description;
521:
522:                /** Matching pair mark used for fold construction */
523:                private FoldMarkInfo pairMark;
524:
525:                /** Parent mark defining nesting in the mark hierarchy. */
526:                private FoldMarkInfo parentMark;
527:
528:                /**
529:                 * Fold that corresponds to this mark (if it's start mark).
530:                 * It can be null if this mark is end mark or if it currently
531:                 * does not have the fold assigned.
532:                 */
533:                private Fold fold;
534:
535:                private boolean released;
536:
537:                private FoldMarkInfo(boolean startMark, int offset, int length,
538:                        String id, boolean collapsed, String description)
539:                        throws BadLocationException {
540:
541:                    this .startMark = startMark;
542:                    this .pos = doc.createPosition(offset);
543:                    this .length = length;
544:                    this .id = id;
545:                    this .collapsed = collapsed;
546:                    this .description = description;
547:                }
548:
549:                public String getId() {
550:                    return id;
551:                }
552:
553:                public String getDescription() {
554:                    return description;
555:                }
556:
557:                public boolean isStartMark() {
558:                    return startMark;
559:                }
560:
561:                public int getLength() {
562:                    return length;
563:                }
564:
565:                public int getOffset() {
566:                    return pos.getOffset();
567:                }
568:
569:                public int getEndOffset() {
570:                    return getOffset() + getLength();
571:                }
572:
573:                public boolean isCollapsed() {
574:                    return (fold != null) ? fold.isCollapsed() : collapsed;
575:                }
576:
577:                public boolean hasFold() {
578:                    return (fold != null);
579:                }
580:
581:                public void setCollapsed(boolean collapsed) {
582:                    this .collapsed = collapsed;
583:                }
584:
585:                public boolean isSolitaire() {
586:                    return (pairMark == null);
587:                }
588:
589:                public void makeSolitaire(boolean forced,
590:                        FoldHierarchyTransaction transaction) {
591:                    if (!isSolitaire()) {
592:                        if (isStartMark()) {
593:                            setEndMark(null, forced, transaction);
594:                        } else { // end mark
595:                            getPairMark().setEndMark(null, forced, transaction);
596:                        }
597:                    }
598:                }
599:
600:                public boolean isReleased() {
601:                    return released;
602:                }
603:
604:                /**
605:                 * Release this mark and mark for update.
606:                 */
607:                public void release(boolean forced,
608:                        FoldHierarchyTransaction transaction) {
609:                    if (!released) {
610:                        makeSolitaire(forced, transaction);
611:                        released = true;
612:                        markUpdate(this );
613:                    }
614:                }
615:
616:                public FoldMarkInfo getPairMark() {
617:                    return pairMark;
618:                }
619:
620:                private void setPairMark(FoldMarkInfo pairMark) {
621:                    this .pairMark = pairMark;
622:                }
623:
624:                public void setEndMark(FoldMarkInfo endMark, boolean forced,
625:                        FoldHierarchyTransaction transaction) {
626:                    if (!isStartMark()) {
627:                        throw new IllegalStateException("Not start mark"); // NOI18N
628:                    }
629:                    if (pairMark == endMark) {
630:                        return;
631:                    }
632:
633:                    if (pairMark != null) { // is currently paired to an end mark
634:                        releaseFold(forced, transaction);
635:                        pairMark.setPairMark(null);
636:                    }
637:
638:                    pairMark = endMark;
639:                    if (endMark != null) {
640:                        if (!endMark.isSolitaire()) { // make solitaire first
641:                            endMark.makeSolitaire(false, transaction); // not forced here
642:                        }
643:                        endMark.setPairMark(this );
644:                        endMark.setParentMark(this .getParentMark());
645:                        ensureFoldExists(transaction);
646:                    }
647:                }
648:
649:                public FoldMarkInfo getParentMark() {
650:                    return parentMark;
651:                }
652:
653:                public void setParentMark(FoldMarkInfo parentMark) {
654:                    this .parentMark = parentMark;
655:                }
656:
657:                private void releaseFold(boolean forced,
658:                        FoldHierarchyTransaction transaction) {
659:                    if (isSolitaire() || !isStartMark()) {
660:                        throw new IllegalStateException();
661:                    }
662:
663:                    if (fold != null) {
664:                        setCollapsed(fold.isCollapsed()); // serialize the collapsed info
665:                        if (!forced) {
666:                            getOperation().removeFromHierarchy(fold,
667:                                    transaction);
668:                        }
669:                        fold = null;
670:                    }
671:                }
672:
673:                public Fold getFold() {
674:                    if (isSolitaire()) {
675:                        return null;
676:                    }
677:                    if (!isStartMark()) {
678:                        return pairMark.getFold();
679:                    }
680:                    return fold;
681:                }
682:
683:                public void ensureFoldExists(
684:                        FoldHierarchyTransaction transaction) {
685:                    if (isSolitaire() || !isStartMark()) {
686:                        throw new IllegalStateException();
687:                    }
688:
689:                    if (fold == null) {
690:                        try {
691:                            if (!startMark) {
692:                                throw new IllegalStateException(
693:                                        "Not start mark: " + this ); // NOI18N
694:                            }
695:                            if (pairMark == null) {
696:                                throw new IllegalStateException(
697:                                        "No pairMark for mark:" + this ); // NOI18N
698:                            }
699:                            int startOffset = getOffset();
700:                            int startGuardedLength = getLength();
701:                            int endGuardedLength = pairMark.getLength();
702:                            int endOffset = pairMark.getOffset()
703:                                    + endGuardedLength;
704:                            fold = getOperation().addToHierarchy(
705:                                    CUSTOM_FOLD_TYPE, getDescription(),
706:                                    collapsed, startOffset, endOffset,
707:                                    startGuardedLength, endGuardedLength, this ,
708:                                    transaction);
709:                        } catch (BadLocationException e) {
710:                            ErrorManager.getDefault().notify(e);
711:                        }
712:                    }
713:                }
714:
715:                public String toString() {
716:                    StringBuffer sb = new StringBuffer();
717:                    sb.append(isStartMark() ? 'S' : 'E'); // NOI18N
718:
719:                    // Check whether this mark (or its pair) has fold
720:                    if (hasFold()
721:                            || (!isSolitaire() && getPairMark().hasFold())) {
722:                        sb.append("F"); // NOI18N
723:
724:                        // Check fold's status
725:                        if (isStartMark()
726:                                && (isSolitaire()
727:                                        || getOffset() != fold.getStartOffset() || getPairMark()
728:                                        .getEndOffset() != fold.getEndOffset())) {
729:                            sb.append("!!<"); // NOI18N
730:                            sb.append(fold.getStartOffset());
731:                            sb.append(","); // NOI18N
732:                            sb.append(fold.getEndOffset());
733:                            sb.append(">!!"); // NOI18N
734:                        }
735:                    }
736:
737:                    // Append mark's internal status
738:                    sb.append(" ("); // NOI18N
739:                    sb.append("o="); // NOI18N
740:                    sb.append(pos.getOffset());
741:                    sb.append(", l="); // NOI18N
742:                    sb.append(length);
743:                    sb.append(", d='"); // NOI18N
744:                    sb.append(description);
745:                    sb.append('\'');
746:                    if (getPairMark() != null) {
747:                        sb.append(", <->"); // NOI18N
748:                        sb.append(getPairMark().getOffset());
749:                    }
750:                    if (getParentMark() != null) {
751:                        sb.append(", ^"); // NOI18N
752:                        sb.append(getParentMark().getOffset());
753:                    }
754:                    sb.append(')');
755:
756:                    return sb.toString();
757:                }
758:
759:            }
760:
761:            public static final class Factory implements  FoldManagerFactory {
762:
763:                public FoldManager createFoldManager() {
764:                    return new CustomFoldManager();
765:                }
766:            }
767:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.