1 /* 2 * Copyright 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 package com.google.gwt.sample.showcase.client.content.i18n; 17 18 import com.google.gwt.core.client.GWT; 19 import com.google.gwt.core.client.RunAsyncCallback; 20 import com.google.gwt.event.dom.client.ClickEvent; 21 import com.google.gwt.event.dom.client.ClickHandler; 22 import com.google.gwt.event.dom.client.KeyUpEvent; 23 import com.google.gwt.event.dom.client.KeyUpHandler; 24 import com.google.gwt.i18n.client.Constants; 25 import com.google.gwt.i18n.client.LocaleInfo; 26 import com.google.gwt.i18n.shared.BidiFormatter; 27 import com.google.gwt.safehtml.shared.SafeHtmlUtils; 28 import com.google.gwt.sample.showcase.client.ContentWidget; 29 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseData; 30 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseRaw; 31 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource; 32 import com.google.gwt.user.client.rpc.AsyncCallback; 33 import com.google.gwt.user.client.ui.Anchor; 34 import com.google.gwt.user.client.ui.FlexTable; 35 import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter; 36 import com.google.gwt.user.client.ui.HTML; 37 import com.google.gwt.user.client.ui.HasVerticalAlignment; 38 import com.google.gwt.user.client.ui.HorizontalPanel; 39 import com.google.gwt.user.client.ui.TextBox; 40 import com.google.gwt.user.client.ui.Widget; 41 42 /** 43 * Example file. 44 */ 45 @ShowcaseRaw({"BlogMessages.java", "BlogMessages.properties"}) 46 public class CwBidiFormatting extends ContentWidget { 47 /** 48 * The constants used in this Content Widget. 49 */ 50 @ShowcaseSource 51 public static interface CwConstants extends Constants { cwBidiFormattingArg0Label()52 String cwBidiFormattingArg0Label(); 53 cwBidiFormattingArg1Label()54 String cwBidiFormattingArg1Label(); 55 cwBidiFormattingArg2Label()56 String cwBidiFormattingArg2Label(); 57 cwBidiFormattingBidiFormattedLabel()58 String cwBidiFormattingBidiFormattedLabel(); 59 cwBidiFormattingDescription()60 String cwBidiFormattingDescription(); 61 cwBidiFormattingLinkText()62 String cwBidiFormattingLinkText(); 63 cwBidiFormattingName()64 String cwBidiFormattingName(); 65 cwBidiFormattingNonbidiFormattedLabel()66 String cwBidiFormattingNonbidiFormattedLabel(); 67 cwBidiFormattingTemplateLabel()68 String cwBidiFormattingTemplateLabel(); 69 } 70 71 /** 72 * The {@link TextBox} where the user enters argument 0. 73 */ 74 @ShowcaseData 75 private TextBox arg0Box = null; 76 77 /** 78 * The {@link TextBox} where the user enters argument 1. 79 */ 80 @ShowcaseData 81 private TextBox arg1Box = null; 82 83 /** 84 * The {@link TextBox} where the user enters argument 2. 85 */ 86 @ShowcaseData 87 private TextBox arg2Box = null; 88 89 /** 90 * A {@link com.google.gwt.i18n.shared.BidiFormatter} instance used for 91 * bidi-formatting of user input. 92 */ 93 @ShowcaseData 94 private BidiFormatter bidiFormatter = 95 BidiFormatter.getInstanceForCurrentLocale(); 96 97 /** 98 * An instance of the constants. 99 */ 100 @ShowcaseData 101 private final CwConstants constants; 102 103 /** 104 * The blog messages used in this example. 105 */ 106 @ShowcaseData 107 private BlogMessages blogMessages = null; 108 109 /** 110 * The {@link HTML} used to display the message. 111 */ 112 @ShowcaseData 113 private HTML message = null; 114 115 /** 116 * The {@link HTML} used to display the bidi formatted message. 117 */ 118 @ShowcaseData 119 private HTML bidiFormattedMessage = null; 120 121 /** 122 * Constructor. 123 * 124 * @param constants the constants 125 */ CwBidiFormatting(CwConstants constants)126 public CwBidiFormatting(CwConstants constants) { 127 super(constants.cwBidiFormattingName(), 128 constants.cwBidiFormattingDescription(), false, "BlogMessages.java", 129 "BlogMessages.properties"); 130 this.constants = constants; 131 } 132 133 /** 134 * Initialize this example. 135 */ 136 @ShowcaseSource 137 @Override onInitialize()138 public Widget onInitialize() { 139 // Create the internationalized blog messages 140 blogMessages = GWT.create(BlogMessages.class); 141 142 // Use a FlexTable to layout the content 143 FlexTable layout = new FlexTable(); 144 FlexCellFormatter formatter = layout.getFlexCellFormatter(); 145 layout.setCellSpacing(5); 146 147 // Add a link to the source code of the Interface 148 final String rawFile = getSimpleName(BlogMessages.class); 149 Anchor link = new Anchor(rawFile); 150 link.addClickHandler(new ClickHandler() { 151 public void onClick(ClickEvent event) { 152 fireRawSourceRequest(rawFile + ".java"); 153 } 154 }); 155 HorizontalPanel linkPanel = new HorizontalPanel(); 156 linkPanel.setSpacing(3); 157 linkPanel.add(new HTML(constants.cwBidiFormattingLinkText())); 158 linkPanel.add(link); 159 layout.setWidget(0, 0, linkPanel); 160 formatter.setColSpan(0, 0, 2); 161 162 // Show the template for reference 163 String template = blogMessages.userComment("{0}", "{1}", "{2}"); 164 layout.setHTML(1, 0, constants.cwBidiFormattingTemplateLabel()); 165 layout.setHTML(1, 1, template); 166 167 // Add argument 0 168 arg0Box = new TextBox(); 169 // Using an initial value whose direction is opposite the locale's direction 170 // demonstrates the need for and effect of bidi formatting. 171 arg0Box.setText( 172 LocaleInfo.getCurrentLocale().isRTL() ? "Tom Bombadil" : "תומר גרין"); 173 layout.setHTML(2, 0, constants.cwBidiFormattingArg0Label()); 174 layout.setWidget(2, 1, arg0Box); 175 176 // Add argument 1 177 arg1Box = new TextBox(); 178 arg1Box.setText("16"); 179 layout.setHTML(3, 0, constants.cwBidiFormattingArg1Label()); 180 layout.setWidget(3, 1, arg1Box); 181 182 // Add argument 2 183 arg2Box = new TextBox(); 184 // Using an initial value whose direction is opposite the locale's direction 185 // demonstrates the need for and effect of bidi formatting. 186 arg2Box.setText(LocaleInfo.getCurrentLocale().isRTL() 187 ? "How deep is your love?" : "כמה חול יש בחוף?"); 188 layout.setHTML(4, 0, constants.cwBidiFormattingArg2Label()); 189 layout.setWidget(4, 1, arg2Box); 190 191 // Add the unformatted message 192 message = new HTML(); 193 layout.setHTML(5, 0, constants.cwBidiFormattingNonbidiFormattedLabel()); 194 layout.setWidget(5, 1, message); 195 formatter.setVerticalAlignment(5, 0, HasVerticalAlignment.ALIGN_TOP); 196 197 // Add the bidi formatted message 198 bidiFormattedMessage = new HTML(); 199 layout.setHTML(6, 0, constants.cwBidiFormattingBidiFormattedLabel()); 200 layout.setWidget(6, 1, bidiFormattedMessage); 201 formatter.setVerticalAlignment(6, 0, HasVerticalAlignment.ALIGN_TOP); 202 203 // Add handlers to all of the argument boxes 204 KeyUpHandler keyUpHandler = new KeyUpHandler() { 205 public void onKeyUp(KeyUpEvent event) { 206 updateMessages(); 207 } 208 }; 209 arg0Box.addKeyUpHandler(keyUpHandler); 210 arg1Box.addKeyUpHandler(keyUpHandler); 211 arg2Box.addKeyUpHandler(keyUpHandler); 212 213 // Return the layout Widget 214 updateMessages(); 215 216 return layout; 217 } 218 219 @Override asyncOnInitialize(final AsyncCallback<Widget> callback)220 protected void asyncOnInitialize(final AsyncCallback<Widget> callback) { 221 GWT.runAsync(CwBidiFormatting.class, new RunAsyncCallback() { 222 223 public void onFailure(Throwable caught) { 224 callback.onFailure(caught); 225 } 226 227 public void onSuccess() { 228 callback.onSuccess(onInitialize()); 229 } 230 }); 231 } 232 233 /** 234 * Update the formatted message. 235 */ 236 @ShowcaseSource updateMessages()237 private void updateMessages() { 238 String arg0 = arg0Box.getText().trim(); 239 String arg1 = arg1Box.getText().trim(); 240 String arg2 = arg2Box.getText().trim(); 241 message.setText(blogMessages.userComment(arg0, arg1, arg2)); 242 243 bidiFormattedMessage.setHTML( 244 blogMessages.userComment(bidiFormatter.spanWrap(arg0), 245 // arg1 is intended to be an unsigned number, so bidi formatting is not 246 // needed. However, HTML escaping is a must to avoid an XSS attack hole! 247 SafeHtmlUtils.htmlEscape(arg1), bidiFormatter.spanWrap(arg2))); 248 } 249 } 250