KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > spi > editor > highlighting > ZOrder


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.spi.editor.highlighting;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.Arrays JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.logging.Logger JavaDoc;
30 import org.openide.util.TopologicalSortException;
31 import org.openide.util.Utilities;
32
33 /**
34  * This class determines a position of a <code>HighlightsLayer</code> in relation
35  * to other layers. Instances of this class are immutable.
36  *
37  * <p>For the purpose of vertical ordering each <code>HighlightsLayer</code> is
38  * identified by its <i>layer type id</i>. When creating a new
39  * <code>ZOrder</code> you simply specify that the new <code>ZOrder</code> lies
40  * above and/or below certain layers using their IDs.
41  *
42  * <p>Developers are encouraged to use the predefined z-order constants in this
43  * class. Each constant refers to a rack in vertical ordering with a specific
44  * purpose. The racks are ordered in the following way:
45  *
46  * <ul>
47  * <li>TOP_RACK - the highest rack
48  * <li>SHOW_OFF_RACK
49  * <li>DEFAULT_RACK
50  * <li>CARET_RACK
51  * <li>SYNTAX_RACK
52  * <li>BOTTOM_RACK - the lowest rack
53  * </ul>
54  *
55  * <div class="nonnormative">
56  * <p>When positioning your layer you should choose the rack that suites the purpose
57  * of your layer. It is possible to further define more precise ordering
58  * between layers within a rack. For example, if you have two layers - one providing
59  * syntactical highlighting and the other one providing semantical highlighting -
60  * they both belong to the <code>SYNTAX_RACK</code>, but the semantical layer should be placed
61  * above the syntactical one, because it provides 'more accurate' highlights. You could
62  * define <code>ZOrder</code> of your layers like this:
63  *
64  * <pre>
65  * ZOrder syntaxLayerZOrder = ZOrder.SYNTAX;
66  * ZOrder semanticLayerZOrder = ZOrder.SYNTAX.aboveLayers("your-syntax-layer-id");
67  * </pre>
68  * </div>
69  *
70  * @author Vita Stejskal
71  */

