Adds datetime demonstration application.

This commit is contained in:
konsoletyper 2014-05-24 17:48:09 +04:00
parent 5770df5413
commit e83fd18dec
16 changed files with 531 additions and 15 deletions

View File

@ -76,6 +76,7 @@
<module>teavm-dom</module>
<module>teavm-jso</module>
<module>teavm-html4j</module>
<module>teavm-samples</module>
</modules>
<dependencyManagement>

View File

@ -15,6 +15,7 @@
*/
package org.teavm.classlib.impl;
import org.teavm.classlib.impl.unicode.CLDRHelper;
import org.teavm.classlib.java.util.LocaleSettingsNativeGenerator;
import org.teavm.javascript.ni.Generator;
import org.teavm.model.MethodDescriptor;
@ -47,7 +48,10 @@ public class JCLPlugin implements TeaVMPlugin {
host.add(new MethodReference("java.util.Locale", "readLanguagesFromCLDR", ValueType.VOID), localeGen);
host.add(new MethodReference("java.util.Locale", "readCountriesFromCLDR", ValueType.VOID), localeGen);
host.add(new MethodReference("java.util.Calendar", "readWeeksFromCLDR", ValueType.VOID), localeGen);
host.add(new MethodReference(CLDRHelper.class.getName(), "readLikelySubtagsFromCLDR", ValueType.VOID),
localeGen);
host.add(new MethodReference("java.util.Locale", "getDefaultLocale", ValueType.object("java.lang.String")),
localeGen);
host.add(new MethodReference("java.util.Locale", "readAvailableLocales", ValueType.VOID), localeGen);
}
}

View File

@ -15,6 +15,9 @@
*/
package org.teavm.classlib.impl.unicode;
import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.ni.GeneratedBy;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
@ -33,6 +36,7 @@ public class CLDRHelper {
// Defined by JCLPlugin
private static native void readLikelySubtagsFromCLDR();
// TODO: implement using CLDR
@GeneratedBy(CLDRHelperNativeGenerator.class)
@PluggableDependency(CLDRHelperNativeGenerator.class)
private static native String getLikelySubtagsImpl(String localeCode);
}

View File

