Source Code Cross Referenced for Annotations.java in  » Swing-Library » abeille-forms-designer » 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 » Swing Library » abeille forms designer » org.netbeans.editor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *                 Sun Public License Notice
0003:         *
0004:         * The contents of this file are subject to the Sun Public License
0005:         * Version 1.0 (the "License"). You may not use this file except in
0006:         * compliance with the License. A copy of the License is available at
0007:         * http://www.sun.com/
0008:         *
0009:         * The Original Code is NetBeans. The Initial Developer of the Original
0010:         * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun
0011:         * Microsystems, Inc. All Rights Reserved.
0012:         */
0013:
0014:        package org.netbeans.editor;
0015:
0016:        import java.beans.PropertyChangeEvent;
0017:        import java.beans.PropertyChangeListener;
0018:        import java.util.ArrayList;
0019:        import java.util.EventListener;
0020:        import java.util.HashMap;
0021:        import java.util.Iterator;
0022:        import java.util.LinkedList;
0023:        import java.util.Map;
0024:
0025:        import javax.swing.Action;
0026:        import javax.swing.JMenu;
0027:        import javax.swing.JMenuItem;
0028:        import javax.swing.JPopupMenu;
0029:        import javax.swing.event.DocumentEvent;
0030:        import javax.swing.event.DocumentListener;
0031:        import javax.swing.event.EventListenerList;
0032:        import javax.swing.text.BadLocationException;
0033:
0034:        /**
0035:         * Annotations class act as data model containing all annotations attached to
0036:         * one document. Class uses instances of private class LineAnnotations for
0037:         * grouping of added annotations by line. These objects (LineAnnotations) are
0038:         * referenced from two collections. First one is Map where the key is Mark. It
0039:         * is used during the drawing in DrawLayerFactory.AnnotationLayer - when the
0040:         * mark appears in mark change, the LineAnnotations instance is found for it and
0041:         * the active annotation on the line can be queried. Second is List where the
0042:         * LineAnnotations are sorted by line number. This list is used for drawing the
0043:         * annotations in the gutter when the sequential order is important.
0044:         * 
0045:         * The class also listen on document. It need to know how many lines where
0046:         * removed or added to refresh the LineAnnotations.line property.
0047:         * 
0048:         * @author David Konecny
0049:         * @since 07/2001
0050:         */
0051:        public class Annotations implements  DocumentListener {
0052:
0053:            /** Map of [Mark, LineAnnotations] */
0054:            private HashMap lineAnnotationsByMark;
0055:
0056:            /** List of [LineAnnotations] which is ordered by line number */
0057:            private ArrayList lineAnnotationsArray;
0058:
0059:            /** Drawing layer for drawing of annotations */
0060:            private DrawLayerFactory.AnnotationLayer drawLayer;
0061:
0062:            /** Reference to document */
0063:            private BaseDocument doc;
0064:
0065:            /** List of listeners on AnnotationsListener */
0066:            private EventListenerList listenerList;
0067:
0068:            /** Property change listener on annotation type changes */
0069:            private PropertyChangeListener l;
0070:
0071:            /** Property change listener on AnnotationTypes changes */
0072:            private PropertyChangeListener annoTypesListener;
0073:
0074:            /** Whether the column with glyph icons is visible */
0075:            private boolean glyphColumn = false;
0076:
0077:            /** Whether the column with cycling button is visible */
0078:            private boolean glyphButtonColumn = false;
0079:
0080:            public Annotations(BaseDocument doc) {
0081:                lineAnnotationsByMark = new HashMap(30);
0082:                lineAnnotationsArray = new ArrayList(20);
0083:                listenerList = new EventListenerList();
0084:
0085:                drawLayer = null;
0086:                this .doc = doc;
0087:
0088:                // add annotation drawing layer
0089:                doc.addLayer(new DrawLayerFactory.AnnotationLayer(doc),
0090:                        DrawLayerFactory.ANNOTATION_LAYER_VISIBILITY);
0091:
0092:                // listener on document changes
0093:                this .doc.addDocumentListener(this );
0094:
0095:                l = new PropertyChangeListener() {
0096:                    public void propertyChange(PropertyChangeEvent evt) {
0097:                        if (evt.getPropertyName() == AnnotationDesc.PROP_ANNOTATION_TYPE) {
0098:                            AnnotationDesc anno = (AnnotationDesc) evt
0099:                                    .getSource();
0100:                            LineAnnotations lineAnnos = (LineAnnotations) lineAnnotationsByMark
0101:                                    .get(anno.getMark());
0102:                            lineAnnos.refreshAnnotations();
0103:                            refreshLine(lineAnnos.getLine());
0104:                        }
0105:                        if (evt.getPropertyName() == AnnotationDesc.PROP_MOVE_TO_FRONT) {
0106:                            AnnotationDesc anno = (AnnotationDesc) evt
0107:                                    .getSource();
0108:                            frontAnnotation(anno);
0109:                        }
0110:                    }
0111:                };
0112:
0113:                AnnotationTypes.getTypes().addPropertyChangeListener(
0114:                        annoTypesListener = new PropertyChangeListener() {
0115:                            public void propertyChange(PropertyChangeEvent evt) {
0116:                                if (evt.getPropertyName() == AnnotationTypes.PROP_COMBINE_GLYPHS) {
0117:                                    LineAnnotations lineAnnos;
0118:                                    for (Iterator it = lineAnnotationsArray
0119:                                            .iterator(); it.hasNext();) {
0120:                                        lineAnnos = (LineAnnotations) it.next();
0121:                                        lineAnnos.refreshAnnotations();
0122:                                    }
0123:                                }
0124:                                if (evt.getPropertyName() == AnnotationTypes.PROP_ANNOTATION_TYPES) {
0125:                                    LineAnnotations lineAnnos;
0126:                                    for (Iterator it = lineAnnotationsArray
0127:                                            .iterator(); it.hasNext();) {
0128:                                        lineAnnos = (LineAnnotations) it.next();
0129:                                        for (Iterator it2 = lineAnnos
0130:                                                .getAnnotations(); it2
0131:                                                .hasNext();) {
0132:                                            AnnotationDesc anno = (AnnotationDesc) it2
0133:                                                    .next();
0134:                                            anno.updateAnnotationType();
0135:                                        }
0136:                                    }
0137:                                }
0138:                                fireChangedAll();
0139:                            }
0140:                        });
0141:
0142:            }
0143:
0144:            /** Finds the drawing layer for annotations */
0145:            public synchronized DrawLayerFactory.AnnotationLayer getLayer() {
0146:                if (drawLayer == null)
0147:                    drawLayer = (DrawLayerFactory.AnnotationLayer) doc
0148:                            .findLayer(DrawLayerFactory.ANNOTATION_LAYER_NAME);
0149:                return drawLayer;
0150:            }
0151:
0152:            /** Add annotation */
0153:            public void addAnnotation(AnnotationDesc anno) {
0154:
0155:                // create mark for this annotation. One mark can be shared by more
0156:                // annotations
0157:                MarkChain chain = getLayer().getMarkChain();
0158:                try {
0159:                    chain.addMark(anno.getOffset());
0160:                } catch (BadLocationException e) {
0161:                    return;
0162:                }
0163:                // attach created mark to annotation
0164:                anno.setMark(chain.getAddedMark());
0165:
0166:                // fine LineAnnotations instance corresponding to the line of this
0167:                // annotation
0168:                // or create new LineAnnotations if this is first annotation on this
0169:                // line
0170:                LineAnnotations lineAnnos = getLineAnnotations(anno.getLine());
0171:                if (lineAnnos == null) {
0172:                    lineAnnos = new LineAnnotations();
0173:                    lineAnnos.addAnnotation(anno);
0174:                    lineAnnotationsByMark.put(anno.getMark(), lineAnnos);
0175:
0176:                    // insert newly created LineAnnotations into sorted array
0177:                    boolean inserted = false;
0178:                    for (int i = 0; i < lineAnnotationsArray.size(); i++) {
0179:                        if (((LineAnnotations) lineAnnotationsArray.get(i))
0180:                                .getLine() > lineAnnos.getLine()) {
0181:                            lineAnnotationsArray.add(i, lineAnnos);
0182:                            inserted = true;
0183:                            break;
0184:                        }
0185:                    }
0186:                    if (!inserted)
0187:                        lineAnnotationsArray.add(lineAnnos);
0188:
0189:                } else {
0190:                    lineAnnos.addAnnotation(anno);
0191:                    // check whether this mark is in lineAnnotationsByMark Map
0192:                    // it is possible that Line.Part annotations will have more marks
0193:                    // for one line
0194:                    if (lineAnnotationsByMark.get(anno.getMark()) == null)
0195:                        lineAnnotationsByMark.put(anno.getMark(), lineAnnos);
0196:                }
0197:
0198:                // add listener on changes of annotation type
0199:                anno.addPropertyChangeListener(l);
0200:
0201:                // ignore annotation types with default icon
0202:                if (anno.isVisible()
0203:                        && (!anno.isDefaultGlyph() || (anno.isDefaultGlyph() && lineAnnos
0204:                                .getCount() > 1))) {
0205:                    glyphColumn = true;
0206:                }
0207:
0208:                if (lineAnnos.getCount() > 1)
0209:                    glyphButtonColumn = true;
0210:
0211:                // notify view that it must be redrawn
0212:                refreshLine(lineAnnos.getLine());
0213:            }
0214:
0215:            /** Remove annotation */
0216:            public void removeAnnotation(AnnotationDesc anno) {
0217:
0218:                // find LineAnnotations for the mark
0219:                LineAnnotations lineAnnos = (LineAnnotations) lineAnnotationsByMark
0220:                        .get(anno.getMark());
0221:                int line = lineAnnos.getLine();
0222:                // remove annotation from the line
0223:                lineAnnos.removeAnnotation(anno);
0224:
0225:                // check if this mark is referenced or not. If not, remove it
0226:                if (!lineAnnos.isMarkStillReferenced(anno.getMark())) {
0227:                    lineAnnotationsByMark.remove(anno.getMark());
0228:                    MarkChain chain = getLayer().getMarkChain();
0229:                    chain.removeMark(anno.getOffset());
0230:                }
0231:
0232:                // if there is no more annotations on the line, remove LineAnnotations
0233:                if (lineAnnos.getCount() == 0) {
0234:                    lineAnnotationsArray.remove(lineAnnotationsArray
0235:                            .indexOf(lineAnnos));
0236:                }
0237:
0238:                // clear the mark from annotation
0239:                anno.setMark(null);
0240:
0241:                // remove listener on changes of annotation type
0242:                anno.removePropertyChangeListener(l);
0243:
0244:                // notify view that must be redrawn
0245:                refreshLine(line);
0246:            }
0247:
0248:            /**
0249:             * Finds active annotation for the Mark. It is called from DrawLayer when it
0250:             * found the DrawMark
0251:             */
0252:            public AnnotationDesc getActiveAnnotation(Mark mark) {
0253:                LineAnnotations annos;
0254:                annos = (LineAnnotations) lineAnnotationsByMark.get(mark);
0255:                if (annos == null) {
0256:                    return null;
0257:                }
0258:                AnnotationDesc anno = annos.getActive();
0259:                // it is possible that some other mark on the line (means
0260:                // some other annotations) is active
0261:                if (anno.getMark() != mark) {
0262:                    return null;
0263:                }
0264:                return anno;
0265:            }
0266:
0267:            /** Finds LineAnnotations for the given line number */
0268:            protected LineAnnotations getLineAnnotations(int line) {
0269:                LineAnnotations annos;
0270:                // TODO: optimize searching
0271:                for (int i = 0; i < lineAnnotationsArray.size(); i++) {
0272:                    annos = (LineAnnotations) lineAnnotationsArray.get(i);
0273:                    if (annos.getLine() == line)
0274:                        return annos;
0275:                }
0276:                return null;
0277:            }
0278:
0279:            /**
0280:             * Returns the active annotation for the given line number. It is called
0281:             * from the glyph gutter
0282:             */
0283:            public AnnotationDesc getActiveAnnotation(int line) {
0284:                LineAnnotations annos = getLineAnnotations(line);
0285:                if (annos == null)
0286:                    return null;
0287:                return annos.getActive();
0288:            }
0289:
0290:            /**
0291:             * Move annotation in front of others. The activated annotation is moved in
0292:             * front of other annotations on the same line
0293:             */
0294:            public void frontAnnotation(AnnotationDesc anno) {
0295:                int line = anno.getLine();
0296:                LineAnnotations annos = getLineAnnotations(line);
0297:                if (annos == null)
0298:                    return;
0299:                annos.activate(anno);
0300:                refreshLine(line);
0301:            }
0302:
0303:            /**
0304:             * Activate next annotation on the line. Used for cycling through the
0305:             * annotations
0306:             */
0307:            public AnnotationDesc activateNextAnnotation(int line) {
0308:                LineAnnotations annos = getLineAnnotations(line);
0309:                if (annos == null)
0310:                    return null;
0311:                AnnotationDesc aa = annos.activateNext();
0312:                refreshLine(line);
0313:                return aa;
0314:            }
0315:
0316:            /** Get next line number with some annotation */
0317:            public int getNextLineWithAnnotation(int line) {
0318:                LineAnnotations annos;
0319:                // TODO: optimize searching
0320:                for (int i = 0; i < lineAnnotationsArray.size(); i++) {
0321:                    annos = (LineAnnotations) lineAnnotationsArray.get(i);
0322:                    if (annos.getLine() >= line)
0323:                        return annos.getLine();
0324:                }
0325:                return -1;
0326:            }
0327:
0328:            /** Get next line number with some annotation */
0329:            public AnnotationDesc getAnnotation(int line, String type) {
0330:                return null;
0331:            }
0332:
0333:            /** Return list of pasive annotations which should be drawn on the backgorund */
0334:            public AnnotationDesc[] getPasiveAnnotations(int line) {
0335:                LineAnnotations annos = getLineAnnotations(line);
0336:                if (annos == null)
0337:                    return null;
0338:                if (annos.getCount() <= 1)
0339:                    return null;
0340:                return annos.getPasive();
0341:            }
0342:
0343:            /** Returns number of visible annotations on the line */
0344:            public int getNumberOfAnnotations(int line) {
0345:                LineAnnotations annos = getLineAnnotations(line);
0346:                if (annos == null)
0347:                    return 0;
0348:                return annos.getCount();
0349:            }
0350:
0351:            /** Notify view that it is necessary to redraw the line of the document */
0352:            protected void refreshLine(int line) {
0353:                fireChangedLine(line);
0354:                int start = Utilities.getRowStartFromLineOffset(doc, line);
0355:                int end = Utilities.getRowStartFromLineOffset(doc, line + 1);
0356:                if (end == -1)
0357:                    end = doc.getLength();
0358:                doc.repaintBlock(start, end);
0359:            }
0360:
0361:            /**
0362:             * Checks the number of removed lines and recalculate LineAnnotations.line
0363:             * property
0364:             */
0365:            public void removeUpdate(DocumentEvent e) {
0366:                BaseDocumentEvent be = (BaseDocumentEvent) e;
0367:                int countOfDeletedLines = be.getLFCount();
0368:                if (countOfDeletedLines == 0)
0369:                    return;
0370:
0371:                int changedLine = be.getLine();
0372:
0373:                LineAnnotations annos;
0374:                for (int i = 0; i < lineAnnotationsArray.size(); i++) {
0375:                    annos = (LineAnnotations) lineAnnotationsArray.get(i);
0376:                    if (annos.getLine() > changedLine
0377:                            && annos.getLine() < changedLine
0378:                                    + countOfDeletedLines)
0379:                        annos.setLine(changedLine);
0380:                    if (annos.getLine() > changedLine)
0381:                        annos.setLine(annos.getLine() - countOfDeletedLines);
0382:                }
0383:                // fire event to AnnotationsListeners that everything should be redraw
0384:                fireChangedAll();
0385:            }
0386:
0387:            /**
0388:             * Checks the number of inserted lines and recalculate LineAnnotations.line
0389:             * property
0390:             */
0391:            public void insertUpdate(DocumentEvent e) {
0392:                BaseDocumentEvent be = (BaseDocumentEvent) e;
0393:                int countOfInsertedLines = be.getLFCount();
0394:                if (countOfInsertedLines == 0)
0395:                    return;
0396:
0397:                int changedLine = be.getLine();
0398:
0399:                LineAnnotations annos;
0400:                LineAnnotations current = null;
0401:                for (int i = 0; i < lineAnnotationsArray.size(); i++) {
0402:                    annos = (LineAnnotations) lineAnnotationsArray.get(i);
0403:                    if (annos.getLine() == changedLine
0404:                            && annos.getActive().getOffset() > e.getOffset())
0405:                        current = annos;
0406:                    if (annos.getLine() > changedLine)
0407:                        annos.setLine(annos.getLine() + countOfInsertedLines);
0408:                }
0409:                if (current != null)
0410:                    current.setLine(current.getLine() + countOfInsertedLines);
0411:
0412:                // fire event to AnnotationsListeners that everything should be redraw
0413:                fireChangedAll();
0414:            }
0415:
0416:            /** Gives notification that an attribute or set of attributes changed. */
0417:            public void changedUpdate(DocumentEvent e) {
0418:            }
0419:
0420:            /** Add AnnotationsListener listener */
0421:            public void addAnnotationsListener(AnnotationsListener listener) {
0422:                listenerList.add(AnnotationsListener.class, listener);
0423:            }
0424:
0425:            /** Remove AnnotationsListener listener */
0426:            public void removeAnnotationsListener(AnnotationsListener listener) {
0427:                listenerList.remove(AnnotationsListener.class, listener);
0428:            }
0429:
0430:            /** Fire AnnotationsListener.ChangedLine change */
0431:            protected void fireChangedLine(int line) {
0432:                // Guaranteed to return a non-null array
0433:                Object[] listeners = listenerList.getListenerList();
0434:                // Process the listeners last to first, notifying
0435:                // those that are interested in this event
0436:                for (int i = listeners.length - 2; i >= 0; i -= 2) {
0437:                    if (listeners[i] == AnnotationsListener.class) {
0438:                        // Lazily create the event:
0439:                        // if (e == null)
0440:                        // e = new ListSelectionEvent(this, firstIndex, lastIndex);
0441:                        ((AnnotationsListener) listeners[i + 1])
0442:                                .changedLine(line);
0443:                    }
0444:                }
0445:            }
0446:
0447:            /** Fire AnnotationsListener.ChangedAll change */
0448:            protected void fireChangedAll() {
0449:                // Guaranteed to return a non-null array
0450:                Object[] listeners = listenerList.getListenerList();
0451:                // Process the listeners last to first, notifying
0452:                // those that are interested in this event
0453:                for (int i = listeners.length - 2; i >= 0; i -= 2) {
0454:                    if (listeners[i] == AnnotationsListener.class) {
0455:                        // Lazily create the event:
0456:                        // if (e == null)
0457:                        // e = new ListSelectionEvent(this, firstIndex, lastIndex);
0458:                        ((AnnotationsListener) listeners[i + 1]).changedAll();
0459:                    }
0460:                }
0461:            }
0462:
0463:            /**
0464:             * Return whether this document has or had any glyph icon attached. This
0465:             * method is called from glyph gutter to check whether the glyph column
0466:             * should be drawn or not.
0467:             */
0468:            public boolean isGlyphColumn() {
0469:                return glyphColumn;
0470:            }
0471:
0472:            /**
0473:             * Return whether this document has or had more annotations on one line.
0474:             * This method is called from glyph gutter to check whether the glyph
0475:             * cycling column should be drawn or not.
0476:             */
0477:            public boolean isGlyphButtonColumn() {
0478:                return glyphButtonColumn;
0479:            }
0480:
0481:            /**
0482:             * Creates menu item for the given action. It must handle the BaseActions,
0483:             * which have localized name stored not in Action.NAME property.
0484:             */
0485:            private JMenuItem createMenuItem(Action action) {
0486:                if (action instanceof  BaseAction) {
0487:                    JMenuItem item = new JMenuItem(((BaseAction) action)
0488:                            .getPopupMenuText(null));
0489:                    item.addActionListener(action);
0490:                    return item;
0491:                } else {
0492:                    JMenuItem item = new JMenuItem((String) action
0493:                            .getValue(Action.NAME));
0494:                    item.addActionListener(action);
0495:                    return item;
0496:                }
0497:            }
0498:
0499:            /** Creates popup menu with all actions for the given line. */
0500:            public JPopupMenu createPopupMenu(BaseKit kit, int line) {
0501:                return createMenu(kit, line).getPopupMenu();
0502:            }
0503:
0504:            /** Creates popup menu with all actions for the given line. */
0505:            public JMenu createMenu(BaseKit kit, int line) {
0506:                LineAnnotations annos = getLineAnnotations(line);
0507:                Map types = new HashMap(AnnotationTypes.getTypes()
0508:                        .getVisibleAnnotationTypeNamesCount() * 4 / 3);
0509:
0510:                JMenu pm = new JMenu(LocaleSupport
0511:                        .getString("generate-gutter-popup"));
0512:                Action[] actions;
0513:                boolean separator = false;
0514:                boolean added = false;
0515:                JMenu subMenu;
0516:
0517:                if (annos != null) {
0518:
0519:                    // first, add actions for active annotation
0520:                    AnnotationDesc anno = annos.getActive();
0521:                    if (anno != null) {
0522:                        actions = anno.getActions();
0523:                        if (actions != null) {
0524:                            for (int i = 0; i < actions.length; i++) {
0525:                                pm.add(createMenuItem(actions[i]));
0526:                            }
0527:                            separator = true;
0528:                            types.put(anno.getAnnotationType(), anno
0529:                                    .getAnnotationType());
0530:                        }
0531:                    }
0532:
0533:                    // second, add submenus for all pasive annotations
0534:                    AnnotationDesc[] pasiveAnnos = annos.getPasive();
0535:                    added = false;
0536:                    if (pasiveAnnos != null) {
0537:                        for (int i = 0; i < pasiveAnnos.length; i++) {
0538:                            actions = pasiveAnnos[i].getActions();
0539:                            if (actions != null) {
0540:                                subMenu = new JMenu(pasiveAnnos[i]
0541:                                        .getAnnotationTypeInstance()
0542:                                        .getDescription());
0543:                                for (int j = 0; j < actions.length; j++)
0544:                                    subMenu.add(createMenuItem(actions[j]));
0545:                                if (separator) {
0546:                                    separator = false;
0547:                                    pm.addSeparator();
0548:                                }
0549:                                pm.add(subMenu);
0550:                                added = true;
0551:                                types.put(pasiveAnnos[i].getAnnotationType(),
0552:                                        pasiveAnnos[i].getAnnotationType());
0553:                            }
0554:                        }
0555:                        if (added)
0556:                            separator = true;
0557:                    }
0558:                }
0559:
0560:                // third, add all remaining possible actions to the end of the list
0561:                added = false;
0562:                AnnotationType type;
0563:                for (Iterator i = AnnotationTypes.getTypes()
0564:                        .getAnnotationTypeNames(); i.hasNext();) {
0565:                    type = AnnotationTypes.getTypes()
0566:                            .getType((String) i.next());
0567:                    if (type == null || !type.isVisible())
0568:                        continue;
0569:                    if (types.get(type.getName()) != null)
0570:                        continue;
0571:                    actions = type.getActions();
0572:                    if (actions != null) {
0573:                        subMenu = new JMenu(type.getDescription());
0574:                        for (int j = 0; j < actions.length; j++)
0575:                            subMenu.add(createMenuItem(actions[j]));
0576:                        if (separator) {
0577:                            separator = false;
0578:                            pm.addSeparator();
0579:                        }
0580:                        pm.add(subMenu);
0581:                        added = true;
0582:                    }
0583:                }
0584:                if (added)
0585:                    separator = true;
0586:
0587:                if (separator)
0588:                    pm.addSeparator();
0589:
0590:                // add checkbox for enabling/disabling of line numbers
0591:                BaseAction action = (BaseAction) kit
0592:                        .getActionByName(BaseKit.toggleLineNumbersAction);
0593:                pm.add(action.getPopupMenuItem(null));
0594:
0595:                return pm;
0596:            }
0597:
0598:            /**
0599:             * Manager of all annotations attached to one line. Class stores the
0600:             * references to all annotations from one line in List and also stores which
0601:             * annotation is active, count of visible annotations and line number.
0602:             */
0603:            static public class LineAnnotations extends Object {
0604:
0605:                /** List with all annotations in this LineAnnotations */
0606:                private LinkedList annos;
0607:
0608:                /** List with all visible annotations in this LineAnnotations */
0609:                private LinkedList annosVisible;
0610:
0611:                /**
0612:                 * Active annotation. Used only in case there is more than one
0613:                 * annotation on the line
0614:                 */
0615:                private AnnotationDesc active;
0616:
0617:                /** Line number */
0618:                private int lineNumber;
0619:
0620:                protected LineAnnotations() {
0621:                    annos = new LinkedList();
0622:                    annosVisible = new LinkedList();
0623:                    lineNumber = -1;
0624:                }
0625:
0626:                /** Add annotation to this line and activate it. */
0627:                public void addAnnotation(AnnotationDesc anno) {
0628:                    if (lineNumber == -1)
0629:                        lineNumber = anno.getLine();
0630:                    annos.add(anno);
0631:                    if (anno.isVisible()) {
0632:                        active = anno;
0633:                    }
0634:                    refreshAnnotations();
0635:                }
0636:
0637:                /**
0638:                 * Remove annotation from this line. Refresh the active one and count of
0639:                 * visible.
0640:                 */
0641:                public void removeAnnotation(AnnotationDesc anno) {
0642:                    if (anno == active)
0643:                        activateNext();
0644:                    annos.remove(anno);
0645:                    if (active == anno)
0646:                        active = null;
0647:                    refreshAnnotations();
0648:                }
0649:
0650:                /** Return the active line annotation. */
0651:                public AnnotationDesc getActive() {
0652:                    return active;
0653:                }
0654:
0655:                /** Getter for the line number property */
0656:                public int getLine() {
0657:                    return lineNumber;
0658:                }
0659:
0660:                /** Setter for the line number property */
0661:                public void setLine(int line) {
0662:                    lineNumber = line;
0663:                }
0664:
0665:                /** Gets the array of all pasive and visible annotations */
0666:                public AnnotationDesc[] getPasive() {
0667:                    AnnotationDesc[] pasives = new AnnotationDesc[getCount() - 1];
0668:                    AnnotationDesc anno;
0669:                    int startIndex = annosVisible.indexOf(getActive());
0670:                    int index = startIndex;
0671:                    int i = 0;
0672:                    while (true) {
0673:                        index++;
0674:                        if (index >= annosVisible.size())
0675:                            index = 0;
0676:                        if (index == startIndex)
0677:                            break;
0678:
0679:                        pasives[i] = (AnnotationDesc) annosVisible.get(index);
0680:                        i++;
0681:                    }
0682:                    return pasives;
0683:                }
0684:
0685:                /** Make the given annotation active. */
0686:                public boolean activate(AnnotationDesc anno) {
0687:
0688:                    int i, j;
0689:                    i = annosVisible.indexOf(anno);
0690:
0691:                    if (i == -1) {
0692:                        // was anno combined by some type ??
0693:                        for (j = 0; j < annosVisible.size(); j++) {
0694:                            if (annosVisible.get(j) instanceof  AnnotationCombination) {
0695:                                if (((AnnotationCombination) annosVisible
0696:                                        .get(j)).isAnnotationCombined(anno)) {
0697:                                    i = j;
0698:                                    anno = (AnnotationCombination) annosVisible
0699:                                            .get(j);
0700:                                    break;
0701:                                }
0702:                            }
0703:                        }
0704:                    }
0705:
0706:                    if (i == -1)
0707:                        return false;
0708:
0709:                    if (annosVisible.get(i) == null)
0710:                        return false;
0711:
0712:                    if (anno == active || !anno.isVisible())
0713:                        return false;
0714:
0715:                    active = anno;
0716:
0717:                    return true;
0718:                }
0719:
0720:                /** Get count of visible annotations on the line */
0721:                public int getCount() {
0722:                    return annosVisible.size();
0723:                }
0724:
0725:                /** Activate next annoation on the line. Used during the cycling. */
0726:                public AnnotationDesc activateNext() {
0727:                    if (getCount() <= 1)
0728:                        return active;
0729:
0730:                    int current = annosVisible.indexOf(active);
0731:                    current++;
0732:                    if (current >= getCount())
0733:                        current = 0;
0734:                    active = (AnnotationDesc) annosVisible.get(current);
0735:                    return active;
0736:                }
0737:
0738:                /**
0739:                 * Searches all combination annotation type and sort them by
0740:                 * getCombinationOrder into combTypes array which is passed as paramter.
0741:                 */
0742:                private void fillInCombinationsAndOrderThem(LinkedList combTypes) {
0743:                    AnnotationType type;
0744:                    AnnotationType.CombinationMember[] combs;
0745:
0746:                    for (Iterator it = AnnotationTypes.getTypes()
0747:                            .getAnnotationTypeNames(); it.hasNext();) {
0748:                        type = AnnotationTypes.getTypes().getType(
0749:                                (String) it.next());
0750:                        if (type == null)
0751:                            continue;
0752:                        combs = type.getCombinations();
0753:                        if (combs != null
0754:                                && type.isWholeLine()
0755:                                && (combs.length >= 2 || (combs.length == 1 && combs[0]
0756:                                        .isAbsorbAll()))) {
0757:                            if (type.getCombinationOrder() == 0) {
0758:                                combTypes.add(type);
0759:                            } else {
0760:                                boolean inserted = false;
0761:                                for (int i = 0; i < combTypes.size(); i++) {
0762:                                    if (((AnnotationType) combTypes.get(i))
0763:                                            .getCombinationOrder() > type
0764:                                            .getCombinationOrder()) {
0765:                                        combTypes.add(i, type);
0766:                                        inserted = true;
0767:                                        break;
0768:                                    }
0769:                                }
0770:                                if (!inserted)
0771:                                    combTypes.add(type);
0772:                            }
0773:                        }
0774:                    }
0775:                }
0776:
0777:                /**
0778:                 * For the given combination annotation type and list of annotations it
0779:                 * finds all annotations which are combined by this combination and
0780:                 * inserts into list of annotations new combined annotation which wraps
0781:                 * combined annotations. The result list of annotations can contain null
0782:                 * values for annotations which were combined.
0783:                 */
0784:                private boolean combineType(AnnotationType combType,
0785:                        LinkedList annosDupl) {
0786:
0787:                    int i, j, k;
0788:                    boolean matchedType;
0789:                    int countOfAnnos = 0;
0790:                    int valid_optional_count = 0;
0791:
0792:                    LinkedList combinedAnnos = new LinkedList();
0793:
0794:                    AnnotationType.CombinationMember[] combs = combType
0795:                            .getCombinations();
0796:
0797:                    // check that there is match between line annos & all types
0798:                    // specified in combination
0799:                    boolean matchedComb = true;
0800:                    AnnotationType.CombinationMember comb;
0801:                    AnnotationDesc anno;
0802:                    for (i = 0; i < combs.length; i++) {
0803:
0804:                        comb = combs[i];
0805:                        matchedType = false;
0806:
0807:                        // check that for one specified combination type there exist
0808:                        // some annotation
0809:                        for (j = 0; j < annosDupl.size(); j++) {
0810:
0811:                            anno = (AnnotationDesc) annosDupl.get(j);
0812:
0813:                            if (anno == null)
0814:                                continue;
0815:
0816:                            // check whether this annotation matches the specified
0817:                            // combination type
0818:                            if (comb.getName().equals(anno.getAnnotationType())) {
0819:                                countOfAnnos++;
0820:
0821:                                // now check if the combination has specified some
0822:                                // minimum count of annos
0823:                                if (comb.getMinimumCount() == 0) {
0824:                                    matchedType = true;
0825:                                    countOfAnnos++;
0826:                                    combinedAnnos.add(anno);
0827:                                    if (!comb.isAbsorbAll())
0828:                                        break;
0829:                                } else {
0830:                                    int requiredCount = comb.getMinimumCount() - 1;
0831:                                    for (k = j + 1; (k < annosDupl.size())
0832:                                            && (requiredCount > 0); k++) {
0833:                                        if (annosDupl.get(k) == null)
0834:                                            continue;
0835:                                        if (comb.getName().equals(
0836:                                                ((AnnotationDesc) annosDupl
0837:                                                        .get(k))
0838:                                                        .getAnnotationType())) {
0839:                                            requiredCount--;
0840:                                        }
0841:                                    }
0842:                                    if (requiredCount == 0) {
0843:                                        matchedType = true;
0844:
0845:                                        combinedAnnos.add(anno);
0846:                                        for (k = j + 1; k < annosDupl.size(); k++) {
0847:                                            if (annosDupl.get(k) == null)
0848:                                                continue;
0849:                                            if (comb
0850:                                                    .getName()
0851:                                                    .equals(
0852:                                                            ((AnnotationDesc) annosDupl
0853:                                                                    .get(k))
0854:                                                                    .getAnnotationType())) {
0855:                                                countOfAnnos++;
0856:                                                combinedAnnos.add(annosDupl
0857:                                                        .get(k));
0858:                                            }
0859:                                        }
0860:                                    }
0861:                                    break;
0862:                                }
0863:
0864:                            }
0865:
0866:                        }
0867:
0868:                        if (matchedType) {
0869:                            if (comb.isOptional())
0870:                                valid_optional_count++;
0871:                        } else {
0872:                            if (!comb.isOptional()) {
0873:                                matchedComb = false;
0874:                                break;
0875:                            }
0876:                        }
0877:
0878:                    }
0879:                    if (combType.getMinimumOptionals() > valid_optional_count)
0880:                        matchedComb = false;
0881:
0882:                    AnnotationCombination annoComb = null;
0883:                    if (matchedComb) {
0884:
0885:                        boolean activateComb = false;
0886:
0887:                        for (i = 0; i < combinedAnnos.size(); i++) {
0888:                            if (combinedAnnos.get(i) == active)
0889:                                activateComb = true;
0890:
0891:                            if (annoComb == null) {
0892:                                annoComb = new AnnotationCombination(combType
0893:                                        .getName(),
0894:                                        (AnnotationDesc) combinedAnnos.get(i));
0895:                                annosDupl.set(annosDupl.indexOf(combinedAnnos
0896:                                        .get(i)), annoComb); // replace
0897:                                // the
0898:                                // original
0899:                                // annotation
0900:                                // by
0901:                                // the
0902:                                // new
0903:                                // Combined
0904:                                // one
0905:                            } else {
0906:                                annoComb
0907:                                        .addCombinedAnnotation((AnnotationDesc) combinedAnnos
0908:                                                .get(i));
0909:                                annosDupl.set(annosDupl.indexOf(combinedAnnos
0910:                                        .get(i)), null); // remove
0911:                                // annotations
0912:                                // which
0913:                                // were
0914:                                // combined
0915:                                // form
0916:                                // the
0917:                                // array
0918:                            }
0919:                        }
0920:                        if (activateComb)
0921:                            active = annoComb;
0922:
0923:                        return true;
0924:                    }
0925:
0926:                    return false;
0927:                }
0928:
0929:                /**
0930:                 * Refresh the active annotation and count of visible annotations. This
0931:                 * method is used after change of annotation type of some annotation on
0932:                 * this line
0933:                 */
0934:                public void refreshAnnotations() {
0935:                    int i, j, k, count;
0936:
0937:                    if (!AnnotationTypes.getTypes().isCombineGlyphs()
0938:                            .booleanValue()) {
0939:
0940:                        // combinations are disabled
0941:                        annosVisible = new LinkedList();
0942:                        for (i = 0; i < annos.size(); i++) {
0943:                            if (!((AnnotationDesc) annos.get(i)).isVisible())
0944:                                continue;
0945:                            annosVisible.add(annos.get(i));
0946:                        }
0947:
0948:                    } else {
0949:
0950:                        // combination are enabled
0951:                        LinkedList annosDupl = (LinkedList) annos.clone();
0952:
0953:                        // List of all annotation types
0954:                        LinkedList combTypes = new LinkedList();
0955:
0956:                        // first, fill in the array with combination types sorted by the
0957:                        // order
0958:                        fillInCombinationsAndOrderThem(combTypes);
0959:
0960:                        for (int ct = 0; ct < combTypes.size(); ct++) {
0961:                            combineType((AnnotationType) combTypes.get(ct),
0962:                                    annosDupl);
0963:                        }
0964:
0965:                        annosVisible = new LinkedList();
0966:
0967:                        // add remaining not combined annotations into the line
0968:                        // annotations array
0969:                        for (i = 0; i < annosDupl.size(); i++) {
0970:                            if (annosDupl.get(i) != null
0971:                                    && ((AnnotationDesc) annosDupl.get(i))
0972:                                            .isVisible())
0973:                                annosVisible.add(annosDupl.get(i));
0974:                        }
0975:                    }
0976:
0977:                    // update the active annotation
0978:                    if (annosVisible.indexOf(active) == -1) {
0979:                        if (annosVisible.size() > 0)
0980:                            active = (AnnotationDesc) annosVisible.get(0);
0981:                        else
0982:                            active = null;
0983:                    }
0984:                }
0985:
0986:                /**
0987:                 * Is this given mark still referenced by some annotation or it can be
0988:                 * removed from the draw mark chain
0989:                 */
0990:                public boolean isMarkStillReferenced(Mark mark) {
0991:                    AnnotationDesc anno;
0992:                    for (Iterator it = annos.listIterator(); it.hasNext();) {
0993:                        anno = (AnnotationDesc) it.next();
0994:                        if (anno.getMark() == mark)
0995:                            return true;
0996:                    }
0997:                    return false;
0998:                }
0999:
1000:                public Iterator getAnnotations() {
1001:                    return annos.iterator();
1002:                }
1003:
1004:            }
1005:
1006:            /** Listener for listening on changes in Annotations object. */
1007:            public interface AnnotationsListener extends EventListener {
1008:
1009:                /**
1010:                 * This method is fired when annotations on the line are changed -
1011:                 * annotation was added, removed, changed, etc.
1012:                 */
1013:                public void changedLine(int Line);
1014:
1015:                /**
1016:                 * It is not possible to trace what have changed and so the listeners
1017:                 * are only informed that something has changed and that the change must
1018:                 * be reflected somehow (most probably by complete redraw).
1019:                 */
1020:                public void changedAll();
1021:
1022:            }
1023:
1024:            /**
1025:             * Annotation which is used for representation of combined annotations. Some
1026:             * basic operations like getLine etc. are delegated to one of the
1027:             * annotations which are representd by this combined annotation. The only
1028:             * added functionality is for tooltip text and annotation type.
1029:             */
1030:            private static class AnnotationCombination extends AnnotationDesc {
1031:
1032:                /** Delegate annotaiton */
1033:                private AnnotationDesc delegate;
1034:
1035:                /** Annotation type */
1036:                private String type;
1037:
1038:                /** List of annotations which are combined */
1039:                private LinkedList list;
1040:
1041:                public AnnotationCombination(String type,
1042:                        AnnotationDesc delegate) {
1043:                    super (delegate.getOffset(), delegate.getLength());
1044:                    this .delegate = delegate;
1045:                    this .type = type;
1046:                    updateAnnotationType();
1047:                    list = new LinkedList();
1048:                    list.add(delegate);
1049:                }
1050:
1051:                /** Getter for offset of this annotation */
1052:                public int getOffset() {
1053:                    return delegate.getOffset();
1054:                }
1055:
1056:                /** Getter for line number of this annotation */
1057:                public int getLine() {
1058:                    return delegate.getLine();
1059:                }
1060:
1061:                /** Getter for localized tooltip text for this annotation */
1062:                public String getShortDescription() {
1063:                    return getAnnotationTypeInstance().getDescription();
1064:                }
1065:
1066:                /** Getter for annotation type name */
1067:                public String getAnnotationType() {
1068:                    return type;
1069:                }
1070:
1071:                /** Add the annotation to this combination */
1072:                public void addCombinedAnnotation(AnnotationDesc anno) {
1073:                    list.add(anno);
1074:                }
1075:
1076:                /** Is the given annotation part of this combination */
1077:                public boolean isAnnotationCombined(AnnotationDesc anno) {
1078:                    if (list.indexOf(anno) == -1)
1079:                        return false;
1080:                    else
1081:                        return true;
1082:                }
1083:
1084:                /** Get Mark which represent this annotation in document */
1085:                Mark getMark() {
1086:                    return delegate.getMark();
1087:                }
1088:
1089:            }
1090:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.