001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.visualweb.designer.html;
043:
044: /**
045: * List of html tags the designer needs to be aware of.
046: * @todo Get rid of this class. This info should be derived from
047: * CSS: display: block, display: inline, display:none set up
048: * info about whether a tag is block, inline, or hidden.
049: * That only leaves "replaced", and for that we know exactly
050: * which elements are - image, object/applet, iframe, input,
051: * select, and text area.
052: * Implementation note: Don't change the strings in this table to
053: * something arbitrary: in particular, a lot of code will check the
054: * first character for something hardcoded, then do an equals comparison
055: * on HtmlTag.FOO.name so this will break if you change say
056: * HtmlTag.BODY="body" to HtmlTag.BODY="mybody".
057: *
058: * @todo Clean up - we shouldn't need to know about all these tags;
059: * for example, block vs inline should be determined via the css
060: * display property, and as another example, we shouldn't know anything
061: * about the "center" tag - the default style sheet will set up this
062: * tag with a "text-alignment: center" css property.
063: * @todo Remove the block/inline flag: it's now pulled from the CSS file instead!
064: * @author Tor Norbye
065: */
066: final public class HtmlTag {
067:
068: /**
069: * Creates a new <code>Tag</code> with the specified <code>id</code>;
070: * <code>causesBreak</code> and <code>isBlock</code> are defined
071: * by the user.
072: *
073: * @param name the name of the new tag, such as "table" or "blink"
074: * @param block <code>true</code> if the tag is used
075: * to add structure to a document
076: * @param hidden <code>true</code> if the tag should be hidden in
077: * the visual designer
078: * @param replaced <code>true</code> if the tag is a replaced
079: * element. See isReplaced() for a description of replaced elements.
080: * @todo Get rid of the inline parameter!
081: */
082: protected HtmlTag(String name, boolean block, boolean hidden,
083: boolean replaced) {
084: this .name = name;
085: this .block = block;
086: this .hidden = hidden;
087: this .replaced = replaced;
088: }
089:
090: /** Return the name of this element/tag */
091: public String getTagName() {
092: return name;
093: }
094:
095: /**
096: * Returns <code>true</code> if this tag is a block
097: * tag, which is a tag used to add structure to a
098: * document.
099: *
100: * @return <code>true</code> if this tag is a block
101: * tag, otherwise returns <code>false</code>
102: */
103: public boolean isBlockTag() {
104: return block;
105: }
106:
107: /**
108: * Returns <code>true</code> if this tag is an inline
109: * tag, which is a tag used to add content to lines.
110: *
111: * @return <code>true</code> if this tag is an inline
112: * tag, otherwise returns <code>false</code>
113: */
114: public boolean isInlineTag() {
115: return !block;
116: }
117:
118: /**
119: * Is this a tag which should be completely hidden?
120: * Returns <code>true</code> if this tag is a tag that should
121: * be hidden in the webform designer - such as the script tag.
122: * WARNING: Use this carefully! You cannot tell from a tag alone if it's hidden.
123: * HtmlTag.INPUT is hidden whenever @type != "hidden" for example.
124: */
125: public boolean isHiddenTag() {
126: return hidden;
127: }
128:
129: /**
130: * Returns <code>true</code> if this tag represents a replaced
131: * element. A replaced element is, according to
132: * http://www.w3.org/TR/REC-CSS2/conform.html, 'An element for which
133: * the CSS formatter knows only the intrinsic dimensions. In HTML,
134: * IMG, INPUT, TEXTAREA, SELECT, and OBJECT elements can be examples
135: * of replaced elements. For example, the content of the IMG element
136: * is often replaced by the image that the "src" attribute
137: * designates. CSS does not define how the intrinsic dimensions are
138: * found.'
139: */
140: public boolean isReplacedTag() {
141: // In CSS3, elements with display set to inline-block or inline-table
142: // will also be considered replaced. That may require some reworking
143: // of how this is set up.
144: return replaced;
145: }
146:
147: /**
148: * Return true iff this tag is a tag that participates in a form, such
149: * as <input>. Note that the <form> tag itself is not considered
150: * a form member tag.
151: * @return true iff this tag is a form member tag
152: */
153: public boolean isFormMemberTag() {
154: return this == INPUT || this == SELECT || this == TEXTAREA;
155: }
156:
157: /**
158: * Returns the string representation of the
159: * tag.
160: *
161: * @return the <code>String</code> representation of the tag
162: */
163: public String toString() {
164: return name;
165: }
166:
167: public final String name;
168: boolean block;
169: boolean hidden;
170: boolean replaced;
171:
172: // HTML 4.0 tags
173:
174: // TODO Complete this list by looking up official
175: // html4.0 & xhtml specs
176:
177: // Structure & header: <body>, <html>, <title>, <base>, <link>,
178: // <meta>, <script>, <style> -- none of these should be shown
179:
180: // Inline tags: <a>, <abbr>, <acronym>, <cite>, <code>, <dfn>,
181: // <em>, <kbd>, <samp>, <strong>, <var>, <b>, <big>, <i>, <small>,
182: // <sub>, <sup>, <tt>, <bdo>, <br>, <button>, <del>, <ins>, <img>,
183: // <input>, <label>, <map>, <noscript>, <object>, <q>, <ruby>,
184: // <select>, <script>, <span>, <textarea>, <iframe>!!!!,
185: // XXX is <script> inline or not???
186:
187: // This may clarify it, from
188: // http://www.mit.edu/~ddcc/xhtmlref/inline.html#noscript_elem:
189: // <noscript> is both an inline and a block-level element. But,
190: // however <noscript> is used, it may contain only block-level
191: // elements. This strange rule means that a <noscript> used inline
192: // will assuredly make no sense structurally: in order to use
193: // <noscript> inside a paragraph, for example, an author needs to
194: // wrap the contents of <noscript> inside another paragraph,
195: // creating a nonsensical nesting. Thus, the only sane way to use
196: // <noscript> is as a block-level element.
197:
198: // XXX Still missing some tags: legend, optgroup
199: // XXX Make usre I got the right values for the iframe tag
200:
201: // For style:
202: // Need em, strong, cite, dfn, code, samp, kbd, var, abbr, acronym
203: // font,basefont (deprecated)
204: // big, small, <tt>
205:
206: // name, block, hidden, replaced
207: public static final HtmlTag A = new HtmlTag("a", false, false,
208: false); // NOI18N
209: public static final HtmlTag ABBR = new HtmlTag("abbr", false,
210: false, false); // NOI18N
211: public static final HtmlTag ACRONYM = new HtmlTag("acronym", false,
212: false, false); // NOI18N
213: public static final HtmlTag ADDRESS = new HtmlTag("address", true,
214: false, false); // NOI18N
215: public static final HtmlTag APPLET = new HtmlTag("applet", false,
216: false, true); // NOI18N
217: public static final HtmlTag AREA = new HtmlTag("area", false, true,
218: false); // NOI18N
219: public static final HtmlTag B = new HtmlTag("b", false, false,
220: false); // NOI18N
221: public static final HtmlTag BASE = new HtmlTag("base", false,
222: false, false); // NOI18N
223: public static final HtmlTag BASEFONT = new HtmlTag("basefont",
224: false, false, false); // NOI18N
225: public static final HtmlTag BIG = new HtmlTag("big", false, false,
226: false); // NOI18N
227: // XXX what about <blink> ??? :-)
228: public static final HtmlTag BLOCKQUOTE = new HtmlTag("blockquote",
229: true, false, false); // NOI18N
230: public static final HtmlTag BODY = new HtmlTag("body", true, false,
231: false); // NOI18N
232: public static final HtmlTag BR = new HtmlTag("br", false, false,
233: false); // NOI18N
234: public static final HtmlTag BUTTON = new HtmlTag("button", false,
235: false, true); // NOI18N
236: public static final HtmlTag CAPTION =
237: // new HtmlTag("caption", false, false, false); // NOI18N
238: // I changed the caption to be block type since I want
239: // to format it on its own. This may be wrong. Revisit.
240: new HtmlTag("caption", true, false, false); // NOI18N
241: public static final HtmlTag CENTER = new HtmlTag("center", false,
242: false, false); // NOI18N
243: public static final HtmlTag CITE = new HtmlTag("cite", false,
244: false, false); // NOI18N
245: public static final HtmlTag CODE = new HtmlTag("code", false,
246: false, false); // NOI18N
247: public static final HtmlTag COL = new HtmlTag("col", false, false,
248: false); // NOI18N
249: public static final HtmlTag COLGROUP = new HtmlTag("colgroup",
250: false, false, false); // NOI18N
251: public static final HtmlTag DD = new HtmlTag("dd", true, false,
252: false); // NOI18N
253: public static final HtmlTag DEL =
254: // Note - DEL can be both block and inline!
255: new HtmlTag("del", true, false, false); // NOI18N
256: public static final HtmlTag DFN = new HtmlTag("dfn", false, false,
257: false); // NOI18N
258: public static final HtmlTag DIR = new HtmlTag("dir", true, false,
259: false); // NOI18N
260: public static final HtmlTag DIV = new HtmlTag("div", true, false,
261: false); // NOI18N
262: public static final HtmlTag DL = new HtmlTag("dl", true, false,
263: false); // NOI18N
264: public static final HtmlTag DT = new HtmlTag("dt", true, false,
265: false); // NOI18N
266: public static final HtmlTag EM = new HtmlTag("em", false, false,
267: false); // NOI18N
268: public static final HtmlTag FIELDSET =
269: // inline??? not sure
270: new HtmlTag("fieldset", true, false, false); // NOI18N
271: public static final HtmlTag FONT = new HtmlTag("font", false,
272: false, false); // NOI18N
273: public static final HtmlTag FORM = new HtmlTag("form", true, false,
274: false); // NOI18N
275: public static final HtmlTag FRAME =
276: // XXX is this replaced? IFRAME is!
277: new HtmlTag("frame", false, false, false); // NOI18N
278: public static final HtmlTag FRAMESET = new HtmlTag("frameset",
279: false, false, false); // NOI18N
280: public static final HtmlTag H1 = new HtmlTag("h1", true, false,
281: false); // NOI18N
282: public static final HtmlTag H2 = new HtmlTag("h2", true, false,
283: false); // NOI18N
284: public static final HtmlTag H3 = new HtmlTag("h3", true, false,
285: false); // NOI18N
286: public static final HtmlTag H4 = new HtmlTag("h4", true, false,
287: false); // NOI18N
288: public static final HtmlTag H5 = new HtmlTag("h5", true, false,
289: false); // NOI18N
290: public static final HtmlTag H6 = new HtmlTag("h6", true, false,
291: false); // NOI18N
292: public static final HtmlTag HEAD = new HtmlTag("head", false, true,
293: false); // NOI18N
294: public static final HtmlTag HR = new HtmlTag("hr", true, false,
295: false); // NOI18N
296: public static final HtmlTag HTML = new HtmlTag("html", false, true,
297: false); // NOI18N
298: public static final HtmlTag I = new HtmlTag("i", false, false,
299: false); // NOI18N
300: // Double check what the right display disposition is for iframes!
301: public static final HtmlTag IFRAME = new HtmlTag("iframe", true,
302: false, true); // NOI18N
303: public static final HtmlTag IMG = new HtmlTag("img", false, false,
304: true); // NOI18N
305: public static final HtmlTag INPUT = new HtmlTag("input", false,
306: false, true); // NOI18N
307: public static final HtmlTag INS =
308: // Note - INS can be both block and inline!
309: new HtmlTag("ins", true, false, false); // NOI18N
310: public static final HtmlTag ISINDEX =
311: // Deprecated - use INPUT instead
312: new HtmlTag("isindex", false, false, false); // NOI18N
313:
314: // FAKE TAG!
315: // Here so we don't display these
316: public static final HtmlTag JSPDECLARATION = new HtmlTag(
317: "jsp:declaration", false, true, false); // NOI18N
318: public static final HtmlTag JSPEXPRESSION = new HtmlTag(
319: "jsp:expression", false, true, false); // NOI18N
320: public static final HtmlTag JSPINCLUDE = new HtmlTag(
321: "jsp:directive.include", true, false, false); // NOI18N
322: // XXX #94248 Weblogic problem, supporting also this version of fragments.
323: public static final HtmlTag JSPINCLUDEX = new HtmlTag(
324: "jsp:include", true, false, false); // NOI18N
325: public static final HtmlTag JSPSCRIPTLET = new HtmlTag(
326: "jsp:scriptlet", false, true, false); // NOI18N
327: public static final HtmlTag FSUBVIEW = new HtmlTag("f:subview",
328: true, false, false); // NOI18N
329:
330: public static final HtmlTag KBD = new HtmlTag("kbd", false, false,
331: false); // NOI18N
332: public static final HtmlTag LABEL = new HtmlTag("label", false,
333: false, false); // NOI18N
334: public static final HtmlTag LI = new HtmlTag("li", true, false,
335: false); // NOI18N
336: public static final HtmlTag LINK = new HtmlTag("link", false, true,
337: false); // NOI18N
338: public static final HtmlTag MAP = new HtmlTag("map", false, true,
339: false); // NOI18N
340: public static final HtmlTag MENU = new HtmlTag("menu", true, false,
341: false); // NOI18N
342: public static final HtmlTag META = new HtmlTag("meta", false, true,
343: false); // NOI18N
344: public static final HtmlTag NOBR = new HtmlTag("nobr", false,
345: false, false); // NOI18N
346: public static final HtmlTag NOFRAMES = new HtmlTag("noframes",
347: true, true, false); // NOI18N
348: public static final HtmlTag NOSCRIPT = new HtmlTag("noscript",
349: true, true, false); // NOI18N
350: public static final HtmlTag OBJECT = new HtmlTag("object", false,
351: false, true); // NOI18N
352: public static final HtmlTag OL = new HtmlTag("ol", true, false,
353: false); // NOI18N
354: public static final HtmlTag OPTION = new HtmlTag("option", false,
355: false, false); // NOI18N
356: public static final HtmlTag P = new HtmlTag("p", true, false, false); // NOI18N
357: public static final HtmlTag PARAM = new HtmlTag("param", false,
358: true, false); // NOI18N
359: public static final HtmlTag PRE = new HtmlTag("pre", true, false,
360: false); // NOI18N
361: public static final HtmlTag Q = new HtmlTag("q", false, false,
362: false); // NOI18N
363: public static final HtmlTag S = new HtmlTag("s", false, false,
364: false); // NOI18N
365: public static final HtmlTag SAMP = new HtmlTag("samp", false,
366: false, false); // NOI18N
367: public static final HtmlTag SCRIPT = new HtmlTag("script", true,
368: true, false); // NOI18N
369: public static final HtmlTag SELECT = new HtmlTag("select", false,
370: false, true); // NOI18N
371: public static final HtmlTag SMALL = new HtmlTag("small", false,
372: false, false); // NOI18N
373: public static final HtmlTag SPAN = new HtmlTag("span", false,
374: false, false); // NOI18N
375: public static final HtmlTag STRIKE = new HtmlTag("strike", false,
376: false, false); // NOI18N
377: public static final HtmlTag STRONG = new HtmlTag("strong", false,
378: false, false); // NOI18N
379: public static final HtmlTag STYLE = new HtmlTag("style", false,
380: true, false); // NOI18N
381: public static final HtmlTag SUB = new HtmlTag("sub", false, false,
382: false); // NOI18N
383: public static final HtmlTag SUP = new HtmlTag("sup", false, false,
384: false); // NOI18N
385: public static final HtmlTag TABLE = new HtmlTag("table", true,
386: false, false); // NOI18N
387: public static final HtmlTag TBODY = new HtmlTag("tbody", false,
388: false, false); // NOI18N
389: public static final HtmlTag TD = new HtmlTag("td", true, false,
390: false); // NOI18N
391: public static final HtmlTag TEXTAREA = new HtmlTag("textarea",
392: false, false, true); // NOI18N
393: public static final HtmlTag TFOOT = new HtmlTag("tfoot", false,
394: false, false); // NOI18N
395: public static final HtmlTag TH = new HtmlTag("th", true, false,
396: false); // NOI18N
397: public static final HtmlTag THEAD = new HtmlTag("thead", false,
398: false, false); // NOI18N
399: public static final HtmlTag TITLE = new HtmlTag("title", false,
400: true, false); // NOI18N
401: public static final HtmlTag TR = new HtmlTag("tr", true, false,
402: false); // NOI18N
403: public static final HtmlTag TT = new HtmlTag("tt", false, false,
404: false); // NOI18N
405: public static final HtmlTag U = new HtmlTag("u", false, false,
406: false); // NOI18N
407: public static final HtmlTag UL = new HtmlTag("ul", true, false,
408: false); // NOI18N
409: public static final HtmlTag VAR = new HtmlTag("var", false, false,
410: false); // NOI18N
411:
412: // What about these - should they be blocktags?:
413: // Table Content Elements: <caption>, <col>,
414: // <colgroup>, <thead>, <tbody>, <tfoot>, <td>, <th>, <tr>
415: // Form Fieldset Legends and Menu Options
416: // <legend>, <optgroup>, <option>
417: // Map Areas: <area>
418: // Object Parameters: <param>
419: // Ruby Annotations (?): <rb>, <rbc>, <rp>, <rt>, <rtc>
420:
421: private static HtmlTag[] tags = { A, ABBR, ACRONYM, ADDRESS,
422: APPLET, AREA, B, BASE, BASEFONT, BIG, BLOCKQUOTE, BODY, BR,
423: BUTTON, CAPTION, CENTER, CITE, CODE, COL, COLGROUP, DD,
424: DEL, DFN, DIR, DIV, DL, DT, EM, FSUBVIEW, FIELDSET, FONT,
425: FORM, FRAME, FRAMESET, H1, H2, H3, H4, H5, H6, HEAD, HR,
426: HTML, I, IFRAME, IMG, INPUT, INS, ISINDEX, JSPDECLARATION,
427: JSPINCLUDE, JSPINCLUDEX, JSPEXPRESSION, JSPSCRIPTLET, KBD,
428: LABEL, LI, LINK, MAP, MENU, META, NOBR, NOFRAMES, NOSCRIPT,
429: OBJECT, OL, OPTION, P, PARAM, PRE, Q, S, SAMP, SCRIPT,
430: SELECT, SMALL, SPAN, STRIKE, STRONG, STYLE, SUB, SUP,
431: TABLE, TBODY, TD, TEXTAREA, TFOOT, TH, THEAD, TITLE, TR,
432: TT, U, UL, VAR, null };
433:
434: // static void ensureAlphabetical() {
435: // if (!Trace.ON) {
436: // return;
437: // }
438: // // Binsearch depends on the list being in alphabetical order....
439: // // Make sure getTag can find all tags
440: // for (int i = 0; tags[i] != null; i++) {
441: // HtmlTag tag = getTag(tags[i].name);
442: // if (tag == null) {
443: // System.err.println("Can't find tag " + tags[i]);
444: // System.exit(0); // Only in debug builds! (Trace.ON)
445: // }
446: // }
447: // }
448:
449: /** Return the set of known tags */
450: public static HtmlTag[] getTags() {
451: return tags;
452: }
453:
454: /** Locate a tag by name
455: * @param name The tag name to search for
456: * @return the tag for that name, or null if the name is not a valid
457: * html tag name.
458: */
459: public static HtmlTag getTag(String name) {
460: // Do a binary search
461: int low = 0;
462: int high = tags.length - 1;
463: // boolean ignoreCase = Character.isUpperCase(name.charAt(0));
464: while (high > low) {
465: int middle = (low + high) / 2;
466: // I can optimize this further by comparing on a per character
467: // basis, increasingly more matching characters.
468: int result = name.compareTo(tags[middle].name);
469: // int result;
470: // if (ignoreCase) {
471: // result = name.compareToIgnoreCase(tags[middle].name);
472: // } else {
473: // result = name.compareTo(tags[middle].name);
474: // }
475: if (result == 0) {
476: return tags[middle];
477: } else if (result < 0) {
478: high = middle;
479: } else if (low != middle) {
480: low = middle;
481: } else {
482: break;
483: }
484: }
485: return null;
486: }
487:
488: public static boolean isTableChild(String tag) {
489: char c = tag.charAt(0);
490: if (c == 't' || c == 'c') { // xxx what about rowgroups?
491: return tag.equals(HtmlTag.TD.name)
492: || tag.equals(HtmlTag.TH.name)
493: || tag.equals(HtmlTag.TBODY.name)
494: || tag.equals(HtmlTag.THEAD.name)
495: || tag.equals(HtmlTag.TFOOT.name)
496: || tag.equals(HtmlTag.CAPTION.name)
497: || tag.equals(HtmlTag.COLGROUP.name)
498: || tag.equals(HtmlTag.COL.name);
499: }
500: return false;
501: }
502:
503: /*
504: static {
505: if (Trace.ON) {
506: HtmlTag.ensureAlphabetical();
507: }
508: }
509: */
510:
511: }
|