@ -56,7 +56,8 @@ public class LocaleNativeGenerator implements Generator, DependencyPlugin {
}
private void generateAvailableLocales(SourceWriter writer) throws IOException {
writer.append("var locales = Object.keys(").appendClass("java.util.Locale").append(".$CLDR);").softNewLine();
writer.append("var locales = ").appendClass("java.util.Locale").append(".$CLDR.availableLocales;")
.softNewLine();
writer.append("var array = $rt_createArray(").appendClass("java.lang.String").append(", locales);")
.softNewLine();
writer.append("for (var i = 0; i < locales.length; ++i) {").indent().softNewLine();

View File

@ -40,6 +40,7 @@ public class LocaleSettingsNativeGenerator implements Generator {
private Map<String, LocaleInfo> knownLocales = new LinkedHashMap<>();
private Map<String, Integer> minDaysMap = new LinkedHashMap<>();
private Map<String, Integer> firstDayMap = new LinkedHashMap<>();
private Map<String, String> likelySubtags = new LinkedHashMap<>();
private Set<String> availableLocales = new LinkedHashSet<>();
private Set<String> availableLanguages = new LinkedHashSet<>();
private Set<String> availableCountries = new LinkedHashSet<>();
@ -60,7 +61,7 @@ public class LocaleSettingsNativeGenerator implements Generator {
private void findAvailableLocales() {
String availableLocalesString = properties.getProperty("java.util.Locale.available", "en_EN").trim();
for (String locale : Arrays.asList(availableLocalesString.split(" *, +"))) {
for (String locale : Arrays.asList(availableLocalesString.split(" *, *"))) {
int countryIndex = locale.indexOf('_');
if (countryIndex > 0) {
String language = locale.substring(0, countryIndex);
@ -90,6 +91,8 @@ public class LocaleSettingsNativeGenerator implements Generator {
if (entry.getName().equals("supplemental/weekData.json")) {
readWeekData(input);
continue;
} else if (entry.getName().equals("supplemental/likelySubtags.json")) {
readLikelySubtags(input);
}
int objectIndex = entry.getName().lastIndexOf('/');
String objectName = entry.getName().substring(objectIndex + 1);
@ -156,6 +159,15 @@ public class LocaleSettingsNativeGenerator implements Generator {
}
}
private void readLikelySubtags(InputStream input) {
JsonObject root = (JsonObject)new JsonParser().parse(new InputStreamReader(input));
JsonObject likelySubtagsJson = root.get("supplemental").getAsJsonObject().get("likelySubtags")
.getAsJsonObject();
for (Map.Entry<String, JsonElement> property : likelySubtagsJson.entrySet()) {
likelySubtags.put(property.getKey(), property.getValue().getAsString());
}
}
private int getNumericDay(String day) {
switch (day) {
case "sun":
@ -190,6 +202,12 @@ public class LocaleSettingsNativeGenerator implements Generator {
case "readWeeksFromCLDR":
generateReadWeeksFromCDLR(writer);
break;
case "readLikelySubtagsFromCLDR":
generateReadLikelySubtagsFromCLDR(writer);
break;
case "readAvailableLocales":
generateReadAvailableLocales(writer);
break;
case "getDefaultLocale":
generateGetDefaultLocale(writer);
break;
@ -203,6 +221,20 @@ public class LocaleSettingsNativeGenerator implements Generator {
writer.outdent().append("}").softNewLine();
}
private void generateReadAvailableLocales(SourceWriter writer) throws IOException {
generateDefender(writer, "availableLocales");
writer.appendClass("java.util.Locale").append(".$CLDR.availableLocales = [");
boolean first = true;
for (String locale : availableLocales) {
if (!first) {
writer.append(',').ws();
}
first = false;
writer.append('"').append(Renderer.escapeString(locale)).append('"');
}
writer.append("];").softNewLine();
}
private void generateReadLanguagesFromCLDR(SourceWriter writer) throws IOException {
generateDefender(writer, "languages");
writer.appendClass("java.util.Locale").append(".$CLDR.languages = {").indent().softNewLine();
@ -226,7 +258,7 @@ public class LocaleSettingsNativeGenerator implements Generator {
}
writer.outdent().append('}');
}
writer.outdent().append("}").softNewLine();
writer.outdent().append("};").softNewLine();
}
private void generateReadCountriesFromCLDR(SourceWriter writer) throws IOException {
@ -253,34 +285,49 @@ public class LocaleSettingsNativeGenerator implements Generator {
writer.outdent().append('}');
}
writer.outdent().append("}").softNewLine();
writer.outdent().append("};").softNewLine();
}
private void generateReadWeeksFromCDLR(SourceWriter writer) throws IOException {
generateDefender(writer, "minDays");
writer.appendClass("java.util.Locale").append(".$CLDR.minDays = {").indent().softNewLine();
boolean firstLocale = true;
boolean first = true;
for (Map.Entry<String, Integer> entry : minDaysMap.entrySet()) {
if (!firstLocale) {
if (!first) {
writer.append(",").softNewLine();
}
firstLocale = false;
first = false;
writer.append('"').append(Renderer.escapeString(entry.getKey())).append('"').ws().append(':')
.ws().append('"').append(entry.getValue()).append('"');
.ws().append(entry.getValue());
}
writer.outdent().append("}").softNewLine();
writer.outdent().append("};").softNewLine();
writer.appendClass("java.util.Locale").append(".$CLDR.firstDay = {").indent().softNewLine();
firstLocale = true;
first = true;
for (Map.Entry<String, Integer> entry : firstDayMap.entrySet()) {
if (!firstLocale) {
if (!first) {
writer.append(",").softNewLine();
}
firstLocale = false;
first = false;
writer.append('"').append(Renderer.escapeString(entry.getKey())).append('"').ws().append(':')
.ws().append('"').append(entry.getValue()).append('"');
}
writer.outdent().append("}").softNewLine();
writer.outdent().append("};").softNewLine();
}
private void generateReadLikelySubtagsFromCLDR(SourceWriter writer) throws IOException {
generateDefender(writer, "likelySubtags");
writer.append("java.util.Locale").append(".$CLDR.likelySubtags = {").indent().softNewLine();
boolean first = true;
for (Map.Entry<String, String> entry : likelySubtags.entrySet()) {
if (!first) {
writer.append(",").softNewLine();
}
first = false;
writer.append('"').append(Renderer.escapeString(entry.getKey())).append('"').ws().append(':')
.ws().append('"').append(Renderer.escapeString(entry.getValue())).append('"');
}
writer.outdent().append("};").softNewLine();
}
private void generateGetDefaultLocale(SourceWriter writer) throws IOException {

View File

@ -88,6 +88,9 @@ public final class TLocale implements TCloneable, TSerializable {
// Redefined by JCLPlugin
private static native void readLanguagesFromCLDR();
// Redefined by JCLPlugin
private static native void readAvailableLocales();
public TLocale(String language) {
this(language, "", "");
}
@ -134,6 +137,7 @@ public final class TLocale implements TCloneable, TSerializable {
}
public static TLocale[] getAvailableLocales() {
readAvailableLocales();
if (availableLocales == null) {
String[] strings = getAvailableLocaleStrings();
availableLocales = new TLocale[strings.length];
@ -142,7 +146,7 @@ public final class TLocale implements TCloneable, TSerializable {
int countryIndex = string.indexOf('-');
if (countryIndex > 0) {
availableLocales[i] = new TLocale(string.substring(0, countryIndex),
string.substring(countryIndex));
string.substring(countryIndex + 1));
} else {
availableLocales[i] = new TLocale(string);
}

View File

@ -24,7 +24,11 @@ import org.teavm.jso.JSObject;
public interface EventTarget extends JSObject {
void addEventListener(String type, EventListener listener, boolean useCapture);
void addEventListener(String type, EventListener listener);
void removeEventListener(String type, EventListener listener, boolean useCapture);
void removeEventListener(String type, EventListener listener);
boolean dispatchEvent(Event evt);
}

View File

@ -0,0 +1,29 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.dom.html;
import org.teavm.dom.core.Element;
import org.teavm.jso.JSArrayReader;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface HTMLCollection extends JSArrayReader<Element> {
Element item(int index);
Element namedItem(String name);
}

View File

@ -0,0 +1,72 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.dom.html;
import org.teavm.jso.JSProperty;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface HTMLInputElement extends HTMLElement {
@JSProperty
boolean isChecked();
@JSProperty
void setChecked(boolean checked);
@JSProperty
boolean isDisabled();
@JSProperty
void setDisabled(boolean disabled);
@JSProperty
int getMaxLength();
@JSProperty
void setMaxLength(int maxLength);
@JSProperty
String getName();
@JSProperty
void setName(String name);
@JSProperty
boolean isReadOnly();
@JSProperty
void setReadOnly(boolean readOnly);
@JSProperty
int getSize();
@JSProperty
void setSize(int size);
@JSProperty
String getType();
@JSProperty
void setType(String type);
@JSProperty
String getValue();
@JSProperty
void setValue(String value);
}

View File

@ -0,0 +1,63 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.dom.html;
import org.teavm.jso.JSProperty;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface HTMLOptionElement extends HTMLElement {
@JSProperty
boolean isDisabled();
@JSProperty
void setDisabled(boolean disabled);
@JSProperty
String getLabel();
@JSProperty
void setLabel(String label);
@JSProperty
boolean isDefaultSelected();
@JSProperty
void setDefaultSelected(boolean defaultSelected);
@JSProperty
boolean isSelected();
@JSProperty
void setSelected(boolean selected);
@JSProperty
String getValue();
@JSProperty
void setValue(String value);
@JSProperty
String getText();
@JSProperty
void setText(String text);
@JSProperty
int getIndex();
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.dom.html;
import org.teavm.jso.JSIndexer;
import org.teavm.jso.JSProperty;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface HTMLOptionsCollection extends HTMLCollection {
@Override
HTMLOptionElement item(int index);
@Override
HTMLOptionElement namedItem(String name);
@JSIndexer
void set(int index, HTMLOptionElement element);
void add(HTMLOptionElement element, HTMLElement before);
void add(HTMLOptionElement element, int before);
void add(HTMLOptionElement element);
void remove(int index);
@JSProperty
int getSelectedIndex();
@JSProperty
void setSelectedIndex(int selectedIndex);
}

View File

@ -0,0 +1,63 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.dom.html;
import org.teavm.jso.JSProperty;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface HTMLSelectElement extends HTMLElement {
@JSProperty
boolean isDisabled();
@JSProperty
void setDisabled(boolean disabled);
@JSProperty
boolean isMultiple();
@JSProperty
void setMultiple(boolean multiple);
@JSProperty
HTMLOptionsCollection getOptions();
@JSProperty
String getName();
@JSProperty
void setName(String name);
@JSProperty
int getSize();
@JSProperty
void setSize(int size);
@JSProperty
int getSelectedIndex();
@JSProperty
void setSelectedIndex(int selectedIndex);
@JSProperty
String getValue();
@JSProperty
void setValue(String value);
}

View File

@ -76,6 +76,39 @@
<targetDirectory>${project.build.directory}/javascript/matrix</targetDirectory>
</configuration>
</execution>
<execution>
<id>generate-datetime</id>
<goals>
<goal>build-javascript</goal>
</goals>
<phase>process-classes</phase>
<configuration>
<minifying>false</minifying>
<mainClass>org.teavm.samples.DateTime</mainClass>
<targetDirectory>${project.build.directory}/javascript/datetime</targetDirectory>
<properties>
<java.util.Locale.available>en_US,en_GB,ru_RU,ru_UA,nl_NL,nl_BE</java.util.Locale.available>
</properties>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/teavm-demos.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>

View File

@ -0,0 +1,24 @@
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>teavm-demos</id>
<formats>
<format>zip</format>
</formats>
<files>
<file>
<source>src/main/resources/datetime.html</source>
<outputDirectory>/</outputDirectory>
</file>
<file>
<source>${project.build.directory}/javascript/datetime/classes.js</source>
<outputDirectory>/</outputDirectory>
<destName>datetime.js</destName>
</file>
<file>
<source>${project.build.directory}/javascript/datetime/runtime.js</source>
<outputDirectory>/</outputDirectory>
</file>
</files>
</assembly>

View File

@ -0,0 +1,77 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.samples;
import java.util.Date;
import java.util.Locale;
import org.teavm.dom.browser.TimerHandler;
import org.teavm.dom.browser.Window;
import org.teavm.dom.events.Event;
import org.teavm.dom.events.EventListener;
import org.teavm.dom.html.HTMLDocument;
import org.teavm.dom.html.HTMLInputElement;
import org.teavm.dom.html.HTMLOptionElement;
import org.teavm.dom.html.HTMLSelectElement;
import org.teavm.jso.JS;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class DateTime {
private static Window window = (Window)JS.getGlobal();
private static HTMLDocument document = window.getDocument();
private static Date currentDate;
public static void main(String[] args) {
fillLocales();
window.setInterval(new TimerHandler() {
@Override
public void onTimer() {
updateCurrentTime();
}
}, 250);
}
private static void fillLocales() {
final HTMLSelectElement localeElem = (HTMLSelectElement)document.getElementById("locale");
for (Locale locale : Locale.getAvailableLocales()) {
HTMLOptionElement option = (HTMLOptionElement)document.createElement("option");
option.setValue(locale.toString());
option.setLabel(locale.getDisplayName(Locale.getDefault()));
localeElem.getOptions().add(option);
}
localeElem.addEventListener("change", new EventListener() {
@Override public void handleEvent(Event evt) {
// Don't do anything
}
});
}
private static void updateCurrentTime() {
setCurrentTime(new Date());
}
private static void setCurrentTime(Date date) {
currentDate = date;
updateCurrentTimeText();
}
private static void updateCurrentTimeText() {
HTMLInputElement timeElem = (HTMLInputElement)document.getElementById("current-time");
timeElem.setValue(currentDate.toString());
}
}

View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<title>Localized date & time demo application</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<script src="runtime.js" type="text/javascript"></script>
<script src="datetime.js" type="text/javascript"></script>
</head>
<body onload="main()">
<div>
<label for="locale">Pick a locale:</label>
<select id="locale" size="1"></select>
</div>
<div>
<label for="current-time">Current time is:</label>
<input type="text" id="current-time" readonly>
</div>
<div>
<label for="field">Pick a field:</label>
<select id="field" size="1">
<option value="era">Era</option>
<option value="year">Year</option>
<option value="month">Month</option>
<option value="week-of-year">Week of year</option>
<option value="week-of-month">Week of month</option>
<option value="date">Date</option>
<option value="day-of-year">Day of year</option>
<option value="day-of-week">Day of week</option>
<option value="am-pm">AM/PM</option>
<option value="hour">Hour</option>
<option value="hour-of-day">Hour of day</option>
<option value="minute">Minute</option>
<option value="second">Second</option>
<option value="zone-offset">Zone offset</option>
</select>
</div>
<div>
<label for="field-value">Field value is:</label>
<input type="text" id="field-value" readonly>
</div>
</body>
</html>