|
Lines 45-100
Link Here
|
| 45 |
public static final String CLASS_PREFIX = "w4tCss"; |
45 |
public static final String CLASS_PREFIX = "w4tCss"; |
| 46 |
|
46 |
|
| 47 |
|
47 |
|
| 48 |
private List head = new ArrayList(); |
48 |
private List body = new ArrayList(); |
| 49 |
private List body = new ArrayList(); |
|
|
| 50 |
private List layers = new ArrayList(); |
| 51 |
private List foot = new ArrayList(); |
| 52 |
|
49 |
|
| 53 |
private String elementStarted; |
50 |
private String elementStarted; |
| 54 |
private boolean closed; |
51 |
private boolean closed; |
| 55 |
private boolean avoidEscape; |
52 |
private boolean avoidEscape; |
| 56 |
|
53 |
|
| 57 |
|
54 |
|
| 58 |
/** contains css classes that have been collected from style settings on |
|
|
| 59 |
* components. Every style content (keys) gets assigned a generated |
| 60 |
* class name (elements). |
| 61 |
* |
| 62 |
* It is assured that for every content there is exactly one class name, |
| 63 |
* and the latter is used when the style declaration |
| 64 |
*/ |
| 65 |
private Hashtable registeredCssClasses = new Hashtable(); |
| 66 |
/** contains css classes that have been set and named programmatically, |
| 67 |
* that is which have been set with class name and content (keys). |
| 68 |
* The elements are ArrayLists with all the class names assigned to |
| 69 |
* the content that is the key. |
| 70 |
* |
| 71 |
* This means that, as opposed to managedCssClasses, there can be more than |
| 72 |
* one class name for the same content. In this case a content gets a name |
| 73 |
* of the form ".someName, .someOtherName" |
| 74 |
*/ |
| 75 |
private Hashtable namedCssClasses = new Hashtable(); |
| 76 |
/** contains the names of the javascript libraries that are needed for |
55 |
/** contains the names of the javascript libraries that are needed for |
| 77 |
* the content which was rendered into this HtmlResponseWriter. */ |
56 |
* the content which was rendered into this HtmlResponseWriter. */ |
| 78 |
private List jsLibraries = new ArrayList(); |
57 |
private List jsLibraries = new ArrayList(); |
| 79 |
|
58 |
|
| 80 |
|
59 |
|
| 81 |
/** |
|
|
| 82 |
* <p>Append a token to the token list of the header's token</p> |
| 83 |
* <p>This method is not inteded to be used by clients.</p> |
| 84 |
*/ |
| 85 |
public void appendHead( final StringBuffer token ) { |
| 86 |
head.add( token.toString() ); |
| 87 |
} |
| 88 |
|
| 89 |
/** |
| 90 |
* <p>Append the given <code>token</code> to the token list of the header's |
| 91 |
* token</p> |
| 92 |
* <p>This method is not inteded to be used by clients.</p> |
| 93 |
*/ |
| 94 |
public void appendHead( final String token ) { |
| 95 |
head.add( token ); |
| 96 |
} |
| 97 |
|
| 98 |
/** |
60 |
/** |
| 99 |
* <p>Append a token to the token list of the body's token</p> |
61 |
* <p>Append a token to the token list of the body's token</p> |
| 100 |
* <p>This method is not inteded to be used by clients.</p> |
62 |
* <p>This method is not inteded to be used by clients.</p> |
|
Lines 114-171
Link Here
|
| 114 |
} |
76 |
} |
| 115 |
} |
77 |
} |
| 116 |
|
78 |
|
| 117 |
/** |
|
|
| 118 |
* <p>Append a token to the list of footer tokens</p> |
| 119 |
* <p>This method is not inteded to be used by clients.</p> |
| 120 |
*/ |
| 121 |
public void appendFoot( final StringBuffer token ) { |
| 122 |
foot.add( token.toString() ); |
| 123 |
} |
| 124 |
|
| 125 |
/** |
| 126 |
* <p>Append the given <code>token</code> to the list of footer tokens.</p> |
| 127 |
* <p>This method is not inteded to be used by clients.</p> |
| 128 |
*/ |
| 129 |
public void appendFoot( final String token ) { |
| 130 |
foot.add( token ); |
| 131 |
} |
| 132 |
|
| 133 |
/** |
| 134 |
* <p>Append a token to the list of layer tokens</p> |
| 135 |
* <p>This method is not inteded to be used by clients.</p> |
| 136 |
*/ |
| 137 |
public void appendLayer( final StringBuffer token ) { |
| 138 |
appendLayer( token.toString() ); |
| 139 |
} |
| 140 |
|
| 141 |
/** |
| 142 |
* <p>Append a token to the list of layer tokens</p> |
| 143 |
* <p>This method is not inteded to be used by clients.</p> |
| 144 |
*/ |
| 145 |
public void appendLayer( final String token ) { |
| 146 |
layers.add( token ); |
| 147 |
} |
| 148 |
|
| 149 |
/** <p>Concatenates this HtmlResponseWriter's layers to its body token list. |
| 150 |
* </p> |
| 151 |
* <p>This method is not inteded to be used by clients.</p> |
| 152 |
*/ |
| 153 |
public void concatLayers() { |
| 154 |
for( int i = 0; i < layers.size(); i++ ) { |
| 155 |
append( layers.get( i ).toString() ); |
| 156 |
} |
| 157 |
layers.clear(); |
| 158 |
} |
| 159 |
|
| 160 |
/** |
| 161 |
* <p>Removes all of the tokens from the head list. The head list will be |
| 162 |
* empty after this call returns.</p> |
| 163 |
* <p>This method is not inteded to be used by clients.</p> |
| 164 |
*/ |
| 165 |
public void clearHead() { |
| 166 |
head.clear(); |
| 167 |
} |
| 168 |
|
| 169 |
/** |
79 |
/** |
| 170 |
* <p>Removes all of the tokens from the body list. The body list will be |
80 |
* <p>Removes all of the tokens from the body list. The body list will be |
| 171 |
* empty after this call returns</p> |
81 |
* empty after this call returns</p> |
|
Lines 175-197
Link Here
|
| 175 |
body.clear(); |
85 |
body.clear(); |
| 176 |
} |
86 |
} |
| 177 |
|
87 |
|
| 178 |
/** |
|
|
| 179 |
* </p>Removes all of the tokens from the foot list. The foot list will be |
| 180 |
* empty after this call returns.</p> |
| 181 |
* <p>This method is not inteded to be used by clients.</p> |
| 182 |
*/ |
| 183 |
public void clearFoot() { |
| 184 |
foot.clear(); |
| 185 |
} |
| 186 |
|
| 187 |
/** |
| 188 |
* <p>Returns the number of tokens in the head list.</p> |
| 189 |
* <p>This method is not inteded to be used by clients.</p> |
| 190 |
*/ |
| 191 |
public int getHeadSize() { |
| 192 |
return head.size(); |
| 193 |
} |
| 194 |
|
| 195 |
/** |
88 |
/** |
| 196 |
* <p>Returns the number of tokens in the body list.</p> |
89 |
* <p>Returns the number of tokens in the body list.</p> |
| 197 |
* <p>This method is not inteded to be used by clients.</p> |
90 |
* <p>This method is not inteded to be used by clients.</p> |
|
Lines 200-221
Link Here
|
| 200 |
return body.size(); |
93 |
return body.size(); |
| 201 |
} |
94 |
} |
| 202 |
|
95 |
|
| 203 |
/** |
|
|
| 204 |
* <p>Returns the number of tokens in the foot list.</p> |
| 205 |
* <p>This method is not inteded to be used by clients.</p> |
| 206 |
*/ |
| 207 |
public int getFootSize() { |
| 208 |
return foot.size(); |
| 209 |
} |
| 210 |
|
| 211 |
/** |
| 212 |
* <p>Returns the token at the specified position in the head list.</p> |
| 213 |
* <p>This method is not inteded to be used by clients.</p> |
| 214 |
*/ |
| 215 |
public String getHeadToken( final int index ) { |
| 216 |
return head.get( index ).toString(); |
| 217 |
} |
| 218 |
|
| 219 |
/** |
96 |
/** |
| 220 |
* <p>Returns the token at the specified position in the body list.</p> |
97 |
* <p>Returns the token at the specified position in the body list.</p> |
| 221 |
* <p>This method is not inteded to be used by clients.</p> |
98 |
* <p>This method is not inteded to be used by clients.</p> |
|
Lines 232-268
Link Here
|
| 232 |
return body.iterator(); |
109 |
return body.iterator(); |
| 233 |
} |
110 |
} |
| 234 |
|
111 |
|
| 235 |
/** |
|
|
| 236 |
* <p>Returns the token at the specified position in the foot list.</p> |
| 237 |
* <p>This method is not inteded to be used by clients.</p> |
| 238 |
*/ |
| 239 |
public String getFootToken( final int index ) { |
| 240 |
return foot.get( index ).toString(); |
| 241 |
} |
| 242 |
|
| 243 |
/** |
| 244 |
* <p>Equalizes the head, body and foot list of this HtmlResponseWriter with |
| 245 |
* the lists of the parameter HtmlResponseWriter.</p> |
| 246 |
* <p>This method is not inteded to be used by clients.</p> |
| 247 |
*/ |
| 248 |
public void equalize( final HtmlResponseWriter tokenBuffer ) { |
| 249 |
this.foot.clear(); |
| 250 |
this.body.clear(); |
| 251 |
this.layers.clear(); |
| 252 |
this.head.clear(); |
| 253 |
this.jsLibraries.clear(); |
| 254 |
this.foot = tokenBuffer.foot; |
| 255 |
this.body = tokenBuffer.body; |
| 256 |
this.layers = tokenBuffer.layers; |
| 257 |
this.head = tokenBuffer.head; |
| 258 |
this.jsLibraries = tokenBuffer.jsLibraries; |
| 259 |
this.registeredCssClasses = tokenBuffer.registeredCssClasses; |
| 260 |
this.namedCssClasses = tokenBuffer.namedCssClasses; |
| 261 |
} |
| 262 |
|
| 263 |
|
| 264 |
// control methods for javascript library rendering |
| 265 |
/////////////////////////////////////////////////// |
112 |
/////////////////////////////////////////////////// |
|
|
113 |
// control methods for javascript library rendering |
| 266 |
|
114 |
|
| 267 |
/** <p>Returns the names of the JavaScript libraries that the components |
115 |
/** <p>Returns the names of the JavaScript libraries that the components |
| 268 |
* which were rendered into this HtmlResponseWriter need.</p> */ |
116 |
* which were rendered into this HtmlResponseWriter need.</p> */ |
|
Lines 316-421
Link Here
|
| 316 |
} |
164 |
} |
| 317 |
|
165 |
|
| 318 |
|
166 |
|
| 319 |
/** <p>Returns a unique identifier for a css class that is contained in this |
|
|
| 320 |
* HtmlResponseWriter's cache and contains exactly the settings in the passed |
| 321 |
* <code>style</code>.</p> |
| 322 |
* |
| 323 |
* <p>If no entry for the passed content is contained yet, a name will be |
| 324 |
* generated.</p> |
| 325 |
* |
| 326 |
* <p>Any renderer that calls this method can be sure that the css class |
| 327 |
* named by the return value of this method is available in the HTML |
| 328 |
* document (the corresponding style tag will be rendered into the head |
| 329 |
* section of the HTML document).</p> |
| 330 |
*/ |
| 331 |
public String registerCssClass( final String style ) { |
| 332 |
String result = ""; |
| 333 |
if( registeredCssClasses.containsKey( style ) ) { |
| 334 |
result = ( String )registeredCssClasses.get( style ); |
| 335 |
} else { |
| 336 |
result = createClassName( style ); |
| 337 |
registeredCssClasses.put( style, result ); |
| 338 |
} |
| 339 |
return result; |
| 340 |
} |
| 341 |
|
| 342 |
/** <p>Adds the passed css class to the classes that are declared on top |
| 343 |
* of the page.</p> */ |
| 344 |
public void addNamedCssClass( final CssClass cssClass ) { |
| 345 |
Assert.isNotNull( cssClass ); |
| 346 |
|
| 347 |
String content = cssClass.getContent(); |
| 348 |
List allNames; |
| 349 |
if( namedCssClasses.containsKey( content ) ) { |
| 350 |
allNames = ( List )namedCssClasses.get( content ); |
| 351 |
} else { |
| 352 |
allNames = new ArrayList(); |
| 353 |
namedCssClasses.put( content, allNames ); |
| 354 |
} |
| 355 |
if( !allNames.contains( cssClass.getClassName() ) ) { |
| 356 |
allNames.add( cssClass.getClassName() ); |
| 357 |
} |
| 358 |
} |
| 359 |
|
| 360 |
/** <p>Adds the passed css classes to the classes that are declared on top |
| 361 |
* of the page; they will be regarded as if they had been registered with |
| 362 |
* {@link #registerCssClass( String ) registerCssClass()}.</p> */ |
| 363 |
public void mergeRegisteredCssClasses( final CssClass[] classes ) { |
| 364 |
for( int i = 0; i < classes.length; i++ ) { |
| 365 |
Assert.isNotNull( classes[ i ] ); |
| 366 |
registeredCssClasses.put( classes[ i ].getContent(), |
| 367 |
classes[ i ].getClassName() ); |
| 368 |
} |
| 369 |
} |
| 370 |
|
| 371 |
/** <p>Returns the css classes that have been used for rendering |
| 372 |
* into this HtmlResponseWriter, this includes the classes managed by the |
| 373 |
* library and the named classes set by the user.</p> */ |
| 374 |
public CssClass[] getCssClasses() { |
| 375 |
ArrayList alResult = new ArrayList(); |
| 376 |
Enumeration keys = registeredCssClasses.keys(); |
| 377 |
while( keys.hasMoreElements() ) { |
| 378 |
String content = ( String )keys.nextElement(); |
| 379 |
String className = ( String )registeredCssClasses.get( content ); |
| 380 |
if( !className.startsWith( "." ) ) { |
| 381 |
className = "." + className; |
| 382 |
} |
| 383 |
alResult.add( new CssClass( className, content ) ); |
| 384 |
} |
| 385 |
keys = namedCssClasses.keys(); |
| 386 |
while( keys.hasMoreElements() ) { |
| 387 |
String content = ( String )keys.nextElement(); |
| 388 |
ArrayList alNames = ( ArrayList )namedCssClasses.get( content ); |
| 389 |
String className = getCompoundName( alNames ); |
| 390 |
alResult.add( new CssClass( className, content ) ); |
| 391 |
} |
| 392 |
CssClass[] result = new CssClass[ alResult.size() ]; |
| 393 |
alResult.toArray( result ); |
| 394 |
return result; |
| 395 |
} |
| 396 |
|
| 397 |
/** |
| 398 |
* <p>Returns the number of css classes that were registered via calls to |
| 399 |
* <code>addNamedCssClass(CssClass)</code> or |
| 400 |
* <code>registerCssClass(String)</code></p> |
| 401 |
*/ |
| 402 |
public int getCssClassCount() { |
| 403 |
return registeredCssClasses.size() + namedCssClasses.size(); |
| 404 |
} |
| 405 |
|
| 406 |
/** |
| 407 |
* <p>Removes the css class which contains the given <code>content</code> |
| 408 |
* from list of registered css classes.</p> |
| 409 |
* <p>Does nothing if there is no css class with the given |
| 410 |
* <code>content</code>.</p> |
| 411 |
* @param content the content of the css class to be removed. |
| 412 |
*/ |
| 413 |
public void removeCssClass( final String content ) { |
| 414 |
registeredCssClasses.remove( content ); |
| 415 |
// Note: do not remove namedCssClasses, since then different styles for the |
| 416 |
// same css classname cannot be dynamically switched in AJAX-mode |
| 417 |
} |
| 418 |
|
| 419 |
////////////////// |
167 |
////////////////// |
| 420 |
// response writer |
168 |
// response writer |
| 421 |
|
169 |
|
|
Lines 634-641
Link Here
|
| 634 |
*/ |
382 |
*/ |
| 635 |
// TODO [rh] We could check whether 'elementStarted' is null, since comments |
383 |
// TODO [rh] We could check whether 'elementStarted' is null, since comments |
| 636 |
// are not allowed inside element tags in XHTML 'mode' |
384 |
// are not allowed inside element tags in XHTML 'mode' |
| 637 |
// TODO [rh] calling this method 'inside' an AJaX envelope leads to invalid |
|
|
| 638 |
// XML |
| 639 |
public void writeComment( final Object comment ) throws IOException { |
385 |
public void writeComment( final Object comment ) throws IOException { |
| 640 |
checkIfWriterClosed(); |
386 |
checkIfWriterClosed(); |
| 641 |
ParamCheck.notNull( comment, "comment" ); |
387 |
ParamCheck.notNull( comment, "comment" ); |
|
Lines 705-728
Link Here
|
| 705 |
// helping methods |
451 |
// helping methods |
| 706 |
////////////////// |
452 |
////////////////// |
| 707 |
|
453 |
|
| 708 |
private static String getCompoundName( final List allNames ) { |
454 |
private void checkIfWriterClosed() { |
| 709 |
Assert.isTrue( allNames.size() > 0 ); |
|
|
| 710 |
String result = "." + ( String )allNames.get( 0 ); |
| 711 |
for( int i = 1; i < allNames.size(); i++ ) { |
| 712 |
result += ", ." + ( String )allNames.get( i ); |
| 713 |
} |
| 714 |
return result; |
| 715 |
} |
| 716 |
|
| 717 |
private static String createClassName( final String key ) { |
| 718 |
return CLASS_PREFIX + Integer.toHexString( key.hashCode() ); |
| 719 |
} |
| 720 |
|
| 721 |
private void checkIfWriterClosed() throws IOException { |
| 722 |
// TODO [rh] replace by IllegalStateException? |
| 723 |
if( closed ) { |
455 |
if( closed ) { |
| 724 |
String msg = "Operation is not allowed since the writer was closed."; |
456 |
String msg = "Operation is not allowed since the writer was closed."; |
| 725 |
throw new IOException( msg ); |
457 |
throw new IllegalStateException( msg ); |
| 726 |
} |
458 |
} |
| 727 |
} |
459 |
} |
| 728 |
} |
460 |
} |