72 public final class ZOrder {
73
74     private static final Logger JavaDoc LOG = Logger.getLogger(ZOrder.class.getName());
75
76     private static final Collection JavaDoc<String JavaDoc> EMPTY = new HashSet JavaDoc<String JavaDoc>();
77     
78     private static final String JavaDoc TOP_RACK_MARKER = "org-netbeans-spi-editor-highlighting-ZOrder-TOP-RACK"; //NOI18N
79
private static final String JavaDoc SHOW_OFF_RACK_MARKER = "org-netbeans-spi-editor-highlighting-ZOrder-SHOW-OFF-RACK"; //NOI18N
80
private static final String JavaDoc DEFAULT_RACK_MARKER = "org-netbeans-spi-editor-highlighting-ZOrder-DEFAULT-RACK"; //NOI18N
81
private static final String JavaDoc CARET_RACK_MARKER = "org-netbeans-spi-editor-highlighting-ZOrder-CARET-RACK"; //NOI18N
82
private static final String JavaDoc SYNTAX_RACK_MARKER = "org-netbeans-spi-editor-highlighting-ZOrder-SYNTAX-RACK"; //NOI18N
83

84     /**
85      * The highest rack of z-orders. Layers in this rack will be placed at
86      * the top of the hierarchy.
87      */

88     public static final ZOrder TOP_RACK = ZOrder.above(TOP_RACK_MARKER);
89
90     /**
91      * The show off rack of z-orders. This rack is meant to be used by
92      * layers with short-lived highlights that can temporarily override highlights
93      * provided by other layers (eg. syntax coloring).
94      */

95     public static final ZOrder SHOW_OFF_RACK = new ZOrder(
96         Collections.singleton(TOP_RACK_MARKER), Collections.singleton(SHOW_OFF_RACK_MARKER));
97     
98     /**
99      * The default rack of z-orders. This rack should be used by most of the layers.
100      */

101     public static final ZOrder DEFAULT_RACK = new ZOrder(
102         Collections.singleton(SHOW_OFF_RACK_MARKER), Collections.singleton(DEFAULT_RACK_MARKER));
103     
104     public static final ZOrder CARET_RACK = new ZOrder(
105         Collections.singleton(DEFAULT_RACK_MARKER), Collections.singleton(CARET_RACK_MARKER));
106     
107     /**
108      * The syntax highlighting rack of z-order. This rack is meant to be used by
109      * layers that provide highlighting of a text according to its syntactical or
110      * semantical rules.
111      */

112     public static final ZOrder SYNTAX_RACK = new ZOrder(
113         Collections.singleton(CARET_RACK_MARKER), Collections.singleton(SYNTAX_RACK_MARKER));
114     
115     /**
116      * The lowest rack of z-orders. Layers in this rack will be placed at the
117      * bottom of the hierarchy.
118      */

119     public static final ZOrder BOTTOM_RACK = ZOrder.below(SYNTAX_RACK_MARKER);
120     
121     /**
122      * Creates a z-order that determines a position above the layers passed in.
123      *
124      * @param layerIds The IDs of layers which lay below the position that
125      * will be refered to by a z-order created by this
126      * method.
127      *
128      * @return The new z-order.
129      */

130     public static ZOrder above(String JavaDoc... layerIds) {
131         return new ZOrder(null, Arrays.asList(layerIds));
132     }
133     
134     /**
135      * Creates a z-order that determines a position below the layers passed in.
136      *
137      * @param layerIds The IDs of layers which lay above the position that
138      * will be refered to by a z-order created by this
139      * method.
140      *
141      * @return The new z-order.
142      */

143     public static ZOrder below(String JavaDoc... layerIds) {
144         return new ZOrder(Arrays.asList(layerIds), null);
145     }
146
147     /**
148      * Sorts an array of <code>HighlightLayer</code>s by their z-order. This is
149      * a convenience method that delegates to the <code>sort(Collection)</code>
150      * method.
151      *
152      * @param layers The array to sort.
153      *
154      * @return The sorted array where layers are sorted by their z-order starting
155      * with the lowest z-order and going to the highest one.
156      * @throws TopologicalSortException If the array contains cycles.
157      */

158     /* package */ static HighlightsLayer[] sort(HighlightsLayer[] layers) throws TopologicalSortException {
159         List JavaDoc<? extends HighlightsLayer> list = sort(Arrays.asList(layers));
160         return list.toArray(new HighlightsLayer [list.size()]);
161     }
162     
163     /**
164      * Sorts a collection of <code>HighlightLayer</code>s by their z-order. The layers
165      * with <code>ZOrder.BOTTOM</code> will preceed all other layers in the resulting
166      * list. Similarily the layers with <code>ZOrder.TOP</code> will be placed at the
167      * end of the list. All the other layers will appear in between sorted by their
168      * z-order.
169      *
170      * @param layers The array to sort.
171      *
172      * @return The sorted array where layers are sorted by their z-order starting
173      * with the lowest z-order and going to the highest one.
174      * @throws TopologicalSortException If the collection contains cycles.
175      */

176     /* package */ static List JavaDoc<? extends HighlightsLayer> sort(Collection JavaDoc<? extends HighlightsLayer> layers) throws TopologicalSortException {
177         HashMap JavaDoc<String JavaDoc, HighlightsLayer> id2layer = new HashMap JavaDoc<String JavaDoc, HighlightsLayer>();
178         HashSet JavaDoc<String JavaDoc> vertices = new HashSet JavaDoc<String JavaDoc>();
179         HashMap JavaDoc<String JavaDoc, List JavaDoc<String JavaDoc>> edges = new HashMap JavaDoc<String JavaDoc, List JavaDoc<String JavaDoc>>();
180         
181         vertices.add(TOP_RACK_MARKER);
182         vertices.add(SHOW_OFF_RACK_MARKER);
183         vertices.add(DEFAULT_RACK_MARKER);
184         vertices.add(CARET_RACK_MARKER);
185         vertices.add(SYNTAX_RACK_MARKER);
186
187         edges.put(SYNTAX_RACK_MARKER, new ArrayList JavaDoc<String JavaDoc>(Collections.singleton(CARET_RACK_MARKER)));
188         edges.put(CARET_RACK_MARKER, new ArrayList JavaDoc<String JavaDoc>(Collections.singleton(DEFAULT_RACK_MARKER)));
189         edges.put(DEFAULT_RACK_MARKER, new ArrayList JavaDoc<String JavaDoc>(Collections.singleton(SHOW_OFF_RACK_MARKER)));
190         edges.put(SHOW_OFF_RACK_MARKER, new ArrayList JavaDoc<String JavaDoc>(Collections.singleton(TOP_RACK_MARKER)));
191         
192         for (HighlightsLayer layer : layers) {
193             id2layer.put(layer.getLayerTypeId(), layer);
194
195             // process the layers below the current layer
196
for (String JavaDoc belowLayerId : layer.getZOrder().layersBelow) {
197                 vertices.add(belowLayerId);
198                 List JavaDoc<String JavaDoc> verticeEdges = edges.get(belowLayerId);
199                 if (verticeEdges == null) {
200                     verticeEdges = new ArrayList JavaDoc<String JavaDoc>();
201                     edges.put(belowLayerId, verticeEdges);
202                 }
203                 verticeEdges.add(layer.getLayerTypeId());
204                 LOG.finest(belowLayerId + " < " + layer.getLayerTypeId());
205             }
206
207             // process the layers above the current layer
208
vertices.add(layer.getLayerTypeId());
209             List JavaDoc<String JavaDoc> verticeEdges = edges.get(layer.getLayerTypeId());
210             if (verticeEdges == null) {
211                 verticeEdges = new ArrayList JavaDoc<String JavaDoc>();
212                 edges.put(layer.getLayerTypeId(), verticeEdges);
213             }
214             for (String JavaDoc aboveLayerId : layer.getZOrder().layersAbove) {
215                 verticeEdges.add(aboveLayerId);
216                 LOG.finest(layer.getLayerTypeId() + " < " + aboveLayerId);
217             }
218         }
219         
220         // Sort ordinary layers by their z-order
221
List JavaDoc<String JavaDoc> sortedLayerIds = Utilities.topologicalSort(vertices, edges);
222         List JavaDoc<HighlightsLayer> sortedLayers = new ArrayList JavaDoc<HighlightsLayer>();
223         
224         // Add all ordinary layers sorted by their z-order
225
LOG.finest("Sorted layer Ids: ");
226         for (String JavaDoc layerId : sortedLayerIds) {
227             LOG.finest(" " + layerId);
228             HighlightsLayer layer = id2layer.get(layerId);
229             if (layer != null) {
230                 sortedLayers.add(layer);
231             }
232         }
233         LOG.finest("End of Sorted layer Ids: -----------------------");
234         
235         return sortedLayers;
236     }
237     
238     /* package */ final Collection JavaDoc<String JavaDoc> layersAbove;
239     /* package */ final Collection JavaDoc<String JavaDoc> layersBelow;
240     
241     /** Creates a new instance of ZOrder */
242     private ZOrder(Collection JavaDoc<String JavaDoc> aboveLayers, Collection JavaDoc<String JavaDoc> belowLayers) {
243         this.layersAbove = aboveLayers == null ? EMPTY : aboveLayers;
244         this.layersBelow = belowLayers == null ? EMPTY : belowLayers;
245     }
246
247     /**
248      * Creates a copy of this ZOrder and modifies its position to lay above the
249      * layers passed in.
250      *
251      * @param layerIds The IDs of layers which lay below the position that
252      * will be refered to by a z-order created by this
253      * method.
254      *
255      * @return The new z-order.
256      */

257     public ZOrder aboveLayers(String JavaDoc... layerIds) {
258         HashSet JavaDoc<String JavaDoc> newLayersAbove = new HashSet JavaDoc<String JavaDoc>(layersAbove);
259         HashSet JavaDoc<String JavaDoc> newLayersBelow = new HashSet JavaDoc<String JavaDoc>(layersBelow.size() + layerIds.length);
260         newLayersBelow.addAll(layersBelow);
261         newLayersBelow.addAll(Arrays.asList(layerIds));
262         return new ZOrder(newLayersAbove, newLayersBelow);
263     }
264     
265     /**
266      * Creates a copy of this ZOrder and modifies its position to lay below the
267      * layers passed in.
268      *
269      * @param layerIds The IDs of layers which lay above the position that
270      * will be refered to by a z-order created by this
271      * method.
272      *
273      * @return The new z-order.
274      */

275     public ZOrder belowLayers(String JavaDoc... layerIds) {
276         HashSet JavaDoc<String JavaDoc> newLayersBelow = new HashSet JavaDoc<String JavaDoc>(layersBelow);
277         HashSet JavaDoc<String JavaDoc> newLayersAbove = new HashSet JavaDoc<String JavaDoc>(layersAbove.size() + layerIds.length);
278         newLayersAbove.addAll(layersAbove);
279         newLayersAbove.addAll(Arrays.asList(layerIds));
280         return new ZOrder(newLayersAbove, newLayersBelow);
281     }
282 }
283
Popular Tags