001 package org.apache.myfaces.tobago.renderkit.html; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one or more 005 * contributor license agreements. See the NOTICE file distributed with 006 * this work for additional information regarding copyright ownership. 007 * The ASF licenses this file to You under the Apache License, Version 2.0 008 * (the "License"); you may not use this file except in compliance with 009 * the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020 import org.apache.commons.lang.StringUtils; 021 import org.apache.commons.logging.Log; 022 import org.apache.commons.logging.LogFactory; 023 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_FOCUS; 024 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_INLINE; 025 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_INNER_HEIGHT; 026 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_INNER_WIDTH; 027 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_LAYOUT_HEIGHT; 028 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_LAYOUT_WIDTH; 029 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_STYLE; 030 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_STYLE_BODY; 031 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_STYLE_HEADER; 032 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_TIP; 033 import static org.apache.myfaces.tobago.TobagoConstants.FACET_LAYOUT; 034 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_OUT; 035 import org.apache.myfaces.tobago.component.ComponentUtil; 036 import org.apache.myfaces.tobago.component.UIPage; 037 import org.apache.myfaces.tobago.component.UIData; 038 import org.apache.myfaces.tobago.context.ResourceManagerUtil; 039 import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey; 040 import org.apache.myfaces.tobago.renderkit.LayoutInformationProvider; 041 import org.apache.myfaces.tobago.renderkit.LayoutableRendererBase; 042 import org.apache.myfaces.tobago.renderkit.RenderUtil; 043 import org.apache.myfaces.tobago.renderkit.RendererBaseWrapper; 044 import org.apache.myfaces.tobago.util.LayoutUtil; 045 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter; 046 import org.apache.myfaces.tobago.webapp.TobagoResponseWriterWrapper; 047 048 import javax.faces.component.UIComponent; 049 import javax.faces.component.UIInput; 050 import javax.faces.component.NamingContainer; 051 import javax.faces.context.FacesContext; 052 import javax.faces.context.ResponseWriter; 053 import javax.faces.model.SelectItem; 054 import javax.faces.model.SelectItemGroup; 055 import java.io.IOException; 056 import java.util.Arrays; 057 import java.util.List; 058 import java.util.Map; 059 import java.util.StringTokenizer; 060 061 /* 062 * User: weber 063 * Date: Jan 11, 2005 064 * Time: 4:59:36 PM 065 */ 066 public final class HtmlRendererUtil { 067 068 private static final Log LOG = LogFactory.getLog(HtmlRendererUtil.class); 069 070 private HtmlRendererUtil() { 071 // to prevent instantiation 072 } 073 074 public static void renderFocusId(FacesContext facesContext, UIComponent component) 075 throws IOException { 076 077 if (ComponentUtil.getBooleanAttribute(component, ATTR_FOCUS)) { 078 UIPage page = ComponentUtil.findPage(facesContext, component); 079 String id = component.getClientId(facesContext); 080 if (!StringUtils.isBlank(page.getFocusId()) && !page.getFocusId().equals(id)) { 081 LOG.warn("page focusId = \"" + page.getFocusId() + "\" ignoring new value \"" 082 + id + "\""); 083 } else { 084 TobagoResponseWriter writer = HtmlRendererUtil.getTobagoResponseWriter(facesContext); 085 writer.writeJavascript("Tobago.focusId = '" + id + "';"); 086 } 087 } 088 } 089 090 public static void prepareRender(FacesContext facesContext, UIComponent component) { 091 // xxx find a better way for this question: isTobago or isLayoutable something like that. 092 LayoutableRendererBase layoutRendererBase = ComponentUtil.getRenderer(facesContext, component); 093 if (layoutRendererBase != null && !(layoutRendererBase instanceof RendererBaseWrapper)) { 094 createCssClass(facesContext, component); 095 layoutWidth(facesContext, component); 096 layoutHeight(facesContext, component); 097 } 098 } 099 100 public static HtmlStyleMap prepareInnerStyle(UIComponent component) { 101 HtmlStyleMap htmlStyleMap = new HtmlStyleMap(); 102 Integer innerSpaceInteger = (Integer) 103 component.getAttributes().get(ATTR_INNER_WIDTH); 104 if (innerSpaceInteger != null && innerSpaceInteger != -1) { 105 htmlStyleMap.put("width", innerSpaceInteger); 106 } 107 innerSpaceInteger = (Integer) 108 component.getAttributes().get(ATTR_INNER_HEIGHT); 109 if (innerSpaceInteger != null && innerSpaceInteger != -1) { 110 htmlStyleMap.put("height", innerSpaceInteger); 111 } 112 return htmlStyleMap; 113 } 114 115 116 public static void createCssClass(FacesContext facesContext, UIComponent component) { 117 String rendererName = getRendererName(facesContext, component); 118 if (rendererName != null) { 119 StyleClasses classes = StyleClasses.ensureStyleClasses(component); 120 classes.updateClassAttributeAndMarkup(component, rendererName); 121 } 122 } 123 124 public static String getRendererName(FacesContext facesContext, UIComponent component) { 125 final String rendererType = component.getRendererType(); 126 //final String family = component.getFamily(); 127 if (rendererType != null//&& !"facelets".equals(family) 128 ) { 129 LayoutableRendererBase layoutableRendererBase = ComponentUtil.getRenderer(facesContext, component); 130 if (layoutableRendererBase != null) { 131 return layoutableRendererBase.getRendererName(rendererType); 132 } 133 } 134 return null; 135 } 136 137 public static void writeLabelWithAccessKey(TobagoResponseWriter writer, LabelWithAccessKey label) 138 throws IOException { 139 int pos = label.getPos(); 140 String text = label.getText(); 141 if (pos == -1) { 142 writer.writeText(text); 143 } else { 144 writer.writeText(text.substring(0, pos)); 145 writer.startElement(HtmlConstants.U, null); 146 writer.writeText(Character.toString(text.charAt(pos))); 147 writer.endElement(HtmlConstants.U); 148 writer.writeText(text.substring(pos + 1)); 149 } 150 } 151 152 public static void setDefaultTransition(FacesContext facesContext, boolean transition) 153 throws IOException { 154 writeScriptLoader(facesContext, null, new String[]{"Tobago.transition = " + transition + ";"}); 155 } 156 157 public static void addClickAcceleratorKey( 158 FacesContext facesContext, String clientId, char key) 159 throws IOException { 160 addClickAcceleratorKey(facesContext, clientId, key, null); 161 } 162 163 public static void addClickAcceleratorKey( 164 FacesContext facesContext, String clientId, char key, String modifier) 165 throws IOException { 166 String str 167 = createOnclickAcceleratorKeyJsStatement(clientId, key, modifier); 168 writeScriptLoader(facesContext, null, new String[]{str}); 169 } 170 171 public static void addAcceleratorKey( 172 FacesContext facesContext, String func, char key) throws IOException { 173 addAcceleratorKey(facesContext, func, key, null); 174 } 175 176 public static void addAcceleratorKey( 177 FacesContext facesContext, String func, char key, String modifier) 178 throws IOException { 179 String str = createAcceleratorKeyJsStatement(func, key, modifier); 180 writeScriptLoader(facesContext, null, new String[]{str}); 181 } 182 183 public static String createOnclickAcceleratorKeyJsStatement( 184 String clientId, char key, String modifier) { 185 String func = "Tobago.clickOnElement('" + clientId + "');"; 186 return createAcceleratorKeyJsStatement(func, key, modifier); 187 } 188 189 public static String createAcceleratorKeyJsStatement( 190 String func, char key, String modifier) { 191 StringBuilder buffer = new StringBuilder(); 192 buffer.append("new Tobago.AcceleratorKey(function() {"); 193 buffer.append(func); 194 if (!func.endsWith(";")) { 195 buffer.append(';'); 196 } 197 buffer.append("}, \""); 198 buffer.append(key); 199 if (modifier != null) { 200 buffer.append("\", \""); 201 buffer.append(modifier); 202 } 203 buffer.append("\");"); 204 return buffer.toString(); 205 } 206 207 public static String getLayoutSpaceStyle(UIComponent component) { 208 StringBuilder sb = new StringBuilder(); 209 Integer space = LayoutUtil.getLayoutSpace(component, ATTR_LAYOUT_WIDTH, ATTR_LAYOUT_WIDTH); 210 if (space != null) { 211 sb.append(" width: "); 212 sb.append(space); 213 sb.append("px;"); 214 } 215 space = LayoutUtil.getLayoutSpace(component, ATTR_LAYOUT_HEIGHT, ATTR_LAYOUT_HEIGHT); 216 if (space != null) { 217 sb.append(" height: "); 218 sb.append(space); 219 sb.append("px;"); 220 } 221 return sb.toString(); 222 } 223 224 public static Integer getStyleAttributeIntValue(HtmlStyleMap style, String name) { 225 if (style == null) { 226 return null; 227 } 228 return style.getInt(name); 229 } 230 231 public static String getStyleAttributeValue(String style, String name) { 232 if (style == null) { 233 return null; 234 } 235 String value = null; 236 StringTokenizer st = new StringTokenizer(style, ";"); 237 while (st.hasMoreTokens()) { 238 String attribute = st.nextToken().trim(); 239 if (attribute.startsWith(name)) { 240 value = attribute.substring(attribute.indexOf(':') + 1).trim(); 241 } 242 } 243 return value; 244 } 245 246 247 public static void replaceStyleAttribute(UIComponent component, String styleAttribute, String value) { 248 HtmlStyleMap style = ensureStyleAttributeMap(component); 249 style.put(styleAttribute, value); 250 } 251 252 public static void replaceStyleAttribute(UIComponent component, String attribute, 253 String styleAttribute, String value) { 254 HtmlStyleMap style = ensureStyleAttributeMap(component, attribute); 255 style.put(styleAttribute, value); 256 } 257 258 public static void replaceStyleAttribute(UIComponent component, String styleAttribute, int value) { 259 HtmlStyleMap style = ensureStyleAttributeMap(component); 260 style.put(styleAttribute, value); 261 } 262 263 public static void replaceStyleAttribute(UIComponent component, String attribute, 264 String styleAttribute, int value) { 265 HtmlStyleMap style = ensureStyleAttributeMap(component, attribute); 266 style.put(styleAttribute, value); 267 268 } 269 270 private static HtmlStyleMap ensureStyleAttributeMap(UIComponent component) { 271 return ensureStyleAttributeMap(component, ATTR_STYLE); 272 } 273 274 private static HtmlStyleMap ensureStyleAttributeMap(UIComponent component, String attribute) { 275 final Map attributes = component.getAttributes(); 276 HtmlStyleMap style = (HtmlStyleMap) attributes.get(attribute); 277 if (style == null) { 278 style = new HtmlStyleMap(); 279 attributes.put(attribute, style); 280 } 281 return style; 282 } 283 284 public static String replaceStyleAttribute(String style, String name, 285 String value) { 286 style = removeStyleAttribute(style != null ? style : "", name); 287 return style + " " + name + ": " + value + ";"; 288 } 289 290 public static String removeStyleAttribute(String style, String name) { 291 if (style == null) { 292 return null; 293 } 294 String pattern = name + "\\s*?:[^;]*?;"; 295 return style.replaceAll(pattern, "").trim(); 296 } 297 298 public static void removeStyleAttribute(UIComponent component, String name) { 299 ensureStyleAttributeMap(component).remove(name); 300 } 301 302 /** 303 * @deprecated Please use StyleClasses.ensureStyleClasses(component).add(clazz); 304 */ 305 @Deprecated 306 public static void addCssClass(UIComponent component, String clazz) { 307 StyleClasses.ensureStyleClasses(component).addFullQualifiedClass(clazz); 308 } 309 310 public static void layoutWidth(FacesContext facesContext, UIComponent component) { 311 layoutSpace(facesContext, component, true); 312 } 313 314 public static void layoutHeight(FacesContext facesContext, UIComponent component) { 315 layoutSpace(facesContext, component, false); 316 } 317 318 public static void layoutSpace(FacesContext facesContext, UIComponent component, 319 boolean width) { 320 321 // prepare html 'style' attribute 322 Integer layoutSpace; 323 String layoutAttribute; 324 String styleAttribute; 325 if (width) { 326 layoutSpace = LayoutUtil.getLayoutWidth(component); 327 layoutAttribute = ATTR_LAYOUT_WIDTH; 328 styleAttribute = HtmlAttributes.WIDTH; 329 } else { 330 layoutSpace = LayoutUtil.getLayoutHeight(component); 331 layoutAttribute = ATTR_LAYOUT_HEIGHT; 332 styleAttribute = HtmlAttributes.HEIGHT; 333 } 334 int space = -1; 335 if (layoutSpace != null) { 336 space = layoutSpace.intValue(); 337 } 338 if (space == -1 && (!RENDERER_TYPE_OUT.equals(component.getRendererType()))) { 339 UIComponent parent = component.getParent(); 340 space = LayoutUtil.getInnerSpace(facesContext, parent, width); 341 if (space > 0 && !ComponentUtil.isFacetOf(component, parent)) { 342 component.getAttributes().put(layoutAttribute, Integer.valueOf(space)); 343 if (width) { 344 component.getAttributes().remove(ATTR_INNER_WIDTH); 345 } else { 346 component.getAttributes().remove(ATTR_INNER_HEIGHT); 347 } 348 } 349 } 350 if (space > 0) { 351 LayoutInformationProvider renderer = ComponentUtil.getRenderer(facesContext, component); 352 if (layoutSpace != null 353 || !ComponentUtil.getBooleanAttribute(component, ATTR_INLINE)) { 354 int styleSpace = space; 355 if (renderer != null) { 356 if (width) { 357 styleSpace -= renderer.getComponentExtraWidth(facesContext, component); 358 } else { 359 styleSpace -= renderer.getComponentExtraHeight(facesContext, component); 360 } 361 } 362 363 replaceStyleAttribute(component, styleAttribute, styleSpace); 364 365 } 366 UIComponent layout = component.getFacet(FACET_LAYOUT); 367 if (layout != null) { 368 int layoutSpace2 = LayoutUtil.getInnerSpace(facesContext, component, 369 width); 370 if (layoutSpace2 > 0) { 371 layout.getAttributes().put(layoutAttribute, Integer.valueOf(layoutSpace2)); 372 } 373 } 374 } 375 } 376 377 public static void createHeaderAndBodyStyles(FacesContext facesContext, UIComponent component) { 378 createHeaderAndBodyStyles(facesContext, component, true); 379 createHeaderAndBodyStyles(facesContext, component, false); 380 } 381 382 public static void createHeaderAndBodyStyles(FacesContext facesContext, UIComponent component, boolean width) { 383 LayoutInformationProvider renderer = ComponentUtil.getRenderer(facesContext, component); 384 HtmlStyleMap style = (HtmlStyleMap) component.getAttributes().get(ATTR_STYLE); 385 Integer styleSpace = null; 386 try { 387 styleSpace = style.getInt(width ? "width" : "height"); 388 } catch (Exception e) { 389 /* ignore */ 390 } 391 if (styleSpace != null) { 392 int bodySpace = 0; 393 int headerSpace = 0; 394 if (!width) { 395 if (renderer != null) { 396 headerSpace = renderer.getHeaderHeight(facesContext, component); 397 } 398 bodySpace = styleSpace - headerSpace; 399 } 400 HtmlStyleMap headerStyle = ensureStyleAttributeMap(component, ATTR_STYLE_HEADER); 401 HtmlStyleMap bodyStyle = ensureStyleAttributeMap(component, ATTR_STYLE_BODY); 402 if (width) { 403 headerStyle.put("width", styleSpace); 404 bodyStyle.put("width", styleSpace); 405 } else { 406 headerStyle.put("height", headerSpace); 407 bodyStyle.put("height", bodySpace); 408 } 409 } 410 } 411 412 /** 413 * @deprecated Please use StyleClasses.ensureStyleClasses(component).updateClassAttribute(renderer, component); 414 */ 415 @Deprecated 416 public static void updateClassAttribute(String cssClass, String rendererName, UIComponent component) { 417 throw new UnsupportedOperationException( 418 "Please use StyleClasses.ensureStyleClasses(component).updateClassAttribute(renderer, component)"); 419 } 420 421 /** 422 * @deprecated Please use StyleClasses.addMarkupClass() 423 */ 424 @Deprecated 425 public static void addMarkupClass(UIComponent component, String rendererName, 426 String subComponent, StringBuilder tobagoClass) { 427 throw new UnsupportedOperationException("Please use StyleClasses.addMarkupClass()"); 428 } 429 430 /** 431 * @deprecated Please use StyleClasses.addMarkupClass() 432 */ 433 @Deprecated 434 public static void addMarkupClass(UIComponent component, String rendererName, StyleClasses classes) { 435 classes.addMarkupClass(component, rendererName); 436 } 437 438 public static void addImageSources(FacesContext facesContext, TobagoResponseWriter writer, String src, String id) 439 throws IOException { 440 StringBuilder buffer = new StringBuilder(); 441 buffer.append("new Tobago.Image('"); 442 buffer.append(id); 443 buffer.append("','"); 444 buffer.append(ResourceManagerUtil.getImageWithPath(facesContext, src, false)); 445 buffer.append("','"); 446 buffer.append(ResourceManagerUtil.getImageWithPath(facesContext, createSrc(src, "Disabled"), true)); 447 buffer.append("','"); 448 buffer.append(ResourceManagerUtil.getImageWithPath(facesContext, createSrc(src, "Hover"), true)); 449 buffer.append("');"); 450 writer.writeJavascript(buffer.toString()); 451 } 452 453 public static String createSrc(String src, String ext) { 454 int dot = src.lastIndexOf('.'); 455 if (dot == -1) { 456 LOG.warn("Image src without extension: '" + src + "'"); 457 return src; 458 } else { 459 return src.substring(0, dot) + ext + src.substring(dot); 460 } 461 } 462 463 public static TobagoResponseWriter getTobagoResponseWriter(FacesContext facesContext) { 464 465 ResponseWriter writer = facesContext.getResponseWriter(); 466 if (writer instanceof TobagoResponseWriter) { 467 return (TobagoResponseWriter) writer; 468 } else { 469 return new TobagoResponseWriterWrapper(writer); 470 } 471 } 472 473 /** @deprecated use TobagoResponseWriter.writeJavascript() */ 474 @Deprecated 475 public static void writeJavascript(ResponseWriter writer, String script) throws IOException { 476 startJavascript(writer); 477 writer.write(script); 478 endJavascript(writer); 479 } 480 481 /** @deprecated use TobagoResponseWriter.writeJavascript() */ 482 @Deprecated 483 public static void startJavascript(ResponseWriter writer) throws IOException { 484 writer.startElement(HtmlConstants.SCRIPT, null); 485 writer.writeAttribute(HtmlAttributes.TYPE, "text/javascript", null); 486 writer.write("\n<!--\n"); 487 } 488 489 /** @deprecated use TobagoResponseWriter.writeJavascript() */ 490 @Deprecated 491 public static void endJavascript(ResponseWriter writer) throws IOException { 492 writer.write("\n// -->\n"); 493 writer.endElement(HtmlConstants.SCRIPT); 494 } 495 496 public static void writeScriptLoader(FacesContext facesContext, String script) 497 throws IOException { 498 writeScriptLoader(facesContext, new String[]{script}, null); 499 } 500 501 public static void writeScriptLoader(FacesContext facesContext, String[] scripts, String[] afterLoadCmds) 502 throws IOException { 503 TobagoResponseWriter writer = HtmlRendererUtil.getTobagoResponseWriter(facesContext); 504 505 String allScripts = "[]"; 506 if (scripts != null) { 507 allScripts = ResourceManagerUtil.getScriptsAsJSArray(facesContext, scripts); 508 } 509 510 StringBuilder script = new StringBuilder(); 511 script.append("new Tobago.ScriptLoader(\n "); 512 script.append(allScripts); 513 514 if (afterLoadCmds != null && afterLoadCmds.length > 0) { 515 script.append(", \n"); 516 boolean first = true; 517 for (String afterLoadCmd : afterLoadCmds) { 518 String[] splittedStrings = StringUtils.split(afterLoadCmd, '\n'); // split on <CR> to have nicer JS 519 for (String splitted : splittedStrings) { 520 String cmd = StringUtils.replace(splitted, "\\", "\\\\"); 521 cmd = StringUtils.replace(cmd, "\"", "\\\""); 522 script.append(first ? " " : " + "); 523 script.append("\""); 524 script.append(cmd); 525 script.append("\"\n"); 526 first = false; 527 } 528 } 529 } 530 script.append(");"); 531 532 writer.writeJavascript(script.toString()); 533 } 534 535 public static void writeStyleLoader( 536 FacesContext facesContext, String[] styles) throws IOException { 537 TobagoResponseWriter writer = HtmlRendererUtil.getTobagoResponseWriter(facesContext); 538 539 StringBuilder builder = new StringBuilder(); 540 builder.append("Tobago.ensureStyleFiles(\n "); 541 builder.append(ResourceManagerUtil.getStylesAsJSArray(facesContext, styles)); 542 builder.append(");"); 543 writer.writeJavascript(builder.toString()); 544 } 545 546 public static String getTitleFromTipAndMessages(FacesContext facesContext, UIComponent component) { 547 String messages = ComponentUtil.getFacesMessageAsString(facesContext, component); 548 return HtmlRendererUtil.addTip(messages, (String) component.getAttributes().get(ATTR_TIP)); 549 } 550 551 public static String addTip(String title, String tip) { 552 if (tip != null) { 553 if (title != null && title.length() > 0) { 554 title += " :: "; 555 } else { 556 title = ""; 557 } 558 title += tip; 559 } 560 return title; 561 } 562 563 public static void renderSelectItems(UIInput component, List<SelectItem> items, Object[] values, 564 TobagoResponseWriter writer, FacesContext facesContext) throws IOException { 565 566 if (LOG.isDebugEnabled()) { 567 LOG.debug("value = '" + Arrays.toString(values) + "'"); 568 } 569 for (SelectItem item : items) { 570 if (item instanceof SelectItemGroup) { 571 writer.startElement(HtmlConstants.OPTGROUP, null); 572 writer.writeAttribute(HtmlAttributes.LABEL, item.getLabel(), true); 573 SelectItem[] selectItems = ((SelectItemGroup) item).getSelectItems(); 574 renderSelectItems(component, Arrays.asList(selectItems), values, writer, facesContext); 575 writer.endElement(HtmlConstants.OPTGROUP); 576 } else { 577 writer.startElement(HtmlConstants.OPTION, null); 578 final Object itemValue = item.getValue(); 579 String formattedValue 580 = RenderUtil.getFormattedValue(facesContext, component, itemValue); 581 writer.writeAttribute(HtmlAttributes.VALUE, formattedValue, true); 582 if (RenderUtil.contains(values, item.getValue())) { 583 writer.writeAttribute(HtmlAttributes.SELECTED, true); 584 } 585 writer.writeText(item.getLabel()); 586 writer.endElement(HtmlConstants.OPTION); 587 } 588 } 589 } 590 591 public static String getComponentId(FacesContext context, UIComponent component, String componentId) { 592 UIComponent partiallyComponent = ComponentUtil.findComponent(component, componentId); 593 if (partiallyComponent != null) { 594 String clientId = partiallyComponent.getClientId(context); 595 if (partiallyComponent instanceof UIData) { 596 int rowIndex = ((UIData) partiallyComponent).getRowIndex(); 597 if (rowIndex >= 0 && clientId.endsWith(Integer.toString(rowIndex))) { 598 return clientId.substring(0, clientId.lastIndexOf(NamingContainer.SEPARATOR_CHAR)); 599 } 600 } 601 return clientId; 602 } 603 LOG.error("No Component found for id " + componentId); 604 return null; 605 } 606 607 public static String toStyleString(String key, Integer value) { 608 StringBuilder buf = new StringBuilder(); 609 buf.append(key); 610 buf.append(":"); 611 buf.append(value); 612 buf.append("px; "); 613 return buf.toString(); 614 } 615 616 public static String toStyleString(String key, String value) { 617 StringBuilder buf = new StringBuilder(); 618 buf.append(key); 619 buf.append(":"); 620 buf.append(value); 621 buf.append("; "); 622 return buf.toString(); 623 } 624 625 }