diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py index 80ca0ad17e..9a8afb8edf 100755 --- a/.github/scripts/generate-quality-report.py +++ b/.github/scripts/generate-quality-report.py @@ -776,12 +776,53 @@ def main() -> None: "EQ_ALWAYS_FALSE", "SBSC_USE_STRINGBUFFER_CONCATENATION", "SIC_INNER_SHOULD_BE_STATIC", - "EQ_DOESNT_OVERRIDE_EQUALS" + "EQ_DOESNT_OVERRIDE_EQUALS", + "CO_COMPARETO_INCORRECT_FLOATING", + "DL_SYNCHRONIZATION_ON_SHARED_CONSTANT", + "DLS_DEAD_LOCAL_STORE", + "DM_NUMBER_CTOR", + "DMI_INVOKING_TOSTRING_ON_ARRAY", + "EC_NULL_ARG", + "EC_UNRELATED_TYPES_USING_POINTER_EQUALITY", + "EQ_GETCLASS_AND_CLASS_CONSTANT", + "EQ_UNUSUAL", + "ES_COMPARING_STRINGS_WITH_EQ", + "FI_EMPTY", + "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", + "DM_GC", + "CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE", + "BC_UNCONFIRMED_CAST", + "BC_UNCONFIRMED_CAST_OF_RETURN_VALUE", + "CN_IDIOM_NO_SUPER_CALL", + "DM_BOOLEAN_CTOR", + "DM_EXIT", + "EI_EXPOSE_REP", + "EI_EXPOSE_REP2", + "EI_EXPOSE_STATIC_REP2", + "EQ_COMPARETO_USE_OBJECT_EQUALS", + "MS_EXPOSE_REP", + "NM_CONFUSING", + "NO_NOTIFY_NOT_NOTIFYALL", + "NP_BOOLEAN_RETURN_NULL", + "REFLC_REFLECTION_MAY_INCREASE_ACCESSIBILITY_OF_CLASS", + "UI_INHERITANCE_UNSAFE_GETRESOURCE", + "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", + "UW_UNCOND_WAIT", + "SIC_INNER_SHOULD_BE_STATIC_ANON" } + + def _is_exempt(f: Finding) -> bool: + loc = f.path or f.location or "" + if f.rule == "SA_FIELD_SELF_ASSIGNMENT" and "InfBlocks.java" in loc: + return True + if f.rule == "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD" and "TarEntry.java" in loc: + return True + return False + + violations = [ f for f in spotbugs.findings - if f.rule in forbidden_rules - and not (f.rule == "SA_FIELD_SELF_ASSIGNMENT" and "InfBlocks.java" in f.location) + if f.rule in forbidden_rules and not _is_exempt(f) ] if violations: print("\n❌ Build failed due to forbidden SpotBugs violations:") diff --git a/.github/workflows/designer.yml b/.github/workflows/designer.yml index 8f82d6c11d..a31f22a7a0 100644 --- a/.github/workflows/designer.yml +++ b/.github/workflows/designer.yml @@ -39,6 +39,7 @@ jobs: - name: Build core dependencies run: | + xvfb-run -a ant -noinput -buildfile Ports/CLDC11/build.xml jar xvfb-run -a ant -noinput -buildfile Ports/JavaSE/build.xml jar xvfb-run -a ant -noinput -buildfile Ports/JavaSEWithSVGSupport/build.xml jar xvfb-run -a ant -noinput -buildfile CodenameOne/build.xml jar diff --git a/CodenameOne/nbproject/project.properties b/CodenameOne/nbproject/project.properties index 9b85c92082..21be55749e 100644 --- a/CodenameOne/nbproject/project.properties +++ b/CodenameOne/nbproject/project.properties @@ -28,7 +28,7 @@ dist.jar=${dist.dir}/CodenameOne.jar dist.javadoc.dir=${dist.dir}/javadoc endorsed.classpath= excludes= -file.reference.corevm.jar=../../cn1-binaries/corevm.jar +file.reference.corevm.jar=../Ports/CLDC11/dist/CLDC11.jar includes=** jar.compress=false javac.classpath=\ @@ -76,4 +76,4 @@ source.encoding=windows-1252 src.dir=src test.src.dir=test endorsed.classpath.cmd.line.arg=-bootclasspath ${file.reference.corevm.jar} -codenameone.dir=../../CodenameOne \ No newline at end of file +codenameone.dir=../../CodenameOne diff --git a/CodenameOne/src/com/codename1/capture/Capture.java b/CodenameOne/src/com/codename1/capture/Capture.java index 70f02cb14d..4b65da9637 100644 --- a/CodenameOne/src/com/codename1/capture/Capture.java +++ b/CodenameOne/src/com/codename1/capture/Capture.java @@ -74,7 +74,7 @@ public static boolean hasCamera() { * @param response a callback Object to retrieve the file path * @throws RuntimeException if this feature failed or unsupported on the platform */ - public static void capturePhoto(ActionListener response) { + public static void capturePhoto(ActionListener response) { Display.getInstance().capturePhoto(response); } @@ -193,7 +193,7 @@ public static String capturePhoto(int width, int height) { * @param response a callback Object to retrieve the file path * @throws RuntimeException if this feature failed or unsupported on the platform */ - public static void captureAudio(ActionListener response) { + public static void captureAudio(ActionListener response) { Display.getInstance().captureAudio(response); } @@ -210,7 +210,7 @@ public static void captureAudio(ActionListener response) { * @throws RuntimeException if this feature failed or unsupported on the platform * @since 7.0 */ - public static void captureAudio(MediaRecorderBuilder recorderOptions, ActionListener response) { + public static void captureAudio(MediaRecorderBuilder recorderOptions, ActionListener response) { Display.getInstance().captureAudio(recorderOptions, response); } @@ -224,7 +224,7 @@ public static void captureAudio(MediaRecorderBuilder recorderOptions, ActionList * @param response a callback Object to retrieve the file path * @since 7.0 */ - public static void captureVideo(VideoCaptureConstraints constraints, ActionListener response) { + public static void captureVideo(VideoCaptureConstraints constraints, ActionListener response) { Display.getInstance().captureVideo(constraints, response); } @@ -241,11 +241,11 @@ public static void captureVideo(VideoCaptureConstraints constraints, ActionListe * @throws RuntimeException if this feature failed or unsupported on the platform * @see #captureVideo(com.codename1.capture.VideoCaptureConstraints, com.codename1.ui.events.ActionListener) */ - public static void captureVideo(ActionListener response) { + public static void captureVideo(ActionListener response) { Display.getInstance().captureVideo(response); } - static class CallBack implements ActionListener, Runnable { + static class CallBack implements ActionListener, Runnable { String url; private boolean completed; private int targetWidth = -1; @@ -259,7 +259,7 @@ public void actionPerformed(ActionEvent evt) { } completed = true; synchronized (this) { - this.notify(); + this.notifyAll(); } } @@ -267,7 +267,10 @@ public void run() { while (!completed) { synchronized (this) { try { - this.wait(); + // we need to recheck the condition within the synchronized block (double locking) + if(!completed) { + this.wait(); + } } catch (InterruptedException ex) { } } diff --git a/CodenameOne/src/com/codename1/capture/VideoCaptureConstraints.java b/CodenameOne/src/com/codename1/capture/VideoCaptureConstraints.java index aeb632f8ba..4ef2ffc6ce 100644 --- a/CodenameOne/src/com/codename1/capture/VideoCaptureConstraints.java +++ b/CodenameOne/src/com/codename1/capture/VideoCaptureConstraints.java @@ -190,7 +190,7 @@ private String getMaxFileSizeString() { @Override public boolean equals(Object obj) { - if (obj.getClass() == VideoCaptureConstraints.class) { + if (obj instanceof VideoCaptureConstraints) { VideoCaptureConstraints c = (VideoCaptureConstraints) obj; return c.preferredHeight == preferredHeight && c.preferredWidth == preferredWidth && diff --git a/CodenameOne/src/com/codename1/charts/ChartComponent.java b/CodenameOne/src/com/codename1/charts/ChartComponent.java index bbeee84efa..18a4aeb3bd 100644 --- a/CodenameOne/src/com/codename1/charts/ChartComponent.java +++ b/CodenameOne/src/com/codename1/charts/ChartComponent.java @@ -208,7 +208,7 @@ public class ChartComponent extends Component { * @param chart The chart to be displayed in this component. */ public ChartComponent(AbstractChart chart) { - setUIID("ChartComponent"); + setUIIDFinal("ChartComponent"); this.chart = chart; if (chart != null && chart instanceof XYChart) { XYChart xyChart = (XYChart) chart; diff --git a/CodenameOne/src/com/codename1/charts/views/BubbleChart.java b/CodenameOne/src/com/codename1/charts/views/BubbleChart.java index 384073567a..f5770b75bc 100644 --- a/CodenameOne/src/com/codename1/charts/views/BubbleChart.java +++ b/CodenameOne/src/com/codename1/charts/views/BubbleChart.java @@ -27,17 +27,17 @@ import java.util.List; -/** - * Displays series of {@link XYValueSeries} entries as proportional bubbles on - * top of an {@link XYChart} plot. - *

- * Combine the chart with an {@link XYMultipleSeriesDataset} that contains one - * or more {@link XYValueSeries} instances and supply an - * {@link XYMultipleSeriesRenderer}. The resulting {@code BubbleChart} can be - * wrapped in a {@link com.codename1.charts.ChartComponent} to embed it inside a - * Codename One UI. - */ -public class BubbleChart extends XYChart { +/** + * Displays series of {@link XYValueSeries} entries as proportional bubbles on + * top of an {@link XYChart} plot. + *

+ * Combine the chart with an {@link XYMultipleSeriesDataset} that contains one + * or more {@link XYValueSeries} instances and supply an + * {@link XYMultipleSeriesRenderer}. The resulting {@code BubbleChart} can be + * wrapped in a {@link com.codename1.charts.ChartComponent} to embed it inside a + * Codename One UI. + */ +public class BubbleChart extends XYChart { /** The constant to identify this chart type. */ public static final String TYPE = "Bubble"; /** The legend shape width. */ @@ -66,8 +66,8 @@ public BubbleChart(XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer ren * @param canvas the canvas to paint to * @param paint the paint to be used for drawing * @param points the array of points to be used for drawing the series - * @param seriesRenderer the series renderer - * @param yAxisValue the minimum value of the y axis + * @param renderer the series renderer + * @param yAxisValue the minimum value of the y-axis * @param seriesIndex the index of the series currently being drawn * @param startIndex the start index of the rendering points */ diff --git a/CodenameOne/src/com/codename1/charts/views/LineChart.java b/CodenameOne/src/com/codename1/charts/views/LineChart.java index 6ab5310c0c..8c5703be36 100644 --- a/CodenameOne/src/com/codename1/charts/views/LineChart.java +++ b/CodenameOne/src/com/codename1/charts/views/LineChart.java @@ -349,7 +349,8 @@ public void drawLegendShape(Canvas canvas, SimpleSeriesRenderer renderer, float * @param renderer the series renderer */ public boolean isRenderPoints(SimpleSeriesRenderer renderer) { - return ((XYSeriesRenderer) renderer).getPointStyle() != PointStyle.POINT; + return renderer instanceof XYSeriesRenderer && + ((XYSeriesRenderer) renderer).getPointStyle() != PointStyle.POINT; } /** diff --git a/CodenameOne/src/com/codename1/charts/views/ScatterChart.java b/CodenameOne/src/com/codename1/charts/views/ScatterChart.java index 0150f2dc02..6f9e1d68a1 100644 --- a/CodenameOne/src/com/codename1/charts/views/ScatterChart.java +++ b/CodenameOne/src/com/codename1/charts/views/ScatterChart.java @@ -26,15 +26,15 @@ import java.util.List; -/** - * Renders discrete X/Y points without connecting lines. - *

- * Configure the marker style through {@link XYSeriesRenderer#setPointStyle} and - * related options on the {@link XYMultipleSeriesRenderer}. As with other - * charts, wrap the instance in a {@link com.codename1.charts.ChartComponent} to - * place it on a form. - */ -public class ScatterChart extends XYChart { +/** + * Renders discrete X/Y points without connecting lines. + *

+ * Configure the marker style through {@link XYSeriesRenderer#setPointStyle} and + * related options on the {@link XYMultipleSeriesRenderer}. As with other + * charts, wrap the instance in a {@link com.codename1.charts.ChartComponent} to + * place it on a form. + */ +public class ScatterChart extends XYChart { /** The constant to identify this chart type. */ public static final String TYPE = "Scatter"; /** The default point shape size. */ @@ -203,7 +203,8 @@ public int getLegendShapeWidth(int seriesIndex) { */ public void drawLegendShape(Canvas canvas, SimpleSeriesRenderer renderer, float x, float y, int seriesIndex, Paint paint) { - if (((XYSeriesRenderer) renderer).isFillPoints()) { + if (renderer instanceof XYSeriesRenderer && + ((XYSeriesRenderer) renderer).isFillPoints()) { paint.setStyle(Style.FILL); } else { paint.setStyle(Style.STROKE); diff --git a/CodenameOne/src/com/codename1/cloud/CloudException.java b/CodenameOne/src/com/codename1/cloud/CloudException.java deleted file mode 100644 index 23aa22f088..0000000000 --- a/CodenameOne/src/com/codename1/cloud/CloudException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. - */ -package com.codename1.cloud; - -/** - * Thrown in case of a server error or failure in connection - * - * @author Shai Almog - * @deprecated the cloud storage API is no longer supported, we recommend switching to a solution such as parse4cn1 - */ -public class CloudException extends Exception { - private final int errorCode; - - CloudException(int errorCode) { - super("Cloud exception " + errorCode); - this.errorCode = errorCode; - } - - CloudException(int errorCode, String message) { - super("Cloud exception: " + message); - this.errorCode = errorCode; - } - - /** - * Returns the error code for the cloud exception, see the cloud storage for return codes - * - * @return the error code - */ - public int getErrorCode() { - return errorCode; - } -} diff --git a/CodenameOne/src/com/codename1/cloud/CloudImageProperty.java b/CodenameOne/src/com/codename1/cloud/CloudImageProperty.java deleted file mode 100644 index 99ffad9642..0000000000 --- a/CodenameOne/src/com/codename1/cloud/CloudImageProperty.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. - */ -package com.codename1.cloud; - -import com.codename1.components.ReplaceableImage; -import com.codename1.io.CacheMap; -import com.codename1.io.ConnectionRequest; -import com.codename1.io.NetworkManager; -import com.codename1.ui.EncodedImage; -import com.codename1.ui.Image; -import com.codename1.ui.util.ImageIO; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Hashtable; - -/** - * A custom property that converts a cloud file id value to an image - * that is cached locally asynchronously. - * - * @author Shai Almog - * @deprecated the cloud storage API is no longer supported, we recommend switching to a solution such as parse4cn1 - */ -public class CloudImageProperty implements CustomProperty { // PMD Fix: UnnecessarySemicolon removed stray delimiter - private static CacheMap cloudImageCache; - private final String idProperty; - private final EncodedImage placeholderImage; - private final Hashtable inProgress = new Hashtable(); - - /** - * Create an image property for the given id that will hold the place holder image - * while downloading the actual image - * - * @param idProperty the id - * @param placeholderImage placeholder shown while id is downloaded - */ - public CloudImageProperty(String idProperty, EncodedImage placeholderImage) { - this.idProperty = idProperty; - this.placeholderImage = placeholderImage; - } - - private CacheMap getCache() { - if (cloudImageCache == null) { - cloudImageCache = new CacheMap("CN1CIP$"); - } - return cloudImageCache; - } - - /** - * {@inheritDoc} - */ - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - CloudImageProperty that = (CloudImageProperty) o; - - if (idProperty != null ? !idProperty.equals(that.idProperty) : that.idProperty != null) { - return false; - } - if (placeholderImage != null ? !placeholderImage.equals(that.placeholderImage) : that.placeholderImage != null) { - return false; - } - - return true; - } - - /** - * {@inheritDoc} - */ - public int hashCode() { - int result = idProperty != null ? idProperty.hashCode() : 0; - result = 31 * result + (placeholderImage != null ? placeholderImage.hashCode() : 0); - return result; - } - - /** - * {@inheritDoc} - */ - public Object propertyValue(CloudObject obj, String propertyName) { - final String key = (String) obj.getObject(idProperty); - if (key == null) { - return placeholderImage; - } - Image image = (Image) getCache().get(key); - if (image == null) { - ReplaceableImage r = inProgress.get(key); - if (r != null) { - return r; - } - final ReplaceableImage rp = ReplaceableImage.create(placeholderImage); - inProgress.put(key, rp); - ConnectionRequest cr = new CloudImageRequest(rp, key); - cr.setPost(false); - cr.setUrl(CloudStorage.getInstance().getUrlForCloudFileId(key)); - NetworkManager.getInstance().addToQueue(cr); - return rp; - } - return image; - } - - private class CloudImageRequest extends ConnectionRequest { - private EncodedImage e; - private final ReplaceableImage rp; - private final String key; - - public CloudImageRequest(ReplaceableImage rp, String key) { - this.rp = rp; - this.key = key; - } - - protected void readResponse(InputStream input) throws IOException { - e = EncodedImage.create(input); - if (e.getWidth() != placeholderImage.getWidth() || e.getHeight() != placeholderImage.getHeight()) { - ImageIO io = ImageIO.getImageIO(); - if (io != null) { - ByteArrayOutputStream bo = new ByteArrayOutputStream(); - io.save(new ByteArrayInputStream(e.getImageData()), bo, ImageIO.FORMAT_JPEG, placeholderImage.getWidth(), placeholderImage.getHeight(), 0.9f); - e = EncodedImage.create(bo.toByteArray()); - } - } - } - - protected void postResponse() { - rp.replace(e); - getCache().put(key, e); - inProgress.remove(key); - } - - /** - * {@inheritDoc} - */ - public boolean equals(Object o) { - return super.equals(o); - } - - /** - * {@inheritDoc} - */ - public int hashCode() { - return super.hashCode(); - } - } - -} diff --git a/CodenameOne/src/com/codename1/cloud/CloudListModel.java b/CodenameOne/src/com/codename1/cloud/CloudListModel.java deleted file mode 100644 index b337c087eb..0000000000 --- a/CodenameOne/src/com/codename1/cloud/CloudListModel.java +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. - */ -package com.codename1.cloud; - -import com.codename1.io.CacheMap; -import com.codename1.io.Log; -import com.codename1.io.Util; -import com.codename1.ui.events.DataChangedListener; -import com.codename1.ui.events.SelectionListener; -import com.codename1.ui.list.ListModel; -import com.codename1.ui.util.EventDispatcher; - -import java.util.Hashtable; -import java.util.Vector; - -/** - * Seamlessly creates a cloud based searchable list model - * - * @author Shai Almog - * @deprecated the cloud storage API is no longer supported, we recommend switching to a solution such as parse4cn1 - */ -public class CloudListModel implements ListModel { - - private final String type; - private final int visibilityScope; - private int batchSize = 20; - private final int keyBatchSize = 1000; - private int sortProperty; - private final boolean ascending; - private Object[] keys; - private final EventDispatcher modelListener = new EventDispatcher(); - private final EventDispatcher selectionListener = new EventDispatcher(); - private int selectedIndex = 0; - private Hashtable loadingPlaceholder; - private CacheMap cache; - private int index; - private String queryValue; - - /** - * Refreshes items in the current view every 30 seconds when repainted - */ - private int refreshRateMillis = 30000; - - private long[] lastRefresh; - - /** - * Creates a list model that shows all the cloud elements that have the given key matching - * the given value at the visibility scope listed below. This model can be further narrowed - * down by using the filter functionality below.
- * This is effectively equivalent to issuing a queryEquals method, however it polls in batches - * and caches data as needed. - * - * @param type the type of object shown on the list - * @param visibilityScope the scope of the list (CloudObject.ACCESS_* values) - * @param sortProperty the index by which we sort the entries, 0 for unsorted - * @param ascending whether the sort is ascending or descending - */ - public CloudListModel(String type, int visibilityScope, int sortProperty, boolean ascending) { - this.type = type; - this.visibilityScope = visibilityScope; - this.sortProperty = sortProperty; - this.ascending = ascending; - init(); - } - - /** - * Creates a list model that shows all the cloud elements that have the given key matching - * the given value at the visibility scope listed below. This model can be further narrowed - * down by using the filter functionality below.
- * This is effectively equivalent to issuing a queryEquals method, however it polls in batches - * and caches data as needed. - * - * @param type the type of object shown on the list - * @param visibilityScope the scope of the list (CloudObject.ACCESS_* values) - * @param index the index by which we limit the entries - * @param queryValue the queryValue for the given index - * @param ascending whether the sort is ascending or descending - */ - public CloudListModel(String type, int visibilityScope, int index, String queryValue, boolean ascending) { - this.type = type; - this.visibilityScope = visibilityScope; - this.index = index; - this.queryValue = queryValue; - this.ascending = ascending; - init(); - } - - private void init() { - cache = new CacheMap(type + visibilityScope + sortProperty); - cache.setCacheSize(30); - cache.setStorageCacheSize(100); - cache.setAlwaysStore(true); - loadingPlaceholder = new Hashtable(); - loadingPlaceholder.put("Line1", "Loading..."); - loadingPlaceholder.put("Placeholder", Boolean.TRUE); - - // remove loading placeholders that might have gotten stuck in cache - Vector v = cache.getKeysInCache(); - int cacheSize = v.size(); - for (int iter = 0; iter < cacheSize; iter++) { - Object k = v.elementAt(iter); - Object e = cache.get(k); - if (e instanceof Hashtable) { - Hashtable h = (Hashtable) e; - if (h.containsKey("Placeholder")) { - cache.delete(k); - } - } - } - } - - /** - * Refreshes the list from the server, this method blocks the EDT until - * completion. - */ - public void refresh() { - Vector vec = cache.getKeysInCache(); - int s = vec.size(); - Vector cld = new Vector(); - for (int iter = 0; iter < s; iter++) { - Object key = vec.elementAt(iter); - Object val = cache.get(key); - if (val != null && val instanceof CloudObject) { - cld.addElement(val); - } - } - if (cld.size() > 0) { - CloudObject[] obj = new CloudObject[cld.size()]; - cld.toArray(obj); - int response = CloudStorage.getInstance().refresh(obj); - if (response != CloudStorage.RETURN_CODE_SUCCESS) { - onError(new CloudException(response)); - } else { - // persist the object to the cache and fire the list model change - for (int iter = 0; iter < obj.length; iter++) { - cache.put(obj[iter].getCloudId(), obj[iter]); - } - modelListener.fireDataChangeEvent(0, getSize()); - } - } - } - - /** - * Flushes the cache which might be essential when adding new elements - */ - public void clearCache() { - cache.clearAllCache(); - } - - /** - * Returns the elements cached within the implementation - * - * @return the cache size - */ - public int getCacheSize() { - return cache.getCacheSize(); - } - - /** - * Sets the size of the local cache - * - * @param elements elements to store in cache - */ - public void setCacheSize(int elements) { - cache.setCacheSize(elements); - } - - /** - * Returns the elements cached within the persistent storage - * - * @return the cache size - */ - public int getStorageCacheSize() { - return cache.getCacheSize(); - } - - /** - * Sets the size of the cache in persistent storage - * - * @param elements elements to store in cache - */ - public void setStorageCacheSize(int elements) { - cache.setStorageCacheSize(elements); - } - - /** - * When loading the element from the cloud a placehold is shown to indicate to the user that the content isn't fully - * here - * - * @return the element shown when content isn't available for a specific entry - */ - public Hashtable getLoadingPlaceholder() { - return loadingPlaceholder; - } - - /** - * When loading the element from the cloud a placehold is shown to indicate to the user that the content isn't fully - * here - * - * @param loadingPlaceholder shows blank content to the user - */ - public void setLoadingPlaceholder(Hashtable loadingPlaceholder) { - this.loadingPlaceholder = loadingPlaceholder; - this.loadingPlaceholder.put("Placeholder", Boolean.TRUE); - } - - /** - * Returns the batch size fetched from the server - * - * @return the size - */ - public int getBatchSize() { - return batchSize; - } - - /** - * Updates the number of elements fetched from the server in a single batch - * - * @param batchSize the batch size - */ - public void setBatchSize(int batchSize) { - this.batchSize = batchSize; - } - - /** - * {@inheritDoc} - */ - public Object getItemAt(int index) { - if (keys != null && index < keys.length && index > -1) { - Object value = cache.get(keys[index]); - if (value == null) { - value = getLoadingPlaceholder(); - fillUpList(index); - } else { - if (value instanceof CloudObject) { - long time = System.currentTimeMillis(); - if (lastRefresh[index] + refreshRateMillis < time) { - CloudObject cld = (CloudObject) value; - if (cld.getLastModified() > lastRefresh[index]) { - lastRefresh[index] = cld.getLastModified(); - } else { - if (cld.getStatus() == CloudObject.STATUS_COMMITTED) { - CloudStorage.getInstance().refreshAsync(cld); - } - } - } - } - } - return value; - } - - return null; - } - - private void fillUpList(final int startIndex) { - final int len = Math.min(batchSize, keys.length - startIndex); - Vector request = new Vector(); - for (int iter = startIndex; iter < startIndex + len; iter++) { - if (cache.get(keys[iter]) == null) { - cache.put(keys[iter], loadingPlaceholder); - request.addElement((String) keys[iter]); - } - } - CloudResponse resp = new CloudResponse() { - public void onSuccess(CloudObject[] returnValue) { - for (int iter = 0; iter < returnValue.length; iter++) { - cache.put(returnValue[iter].getCloudId(), returnValue[iter]); - } - modelListener.fireDataChangeEvent(startIndex, len); - } - - public void onError(CloudException err) { - CloudListModel.this.onError(err); - } - }; - String[] arr = new String[request.size()]; - request.toArray(arr); - CloudStorage.getInstance().fetch(arr, resp); - } - - private void newRefreshRate() { - lastRefresh = new long[keys.length]; - long t = System.currentTimeMillis(); - for (int iter = 0; iter < lastRefresh.length; iter++) { - lastRefresh[iter] = t; - } - } - - /** - * {@inheritDoc} - */ - public int getSize() { - if (keys == null) { - keys = (Object[]) cache.get("keyIndex"); - if (keys == null) { - keys = new Object[0]; - } else { - newRefreshRate(); - } - - // refresh the key list even if we have them in cache since this might have changed - CloudResponse resp = new CloudResponse() { - private int responseOffset; - - public void onSuccess(String[] returnValue) { - if (responseOffset == 0) { - keys = returnValue; - } else { - String[] k = new String[keys.length + returnValue.length]; - Util.mergeArrays(keys, returnValue, k); - keys = k; - } - newRefreshRate(); - cache.put("keyIndex", keys); - modelListener.fireDataChangeEvent(-1, DataChangedListener.ADDED); - - // we might have more data, send another request - if (returnValue.length == keyBatchSize) { - responseOffset = keys.length; - if (index > 0) { - CloudStorage.getInstance().queryEqualsKeys(type, index, queryValue, keys.length, keyBatchSize, visibilityScope, this); - } else { - CloudStorage.getInstance().querySortedKeys(type, sortProperty, ascending, keys.length, keyBatchSize, visibilityScope, this); - } - } - } - - public void onError(CloudException err) { - CloudListModel.this.onError(err); - } - }; - if (index > 0) { - CloudStorage.getInstance().queryEqualsKeys(type, index, queryValue, 0, keyBatchSize, visibilityScope, resp); - } else { - CloudStorage.getInstance().querySortedKeys(type, sortProperty, ascending, 0, keyBatchSize, visibilityScope, resp); - } - } - return keys.length; - } - - /** - * Invoked when a cloud error occurs - * - * @param err the exception representing the error in cloud communications - */ - protected void onError(CloudException err) { - Log.e(err); - } - - /** - * {@inheritDoc} - */ - public int getSelectedIndex() { - return selectedIndex; - } - - /** - * {@inheritDoc} - */ - public void setSelectedIndex(int index) { - int oldIndex = selectedIndex; - this.selectedIndex = index; - selectionListener.fireSelectionEvent(oldIndex, selectedIndex); - } - - /** - * {@inheritDoc} - */ - public void addDataChangedListener(DataChangedListener l) { - modelListener.addListener(l); - } - - /** - * {@inheritDoc} - */ - public void removeDataChangedListener(DataChangedListener l) { - modelListener.removeListener(l); - } - - /** - * {@inheritDoc} - */ - public void addSelectionListener(SelectionListener l) { - selectionListener.addListener(l); - } - - /** - * {@inheritDoc} - */ - public void removeSelectionListener(SelectionListener l) { - selectionListener.removeListener(l); - } - - /** - * Notice this method does NOT commit the data, after committing the data - * the cache MUST be cleared! - * {@inheritDoc} - */ - public void addItem(Object item) { - CloudObject cld = (CloudObject) item; - if (cld.getType() == null) { - cld.setType(type); - } - CloudStorage.getInstance().save(cld); - } - - /** - * Notice this method does NOT commit the data, after committing the data - * the cache MUST be cleared! - * {@inheritDoc} - */ - public void removeItem(int index) { - Object o = getItemAt(index); - if (o instanceof CloudObject) { - CloudObject cld = (CloudObject) o; - CloudStorage.getInstance().delete(cld); - } - } - - /** - * Indicates the rate in milliseconds in which to poll the server for the current data - * of elements that are visible at the moment. - * - * @return the refreshRateMillis - */ - public int getRefreshRateMillis() { - return refreshRateMillis; - } - - /** - * Indicates the rate in milliseconds in which to poll the server for the current data - * of elements that are visible at the moment. - * - * @param refreshRateMillis the refreshRateMillis to set - */ - public void setRefreshRateMillis(int refreshRateMillis) { - this.refreshRateMillis = refreshRateMillis; - } - -} diff --git a/CodenameOne/src/com/codename1/cloud/CloudObject.java b/CodenameOne/src/com/codename1/cloud/CloudObject.java deleted file mode 100644 index f7e1536a89..0000000000 --- a/CodenameOne/src/com/codename1/cloud/CloudObject.java +++ /dev/null @@ -1,808 +0,0 @@ -/* - * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. - */ -package com.codename1.cloud; - -import com.codename1.io.Externalizable; -import com.codename1.io.Util; -import com.codename1.ui.Component; -import com.codename1.ui.Container; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.Enumeration; -import java.util.Hashtable; - -/** - * A cloud object can be persisted to the cloud or locally - * it is a set of key/value pairs that can be either strings - * or numbers. There is a 512 character limit on string length! - * Notice: keys starting with CN1 are reserved for internal usage! - * - * @author Shai Almog - * @deprecated the cloud storage API is no longer supported, we recommend switching to a solution such as parse4cn1 - */ -public final class CloudObject implements Externalizable { - /** - * Indicates the state of the current object, a new object never persisted - */ - public static final int STATUS_NEW = 0; - - /** - * Indicates the state of the current object, an object that is in sync with the database as far as - * the client code is aware (the client code doesn't check!) - */ - public static final int STATUS_COMMITTED = 1; - - /** - * Indicates the state of the current object, a locally modified object that wasn't committed yet - */ - public static final int STATUS_MODIFIED = 2; - - /** - * Indicates the state of the current object, an object in the process of committing - */ - public static final int STATUS_COMMIT_IN_PROGRESS = 3; - - /** - * Indicates the state of the current object, an object that is in the process of deletion - */ - public static final int STATUS_DELETE_IN_PROGRESS = 4; - - /** - * Indicates the state of the current object, a deleted object - */ - public static final int STATUS_DELETED = 5; - - /** - * Indicates the state of the current object, an object in the process of refresh - */ - public static final int STATUS_REFRESH_IN_PROGRESS = 6; - - /** - * A world visible/modifiable object! - */ - public static final int ACCESS_PUBLIC = 1; - - /** - * A world visible object! Can only be modified by its creator. - */ - public static final int ACCESS_PUBLIC_READ_ONLY = 2; - - /** - * An application visible/modifiable object! - */ - public static final int ACCESS_APPLICATION = 3; - - /** - * An application scope readable object! Can only be modified by its creator - */ - public static final int ACCESS_APPLICATION_READ_ONLY = 4; - - /** - * An object that can only be viewed or modified by its creator - */ - public static final int ACCESS_PRIVATE = 5; - - - /** - * Changes to the bound property won't be reflected into the bound cloud object until commit binding is invoked - */ - public static final int BINDING_DEFERRED = 1; - - /** - * Changes to the bound property will be reflected instantly into the cloud object - */ - public static final int BINDING_IMMEDIATE = 2; - - /** - * Changes to the bound property will be reflected instantly into the cloud object and the object would - * be saved immediately (not committed!). - */ - public static final int BINDING_AUTO_SAVE = 3; - - private static final Hashtable custom = new Hashtable(); - private Hashtable values = new Hashtable(); - private Hashtable deferedValues; - - private String cloudId; - private long lastModified; - private int status; - private boolean owner = true; - private int accessPermissions = ACCESS_PRIVATE; - - /** - * Default constructor for externalization purposes only! - */ - public CloudObject() { - } - - /** - * Constructor - * - * @param type the type of the object - */ - public CloudObject(String type) { - values.put(CloudStorage.TYPE_FIELD, type); - } - - /** - * Create an object with different permissions settings - * - * @param type the type of the object - * @param permissions one of the ACCESS_* values - */ - public CloudObject(String type, int permissions) { - accessPermissions = permissions; - values.put(CloudStorage.TYPE_FIELD, type); - } - - CloudObject(int permissions) { - accessPermissions = permissions; - } - - /** - * Install a custom property on the given property name - * - * @param key the key on which to install the custom property - * @param cp the custom property implementation - */ - public static void setCustomProperty(String key, CustomProperty cp) { - if (cp == null) { - custom.remove(key); - } else { - custom.put(key, cp); - } - } - - /** - * Returns one of the status constants in this class - * - * @return the status of the object against the cloud - */ - public int getStatus() { - return status; - } - - void setStatus(int s) { - status = s; - } - - Hashtable getValues() { - return values; - } - - void setValues(Hashtable values) { - this.values = values; - } - - /** - * Returns the type of the object - * - * @return the type of the object - */ - public String getType() { - return getString(CloudStorage.TYPE_FIELD); - } - - /** - * Set the type of the object - * - * @param type the type of the field - */ - public void setType(String type) { - setString(CloudStorage.TYPE_FIELD, type); - } - - /** - * Only indexed values can be queried and sorted - * - * @param index the index which must be a value between 1 and 10. - * @param value the value for the given index - */ - public void setIndexString(int index, String value) { - if (index > 10 || index < 1) { - throw new IllegalArgumentException("Invalid index: " + index); - } - setString(CloudStorage.INDEX_FIELD + index, value); - } - - /** - * Returns the index value for the given index number - * - * @param index the index number - * @return the value of this entry for that index as a String - */ - public String getIndexString(int index) { - return getString(CloudStorage.INDEX_FIELD + index); - } - - /** - * Only indexed values can be queried and sorted - * - * @param index the index which must be a value between 1 and 10. - * @param value the value for the given index - */ - public void setIndexLong(int index, long value) { - if (index > 10 || index < 1) { - throw new IllegalArgumentException("Invalid index: " + index); - } - setLong(CloudStorage.INDEX_FIELD + index, value); - } - - /** - * Returns the index value for the given index number - * - * @param index the index number - * @return the value of this entry for that index as a Long value - */ - public Long getIndexLong(int index) { - return getLong(CloudStorage.INDEX_FIELD + index); - } - - /** - * Only indexed values can be queried and sorted - * - * @param index the index which must be a value between 1 and 10. - * @param value the value for the given index - */ - public void setIndexDouble(int index, double value) { - if (index > 10 || index < 1) { - throw new IllegalArgumentException("Invalid index: " + index); - } - setDouble(CloudStorage.INDEX_FIELD + index, value); - } - - /** - * Returns the index value for the given index number - * - * @param index the index number - * @return the value of this entry for that index as a Double value - */ - public Double getIndexDouble(int index) { - return getDouble(CloudStorage.INDEX_FIELD + index); - } - - /** - * Returns true if this object is owned by me or is world writeable - * - * @return ownership status - */ - public boolean isOwner() { - return owner; - } - - /** - * The object id is a unique key that allows you to find an object that was persisted in the - * store (a primary key). When it is null the object is effectively unsynchronized! - * - * @return the object id or null for an object that isn't fully persisted yet - */ - public String getCloudId() { - return cloudId; - } - - void setCloudId(String cloudId) { - this.cloudId = cloudId; - } - - /** - * Indicates the last modification date for the object - * - * @return the last modification date - */ - public long getLastModified() { - return lastModified; - } - - void setLastModified(long lastModified) { - this.lastModified = lastModified; - } - - /** - * Allows us to extract an object from the cloud object without knowing its type in advance - * or whether it exists - * - * @param key the key for the object - * @return the value of the object - */ - public Object getObject(String key) { - Object o = values.get(key); - if (o == null) { - CustomProperty cp = custom.get(key); - if (cp != null) { - return cp.propertyValue(this, key); - } - } - return o; - } - - /** - * Sets a value that can be no more than 512 characters - * - * @param key the key for the given value - * @param value the value - */ - public void setString(String key, String value) { - if (!owner) { - throw new RuntimeException("Read only object, you are not the owner"); - } - if (value == null) { - values.remove(key); - return; - } - if (value.length() > 512) { - throw new IllegalArgumentException("String too long!"); - } - status = STATUS_MODIFIED; - values.put(key, value); - } - - /** - * Returns the value for the given key - * - * @param key the key - * @return a string value - */ - public String getString(String key) { - return (String) getObject(key); - } - - /** - * Delete an entry within the object - * - * @param key the key to remove from the object - */ - public void remove(String key) { - values.remove(key); - } - - - /** - * Sets a value - * - * @param key the key for the given value - * @param value the value - */ - public void setLong(String key, long value) { - if (!owner) { - throw new RuntimeException("Read only object, you are not the owner"); - } - status = STATUS_MODIFIED; - values.put(key, Long.valueOf(value)); // PMD Fix: PrimitiveWrapperInstantiation avoid constructor - } - - /** - * Sets a value - * - * @param key the key for the given value - * @param value the value - */ - public void setLong(String key, Long value) { - if (!owner) { - throw new RuntimeException("Read only object, you are not the owner"); - } - status = STATUS_MODIFIED; - values.put(key, value); - } - - /** - * Returns the value for the given key - * - * @param key the key - * @return a long value - */ - public Long getLong(String key) { - Object o = getObject(key); - if (o instanceof Integer) { - return Long.valueOf(((Integer) o).intValue()); // PMD Fix: PrimitiveWrapperInstantiation avoid constructor - } - return (Long) o; - } - - /** - * Sets a value - * - * @param key the key for the given value - * @param value the value - */ - public void setInteger(String key, int value) { - if (!owner) { - throw new RuntimeException("Read only object, you are not the owner"); - } - status = STATUS_MODIFIED; - values.put(key, Integer.valueOf(value)); // PMD Fix: PrimitiveWrapperInstantiation avoid constructor - } - - /** - * Sets a value - * - * @param key the key for the given value - * @param value the value - */ - public void setInteger(String key, Integer value) { - if (!owner) { - throw new RuntimeException("Read only object, you are not the owner"); - } - status = STATUS_MODIFIED; - values.put(key, value); - } - - /** - * Returns the value for the given key - * - * @param key the key - * @return a value - */ - public Integer getInteger(String key) { - Object o = getObject(key); - if (o instanceof Long) { - return Integer.valueOf((int) ((Long) o).longValue()); // PMD Fix: PrimitiveWrapperInstantiation avoid constructor - } - return (Integer) o; - } - - /** - * Sets a value - * - * @param key the key for the given value - * @param value the value - */ - public void setDouble(String key, double value) { - if (!owner) { - throw new RuntimeException("Read only object, you are not the owner"); - } - status = STATUS_MODIFIED; - values.put(key, Double.valueOf(value)); // PMD Fix: PrimitiveWrapperInstantiation avoid constructor - } - - /** - * Sets a value - * - * @param key the key for the given value - * @param value the value - */ - public void setDouble(String key, Double value) { - if (!owner) { - throw new RuntimeException("Read only object, you are not the owner"); - } - status = STATUS_MODIFIED; - values.put(key, value); - } - - /** - * Returns the value for the given key - * - * @param key the key - * @return a value - */ - public Double getDouble(String key) { - return (Double) getObject(key); - } - - /** - * Sets a value - * - * @param key the key for the given value - * @param value the value - */ - public void setFloat(String key, float value) { - if (!owner) { - throw new RuntimeException("Read only object, you are not the owner"); - } - status = STATUS_MODIFIED; - values.put(key, Float.valueOf(value)); // PMD Fix: PrimitiveWrapperInstantiation avoid constructor - } - - /** - * Sets a value - * - * @param key the key for the given value - * @param value the value - */ - public void setFloat(String key, Float value) { - if (!owner) { - throw new RuntimeException("Read only object, you are not the owner"); - } - status = STATUS_MODIFIED; - values.put(key, value); - } - - /** - * Returns the value for the given key - * - * @param key the key - * @return a value - */ - public Float getFloat(String key) { - Object o = getObject(key); - if (o instanceof Double) { - return Float.valueOf(((Double) o).floatValue()); // PMD Fix: PrimitiveWrapperInstantiation avoid constructor - } - return (Float) o; - } - - /** - * Sets a value - * - * @param key the key for the given value - * @param value the value - */ - public void setBoolean(String key, boolean value) { - if (!owner) { - throw new RuntimeException("Read only object, you are not the owner"); - } - status = STATUS_MODIFIED; - values.put(key, Boolean.valueOf(value)); // PMD Fix: PrimitiveWrapperInstantiation avoid constructor - } - - /** - * Sets a value - * - * @param key the key for the given value - * @param value the value - */ - public void setBoolean(String key, Boolean value) { - if (!owner) { - throw new RuntimeException("Read only object, you are not the owner"); - } - status = STATUS_MODIFIED; - values.put(key, value); - } - - /** - * Returns the value for the given key - * - * @param key the key - * @return a value - */ - public Boolean getBoolean(String key) { - return (Boolean) getObject(key); - } - - /** - * {@inheritDoc} - */ - public int getVersion() { - return 1; - } - - /** - * {@inheritDoc} - */ - public void externalize(DataOutputStream out) throws IOException { - Util.writeUTF(cloudId, out); - out.writeBoolean(owner); - out.writeByte(getAccessPermissions()); - out.writeLong(lastModified); - out.writeInt(status); - Util.writeObject(values, out); - } - - - public String getObjectId() { - return "CloudObject"; - } - - /** - * {@inheritDoc} - */ - public void internalize(int version, DataInputStream in) throws IOException { - cloudId = Util.readUTF(in); - owner = in.readBoolean(); - accessPermissions = in.readByte(); - lastModified = in.readLong(); - status = in.readInt(); - values = (Hashtable) Util.readObject(in); - } - - /** - * The access permissions for an object can only be changed for an object in which - * the current user is the owner - * - * @return the accessPermissions - */ - public int getAccessPermissions() { - return accessPermissions; - } - - /** - * {@inheritDoc} - */ - public boolean equals(Object o) { - if (!(o instanceof CloudObject)) { - return false; - } - CloudObject cl = (CloudObject) o; - if (cloudId == null && cl.cloudId == null) { - return values.equals(cl.values); - } - if (cloudId == null || cl.cloudId == null) { - return false; - } - return cloudId.equals(cl.cloudId); - } - - /** - * {@inheritDoc} - */ - public int hashCode() { - if (cloudId != null) { - return cloudId.hashCode(); - } - return 0; - } - - /** - * Binds a UI tree to the cloud object so its values automatically update in the cloud object - * - * @param ui the component tree to bind - * @param defer bind settings whether to defer the binding which requires developers to explicitly commit - * the binding to perform the changes - * @param objectLead if set to true the UI property is initialized from values in the CloudObject, if false - * the cloud object property is initialized from the UI - */ - public void bindTree(Container ui, int defer, boolean objectLead) { - int componentCount = ui.getComponentCount(); - for (int iter = 0; iter < componentCount; iter++) { - Component c = ui.getComponentAt(iter); - if (c instanceof Container) { - bindTree((Container) c, defer, objectLead); - continue; - } - - String bind = c.getCloudBoundProperty(); - if (bind != null && bind.length() > 0) { - String attributeName = c.getCloudDestinationProperty(); - if (attributeName != null) { - bindProperty(c, bind, attributeName, defer, objectLead); - } - } - } - } - - /** - * Clears the binding to this component tree - * - * @param ui the container whose children might be bound - */ - public void unbindTree(Container ui) { - int componentCount = ui.getComponentCount(); - for (int iter = 0; iter < componentCount; iter++) { - Component c = ui.getComponentAt(iter); - if (c instanceof Container) { - unbindTree((Container) c); - continue; - } - - String bind = c.getCloudBoundProperty(); - if (bind != null && bind.length() > 0) { - String attributeName = c.getCloudDestinationProperty(); - if (attributeName != null) { - unbindProperty(c, bind); - } - } - } - } - - /** - * Binds a property value within the given component to this cloud object, this means that - * when the component changes the cloud object changes unless deferred. If the defer flag is - * false all changes are stored in a temporary location and only "committed" once commitBindings() - * is invoked. - * - * @param cmp the component to bind - * @param propertyName the name of the property in the bound component - * @param attributeName the key within the cloud object - * @param defer bind settings whether to defer the binding which requires developers to explicitly commit - * the binding to perform the changes - * @param objectLead if set to true the UI property is initialized from values in the CloudObject, if false - * the cloud object property is initialized from the UI - */ - public void bindProperty(Component cmp, final String propertyName, final String attributeName, final int defer, boolean objectLead) { - if (objectLead) { - Object val = values.get(attributeName); - Object cmpVal = cmp.getBoundPropertyValue(propertyName); - if (val == null) { - if (cmpVal != null) { - cmp.setBoundPropertyValue(propertyName, null); - } - } else { - if (!(val.equals(cmpVal))) { - cmp.setBoundPropertyValue(propertyName, val); - } - } - } else { - Object val = values.get(attributeName); - Object cmpVal = cmp.getBoundPropertyValue(propertyName); - if (cmpVal == null) { - if (val != null) { - values.remove(attributeName); - status = STATUS_MODIFIED; - } - } else { - if (val == null || !(val.equals(cmpVal))) { - values.put(attributeName, cmpVal); - status = STATUS_MODIFIED; - } - } - } - BindTarget target = new BindTarget() { - public void propertyChanged(Component source, String propertyName, Object oldValue, Object newValue) { - switch (defer) { - case BINDING_DEFERRED: - if (deferedValues == null) { - deferedValues = new Hashtable(); - } - deferedValues.put(attributeName, newValue); - break; - case BINDING_IMMEDIATE: - values.put(attributeName, newValue); - status = STATUS_MODIFIED; - break; - case BINDING_AUTO_SAVE: - values.put(attributeName, newValue); - status = STATUS_MODIFIED; - CloudStorage.getInstance().save(CloudObject.this); - break; - default: - break; - } - } - }; - cmp.bindProperty(propertyName, target); - cmp.putClientProperty("CN1Bind" + propertyName, target); - } - - /** - * Releases the binding for the specific property name - * - * @param cmp the component - * @param propertyName the name of the property - */ - public void unbindProperty(Component cmp, String propertyName) { - BindTarget t = (BindTarget) cmp.getClientProperty("CN1Bind" + propertyName); - cmp.unbindProperty(propertyName, t); - } - - /** - * If deferred changes exist this method applies these changes to the data - */ - public void commitBinding() { - if (deferedValues != null && deferedValues.size() > 0) { - Enumeration en = deferedValues.keys(); - while (en.hasMoreElements()) { - Object k = en.nextElement(); - values.put(k, deferedValues.get(k)); - } - deferedValues = null; - } - } - - /** - * If deferred changes exist this method discards such values - */ - public void cancelBinding() { - deferedValues = null; - } -} diff --git a/CodenameOne/src/com/codename1/cloud/CloudPersona.java b/CodenameOne/src/com/codename1/cloud/CloudPersona.java deleted file mode 100644 index 25743064b2..0000000000 --- a/CodenameOne/src/com/codename1/cloud/CloudPersona.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. - */ -package com.codename1.cloud; - -/** - * A persona represents a user of the cloud, this is an optional feature that allows - * data to be limited to a specific user on the server side. - * - * @author Shai Almog - * @deprecated the cloud storage API is no longer supported, we recommend switching to a solution such as parse4cn1 - */ -public class CloudPersona { - private CloudPersona() { - } - - /** - * This method returns the currently logged in persona or a blank persona - * (token would be null) - * - * @return the current persona - */ - public static CloudPersona getCurrentPersona() { - return null; - - } - - /** - * Initializes the persona based on a token, since this method assumes binary transfer of a completed - * token the token isn't verified in any way and the user is considered logged in. - * - * @param token the token - */ - public static void createFromToken(String token) { - } - - /** - * Creates an anonymous persona that will be unique in the cloud, NEVER logout an anonymous user! - * - * @return false in case login failed e.g. due to bad network connection - */ - public static boolean createAnonymous() { - return false; - } - - /** - * Creates a new user if a user isn't occupying the given login already, - * if the user exists performs a login operation. - * - * @param login a user name - * @param password a password - * @return true if the login is successful false otherwise - */ - public static boolean createOrLogin(String login, String password) { - return false; - } - - /** - * Returns a unique login token that represents the current user and his password, while this login token shouldn't - * be user visible (it's a password too!) it can be transfered to a different device to give - * them both identical user role and joined access. - * - * @return a persona UID - */ - public String getToken() { - return null; - } - - /** - * Logs out the current user, notice that with an anonymous user this will effectively KILL all - * the data in the cloud! - */ - public void logout() { - } -} diff --git a/CodenameOne/src/com/codename1/cloud/CloudResponse.java b/CodenameOne/src/com/codename1/cloud/CloudResponse.java deleted file mode 100644 index 3d44f93ebb..0000000000 --- a/CodenameOne/src/com/codename1/cloud/CloudResponse.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. - */ -package com.codename1.cloud; - -/** - * Used as a callback for the asynchronous version of the cloud storage API, these methods - * are invoked on the EDT! - * - * @author Shai Almog - * @deprecated the cloud storage API is no longer supported, we recommend switching to a solution such as parse4cn1 - */ -public interface CloudResponse { - /** - * Invoked to return a value from the asynchronous version of the API - * - * @param returnValue the return value of the metho - */ - void onSuccess(T returnValue); // PMD Fix: UnnecessaryModifier removed - - /** - * Invoked if there was a server error - * - * @param err the exception containing the error details - */ - void onError(CloudException err); // PMD Fix: UnnecessaryModifier removed -} diff --git a/CodenameOne/src/com/codename1/cloud/CloudStorage.java b/CodenameOne/src/com/codename1/cloud/CloudStorage.java deleted file mode 100644 index bcd285b63e..0000000000 --- a/CodenameOne/src/com/codename1/cloud/CloudStorage.java +++ /dev/null @@ -1,578 +0,0 @@ -/* - * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. - */ -package com.codename1.cloud; - -import java.io.IOException; -import java.io.InputStream; - -/** - * The cloud storage class allows developers to use the Codename One cloud - * based storage API as a shared database for your application. The database - * will be visible only to a specific application (based on author/package - * definitions).
- * The calls to this class only become effective as a single batch when commit - * is sent. The commit can be synchronous or asynchronous.
- * Important due to the nature of the underlying object data store queries - * can only be performed against an indexed field of which there are 10 hardcoded - * indexes! Basic data is case sensitive and queries/sort will be performed in a case - * sensitive way! In order to work around this create a property with an identical - * name that contains the field as lower or upper case in order to query/sort - * against. - * - * @author Shai Almog - * @deprecated this API is targeted for removal due to changes in Google App Engine API support - */ -public class CloudStorage { // PMD Fix: UnusedPrivateField removed pendingRefreshes cache - /** - * Return code for methods in this class indicating a successful operation - */ - public static final int RETURN_CODE_SUCCESS = 0; - - /** - * Return code for methods in this class indicating a failure due to server side - * modification of an object (e.g. different user changed the object) - */ - public static final int RETURN_CODE_FAIL_OBJECT_MODIFIED = 1; - - /** - * Return code for methods in this class indicating a failure due to generic server side - * error - */ - public static final int RETURN_CODE_FAIL_SERVER_ERROR = 2; - - /** - * Return code for methods in this class indicating a failure due to exceeding - * server storage quotas - */ - public static final int RETURN_CODE_FAIL_QUOTA_EXCEEDED = 3; - - /** - * Return code for methods in this class indicating an empty queue - */ - public static final int RETURN_CODE_EMPTY_QUEUE = 4; - - /** - * Return code for methods in this class indicating a failure due to exceeding - * server storage quotas - */ - public static final int RETURN_CODE_FAIL_PERMISSION_VIOLATION = 5; - - /** - * Indicates the type of the field for queries and filtering - */ - static final String TYPE_FIELD = "CN1Type"; - - /** - * Indicates the index field prefix - */ - static final String INDEX_FIELD = "CN1Index"; - - private static CloudStorage INSTANCE; - - - private CloudStorage() { - } - - /** - * Creates an instance of the cloud storage object, only one instance should be used per application. - * This method is important since it may block to complete/cleanup a previous transaction that wasn't - * fully completed before exiting the application. - * - * @return the instance of the class - */ - public static CloudStorage getInstance() { - if (INSTANCE == null) { - INSTANCE = new CloudStorage(); - } - return INSTANCE; - } - - - /** - * Adds the given object to the save queue, the operation will only take place once committed - * - * @param object the object to save into the cloud, new objects are inserted. existing - * objects are updated - */ - public synchronized void save(CloudObject object) { - } - - /** - * Deletes the following object from the cloud storage upon commit - * - * @param cl the cloud object to delete - */ - public synchronized void delete(CloudObject cl) { - } - - /** - * Refresh the given objects with data from the server if they were modified on the server (this is the asynchronous - * version of the method). - * This operation executes immeditely without waiting for commit. - * - * @param objects objects to refresh - * @param response object for the response - */ - public void refresh(CloudObject[] objects, CloudResponse response) { - } - - /** - * Adds the given object to a set of refresh operations in which we don't - * really care if the operation is successful - * - * @param obj the object to refresh - */ - public void refreshAsync(CloudObject obj) { - } - - /** - * Refresh the given objects with data from the server if they were modified on the server. - * This operation executes immeditely without waiting for commit. - * - * @param objects objects to refresh - * @return status code matching the situation, one of: RETURN_CODE_SUCCESS, - * RETURN_CODE_FAIL_SERVER_ERROR - * @deprecated this feature is no longer supported - */ - public int refresh(CloudObject[] objects) { - return -1; - } - - /** - * Fetches the objects from the server. - * This operation executes immediately without waiting for commit. - * - * @param cloudIds the object id's to fetch - * @return the cloud objects or null if a server error occurred - * @throws CloudException thrown for a server side/connection error - */ - public CloudObject[] fetch(String[] cloudIds) throws CloudException { - throw new CloudException(-1); - } - - /** - * Fetches the objects from the server asynchronously. - * This operation executes immeditely without waiting for commit. - * - * @param cloudIds the object id's to fetch - * @param response returns the response from the server - * @return the cloud objects or null if a server error occurred - */ - public void fetch(String[] cloudIds, final CloudResponse response) { - } - - /** - * Performs a query to the server finding the objects where the key - * value is equal to the given value. - * This operation executes immeditely without waiting for commit. - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param page the page of responses (allows for paging) - * @param limit number of responses to fetch - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - * @return array of objects matching the query - * @throws CloudException thrown for a server side/connection error - */ - public CloudObject[] queryEquals(String type, int index, String value, int page, int limit, int visibilityScope) throws CloudException { - return null; - } - - /** - * Performs a query to the server finding the objects where the sort is equal to the given value. - * This operation executes immeditely without waiting for commit. - * - * @param type the object type - * @param index the index on which the sort is based - * @param ascending indicates if the sort order is ascending or descending - * @param page the page of responses (allows for paging) - * @param limit number of responses to fetch - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - * @return array of objects matching the query - * @throws CloudException thrown for a server side/connection error - */ - public CloudObject[] querySorted(String type, int index, boolean ascending, int page, int limit, int visibilityScope) throws CloudException { - return null; - } - - /** - * Performs a query to the server finding the objects where the sort is equal to the given value and returning - * the cloud key of these objects. - * This operation executes immeditely without waiting for commit. - * - * @param type the object type - * @param index the index on which the sort is based - * @param ascending indicates if the sort order is ascending or descending - * @param page the page of responses (allows for paging) - * @param limit number of responses to fetch - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - * @return the keys for the cloud objects matching the query - * @throws CloudException thrown for a server side/connection error - */ - public String[] querySortedKeys(String type, int index, boolean ascending, int page, int limit, int visibilityScope) throws CloudException { - return null; - } - - /** - * Equivalent to the standard query but just returns the keys matching the given query - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param page the page of responses (allows for paging) - * @param limit number of responses to fetch - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - * @return the keys for the cloud objects matching the query - * @throws CloudException thrown for a server side/connection error - */ - public String[] queryEqualsKeys(String type, int index, String value, int page, int limit, int visibilityScope) throws CloudException { - return null; - } - - /** - * Equivalent to the standard query but just returns the total count of entries that will be returned - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - * @return the number of elements - * @throws CloudException thrown for a server side/connection error - */ - public int queryEqualsCount(String type, int index, String value, int visibilityScope) throws CloudException { - return -1; - } - - /** - * Equivalent to the standard query but just returns the total count of entries that will be returned - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - * @return the number of elements - * @throws CloudException thrown for a server side/connection error - */ - public int queryGreaterThanCount(String type, int index, String value, int visibilityScope) throws CloudException { - return -1; - } - - /** - * Equivalent to the standard query but just returns the total count of entries that will be returned - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - * @return the number of elements - * @throws CloudException thrown for a server side/connection error - */ - public int queryLessThanCount(String type, int index, String value, int visibilityScope) throws CloudException { - return -1; - } - - /** - * Performs a query to the server finding the objects where the key - * value is greater than the given value. - * This operation executes immeditely without waiting for commit. - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param page the page of responses (allows for paging) - * @param limit number of responses to fetch - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - * @return array of objects matching the query - * @throws CloudException thrown for a server side/connection error - */ - public CloudObject[] queryGreaterThan(String type, int index, String value, int page, int limit, int visibilityScope) throws CloudException { - return null; - } - - /** - * Performs a query to the server finding the objects where the key - * value is smaller than the given value. - * This operation executes immeditely without waiting for commit. - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param page the page of responses (allows for paging) - * @param limit number of responses to fetch - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - * @return array of objects matching the query - * @throws CloudException thrown for a server side/connection error - */ - public CloudObject[] queryLessThan(String type, int index, String value, int page, int limit, int visibilityScope) throws CloudException { - return null; - } - - - /** - * Performs a query to the server finding the objects where the sort is equal to the given value. - * This operation executes immeditely without waiting for commit. - * - * @param type the object type - * @param index the index on which the sort is based - * @param ascending indicates if the sort order is ascending or descending - * @param page the page of responses (allows for paging) - * @param limit number of responses to fetch - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - */ - public void querySorted(String type, int index, boolean ascending, int page, int limit, int visibilityScope, CloudResponse response) { - } - - /** - * Performs a query to the server finding the objects where the key - * value is equal to the given value. - * This operation executes immeditely without waiting for commit. - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param page the page of responses (allows for paging) - * @param limit number of responses to fetch - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - */ - public void queryEquals(String type, int index, String value, int page, int limit, int visibilityScope, CloudResponse response) { - - } - - /** - * Equivalent to the standard query but just returns the total count of entries that will be returned - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - */ - public void queryEqualsCount(String type, int index, String value, int visibilityScope, CloudResponse response) { - } - - /** - * Equivalent to the standard query but just returns the total count of entries that will be returned - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - * @return the number of elements - */ - public void queryGreaterThanCount(String type, int index, String value, int visibilityScope, CloudResponse response) { - - } - - /** - * Performs a query to the server finding the objects where the sort is equal to the given value and returning - * the cloud key of these objects. - * This operation executes immeditely without waiting for commit. - * - * @param type the object type - * @param index the index on which the sort is based - * @param ascending indicates if the sort order is ascending or descending - * @param page the page of responses (allows for paging) - * @param limit number of responses to fetch - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - */ - public void querySortedKeys(String type, int index, boolean ascending, int page, int limit, int visibilityScope, CloudResponse response) { - - } - - /** - * Equivalent to the standard query but just returns the keys matching the given query - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param page the page of responses (allows for paging) - * @param limit number of responses to fetch - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - */ - public void queryEqualsKeys(String type, int index, String value, int page, int limit, int visibilityScope, CloudResponse response) { - - } - - /** - * Equivalent to the standard query but just returns the total count of entries that will be returned - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - */ - public void queryLessThanCount(String type, int index, String value, int visibilityScope, CloudResponse response) { - - } - - /** - * Performs a query to the server finding the objects where the key - * value is greater than the given value. - * This operation executes immeditely without waiting for commit. - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param page the page of responses (allows for paging) - * @param limit number of responses to fetch - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - */ - public void queryGreaterThan(String type, int index, String value, int page, int limit, int visibilityScope, CloudResponse response) { - } - - /** - * Performs a query to the server finding the objects where the key - * value is smaller than the given value. - * This operation executes immeditely without waiting for commit. - * - * @param type the object type - * @param index the index to query for the given value - * @param value the value of said index to include in the response object - * @param page the page of responses (allows for paging) - * @param limit number of responses to fetch - * @param visibilityScope indicates the scope in which to look as one of the - * CloudObject constants ACCESS_* - * @param response array of objects matching the query - */ - public void queryLessThan(String type, int index, String value, int page, int limit, int visibilityScope, CloudResponse response) { - } - - /** - * Allows uploading of images etc. to the cloud which can later on be referenced as URL's. - * - * @param mimeType the mimetype of the uploaded file - * @param file the URL of the local file - * @return an ID for the given file that can be used to delete the file or construct a URL of the file - * @throws CloudException in case of a server side error - * @throws IOException when a problem occurs with the file - * @deprecated this API is currently deprecated due to Googles cloud storage deprection - */ - public String uploadCloudFile(String mimeType, String file) throws CloudException, IOException { - return null; - } - - /** - * Allows uploading of images etc. to the cloud which can later on be referenced as URL's. - * - * @param mimeType the mimetype of the uploaded file - * @param filename a short name for the file uploaded (not a full path) - * @param data input stream from which to read the file - * @param dataSize the size in bytes of the input stream (this is essential for file upload to work on all devices!) - * @return an ID for the given file that can be used to delete the file or construct a URL of the file - * @throws CloudException in case of a server side error - * @throws IOException when a problem occurs with the file - * @deprecated this API is currently deprecated due to Googles cloud storage deprection - */ - public String uploadCloudFile(String mimeType, String filename, InputStream data, int dataSize) throws CloudException, IOException { - return null; - } - - - /** - * Deletes a file from the cloud storage - * - * @param fileId the file id to delete - * @return true if the operation was successful - * @deprecated this API is currently deprecated due to Googles cloud storage deprection - */ - public boolean deleteCloudFile(String fileId) { - return false; - } - - /** - * Deletes all the cloud files under this user, notice that this method - * is asynchronous and a background server process performs the actual deletion - * - * @deprecated this API is currently deprecated due to Googles cloud storage deprection - */ - public void deleteAllCloudFilesForUser() { - } - - /** - * Deletes all the cloud files before the given time stamp for the given - * development account. Notice that this method is meant for internal use - * and not for distributable apps since it includes your developer account. - * This method works in a background server process and returns immediately. - * - * @param timestamp the timestamp since epoch (as in System.currentTimemillis). - * @param developerAccount your developer email - * @param developerPassword your developer password - * @deprecated this API is currently deprecated due to Googles cloud storage deprection - */ - public void deleteAllCloudFilesBefore(long timestamp, String developerAccount, String developerPassword) { - } - - /** - * Converts a file id to a URL with which the file can be downloaded, notice that the file URL is world - * readable! - * - * @param fileId the file ID - * @return a URL that allows downloading the file - * @deprecated this API is currently deprecated due to Googles cloud storage deprection - */ - public String getUrlForCloudFileId(String fileId) { - return null; - } - - /** - * Commit works synchronously and returns one of the return codes above to indicate - * the status. - * - * @return status code from the constants in this class - */ - public synchronized int commit() { - return RETURN_CODE_EMPTY_QUEUE; - } - - /** - * A commit version that works asynchronously and returns one of the return codes above to indicate - * the status. - * - * @param response response code with status code from the constants in this class - */ - public void commit(CloudResponse response) { - } - - /** - * Cancels current pending changes - */ - public synchronized void rollback() { - } -} diff --git a/CodenameOne/src/com/codename1/cloud/CustomProperty.java b/CodenameOne/src/com/codename1/cloud/CustomProperty.java deleted file mode 100644 index ba79c511cb..0000000000 --- a/CodenameOne/src/com/codename1/cloud/CustomProperty.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Codename One designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Codename One through http://www.codenameone.com/ if you - * need additional information or have any questions. - */ -package com.codename1.cloud; - -/** - * Allows adding a custom property to cloud objects, this effectively - * allows to simulate missing properties or create properties that - * don't represent a database entry (e.g. fullName which can be - * comprised of joining the firstname and surname together).
- * Important: The custom property only takes effect if there is no value - * assigned to the given property! - * - * @author Shai Almog - * @deprecated the cloud storage API is no longer supported, we recommend switching to a solution such as parse4cn1 - */ -public interface CustomProperty { - /** - * Returns a property value for the given property name - * - * @param obj the cloud object - * @param propertyName the name of the property - * @return the property value - */ - Object propertyValue(CloudObject obj, String propertyName); // PMD Fix: UnnecessaryModifier removed -} diff --git a/CodenameOne/src/com/codename1/cloud/package.html b/CodenameOne/src/com/codename1/cloud/package.html deleted file mode 100644 index d979667e4f..0000000000 --- a/CodenameOne/src/com/codename1/cloud/package.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - -

- Provides cloud related services such as storage, binding widgets to the cloud seamlessly so they can be persisted - easily. This package makes use of features available for pro accounts. -

- - diff --git a/CodenameOne/src/com/codename1/components/Accordion.java b/CodenameOne/src/com/codename1/components/Accordion.java index 912846105c..92d643038d 100644 --- a/CodenameOne/src/com/codename1/components/Accordion.java +++ b/CodenameOne/src/com/codename1/components/Accordion.java @@ -81,7 +81,7 @@ public Accordion() { FontImage.createMaterial(FontImage.MATERIAL_KEYBOARD_ARROW_RIGHT, UIManager.getInstance().getComponentStyle(uiidOpenCloseIcon)); this.openIcon = FontImage.createMaterial(FontImage.MATERIAL_KEYBOARD_ARROW_DOWN, UIManager.getInstance().getComponentStyle(uiidOpenCloseIcon)); - setScrollableY(true); + super.setScrollableY(true); } /** @@ -420,7 +420,7 @@ class AccordionContent extends Container { private String topUiid = uiidHeader; public AccordionContent(Component header, final Component body) { - setUIID(uiidBackGroundItem); + setUIIDFinal(uiidBackGroundItem); setLayout(new BorderLayout()); this.body = body; this.header = header; diff --git a/CodenameOne/src/com/codename1/components/Ads.java b/CodenameOne/src/com/codename1/components/Ads.java index 6dcd956dda..7314c50ffe 100644 --- a/CodenameOne/src/com/codename1/components/Ads.java +++ b/CodenameOne/src/com/codename1/components/Ads.java @@ -24,6 +24,7 @@ import com.codename1.ads.AdsService; import com.codename1.io.ConnectionRequest; +import com.codename1.io.NetworkEvent; import com.codename1.ui.Component; import com.codename1.ui.Container; import com.codename1.ui.Display; @@ -76,7 +77,7 @@ public class Ads extends Container implements HTMLCallback { * Default constructor for GUI builder */ public Ads() { - setUIID("Ads"); + setUIIDFinal("Ads"); setLayout(new BorderLayout()); // special case for iOS. It seems the ad component can inadvertedly steal focus from @@ -218,20 +219,7 @@ public String getAd() { */ public void setAd(String ad) { this.ad = ad; - HTMLComponent html = new HTMLComponent(new AsyncDocumentRequestHandlerImpl() { - - protected ConnectionRequest createConnectionRequest(DocumentInfo docInfo, IOCallback callback, Object[] response) { - ConnectionRequest req = super.createConnectionRequest(docInfo, callback, response); - req.setFailSilently(true); - req.addResponseCodeListener(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - //do nothing, just make sure the html won't throw an error - } - }); - return req; - } - }); + HTMLComponent html = new HTMLComponent(new MyAsyncDocumentRequestHandlerImpl()); html.setSupressExceptions(true); html.setHTMLCallback(this); html.setBodyText("
" + ad + "
"); @@ -585,4 +573,21 @@ public String setPropertyValue(String name, Object value) { } return super.setPropertyValue(name, value); } + + private static class MyAsyncDocumentRequestHandlerImpl extends AsyncDocumentRequestHandlerImpl { + + protected ConnectionRequest createConnectionRequest(DocumentInfo docInfo, IOCallback callback, Object[] response) { + ConnectionRequest req = super.createConnectionRequest(docInfo, callback, response); + req.setFailSilently(true); + req.addResponseCodeListener(new NetworkEventActionListener()); + return req; + } + + private static class NetworkEventActionListener implements ActionListener { + + public void actionPerformed(NetworkEvent evt) { + //do nothing, just make sure the html won't throw an error + } + } + } } diff --git a/CodenameOne/src/com/codename1/components/ButtonList.java b/CodenameOne/src/com/codename1/components/ButtonList.java index c549cbd690..94c1575615 100644 --- a/CodenameOne/src/com/codename1/components/ButtonList.java +++ b/CodenameOne/src/com/codename1/components/ButtonList.java @@ -99,18 +99,20 @@ public abstract class ButtonList extends Container implements DataChangedListene private final java.util.List onReady = new ArrayList(); private String cellUIID; private java.util.List decorators; + private final boolean allowMultipleSelection; /** * Creates a new ButtonList. * * @param model The options. Each will be represented by a button. + * @param allowMultipleSelection indicates that multiple selection is allowed or not */ - public ButtonList(ListModel model) { - if (model instanceof DefaultListModel && isAllowMultipleSelection()) { + protected ButtonList(ListModel model, boolean allowMultipleSelection) { + this.allowMultipleSelection = allowMultipleSelection; + if (model instanceof DefaultListModel && allowMultipleSelection) { ((DefaultListModel) model).setMultiSelectionMode(true); } setModel(model); - } /** @@ -130,7 +132,7 @@ protected void onReady(Runnable r) { * This should be called by the concrete implementation once it is ready to generate the * buttons. */ - protected void fireReady() { + protected final void fireReady() { ready = true; for (Runnable r : onReady) { r.run(); @@ -160,7 +162,7 @@ public ListModel getModel() { return model; } - public void setModel(ListModel model) { + public final void setModel(ListModel model) { if (model != this.model) { if (this.model != null) { this.model.removeDataChangedListener(this); @@ -183,14 +185,6 @@ public void run() { } } - /** - * Returns true for lists that allow multiple selection. {@link CheckBoxList}, and {@link SwitchList} support multiple selection. - * {@link RadioButtonList} does not. - * - * @return - */ - public abstract boolean isAllowMultipleSelection(); - /** * Creates a new button for this list. Should be implemented by subclasses to create the correct kind of button. * @@ -238,7 +232,7 @@ public void refresh() { int len = model.getSize(); for (int i = 0; i < len; i++) { Component b = createComponent(model.getItemAt(i)); - if (isAllowMultipleSelection()) { + if (allowMultipleSelection) { if (Arrays.binarySearch(selectedIndices, i) >= 0) { setSelected(b, true); } @@ -329,7 +323,7 @@ public void dataChanged(int status, int index) { // Called when the selection is changed in the model @Override public void selectionChanged(int oldSelected, int newSelected) { - if (isAllowMultipleSelection()) { + if (allowMultipleSelection) { if (oldSelected < 0 && newSelected >= 0) { Component cmp = newSelected < getComponentCount() ? getComponentAt(newSelected) : null; if (cmp != null) { diff --git a/CodenameOne/src/com/codename1/components/CheckBoxList.java b/CodenameOne/src/com/codename1/components/CheckBoxList.java index 6d301bbcde..b76f070838 100644 --- a/CodenameOne/src/com/codename1/components/CheckBoxList.java +++ b/CodenameOne/src/com/codename1/components/CheckBoxList.java @@ -57,15 +57,10 @@ public void actionPerformed(ActionEvent evt) { }; public CheckBoxList(MultipleSelectionListModel model) { - super(model); + super(model, true); fireReady(); } - - @Override - public boolean isAllowMultipleSelection() { - return true; - } - + @Override protected Component createButton(Object model) { return new CheckBox(String.valueOf(model)); diff --git a/CodenameOne/src/com/codename1/components/FileTree.java b/CodenameOne/src/com/codename1/components/FileTree.java index 7783ec8aa8..328edc7e4a 100644 --- a/CodenameOne/src/com/codename1/components/FileTree.java +++ b/CodenameOne/src/com/codename1/components/FileTree.java @@ -38,7 +38,7 @@ public class FileTree extends Tree { */ public FileTree() { super(new FileTreeModel(true)); - setUIID("FileTree"); + setUIIDFinal("FileTree"); } /** @@ -46,7 +46,7 @@ public FileTree() { */ public FileTree(FileTreeModel model) { super(model); - setUIID("FileTree"); + setUIIDFinal("FileTree"); } protected String childToDisplayLabel(Object child) { diff --git a/CodenameOne/src/com/codename1/components/FloatingActionButton.java b/CodenameOne/src/com/codename1/components/FloatingActionButton.java index d31a66a08a..41db265443 100644 --- a/CodenameOne/src/com/codename1/components/FloatingActionButton.java +++ b/CodenameOne/src/com/codename1/components/FloatingActionButton.java @@ -112,7 +112,7 @@ protected FloatingActionButton(char icon, String text, String uiid, float size) setIcon(image); setText(""); this.text = text; - setUIID(uiid); + setUIIDFinal(uiid); Style all = getAllStyles(); all.setAlignment(CENTER); updateBorder(); @@ -125,7 +125,7 @@ private FloatingActionButton(String text) { super.setText(text); rectangle = true; shadowOpacity = 0; - setUIID("Badge"); + setUIIDFinal("Badge"); updateBorder(); isBadge = true; } @@ -370,15 +370,7 @@ public void released(int x, int y) { int oldTint = f.getTintColor(); f.setTintColor(0); d.setBlurBackgroundRadius(-1); - d.addShowListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { - for (Component c : con) { - c.setY(con.getHeight()); - c.setVisible(true); - } - con.animateLayout(200); - } - }); + d.addShowListener(new ReleaseActionListener(con)); showPopupDialog(d); f.setTintColor(oldTint); for (FloatingActionButton next : subMenu) { @@ -404,12 +396,7 @@ protected Container createPopupContent(List fabs) { c.add(BorderLayout.CENTER, FlowLayout.encloseRight(txt)); c.add(BorderLayout.EAST, next); con.add(c); - txt.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { - next.pressed(); - next.released(); - } - }); + txt.addActionListener(new CreatePopupContentActionListener(next)); } return con; } @@ -438,4 +425,32 @@ public void setFloatingActionTextUIID(String floatingActionTextUIID) { this.floatingActionTextUIID = floatingActionTextUIID; } + private static class ReleaseActionListener implements ActionListener { + private final Container con; + + public ReleaseActionListener(Container con) { + this.con = con; + } + + public void actionPerformed(ActionEvent evt) { + for (Component c : con) { + c.setY(con.getHeight()); + c.setVisible(true); + } + con.animateLayout(200); + } + } + + private static class CreatePopupContentActionListener implements ActionListener { + private final FloatingActionButton next; + + public CreatePopupContentActionListener(FloatingActionButton next) { + this.next = next; + } + + public void actionPerformed(ActionEvent evt) { + next.pressed(); + next.released(); + } + } } \ No newline at end of file diff --git a/CodenameOne/src/com/codename1/components/FloatingHint.java b/CodenameOne/src/com/codename1/components/FloatingHint.java index 6b4ca8cde7..d80225c13d 100644 --- a/CodenameOne/src/com/codename1/components/FloatingHint.java +++ b/CodenameOne/src/com/codename1/components/FloatingHint.java @@ -65,12 +65,7 @@ public FloatingHint(final TextArea tf) { this.tf = tf; Container content = new Container(new BorderLayout()); add(content); - hintButton = new Button(tf.getHint()) { - @Override - protected boolean shouldRenderComponentSelection() { - return true; - } - }; + hintButton = new HintButtonImpl(tf); hintLabel = new Label(tf.getHint()); tf.setHint(""); hintButton.setFocusable(false); @@ -87,11 +82,7 @@ protected boolean shouldRenderComponentSelection() { add(BorderLayout.north(hintButton). add(BorderLayout.CENTER, hintLabel)); - hintButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { - tf.startEditingAsync(); - } - }); + hintButton.addActionListener(new HintButtonActionListener(tf)); if (tf.getText() == null || tf.getText().length() == 0) { hintButton.setVisible(false); } else { @@ -170,4 +161,26 @@ protected void initComponent() { } + private static class HintButtonImpl extends Button { + public HintButtonImpl(TextArea tf) { + super(tf.getHint()); + } + + @Override + protected boolean shouldRenderComponentSelection() { + return true; + } + } + + private static class HintButtonActionListener implements ActionListener { + private final TextArea tf; + + public HintButtonActionListener(TextArea tf) { + this.tf = tf; + } + + public void actionPerformed(ActionEvent evt) { + tf.startEditingAsync(); + } + } } diff --git a/CodenameOne/src/com/codename1/components/ImageViewer.java b/CodenameOne/src/com/codename1/components/ImageViewer.java index ae12c803dc..ed04b48857 100644 --- a/CodenameOne/src/com/codename1/components/ImageViewer.java +++ b/CodenameOne/src/com/codename1/components/ImageViewer.java @@ -117,8 +117,8 @@ public class ImageViewer extends Component { */ public ImageViewer() { setFocusable(true); - setUIID("ImageViewer"); - $(this).selectAllStyles().setBgTransparency(0x0); + setUIIDFinal("ImageViewer"); + getAllStyles().setBgTransparency(0x0); } /** @@ -779,7 +779,7 @@ public Image getImage() { * * @param image the image to set */ - public void setImage(Image image) { + public final void setImage(Image image) { if (this.image != image) { panPositionX = 0.5f; panPositionY = 0.5f; diff --git a/CodenameOne/src/com/codename1/components/InfiniteProgress.java b/CodenameOne/src/com/codename1/components/InfiniteProgress.java index c6544d1a36..80017f54fe 100644 --- a/CodenameOne/src/com/codename1/components/InfiniteProgress.java +++ b/CodenameOne/src/com/codename1/components/InfiniteProgress.java @@ -101,7 +101,7 @@ public class InfiniteProgress extends Component { * Default constructor to define the UIID */ public InfiniteProgress() { - setUIID("InfiniteProgress"); + setUIIDFinal("InfiniteProgress"); } /** diff --git a/CodenameOne/src/com/codename1/components/InteractionDialog.java b/CodenameOne/src/com/codename1/components/InteractionDialog.java index c37c0b2ea9..afee7165cf 100644 --- a/CodenameOne/src/com/codename1/components/InteractionDialog.java +++ b/CodenameOne/src/com/codename1/components/InteractionDialog.java @@ -117,7 +117,7 @@ public InteractionDialog(String title, Layout l) { } private void init() { - setUIID("Dialog"); + setUIIDFinal("Dialog"); title.setUIID("DialogTitle"); contentPane.setUIID("DialogContentPane"); super.addComponent(BorderLayout.NORTH, titleArea); diff --git a/CodenameOne/src/com/codename1/components/MultiButton.java b/CodenameOne/src/com/codename1/components/MultiButton.java index 04c0166019..a388d23765 100644 --- a/CodenameOne/src/com/codename1/components/MultiButton.java +++ b/CodenameOne/src/com/codename1/components/MultiButton.java @@ -114,7 +114,7 @@ public MultiButton() { emblem.setUIID("Emblem"); icon.setUIID("Label"); setLeadComponent(emblem); - setUIID("MultiButton"); + setUIIDFinal("MultiButton"); Image i = UIManager.getInstance().getThemeImageConstant("defaultEmblemImage"); if (i != null) { emblem.setIcon(i); diff --git a/CodenameOne/src/com/codename1/components/OnOffSwitch.java b/CodenameOne/src/com/codename1/components/OnOffSwitch.java index e16fcc9def..adbe02931f 100644 --- a/CodenameOne/src/com/codename1/components/OnOffSwitch.java +++ b/CodenameOne/src/com/codename1/components/OnOffSwitch.java @@ -74,7 +74,7 @@ public class OnOffSwitch extends Container implements ActionSource { * Default constructor */ public OnOffSwitch() { - setUIID("OnOffSwitch"); + setUIIDFinal("OnOffSwitch"); initialize(); } diff --git a/CodenameOne/src/com/codename1/components/Progress.java b/CodenameOne/src/com/codename1/components/Progress.java index 9524171772..f82c2ae20e 100644 --- a/CodenameOne/src/com/codename1/components/Progress.java +++ b/CodenameOne/src/com/codename1/components/Progress.java @@ -43,7 +43,7 @@ * * @author Shai Almog */ -public class Progress extends Dialog implements ActionListener { +public class Progress extends Dialog implements ActionListener { private final ConnectionRequest request; private boolean disposeOnCompletion; private boolean autoShow; @@ -136,8 +136,7 @@ public void setDisposeOnCompletion(boolean disposeOnCompletion) { /** * {@inheritDoc} */ - public void actionPerformed(ActionEvent evt) { - NetworkEvent ev = (NetworkEvent) evt; + public void actionPerformed(NetworkEvent ev) { if (ev.getConnectionRequest() == request) { if (disposeOnCompletion && ev.getProgressType() == NetworkEvent.PROGRESS_TYPE_COMPLETED) { dispose(); diff --git a/CodenameOne/src/com/codename1/components/RSSReader.java b/CodenameOne/src/com/codename1/components/RSSReader.java index 556dab5f1e..0d154c3a80 100644 --- a/CodenameOne/src/com/codename1/components/RSSReader.java +++ b/CodenameOne/src/com/codename1/components/RSSReader.java @@ -90,7 +90,7 @@ public class RSSReader extends List { * Creates an rss reader instance */ public RSSReader() { - setUIID("RSSReader"); + setUIIDFinal("RSSReader"); setRenderer(new GenericListCellRenderer(createRendererContainer(), createRendererContainer())); addActionListener(new EventHandler()); } diff --git a/CodenameOne/src/com/codename1/components/RadioButtonList.java b/CodenameOne/src/com/codename1/components/RadioButtonList.java index 0e681e386e..b02eda6b24 100644 --- a/CodenameOne/src/com/codename1/components/RadioButtonList.java +++ b/CodenameOne/src/com/codename1/components/RadioButtonList.java @@ -40,7 +40,7 @@ public class RadioButtonList extends ButtonList { /** * Change listener added to individual radio buttons to keep them in sync with the model. */ - private final ActionListener changeListener = new ActionListener() { + private final ActionListener changeListener = new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { if (evt.getSource() instanceof RadioButton && contains((Component) evt.getSource())) { @@ -61,21 +61,10 @@ public void actionPerformed(ActionEvent evt) { * @param model The model that defines the options that the user can choose between. */ public RadioButtonList(ListModel model) { - super(model); + super(model, false); fireReady(); } - /** - * Returns false for RadioButtonList since only one radio button can be selected at a time. - * - * @return - */ - @Override - public boolean isAllowMultipleSelection() { - return false; - } - - @Override protected Component createButton(Object model) { return new RadioButton(String.valueOf(model)); diff --git a/CodenameOne/src/com/codename1/components/ScaleImageButton.java b/CodenameOne/src/com/codename1/components/ScaleImageButton.java index 0d0dad8b3a..11c8ed4345 100644 --- a/CodenameOne/src/com/codename1/components/ScaleImageButton.java +++ b/CodenameOne/src/com/codename1/components/ScaleImageButton.java @@ -49,7 +49,7 @@ public class ScaleImageButton extends Button { * Default constructor */ public ScaleImageButton() { - setUIID("ScaleImageButton"); + setUIIDFinal("ScaleImageButton"); setShowEvenIfBlank(true); getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT); getAllStyles().setBgTransparency(255); @@ -61,7 +61,7 @@ public ScaleImageButton() { * @param i image */ public ScaleImageButton(Image i) { - setUIID("ScaleImageButton"); + setUIIDFinal("ScaleImageButton"); setShowEvenIfBlank(true); getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT); getAllStyles().setBgTransparency(255); diff --git a/CodenameOne/src/com/codename1/components/ScaleImageLabel.java b/CodenameOne/src/com/codename1/components/ScaleImageLabel.java index 1bbdda65c6..939c2aa6aa 100644 --- a/CodenameOne/src/com/codename1/components/ScaleImageLabel.java +++ b/CodenameOne/src/com/codename1/components/ScaleImageLabel.java @@ -50,7 +50,7 @@ public class ScaleImageLabel extends Label { * Default constructor */ public ScaleImageLabel() { - setUIID("Label"); + setUIIDFinal("Label"); setShowEvenIfBlank(true); getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT); } @@ -61,7 +61,7 @@ public ScaleImageLabel() { * @param i image */ public ScaleImageLabel(Image i) { - setUIID("Label"); + setUIIDFinal("Label"); setShowEvenIfBlank(true); getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT); setIcon(i); diff --git a/CodenameOne/src/com/codename1/components/ShareButton.java b/CodenameOne/src/com/codename1/components/ShareButton.java index acbce1076e..828820d7a2 100644 --- a/CodenameOne/src/com/codename1/components/ShareButton.java +++ b/CodenameOne/src/com/codename1/components/ShareButton.java @@ -69,11 +69,11 @@ public class ShareButton extends Button implements ActionListener { * Default constructor */ public ShareButton() { - setUIID("ShareButton"); + setUIIDFinal("ShareButton"); //Image shareIcon = Resources.getSystemResource().getImage("share.png"); //setIcon(shareIcon); FontImage.setMaterialIcon(this, FontImage.MATERIAL_SHARE); - addActionListener(this); + super.addActionListener(this); shareServices.addElement(new SMSShare()); shareServices.addElement(new EmailShare()); shareServices.addElement(new FacebookShare()); diff --git a/CodenameOne/src/com/codename1/components/SignatureComponent.java b/CodenameOne/src/com/codename1/components/SignatureComponent.java index 7ebc070ffe..e6d55b47a4 100644 --- a/CodenameOne/src/com/codename1/components/SignatureComponent.java +++ b/CodenameOne/src/com/codename1/components/SignatureComponent.java @@ -85,7 +85,7 @@ * @author shannah * @since 3.4 */ -public class SignatureComponent extends Container implements ActionSource { +public class SignatureComponent extends Container implements ActionSource { private final SignaturePanel signaturePanel = new SignaturePanel(); private final Button lead; @@ -126,9 +126,9 @@ public void paint(Graphics g) { * Creates a new signature component. */ public SignatureComponent() { - setLayout(new BorderLayout()); + super.setLayout(new BorderLayout()); xFont = Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_LARGE); - final Style signatureButtonBoxStyle = getUIManager().getComponentStyle("SignatureButtonBox"); + final Style signatureButtonBoxStyle = super.getUIManager().getComponentStyle("SignatureButtonBox"); lead = new Button() { @Override @@ -152,7 +152,7 @@ protected void paintBackground(Graphics g) { }; lead.setText(localize("SignatureComponent.LeadText", "Press to sign")); lead.setUIID("SignatureButton"); - lead.addActionListener(new ActionListener() { + lead.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { final Dialog dialog = new Dialog(localize("SignatureComponent.DialogTitle", "Sign Here")); final SignatureDialogBody sigBody = new SignatureDialogBody() { @@ -164,7 +164,7 @@ protected void onCancel() { }; signaturePanel.clear(); - sigBody.addActionListener(new ActionListener() { + sigBody.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent sigDoneEvent) { dialog.dispose(); setSignatureImage(sigBody.getValue()); @@ -179,7 +179,7 @@ public void actionPerformed(ActionEvent sigDoneEvent) { dialog.show(); } }); - addComponent(BorderLayout.CENTER, lead); + super.addComponent(BorderLayout.CENTER, lead); } /** @@ -208,7 +208,7 @@ protected void onSignatureReset() { * * @param l */ - public void addActionListener(ActionListener l) { + public void addActionListener(ActionListener l) { eventDispatcher.addListener(l); } @@ -217,7 +217,7 @@ public void addActionListener(ActionListener l) { * * @param l */ - public void removeActionListener(ActionListener l) { + public void removeActionListener(ActionListener l) { eventDispatcher.removeListener(l); } @@ -331,25 +331,22 @@ public void clearSignaturePanel() { */ private class SignatureDialogBody extends Container { private final EventDispatcher eventDispatcher = new EventDispatcher(); - private final Button doneButton; - private final Button resetButton; - private final Button cancelButton; private Image value; public SignatureDialogBody() { setLayout(new BorderLayout()); - addComponent(BorderLayout.CENTER, signaturePanel); - doneButton = new Button( + super.addComponent(BorderLayout.CENTER, signaturePanel); + Button doneButton = new Button( localize("SignatureComponent.SaveButtonLabel", "Save"), - getUIManager().getThemeConstant("sigButtonOKUIID", "Button")); - resetButton = new Button( + super.getUIManager().getThemeConstant("sigButtonOKUIID", "Button")); + Button resetButton = new Button( localize("SignatureComponent.ResetButtonLabel", "Reset"), - getUIManager().getThemeConstant("sigButtonResetUIID", "Button")); - cancelButton = new Button( + super.getUIManager().getThemeConstant("sigButtonResetUIID", "Button")); + Button cancelButton = new Button( localize("SignatureComponent.CancelButtonLabel", "Cancel"), - getUIManager().getThemeConstant("sigButtonCancelUIID", "Button")); + super.getUIManager().getThemeConstant("sigButtonCancelUIID", "Button")); - doneButton.addActionListener(new ActionListener() { + doneButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { value = signaturePanel.getImage(); if (value == null) { @@ -366,7 +363,7 @@ public void actionPerformed(ActionEvent evt) { } }); - resetButton.addActionListener(new ActionListener() { + resetButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { signaturePanel.clear(); onSignatureReset(); @@ -374,14 +371,14 @@ public void actionPerformed(ActionEvent evt) { } }); - cancelButton.addActionListener(new ActionListener() { + cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { removeComponent(signaturePanel); onCancel(); } }); - addComponent(BorderLayout.SOUTH, GridLayout.encloseIn(3, cancelButton, resetButton, doneButton)); + super.addComponent(BorderLayout.SOUTH, GridLayout.encloseIn(3, cancelButton, resetButton, doneButton)); } /** @@ -451,9 +448,9 @@ private static class SignaturePanel extends Component { private final Style signatureStyle; SignaturePanel() { - setUIID("SignaturePanel"); - signatureBoxStyle = getUIManager().getComponentStyle("SignaturePanelBox"); - signatureStyle = getUIManager().getComponentStyle("SignaturePanelSignature"); + setUIIDFinal("SignaturePanel"); + signatureBoxStyle = super.getUIManager().getComponentStyle("SignaturePanelBox"); + signatureStyle = super.getUIManager().getComponentStyle("SignaturePanelSignature"); stroke.setLineWidth(Math.max(1, Display.getInstance().convertToPixels(1, true) / 2)); } diff --git a/CodenameOne/src/com/codename1/components/SliderBridge.java b/CodenameOne/src/com/codename1/components/SliderBridge.java index 2c142e4635..034463458c 100644 --- a/CodenameOne/src/com/codename1/components/SliderBridge.java +++ b/CodenameOne/src/com/codename1/components/SliderBridge.java @@ -117,7 +117,7 @@ public static void bindProgress(final ConnectionRequest[] sources, final Slider */ public void actionPerformed(ActionEvent evt) { // PMD Fix (CollapsibleIfStatements): Collapse the nested source checks into one conditional. - if (sources != null && !sourceVec.contains(evt.getSource())) { + if (sources != null && !sourceVec.contains(evt.getSource()) || !(evt instanceof NetworkEvent)) { return; } NetworkEvent e = (NetworkEvent) evt; diff --git a/CodenameOne/src/com/codename1/components/SpanButton.java b/CodenameOne/src/com/codename1/components/SpanButton.java index b2aa3f573f..af7fb23868 100644 --- a/CodenameOne/src/com/codename1/components/SpanButton.java +++ b/CodenameOne/src/com/codename1/components/SpanButton.java @@ -32,6 +32,7 @@ import com.codename1.ui.SelectableIconHolder; import com.codename1.ui.TextArea; import com.codename1.ui.TextHolder; +import com.codename1.ui.events.ActionEvent; import com.codename1.ui.events.ActionListener; import com.codename1.ui.events.ActionSource; import com.codename1.ui.layouts.BorderLayout; @@ -53,7 +54,7 @@ * * @author Shai Almog */ -public class SpanButton extends Container implements ActionSource, SelectableIconHolder, TextHolder { +public class SpanButton extends Container implements ActionSource, SelectableIconHolder, TextHolder { private int gap = Label.getDefaultGap(); private final Button actualButton; @@ -82,9 +83,9 @@ public SpanButton(String txt, String textUiid) { * Constructor accepting default text */ public SpanButton(String txt) { - setUIID("Button"); + setUIIDFinal("Button"); setLayout(new BorderLayout()); - text = new TextArea(getUIManager().localize(txt, txt)); + text = new TextArea(super.getUIManager().localize(txt, txt)); text.setColumns(100); text.setUIID("Button"); text.setGrowByContent(true); @@ -98,11 +99,11 @@ public SpanButton(String txt) { removeBackground(text.getDisabledStyle()); actualButton = new Button(); actualButton.setUIID("icon"); - addComponent(BorderLayout.WEST, actualButton); + super.addComponent(BorderLayout.WEST, actualButton); Container center = BoxLayout.encloseYCenter(text); center.getStyle().setMargin(0, 0, 0, 0); center.getStyle().setPadding(0, 0, 0, 0); - addComponent(BorderLayout.CENTER, center); + super.addComponent(BorderLayout.CENTER, center); setLeadComponent(actualButton); updateGap(); } @@ -318,7 +319,7 @@ public void removeLongPressListener(ActionListener l) { * * @param l the listener */ - public void addActionListener(ActionListener l) { + public void addActionListener(ActionListener l) { actualButton.addActionListener(l); } @@ -327,7 +328,7 @@ public void addActionListener(ActionListener l) { * * @param l the listener */ - public void removeActionListener(ActionListener l) { + public void removeActionListener(ActionListener l) { actualButton.removeActionListener(l); } diff --git a/CodenameOne/src/com/codename1/components/SpanLabel.java b/CodenameOne/src/com/codename1/components/SpanLabel.java index cc5f37dd8d..3b430dd928 100644 --- a/CodenameOne/src/com/codename1/components/SpanLabel.java +++ b/CodenameOne/src/com/codename1/components/SpanLabel.java @@ -80,9 +80,9 @@ public SpanLabel(String txt, String textUiid) { * Constructor accepting default text */ public SpanLabel(String txt) { - setUIID("Container"); - setLayout(new BorderLayout()); - text = new TextArea(getUIManager().localize(txt, txt)); + setUIIDFinal("Container"); + super.setLayout(new BorderLayout()); + text = new TextArea(super.getUIManager().localize(txt, txt)); text.setActAsLabel(true); text.setColumns(text.getText().length() + 1); text.setGrowByContent(true); @@ -94,8 +94,8 @@ public SpanLabel(String txt) { iconWrapper = new Container(new FlowLayout(CENTER, CENTER)); iconWrapper.getAllStyles().stripMarginAndPadding(); iconWrapper.add(icon); - addComponent(BorderLayout.WEST, iconWrapper); - addComponent(BorderLayout.CENTER, BoxLayout.encloseYCenter(text)); + super.addComponent(BorderLayout.WEST, iconWrapper); + super.addComponent(BorderLayout.CENTER, BoxLayout.encloseYCenter(text)); updateGap(); } diff --git a/CodenameOne/src/com/codename1/components/SpanMultiButton.java b/CodenameOne/src/com/codename1/components/SpanMultiButton.java index b1e3f3477b..e61ef96cee 100644 --- a/CodenameOne/src/com/codename1/components/SpanMultiButton.java +++ b/CodenameOne/src/com/codename1/components/SpanMultiButton.java @@ -83,7 +83,7 @@ public SpanMultiButton(String line1) { * Default constructor allowing the designer to create an instance of this class */ public SpanMultiButton() { - setUIID("MultiButton"); + setUIIDFinal("MultiButton"); firstRow.setActAsLabel(true); firstRow.setGrowByContent(true); diff --git a/CodenameOne/src/com/codename1/components/SplitPane.java b/CodenameOne/src/com/codename1/components/SplitPane.java index 84105bbb9b..7737a4782f 100644 --- a/CodenameOne/src/com/codename1/components/SplitPane.java +++ b/CodenameOne/src/com/codename1/components/SplitPane.java @@ -208,7 +208,7 @@ public SplitPane(Settings settings, Component topOrLeft, Component bottomOrRight divider = new Divider(); add(this.topOrLeft).add(this.bottomOrRight).add(divider); - LayeredLayout l = (LayeredLayout) getLayout(); + LayeredLayout l = (LayeredLayout) super.getLayout(); this.preferredInset = initDividerInset(l.createConstraint(), preferredInset); this.minInset = initDividerInset(l.createConstraint(), minInset); this.maxInset = initDividerInset(l.createConstraint(), maxInset); @@ -217,22 +217,13 @@ public SplitPane(Settings settings, Component topOrLeft, Component bottomOrRight .setInsets(this.topOrLeft, "0 0 0 0"); this.preferredInset.copyTo(l.getOrCreateConstraint(divider)); - switch (orientation) { - case HORIZONTAL_SPLIT: { - l.setReferenceComponentRight(this.topOrLeft, divider, 1f); - l.setReferenceComponentLeft(this.bottomOrRight, divider, 1f); - break; - } - - default: { - l.setReferenceComponentBottom(this.topOrLeft, divider, 1f); - l.setReferenceComponentTop(this.bottomOrRight, divider, 1f); - break; - } - + if (orientation == HORIZONTAL_SPLIT) { + l.setReferenceComponentRight(this.topOrLeft, divider, 1f); + l.setReferenceComponentLeft(this.bottomOrRight, divider, 1f); + } else { + l.setReferenceComponentBottom(this.topOrLeft, divider, 1f); + l.setReferenceComponentTop(this.bottomOrRight, divider, 1f); } - - } /** @@ -959,7 +950,7 @@ private class Divider extends Container { Divider() { super(new LayeredLayout()); if (dividerUIID != null) { - setUIID(dividerUIID); + setUIIDFinal(dividerUIID); } btnCollapse = $(new Button()) .setUIID(collapseButtonUIID) @@ -967,10 +958,12 @@ private class Divider extends Container { .each(new ComponentClosure() { @Override public void call(Component c) { - if (collapseIcon != null) { - ((Label) c).setIcon(collapseIcon); - } else { - ((Label) c).setMaterialIcon(getCollapseMaterialIcon()); + if(c instanceof Label) { + if (collapseIcon != null) { + ((Label) c).setIcon(collapseIcon); + } else { + ((Label) c).setMaterialIcon(getCollapseMaterialIcon()); + } } } @@ -990,13 +983,14 @@ public void actionPerformed(ActionEvent evt) { .each(new ComponentClosure() { @Override public void call(Component c) { - if (expandIcon != null) { - ((Label) c).setIcon(expandIcon); - } else { - ((Label) c).setMaterialIcon(getExpandMaterialIcon()); + if(c instanceof Label) { + if (expandIcon != null) { + ((Label) c).setIcon(expandIcon); + } else { + ((Label) c).setMaterialIcon(getExpandMaterialIcon()); + } } } - }) .addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { @@ -1026,34 +1020,30 @@ public void actionPerformed(ActionEvent evt) { boolean isDesktop = CN.isDesktop(); - LayeredLayout l = (LayeredLayout) getLayout(); - switch (orientation) { - case HORIZONTAL_SPLIT: { - l.setInsets(btnCollapse, "0 0 auto 0") - .setInsets(btnExpand, "0 0 auto 0") - .setInsets(dragHandle, "auto auto auto auto") - .setReferenceComponentTop(btnExpand, btnCollapse, 1f); - if (!isDesktop) { - // On tablets and phones it is difficult to use the collapse - // expand buttons when they are adjacent. - // On these devices we'll place them at opposite ends of the divider - l.setInsets(btnExpand, "auto 0 0 0") - .setReferenceComponentTop(btnExpand, null, 1f); - } - break; + LayeredLayout l = (LayeredLayout) super.getLayout(); + if (orientation == HORIZONTAL_SPLIT) { + l.setInsets(btnCollapse, "0 0 auto 0") + .setInsets(btnExpand, "0 0 auto 0") + .setInsets(dragHandle, "auto auto auto auto") + .setReferenceComponentTop(btnExpand, btnCollapse, 1f); + if (!isDesktop) { + // On tablets and phones it is difficult to use the collapse + // expand buttons when they are adjacent. + // On these devices we'll place them at opposite ends of the divider + l.setInsets(btnExpand, "auto 0 0 0") + .setReferenceComponentTop(btnExpand, null, 1f); } - default: { - l.setInsets(btnCollapse, "0 auto 0 0") - .setInsets(btnExpand, "0 auto 0 0") - .setInsets(dragHandle, "auto auto auto auto") - .setReferenceComponentLeft(btnExpand, btnCollapse, 1f); - if (!isDesktop) { - // On tablets and phones it is difficult to use the collapse - // expand buttons when they are adjacent. - // On these devices we'll place them at opposite ends of the divider - l.setInsets(btnExpand, "0 0 0 auto") - .setReferenceComponentLeft(btnExpand, null, 1f); - } + } else { + l.setInsets(btnCollapse, "0 auto 0 0") + .setInsets(btnExpand, "0 auto 0 0") + .setInsets(dragHandle, "auto auto auto auto") + .setReferenceComponentLeft(btnExpand, btnCollapse, 1f); + if (!isDesktop) { + // On tablets and phones it is difficult to use the collapse + // expand buttons when they are adjacent. + // On these devices we'll place them at opposite ends of the divider + l.setInsets(btnExpand, "0 0 0 auto") + .setReferenceComponentLeft(btnExpand, null, 1f); } } @@ -1061,18 +1051,12 @@ public void actionPerformed(ActionEvent evt) { $(this) .setBorder(createBorder()) .setCursor(getDragCursor()) - .setDraggable(true) - - ; + .setDraggable(true); } else { $(this) .setCursor(getDragCursor()) - .setDraggable(true) - - ; + .setDraggable(true); } - - } private char getCollapseMaterialIcon() { diff --git a/CodenameOne/src/com/codename1/components/Switch.java b/CodenameOne/src/com/codename1/components/Switch.java index a444ae52cc..87a68d9ede 100644 --- a/CodenameOne/src/com/codename1/components/Switch.java +++ b/CodenameOne/src/com/codename1/components/Switch.java @@ -273,7 +273,7 @@ public Switch() { * necessary for theme constants */ public Switch(String uiid) { - setUIID(uiid); + setUIIDFinal(uiid); setOpaque(false); initialize(); } diff --git a/CodenameOne/src/com/codename1/components/SwitchList.java b/CodenameOne/src/com/codename1/components/SwitchList.java index 797d0f4ad7..ff7ea63224 100644 --- a/CodenameOne/src/com/codename1/components/SwitchList.java +++ b/CodenameOne/src/com/codename1/components/SwitchList.java @@ -42,7 +42,7 @@ public class SwitchList extends ButtonList { - private final ActionListener changeListener = new ActionListener() { + private final ActionListener changeListener = new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { if (evt.getSource() instanceof Switch && contains((Switch) evt.getSource())) { @@ -59,15 +59,8 @@ public void actionPerformed(ActionEvent evt) { }; public SwitchList(MultipleSelectionListModel model) { - super(model); - + super(model, true); fireReady(); - - } - - @Override - public boolean isAllowMultipleSelection() { - return true; } @Override @@ -80,16 +73,7 @@ protected Component createButton(Object model) { @Override protected void setSelected(Component button, final boolean selected) { - $(".switch", button).each(new ComponentSelector.ComponentClosure() { - @Override - public void call(Component c) { - if (selected) { - ((Switch) c).setOn(); - } else { - ((Switch) c).setOff(); - } - } - }); + $(".switch", button).each(new SetSelectedComponentClosure(selected)); } @@ -111,4 +95,20 @@ protected Component undecorateComponent(Component b) { } + private static class SetSelectedComponentClosure implements ComponentSelector.ComponentClosure { + private final boolean selected; + + public SetSelectedComponentClosure(boolean selected) { + this.selected = selected; + } + + @Override + public void call(Component c) { + if (selected) { + ((Switch) c).setOn(); + } else { + ((Switch) c).setOff(); + } + } + } } diff --git a/CodenameOne/src/com/codename1/components/ToastBar.java b/CodenameOne/src/com/codename1/components/ToastBar.java index c1c098e28f..286e8bb346 100644 --- a/CodenameOne/src/com/codename1/components/ToastBar.java +++ b/CodenameOne/src/com/codename1/components/ToastBar.java @@ -608,15 +608,7 @@ private void moveLayerToFront() { return; } if (parent.getComponentIndex(layered) != parent.getComponentCount() - 1) { - f.getAnimationManager().flushAnimation(new Runnable() { - public void run() { - parent.removeComponent(layered); - parent.addComponent(layered); - parent.revalidate(); - } - }); - - + f.getAnimationManager().flushAnimation(new FlushAnimationCallback(parent, layered)); } } @@ -710,6 +702,22 @@ public void setVisible(boolean visible) { } } + private static class FlushAnimationCallback implements Runnable { + private final Container parent; + private final Container layered; + + public FlushAnimationCallback(Container parent, Container layered) { + this.parent = parent; + this.layered = layered; + } + + public void run() { + parent.removeComponent(layered); + parent.addComponent(layered); + parent.revalidate(); + } + } + /** * Represents a single status message. */ diff --git a/CodenameOne/src/com/codename1/components/WebBrowser.java b/CodenameOne/src/com/codename1/components/WebBrowser.java index 66c13ae7da..50f4791d8b 100644 --- a/CodenameOne/src/com/codename1/components/WebBrowser.java +++ b/CodenameOne/src/com/codename1/components/WebBrowser.java @@ -156,7 +156,7 @@ protected void readResponse(InputStream input) throws IOException { } else { response[0] = input; synchronized (LOCK) { - LOCK.notify(); + LOCK.notifyAll(); } } } diff --git a/CodenameOne/src/com/codename1/facebook/FaceBookAccess.java b/CodenameOne/src/com/codename1/facebook/FaceBookAccess.java index 195ff905e9..1fcf018e80 100644 --- a/CodenameOne/src/com/codename1/facebook/FaceBookAccess.java +++ b/CodenameOne/src/com/codename1/facebook/FaceBookAccess.java @@ -245,16 +245,8 @@ public Oauth2 createOAuth() { * @param al a listener that will receive at its source either a token for the service or an exception in case of a failure * @return a component that should be displayed to the user in order to perform the authentication */ - public Component createAuthComponent(final ActionListener al) { - return createOAuth().createAuthComponent(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - if (evt.getSource() instanceof String) { - token = (String) evt.getSource(); - } - al.actionPerformed(evt); - } - }); + public Component createAuthComponent(final ActionListener al) { + return createOAuth().createAuthComponent(new CreateAuthComponentActionListener(al)); } /** @@ -263,21 +255,8 @@ public void actionPerformed(ActionEvent evt) { * @param al a listener that will receive at its source either a token for * the service or an exception in case of a failure */ - public void showAuthentication(final ActionListener al) { - createOAuth().showAuthentication(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - if (evt.getSource() instanceof String) { - token = (String) evt.getSource(); - } - if (evt.getSource() instanceof AccessToken) { - AccessToken t = (AccessToken) evt.getSource(); - token = t.getToken(); - - } - al.actionPerformed(evt); - } - }); + public void showAuthentication(final ActionListener al) { + createOAuth().showAuthentication(new ShowAuthenticationActionListener(al)); } /** @@ -311,20 +290,10 @@ public void setProgress(Slider slider) { * @param faceBookId the object id that we would like to query * @param callback the callback that should be updated when the data arrives */ - public void getFaceBookObject(String faceBookId, final ActionListener callback) throws IOException { + public void getFaceBookObject(String faceBookId, final ActionListener callback) throws IOException { checkAuthentication(); final FacebookRESTService con = new FacebookRESTService(token, faceBookId, "", false); - con.addResponseListener(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - if (!con.isAlive()) { - return; - } - if (callback != null) { - callback.actionPerformed(evt); - } - } - }); + con.addResponseListener(new GetFaceBookObjectActionListener(con, callback)); if (slider != null) { SliderBridge.bindProgress(con, slider); } @@ -343,22 +312,12 @@ public void actionPerformed(ActionEvent evt) { * @param callback the callback that should be updated when the data arrives * @param needToken if true authentication is being checked */ - public void getFaceBookObject(String faceBookId, final ActionListener callback, boolean needToken, boolean async) throws IOException { + public void getFaceBookObject(String faceBookId, final ActionListener callback, boolean needToken, boolean async) throws IOException { if (needToken) { checkAuthentication(); } final FacebookRESTService con = new FacebookRESTService(token, faceBookId, "", false); - con.addResponseListener(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - if (!con.isAlive()) { - return; - } - if (callback != null) { - callback.actionPerformed(evt); - } - } - }); + con.addResponseListener(new GetFaceBookObjectWithTokenActionListener(con, callback)); if (slider != null) { SliderBridge.bindProgress(con, slider); } @@ -413,24 +372,12 @@ public void getFaceBookObjectItems(String faceBookId, String itemsConnection, * @param user an object to fill with the user details * @param callback the callback that should be updated when the data arrives */ - public void getUser(String userId, final User user, final ActionListener callback) throws IOException { + public void getUser(String userId, final User user, final ActionListener callback) throws IOException { String id = userId; if (id == null) { id = "me"; } - getFaceBookObject(id, new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - Vector v = (Vector) ((NetworkEvent) evt).getMetaData(); - Hashtable t = (Hashtable) v.elementAt(0); - if (user != null) { - user.copy(t); - } - if (callback != null) { - callback.actionPerformed(evt); - } - } - }); + getFaceBookObject(id, new GetUserActionListener(user, callback)); } /** @@ -447,22 +394,8 @@ public User getUser(String userId) throws IOException { } final User user = new User(); final Vector err = new Vector(); - addResponseCodeListener(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - NetworkEvent ne = (NetworkEvent) evt; - err.addElement(ne); - removeResponseCodeListener(this); - } - }); - getFaceBookObject(id, new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - Vector v = (Vector) ((NetworkEvent) evt).getMetaData(); - Hashtable t = (Hashtable) v.elementAt(0); - user.copy(t); - } - }, true, false); + addResponseCodeListener(new GetUserResponseCodeActionListener(err)); + getFaceBookObject(id, new GetUserFacebookObjectActionListener(user), true, false); if (err.size() > 0) { throw new IOException(((NetworkEvent) err.elementAt(0)).getResponseCode() + ": " + ((NetworkEvent) err.elementAt(0)).getMessage()); } @@ -480,22 +413,8 @@ public void actionPerformed(ActionEvent evt) { public Page getPage(String pageId) throws IOException { final Page page = new Page(); final Vector err = new Vector(); - addResponseCodeListener(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - NetworkEvent ne = (NetworkEvent) evt; - err.addElement(ne); - removeResponseCodeListener(this); - } - }); - getFaceBookObject(pageId, new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - Vector v = (Vector) ((NetworkEvent) evt).getMetaData(); - Hashtable t = (Hashtable) v.elementAt(0); - page.copy(t); - } - }, false, false); + addResponseCodeListener(new GetPageResponseCodeActionListener(err)); + getFaceBookObject(pageId, new GetPageActionListener(page), false, false); if (err.size() > 0) { throw new IOException(((NetworkEvent) err.elementAt(0)).getResponseCode() + ": " + ((NetworkEvent) err.elementAt(0)).getMessage()); } @@ -509,20 +428,8 @@ public void actionPerformed(ActionEvent evt) { * @param post an Object to fill with the data * @param callback the callback that should be updated when the data arrives */ - public void getPost(String postId, final Post post, final ActionListener callback) throws IOException { - getFaceBookObject(postId, new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - Vector v = (Vector) ((NetworkEvent) evt).getMetaData(); - Hashtable t = (Hashtable) v.elementAt(0); - if (post != null) { - post.copy(t); - } - if (callback != null) { - callback.actionPerformed(evt); - } - } - }); + public void getPost(String postId, final Post post, final ActionListener callback) throws IOException { + getFaceBookObject(postId, new GetPostActionListener(post, callback)); } /** @@ -537,23 +444,8 @@ public void actionPerformed(ActionEvent evt) { public Post getPost(String postId, boolean needAuth) throws IOException { final Post post = new Post(); final Vector err = new Vector(); - addResponseCodeListener(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - NetworkEvent ne = (NetworkEvent) evt; - err.addElement(ne); - removeResponseCodeListener(this); - } - }); - getFaceBookObject(postId, new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - Vector v = (Vector) ((NetworkEvent) evt).getMetaData(); - Hashtable t = (Hashtable) v.elementAt(0); - post.copy(t); - - } - }, needAuth, false); + addResponseCodeListener(new GetPostAuthResponseCodeActionListener(err)); + getFaceBookObject(postId, new GetPostAuthActionListener(post), needAuth, false); if (err.size() > 0) { throw new IOException(((NetworkEvent) err.elementAt(0)).getResponseCode() + ": " + ((NetworkEvent) err.elementAt(0)).getMessage()); } @@ -567,27 +459,15 @@ public void actionPerformed(ActionEvent evt) { * @param photo an Object to fill with the data * @param callback the callback that should be updated when the data arrives */ - public void getPhoto(String photoId, final Photo photo, final ActionListener callback) throws IOException { - getFaceBookObject(photoId, new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - Vector v = (Vector) ((NetworkEvent) evt).getMetaData(); - Hashtable t = (Hashtable) v.elementAt(0); - if (photo != null) { - photo.copy(t); - } - if (callback != null) { - callback.actionPerformed(evt); - } - } - }); + public void getPhoto(String photoId, final Photo photo, final ActionListener callback) throws IOException { + getFaceBookObject(photoId, new GetPhotoActionListener(photo, callback)); } /** * Gets a Photo from a photoId * This is a sync method it will block until a response it returned * - * @param the photoId + * @param photoId the photoId * @param needAuth if this object is public needAuth can be false and no * authentication will be performed * @return the Photo requested @@ -596,22 +476,8 @@ public Photo getPhoto(String photoId, boolean needAuth) throws IOException { final Photo photo = new Photo(); final Vector err = new Vector(); - addResponseCodeListener(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - NetworkEvent ne = (NetworkEvent) evt; - err.addElement(ne); - removeResponseCodeListener(this); - } - }); - getFaceBookObject(photoId, new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - Vector v = (Vector) ((NetworkEvent) evt).getMetaData(); - Hashtable t = (Hashtable) v.elementAt(0); - photo.copy(t); - } - }, needAuth, false); + addResponseCodeListener(new GetPhotoAuthResponseCodeActionListener(err)); + getFaceBookObject(photoId, new GetPhotoAuthActionListener(photo), needAuth, false); if (err.size() > 0) { throw new IOException(((NetworkEvent) err.elementAt(0)).getResponseCode() + ": " + ((NetworkEvent) err.elementAt(0)).getMessage()); } @@ -625,27 +491,15 @@ public void actionPerformed(ActionEvent evt) { * @param album an Object to fill with the data * @param callback the callback that should be updated when the data arrives */ - public void getAlbum(String albumId, final Album album, final ActionListener callback) throws IOException { - getFaceBookObject(albumId, new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - Vector v = (Vector) ((NetworkEvent) evt).getMetaData(); - Hashtable t = (Hashtable) v.elementAt(0); - if (album != null) { - album.copy(t); - } - if (callback != null) { - callback.actionPerformed(evt); - } - } - }); + public void getAlbum(String albumId, final Album album, final ActionListener callback) throws IOException { + getFaceBookObject(albumId, new GetAlbumActionListener(album, callback)); } /** * Gets a Album from a albumId * This is a sync method it will block until a response it returned * - * @param the albumId + * @param albumId the albumId * @param needAuth if this object is public needAuth can be false and no * authentication will be performed * @return the Album requested @@ -653,22 +507,13 @@ public void actionPerformed(ActionEvent evt) { public Album getAlbum(String albumId, boolean needAuth) throws IOException { final Album album = new Album(); final Vector err = new Vector(); - addResponseCodeListener(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - NetworkEvent ne = (NetworkEvent) evt; - err.addElement(ne); + addResponseCodeListener(new ActionListener() { + public void actionPerformed(NetworkEvent evt) { + err.addElement(evt); removeResponseCodeListener(this); } }); - getFaceBookObject(albumId, new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - Vector v = (Vector) ((NetworkEvent) evt).getMetaData(); - Hashtable t = (Hashtable) v.elementAt(0); - album.copy(t); - } - }, needAuth, false); + getFaceBookObject(albumId, new GetAlbumAuthActionListener(album), needAuth, false); if (err.size() > 0) { throw new IOException(((NetworkEvent) err.elementAt(0)).getResponseCode() + ": " + ((NetworkEvent) err.elementAt(0)).getMessage()); } @@ -1175,7 +1020,7 @@ public void createNote(String userId, String subject, String message, ActionList * @param callback the callback that should be updated when the data arrives */ public void getUserNotifications(String userId, String startTime, boolean includeRead, - DefaultListModel notifications, final ActionListener callback) throws IOException { + DefaultListModel notifications, final ActionListener callback) throws IOException { checkAuthentication(); final FacebookRESTService con = new FacebookRESTService(token, "https://api.facebook.com/method/notifications.getList", false); @@ -1185,17 +1030,7 @@ public void getUserNotifications(String userId, String startTime, boolean includ con.addArgument("format", "json"); con.setResponseDestination(notifications); - con.addResponseListener(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - if (!con.isAlive()) { - return; - } - if (callback != null) { - callback.actionPerformed(evt); - } - } - }); + con.addResponseListener(new GetUserNotificationsActionListener(con, callback)); if (slider != null) { SliderBridge.bindProgress(con, slider); @@ -1219,7 +1054,7 @@ public void actionPerformed(ActionEvent evt) { * Vector users = (Vector) data.elementAt(0); * } */ - public void getUsersDetails(String[] usersIds, String[] fields, final ActionListener callback) throws IOException { + public void getUsersDetails(String[] usersIds, String[] fields, final ActionListener callback) throws IOException { checkAuthentication(); final FacebookRESTService con = new FacebookRESTService(token, "https://api.facebook.com/method/users.getInfo", false); @@ -1240,17 +1075,7 @@ public void getUsersDetails(String[] usersIds, String[] fields, final ActionList con.addArgumentNoEncoding("fields", fieldsStr.toString()); con.addArgument("format", "json"); - con.addResponseListener(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - if (!con.isAlive()) { - return; - } - if (callback != null) { - callback.actionPerformed(evt); - } - } - }); + con.addResponseListener(new GetUsersDetailsActionListener(con, callback)); if (slider != null) { SliderBridge.bindProgress(con, slider); } @@ -1349,4 +1174,337 @@ public void actionPerformed(ActionEvent evt) { } + private static class CreateAuthComponentActionListener implements ActionListener { + + private final ActionListener al; + + public CreateAuthComponentActionListener(ActionListener al) { + this.al = al; + } + + public void actionPerformed(ActionEvent evt) { + if (evt.getSource() instanceof String) { + token = (String) evt.getSource(); + } + al.actionPerformed(evt); + } + } + + private static class ShowAuthenticationActionListener implements ActionListener { + private final ActionListener al; + + public ShowAuthenticationActionListener(ActionListener al) { + this.al = al; + } + + public void actionPerformed(ActionEvent evt) { + if (evt.getSource() instanceof String) { + token = (String) evt.getSource(); + } + if (evt.getSource() instanceof AccessToken) { + AccessToken t = (AccessToken) evt.getSource(); + token = t.getToken(); + + } + al.actionPerformed(evt); + } + } + + private static class GetFaceBookObjectActionListener implements ActionListener { + private final FacebookRESTService con; + private final ActionListener callback; + + public GetFaceBookObjectActionListener(FacebookRESTService con, ActionListener callback) { + this.con = con; + this.callback = callback; + } + + public void actionPerformed(NetworkEvent evt) { + if (!con.isAlive()) { + return; + } + if (callback != null) { + callback.actionPerformed(evt); + } + } + } + + private static class GetFaceBookObjectWithTokenActionListener implements ActionListener { + private final FacebookRESTService con; + private final ActionListener callback; + + public GetFaceBookObjectWithTokenActionListener(FacebookRESTService con, ActionListener callback) { + this.con = con; + this.callback = callback; + } + + public void actionPerformed(NetworkEvent evt) { + if (!con.isAlive()) { + return; + } + if (callback != null) { + callback.actionPerformed(evt); + } + } + } + + private static class GetUserActionListener implements ActionListener { + + private final User user; + private final ActionListener callback; + + public GetUserActionListener(User user, ActionListener callback) { + this.user = user; + this.callback = callback; + } + + public void actionPerformed(NetworkEvent evt) { + Vector v = (Vector) ((NetworkEvent) evt).getMetaData(); + Hashtable t = (Hashtable) v.elementAt(0); + if (user != null) { + user.copy(t); + } + if (callback != null) { + callback.actionPerformed(evt); + } + } + } + + private static class GetUserFacebookObjectActionListener implements ActionListener { + + private final User user; + + public GetUserFacebookObjectActionListener(User user) { + this.user = user; + } + + public void actionPerformed(NetworkEvent evt) { + Vector v = (Vector) evt.getMetaData(); + Hashtable t = (Hashtable) v.elementAt(0); + user.copy(t); + } + } + + private static class GetPageActionListener implements ActionListener { + private final Page page; + + public GetPageActionListener(Page page) { + this.page = page; + } + + public void actionPerformed(NetworkEvent evt) { + Vector v = (Vector) evt.getMetaData(); + Hashtable t = (Hashtable) v.elementAt(0); + page.copy(t); + } + } + + private static class GetPostActionListener implements ActionListener { + private final Post post; + private final ActionListener callback; + + public GetPostActionListener(Post post, ActionListener callback) { + this.post = post; + this.callback = callback; + } + + public void actionPerformed(NetworkEvent evt) { + final Object val = evt.getMetaData();; + if(val instanceof Vector) { + final Vector v = (Vector) val; + final Object o = v.elementAt(0); + if(o instanceof Hashtable) { + final Hashtable t = (Hashtable) o; + if (post != null) { + post.copy(t); + } + if (callback != null) { + callback.actionPerformed(evt); + } + } + } + } + } + + private static class GetPostAuthActionListener implements ActionListener { + private final Post post; + + public GetPostAuthActionListener(Post post) { + this.post = post; + } + + public void actionPerformed(NetworkEvent evt) { + final Object val = evt.getMetaData(); + if(val instanceof Vector) { + final Vector v = (Vector) val; + final Object o = v.elementAt(0); + if(o instanceof Hashtable) { + Hashtable t = (Hashtable) o; + post.copy(t); + } + } + } + } + + private static class GetPhotoActionListener implements ActionListener { + private final Photo photo; + private final ActionListener callback; + + public GetPhotoActionListener(Photo photo, ActionListener callback) { + this.photo = photo; + this.callback = callback; + } + + public void actionPerformed(NetworkEvent evt) { + Vector v = (Vector) evt.getMetaData(); + Hashtable t = (Hashtable) v.elementAt(0); + if (photo != null) { + photo.copy(t); + } + if (callback != null) { + callback.actionPerformed(evt); + } + } + } + + private static class GetPhotoAuthActionListener implements ActionListener { + + private final Photo photo; + + public GetPhotoAuthActionListener(Photo photo) { + this.photo = photo; + } + + public void actionPerformed(NetworkEvent evt) { + Vector v = (Vector) evt.getMetaData(); + Hashtable t = (Hashtable) v.elementAt(0); + photo.copy(t); + } + } + + private static class GetAlbumActionListener implements ActionListener { + private final Album album; + private final ActionListener callback; + + public GetAlbumActionListener(Album album, ActionListener callback) { + this.album = album; + this.callback = callback; + } + + public void actionPerformed(NetworkEvent evt) { + Vector v = (Vector) evt.getMetaData(); + Hashtable t = (Hashtable) v.elementAt(0); + if (album != null) { + album.copy(t); + } + if (callback != null) { + callback.actionPerformed(evt); + } + } + } + + private static class GetAlbumAuthActionListener implements ActionListener { + private final Album album; + + public GetAlbumAuthActionListener(Album album) { + this.album = album; + } + + public void actionPerformed(NetworkEvent evt) { + Vector v = (Vector) evt.getMetaData(); + Hashtable t = (Hashtable) v.elementAt(0); + album.copy(t); + } + } + + private static class GetUserNotificationsActionListener implements ActionListener { + private final FacebookRESTService con; + private final ActionListener callback; + + public GetUserNotificationsActionListener(FacebookRESTService con, ActionListener callback) { + this.con = con; + this.callback = callback; + } + + public void actionPerformed(NetworkEvent evt) { + if (!con.isAlive()) { + return; + } + if (callback != null) { + callback.actionPerformed(evt); + } + } + } + + private static class GetUsersDetailsActionListener implements ActionListener { + private final FacebookRESTService con; + private final ActionListener callback; + + public GetUsersDetailsActionListener(FacebookRESTService con, ActionListener callback) { + this.con = con; + this.callback = callback; + } + + public void actionPerformed(NetworkEvent evt) { + if (!con.isAlive()) { + return; + } + if (callback != null) { + callback.actionPerformed(evt); + } + } + } + + private class GetUserResponseCodeActionListener implements ActionListener { + + private final Vector err; + + public GetUserResponseCodeActionListener(Vector err) { + this.err = err; + } + + public void actionPerformed(NetworkEvent ne) { + err.addElement(ne); + removeResponseCodeListener(this); + } + } + + private class GetPageResponseCodeActionListener implements ActionListener { + private final Vector err; + + public GetPageResponseCodeActionListener(Vector err) { + this.err = err; + } + + public void actionPerformed(NetworkEvent evt) { + err.addElement(evt); + removeResponseCodeListener(this); + } + } + + private class GetPostAuthResponseCodeActionListener implements ActionListener { + private final Vector err; + + public GetPostAuthResponseCodeActionListener(Vector err) { + this.err = err; + } + + public void actionPerformed(NetworkEvent evt) { + err.addElement(evt); + removeResponseCodeListener(this); + } + } + + private class GetPhotoAuthResponseCodeActionListener implements ActionListener { + private final Vector err; + + public GetPhotoAuthResponseCodeActionListener(Vector err) { + this.err = err; + } + + public void actionPerformed(NetworkEvent evt) { + err.addElement(evt); + removeResponseCodeListener(this); + } + } } diff --git a/CodenameOne/src/com/codename1/facebook/FacebookRESTService.java b/CodenameOne/src/com/codename1/facebook/FacebookRESTService.java index 10e8dfa3e6..e6fe3ad0d5 100644 --- a/CodenameOne/src/com/codename1/facebook/FacebookRESTService.java +++ b/CodenameOne/src/com/codename1/facebook/FacebookRESTService.java @@ -50,9 +50,6 @@ class FacebookRESTService extends ConnectionRequest implements JSONParseCallback public static final String GRAPH_URL = "https://graph.facebook.com/"; public static String PICTURE = "picture"; public static String FRIENDS = "friends"; - public static String TAGGED = "tagged"; - public static String ACTIVITIES = "activities"; - public static String INTERESTS = "interests"; public static String LIKES = "likes"; public static String ALBUMS = "albums"; public static String PHOTOS = "photos"; @@ -61,7 +58,6 @@ class FacebookRESTService extends ConnectionRequest implements JSONParseCallback public static String FEED = "feed"; public static String POSTS = "posts"; public static String INBOX = "inbox"; - public static String MESSAGES = "messages"; public static String EVENTS = "events"; public static String NOTES = "notes"; private final Hashtable entry = new Hashtable(); @@ -70,13 +66,8 @@ class FacebookRESTService extends ConnectionRequest implements JSONParseCallback private String connectionType = ""; private DefaultListModel responseDestination; private int responseOffset = -1; - private String imageKey; private String root; - public FacebookRESTService(boolean post, String token) { - setPost(post); - } - public FacebookRESTService(String token, String id, String connectionType, boolean post) { setPost(post); String query = id; @@ -135,14 +126,6 @@ protected void readResponse(InputStream input) throws IOException { } } - protected String getConnectionType() { - return connectionType; - } - - protected void setConnectionType(String connectionType) { - this.connectionType = connectionType; - } - public void startBlock(String block) { if (block.equals("paging")) { return; @@ -281,34 +264,6 @@ protected int getYield() { return -1; } - /** - * @return the responseOffset - */ - public int getResponseOffset() { - return responseOffset; - } - - /** - * @param responseOffset the responseOffset to set - */ - public void setResponseOffset(int responseOffset) { - this.responseOffset = responseOffset; - } - - /** - * @return the imageKey - */ - public String getImageKey() { - return imageKey; - } - - /** - * @param imageKey the imageKey to set - */ - public void setImageKey(String imageKey) { - this.imageKey = imageKey; - } - /** * {@inheritDoc} */ @@ -340,9 +295,6 @@ public boolean equals(Object o) { if (connectionType != null ? !connectionType.equals(that.connectionType) : that.connectionType != null) { return false; } - if (imageKey != null ? !imageKey.equals(that.imageKey) : that.imageKey != null) { - return false; - } if (root != null ? !root.equals(that.root) : that.root != null) { return false; } @@ -357,7 +309,6 @@ public int hashCode() { int result = super.hashCode(); result = 31 * result + (connectionType != null ? connectionType.hashCode() : 0); result = 31 * result + responseOffset; - result = 31 * result + (imageKey != null ? imageKey.hashCode() : 0); result = 31 * result + (root != null ? root.hashCode() : 0); return result; } diff --git a/CodenameOne/src/com/codename1/facebook/ui/LikeButton.java b/CodenameOne/src/com/codename1/facebook/ui/LikeButton.java index 66ce5a7480..e7b9201eb9 100644 --- a/CodenameOne/src/com/codename1/facebook/ui/LikeButton.java +++ b/CodenameOne/src/com/codename1/facebook/ui/LikeButton.java @@ -60,9 +60,9 @@ public LikeButton(String postId) { * Default constructor */ public LikeButton() { - setUIID("LikeButton"); + setUIIDFinal("LikeButton"); setText("Like"); - addActionListener(this); + super.addActionListener(this); } /** diff --git a/CodenameOne/src/com/codename1/impl/CaptureAudioActionListener.java b/CodenameOne/src/com/codename1/impl/CaptureAudioActionListener.java new file mode 100644 index 0000000000..52cc67ea1b --- /dev/null +++ b/CodenameOne/src/com/codename1/impl/CaptureAudioActionListener.java @@ -0,0 +1,70 @@ +package com.codename1.impl; + +import com.codename1.components.AudioRecorderComponent; +import com.codename1.io.FileSystemStorage; +import com.codename1.media.MediaRecorderBuilder; +import com.codename1.ui.CN; +import com.codename1.ui.Sheet; +import com.codename1.ui.events.ActionEvent; +import com.codename1.ui.events.ActionListener; + +class CaptureAudioActionListener implements ActionListener { + private final AudioRecorderComponent cmp; + private final Sheet sheet; + private final ActionListener response; + private final MediaRecorderBuilder builder; + + public CaptureAudioActionListener(AudioRecorderComponent cmp, Sheet sheet, ActionListener response, MediaRecorderBuilder builder) { + this.cmp = cmp; + this.sheet = sheet; + this.response = response; + this.builder = builder; + } + + @Override + public void actionPerformed(ActionEvent e) { + switch (cmp.getState()) { + case Accepted: + CN.getCurrentForm().getAnimationManager().flushAnimation(new Runnable() { + public void run() { + sheet.back(); + sheet.addCloseListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + sheet.removeCloseListener(this); + response.actionPerformed(new ActionEvent(builder.getPath())); + } + + }); + } + }); + + + break; + case Canceled: + FileSystemStorage fs = FileSystemStorage.getInstance(); + if (fs.exists(builder.getPath())) { + FileSystemStorage.getInstance().delete(builder.getPath()); + } + CN.getCurrentForm().getAnimationManager().flushAnimation(new Runnable() { + public void run() { + sheet.back(); + sheet.addCloseListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + sheet.removeCloseListener(this); + response.actionPerformed(new ActionEvent(null)); + } + + }); + } + }); + + + break; + default: + break; + } + } + +} diff --git a/CodenameOne/src/com/codename1/impl/CaptureAudioCloseActionListener.java b/CodenameOne/src/com/codename1/impl/CaptureAudioCloseActionListener.java new file mode 100644 index 0000000000..9e9c5b06eb --- /dev/null +++ b/CodenameOne/src/com/codename1/impl/CaptureAudioCloseActionListener.java @@ -0,0 +1,35 @@ +package com.codename1.impl; + +import com.codename1.components.AudioRecorderComponent; +import com.codename1.io.FileSystemStorage; +import com.codename1.media.MediaRecorderBuilder; +import com.codename1.ui.CN; +import com.codename1.ui.events.ActionEvent; +import com.codename1.ui.events.ActionListener; + +class CaptureAudioCloseActionListener implements ActionListener { + private final AudioRecorderComponent cmp; + private final MediaRecorderBuilder builder; + private final ActionListener response; + + public CaptureAudioCloseActionListener(AudioRecorderComponent cmp, MediaRecorderBuilder builder, ActionListener response) { + this.cmp = cmp; + this.builder = builder; + this.response = response; + } + + @Override + public void actionPerformed(ActionEvent e) { + if (cmp.getState() != AudioRecorderComponent.RecorderState.Accepted && cmp.getState() != AudioRecorderComponent.RecorderState.Canceled) { + FileSystemStorage fs = FileSystemStorage.getInstance(); + if (fs.exists(builder.getPath())) { + FileSystemStorage.getInstance().delete(builder.getPath()); + } + CN.getCurrentForm().getAnimationManager().flushAnimation(new Runnable() { + public void run() { + response.actionPerformed(new ActionEvent(null)); + } + }); + } + } +} diff --git a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java index 5be7e0fea4..4c07a3be91 100644 --- a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java +++ b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java @@ -123,8 +123,8 @@ public abstract class CodenameOneImplementation { */ private static final int RTL_RANGE_BEGIN = 0x590; private static final int RTL_RANGE_END = 0x7BF; - private static Object displayLock; - private static boolean bidi; + private Object displayLock; + private boolean bidi; private static boolean pollingThreadRunning; private static PushCallback callback; private static PurchaseCallback purchaseCallback; @@ -575,7 +575,9 @@ public void stopTextEditing() { */ public void stopTextEditing(Runnable onFinish) { stopTextEditing(); - onFinish.run(); + if(onFinish != null) { + onFinish.run(); + } } /** @@ -927,16 +929,6 @@ public boolean paintNativePeersBehind() { return false; } - /** - * Returns a lock object which can be synchronized against, this lock is used - * by the EDT. - * - * @return a lock object - */ - public Object getDisplayLock() { - return displayLock; - } - /** * Installs the display lock allowing implementors to synchronize against the * Display mutex, this method is invoked internally and should not be used. @@ -999,7 +991,7 @@ public void repaint(Animation cmp) { paintQueue[paintQueueFill] = cmp; paintQueueFill++; - displayLock.notify(); + displayLock.notifyAll(); } } @@ -3793,7 +3785,7 @@ public InputStream getResourceAsStream(Class cls, String resource) { if (cls != null) { return cls.getResourceAsStream(resource); } - return getClass().getResourceAsStream(resource); + return CodenameOneImplementation.class.getResourceAsStream(resource); } /** @@ -5769,7 +5761,7 @@ public Image captureScreen() { return null; } - public void captureAudio(final com.codename1.ui.events.ActionListener response) { + public void captureAudio(final ActionListener response) { captureAudio(new MediaRecorderBuilder() .path(new com.codename1.io.File("tmpaudio.wav").getAbsolutePath()) .mimeType("audio/wav"), response); @@ -5815,7 +5807,7 @@ protected BrowserComponent createSharedJavascriptContext() { * @param response callback for the resulting data */ - public void captureAudio(final MediaRecorderBuilder recordingOptions, final com.codename1.ui.events.ActionListener response) { + public void captureAudio(final MediaRecorderBuilder recordingOptions, final ActionListener response) { final MediaRecorderBuilder builder = recordingOptions == null ? new MediaRecorderBuilder() : recordingOptions; if (!builder.isRedirectToAudioBuffer() && builder.getPath() == null) { builder.path(new com.codename1.io.File("tmpaudio.wav").getAbsolutePath()); @@ -5823,76 +5815,12 @@ public void captureAudio(final MediaRecorderBuilder recordingOptions, final com. if (!builder.isRedirectToAudioBuffer() && builder.getMimeType() == null) { builder.mimeType("audio/wav"); } - System.out.println("in captureAudio " + builder.isRedirectToAudioBuffer()); final AudioRecorderComponent cmp = new AudioRecorderComponent(builder); final Sheet sheet = new Sheet(null, "Record Audio"); sheet.getContentPane().setLayout(new com.codename1.ui.layouts.BorderLayout()); sheet.getContentPane().add(com.codename1.ui.layouts.BorderLayout.CENTER, cmp); - cmp.addActionListener(new com.codename1.ui.events.ActionListener() { - @Override - public void actionPerformed(com.codename1.ui.events.ActionEvent e) { - switch (cmp.getState()) { - case Accepted: - CN.getCurrentForm().getAnimationManager().flushAnimation(new Runnable() { - public void run() { - sheet.back(); - sheet.addCloseListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent evt) { - sheet.removeCloseListener(this); - response.actionPerformed(new com.codename1.ui.events.ActionEvent(builder.getPath())); - } - - }); - } - }); - - - break; - case Canceled: - FileSystemStorage fs = FileSystemStorage.getInstance(); - if (fs.exists(builder.getPath())) { - FileSystemStorage.getInstance().delete(builder.getPath()); - } - CN.getCurrentForm().getAnimationManager().flushAnimation(new Runnable() { - public void run() { - sheet.back(); - sheet.addCloseListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent evt) { - sheet.removeCloseListener(this); - response.actionPerformed(new com.codename1.ui.events.ActionEvent(null)); - } - - }); - } - }); - - - break; - default: - break; - } - } - - }); - sheet.addCloseListener(new com.codename1.ui.events.ActionListener() { - @Override - public void actionPerformed(com.codename1.ui.events.ActionEvent e) { - if (cmp.getState() != AudioRecorderComponent.RecorderState.Accepted && cmp.getState() != AudioRecorderComponent.RecorderState.Canceled) { - FileSystemStorage fs = FileSystemStorage.getInstance(); - if (fs.exists(builder.getPath())) { - FileSystemStorage.getInstance().delete(builder.getPath()); - } - CN.getCurrentForm().getAnimationManager().flushAnimation(new Runnable() { - public void run() { - response.actionPerformed(new com.codename1.ui.events.ActionEvent(null)); - } - }); - } - } - - }); + cmp.addActionListener(new CaptureAudioActionListener(cmp, sheet, response, builder)); + sheet.addCloseListener(new CaptureAudioCloseActionListener(cmp, builder, response)); sheet.show(); //capture(response, new String[] {"wav", "mp3", "aac"}, "*.wav;*.mp3;*.aac"); } @@ -5972,58 +5900,7 @@ public void openGallery(final ActionListener response, int type) { model.addExtensionFilter("mov"); } - FileTree t = new FileTree(model) { - - protected Button createNodeComponent(final Object node, int depth) { - if (node == null || !getModel().isLeaf(node)) { - return super.createNodeComponent(node, depth); - } - Hashtable t = (Hashtable) Storage.getInstance().readObject("thumbnails"); - if (t == null) { - t = new Hashtable(); - } - final Hashtable thumbs = t; - final Button b = super.createNodeComponent(node, depth); - b.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent evt) { - response.actionPerformed(new ActionEvent(node, ActionEvent.Type.Other)); - d.dispose(); - } - }); - final ImageIO imageio = ImageIO.getImageIO(); - if (imageio != null) { - - Display.getInstance().scheduleBackgroundTask(new Runnable() { - - public void run() { - byte[] data = (byte[]) thumbs.get(node); - if (data == null) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - try { - imageio.save(FileSystemStorage.getInstance().openInputStream((String) node), - out, - ImageIO.FORMAT_JPEG, - b.getIcon().getWidth(), b.getIcon().getHeight(), 1); - data = out.toByteArray(); - thumbs.put(node, data); - Storage.getInstance().writeObject("thumbnails", thumbs); - } catch (IOException ex) { - Log.e(ex); - } - } - if (data != null) { - Image im = Image.createImage(data, 0, data.length); - b.setIcon(im); - } - } - }); - - } - return b; - } - - }; + FileTree t = new OpenGalleryFileTree(model, response, d); d.addComponent(BorderLayout.CENTER, t); @@ -7299,10 +7176,9 @@ protected final void pushReceived(String data) { * @param freq the frequency in milliseconds */ public void setPollingFrequency(int freq) { - // PMD Fix (UnusedPrivateField): Removed obsolete pollingMillis state; method now only triggers listener wake-up. if (callback != null && pollingThreadRunning) { synchronized (callback) { - callback.notify(); + callback.notifyAll(); } } } @@ -8786,7 +8662,7 @@ public void postMessage(MessageEvent message) { * @return true in case of dark mode */ public Boolean isDarkMode() { - return null; + return Boolean.FALSE; } /** diff --git a/CodenameOne/src/com/codename1/impl/FullScreenAdService.java b/CodenameOne/src/com/codename1/impl/FullScreenAdService.java index 792b795369..1d826c8bcc 100644 --- a/CodenameOne/src/com/codename1/impl/FullScreenAdService.java +++ b/CodenameOne/src/com/codename1/impl/FullScreenAdService.java @@ -248,21 +248,12 @@ void unlock(final ActionListener callback) { AdForm adf = (AdForm) Display.getInstance().getCurrent(); synchronized (LOCK) { adf.blocked = false; - LOCK.notify(); + LOCK.notifyAll(); } // move to the next screen so the ad will be shown and so we // can return to the next screen and not this screen - Display.getInstance().callSerially(new Runnable() { - public void run() { - // prevent a potential race condition with the locking - if (Display.getInstance().getCurrent() instanceof AdForm) { - Display.getInstance().callSerially(this); - return; - } - callback.actionPerformed(null); - } - }); + Display.getInstance().callSerially(new UnlockRunnable(callback)); } class AdForm extends Form { @@ -280,7 +271,7 @@ public AdForm(Component ad) { public void actionPerformed(ActionEvent ev) { synchronized (LOCK) { blocked = false; - LOCK.notify(); + LOCK.notifyAll(); } // move to the next screen so the ad will be shown and so we @@ -301,7 +292,7 @@ public void run() { public void actionPerformed(ActionEvent ev) { synchronized (LOCK) { blocked = false; - LOCK.notify(); + LOCK.notifyAll(); } } }; @@ -350,4 +341,21 @@ public boolean animate() { return false; } } + + private static class UnlockRunnable implements Runnable { + private final ActionListener callback; + + public UnlockRunnable(ActionListener callback) { + this.callback = callback; + } + + public void run() { + // prevent a potential race condition with the locking + if (Display.getInstance().getCurrent() instanceof AdForm) { + Display.getInstance().callSerially(this); + return; + } + callback.actionPerformed(null); + } + } } diff --git a/CodenameOne/src/com/codename1/impl/OpenGalleryFileTree.java b/CodenameOne/src/com/codename1/impl/OpenGalleryFileTree.java new file mode 100644 index 0000000000..fba3ad3d25 --- /dev/null +++ b/CodenameOne/src/com/codename1/impl/OpenGalleryFileTree.java @@ -0,0 +1,92 @@ +package com.codename1.impl; + +import com.codename1.components.FileTree; +import com.codename1.components.FileTreeModel; +import com.codename1.io.FileSystemStorage; +import com.codename1.io.Log; +import com.codename1.io.Storage; +import com.codename1.ui.Button; +import com.codename1.ui.Dialog; +import com.codename1.ui.Display; +import com.codename1.ui.Image; +import com.codename1.ui.events.ActionEvent; +import com.codename1.ui.events.ActionListener; +import com.codename1.ui.util.ImageIO; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Hashtable; + +class OpenGalleryFileTree extends FileTree { + + private final ActionListener response; + private final Dialog d; + + public OpenGalleryFileTree(FileTreeModel model, ActionListener response, Dialog d) { + super(model); + this.response = response; + this.d = d; + } + + protected Button createNodeComponent(final Object node, int depth) { + if (node == null || !getModel().isLeaf(node)) { + return super.createNodeComponent(node, depth); + } + Hashtable t = (Hashtable) Storage.getInstance().readObject("thumbnails"); + if (t == null) { + t = new Hashtable(); + } + final Hashtable thumbs = t; + final Button b = super.createNodeComponent(node, depth); + b.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + response.actionPerformed(new ActionEvent(node, ActionEvent.Type.Other)); + d.dispose(); + } + }); + final ImageIO imageio = ImageIO.getImageIO(); + if (imageio != null) { + Display.getInstance().scheduleBackgroundTask( + new CreateNodeComponentRunnable(thumbs, node, imageio, b)); + } + return b; + } + + private static class CreateNodeComponentRunnable implements Runnable { + + private final Hashtable thumbs; + private final Object node; + private final ImageIO imageio; + private final Button b; + + public CreateNodeComponentRunnable(Hashtable thumbs, Object node, ImageIO imageio, Button b) { + this.thumbs = thumbs; + this.node = node; + this.imageio = imageio; + this.b = b; + } + + public void run() { + byte[] data = (byte[]) thumbs.get(node); + if (data == null) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + imageio.save(FileSystemStorage.getInstance().openInputStream((String) node), + out, + ImageIO.FORMAT_JPEG, + b.getIcon().getWidth(), b.getIcon().getHeight(), 1); + data = out.toByteArray(); + thumbs.put(node, data); + Storage.getInstance().writeObject("thumbnails", thumbs); + } catch (IOException ex) { + Log.e(ex); + } + } + if (data != null) { + Image im = Image.createImage(data, 0, data.length); + b.setIcon(im); + } + } + } +} diff --git a/CodenameOne/src/com/codename1/io/ConnectionRequest.java b/CodenameOne/src/com/codename1/io/ConnectionRequest.java index 2d64cd96b0..d509257393 100644 --- a/CodenameOne/src/com/codename1/io/ConnectionRequest.java +++ b/CodenameOne/src/com/codename1/io/ConnectionRequest.java @@ -2580,21 +2580,8 @@ public AsyncResource downloadImageToStorage(String storageFile) { */ public AsyncResource downloadImageToStorage(String storageFile, boolean useCache) { final AsyncResource out = new AsyncResource(); - downloadImageToStorage(storageFile, new SuccessCallback() { - @Override - public void onSucess(Image value) { - if (!out.isDone()) { - out.complete(value); - } - } - }, new FailureCallback() { - @Override - public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { - if (!out.isDone()) { - out.error(err); - } - } - }, useCache); + downloadImageToStorage(storageFile, new ImageStorageSuccessCallback(out), + new ImageStorageFailureCallback(out), useCache); return out; } @@ -2646,28 +2633,13 @@ public void downloadImageToStorage(String storageFile, SuccessCallback on */ public AsyncResource downloadImageToFileSystem(String file, boolean useCache) { final AsyncResource out = new AsyncResource(); - downloadImageToFileSystem(file, new SuccessCallback() { - @Override - public void onSucess(Image value) { - if (out.isDone()) { - return; - } - out.complete(value); - } - }, new FailureCallback() { - @Override - public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { - if (out.isDone()) { - return; - } - out.error(err); - } - }, useCache); + downloadImageToFileSystem(file, new ImageFileSystemSuccessCallback(out), + new ImageFileSystemFailureCallback(out), useCache); return out; } /** - * Downloads an image to a the file system asynchronously returning an AsyncResource object that resolves to the loaded image.. + * Downloads an image to the file system asynchronously returning an AsyncResource object that resolves to the loaded image.. * If useCache is true, then this will first try to load the image from Storage if it exists. This is a wrapper around {@link #downloadImageToFileSystem(java.lang.String, boolean) } * with {@literal true} as the 2nd parameter. * @@ -2962,4 +2934,66 @@ public String getCertificteAlgorithm() { return certificateAlgorithm; } } + + private static class ImageStorageSuccessCallback implements SuccessCallback { + private final AsyncResource out; + + public ImageStorageSuccessCallback(AsyncResource out) { + this.out = out; + } + + @Override + public void onSucess(Image value) { + if (!out.isDone()) { + out.complete(value); + } + } + } + + private static class ImageStorageFailureCallback implements FailureCallback { + private final AsyncResource out; + + public ImageStorageFailureCallback(AsyncResource out) { + this.out = out; + } + + @Override + public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { + if (!out.isDone()) { + out.error(err); + } + } + } + + private static class ImageFileSystemSuccessCallback implements SuccessCallback { + private final AsyncResource out; + + public ImageFileSystemSuccessCallback(AsyncResource out) { + this.out = out; + } + + @Override + public void onSucess(Image value) { + if (out.isDone()) { + return; + } + out.complete(value); + } + } + + private static class ImageFileSystemFailureCallback implements FailureCallback { + private final AsyncResource out; + + public ImageFileSystemFailureCallback(AsyncResource out) { + this.out = out; + } + + @Override + public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { + if (out.isDone()) { + return; + } + out.error(err); + } + } } diff --git a/CodenameOne/src/com/codename1/io/FileSystemStorage.java b/CodenameOne/src/com/codename1/io/FileSystemStorage.java index a22163a400..d512f78f07 100644 --- a/CodenameOne/src/com/codename1/io/FileSystemStorage.java +++ b/CodenameOne/src/com/codename1/io/FileSystemStorage.java @@ -161,7 +161,6 @@ public void delete(String file) { * @param retryCount the number of times to retry */ public void deleteRetry(final String file, final int retryCount) { - System.gc(); try { Util.getImplementation().deleteFile(file); } catch (Throwable t) { diff --git a/CodenameOne/src/com/codename1/io/NetworkManager.java b/CodenameOne/src/com/codename1/io/NetworkManager.java index 013e964162..a96c460b8f 100644 --- a/CodenameOne/src/com/codename1/io/NetworkManager.java +++ b/CodenameOne/src/com/codename1/io/NetworkManager.java @@ -602,7 +602,7 @@ void addToQueue(@Async.Schedule ConnectionRequest request, boolean retry) { addSortedToQueue(request, i); break; } - LOCK.notify(); + LOCK.notifyAll(); } } @@ -663,7 +663,7 @@ public void removeErrorListener(ActionListener e) { * * @param al action listener */ - public void addProgressListener(ActionListener al) { + public final void addProgressListener(ActionListener al) { if (progressListeners == null) { progressListeners = new EventDispatcher(); progressListeners.setBlocking(false); @@ -836,7 +836,7 @@ private boolean runCurrentRequest(@Async.Execute ConnectionRequest req) { return false; } pending.addElement(currentRequest); - LOCK.notify(); + LOCK.notifyAll(); long end = System.currentTimeMillis() + 30; while (true) { long remaining = end - System.currentTimeMillis(); diff --git a/CodenameOne/src/com/codename1/io/Oauth2.java b/CodenameOne/src/com/codename1/io/Oauth2.java index ba471ab829..83ca40a5d1 100644 --- a/CodenameOne/src/com/codename1/io/Oauth2.java +++ b/CodenameOne/src/com/codename1/io/Oauth2.java @@ -23,6 +23,7 @@ */ package com.codename1.io; +import com.codename1.compat.java.util.Objects; import com.codename1.components.InfiniteProgress; import com.codename1.components.WebBrowser; import com.codename1.ui.BrowserWindow; @@ -329,7 +330,7 @@ public Component createAuthComponent(ActionListener al) { * @param al a listener that will receive at its source either a token for * the service or an exception in case of a failure */ - public void showAuthentication(final ActionListener al) { + public void showAuthentication(final ActionListener al) { if ("HTML5".equals(CN.getPlatformName()) && useRedirectForWeb) { @@ -343,15 +344,7 @@ public void showAuthentication(final ActionListener al) { if (useBrowserWindow) { final BrowserWindow win = new BrowserWindow(buildURL()); win.setTitle("Login"); - win.addLoadListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { - String url = (String) evt.getSource(); - if (url.startsWith(redirectURI)) { - win.close(); - handleURL((String) evt.getSource(), null, al, null, null, null); - } - } - }); + win.addLoadListener(new ShowAuthenticationActionListener(win, al)); win.show(); return; @@ -364,14 +357,7 @@ public void actionPerformed(ActionEvent evt) { Form authenticationForm = new Form("Login"); authenticationForm.setScrollable(false); if (old != null) { - Command cancel = new Command("Cancel") { - public void actionPerformed(ActionEvent ev) { - if (Display.getInstance().getCurrent() == progress) { - progress.dispose(); - } - old.showBack(); - } - }; + Command cancel = new ShowAuthenticationCommand(progress, old); if (authenticationForm.getToolbar() != null) { authenticationForm.getToolbar().addCommandToLeftBar(cancel); } else { @@ -407,7 +393,7 @@ private String buildURL() { return URL.toString(); } - private Component createLoginComponent(final ActionListener al, final Form frm, final Form backToForm, final Dialog progress) { + private Component createLoginComponent(final ActionListener al, final Form frm, final Form backToForm, final Dialog progress) { String URL = buildURL(); @@ -499,26 +485,15 @@ protected void handleRedirectURLParams(Map params) { public RefreshTokenRequest refreshToken(String refreshToken) { final RefreshTokenRequest out = new RefreshTokenRequest(); - refreshToken(refreshToken, new ActionListener() { - public void actionPerformed(ActionEvent evt) { - if (out.isDone()) { - return; - } - if (evt.getSource() instanceof Throwable) { - out.error(new AsyncResource.AsyncExecutionException((Throwable) evt.getSource())); - } else { - out.complete((AccessToken) evt.getSource()); - } - } - }); + refreshToken(refreshToken, new RefreshTokenActionListener(out)); return out; } - private void refreshToken(String refreshToken, ActionListener al) { + private void refreshToken(String refreshToken, ActionListener al) { handleURL(redirectURI + "?code=" + Util.encodeUrl(refreshToken) + "&cn1_refresh_token=1", null, al, null, null, null); } - private void handleURL(String url, WebBrowser web, final ActionListener al, final Form frm, final Form backToForm, final Dialog progress) { + private void handleURL(String url, WebBrowser web, final ActionListener al, final Form frm, final Form backToForm, final Dialog progress) { if ((url.startsWith(redirectURI))) { if (progress != null && Display.getInstance().getCurrent() == progress) { progress.dispose(); @@ -568,27 +543,20 @@ protected void handleException(Exception err) { } } - /** - * {@inheritDoc} - */ - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - if (!super.equals(o)) { - return false; - } - return true; + @Override + public final boolean equals(Object o) { + if (!(o instanceof TokenRequest)) return false; + if (!super.equals(o)) return false; + + TokenRequest that = (TokenRequest) o; + return callbackCalled == that.callbackCalled; } - /** - * {@inheritDoc} - */ + @Override public int hashCode() { - return super.hashCode(); + int result = super.hashCode(); + result = 31 * result + (callbackCalled ? 1 : 0); + return result; } protected void postResponse() { @@ -686,6 +654,79 @@ private Hashtable getParamsFromURL(String url) { } public static class RefreshTokenRequest extends AsyncResource { + } + + private static class RefreshTokenActionListener implements ActionListener { + private final RefreshTokenRequest out; + + public RefreshTokenActionListener(RefreshTokenRequest out) { + this.out = out; + } + public void actionPerformed(ActionEvent evt) { + if (out.isDone()) { + return; + } + if (evt.getSource() instanceof Throwable) { + out.error(new AsyncResource.AsyncExecutionException((Throwable) evt.getSource())); + } else { + out.complete((AccessToken) evt.getSource()); + } + } + } + + private static class ShowAuthenticationCommand extends Command { + private final Dialog progress; + private final Form old; + + public ShowAuthenticationCommand(Dialog progress, Form old) { + super("Cancel"); + this.progress = progress; + this.old = old; + } + + @Override + public boolean equals(Object obj) { + if(obj instanceof ShowAuthenticationCommand) { + ShowAuthenticationCommand c = (ShowAuthenticationCommand) obj; + return super.equals(c) && + Objects.equals(progress, c.progress) && + Objects.equals(old, c.old); + } + return false; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (progress != null ? progress.hashCode() : 0); + result = 31 * result + (old != null ? old.hashCode() : 0); + return result; + } + + public void actionPerformed(ActionEvent ev) { + if (Display.getInstance().getCurrent() == progress) { + progress.dispose(); + } + old.showBack(); + } + } + + private class ShowAuthenticationActionListener implements ActionListener { + private final BrowserWindow win; + private final ActionListener al; + + public ShowAuthenticationActionListener(BrowserWindow win, ActionListener al) { + this.win = win; + this.al = al; + } + + public void actionPerformed(NetworkEvent evt) { + String url = (String) evt.getSource(); + if (url.startsWith(redirectURI)) { + win.close(); + handleURL((String) evt.getSource(), null, al, null, null, null); + } + } } } diff --git a/CodenameOne/src/com/codename1/io/Util.java b/CodenameOne/src/com/codename1/io/Util.java index 0be813a283..5cfcf6dbc5 100644 --- a/CodenameOne/src/com/codename1/io/Util.java +++ b/CodenameOne/src/com/codename1/io/Util.java @@ -700,25 +700,25 @@ public static Object readObject(DataInputStream input) throws IOException { } String type = input.readUTF(); if ("int".equals(type)) { - return new Integer(input.readInt()); + return input.readInt(); } if ("byte".equals(type)) { - return new Byte(input.readByte()); + return input.readByte(); } if ("short".equals(type)) { - return new Short(input.readShort()); + return input.readShort(); } if ("long".equals(type)) { - return new Long(input.readLong()); + return input.readLong(); } if ("float".equals(type)) { - return new Float(input.readFloat()); + return input.readFloat(); } if ("double".equals(type)) { - return new Double(input.readDouble()); + return input.readDouble(); } if ("bool".equals(type)) { - return new Boolean(input.readBoolean()); + return input.readBoolean(); } if ("String".equals(type)) { return input.readUTF(); diff --git a/CodenameOne/src/com/codename1/io/WebServiceProxyCall.java b/CodenameOne/src/com/codename1/io/WebServiceProxyCall.java index 9c33fdeaa9..d7779bbc43 100644 --- a/CodenameOne/src/com/codename1/io/WebServiceProxyCall.java +++ b/CodenameOne/src/com/codename1/io/WebServiceProxyCall.java @@ -357,82 +357,82 @@ protected void readResponse(InputStream input) throws IOException { return; case TYPE_BYTE: - returnValue = Byte.valueOf(dis.readByte()); + returnValue = dis.readByte(); break; case TYPE_CHAR: - returnValue = new Character(dis.readChar()); + returnValue = dis.readChar(); break; case TYPE_SHORT: - returnValue = Short.valueOf(dis.readShort()); + returnValue = dis.readShort(); break; case TYPE_INT: - returnValue = Integer.valueOf(dis.readInt()); + returnValue = dis.readInt(); break; case TYPE_LONG: - returnValue = Long.valueOf(dis.readLong()); + returnValue = dis.readLong(); break; case TYPE_DOUBLE: - returnValue = new Double(dis.readDouble()); + returnValue = dis.readDouble(); break; case TYPE_FLOAT: - returnValue = new Float(dis.readFloat()); + returnValue = dis.readFloat(); break; case TYPE_BOOLEAN: - returnValue = Boolean.valueOf(dis.readBoolean()); + returnValue = dis.readBoolean(); break; case TYPE_BYTE_OBJECT: if (dis.readBoolean()) { - returnValue = Byte.valueOf(dis.readByte()); + returnValue = dis.readByte(); } break; case TYPE_CHARACTER_OBJECT: if (dis.readBoolean()) { - returnValue = new Character(dis.readChar()); + returnValue = dis.readChar(); } break; case TYPE_SHORT_OBJECT: if (dis.readBoolean()) { - returnValue = Short.valueOf(dis.readShort()); + returnValue = dis.readShort(); } break; case TYPE_INTEGER_OBJECT: if (dis.readBoolean()) { - returnValue = Integer.valueOf(dis.readInt()); + returnValue = dis.readInt(); } break; case TYPE_LONG_OBJECT: if (dis.readBoolean()) { - returnValue = Long.valueOf(dis.readLong()); + returnValue = dis.readLong(); } break; case TYPE_DOUBLE_OBJECT: if (dis.readBoolean()) { - returnValue = new Double(dis.readDouble()); + returnValue = dis.readDouble(); } break; case TYPE_FLOAT_OBJECT: if (dis.readBoolean()) { - returnValue = new Float(dis.readFloat()); + returnValue = dis.readFloat(); } break; case TYPE_BOOLEAN_OBJECT: if (dis.readBoolean()) { - returnValue = Boolean.valueOf(dis.readBoolean()); + returnValue = dis.readBoolean(); } break; diff --git a/CodenameOne/src/com/codename1/io/gzip/GZIPHeader.java b/CodenameOne/src/com/codename1/io/gzip/GZIPHeader.java index 9a3230d100..267cb82bc9 100644 --- a/CodenameOne/src/com/codename1/io/gzip/GZIPHeader.java +++ b/CodenameOne/src/com/codename1/io/gzip/GZIPHeader.java @@ -119,7 +119,7 @@ public void setComment(String comment) { try { this.comment = comment.getBytes("ISO-8859-1"); } catch (UnsupportedEncodingException e) { - throw new IllegalArgumentException("comment must be in ISO-8859-1 " + name); + throw new IllegalArgumentException("comment must be in ISO-8859-1 " + comment); } } diff --git a/CodenameOne/src/com/codename1/io/gzip/InfBlocks.java b/CodenameOne/src/com/codename1/io/gzip/InfBlocks.java index f34e778ea9..b5e79f54d3 100644 --- a/CodenameOne/src/com/codename1/io/gzip/InfBlocks.java +++ b/CodenameOne/src/com/codename1/io/gzip/InfBlocks.java @@ -433,10 +433,6 @@ int proc(int r) { k += 8; } - if (tb[0] == -1) { - //System.err.println("null..."); - } - t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1]; c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2]; @@ -504,7 +500,6 @@ int proc(int r) { { bl[0] = 9; // must be <= 9 for lookahead assumptions bd[0] = 6; // must be <= 9 for lookahead assumptions - t = table; t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl, bd, tli, tdi, hufts, z); @@ -557,14 +552,12 @@ int proc(int r) { write = q; r = inflate_flush(r); q = write; - m = q < read ? read - q - 1 : end - q; if (read != write) { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; - write = q; return inflate_flush(r); } mode = DONE; diff --git a/CodenameOne/src/com/codename1/io/gzip/Inflate.java b/CodenameOne/src/com/codename1/io/gzip/Inflate.java index ab443cb850..610e667445 100644 --- a/CodenameOne/src/com/codename1/io/gzip/Inflate.java +++ b/CodenameOne/src/com/codename1/io/gzip/Inflate.java @@ -299,7 +299,6 @@ int inflate(int f) { case DICT1: if (z.avail_in == 0) return r; - r = f; z.avail_in--; z.total_in++; diff --git a/CodenameOne/src/com/codename1/io/rest/RequestBuilder.java b/CodenameOne/src/com/codename1/io/rest/RequestBuilder.java index de1740f9ef..edff6bd1ff 100644 --- a/CodenameOne/src/com/codename1/io/rest/RequestBuilder.java +++ b/CodenameOne/src/com/codename1/io/rest/RequestBuilder.java @@ -257,22 +257,12 @@ public RequestBuilder header(String key, String value) { /** * Sets the request body * - * @param body request bodyContent + * @param bodyContent request body content * @return RequestBuilder instance */ public RequestBuilder body(final String bodyContent) { checkFetched(); - this.body = new Data() { - @Override - public void appendTo(OutputStream output) throws IOException { - output.write(bodyContent.getBytes("UTF-8")); - } - - @Override - public long getSize() throws IOException { - return bodyContent.getBytes("UTF-8").length; - } - }; + this.body = new BodyData(bodyContent); return this; } @@ -476,25 +466,7 @@ public ConnectionRequest fetchAsString(final OnComplete> callba private ConnectionRequest getAsStringAsyncImpl(final Object callback) { final Connection request = createRequest(false); - request.addResponseListener(new ActionListener() { - @Override - public void actionPerformed(NetworkEvent evt) { - if (request.errorCode) { - return; - } - Response res = null; - try { - res = new Response(evt.getResponseCode(), new String(evt.getConnectionRequest().getResponseData(), "UTF-8"), evt.getMessage()); - if (callback instanceof Callback) { - ((Callback) callback).onSucess(res); - } else { - ((OnComplete>) callback).completed(res); - } - } catch (UnsupportedEncodingException ex) { - ex.printStackTrace(); - } - } - }); + request.addResponseListener(new GetAsStringAsyncImplActionListener(request, callback)); fetched = true; CN.addToQueue(request); return request; @@ -549,21 +521,7 @@ public ConnectionRequest fetchAsBytes(final OnComplete> callbac private ConnectionRequest getAsBytesAsyncImpl(final Object callback) { final Connection request = createRequest(false); - request.addResponseListener(new ActionListener() { - @Override - public void actionPerformed(NetworkEvent evt) { - if (request.errorCode) { - return; - } - Response res = null; - res = new Response(evt.getResponseCode(), evt.getConnectionRequest().getResponseData(), evt.getMessage()); - if (callback instanceof Callback) { - ((Callback) callback).onSucess(res); - } else { - ((OnComplete) callback).completed(res); - } - } - }); + request.addResponseListener(new GetAsBytesAsyncImplActionListener(request, callback)); fetched = true; CN.addToQueue(request); return request; @@ -602,18 +560,7 @@ public Response getAsBytes() { */ public ConnectionRequest fetchAsJsonMap(final OnComplete> callback) { final Connection request = createRequest(true); - request.addResponseListener(new ActionListener() { - @Override - public void actionPerformed(NetworkEvent evt) { - if (request.errorCode) { - return; - } - Response res = null; - Map response = (Map) evt.getMetaData(); - res = new Response(evt.getResponseCode(), response, evt.getMessage()); - callback.completed(res); - } - }); + request.addResponseListener(new FetchAsJsonMapActionListener(request, callback)); fetched = true; CN.addToQueue(request); return request; @@ -630,25 +577,7 @@ public void actionPerformed(NetworkEvent evt) { public ConnectionRequest fetchAsProperties(final OnComplete> callback, final Class type) { useBoolean(true); final Connection request = createRequest(true); - request.addResponseListener(new ActionListener() { - @Override - public void actionPerformed(NetworkEvent evt) { - if (request.errorCode) { - return; - } - Response res = null; - Map response = (Map) evt.getMetaData(); - try { - PropertyBusinessObject pb = (PropertyBusinessObject) type.newInstance(); - pb.getPropertyIndex().populateFromMap(response); - res = new Response(evt.getResponseCode(), pb, evt.getMessage()); - callback.completed(res); - } catch (Exception err) { - Log.e(err); - throw new RuntimeException(err.toString()); - } - } - }); + request.addResponseListener(new FetchAsPropertiesActionListener(request, type, callback)); fetched = true; CN.addToQueue(request); return request; @@ -677,24 +606,7 @@ public ConnectionRequest getAsJsonMap(final SuccessCallback> callb */ public ConnectionRequest getAsJsonMap(final SuccessCallback> callback, final FailureCallback onError) { final Connection request = createRequest(true); - request.addResponseListener(new ActionListener() { - @Override - public void actionPerformed(NetworkEvent evt) { - if (request.errorCode) { - return; - } - if (onError != null) { - // this is an error response code and should be handled as an error - if (evt.getResponseCode() > 310) { - return; - } - } - Response res = null; - Map response = (Map) evt.getMetaData(); - res = new Response(evt.getResponseCode(), response, evt.getMessage()); - callback.onSucess(res); - } - }); + request.addResponseListener(new GetAsJsonMapActionListener(request, onError, callback)); bindOnError(request, onError); fetched = true; CN.addToQueue(request); @@ -705,18 +617,8 @@ private void bindOnError(final ConnectionRequest req, final FailureCallback() { - public void actionPerformed(NetworkEvent evt) { - evt.consume(); - f.onError(null, evt.getError(), evt.getResponseCode(), evt.getMessage()); - } - }); - req.addExceptionListener(new ActionListener() { - public void actionPerformed(NetworkEvent evt) { - evt.consume(); - f.onError(null, evt.getError(), evt.getResponseCode(), evt.getMessage()); - } - }); + req.addResponseCodeListener(new BindOnErrorResponseCodeActionListener(f)); + req.addExceptionListener(new BindOnErrorExceptionActionListener(f)); } /** @@ -777,36 +679,7 @@ public Response getAsProperties(Class type) { public ConnectionRequest fetchAsPropertyList(final OnComplete>> callback, final Class type, final String root) { useBoolean(true); final Connection request = createRequest(true); - request.addResponseListener(new ActionListener() { - @Override - public void actionPerformed(NetworkEvent evt) { - if (request.errorCode) { - return; - } - Response res = null; - Map response = (Map) evt.getMetaData(); - if (response == null) { - return; - } - List lst = (List) response.get(root); - if (lst == null) { - return; - } - try { - List result = new ArrayList(); - for (Map m : lst) { - PropertyBusinessObject pb = (PropertyBusinessObject) type.newInstance(); - pb.getPropertyIndex().populateFromMap(m); - result.add(pb); - } - res = new Response(evt.getResponseCode(), result, evt.getMessage()); - callback.completed(res); - } catch (Exception err) { - Log.e(err); - throw new RuntimeException(err.toString()); - } - } - }); + request.addResponseListener(new FetchAsPropertyListActionListener(request, root, type, callback)); fetched = true; CN.addToQueue(request); return request; @@ -942,6 +815,225 @@ private Connection createRequest(boolean parseJson) { return req; } + private static class FetchAsPropertyListActionListener implements ActionListener { + private final Connection request; + private final String root; + private final Class type; + private final OnComplete>> callback; + + public FetchAsPropertyListActionListener(Connection request, String root, Class type, OnComplete>> callback) { + this.request = request; + this.root = root; + this.type = type; + this.callback = callback; + } + + @Override + public void actionPerformed(NetworkEvent evt) { + if (request.errorCode) { + return; + } + Response res = null; + Map response = (Map) evt.getMetaData(); + if (response == null) { + return; + } + List lst = (List) response.get(root); + if (lst == null) { + return; + } + try { + List result = new ArrayList(); + for (Map m : lst) { + PropertyBusinessObject pb = (PropertyBusinessObject) type.newInstance(); + pb.getPropertyIndex().populateFromMap(m); + result.add(pb); + } + res = new Response(evt.getResponseCode(), result, evt.getMessage()); + callback.completed(res); + } catch (Exception err) { + Log.e(err); + throw new RuntimeException(err.toString()); + } + } + } + + private static class BindOnErrorExceptionActionListener implements ActionListener { + private final FailureCallback f; + + public BindOnErrorExceptionActionListener(FailureCallback f) { + this.f = f; + } + + public void actionPerformed(NetworkEvent evt) { + evt.consume(); + f.onError(null, evt.getError(), evt.getResponseCode(), evt.getMessage()); + } + } + + private static class BindOnErrorResponseCodeActionListener implements ActionListener { + private final FailureCallback f; + + public BindOnErrorResponseCodeActionListener(FailureCallback f) { + this.f = f; + } + + public void actionPerformed(NetworkEvent evt) { + evt.consume(); + f.onError(null, evt.getError(), evt.getResponseCode(), evt.getMessage()); + } + } + + private static class GetAsJsonMapActionListener implements ActionListener { + private final Connection request; + private final FailureCallback onError; + private final SuccessCallback> callback; + + public GetAsJsonMapActionListener(Connection request, FailureCallback onError, SuccessCallback> callback) { + this.request = request; + this.onError = onError; + this.callback = callback; + } + + @Override + public void actionPerformed(NetworkEvent evt) { + if (request.errorCode) { + return; + } + if (onError != null) { + // this is an error response code and should be handled as an error + if (evt.getResponseCode() > 310) { + return; + } + } + Response res = null; + Map response = (Map) evt.getMetaData(); + res = new Response(evt.getResponseCode(), response, evt.getMessage()); + callback.onSucess(res); + } + } + + private static class FetchAsPropertiesActionListener implements ActionListener { + private final Connection request; + private final Class type; + private final OnComplete> callback; + + public FetchAsPropertiesActionListener(Connection request, Class type, OnComplete> callback) { + this.request = request; + this.type = type; + this.callback = callback; + } + + @Override + public void actionPerformed(NetworkEvent evt) { + if (request.errorCode) { + return; + } + Response res = null; + Map response = (Map) evt.getMetaData(); + try { + PropertyBusinessObject pb = (PropertyBusinessObject) type.newInstance(); + pb.getPropertyIndex().populateFromMap(response); + res = new Response(evt.getResponseCode(), pb, evt.getMessage()); + callback.completed(res); + } catch (Exception err) { + Log.e(err); + throw new RuntimeException(err.toString()); + } + } + } + + private static class FetchAsJsonMapActionListener implements ActionListener { + private final Connection request; + private final OnComplete> callback; + + public FetchAsJsonMapActionListener(Connection request, OnComplete> callback) { + this.request = request; + this.callback = callback; + } + + @Override + public void actionPerformed(NetworkEvent evt) { + if (request.errorCode) { + return; + } + Response res = null; + Map response = (Map) evt.getMetaData(); + res = new Response(evt.getResponseCode(), response, evt.getMessage()); + callback.completed(res); + } + } + + private static class GetAsBytesAsyncImplActionListener implements ActionListener { + private final Connection request; + private final Object callback; + + public GetAsBytesAsyncImplActionListener(Connection request, Object callback) { + this.request = request; + this.callback = callback; + } + + @Override + public void actionPerformed(NetworkEvent evt) { + if (request.errorCode) { + return; + } + Response res = null; + res = new Response(evt.getResponseCode(), evt.getConnectionRequest().getResponseData(), evt.getMessage()); + if (callback instanceof Callback) { + ((Callback) callback).onSucess(res); + } else { + ((OnComplete) callback).completed(res); + } + } + } + + private static class GetAsStringAsyncImplActionListener implements ActionListener { + private final Connection request; + private final Object callback; + + public GetAsStringAsyncImplActionListener(Connection request, Object callback) { + this.request = request; + this.callback = callback; + } + + @Override + public void actionPerformed(NetworkEvent evt) { + if (request.errorCode) { + return; + } + Response res = null; + try { + res = new Response(evt.getResponseCode(), new String(evt.getConnectionRequest().getResponseData(), "UTF-8"), evt.getMessage()); + if (callback instanceof Callback) { + ((Callback) callback).onSucess(res); + } else { + ((OnComplete>) callback).completed(res); + } + } catch (UnsupportedEncodingException ex) { + ex.printStackTrace(); + } + } + } + + private static class BodyData implements Data { + private final String bodyContent; + + public BodyData(String bodyContent) { + this.bodyContent = bodyContent; + } + + @Override + public void appendTo(OutputStream output) throws IOException { + output.write(bodyContent.getBytes("UTF-8")); + } + + @Override + public long getSize() throws IOException { + return bodyContent.getBytes("UTF-8").length; + } + } + class Connection extends GZConnectionRequest { boolean errorCode; Map json; diff --git a/CodenameOne/src/com/codename1/io/services/RSSService.java b/CodenameOne/src/com/codename1/io/services/RSSService.java index 4cb1b1124f..92905d3650 100644 --- a/CodenameOne/src/com/codename1/io/services/RSSService.java +++ b/CodenameOne/src/com/codename1/io/services/RSSService.java @@ -134,13 +134,77 @@ public int hashCode() { return result; } + static class FinishParsing extends RuntimeException { + } + /** * {@inheritDoc} */ protected void readResponse(InputStream input) throws IOException { results = new Vector(); - class FinishParsing extends RuntimeException { + XMLParser p = getXmlParser(); + input.mark(10); + + // Skip the bom marking UTF-8 in some streams + while (input.read() != '<') { + //input.mark(4); + } + int question = input.read(); + String cType = "UTF-8"; + if (question == '?') { + // we are in an XML header, check if the encoding section exists + StringBuilder cs = new StringBuilder(); + question = input.read(); + while (question != '>') { + cs.append((char) question); + question = input.read(); + } + String str = cs.toString(); + int index = str.indexOf("encoding=\"") + 10; + if (index > -1) { + cType = str.substring(index, Math.max(str.indexOf("\"", index), str.indexOf("'", index))); + } + } else { + // oops, continue as usual + input.reset(); + } + + String resultType = getResponseContentType(); + if (resultType != null && resultType.indexOf("charset=") > -1) { + cType = resultType.substring(resultType.indexOf("charset=") + 8); } + try { + int pos2 = cType.indexOf(';'); + if (pos2 > 0) { + cType = cType.substring(0, pos2); + } + p.eventParser(new InputStreamReader(input, cType)); + } catch (FinishParsing ignor) { + hasMore = true; + } + + if (isCreatePlainTextDetails()) { + int elementCount = results.size(); + for (int iter = 0; iter < elementCount; iter++) { + Hashtable h = (Hashtable) results.elementAt(iter); + String s = (String) h.get("description"); + if (s != null && !h.containsKey("details")) { + XMLParser x = new XMLParser(); + Element e = x.parse(new CharArrayReader(("" + s + "").toCharArray())); + Vector results = e.getTextDescendants(null, false); + StringBuilder endResult = new StringBuilder(); + for (int i = 0; i < results.size(); i++) { + endResult.append(((Element) results.elementAt(i)).getText()); + } + h.put("details", endResult.toString()); + } + } + } + + fireResponseListener(new NetworkEvent(this, results)); + } + + private XMLParser getXmlParser() { XMLParser p = new XMLParser() { private String lastTag; private Hashtable current; @@ -205,65 +269,7 @@ protected void endTag(String tag) { } }; p.setParserCallback(this); - input.mark(10); - - // Skip the bom marking UTF-8 in some streams - while (input.read() != '<') { - //input.mark(4); - } - int question = input.read(); - String cType = "UTF-8"; - if (question == '?') { - // we are in an XML header, check if the encoding section exists - StringBuilder cs = new StringBuilder(); - question = input.read(); - while (question != '>') { - cs.append((char) question); - question = input.read(); - } - String str = cs.toString(); - int index = str.indexOf("encoding=\"") + 10; - if (index > -1) { - cType = str.substring(index, Math.max(str.indexOf("\"", index), str.indexOf("'", index))); - } - } else { - // oops, continue as usual - input.reset(); - } - - String resultType = getResponseContentType(); - if (resultType != null && resultType.indexOf("charset=") > -1) { - cType = resultType.substring(resultType.indexOf("charset=") + 8); - } - try { - int pos2 = cType.indexOf(';'); - if (pos2 > 0) { - cType = cType.substring(0, pos2); - } - p.eventParser(new InputStreamReader(input, cType)); - } catch (FinishParsing ignor) { - hasMore = true; - } - - if (isCreatePlainTextDetails()) { - int elementCount = results.size(); - for (int iter = 0; iter < elementCount; iter++) { - Hashtable h = (Hashtable) results.elementAt(iter); - String s = (String) h.get("description"); - if (s != null && !h.containsKey("details")) { - XMLParser x = new XMLParser(); - Element e = x.parse(new CharArrayReader(("" + s + "").toCharArray())); - Vector results = e.getTextDescendants(null, false); - StringBuilder endResult = new StringBuilder(); - for (int i = 0; i < results.size(); i++) { - endResult.append(((Element) results.elementAt(i)).getText()); - } - h.put("details", endResult.toString()); - } - } - } - - fireResponseListener(new NetworkEvent(this, results)); + return p; } diff --git a/CodenameOne/src/com/codename1/javascript/JSObject.java b/CodenameOne/src/com/codename1/javascript/JSObject.java index 58423f5413..7edcea9f50 100644 --- a/CodenameOne/src/com/codename1/javascript/JSObject.java +++ b/CodenameOne/src/com/codename1/javascript/JSObject.java @@ -269,7 +269,6 @@ public JSObject(JavascriptContext context, String expr) { R1 + "." + PROP_REFCOUNT + "++;" + "} id"; - String id = exec(js); this.objectId = Integer.parseInt(id); context.retain(this); @@ -769,14 +768,7 @@ public void callAsync(String key, Object[] params, Callback callback) { * @param callback Callback to be called when the method call is completed. */ public void callAsync(String key, Object[] params, final SuccessCallback callback) { - this.callAsync(key, params, new CallbackAdapter() { - - @Override - public void onSucess(Object value) { - callback.onSucess(value); - } - - }); + this.callAsync(key, params, new CallAsyncCallbackAdapter(callback)); } /** @@ -806,14 +798,7 @@ public void callAsync(String key, Callback callback) { * @param callback Callback to be called with the return value. */ public void callAsync(String key, final SuccessCallback callback) { - callAsync(key, new CallbackAdapter() { - - @Override - public void onSucess(Object value) { - callback.onSucess(value); - } - - }); + callAsync(key, new CallAsyncCallbackAdapter(callback)); } /** @@ -835,17 +820,7 @@ public int callInt(String key) { * @param callback Callback to handle the return value. */ public void callIntAsync(String key, final Callback callback) { - callDoubleAsync(key, new Callback() { - - public void onSucess(Double value) { - callback.onSucess(value.intValue()); - } - - public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { - callback.onError(sender, err, errorCode, errorMessage); - } - - }); + callDoubleAsync(key, new CallIntAsyncCallback(callback)); } /** @@ -856,14 +831,7 @@ public void onError(Object sender, Throwable err, int errorCode, String errorMes * @param callback Callback to handle the return value. */ public void callIntAsync(String key, final SuccessCallback callback) { - callIntAsync(key, new CallbackAdapter() { - - @Override - public void onSucess(Integer value) { - callback.onSucess(value); - } - - }); + callIntAsync(key, new CallIntAsyncCallbackAdapter(callback)); } /** @@ -896,14 +864,7 @@ public void callDoubleAsync(String key, Callback callback) { * @param callback Callback to handle the return value. */ public void callDoubleAsync(String key, final SuccessCallback callback) { - callDoubleAsync(key, new CallbackAdapter() { - - @Override - public void onSucess(Double value) { - callback.onSucess(value); - } - - }); + callDoubleAsync(key, new CallDoubleAsyncCallbackAdapter(callback)); } /** @@ -935,13 +896,7 @@ public void callStringAsync(String key, Callback callback) { * @param callback Callback to handle the return value. */ public void callStringAsync(String key, final SuccessCallback callback) { - callStringAsync(key, new CallbackAdapter() { - - @Override - public void onSucess(String value) { - callback.onSucess(value); - } - }); + callStringAsync(key, new CallStringAsyncCallbackAdapter(callback)); } /** @@ -973,13 +928,7 @@ public void callObjectAsync(String key, Callback callback) { * @param callback Callback to handle the return value. */ public void callObjectAsync(String key, final SuccessCallback callback) { - callObjectAsync(key, new CallbackAdapter() { - - @Override - public void onSucess(JSObject value) { - callback.onSucess(value); - } - }); + callObjectAsync(key, new CallObjectAsyncCallbackAdapter(callback)); } /** @@ -1058,14 +1007,7 @@ public void callAsync(Object[] params, Callback callback) { * Java type and passed to the callback. */ public void callAsync(Object[] params, final SuccessCallback callback) { - callAsync(params, new CallbackAdapter() { - - @Override - public void onSucess(Object value) { - callback.onSucess(value); - } - - }); + callAsync(params, new CallAsyncCallbackAdapter(callback)); } /** @@ -1079,4 +1021,92 @@ public String toString() { } + private static class CallAsyncCallbackAdapter extends CallbackAdapter { + private final SuccessCallback callback; + + public CallAsyncCallbackAdapter(SuccessCallback callback) { + this.callback = callback; + } + + @Override + public void onSucess(Object value) { + callback.onSucess(value); + } + } + + private static class CallObjectAsyncCallbackAdapter extends CallbackAdapter { + + private final SuccessCallback callback; + + public CallObjectAsyncCallbackAdapter(SuccessCallback callback) { + this.callback = callback; + } + + @Override + public void onSucess(JSObject value) { + callback.onSucess(value); + } + } + + private static class CallStringAsyncCallbackAdapter extends CallbackAdapter { + + private final SuccessCallback callback; + + public CallStringAsyncCallbackAdapter(SuccessCallback callback) { + this.callback = callback; + } + + @Override + public void onSucess(String value) { + callback.onSucess(value); + } + } + + private static class CallDoubleAsyncCallbackAdapter extends CallbackAdapter { + + private final SuccessCallback callback; + + public CallDoubleAsyncCallbackAdapter(SuccessCallback callback) { + this.callback = callback; + } + + @Override + public void onSucess(Double value) { + callback.onSucess(value); + } + + } + + private static class CallIntAsyncCallbackAdapter extends CallbackAdapter { + + private final SuccessCallback callback; + + public CallIntAsyncCallbackAdapter(SuccessCallback callback) { + this.callback = callback; + } + + @Override + public void onSucess(Integer value) { + callback.onSucess(value); + } + + } + + private static class CallIntAsyncCallback implements Callback { + + private final Callback callback; + + public CallIntAsyncCallback(Callback callback) { + this.callback = callback; + } + + public void onSucess(Double value) { + callback.onSucess(value.intValue()); + } + + public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { + callback.onError(sender, err, errorCode, errorMessage); + } + + } } diff --git a/CodenameOne/src/com/codename1/javascript/JavascriptContext.java b/CodenameOne/src/com/codename1/javascript/JavascriptContext.java index eca93b55a5..fcd991cba9 100644 --- a/CodenameOne/src/com/codename1/javascript/JavascriptContext.java +++ b/CodenameOne/src/com/codename1/javascript/JavascriptContext.java @@ -119,7 +119,7 @@ public class JavascriptContext { * is packaged by the JavascriptContext class in response to a * BrowserNavigationCallback. */ - private final ActionListener scriptMessageListener; + private final ActionListener scriptMessageListener; /** * A handler for navigation attempts. This intercepts URLs of the * form cn1command:... . This is how Javascript communicates/calls @@ -180,7 +180,7 @@ public final void setBrowserComponent(BrowserComponent c) { } /** - * Increments the reference count for a the javascript object wrapped by + * Increments the reference count for the javascript object wrapped by * the given JSObject. This may also trigger a cleanup of the object map if * the map grows too big, or it randomly decided to perform cleanup. * @@ -420,13 +420,7 @@ public void apply(JSObject self, Object[] args) { * @param callback Callback to be called with the result of the expression. */ public void getAsync(String javascript, final SuccessCallback callback) { - getAsync(javascript, new CallbackAdapter() { - - @Override - public void onSucess(Object value) { - callback.onSucess(value); - } - }); + getAsync(javascript, new GetAsyncCallbackAdapter(callback)); } /** @@ -841,14 +835,7 @@ public void callAsync(String jsFunc, JSObject self, Object[] params, Callback ca * object type. */ public void callAsync(String jsFunc, JSObject self, Object[] params, final SuccessCallback callback) { - callAsync(jsFunc, self, params, new CallbackAdapter() { - - @Override - public void onSucess(Object value) { - callback.onSucess(value); - } - - }); + callAsync(jsFunc, self, params, new CallAsyncCallbackAdapter(callback)); } /** @@ -960,6 +947,35 @@ public void onSucess(Object value) { }); } + private static class GetAsyncCallbackAdapter extends CallbackAdapter { + + private final SuccessCallback callback; + + public GetAsyncCallbackAdapter(SuccessCallback callback) { + this.callback = callback; + } + + @Override + public void onSucess(Object value) { + callback.onSucess(value); + } + } + + private static class CallAsyncCallbackAdapter extends CallbackAdapter { + + private final SuccessCallback callback; + + public CallAsyncCallbackAdapter(SuccessCallback callback) { + this.callback = callback; + } + + @Override + public void onSucess(Object value) { + callback.onSucess(value); + } + + } + /** * A navigation callback that handles navigations to urls of the form * cn1command:... @@ -1000,9 +1016,9 @@ public boolean shouldNavigate(String url) { * @see addCallback() * @see JSObject.addCallback() */ - private class ScriptMessageListener implements ActionListener { + private class ScriptMessageListener implements ActionListener { - public void actionPerformed(ActionEvent evt) { + public void actionPerformed(JavascriptEvent evt) { JavascriptEvent jevt = (JavascriptEvent) evt; JSObject source = jevt.getSelf(); String method = jevt.getMethod(); diff --git a/CodenameOne/src/com/codename1/l10n/SimpleDateFormat.java b/CodenameOne/src/com/codename1/l10n/SimpleDateFormat.java index ea6bbd6d37..2ddae74e99 100644 --- a/CodenameOne/src/com/codename1/l10n/SimpleDateFormat.java +++ b/CodenameOne/src/com/codename1/l10n/SimpleDateFormat.java @@ -561,7 +561,7 @@ public Date parse(String source) throws ParseException { switch (patternChar) { case LITERAL_LETTER: s = readLiteral(source, startIndex, token); - if (!s.equalsIgnoreCase(token)) { + if (s == null || !s.equalsIgnoreCase(token)) { throw new ParseException("Unparseable string " + source, startIndex); } break; diff --git a/CodenameOne/src/com/codename1/location/LocationManager.java b/CodenameOne/src/com/codename1/location/LocationManager.java index 63a29e28dc..cb29be9d96 100644 --- a/CodenameOne/src/com/codename1/location/LocationManager.java +++ b/CodenameOne/src/com/codename1/location/LocationManager.java @@ -52,7 +52,7 @@ public abstract class LocationManager { public static final int OUT_OF_SERVICE = 1; public static final int TEMPORARILY_UNAVAILABLE = 2; private static LocationListener listener; - private static LocationRequest request; + private LocationRequest request; private static Class backgroundlistener; private int status = TEMPORARILY_UNAVAILABLE; diff --git a/CodenameOne/src/com/codename1/maps/CacheProviderProxy.java b/CodenameOne/src/com/codename1/maps/CacheProviderProxy.java index 0bb3332ee8..6d8e6875d5 100644 --- a/CodenameOne/src/com/codename1/maps/CacheProviderProxy.java +++ b/CodenameOne/src/com/codename1/maps/CacheProviderProxy.java @@ -30,15 +30,11 @@ class CacheProviderProxy extends MapProvider { private final MapProvider provider; private final WeakHashMap _cache; - private int _time; - private int _maxSize; CacheProviderProxy(MapProvider provider) { super(provider.projection(), provider.tileSize()); this.provider = provider; _cache = new WeakHashMap(); - _time = 0; - _maxSize = 100; } public int maxZoomLevel() { @@ -70,34 +66,28 @@ public MapProvider originalProvider() { } protected Tile get(BoundingBox bbox) { - _time += 1; Object o = _cache.get(bbox); if (o == null) { return null; } - AgeableTile tile = (AgeableTile) o; - tile.age = _time; - return tile; + return (Tile) o; } protected void put(BoundingBox bbox, Tile tile) { - _cache.put(bbox, new AgeableTile(tile, _time)); + _cache.put(bbox, new AgeableTile(tile)); } public void clearCache() { - _maxSize = 6; _cache.clear(); } static class AgeableTile extends Tile { - public int age; private final Tile tile; - public AgeableTile(Tile tile, int time) { + public AgeableTile(Tile tile) { super(tile.dimension(), tile.getBoundingBox(), null); this.tile = tile; - this.age = time; } public boolean paint(Graphics g) { diff --git a/CodenameOne/src/com/codename1/maps/MapComponent.java b/CodenameOne/src/com/codename1/maps/MapComponent.java index e287a38904..89f3785993 100644 --- a/CodenameOne/src/com/codename1/maps/MapComponent.java +++ b/CodenameOne/src/com/codename1/maps/MapComponent.java @@ -168,7 +168,7 @@ public MapComponent(MapProvider provider, Coord centerPosition, int zoomLevel, b _layers = new Vector(); setFocusable(false); if (Display.getInstance().isTouchScreenDevice() && getUIManager().isThemeConstant("mapZoomButtonsBool", true)) { - setLayout(new BorderLayout()); + super.setLayout(new BorderLayout()); Container buttonsbar = new Container(new FlowLayout(Component.RIGHT)); Button out = new Button("-"); out.setUIID("MapZoomOut"); diff --git a/CodenameOne/src/com/codename1/media/AbstractMedia.java b/CodenameOne/src/com/codename1/media/AbstractMedia.java index f0f1e3ecc8..4246044710 100644 --- a/CodenameOne/src/com/codename1/media/AbstractMedia.java +++ b/CodenameOne/src/com/codename1/media/AbstractMedia.java @@ -185,21 +185,8 @@ public void onSucess(Throwable value) { } if (pendingPlayRequest != null && pendingPlayRequest != out) { - pendingPlayRequest.ready(new SuccessCallback() { - @Override - public void onSucess(AsyncMedia value) { - if (!out.isDone()) { - out.complete(value); - } - } - }).except(new SuccessCallback() { - @Override - public void onSucess(Throwable value) { - if (!out.isDone()) { - out.error(value); - } - } - }); + pendingPlayRequest.ready(new PlayAsyncSuccessCallback(out)) + .except(new PlayAsyncExceptSuccessCallback(out)); return out; } else { pendingPlayRequest = out; @@ -304,21 +291,8 @@ public void onSucess(Throwable value) { return out; } if (pendingPauseRequest != null && pendingPauseRequest != out) { - pendingPauseRequest.ready(new SuccessCallback() { - @Override - public void onSucess(AsyncMedia value) { - if (!out.isDone()) { - out.complete(value); - } - } - }).except(new SuccessCallback() { - @Override - public void onSucess(Throwable value) { - if (!out.isDone()) { - out.error(value); - } - } - }); + pendingPauseRequest.ready(new PauseAsyncSuccessCallback(out)) + .except(new PauseAsyncExceptSuccessCallback(out)); return out; } else { pendingPauseRequest = out; @@ -394,4 +368,64 @@ public final void play() { public final void pause() { pauseAsync(); } + + private static class PauseAsyncSuccessCallback implements SuccessCallback { + private final PauseRequest out; + + public PauseAsyncSuccessCallback(PauseRequest out) { + this.out = out; + } + + @Override + public void onSucess(AsyncMedia value) { + if (!out.isDone()) { + out.complete(value); + } + } + } + + private static class PauseAsyncExceptSuccessCallback implements SuccessCallback { + private final PauseRequest out; + + public PauseAsyncExceptSuccessCallback(PauseRequest out) { + this.out = out; + } + + @Override + public void onSucess(Throwable value) { + if (!out.isDone()) { + out.error(value); + } + } + } + + private static class PlayAsyncSuccessCallback implements SuccessCallback { + private final PlayRequest out; + + public PlayAsyncSuccessCallback(PlayRequest out) { + this.out = out; + } + + @Override + public void onSucess(AsyncMedia value) { + if (!out.isDone()) { + out.complete(value); + } + } + } + + private static class PlayAsyncExceptSuccessCallback implements SuccessCallback { + private final PlayRequest out; + + public PlayAsyncExceptSuccessCallback(PlayRequest out) { + this.out = out; + } + + @Override + public void onSucess(Throwable value) { + if (!out.isDone()) { + out.error(value); + } + } + } } diff --git a/CodenameOne/src/com/codename1/payment/Purchase.java b/CodenameOne/src/com/codename1/payment/Purchase.java index 4ada6161d9..3798818ae4 100644 --- a/CodenameOne/src/com/codename1/payment/Purchase.java +++ b/CodenameOne/src/com/codename1/payment/Purchase.java @@ -53,11 +53,12 @@ public abstract class Purchase { private static final String RECEIPTS_KEY = "CN1SubscriptionsData.dat"; private static final String RECEIPTS_REFRESH_TIME_KEY = "CN1SubscriptionsDataRefreshTime.dat"; private static final String PENDING_PURCHASE_KEY = "PendingPurchases.dat"; + private static final Object PENDING_PURCHASE_LOCK = new Object(); private static final Object synchronizationLock = new Object(); private static final Object receiptsLock = new Object(); - private static ReceiptStore receiptStore; - private static List receipts; - private static Date receiptsRefreshTime; + private ReceiptStore receiptStore; + private List receipts; + private Date receiptsRefreshTime; /** * Boolean flag to prevent {@link #synchronizeReceipts(long, com.codename1.util.SuccessCallback) } * re-entry. @@ -280,7 +281,7 @@ public boolean isItemListingSupported() { /** * Returns the product list for the given SKU array * - * @param sku the ids for the specific products + * @param skus the ids for the specific products * @return the product instances * @throws RuntimeException This method is a part of the managed payments API and will fail if * isManagedPaymentSupported() returns false @@ -394,8 +395,9 @@ public void unsubscribe(String sku) { * * @return List of receipts that haven't been sent to the server. */ + @SuppressWarnings("unchecked") public List getPendingPurchases() { - synchronized (PENDING_PURCHASE_KEY) { + synchronized (PENDING_PURCHASE_LOCK) { Storage s = Storage.getInstance(); Util.register(new Receipt()); if (s.exists(PENDING_PURCHASE_KEY)) { @@ -409,10 +411,10 @@ public List getPendingPurchases() { /** * Adds a receipt to be pushed to the server. * - * @param receipt + * @param receipt the receipt */ private void addPendingPurchase(Receipt receipt) { - synchronized (PENDING_PURCHASE_KEY) { + synchronized (PENDING_PURCHASE_LOCK) { Storage s = Storage.getInstance(); List pendingPurchases = getPendingPurchases(); pendingPurchases.add(receipt); @@ -423,11 +425,11 @@ private void addPendingPurchase(Receipt receipt) { /** * Removes a receipt from pending purchases. * - * @param transactionId - * @return + * @param transactionId the transaction id + * @return the removed receipt */ private Receipt removePendingPurchase(String transactionId) { - synchronized (PENDING_PURCHASE_KEY) { + synchronized (PENDING_PURCHASE_LOCK) { Storage s = Storage.getInstance(); List pendingPurchases = getPendingPurchases(); Receipt found = null; @@ -490,7 +492,7 @@ public final void synchronizeReceipts(final long ifOlderThanMs, final SuccessCal syncInProgress = true; } - synchronized (PENDING_PURCHASE_KEY) { + synchronized (PENDING_PURCHASE_LOCK) { List pending = getPendingPurchases(); if (!pending.isEmpty() && receiptStore != null) { @@ -539,7 +541,6 @@ public void run() { synchronizeReceipts(); } }); - } /** @@ -551,38 +552,10 @@ public void run() { public final boolean synchronizeReceiptsSync(long ifOlderThanMs) { final boolean[] complete = new boolean[1]; final boolean[] success = new boolean[1]; - synchronizeReceipts(ifOlderThanMs, new SuccessCallback() { - - public void onSucess(Boolean value) { - complete[0] = true; - success[0] = value; - - synchronized (complete) { - complete.notifyAll(); - } - - } - - }); + synchronizeReceipts(ifOlderThanMs, new SynchronizeReceiptsSyncSuccessCallback(complete, success)); if (!complete[0]) { - Display.getInstance().invokeAndBlock(new Runnable() { - - public void run() { - - while (!complete[0]) { - synchronized (complete) { - try { - complete.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - return; - } - } - } - } - - }); + Display.getInstance().invokeAndBlock(new SynchronizeReceiptsSyncRunnable(complete)); } return success[0]; } @@ -746,51 +719,6 @@ public Receipt getFirstReceiptExpiringAfter(Date dt, String... skus) { return getFirstReceiptExpiringAfter(getReceipts(skus), dt, skus); } - /** - * Fetch receipts from IAP service synchronously. - * - * @param ifOlderThanMs If the current data is not older than this number of milliseconds - * then it will not attempt to fetch the receipts. - * @return true if data was successfully retrieved. false otherwise. - */ - private boolean loadReceiptsSync(long ifOlderThanMs) { - final boolean[] complete = new boolean[1]; - final boolean[] success = new boolean[1]; - loadReceipts(ifOlderThanMs, new SuccessCallback() { - - public void onSucess(Boolean value) { - complete[0] = true; - success[0] = value; - - synchronized (complete) { - complete.notifyAll(); - } - - } - - }); - - if (!complete[0]) { - Display.getInstance().invokeAndBlock(new Runnable() { - - public void run() { - while (!complete[0]) { - synchronized (complete) { - try { - complete.wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - return; - } - } - } - } - - }); - } - return success[0]; - } - /** * Indicates whether refunding is possible when the SKU is purchased * @@ -880,4 +808,52 @@ public String getStoreCode() { return null; } + private static class SynchronizeReceiptsSyncRunnable implements Runnable { + + private final boolean[] complete; + + public SynchronizeReceiptsSyncRunnable(boolean[] complete) { + this.complete = complete; + } + + public void run() { + + while (!complete[0]) { + synchronized (complete) { + try { + // need to recheck condition within the synchronized block + if(!complete[0]) { + complete.wait(); + } + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + return; + } + } + } + } + + } + + private static class SynchronizeReceiptsSyncSuccessCallback implements SuccessCallback { + + private final boolean[] complete; + private final boolean[] success; + + public SynchronizeReceiptsSyncSuccessCallback(boolean[] complete, boolean[] success) { + this.complete = complete; + this.success = success; + } + + public void onSucess(Boolean value) { + complete[0] = true; + success[0] = value; + + synchronized (complete) { + complete.notifyAll(); + } + + } + + } } diff --git a/CodenameOne/src/com/codename1/processing/HashtableContent.java b/CodenameOne/src/com/codename1/processing/HashtableContent.java index 3933f56671..6cbb407195 100644 --- a/CodenameOne/src/com/codename1/processing/HashtableContent.java +++ b/CodenameOne/src/com/codename1/processing/HashtableContent.java @@ -38,7 +38,7 @@ import java.util.Vector; /** - * Internal class, do not use. + * Internal class do not use. *

* A DOM accessor implementation for working with Map data. * @@ -54,7 +54,7 @@ class MapContent implements StructuredContent { * * @param content parsed Map content */ - public MapContent(Map content) { + public MapContent(Map content) { this.root = content; } @@ -130,7 +130,9 @@ public int hashCode() { * @see java.lang.Object#equals(Object) */ public boolean equals(Object o) { - return root.hashCode() == o.hashCode(); + return o instanceof MapContent && + (root == ((MapContent) o).root || + (root != null && root.equals(((MapContent) o).root))); } /** diff --git a/CodenameOne/src/com/codename1/processing/PrettyPrinter.java b/CodenameOne/src/com/codename1/processing/PrettyPrinter.java index 92275e792f..742abd064d 100644 --- a/CodenameOne/src/com/codename1/processing/PrettyPrinter.java +++ b/CodenameOne/src/com/codename1/processing/PrettyPrinter.java @@ -53,26 +53,26 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * @author Eric Coolman (2012-03 - derivative work from original Sun source). */ class PrettyPrinter { - Map myHashMap; + Map myHashMap; - private PrettyPrinter(Map h) { + private PrettyPrinter(Map h) { this.myHashMap = h; } - public static String print(Map h) { + public static String print(Map h) { return print(h, 2, 0); } - public static String print(List v) { + public static String print(List v) { return print(v, 2, 0); } - static String print(Map h, int indentFactor, int indent) { + static String print(Map h, int indentFactor, int indent) { PrettyPrinter printer = new PrettyPrinter(h); return printer.toString(indentFactor, indent); } - static String print(List v, int indentFactor, int indent) { + static String print(List v, int indentFactor, int indent) { int len = v.size(); if (len == 0) { return "[]"; @@ -120,7 +120,7 @@ static String print(List v, int indentFactor, int indent) { * with } (right brace). */ static String valueToString(Object value, int indentFactor, int indent) { - if (value == null || value.equals(null)) { + if (value == null) { return "null"; } try { @@ -215,41 +215,6 @@ public static String quote(String string) { return sb.toString(); } - /** - * Make a JSON text of an Object value. If the object has an - * value.toJSONString() method, then that method will be used to produce - * the JSON text. The method is required to produce a strictly - * conforming text. If the object does not contain a toJSONString - * method (which is the most common case), then a text will be - * produced by the rules. - *

- * Warning: This method assumes that the data structure is acyclical. - * - * @param value The value to be serialized. - * @return a printable, displayable, transmittable - * representation of the object, beginning - * with { (left brace) and ending - * with } (right brace). - */ - static String valueToString(Object value) { - if (value == null || value.equals(null)) { - return "null"; - } - if (value instanceof String) { - return (String) value; - } - if (value instanceof Float || value instanceof Double || - value instanceof Byte || value instanceof Short || - value instanceof Integer || value instanceof Long) { - return numberToString(value); - } - if (value instanceof Boolean || value instanceof Map || - value instanceof List) { - return value.toString(); - } - return quote(value.toString()); - } - static public String trimNumber(String s) { if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) { while (s.endsWith("0")) { @@ -267,7 +232,6 @@ static public String trimNumber(String s) { * * @param n A Number * @return A String. - * @throws JSONException If n is a non-finite number. */ static public String numberToString(Object n) { if (n == null) { @@ -290,7 +254,7 @@ public int length() { * * @return An iterator of the keys. */ - public Enumeration keys() { + public Enumeration keys() { return Collections.enumeration(this.myHashMap.keySet()); } diff --git a/CodenameOne/src/com/codename1/properties/PreferencesObject.java b/CodenameOne/src/com/codename1/properties/PreferencesObject.java index 24c4fb78ec..5109441045 100644 --- a/CodenameOne/src/com/codename1/properties/PreferencesObject.java +++ b/CodenameOne/src/com/codename1/properties/PreferencesObject.java @@ -105,33 +105,7 @@ public PreferencesObject bind() { } private void bindChangeListener(final Property pb, final String n, final Class type) { - pb.addChangeListener(new PropertyChangeListener() { - public void propertyChanged(PropertyBase p) { - if (type == String.class || type == null) { - Preferences.set(n, (String) pb.get()); - return; - } - if (type == Boolean.class) { - Preferences.set(n, (Boolean) pb.get()); - return; - } - if (type == Double.class) { - Preferences.set(n, (Double) pb.get()); - return; - } - if (type == Float.class) { - Preferences.set(n, (Float) pb.get()); - return; - } - if (type == Integer.class) { - Preferences.set(n, (Integer) pb.get()); - return; - } - if (type == Long.class) { - Preferences.set(n, (Long) pb.get()); - } - } - }); + pb.addChangeListener(new BindPropertyChangeListener(type, n, pb)); } private void checkBind() { @@ -168,4 +142,42 @@ public PreferencesObject setName(PropertyBase pb, String name) { pb.putClientProperty("cn1-po-name", name); return this; } + + private static class BindPropertyChangeListener implements PropertyChangeListener { + private final Class type; + private final String n; + private final Property pb; + + public BindPropertyChangeListener(Class type, String n, Property pb) { + this.type = type; + this.n = n; + this.pb = pb; + } + + public void propertyChanged(PropertyBase p) { + if (type == String.class || type == null) { + Preferences.set(n, (String) pb.get()); + return; + } + if (type == Boolean.class) { + Preferences.set(n, (Boolean) pb.get()); + return; + } + if (type == Double.class) { + Preferences.set(n, (Double) pb.get()); + return; + } + if (type == Float.class) { + Preferences.set(n, (Float) pb.get()); + return; + } + if (type == Integer.class) { + Preferences.set(n, (Integer) pb.get()); + return; + } + if (type == Long.class) { + Preferences.set(n, (Long) pb.get()); + } + } + } } diff --git a/CodenameOne/src/com/codename1/properties/UiBinding.java b/CodenameOne/src/com/codename1/properties/UiBinding.java index 6240b49e66..bb3defb70c 100644 --- a/CodenameOne/src/com/codename1/properties/UiBinding.java +++ b/CodenameOne/src/com/codename1/properties/UiBinding.java @@ -678,7 +678,9 @@ public void assignTo(PropertyType value, Button cmp) { if (cmp instanceof CheckBox) { ((CheckBox) cmp).setSelected((Boolean) toComponentType.convert(value)); } else { - ((RadioButton) cmp).setSelected((Boolean) toComponentType.convert(value)); + if(cmp instanceof RadioButton) { + ((RadioButton) cmp).setSelected((Boolean) toComponentType.convert(value)); + } } } diff --git a/CodenameOne/src/com/codename1/share/FacebookShare.java b/CodenameOne/src/com/codename1/share/FacebookShare.java index 2315b33845..c0160df4ac 100644 --- a/CodenameOne/src/com/codename1/share/FacebookShare.java +++ b/CodenameOne/src/com/codename1/share/FacebookShare.java @@ -130,7 +130,6 @@ public void actionPerformed(ActionEvent evt) { FaceBookAccess.getInstance().addResponseCodeListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { - NetworkEvent ne = (NetworkEvent) evt; FaceBookAccess.getInstance().removeResponseCodeListener(this); progress.dispose(); Dialog.show("Failed to Share", "for some reason sharing has failed, try again later.", "Ok", null); @@ -163,8 +162,7 @@ public void actionPerformed(ActionEvent evt) { FaceBookAccess.getInstance().addResponseCodeListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { - NetworkEvent ne = (NetworkEvent) evt; - FaceBookAccess.getInstance().removeResponseCodeListener(this); + FaceBookAccess.getInstance().removeResponseCodeListener(this); progress.dispose(); Dialog.show("Failed to Share", "for some reason sharing has failed, try again later.", "Ok", null); finish(); diff --git a/CodenameOne/src/com/codename1/share/ShareForm.java b/CodenameOne/src/com/codename1/share/ShareForm.java index 2e2c112601..8508dc5b92 100644 --- a/CodenameOne/src/com/codename1/share/ShareForm.java +++ b/CodenameOne/src/com/codename1/share/ShareForm.java @@ -95,13 +95,7 @@ class ShareForm extends Form { addComponent(BorderLayout.CENTER, body); } addComponent(BorderLayout.SOUTH, post); - Command back = new Command("Back") { - - public void actionPerformed(ActionEvent evt) { - - contacts.showBack(); - } - }; + Command back = new BackCommand(contacts); addCommand(back); setBackCommand(back); } @@ -114,4 +108,32 @@ String getMessage() { return message.getText(); } + private static class BackCommand extends Command { + private final Form contacts; + + public BackCommand(Form contacts) { + super("Back"); + this.contacts = contacts; + } + + @Override + public final boolean equals(Object o) { + if (!(o instanceof BackCommand)) return false; + if (!super.equals(o)) return false; + + BackCommand that = (BackCommand) o; + return (contacts == null ? that.contacts == null : contacts.equals(that.contacts)); + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (contacts != null ? contacts.hashCode() : 0); + return result; + } + + public void actionPerformed(ActionEvent evt) { + contacts.showBack(); + } + } } diff --git a/CodenameOne/src/com/codename1/social/FacebookConnect.java b/CodenameOne/src/com/codename1/social/FacebookConnect.java index 4c14b748e6..8a59032df7 100644 --- a/CodenameOne/src/com/codename1/social/FacebookConnect.java +++ b/CodenameOne/src/com/codename1/social/FacebookConnect.java @@ -30,6 +30,8 @@ import com.codename1.io.Oauth2; import com.codename1.util.Callback; +import java.util.Arrays; + /** * Invokes the native bundled facebook SDK to login/logout of facebook, notice * that in order for this to work server build arguments must indicate that you @@ -42,7 +44,7 @@ */ public class FacebookConnect extends Login { - static Class implClass; + static Class implClass; private static FacebookConnect instance; private final String[] permissions = new String[]{"public_profile", "email", "user_friends"}; @@ -252,22 +254,45 @@ protected boolean validateToken(String token) { //valid anymore final boolean[] retval = new boolean[1]; retval[0] = true; - ConnectionRequest req = new ConnectionRequest() { - @Override - protected void handleErrorResponseCode(int code, String message) { - //access token not valid anymore - if (code >= 400 && code <= 410) { - retval[0] = false; - return; - } - super.handleErrorResponseCode(code, message); - } - - }; + ConnectionRequest req = new ValidateTokenConnectionRequest(retval); req.setPost(false); req.setUrl("https://graph.facebook.com/v2.4/me"); req.addArgumentNoEncoding("access_token", token); NetworkManager.getInstance().addToQueueAndWait(req); return retval[0]; } + + private static class ValidateTokenConnectionRequest extends ConnectionRequest { + private final boolean[] retval; + + public ValidateTokenConnectionRequest(boolean[] retval) { + this.retval = retval; + } + + @Override + public final boolean equals(Object o) { + if (!(o instanceof ValidateTokenConnectionRequest)) return false; + if (!super.equals(o)) return false; + + ValidateTokenConnectionRequest that = (ValidateTokenConnectionRequest) o; + return Arrays.equals(retval, that.retval); + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + Arrays.hashCode(retval); + return result; + } + + @Override + protected void handleErrorResponseCode(int code, String message) { + //access token not valid anymore + if (code >= 400 && code <= 410) { + retval[0] = false; + return; + } + super.handleErrorResponseCode(code, message); + } + } } diff --git a/CodenameOne/src/com/codename1/social/GoogleConnect.java b/CodenameOne/src/com/codename1/social/GoogleConnect.java index 0535c62214..13163f5959 100644 --- a/CodenameOne/src/com/codename1/social/GoogleConnect.java +++ b/CodenameOne/src/com/codename1/social/GoogleConnect.java @@ -26,6 +26,7 @@ import com.codename1.io.NetworkManager; import com.codename1.io.Oauth2; +import java.util.Arrays; import java.util.Hashtable; /** @@ -99,18 +100,7 @@ protected boolean validateToken(String token) { //valid anymore final boolean[] retval = new boolean[1]; retval[0] = true; - ConnectionRequest req = new ConnectionRequest() { - @Override - protected void handleErrorResponseCode(int code, String message) { - //access token not valid anymore - if (code >= 400 && code <= 410) { - retval[0] = false; - return; - } - super.handleErrorResponseCode(code, message); - } - - }; + ConnectionRequest req = new ValidateTokenConnectionRequest(retval); req.setPost(false); req.setUrl("https://www.googleapis.com/plus/v1/people/me"); req.addRequestHeader("Authorization", "Bearer " + token); @@ -119,4 +109,38 @@ protected void handleErrorResponseCode(int code, String message) { } + private static class ValidateTokenConnectionRequest extends ConnectionRequest { + private final boolean[] retval; + + public ValidateTokenConnectionRequest(boolean[] retval) { + this.retval = retval; + } + + @Override + public final boolean equals(Object o) { + if (!(o instanceof ValidateTokenConnectionRequest)) return false; + if (!super.equals(o)) return false; + + ValidateTokenConnectionRequest that = (ValidateTokenConnectionRequest) o; + return Arrays.equals(retval, that.retval); + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + Arrays.hashCode(retval); + return result; + } + + @Override + protected void handleErrorResponseCode(int code, String message) { + //access token not valid anymore + if (code >= 400 && code <= 410) { + retval[0] = false; + return; + } + super.handleErrorResponseCode(code, message); + } + + } } diff --git a/CodenameOne/src/com/codename1/testing/DeviceRunner.java b/CodenameOne/src/com/codename1/testing/DeviceRunner.java index e62f5c5bbc..04c5405b7a 100644 --- a/CodenameOne/src/com/codename1/testing/DeviceRunner.java +++ b/CodenameOne/src/com/codename1/testing/DeviceRunner.java @@ -49,7 +49,7 @@ public void runTests() { passedTests = 0; Log.p("-----STARTING TESTS-----"); try { - InputStream is = getClass().getResourceAsStream("/tests.dat"); + InputStream is = DeviceRunner.class.getResourceAsStream("/tests.dat"); if (is == null) { is = Display.getInstance().getResourceAsStream(null, "/tests.dat"); diff --git a/CodenameOne/src/com/codename1/testing/TestRunnerComponent.java b/CodenameOne/src/com/codename1/testing/TestRunnerComponent.java index 56df89c4bf..8a9b125382 100644 --- a/CodenameOne/src/com/codename1/testing/TestRunnerComponent.java +++ b/CodenameOne/src/com/codename1/testing/TestRunnerComponent.java @@ -99,42 +99,14 @@ public Form showForm() { private void runTest(final AbstractTest test, final Button statusLabel) { try { - if (test.runTest()) { - CN.callSerially(new Runnable() { - public void run() { - statusLabel.setText(test + ": Passed"); - $(statusLabel).selectAllStyles().setBgColor(0x00ff00).revalidate(); - } - }); - + CN.callSerially(new OnPassedRunnable(statusLabel, test)); } else { - CN.callSerially(new Runnable() { - public void run() { - statusLabel.setText(test + ": Failed"); - $(statusLabel).selectAllStyles().setBgColor(0xff0000).revalidate(); - } - }); - + CN.callSerially(new OnFailedRunnable(statusLabel, test)); } - } catch (final Throwable t) { Log.e(t); - CN.callSerially(new Runnable() { - public void run() { - statusLabel.setText(test + ": Failed"); - $(statusLabel).selectAllStyles().setBgColor(0xff0000).revalidate(); - - statusLabel.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent ev) { - ToastBar.showInfoMessage(t.getMessage()); - Log.e(t); - } - }); - } - }); - - + CN.callSerially(new ExceptionHandlerRunnable(statusLabel, test, t)); } } @@ -170,4 +142,58 @@ public void run() { f.showBack(); } } + + private static class ExceptionHandlerRunnable implements Runnable { + private final Button statusLabel; + private final AbstractTest test; + private final Throwable t; + + public ExceptionHandlerRunnable(Button statusLabel, AbstractTest test, Throwable t) { + this.statusLabel = statusLabel; + this.test = test; + this.t = t; + } + + public void run() { + statusLabel.setText(test + ": Failed"); + $(statusLabel).selectAllStyles().setBgColor(0xff0000).revalidate(); + + statusLabel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + ToastBar.showInfoMessage(t.getMessage()); + Log.e(t); + } + }); + } + } + + private static class OnFailedRunnable implements Runnable { + private final Button statusLabel; + private final AbstractTest test; + + public OnFailedRunnable(Button statusLabel, AbstractTest test) { + this.statusLabel = statusLabel; + this.test = test; + } + + public void run() { + statusLabel.setText(test + ": Failed"); + $(statusLabel).selectAllStyles().setBgColor(0xff0000).revalidate(); + } + } + + private static class OnPassedRunnable implements Runnable { + private final Button statusLabel; + private final AbstractTest test; + + public OnPassedRunnable(Button statusLabel, AbstractTest test) { + this.statusLabel = statusLabel; + this.test = test; + } + + public void run() { + statusLabel.setText(test + ": Passed"); + $(statusLabel).selectAllStyles().setBgColor(0x00ff00).revalidate(); + } + } } diff --git a/CodenameOne/src/com/codename1/testing/TestUtils.java b/CodenameOne/src/com/codename1/testing/TestUtils.java index 10223d789f..8c71c872de 100644 --- a/CodenameOne/src/com/codename1/testing/TestUtils.java +++ b/CodenameOne/src/com/codename1/testing/TestUtils.java @@ -1144,26 +1144,6 @@ private static void assertRelativeErrorExceeded(double expected, double actual, } } - private static void assertRelativeErrorNotExceeded(float expected, float actual, double maxRelativeError) { - if (verbose) { - log("assertRelativeErrorNotExceeded(" + expected + ", " + actual + ", " + maxRelativeError + ")"); - } - double relative_error = Math.abs((expected - actual) / actual) * 100; - if (relative_error > maxRelativeError) { - assertBool(false); - } - } - - private static void assertRelativeErrorNotExceeded(double expected, double actual, double maxRelativeError) { - if (verbose) { - log("assertRelativeErrorNotExceeded(" + expected + ", " + actual + ", " + maxRelativeError + ")"); - } - double relative_error = Math.abs((expected - actual) / actual) * 100; - if (relative_error > maxRelativeError) { - assertBool(false); - } - } - private static void assertRelativeErrorNotExceeded(float expected, float actual, double maxRelativeError, String errorMessage) { if (verbose) { log("assertRelativeErrorNotExceeded(" + expected + ", " + actual + ", " + maxRelativeError + ", " + errorMessage + ")"); diff --git a/CodenameOne/src/com/codename1/ui/AutoCompleteTextComponent.java b/CodenameOne/src/com/codename1/ui/AutoCompleteTextComponent.java index 5b930e9a9a..63a82f612c 100644 --- a/CodenameOne/src/com/codename1/ui/AutoCompleteTextComponent.java +++ b/CodenameOne/src/com/codename1/ui/AutoCompleteTextComponent.java @@ -174,7 +174,7 @@ void constructUI() { * @return the editor component */ @Override - public Component getEditor() { + public final Component getEditor() { return field; } diff --git a/CodenameOne/src/com/codename1/ui/BrowserComponent.java b/CodenameOne/src/com/codename1/ui/BrowserComponent.java index 6d39ec7e27..49d16d1b29 100644 --- a/CodenameOne/src/com/codename1/ui/BrowserComponent.java +++ b/CodenameOne/src/com/codename1/ui/BrowserComponent.java @@ -131,11 +131,7 @@ public class BrowserComponent extends Container { private boolean nativeScrolling = true; private boolean ready = false; private boolean fireCallbacksOnEdt = true; - private BrowserNavigationCallback browserNavigationCallback = new BrowserNavigationCallback() { - public boolean shouldNavigate(String url) { - return true; - } - }; + private BrowserNavigationCallback browserNavigationCallback = new AlwaysTrueShouldNavigateCallback(); /** * List of registered browser navigation callbacks. */ @@ -154,7 +150,7 @@ public boolean shouldNavigate(String url) { * This constructor will work as expected when a browser component is supported, see isNativeBrowserSupported() */ public BrowserComponent() { - setUIID("BrowserComponent"); + setUIIDFinal("BrowserComponent"); putClientProperty("BrowserComponent.useWKWebView", "true".equals(Display.getInstance().getProperty("BrowserComponent.useWKWebView", "true"))); setLayout(new BorderLayout()); addComponent(BorderLayout.CENTER, placeholder); @@ -290,13 +286,6 @@ public static boolean isNativeBrowserSupported() { return Display.impl.isNativeBrowserComponentSupported(); } - private static boolean isNumber(Object o) { - if (o == null) { - return false; - } - Class c = o.getClass(); - return c == Integer.class || c == Double.class || c == Float.class || c == Long.class || c == Short.class; - } /** * Injects parameters into a Javascript string expression. This will quote strings properly. The @@ -548,13 +537,6 @@ private SuccessCallback popReturnValueCallback(int id) { return null; } - private JSONParser returnValueParser() { - if (returnValueParser == null) { - returnValueParser = new JSONParser(); - } - return returnValueParser; - } - @Override protected void initComponent() { super.initComponent(); @@ -667,16 +649,7 @@ public boolean fireBrowserNavigationCallbacks(String url) { if (callback != null) { if (errorMessage != null) { if (fireCallbacksOnEdt) { - Display.getInstance().callSerially(new Runnable() { - - public void run() { - if (callback instanceof Callback) { - ((Callback) callback).onError(this, new RuntimeException(errorMessage), 0, errorMessage); - - } - } - - }); + Display.getInstance().callSerially(new FireNavigationCallbackRunnable(callback, errorMessage)); } else { if (callback instanceof Callback) { ((Callback) callback).onError(this, new RuntimeException(errorMessage), 0, errorMessage); @@ -686,13 +659,7 @@ public void run() { } else { if (fireCallbacksOnEdt) { - Display.getInstance().callSerially(new Runnable() { - - public void run() { - callback.onSucess(new JSRef(value, type)); - } - - }); + Display.getInstance().callSerially(new NavigationCallbackRunnable(callback, value, type)); } else { callback.onSucess(new JSRef(value, type)); } @@ -798,13 +765,8 @@ public AsyncResource ready(int timeout) { if (ready) { out.complete(this); } else { - class LoadWrapper { - Timer timer; - ActionListener l; - } final LoadWrapper w = new LoadWrapper(); if (timeout > 0) { - w.timer = CN.setTimeout(timeout, new Runnable() { public void run() { w.timer = null; @@ -819,7 +781,7 @@ public void run() { }); } - w.l = new ActionListener() { + w.l = new ActionListener() { public void actionPerformed(ActionEvent evt) { w.l = null; if (w.timer != null) { @@ -840,6 +802,11 @@ public void actionPerformed(ActionEvent evt) { return out; } + static class LoadWrapper { + Timer timer; + ActionListener l; + } + /** * This method allows customizing the properties of a web view in various ways including platform specific settings. * When a property isn't supported by a specific platform it is just ignored. @@ -1264,11 +1231,7 @@ public void execute(String js, Object[] params) { */ public String executeAndReturnString(String javaScript) { while (internal == null) { - CN.invokeAndBlock(new Runnable() { - public void run() { - Util.sleep(50); - } - }); + CN.invokeAndBlock(new ShortSleepRunnable()); } if (Display.impl.supportsBrowserExecuteAndReturnString(internal)) { return Display.impl.browserExecuteAndReturnString(internal, javaScript); @@ -1583,33 +1546,10 @@ public JSRef executeAndWait(String js) { */ public JSRef executeAndWait(int timeout, String js) { final ExecuteResult res = new ExecuteResult(); - execute(timeout, js, new Callback() { - - public void onSucess(JSRef value) { - synchronized (res) { - res.complete = true; - res.value = value; - res.notifyAll(); - } - } - - public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { - synchronized (res) { - res.complete = true; - res.error = err; - res.notifyAll(); - } - } - }); + execute(timeout, js, new WaitCallback(res)); while (!res.complete) { - Display.getInstance().invokeAndBlock(new Runnable() { - - public void run() { - Util.wait(res, 1000); - } - - }); + Display.getInstance().invokeAndBlock(new WaitRunnable(res)); } if (res.error != null) { throw new RuntimeException(res.error.getMessage()); @@ -1698,6 +1638,11 @@ public enum JSType { UNDEFINED("undefined"), BOOLEAN("boolean"); + // values() doesn't work great on iOS builds + private static final JSType[] values = { + OBJECT, FUNCTION, NUMBER, STRING, UNDEFINED, BOOLEAN + }; + private final String typeOfValue; JSType(String val) { @@ -1708,26 +1653,13 @@ public enum JSType { * Gets the corresponding JSType for the given string type. * * @param type The string type as returned by the typeof operator. Possible input values are 'object', 'function', 'number', 'boolean', and 'undefined' - * @return + * @return the enum corresponding to the type */ public static JSType get(String type) { - if ("object".equals(type)) { - return OBJECT; - } - if ("string".equals(type)) { - return JSType.STRING; - } - if ("number".equals(type)) { - return JSType.NUMBER; - } - if ("function".equals(type)) { - return JSType.FUNCTION; - } - if ("undefined".equals(type)) { - return JSType.UNDEFINED; - } - if ("boolean".equals(type)) { - return BOOLEAN; + for(JSType t : values) { + if(t.typeOfValue.equals(type)) { + return t; + } } return UNDEFINED; } @@ -1771,15 +1703,6 @@ public String getValue() { return value; } - /** - * Returns the type of the value - * - * @return - */ - private String getType() { - return type; - } - /** * Returns the type of the value. * @@ -1860,6 +1783,92 @@ public String toString() { } } + private static class FireNavigationCallbackRunnable implements Runnable { + private final SuccessCallback callback; + private final String errorMessage; + + public FireNavigationCallbackRunnable(SuccessCallback callback, String errorMessage) { + this.callback = callback; + this.errorMessage = errorMessage; + } + + public void run() { + if (callback instanceof Callback) { + ((Callback) callback).onError(this, new RuntimeException(errorMessage), 0, errorMessage); + + } + } + } + + private static class WaitRunnable implements Runnable { + + private final ExecuteResult res; + + public WaitRunnable(ExecuteResult res) { + this.res = res; + } + + public void run() { + Util.wait(res, 1000); + } + + } + + private static class WaitCallback implements Callback { + + private final ExecuteResult res; + + public WaitCallback(ExecuteResult res) { + this.res = res; + } + + public void onSucess(JSRef value) { + synchronized (res) { + res.complete = true; + res.value = value; + res.notifyAll(); + } + } + + public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { + synchronized (res) { + res.complete = true; + res.error = err; + res.notifyAll(); + } + } + } + + private static class ShortSleepRunnable implements Runnable { + public void run() { + Util.sleep(50); + } + } + + private static class NavigationCallbackRunnable implements Runnable { + + private final SuccessCallback callback; + private final String value; + private final String type; + + public NavigationCallbackRunnable(SuccessCallback callback, String value, String type) { + this.callback = callback; + this.value = value; + this.type = type; + } + + public void run() { + callback.onSucess(new JSRef(value, type)); + } + + } + + private static class AlwaysTrueShouldNavigateCallback implements BrowserNavigationCallback { + public boolean shouldNavigate(String url) { + return true; + } + } + /** * A thin wrapper around a Javascript variable that makes it easier to * call methods on that variable. diff --git a/CodenameOne/src/com/codename1/ui/Button.java b/CodenameOne/src/com/codename1/ui/Button.java index 4dad66f706..04bcb80e73 100644 --- a/CodenameOne/src/com/codename1/ui/Button.java +++ b/CodenameOne/src/com/codename1/ui/Button.java @@ -27,6 +27,7 @@ import com.codename1.ui.events.ActionEvent; import com.codename1.ui.events.ActionListener; import com.codename1.ui.events.ActionSource; +import com.codename1.ui.events.ComponentStateChangeEvent; import com.codename1.ui.geom.Dimension; import com.codename1.ui.plaf.Border; import com.codename1.ui.plaf.UIManager; @@ -57,7 +58,7 @@ * * @author Chen Fishbein */ -public class Button extends Label implements ReleasableComponent, ActionSource, SelectableIconHolder { +public class Button extends Label implements ReleasableComponent, ActionSource, SelectableIconHolder { /** * Indicates the rollover state of a button which is equivalent to focused for * most uses @@ -100,7 +101,7 @@ public class Button extends Label implements ReleasableComponent, ActionSource, * * @since 7.0 */ - private ActionListener bindListener; + private ActionListener bindListener; private int pressedX, pressedY; /** @@ -186,7 +187,7 @@ public Button(String text, char icon, float iconSize, String id) { */ public Button(String text, Image icon, String id) { super(text); - setUIID(id); + setUIIDFinal(id); setFocusable(true); setIcon(icon); this.pressedIcon = icon; @@ -308,9 +309,9 @@ private void updateCommand() { } } - private ActionListener bindListener() { + private ActionListener bindListener() { if (bindListener == null) { - bindListener = new ActionListener() { + bindListener = new ActionListener() { public void actionPerformed(ActionEvent e) { if (e.getSource() instanceof Button) { Button b = (Button) e.getSource(); @@ -334,7 +335,7 @@ public void actionPerformed(ActionEvent e) { * @since 7.0 */ public void bindStateTo(Button button) { - button.addStateChangeListener(bindListener()); + button.addStateChangeListener((ActionListener) bindListener()); } /** @@ -346,7 +347,7 @@ public void bindStateTo(Button button) { */ public void unbindStateFrom(Button button) { if (bindListener != null) { - button.removeStateChangeListener(bindListener); + button.removeStateChangeListener((ActionListener) bindListener); } } @@ -528,7 +529,7 @@ void checkAnimation() { * @see #removeStateChangeListener(com.codename1.ui.events.ActionListener) * @since 7.0 */ - public void addStateChangeListener(ActionListener l) { + public void addStateChangeListener(ActionListener l) { if (stateChangeListeners == null) { stateChangeListeners = new EventDispatcher(); } @@ -544,7 +545,7 @@ public void addStateChangeListener(ActionListener l) { * @see #setState(int) * @since 7.0 */ - public void removeStateChangeListener(ActionListener l) { + public void removeStateChangeListener(ActionListener l) { if (stateChangeListeners != null) { stateChangeListeners.removeListener(l); } @@ -561,7 +562,7 @@ private void fireStateChange() { * * @param l implementation of the action listener interface */ - public void addActionListener(ActionListener l) { + public void addActionListener(ActionListener l) { dispatcher.addListener(l); } @@ -570,7 +571,7 @@ public void addActionListener(ActionListener l) { * * @param l implementation of the action listener interface */ - public void removeActionListener(ActionListener l) { + public void removeActionListener(ActionListener l) { dispatcher.removeListener(l); } @@ -580,7 +581,7 @@ public void removeActionListener(ActionListener l) { * @return the action listeners * @deprecated use getListeners instead */ - public Vector getActionListeners() { + public Vector> getActionListeners() { return dispatcher.getListenerVector(); } @@ -589,7 +590,7 @@ public Vector getActionListeners() { * * @return the action listeners */ - public Collection getListeners() { + public Collection> getListeners() { return dispatcher.getListenerCollection(); } @@ -1086,7 +1087,7 @@ public final boolean isCapsText() { if (capsTextDefault) { String uiid = getUIID(); return uiid.equals("Button") || uiid.equals("RaisedButton") || - getUIManager().getThemeConstant("capsButtonUiids", "").indexOf(uiid) > -1; + super.getUIManager().getThemeConstant("capsButtonUiids", "").indexOf(uiid) > -1; } return false; } diff --git a/CodenameOne/src/com/codename1/ui/Calendar.java b/CodenameOne/src/com/codename1/ui/Calendar.java index d23969cd39..8c07b88fe4 100644 --- a/CodenameOne/src/com/codename1/ui/Calendar.java +++ b/CodenameOne/src/com/codename1/ui/Calendar.java @@ -145,7 +145,7 @@ public Calendar(Image leftArrowImage, Image rightArrowImage) { public Calendar(long time, TimeZone tmz, Image leftArrowImage, Image rightArrowImage) { super(new BorderLayout()); this.tmz = tmz; - setUIID("Calendar"); + setUIIDFinal("Calendar"); mv = new MonthView(time); Image leftArrow = leftArrowImage != null ? leftArrowImage : UIManager.getInstance().getThemeImageConstant("calendarLeftImage"); @@ -967,7 +967,7 @@ class MonthView extends Container implements ActionListener { public MonthView(long time) { super(new BoxLayout(BoxLayout.Y_AXIS)); - setUIID("MonthView"); + setUIIDFinal("MonthView"); titles = new Container(new GridLayout(1, 7)); days = new Container(new GridLayout(6, 7)); addComponent(titles); diff --git a/CodenameOne/src/com/codename1/ui/CheckBox.java b/CodenameOne/src/com/codename1/ui/CheckBox.java index 46c4a9932a..2ba0072163 100644 --- a/CodenameOne/src/com/codename1/ui/CheckBox.java +++ b/CodenameOne/src/com/codename1/ui/CheckBox.java @@ -84,7 +84,7 @@ public CheckBox(Image icon) { */ public CheckBox(String text, Image icon) { super(text, icon); - setUIID("CheckBox"); + setUIIDFinal("CheckBox"); updateSide(); } @@ -267,6 +267,7 @@ public Class[] getBindablePropertyTypes() { /** * {@inheritDoc} + * @deprecated uses the deprecated BindTarget interface */ public void bindProperty(String prop, BindTarget target) { if (prop.equals("selected")) { @@ -281,6 +282,7 @@ public void bindProperty(String prop, BindTarget target) { /** * {@inheritDoc} + * @deprecated uses the deprecated BindTarget interface */ public void unbindProperty(String prop, BindTarget target) { if (prop.equals("selected")) { diff --git a/CodenameOne/src/com/codename1/ui/ComboBox.java b/CodenameOne/src/com/codename1/ui/ComboBox.java index 3e769d6bc4..3ad830de82 100644 --- a/CodenameOne/src/com/codename1/ui/ComboBox.java +++ b/CodenameOne/src/com/codename1/ui/ComboBox.java @@ -128,7 +128,7 @@ public ComboBox() { */ public ComboBox(ListModel model) { super(model); - super.setUIID("ComboBox"); + setUIIDFinal("ComboBox"); ((DefaultListCellRenderer) super.getRenderer()).setShowNumbers(false); setInputOnFocus(false); diff --git a/CodenameOne/src/com/codename1/ui/Command.java b/CodenameOne/src/com/codename1/ui/Command.java index 0b9d804475..0c3c12326b 100644 --- a/CodenameOne/src/com/codename1/ui/Command.java +++ b/CodenameOne/src/com/codename1/ui/Command.java @@ -36,7 +36,7 @@ * * @author Nir Shabi */ -public class Command implements ActionListener { +public class Command implements ActionListener { private boolean disposesDialog = true; private Image icon; private char materialIcon; diff --git a/CodenameOne/src/com/codename1/ui/CommonProgressAnimations.java b/CodenameOne/src/com/codename1/ui/CommonProgressAnimations.java index 664c0ad63f..ea46d2808a 100644 --- a/CodenameOne/src/com/codename1/ui/CommonProgressAnimations.java +++ b/CodenameOne/src/com/codename1/ui/CommonProgressAnimations.java @@ -259,9 +259,11 @@ public static class LoadingTextAnimation extends ProgressAnimation { public LoadingTextAnimation() { - getStyle().setFgColor(0x666666); - getStyle().setOpacity(0x66); - $(this).setPaddingMillimeters(2f); + Style s = getUnselectedStyle(); + s.setFgColor(0x666666); + s.setOpacity(0x66); + s.setPadding(2, 2, 2, 2); + s.setPaddingUnit(Style.UNIT_TYPE_DIPS); } /** diff --git a/CodenameOne/src/com/codename1/ui/Component.java b/CodenameOne/src/com/codename1/ui/Component.java index dfd4d310c5..1616a0bbd4 100644 --- a/CodenameOne/src/com/codename1/ui/Component.java +++ b/CodenameOne/src/com/codename1/ui/Component.java @@ -237,7 +237,7 @@ public class Component implements Animation, StyleListener, Editable { *

* Users can disable this with {@code CN.setProperty("Component.revalidateOnStyleChange", "false")}. */ - static boolean revalidateOnStyleChange = true; + private static boolean revalidateOnStyleChange = true; static int restoreDragPercentage = -1; private static byte defaultDragTransparency = 55; private static boolean disableSmoothScrolling = false; @@ -510,7 +510,7 @@ public class Component implements Animation, StyleListener, Editable { * Creates a new instance of Component */ protected Component() { - initLaf(getUIManager()); + initLaf(getUIManagerImpl()); setCursor(DEFAULT_CURSOR); } @@ -534,6 +534,14 @@ public static boolean isSetCursorSupported() { return Display.getInstance().getImplementation().isSetCursorSupported(); } + static void setRevalidateOnStyleChange(boolean val) { + revalidateOnStyleChange = val; + } + + static boolean isRevalidateOnStyleChange() { + return revalidateOnStyleChange; + } + /** * Parses the preferred size given as a string * @@ -719,9 +727,9 @@ public Object getNativeOverlay() { * * * - * @return a unified style object for the purpose of setting on object object instances + * @return a unified style object to set values on all styles */ - public Style getAllStyles() { + public final Style getAllStyles() { if (allStyles == null) { allStyles = Style.createProxyStyle(getUnselectedStyle(), getSelectedStyle(), getPressedStyle(), getDisabledStyle()); } @@ -1039,6 +1047,10 @@ private void initStyle() { * @return a UIManager instance */ public UIManager getUIManager() { + return getUIManagerImpl(); + } + + private UIManager getUIManagerImpl() { Container parent = getParent(); //if no parent return the default UIManager if (parent == null) { @@ -1307,7 +1319,7 @@ public boolean isOpaque() { * @param opaque False to not paint the component's background. * @since 6.0 */ - public void setOpaque(boolean opaque) { + public final void setOpaque(boolean opaque) { this.opaque = opaque; } @@ -1687,7 +1699,7 @@ public void setSize(Dimension d) { * * @return unique string identifying this component for the style sheet */ - public String getUIID() { + public final String getUIID() { if (landscapeUiid != null) { if (Display.impl.isPortrait()) { return portraitUiid; @@ -1704,6 +1716,15 @@ public String getUIID() { * @param id UIID unique identifier for component type */ public void setUIID(String id) { + setUIIDFinal(id); + } + + /** + * This method is the implementation of setUIID and is defined + * as final to allow invocation from constructors. + * @param id UIID unique identifier for component type + */ + protected final void setUIIDFinal(String id) { this.portraitUiid = id; unSelectedStyle = null; selectedStyle = null; @@ -3197,8 +3218,8 @@ private void drawPaintersImpl(com.codename1.ui.Graphics g, Component par, Compon } private void paintRippleEffect(Graphics g) { - if (isRippleEffect() && Form.rippleComponent == this && Form.rippleMotion != null) { - paintRippleOverlay(g, Form.rippleX, Form.rippleY, Form.rippleMotion.getValue()); + if (isRippleEffect() && Form.getRippleComponent() == this && Form.getRippleMotion() != null) { + paintRippleOverlay(g, Form.rippleX, Form.rippleY, Form.getRippleMotion().getValue()); } } @@ -3696,8 +3717,18 @@ public boolean isFocusable() { * * @param focusable indicate whether this component can get focused */ - public void setFocusable(boolean focusable) { + public final void setFocusable(boolean focusable) { this.focusable = focusable; + onSetFocusable(focusable); + } + + /** + * Since setFocusable is final this callback is invoked when + * focusable changes. + * + * @param focusable true if the component was made focusable + */ + protected void onSetFocusable(boolean focusable) { } /** @@ -4497,7 +4528,7 @@ protected void updateState() { sourceStyle.setMargin(RIGHT, marginRight.getValue()); requiresRevalidate = true; } - if (!Component.revalidateOnStyleChange) { + if (!Component.isRevalidateOnStyleChange()) { // If revalidation on stylechange is not enabled, then the style animation // won't work. We need to explicitly revalidate or repaint here. if (requiresRevalidate) { @@ -6016,7 +6047,7 @@ protected void initSelectedStyle(Style selectedStyle) { * * @return the component Style object */ - public Style getUnselectedStyle() { + public final Style getUnselectedStyle() { if (unSelectedStyle == null) { initStyle(); } @@ -6531,7 +6562,10 @@ public boolean animate() { Painter bgp = getStyle().getBgPainter(); - boolean animateBackgroundB = bgp != null && bgp.getClass() != BGPainter.class && bgp instanceof Animation && (bgp != this) && ((Animation) bgp).animate(); + boolean animateBackgroundB = bgp != null && + bgp.getClass() != BGPainter.class && + bgp instanceof Animation && + ((Animation) bgp).animate(); animateBackground = animateBackgroundB || animateBackground; if (getUIManager().getLookAndFeel().isFadeScrollBar()) { @@ -7060,7 +7094,7 @@ public void styleChanged(String propertyName, Style source) { setShouldCalcPreferredSize(true); Container parent = getParent(); if (parent != null && parent.getComponentForm() != null) { - if (revalidateOnStyleChange) { + if (isRevalidateOnStyleChange()) { parent.revalidateLater(); } } @@ -7241,7 +7275,7 @@ protected void deinitializeCustomStyle(Style s) { * * @return true if the component is working in a right to left mode */ - public boolean isRTL() { + public final boolean isRTL() { return rtl; } diff --git a/CodenameOne/src/com/codename1/ui/ComponentGroup.java b/CodenameOne/src/com/codename1/ui/ComponentGroup.java index f904772742..c2122c4ef4 100644 --- a/CodenameOne/src/com/codename1/ui/ComponentGroup.java +++ b/CodenameOne/src/com/codename1/ui/ComponentGroup.java @@ -57,7 +57,7 @@ public class ComponentGroup extends Container { */ public ComponentGroup() { super(new BoxLayout(BoxLayout.Y_AXIS)); - setUIID("ComponentGroup"); + setUIIDFinal("ComponentGroup"); } /** diff --git a/CodenameOne/src/com/codename1/ui/Container.java b/CodenameOne/src/com/codename1/ui/Container.java index 8111f45dbd..b20a49b4a0 100644 --- a/CodenameOne/src/com/codename1/ui/Container.java +++ b/CodenameOne/src/com/codename1/ui/Container.java @@ -40,7 +40,6 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.Vector; @@ -78,13 +77,13 @@ * @see Component */ public class Container extends Component implements Iterable { - static boolean enableLayoutOnPaint = true; + private static boolean enableLayoutOnPaint = true; /** * Workaround for the behavior of the sidemenu bar on iOS etc. which translates aggressively, * this is visible with the table component where the lines slide out of place */ static int sidemenuBarTranslation; - static boolean blockOverdraw = false; + private static boolean blockOverdraw; boolean scrollableX; boolean scrollableY; /** @@ -147,11 +146,19 @@ public class Container extends Component implements Iterable { */ public Container(Layout layout, String uiid) { super(); - setUIID(uiid); + setUIIDFinal(uiid); this.layout = layout; setFocusable(false); } + static void setBlockOverdraw(boolean b) { + blockOverdraw = b; + } + + static boolean isBlockOverdraw() { + return blockOverdraw; + } + /** * Constructs a new Container with a new layout manager. * @@ -296,24 +303,12 @@ public void run() { }; AnimationManager a = getAnimationManager(); if (a != null && a.isAnimating()) { - - a.addAnimation(new ComponentAnimation() { - @Override - public boolean isInProgress() { - return false; - } - - @Override - protected void updateState() { - r.run(); - } - }); + a.addAnimation(new RefreshThemeCallback(r)); return newParent; } else { r.run(); return newParent; } - } /** @@ -379,7 +374,7 @@ void setSurface(boolean surface) { * @param cmp the component to add * @return this for call chaining */ - public Container add(Component cmp) { + public final Container add(Component cmp) { addComponent(cmp); return this; } @@ -490,7 +485,7 @@ public Component getLeadComponent() { * * @param lead component that takes over the hierarchy */ - public void setLeadComponent(Component lead) { + public final void setLeadComponent(Component lead) { if (lead == leadComponent) { return; } @@ -953,11 +948,7 @@ void insertComponentAtImpl(int index, final Component cmp) { boolean refreshLaf = manager != cmp.getUIManager(); cmp.setParent(this); if (refreshLaf) { - Display.getInstance().callSerially(new Runnable() { - public void run() { - cmp.refreshTheme(false); - } - }); + Display.getInstance().callSerially(new RefreshThemeRunnable(cmp)); } components.add(index, cmp); if (layout instanceof BorderLayout && !BorderLayout.OVERLAY.equals(layout.getComponentConstraint(cmp))) { @@ -1002,6 +993,10 @@ public void replaceAndWait(final Component current, final Component next, final replaceComponents(current, next, t, true, false, null, 0, 0, true); } + static void setEnableLayoutOnPaint(boolean val) { + enableLayoutOnPaint = val; + } + /** * This method replaces the current Component with the next Component. * Current Component must be contained in this Container. @@ -1014,13 +1009,13 @@ public void replaceAndWait(final Component current, final Component next, final * @param layoutAnimationSpeed the speed of the layout animation after replace is completed */ public void replaceAndWait(final Component current, final Component next, final Transition t, int layoutAnimationSpeed) { - enableLayoutOnPaint = false; + setEnableLayoutOnPaint(false); replaceComponents(current, next, t, true, false, null, 0, layoutAnimationSpeed, true); if (layoutAnimationSpeed > 0) { animateLayoutAndWait(layoutAnimationSpeed); } dontRecurseContainer = false; - enableLayoutOnPaint = true; + setEnableLayoutOnPaint(true); } /** @@ -1892,18 +1887,7 @@ void paintElevatedPane(Graphics g, final boolean useIntersection, int intersecti _tmpRenderingElevatedComponents.clear(); _tmpRenderingElevatedComponents.addAll(elevatedComponents); } - Collections.sort(_tmpRenderingElevatedComponents, new Comparator() { - - public int compare(Component o1, Component o2) { - int e1 = o1.getStyle().getElevation(); - int e2 = o2.getStyle().getElevation(); - if (e1 < e2) return -1; - else if (e1 > e2) return 1; - else { - return o1.renderedElevationComponentIndex - o2.renderedElevationComponentIndex; - } - } - }); + Collections.sort(_tmpRenderingElevatedComponents, new ElevationComparator()); for (Component child : _tmpRenderingElevatedComponents) { int relativeX = child.getRelativeX(this) + child.getScrollX(); int relativeY = child.getRelativeY(this) + child.getScrollY(); @@ -3700,7 +3684,7 @@ public void morphAndWait(Component source, Component destination, int duration) private void morph(Component source, Component destination, int duration, boolean wait, Runnable onCompletion) { setShouldCalcPreferredSize(true); - enableLayoutOnPaint = false; + setEnableLayoutOnPaint(false); dontRecurseContainer = true; int deltaX = getAbsoluteX(); int deltaY = getAbsoluteY(); @@ -3755,7 +3739,7 @@ private void morph(Component source, Component destination, int duration, boolea */ private ComponentAnimation animateHierarchy(final int duration, boolean wait, int opacity, boolean add) { setShouldCalcPreferredSize(true); - enableLayoutOnPaint = false; + setEnableLayoutOnPaint(false); dontRecurseContainer = true; Vector comps = new Vector(); findComponentsInHierachy(comps); @@ -3853,7 +3837,7 @@ public ComponentAnimation createAnimateUnlayout(int duration, int opacity, Runna */ private ComponentAnimation animateUnlayout(final int duration, boolean wait, int opacity, Runnable callback, boolean add) { setShouldCalcPreferredSize(true); - enableLayoutOnPaint = false; + setEnableLayoutOnPaint(false); final int componentCount = getComponentCount(); int[] beforeX = new int[componentCount]; int[] beforeY = new int[componentCount]; @@ -3913,7 +3897,7 @@ private ComponentAnimation animateLayout(final int duration, boolean wait, int o return null; } setShouldCalcPreferredSize(true); - enableLayoutOnPaint = false; + setEnableLayoutOnPaint(false); final int componentCount = getComponentCount(); int[] beforeX = new int[componentCount]; int[] beforeY = new int[componentCount]; @@ -4190,9 +4174,6 @@ private void restore(Style style) { static class TransitionAnimation extends ComponentAnimation { int growSpeed; int layoutAnimationSpeed; - Vector animatedComponents; - Motion[] opacity; - boolean dontRevalidate; private final Transition t; private final Container thisContainer; private boolean started = false; @@ -4265,10 +4246,8 @@ public void destroy() { if (growSpeed > 0) { current.growShrink(growSpeed); } else { - if (layoutAnimationSpeed <= 0 && !dontRevalidate) { - if (parent != null) { - parent.revalidate(); - } + if (layoutAnimationSpeed <= 0 && parent != null) { + parent.revalidate(); } } } @@ -4277,9 +4256,6 @@ public void destroy() { } static class MorphAnimation extends ComponentAnimation { - Runnable onFinish; - int growSpeed; - int layoutAnimationSpeed; Vector animatedComponents; Motion[] opacity; boolean dontRevalidate; @@ -4362,7 +4338,7 @@ protected void updateState() { } thisContainer.repaint(); if (System.currentTimeMillis() - startTime >= duration) { - enableLayoutOnPaint = true; + setEnableLayoutOnPaint(true); thisContainer.dontRecurseContainer = false; Form f = thisContainer.getComponentForm(); finished = true; diff --git a/CodenameOne/src/com/codename1/ui/Dialog.java b/CodenameOne/src/com/codename1/ui/Dialog.java index 699c2dde9d..9bbf0906de 100644 --- a/CodenameOne/src/com/codename1/ui/Dialog.java +++ b/CodenameOne/src/com/codename1/ui/Dialog.java @@ -747,7 +747,7 @@ public Layout getLayout() { /** * {@inheritDoc} */ - public void setLayout(Layout layout) { + public final void setLayout(Layout layout) { dialogContentPane.setLayout(layout); } @@ -761,14 +761,14 @@ public String getTitle() { /** * {@inheritDoc} */ - public void setTitle(String title) { + public final void setTitle(String title) { dialogTitle.setText(title); } /** * {@inheritDoc} */ - public void addComponent(Component cmp) { + public final void addComponent(Component cmp) { dialogContentPane.addComponent(cmp); } @@ -1736,7 +1736,7 @@ public boolean isAutoDispose() { * * @param autoDispose true if this dialog disposes on any command */ - public void setAutoDispose(boolean autoDispose) { + public final void setAutoDispose(boolean autoDispose) { this.autoDispose = autoDispose; } @@ -1778,7 +1778,7 @@ public boolean isDisposeWhenPointerOutOfBounds() { * * @param disposeWhenPointerOutOfBounds */ - public void setDisposeWhenPointerOutOfBounds(boolean disposeWhenPointerOutOfBounds) { + public final void setDisposeWhenPointerOutOfBounds(boolean disposeWhenPointerOutOfBounds) { this.disposeWhenPointerOutOfBounds = disposeWhenPointerOutOfBounds; } diff --git a/CodenameOne/src/com/codename1/ui/Display.java b/CodenameOne/src/com/codename1/ui/Display.java index 0cacf01423..e345f7ac13 100644 --- a/CodenameOne/src/com/codename1/ui/Display.java +++ b/CodenameOne/src/com/codename1/ui/Display.java @@ -86,12 +86,12 @@ * specific event delivery and painting semantics and enables threading features such as * animations etc... *

The EDT should not be blocked since paint operations and events would also be blocked - * in much the same way as they would be in other platforms. In order to serialize calls back - * into the EDT use the methods {@link Display#callSerially} & {@link Display#callSeriallyAndWait}. - *

Notice that all Codename One calls occur on the EDT (events, painting, animations etc...), Codename One + * in much the same way as they would be in other platforms. To serialize calls back + * into the EDT, use the methods {@link Display#callSerially} & {@link Display#callSeriallyAndWait}. + *

Notice that all Codename One calls occur on the EDT (events, painting, animations, etc...), Codename One * should normally be manipulated on the EDT as well (hence the {@link Display#callSerially} & - * {@link Display#callSeriallyAndWait} methods). Theoretically it should be possible to manipulate - * some Codename One features from other threads but this can't be guaranteed to work for all use cases. + * {@link Display#callSeriallyAndWait} methods). Theoretically, it should be possible to manipulate + * some Codename One features from other threads, but this can't be guaranteed to work for all use cases. * * @author Chen Fishbein, Shai Almog */ @@ -134,11 +134,11 @@ public final class Display extends CN1Constants { */ public static final int KEYBOARD_TYPE_QWERTY = 2; /** - * Touch device without a physical keyboard that should popup a keyboad + * A touch based device that doesn't have a physical keyboard. Such a device pops up a virtual keyboad. */ public static final int KEYBOARD_TYPE_VIRTUAL = 3; /** - * Half QWERTY which needs software assistance for completion + * Half-QWERTY which needs software assistance for completion */ public static final int KEYBOARD_TYPE_HALF_QWERTY = 4; /** @@ -146,7 +146,7 @@ public final class Display extends CN1Constants { */ public static final int GAME_FIRE = 8; /** - * Game action for left key + * Game action for the left key */ public static final int GAME_LEFT = 2; /** @@ -288,9 +288,9 @@ public final class Display extends CN1Constants { private static final int MAX_ASYNC_EXCEPTION_DEPTH = 10; private static final int[] xArray1 = new int[1]; private static final int[] yArray1 = new int[1]; - static int transitionDelay = -1; + private int transitionDelay = -1; static CodenameOneImplementation impl; - private static String selectedVirtualKeyboard = null; + private String selectedVirtualKeyboard = null; private static final Map virtualKeyboards = new HashMap(); private final LinkedList runningSerialCallsQueue = new LinkedList(); boolean codenameOneExited; @@ -338,7 +338,7 @@ public final class Display extends CN1Constants { * Indicates the maximum drawing speed of no more than 10 frames per second * by default (this can be increased or decreased) the advantage of limiting * framerate is to allow the CPU to perform other tasks besides drawing. - * Notice that when no change is occurring on the screen no frame is drawn and + * Notice that when no change is occurring on the screen, no frame is drawn and * so a high/low FPS will have no effect then. */ private int framerateLock = 15; @@ -388,8 +388,6 @@ public final class Display extends CN1Constants { private int longPressInterval = 500; private long nextKeyRepeatEvent; private int keyRepeatValue; - private final int keyRepeatInitialIntervalTime = 800; - private final int keyRepeatNextIntervalTime = 10; private boolean lastInteractionWasKeypad; private boolean dragOccured; private boolean processingSerialCalls; @@ -1240,6 +1238,7 @@ void edtLoopImpl() { long t = System.currentTimeMillis(); if (keyRepeatCharged && nextKeyRepeatEvent <= t) { current.keyRepeated(keyRepeatValue); + int keyRepeatNextIntervalTime = 10; nextKeyRepeatEvent = t + keyRepeatNextIntervalTime; } if (longPressCharged && longPressInterval <= t - longKeyPressTime) { @@ -1314,7 +1313,7 @@ void processSerialCalls() { // after finishing an event cycle there might be serial calls waiting // to return. synchronized (lock) { - lock.notify(); + lock.notifyAll(); } } processingSerialCalls = false; @@ -1333,7 +1332,7 @@ boolean isProcessingSerialCalls() { void notifyDisplay() { synchronized (lock) { - lock.notify(); + lock.notifyAll(); } } @@ -1622,7 +1621,7 @@ void setCurrent(final Form newForm, boolean reverse) { } } synchronized (lock) { - lock.notify(); + lock.notifyAll(); } if (!transitionExists) { @@ -1848,7 +1847,7 @@ private void addSingleArgumentEvent(int type, int code) { inputEventStackPointer++; inputEventStack[inputEventStackPointer] = code; inputEventStackPointer++; - lock.notify(); + lock.notifyAll(); } } @@ -1926,6 +1925,7 @@ public void keyPressed(final int keyCode) { longPressCharged = keyRepeatCharged; longKeyPressTime = System.currentTimeMillis(); keyRepeatValue = keyCode; + int keyRepeatInitialIntervalTime = 800; nextKeyRepeatEvent = System.currentTimeMillis() + keyRepeatInitialIntervalTime; previousKeyPressed = lastKeyPressed; lastKeyPressed = keyCode; @@ -1977,7 +1977,7 @@ private void addPointerEvent(int type, int x, int y) { inputEventStackPointer++; inputEventStack[inputEventStackPointer] = y; inputEventStackPointer++; - lock.notify(); + lock.notifyAll(); } } @@ -2000,7 +2000,7 @@ private void addPointerEvent(int type, int[] x, int[] y) { inputEventStack[inputEventStackPointer] = y[iter]; inputEventStackPointer++; } - lock.notify(); + lock.notifyAll(); } } @@ -2029,7 +2029,7 @@ private void addPointerDragEventWithTimestamp(int x, int y) { Log.p("EDT performance is very slow triggering this exception!"); Log.e(err); } - lock.notify(); + lock.notifyAll(); } } @@ -2051,7 +2051,7 @@ private void addPointerEventWithTimestamp(int type, int x, int y) { Log.p("EDT performance is very slow triggering this exception!"); Log.e(err); } - lock.notify(); + lock.notifyAll(); } } @@ -2165,7 +2165,7 @@ private void addSizeChangeEvent(int type, int w, int h) { inputEventStackPointer++; inputEventStack[inputEventStackPointer] = h; inputEventStackPointer++; - lock.notify(); + lock.notifyAll(); } } @@ -2196,7 +2196,7 @@ private void addNotifyEvent(int type) { synchronized (lock) { inputEventStack[inputEventStackPointer] = type; inputEventStackPointer++; - lock.notify(); + lock.notifyAll(); } } @@ -3491,7 +3491,7 @@ public String getProperty(String key, String defaultValue) { return out == null ? defaultValue : out; } if ("Component.revalidateOnStyleChange".equals(key)) { - return Component.revalidateOnStyleChange ? "true" : "false"; + return Component.isRevalidateOnStyleChange() ? "true" : "false"; } if (localProperties != null) { String v = localProperties.get(key); @@ -3516,14 +3516,14 @@ public void setProperty(String key, String value) { return; } if ("blockOverdraw".equals(key)) { - Container.blockOverdraw = true; + Container.setBlockOverdraw(true); return; } if ("blockCopyPaste".equals(key)) { impl.blockCopyPaste("true".equals(value)); } if ("Component.revalidateOnStyleChange".equals(key)) { - Component.revalidateOnStyleChange = "true".equalsIgnoreCase(value); + Component.setRevalidateOnStyleChange("true".equalsIgnoreCase(value)); } if (key.startsWith("platformHint.")) { impl.setPlatformHint(key, value); @@ -3989,7 +3989,7 @@ public void capturePhoto(ActionListener response) { * @param response a callback Object to retrieve the file path * @throws RuntimeException if this feature failed or unsupported on the platform */ - public void captureAudio(ActionListener response) { + public void captureAudio(ActionListener response) { impl.captureAudio(response); } diff --git a/CodenameOne/src/com/codename1/ui/ElevationComparator.java b/CodenameOne/src/com/codename1/ui/ElevationComparator.java new file mode 100644 index 0000000000..f7ae3f7402 --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/ElevationComparator.java @@ -0,0 +1,15 @@ +package com.codename1.ui; + +import java.util.Comparator; + +class ElevationComparator implements Comparator { + public int compare(Component o1, Component o2) { + int e1 = o1.getStyle().getElevation(); + int e2 = o2.getStyle().getElevation(); + if (e1 < e2) return -1; + else if (e1 > e2) return 1; + else { + return o1.renderedElevationComponentIndex - o2.renderedElevationComponentIndex; + } + } +} diff --git a/CodenameOne/src/com/codename1/ui/EncodedImage.java b/CodenameOne/src/com/codename1/ui/EncodedImage.java index 42e5a465c4..2a6d8fb403 100644 --- a/CodenameOne/src/com/codename1/ui/EncodedImage.java +++ b/CodenameOne/src/com/codename1/ui/EncodedImage.java @@ -37,9 +37,9 @@ *

{@code EncodedImage} is the workhorse of Codename One. Images returned from resource files are * {@code EncodedImage} and many API's expect it.

* - *

{@code EncodedImage} is effectively a an image that is "hidden" and extracted as needed to remove the + *

{@code EncodedImage} is effectively an image that is "hidden" and extracted as needed to remove the * memory overhead associated with loaded image. When creating an {@code EncodedImage} only the PNG - * (or JPEG etc.) is loaded to an array in RAM. Normally such images are very small (relatively) so they can be + * (or JPEG etc.) is loaded to an array in RAM. Normally, such images are very small (relatively) so they can be * kept in memory without much overhead.

* *

When image information is needed (pixels) the image is decoded into RAM and kept in a weak/sort @@ -157,7 +157,7 @@ public static EncodedImage createFromImage(Image i, boolean jpeg) { Util.cleanup(bo); enc.width = i.getWidth(); enc.height = i.getHeight(); - if (format == ImageIO.FORMAT_JPEG) { + if (format.equals(ImageIO.FORMAT_JPEG)) { enc.opaque = true; enc.opaqueChecked = true; } diff --git a/CodenameOne/src/com/codename1/ui/Form.java b/CodenameOne/src/com/codename1/ui/Form.java index 0de0968d67..1dfbc0f1eb 100644 --- a/CodenameOne/src/com/codename1/ui/Form.java +++ b/CodenameOne/src/com/codename1/ui/Form.java @@ -70,8 +70,8 @@ public class Form extends Container { private static final String Z_INDEX_PROP = "cn1$_zIndex"; static int activePeerCount; - static Motion rippleMotion; - static Component rippleComponent; + private static Motion rippleMotion; + private static Component rippleComponent; static int rippleX; static int rippleY; /** @@ -220,7 +220,7 @@ public Form(Layout contentPaneLayout) { super(new BorderLayout()); setSafeAreaRoot(true); contentPane = new Container(contentPaneLayout); - setUIID("Form"); + setUIIDFinal("Form"); // forms/dialogs are not visible by default setVisible(false); Style formStyle = getStyle(); @@ -256,6 +256,14 @@ public Form(Layout contentPaneLayout) { initGlobalToolbar(); } + static Motion getRippleMotion() { + return rippleMotion; + } + + static void setRippleMotion(Motion m) { + rippleMotion = m; + } + /** * Sets the title after invoking the constructor * @@ -728,14 +736,7 @@ public void releaseAnimationLock() { * @see Component#isEditing() */ public Component findCurrentlyEditingComponent() { - return ComponentSelector.select("*", this).filter(new Filter() { - - - public boolean filter(Component c) { - return c.isEditing(); - } - - }).asComponent(); + return ComponentSelector.select("*", this).filter(new CurrentlyEditingFilter()).asComponent(); } /** @@ -1196,7 +1197,7 @@ public void addGameKeyListener(int keyCode, ActionListener listener) { * * @return the number of softbuttons */ - public int getSoftButtonCount() { + public final int getSoftButtonCount() { return menuBar.getSoftButtons().length; } @@ -1722,7 +1723,6 @@ void updateIcsIconCommandBehavior() { @Override public void stopEditing(Runnable onFinish) { Display.getInstance().stopEditing(this, onFinish); - } @Override @@ -1956,20 +1956,30 @@ void deregisterMediaComponent(Component mediaCmp) { /** * The given component is interested in animating its appearance and will start * receiving callbacks when it is visible in the form allowing it to animate - * its appearance. This method would not register a compnent instance more than once + * its appearance. This method would not register a component instance more than once * * @param cmp component that would be animated */ - public void registerAnimated(Animation cmp) { + public final void registerAnimated(Animation cmp) { if (animatableComponents == null) { animatableComponents = new ArrayList(); } if (!animatableComponents.contains(cmp)) { animatableComponents.add(cmp); } + onRegisterAnimated(cmp); Display.getInstance().notifyDisplay(); } + /** + * Callback that's invoked by registerAnimated to let subclasses keep + * track of animation registration. + * + * @param cmp component that would be animated + */ + protected void onRegisterAnimated(Animation cmp) { + } + /** * Identical to the none-internal version, the difference between the internal/none-internal * is that it references a different vector that is unaffected by the user actions. @@ -2031,6 +2041,14 @@ public boolean animate() { return super.animate(); } + static Component getRippleComponent() { + return rippleComponent; + } + + private static void resetRippleComponent() { + rippleComponent = null; + } + /** * Makes sure all animations are repainted so they would be rendered in every * frame @@ -2039,7 +2057,7 @@ void repaintAnimations() { if (rippleComponent != null) { rippleComponent.repaint(); if (rippleMotion == null) { - rippleComponent = null; + resetRippleComponent(); } } if (animatableComponents != null) { @@ -2929,25 +2947,8 @@ public Component getPreviousComponent(Component current) { public TabIterator getTabIterator(Component start) { updateTabIndices(0); java.util.List out = new ArrayList(); - out.addAll(ComponentSelector.select("*", this).filter(new Filter() { - - - public boolean filter(Component c) { - return c.getTabIndex() >= 0 && c.isVisible() && c.isFocusable() && c.isEnabled() && !c.isHidden(true); - } - - })); - Collections.sort(out, new Comparator() { - - - public int compare(Component o1, Component o2) { - return o1.getTabIndex() < o2.getTabIndex() ? -1 : - o2.getTabIndex() < o1.getTabIndex() ? 1 : - 0; - } - - }); - + out.addAll(ComponentSelector.select("*", this).filter(new TabIteratorFilter())); + Collections.sort(out, new TabIteratorComparator()); return new TabIterator(out, start); } @@ -3089,11 +3090,16 @@ public void keyRepeated(int keyCode) { } } + static void setRippleComponent(Component cmp) { + rippleComponent = cmp; + } + private void initRippleEffect(int x, int y, Component cmp) { if (cmp.isRippleEffect()) { - rippleMotion = Motion.createEaseInMotion(0, 1000, 800); - rippleMotion.start(); - rippleComponent = cmp; + Motion motion = Motion.createEaseInMotion(0, 1000, 800); + motion.start(); + setRippleMotion(motion); + setRippleComponent(cmp); rippleX = x; rippleY = y; } @@ -3375,7 +3381,7 @@ public void pointerDragged(int x, int y) { } } - rippleMotion = null; + setRippleMotion(null); if (dragged != null) { LeadUtil.pointerDragged(dragged, x, y); @@ -3447,7 +3453,7 @@ public void pointerDragged(int[] x, int[] y) { } } - rippleMotion = null; + setRippleMotion(null); if (dragged != null) { LeadUtil.pointerDragged(dragged, x, y); @@ -3652,7 +3658,7 @@ private boolean fireReleaseListeners(int x, int y) { public void pointerReleased(int x, int y) { try { Component origPressedCmp = pressedCmp; - rippleMotion = null; + setRippleMotion(null); setPressedCmp(null); boolean isScrollWheeling = Display.impl.isScrollWheeling(); Container actual = getActualPane(formLayeredPane, x, y); @@ -3903,7 +3909,7 @@ public Command getCommand(int index) { * @param cmd the Form command to be added * @deprecated Please use {@link Toolbar#addCommandToLeftBar(com.codename1.ui.Command)} or similar methods */ - public void addCommand(Command cmd) { + public final void addCommand(Command cmd) { //menuBar.addCommand(cmd); addCommand(cmd, 0); } @@ -4385,6 +4391,7 @@ public boolean isScrollableY() { /** * {@inheritDoc} */ + @Override public void setScrollableY(boolean scrollableY) { getContentPane().setScrollableY(scrollableY); } @@ -4800,4 +4807,23 @@ public void add(Component e) { } + private static class CurrentlyEditingFilter implements Filter { + public boolean filter(Component c) { + return c.isEditing(); + } + } + + private static class TabIteratorComparator implements Comparator { + public int compare(Component o1, Component o2) { + return o1.getTabIndex() < o2.getTabIndex() ? -1 : + o2.getTabIndex() < o1.getTabIndex() ? 1 : + 0; + } + } + + private static class TabIteratorFilter implements Filter { + public boolean filter(Component c) { + return c.getTabIndex() >= 0 && c.isVisible() && c.isFocusable() && c.isEnabled() && !c.isHidden(true); + } + } } diff --git a/CodenameOne/src/com/codename1/ui/InputComponent.java b/CodenameOne/src/com/codename1/ui/InputComponent.java index 8e42180c55..f4771a1f96 100644 --- a/CodenameOne/src/com/codename1/ui/InputComponent.java +++ b/CodenameOne/src/com/codename1/ui/InputComponent.java @@ -71,12 +71,7 @@ public abstract class InputComponent extends Container { static Boolean guiBuilderMode; private static boolean multiLineErrorMessage; - private final Button lbl = new Button("", "Label") { - @Override - protected boolean shouldRenderComponentSelection() { - return true; - } - }; + private final Button lbl = new LabelButton(); private final Label descriptionMessage = new Label("", "DescriptionLabel"); Button action; private Boolean onTopMode; @@ -151,7 +146,7 @@ public static void setMultiLineErrorMessage( /** * This method must be invoked by the constructor of the subclasses to initialize the UI */ - protected void initInput() { + protected final void initInput() { // this can happen for base class constructors if (getEditor() != null) { setUIID("TextComponent"); @@ -182,16 +177,7 @@ Label getLabel() { */ protected TextHolder createErrorLabel() { if (multiLineErrorMessage && isOnTopMode()) { - TextArea errorLabel = new TextArea() { - @Override - protected Dimension calcPreferredSize() { - if (getText() == null || getText().length() == 0) { - return new Dimension(); - } - return super.calcPreferredSize(); - } - - }; + TextArea errorLabel = new ErrorLabelTextArea(); errorLabel.setRows(1); errorLabel.setActAsLabel(true); errorLabel.setGrowByContent(true); @@ -538,4 +524,26 @@ public String setPropertyValue(String name, Object value) { } return super.setPropertyValue(name, value); } + + private static class ErrorLabelTextArea extends TextArea { + @Override + protected Dimension calcPreferredSize() { + if (getText() == null || getText().length() == 0) { + return new Dimension(); + } + return super.calcPreferredSize(); + } + + } + + private static class LabelButton extends Button { + public LabelButton() { + super("", "Label"); + } + + @Override + protected boolean shouldRenderComponentSelection() { + return true; + } + } } diff --git a/CodenameOne/src/com/codename1/ui/Label.java b/CodenameOne/src/com/codename1/ui/Label.java index e535d9e540..a06befc8cb 100644 --- a/CodenameOne/src/com/codename1/ui/Label.java +++ b/CodenameOne/src/com/codename1/ui/Label.java @@ -24,6 +24,7 @@ package com.codename1.ui; import com.codename1.cloud.BindTarget; +import com.codename1.components.SpanLabel; import com.codename1.io.Log; import com.codename1.ui.TextSelection.Char; import com.codename1.ui.TextSelection.Span; @@ -123,7 +124,11 @@ public void actionPerformed(ActionEvent evt) { public Label(String text) { endsWith3Points = UIManager.getInstance().getLookAndFeel().isDefaultEndsWith3Points(); noBind = true; - setUIID("Label"); + + // This solves overridable method calls in constructor which are + // a source of some core problems in Java/CodenameOne + setUIIDFinal("Label"); + setLabelUIID("Label"); this.text = text; localize(); setFocusable(false); @@ -141,7 +146,7 @@ public Label(String text, String uiid) { this.text = text; localize(); setFocusable(false); - setUIID(uiid); + setUIIDFinal(uiid); } @@ -343,7 +348,7 @@ public Component getIconStyleComponent() { } /** - * This method is shorthand for {@link com.codename1.ui.FontImage#setMaterialIcon(com.codename1.ui.Label, com.codename1.ui.Font, char)} + * This method is shorthand for {@link com.codename1.ui.FontImage#setMaterialIcon(Label, Font, char, float)} * * @param c one of the constants from the font */ @@ -489,6 +494,10 @@ public int getBaseline(int width, int height) { @Override public void setUIID(String id) { super.setUIID(id); + setLabelUIID(id); + } + + private void setLabelUIID(String id) { if (id != null && id.length() > 0) { String iconUIID = getUIManager().getIconUIIDFor(id); if (iconUIID != null) { @@ -905,10 +914,8 @@ void initAutoResize() { while (currentWidth > w) { fontSize--; if (fontSize <= minSizePixel) { - fontSize = minSizePixel; currentFont = currentFont.derive(minSizePixel, currentFont.getStyle()); getAllStyles().setFont(currentFont); - currentWidth = calcPreferredSize().getWidth(); break; } currentFont = currentFont.derive(fontSize, currentFont.getStyle()); @@ -1221,6 +1228,7 @@ public Class[] getBindablePropertyTypes() { /** * {@inheritDoc} + * @deprecated uses the deprecated BindTarget interface */ public void bindProperty(String prop, BindTarget target) { if (prop.equals("text")) { @@ -1235,6 +1243,7 @@ public void bindProperty(String prop, BindTarget target) { /** * {@inheritDoc} + * @deprecated uses the deprecated BindTarget interface */ public void unbindProperty(String prop, BindTarget target) { if (prop.equals("text")) { @@ -1348,7 +1357,7 @@ public boolean isShowEvenIfBlank() { * * @param showEvenIfBlank the showEvenIfBlank to set */ - public void setShowEvenIfBlank(boolean showEvenIfBlank) { + public final void setShowEvenIfBlank(boolean showEvenIfBlank) { this.showEvenIfBlank = showEvenIfBlank; } @@ -1558,8 +1567,7 @@ public String getIconUIID() { */ public void setIconUIID(String uiid) { if (iconStyleComponent == null || !uiid.equals(iconStyleComponent.getUIID())) { - iconStyleComponent = new Component() { - }; + iconStyleComponent = new Component(); iconStyleComponent.setUIID(uiid); } } diff --git a/CodenameOne/src/com/codename1/ui/List.java b/CodenameOne/src/com/codename1/ui/List.java index 1e4b6ce247..1af6bc1374 100644 --- a/CodenameOne/src/com/codename1/ui/List.java +++ b/CodenameOne/src/com/codename1/ui/List.java @@ -249,7 +249,7 @@ public List() { * @param model the model instance */ public List(ListModel model) { - setUIID("List"); + setUIIDFinal("List"); setModel(model); } @@ -777,7 +777,7 @@ public void setListCellRenderer(ListCellRenderer renderer) { * * @return the renderer which is used to draw list elements */ - public ListCellRenderer getRenderer() { + public final ListCellRenderer getRenderer() { return renderer; } @@ -786,7 +786,7 @@ public ListCellRenderer getRenderer() { * * @param renderer cell renderer instance */ - public void setRenderer(ListCellRenderer renderer) { + public final void setRenderer(ListCellRenderer renderer) { setListCellRenderer(renderer); } diff --git a/CodenameOne/src/com/codename1/ui/MenuBar.java b/CodenameOne/src/com/codename1/ui/MenuBar.java index 015a2e0ac5..1d0d0e7809 100644 --- a/CodenameOne/src/com/codename1/ui/MenuBar.java +++ b/CodenameOne/src/com/codename1/ui/MenuBar.java @@ -704,11 +704,7 @@ public void showMenu() { final Dialog d = new Dialog("Menu", ""); d.setDisposeWhenPointerOutOfBounds(true); d.setMenu(true); - d.addOrientationListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { - d.dispose(); - } - }); + d.addOrientationListener(new MenuDisposerActionListener(d)); d.setTransitionInAnimator(transitionIn); d.setTransitionOutAnimator(transitionOut); d.setLayout(new BorderLayout()); @@ -1761,4 +1757,16 @@ private boolean isTouchMenus() { return t == Display.COMMAND_BEHAVIOR_TOUCH_MENU || (t == Display.COMMAND_BEHAVIOR_DEFAULT && Display.getInstance().isTouchScreenDevice()); } + + private static class MenuDisposerActionListener implements ActionListener { + private final Dialog d; + + public MenuDisposerActionListener(Dialog d) { + this.d = d; + } + + public void actionPerformed(ActionEvent evt) { + d.dispose(); + } + } } \ No newline at end of file diff --git a/CodenameOne/src/com/codename1/ui/PickerComponent.java b/CodenameOne/src/com/codename1/ui/PickerComponent.java index 92f4ab6b76..3b33779caa 100644 --- a/CodenameOne/src/com/codename1/ui/PickerComponent.java +++ b/CodenameOne/src/com/codename1/ui/PickerComponent.java @@ -147,7 +147,7 @@ protected Picker createPickerInstance() { * {@inheritDoc} */ @Override - public Component getEditor() { + public final Component getEditor() { return picker; } diff --git a/CodenameOne/src/com/codename1/ui/RadioButton.java b/CodenameOne/src/com/codename1/ui/RadioButton.java index f5f11982ec..12342167cc 100644 --- a/CodenameOne/src/com/codename1/ui/RadioButton.java +++ b/CodenameOne/src/com/codename1/ui/RadioButton.java @@ -92,7 +92,7 @@ public RadioButton(Image icon) { */ public RadioButton(String text, Image icon) { super(text, icon); - setUIID("RadioButton"); + setUIIDFinal("RadioButton"); } /** @@ -380,6 +380,7 @@ public Class[] getBindablePropertyTypes() { /** * {@inheritDoc} + * @deprecated uses the deprecated BindTarget interface */ public void bindProperty(String prop, BindTarget target) { if (prop.equals("selected")) { @@ -394,6 +395,7 @@ public void bindProperty(String prop, BindTarget target) { /** * {@inheritDoc} + * @deprecated uses the deprecated BindTarget interface */ public void unbindProperty(String prop, BindTarget target) { if (prop.equals("selected")) { diff --git a/CodenameOne/src/com/codename1/ui/RefreshThemeCallback.java b/CodenameOne/src/com/codename1/ui/RefreshThemeCallback.java new file mode 100644 index 0000000000..88dec4dbff --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/RefreshThemeCallback.java @@ -0,0 +1,21 @@ +package com.codename1.ui; + +import com.codename1.ui.animations.ComponentAnimation; + +class RefreshThemeCallback extends ComponentAnimation { + private final Runnable r; + + public RefreshThemeCallback(Runnable r) { + this.r = r; + } + + @Override + public boolean isInProgress() { + return false; + } + + @Override + protected void updateState() { + r.run(); + } +} diff --git a/CodenameOne/src/com/codename1/ui/RefreshThemeRunnable.java b/CodenameOne/src/com/codename1/ui/RefreshThemeRunnable.java new file mode 100644 index 0000000000..0ebd834b4b --- /dev/null +++ b/CodenameOne/src/com/codename1/ui/RefreshThemeRunnable.java @@ -0,0 +1,13 @@ +package com.codename1.ui; + +class RefreshThemeRunnable implements Runnable { + private final Component cmp; + + public RefreshThemeRunnable(Component cmp) { + this.cmp = cmp; + } + + public void run() { + cmp.refreshTheme(false); + } +} diff --git a/CodenameOne/src/com/codename1/ui/RunnableWrapper.java b/CodenameOne/src/com/codename1/ui/RunnableWrapper.java index 0fc0f60569..985534c41c 100644 --- a/CodenameOne/src/com/codename1/ui/RunnableWrapper.java +++ b/CodenameOne/src/com/codename1/ui/RunnableWrapper.java @@ -65,7 +65,7 @@ static void pushToThreadPool(Runnable r) { } synchronized (THREADPOOL_LOCK) { threadPool.add(r); - THREADPOOL_LOCK.notify(); + THREADPOOL_LOCK.notifyAll(); } } @@ -94,7 +94,9 @@ public void run() { while (!dlg.isDisposed()) { try { synchronized (Display.lock) { - Display.lock.wait(40); + if(!dlg.isDisposed()) { + Display.lock.wait(40); + } } } catch (InterruptedException ex) { } @@ -106,7 +108,7 @@ public void run() { internal.run(); done = true; synchronized (Display.lock) { - Display.lock.notify(); + Display.lock.notifyAll(); } break; case 1: @@ -120,7 +122,9 @@ public void run() { while (!done) { synchronized (Display.lock) { try { - Display.lock.wait(10); + if(!done) { + Display.lock.wait(10); + } } catch (InterruptedException ex) { ex.printStackTrace(); } diff --git a/CodenameOne/src/com/codename1/ui/SearchBar.java b/CodenameOne/src/com/codename1/ui/SearchBar.java index cc067473e8..3849d2ef8d 100644 --- a/CodenameOne/src/com/codename1/ui/SearchBar.java +++ b/CodenameOne/src/com/codename1/ui/SearchBar.java @@ -67,7 +67,7 @@ public void dataChanged(int type, int index) { onSearch(search.getText()); } }); - setUIID("ToolbarSearch"); + setUIIDFinal("ToolbarSearch"); if (parent.getComponentForm() == Display.INSTANCE.getCurrent()) { search.startEditingAsync(); } else { diff --git a/CodenameOne/src/com/codename1/ui/Sheet.java b/CodenameOne/src/com/codename1/ui/Sheet.java index 837c6d5de5..477a2a6845 100644 --- a/CodenameOne/src/com/codename1/ui/Sheet.java +++ b/CodenameOne/src/com/codename1/ui/Sheet.java @@ -216,7 +216,7 @@ public Sheet(Sheet parent, String title, String uiid) { } $(this).addTags("Sheet"); setGrabsPointerEvents(true); - this.setUIID(uiid); + setUIIDFinal(uiid); this.title.setUIID(uiid + "Title"); titleBar.setUIID(uiid + "TitleBar"); backButton.setUIID(uiid + "BackButton"); @@ -460,17 +460,7 @@ public void run() { if (!(cnt.getLayout() instanceof BorderLayout)) { cnt.setLayout(new BorderLayout(BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE)); - cnt.getStyle().setBgPainter(new Painter() { - @Override - public void paint(Graphics g, Rectangle rect) { - int alph = g.getAlpha(); - g.setAlpha((int) (alph * 30 / 100.0)); - g.setColor(0x0); - g.fillRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); - g.setAlpha(alph); - } - - }); + cnt.getStyle().setBgPainter(new ShowPainter()); cnt.revalidate(); @@ -907,4 +897,15 @@ private void fireBackEvent() { } + private static class ShowPainter implements Painter { + @Override + public void paint(Graphics g, Rectangle rect) { + int alph = g.getAlpha(); + g.setAlpha((int) (alph * 30 / 100.0)); + g.setColor(0x0); + g.fillRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); + g.setAlpha(alph); + } + + } } diff --git a/CodenameOne/src/com/codename1/ui/SideMenuBar.java b/CodenameOne/src/com/codename1/ui/SideMenuBar.java index 2a02da2c45..6d453136f3 100644 --- a/CodenameOne/src/com/codename1/ui/SideMenuBar.java +++ b/CodenameOne/src/com/codename1/ui/SideMenuBar.java @@ -1231,7 +1231,7 @@ public void pointerReleased(int x, int y) { } super.pointerReleased(x, y); boolean isRTLValue = isRTL(); - if (placement == COMMAND_PLACEMENT_VALUE_RIGHT) { + if (placement.equals(COMMAND_PLACEMENT_VALUE_RIGHT)) { isRTLValue = !isRTLValue; } int displayWidth = Display.getInstance().getDisplayWidth(); @@ -1871,7 +1871,7 @@ public void actionPerformed(ActionEvent evt) { public void actionPerformed(ActionEvent evt) { synchronized (LOCK) { - LOCK.notify(); + LOCK.notifyAll(); } } diff --git a/CodenameOne/src/com/codename1/ui/Slider.java b/CodenameOne/src/com/codename1/ui/Slider.java index 689e8f3aa7..67984c459b 100644 --- a/CodenameOne/src/com/codename1/ui/Slider.java +++ b/CodenameOne/src/com/codename1/ui/Slider.java @@ -112,7 +112,7 @@ public static Slider createInfinite() { /** * {@inheritDoc} */ - public void setUIID(String id) { + public final void setUIID(String id) { super.setUIID(id); initStyles(id); } diff --git a/CodenameOne/src/com/codename1/ui/Tabs.java b/CodenameOne/src/com/codename1/ui/Tabs.java index 685080739f..e93743059b 100644 --- a/CodenameOne/src/com/codename1/ui/Tabs.java +++ b/CodenameOne/src/com/codename1/ui/Tabs.java @@ -149,7 +149,7 @@ public Tabs(int tabP) { press = new SwipeListener(SwipeListener.PRESS); drag = new SwipeListener(SwipeListener.DRAG); release = new SwipeListener(SwipeListener.RELEASE); - setUIID("Tabs"); + setUIIDFinal("Tabs"); BorderLayout bd = (BorderLayout) super.getLayout(); if (bd != null) { if (UIManager.getInstance().isThemeConstant("tabsOnTopBool", false)) { @@ -304,7 +304,7 @@ public boolean animate() { component.paintLockRelease(); } slideToDestMotion = null; - enableLayoutOnPaint = true; + setEnableLayoutOnPaint(true); deregisterAnimatedInternal(); setSelectedIndex(active); } @@ -1653,7 +1653,7 @@ public void actionPerformed(ActionEvent evt) { component.setX(component.getX() + diffX); component.paintLock(false); } - enableLayoutOnPaint = false; + setEnableLayoutOnPaint(false); repaint(); } } @@ -1667,7 +1667,7 @@ public void actionPerformed(ActionEvent evt) { component.setY(component.getY() + diffY); component.paintLock(false); } - enableLayoutOnPaint = false; + setEnableLayoutOnPaint(false); repaint(); } } diff --git a/CodenameOne/src/com/codename1/ui/TextArea.java b/CodenameOne/src/com/codename1/ui/TextArea.java index cb8a0704f0..f7d2dc3076 100644 --- a/CodenameOne/src/com/codename1/ui/TextArea.java +++ b/CodenameOne/src/com/codename1/ui/TextArea.java @@ -332,7 +332,7 @@ public TextArea() { * @throws IllegalArgumentException if rows <= 0 or columns <= 1 */ private TextArea(String text, int maxSize, int rows, int columns, int constraint) { - setUIID("TextArea"); + setUIIDFinal("TextArea"); setPreferredTabIndex(0); this.maxSize = maxSize; setText(text); @@ -1825,6 +1825,7 @@ public Class[] getBindablePropertyTypes() { /** * {@inheritDoc} + * @deprecated uses the deprecated BindTarget interface */ public void bindProperty(String prop, BindTarget target) { if (prop.equals("text")) { @@ -1839,6 +1840,7 @@ public void bindProperty(String prop, BindTarget target) { /** * {@inheritDoc} + * @deprecated uses the deprecated BindTarget interface */ public void unbindProperty(String prop, BindTarget target) { if (prop.equals("text")) { diff --git a/CodenameOne/src/com/codename1/ui/TextField.java b/CodenameOne/src/com/codename1/ui/TextField.java index eb19166687..80659609d4 100644 --- a/CodenameOne/src/com/codename1/ui/TextField.java +++ b/CodenameOne/src/com/codename1/ui/TextField.java @@ -152,7 +152,7 @@ public class TextField extends TextArea { */ public TextField() { super(1, 20); - setUIID("TextField"); + setUIIDFinal("TextField"); setSingleLineTextArea(true); } @@ -163,7 +163,7 @@ public TextField() { */ public TextField(int columns) { super(1, columns); - setUIID("TextField"); + setUIIDFinal("TextField"); setSingleLineTextArea(true); } @@ -174,7 +174,7 @@ public TextField(int columns) { */ public TextField(String text) { super(text, 1, 20); - setUIID("TextField"); + setUIIDFinal("TextField"); setSingleLineTextArea(true); } /** @@ -211,7 +211,7 @@ public TextField(String text, String hint, int columns, int constraint) { */ public TextField(String text, int columns) { super(text, 1, columns); - setUIID("TextField"); + setUIIDFinal("TextField"); setSingleLineTextArea(true); } diff --git a/CodenameOne/src/com/codename1/ui/TextSelection.java b/CodenameOne/src/com/codename1/ui/TextSelection.java index 05ed152304..406766424c 100644 --- a/CodenameOne/src/com/codename1/ui/TextSelection.java +++ b/CodenameOne/src/com/codename1/ui/TextSelection.java @@ -55,7 +55,7 @@ *

If text selection is enabled on a form, then non-editable text fields and text areas will allow text * selection by default. Labels and SpanLabels have text selection disabled by default, but can be enabled using * {@link Label#setTextSelectionEnabled(boolean) }, and {@link SpanLabel#setTextSelectionEnabled(boolean)} respectively. - * Similarly text selection can be disabled on TextFields and TextAreas using {@link TextArea#setTextSelectionEnabled(boolean) }.

+ * Similarly, text selection can be disabled on TextFields and TextAreas using {@link TextArea#setTextSelectionEnabled(boolean) }.

* * @author shannah * @since 7.0 @@ -70,8 +70,8 @@ public class TextSelection { /** * We can't just use component's AbsoluteY coordinates for ordering because of scrolling, * so we create a scaled coorindate that will order components properly. - * @param cmp - * @return + * @param cmp the component + * @return the Y scale */ private double getScaledY(Component cmp) { double y = 0; @@ -91,14 +91,7 @@ public int compare(Component o1, Component o2) { double y1 = getScaledY(o1); double y2 = getScaledY(o2); - int compareY; - if (y1 < y2) { - compareY = -1; - } else if (y1 > y2) { - compareY = 1; - } else { - compareY = 0; - } + int compareY = Double.compare(y1, y2); if (compareY != 0) { return compareY; } @@ -150,14 +143,7 @@ public int compare(Component o1, Component o2) { double y1 = getScaledY(o1); double y2 = getScaledY(o2); - int compareY; - if (y1 < y2) { - compareY = -1; - } else if (y1 > y2) { - compareY = 1; - } else { - compareY = 0; - } + int compareY = Double.compare(y1, y2); if (compareY != 0) { return compareY; } @@ -639,7 +625,6 @@ public void call(Component c) { } private boolean isVerticallyCoveredByBounds(Component cmp, Rectangle bounds) { - int cmpX = getX(cmp, selectionRoot) + cmp.getScrollX(); int cmpY = getY(cmp, selectionRoot) + cmp.getScrollY(); boolean isVerticallyCovered = cmpY >= bounds.getY() && cmpY + cmp.getHeight() <= bounds.getY() + bounds.getHeight(); if (isVerticallyCovered) { diff --git a/CodenameOne/src/com/codename1/ui/Toolbar.java b/CodenameOne/src/com/codename1/ui/Toolbar.java index 0bb80e3db0..154af57907 100644 --- a/CodenameOne/src/com/codename1/ui/Toolbar.java +++ b/CodenameOne/src/com/codename1/ui/Toolbar.java @@ -146,7 +146,7 @@ public Toolbar() { if (UIManager.getInstance().isThemeConstant("landscapeTitleUiidBool", false)) { setUIID("Toolbar", "ToolbarLandscape"); } else { - setUIID("Toolbar"); + setUIIDFinal("Toolbar"); } sideMenu = new ToolbarSideMenu(); if (centeredDefault @@ -592,15 +592,8 @@ public void actionPerformed(ActionEvent evt) { * * @param callback gets the search string callbacks */ - public void showSearchBar(final ActionListener callback) { - SearchBar s = new SearchBar(Toolbar.this, searchIconSize) { - - @Override - public void onSearch(String text) { - callback.actionPerformed(new ActionEvent(text)); - } - - }; + public void showSearchBar(final ActionListener callback) { + SearchBar s = new CallbackSearchBar(callback); Form f = Toolbar.this.getComponentForm(); setHidden(true); f.removeComponentFromForm(Toolbar.this); @@ -1508,10 +1501,7 @@ public void run() { // changes in code path - since it already worked correctly on // every platform except for iOS. // Ref https://github.com/codenameone/CodenameOne/issues/2444 - f.stopEditing(new Runnable() { - public void run() { - } - }); + f.stopEditing(null); } } AnimationManager a = getAnimationManager(); @@ -1645,10 +1635,7 @@ public void run() { // changes in code path - since it already worked correctly on // every platform except for iOS. // Ref https://github.com/codenameone/CodenameOne/issues/2444 - f.stopEditing(new Runnable() { - public void run() { - } - }); + f.stopEditing(null); } } AnimationManager a = getAnimationManager(); @@ -2308,11 +2295,11 @@ public boolean animate() { final Container actualPane = f.getActualPane(); int val = hideShowMotion.getValue(); setY(val); - if (!layered) { - actualPane.setY(actualPaneInitialY + val); - actualPane.setHeight(actualPaneInitialH - val); - actualPane.doLayout(); - } + if (!layered) { + actualPane.setY(actualPaneInitialY + val); + actualPane.setHeight(actualPaneInitialH - val); + actualPane.doLayout(); + } f.repaint(); boolean finished = hideShowMotion.isFinished(); if (finished) { @@ -2598,11 +2585,11 @@ protected Component getTitleComponent() { @Override protected void initMenuBar(Form parent) { - Container ta = parent.getTitleArea(); - if (ta != null) { - ta.setSafeArea(true); - parent.removeComponentFromForm(ta); - } + Container ta = parent.getTitleArea(); + if (ta != null) { + ta.setSafeArea(true); + parent.removeComponentFromForm(ta); + } super.initMenuBar(parent); if (layered) { Container layeredPane = parent.getLayeredPane(); @@ -2787,4 +2774,17 @@ void initTitleBarStatus() { } + private class CallbackSearchBar extends SearchBar { + private final ActionListener callback; + + public CallbackSearchBar(ActionListener callback) { + super(Toolbar.this, Toolbar.this.searchIconSize); + this.callback = callback; + } + + @Override + public void onSearch(String text) { + callback.actionPerformed(new ActionEvent(text)); + } + } } diff --git a/CodenameOne/src/com/codename1/ui/animations/CommonTransitions.java b/CodenameOne/src/com/codename1/ui/animations/CommonTransitions.java index 5928549166..f32876f774 100644 --- a/CodenameOne/src/com/codename1/ui/animations/CommonTransitions.java +++ b/CodenameOne/src/com/codename1/ui/animations/CommonTransitions.java @@ -917,8 +917,6 @@ private void paintAlpha(Graphics graphics) { if(src == null) { return; } - int w = src.getWidth(); - int h = src.getHeight(); int position = this.position; if (position > 255) { position = 255; diff --git a/CodenameOne/src/com/codename1/ui/animations/ComponentAnimation.java b/CodenameOne/src/com/codename1/ui/animations/ComponentAnimation.java index 69d90f535d..69251572e3 100644 --- a/CodenameOne/src/com/codename1/ui/animations/ComponentAnimation.java +++ b/CodenameOne/src/com/codename1/ui/animations/ComponentAnimation.java @@ -131,7 +131,7 @@ public final void updateAnimationState() { completed = true; if (notifyLock != null) { synchronized (notifyLock) { - notifyLock.notify(); + notifyLock.notifyAll(); } } if (onCompletion != null) { diff --git a/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java b/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java index 19b246ef07..15b65a0e5d 100644 --- a/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java +++ b/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java @@ -32,6 +32,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.util.Arrays; /** * Implementation of the HTML components document request handler to allow simple @@ -116,41 +117,67 @@ private InputStream resourceRequested(final DocumentInfo docInfo, final IOCallba protected ConnectionRequest createConnectionRequest(final DocumentInfo docInfo, final IOCallback callback, final Object[] response) { - return new ConnectionRequest() { + return new AsyncDocumentConnectionRequest(docInfo, callback, response); + } - protected void buildRequestBody(OutputStream os) throws IOException { - if (isPost()) { - if (docInfo.getParams() != null) { - OutputStreamWriter w = new OutputStreamWriter(os, docInfo.getEncoding()); - w.write(docInfo.getParams()); - } - } - } + private static class AsyncDocumentConnectionRequest extends ConnectionRequest { + private final DocumentInfo docInfo; + private final IOCallback callback; + private final Object[] response; - protected void handleIOException(IOException err) { - if (callback == null) { - response[0] = err; + public AsyncDocumentConnectionRequest(DocumentInfo docInfo, IOCallback callback, Object[] response) { + this.docInfo = docInfo; + this.callback = callback; + this.response = response; + } + + protected void buildRequestBody(OutputStream os) throws IOException { + if (isPost()) { + if (docInfo.getParams() != null) { + OutputStreamWriter w = new OutputStreamWriter(os, docInfo.getEncoding()); + w.write(docInfo.getParams()); } - super.handleIOException(err); } + } - protected boolean shouldAutoCloseResponse() { - return callback != null; + protected void handleIOException(IOException err) { + if (callback == null) { + response[0] = err; } + super.handleIOException(err); + } - protected void readResponse(InputStream input) throws IOException { - if (callback != null) { - callback.streamReady(input, docInfo); - } else { - response[0] = input; - synchronized (LOCK) { - LOCK.notify(); - } + protected boolean shouldAutoCloseResponse() { + return callback != null; + } + + protected void readResponse(InputStream input) throws IOException { + if (callback != null) { + callback.streamReady(input, docInfo); + } else { + response[0] = input; + synchronized (LOCK) { + LOCK.notifyAll(); } } + } - }; + @Override + public final boolean equals(Object o) { + if (!(o instanceof AsyncDocumentConnectionRequest)) return false; + if (!super.equals(o)) return false; - } + AsyncDocumentConnectionRequest that = (AsyncDocumentConnectionRequest) o; + return (docInfo == null ? that.docInfo == null : docInfo.equals(that.docInfo)) && (callback == null ? that.callback == null : callback.equals(that.callback)) && Arrays.equals(response, that.response); + } + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (docInfo != null ? docInfo.hashCode() : 0); + result = 31 * result + (callback != null ? callback.hashCode() : 0); + result = 31 * result + Arrays.hashCode(response); + return result; + } + } } diff --git a/CodenameOne/src/com/codename1/ui/html/HTMLComponent.java b/CodenameOne/src/com/codename1/ui/html/HTMLComponent.java index 97d57369ed..5ea95d26f0 100644 --- a/CodenameOne/src/com/codename1/ui/html/HTMLComponent.java +++ b/CodenameOne/src/com/codename1/ui/html/HTMLComponent.java @@ -2719,11 +2719,7 @@ TextArea setInputFormat(final TextArea inputField, String inputFormat) { if (Display.getInstance().getCurrent() != inputField.getComponentForm()) { // ((inputField.getComponentForm()==null) || inputField.getParent().replace(inputField, newInputField, null); // Applying the constraints may return a new instance that has to be replaced in the form } else { - Display.getInstance().callSerially(new Runnable() { - public void run() { - inputField.getParent().replace(inputField, newInputField, null); // Applying the constraints may return a new instance that has to be replaced in the form - } - }); + Display.getInstance().callSerially(new InputFormatRunnable(inputField, newInputField)); } if (firstFocusable == inputField) { firstFocusable = newInputField; @@ -4351,4 +4347,17 @@ protected List createPopupList() { } + private static class InputFormatRunnable implements Runnable { + private final TextArea inputField; + private final TextArea newInputField; + + public InputFormatRunnable(TextArea inputField, TextArea newInputField) { + this.inputField = inputField; + this.newInputField = newInputField; + } + + public void run() { + inputField.getParent().replace(inputField, newInputField, null); // Applying the constraints may return a new instance that has to be replaced in the form + } + } } diff --git a/CodenameOne/src/com/codename1/ui/html/HTMLImageMap.java b/CodenameOne/src/com/codename1/ui/html/HTMLImageMap.java index 7f683490f2..347ce96123 100644 --- a/CodenameOne/src/com/codename1/ui/html/HTMLImageMap.java +++ b/CodenameOne/src/com/codename1/ui/html/HTMLImageMap.java @@ -42,7 +42,7 @@ class HTMLImageMap extends Button implements ActionListener { HTMLImageMap(HTMLComponent htmlC) { this.htmlC = htmlC; - setUIID("HTMLLink"); + setUIIDFinal("HTMLLink"); addActionListener(this); } diff --git a/CodenameOne/src/com/codename1/ui/html/HTMLInputFormat.java b/CodenameOne/src/com/codename1/ui/html/HTMLInputFormat.java index abca8f1da8..f6c4515e2b 100644 --- a/CodenameOne/src/com/codename1/ui/html/HTMLInputFormat.java +++ b/CodenameOne/src/com/codename1/ui/html/HTMLInputFormat.java @@ -167,10 +167,7 @@ TextArea applyConstraints(TextArea ta) { if (ta instanceof TextField) { TextField tf = (TextField) ta; if (((widestConstraint & FormatConstraint.TYPE_SYMBOL) == 0) && ((widestConstraint & FormatConstraint.TYPE_ANY) == 0)) { // No symbols allowed - tf = new TextField(ta.getText()) { - protected void showSymbolDialog() { // Block symbols dialog - } - }; + tf = new ConstraintsTextField(ta); tf.setConstraint(ta.getConstraint()); ta = tf; } @@ -492,5 +489,13 @@ public String toString() { } + private static class ConstraintsTextField extends TextField { + public ConstraintsTextField(TextArea ta) { + super(ta.getText()); + } + + protected void showSymbolDialog() { // Block symbols dialog + } + } } diff --git a/CodenameOne/src/com/codename1/ui/html/HTMLLink.java b/CodenameOne/src/com/codename1/ui/html/HTMLLink.java index 8d4fb83009..dc6d62e32a 100644 --- a/CodenameOne/src/com/codename1/ui/html/HTMLLink.java +++ b/CodenameOne/src/com/codename1/ui/html/HTMLLink.java @@ -58,7 +58,7 @@ class HTMLLink extends Button implements ActionListener { */ HTMLLink(String text, String link, HTMLComponent htmlC, HTMLLink parentLink, boolean linkVisited) { super(text); - setUIID("HTMLLink"); + setUIIDFinal("HTMLLink"); this.link = link; this.htmlC = htmlC; this.parentLink = parentLink; diff --git a/CodenameOne/src/com/codename1/ui/html/HTMLTable.java b/CodenameOne/src/com/codename1/ui/html/HTMLTable.java index 3f23671d67..ed9436c196 100644 --- a/CodenameOne/src/com/codename1/ui/html/HTMLTable.java +++ b/CodenameOne/src/com/codename1/ui/html/HTMLTable.java @@ -49,10 +49,7 @@ class HTMLTable extends Table { HTMLTable(HTMLTableModel model) { super(model, false); setCollapseBorder(false); //default for HTML tables - } - - public String getUIID() { - return "HTMLTable"; + setUIIDFinal("HTMLTable"); } /** diff --git a/CodenameOne/src/com/codename1/ui/html/MultiComboBox.java b/CodenameOne/src/com/codename1/ui/html/MultiComboBox.java index b453df243a..243a86c9f1 100644 --- a/CodenameOne/src/com/codename1/ui/html/MultiComboBox.java +++ b/CodenameOne/src/com/codename1/ui/html/MultiComboBox.java @@ -55,7 +55,7 @@ class MultiComboBox extends List { MultiComboBox(ListModel underlyingModel, boolean multiple) { super(); - setUIID("ComboBox"); + setUIIDFinal("ComboBox"); this.multiple = multiple; setScrollToSelected(!multiple); // In multiple comboboxes we don't scroll to selected, as there can be several model = new MultiListModel(underlyingModel, multiple); @@ -324,20 +324,20 @@ void setOptgroup(boolean optgroup) { public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) { Component cmp = super.getListCellRendererComponent(list, value, index, isSelected); if (model.isSelected(value)) { - setUIID("HTMLMultiComboBoxItem"); + setUIIDFinal("HTMLMultiComboBoxItem"); fgColor = getUnselectedStyle().getFgColor(); bgColor = getUnselectedStyle().getBgColor(); } else { - setUIID("ComboBoxItem"); + setUIIDFinal("ComboBoxItem"); bgColor = -1; fgColor = -1; } if (optgroup) { if (value instanceof String) { - setUIID("HTMLOptgroup"); + setUIIDFinal("HTMLOptgroup"); } else { - setUIID("HTMLOptgroupItem"); + setUIIDFinal("HTMLOptgroupItem"); } } diff --git a/CodenameOne/src/com/codename1/ui/layouts/GroupLayout.java b/CodenameOne/src/com/codename1/ui/layouts/GroupLayout.java index ccac8b2dd2..5b8be7162c 100644 --- a/CodenameOne/src/com/codename1/ui/layouts/GroupLayout.java +++ b/CodenameOne/src/com/codename1/ui/layouts/GroupLayout.java @@ -402,7 +402,6 @@ private void dump(StringBuffer buffer, Spring spring, String indent, String padding = ""; if (spring instanceof ComponentSpring) { ComponentSpring cSpring = (ComponentSpring) spring; - origin = cSpring.getOrigin() + " "; String name = cSpring.getComponent().toString(); origin = "name=" + name + ", "; } diff --git a/CodenameOne/src/com/codename1/ui/layouts/LayeredLayout.java b/CodenameOne/src/com/codename1/ui/layouts/LayeredLayout.java index 64c4e6aa28..d416cdccfe 100644 --- a/CodenameOne/src/com/codename1/ui/layouts/LayeredLayout.java +++ b/CodenameOne/src/com/codename1/ui/layouts/LayeredLayout.java @@ -1195,28 +1195,28 @@ protected Component[] getChildrenInTraversalOrder(Container parent) { cmps.add(cmp); } - Collections.sort(cmps, new Comparator() { + Collections.sort(cmps, new ChildrenInTraversalOrderComparator()); + return cmps.toArray(new Component[cmps.size()]); + } - @Override - public int compare(Component o1, Component o2) { - if (o1.getY() < o2.getY()) { + private static class ChildrenInTraversalOrderComparator implements Comparator { + @Override + public int compare(Component o1, Component o2) { + if (o1.getY() < o2.getY()) { + return -1; + } else if (o1.getY() > o2.getY()) { + return 1; + } else { + if (o1.getX() < o2.getX()) { return -1; - } else if (o1.getY() > o2.getY()) { + } else if (o1.getX() > o2.getX()) { return 1; } else { - if (o1.getX() < o2.getX()) { - return -1; - } else if (o1.getX() > o2.getX()) { - return 1; - } else { - return 0; - } + return 0; } } + } - }); - Component[] cmpArr = cmps.toArray(new Component[cmps.size()]); - return cmpArr; } /** diff --git a/CodenameOne/src/com/codename1/ui/layouts/mig/ConstraintParser.java b/CodenameOne/src/com/codename1/ui/layouts/mig/ConstraintParser.java index 7179819223..847434ca0b 100644 --- a/CodenameOne/src/com/codename1/ui/layouts/mig/ConstraintParser.java +++ b/CodenameOne/src/com/codename1/ui/layouts/mig/ConstraintParser.java @@ -1526,7 +1526,7 @@ private static String[] toTrimmedTokens(String s, char sep) { } } - retArr[pNr++] = s.substring(st, sSize).trim(); + retArr[pNr] = s.substring(st, sSize).trim(); return retArr; } diff --git a/CodenameOne/src/com/codename1/ui/layouts/mig/PlatformDefaults.java b/CodenameOne/src/com/codename1/ui/layouts/mig/PlatformDefaults.java index 8163677acf..1f1ff42cae 100644 --- a/CodenameOne/src/com/codename1/ui/layouts/mig/PlatformDefaults.java +++ b/CodenameOne/src/com/codename1/ui/layouts/mig/PlatformDefaults.java @@ -118,12 +118,12 @@ public final class PlatformDefaults { * to specify the visual padding. *

*/ - public static final String VISUAL_PADDING_PROPERTY = "visualPadding"; + public static final String VISUAL_PADDING_PROPERTY = "visualPadding"; static BoundSize RELATED_X = null, RELATED_Y = null, UNRELATED_X = null, UNRELATED_Y = null; private static int DEF_H_UNIT = UnitValue.LPX; private static int DEF_V_UNIT = UnitValue.LPY; private static InCellGapProvider GAP_PROVIDER = null; - private static volatile int MOD_COUNT = 0; + private static int MOD_COUNT = 0; private static int CUR_PLAF = WINDOWS_XP; private static String BUTTON_FORMAT = null; private static BoundSize DEF_VGAP = null, DEF_HGAP = null; @@ -342,7 +342,7 @@ public static Float getHorizontalScaleFactor() { public static void setHorizontalScaleFactor(Float f) { if (!LayoutUtil.equals(horScale, f)) { horScale = f; - MOD_COUNT++; + incModeCount(); } } @@ -371,7 +371,7 @@ public static Float getVerticalScaleFactor() { public static void setVerticalScaleFactor(Float f) { if (!LayoutUtil.equals(verScale, f)) { verScale = f; - MOD_COUNT++; + incModeCount(); } } @@ -401,7 +401,7 @@ public static void setLogicalPixelBase(int base) { throw new IllegalArgumentException("Unrecognized base: " + base); LP_BASE = base; - MOD_COUNT++; + incModeCount(); } } @@ -465,7 +465,7 @@ public static void setGridCellGap(UnitValue x, UnitValue y) { if (y != null) DEF_VGAP = new BoundSize(y, y, null, null); - MOD_COUNT++; + incModeCount(); } /** @@ -484,7 +484,7 @@ public static UnitValue getMinimumButtonWidth() { */ public static void setMinimumButtonWidth(UnitValue width) { BUTT_WIDTH = width; - MOD_COUNT++; + incModeCount(); } /** @@ -525,7 +525,7 @@ public static void setUnitValue(String[] unitStrings, UnitValue x, UnitValue y) if (y != null) VER_DEFS.put(s, y); } - MOD_COUNT++; + incModeCount(); } /** @@ -587,7 +587,7 @@ public static String getButtonOrder() { */ public static void setButtonOrder(String order) { BUTTON_FORMAT = order; - MOD_COUNT++; + incModeCount(); } /** @@ -678,7 +678,7 @@ public static void setDialogInsets(UnitValue top, UnitValue left, UnitValue bott if (right != null) DIALOG_INS[3] = right; - MOD_COUNT++; + incModeCount(); } /** @@ -712,7 +712,7 @@ public static void setPanelInsets(UnitValue top, UnitValue left, UnitValue botto if (right != null) PANEL_INS[3] = right; - MOD_COUNT++; + incModeCount(); } /** @@ -777,6 +777,10 @@ public static int getModCount() { return MOD_COUNT; } + private static void incModeCount() { + MOD_COUNT++; + } + /** * Returns the current default unit. The default unit is the unit used if no unit is set. E.g. "width 10". * diff --git a/CodenameOne/src/com/codename1/ui/list/ContainerList.java b/CodenameOne/src/com/codename1/ui/list/ContainerList.java index e36051ca0a..37d04fef9b 100644 --- a/CodenameOne/src/com/codename1/ui/list/ContainerList.java +++ b/CodenameOne/src/com/codename1/ui/list/ContainerList.java @@ -91,7 +91,7 @@ public ContainerList(Layout l, ListModel m) { private void init(ListModel m) { setModel(m); - setUIID("ContainerList"); + setUIIDFinal("ContainerList"); setScrollableY(true); } @@ -370,7 +370,7 @@ class Entry extends Component { private int offset; Entry(int off) { - setUIID("Container"); + setUIIDFinal("Container"); setFocusable(true); offset = off; } diff --git a/CodenameOne/src/com/codename1/ui/list/DefaultListCellRenderer.java b/CodenameOne/src/com/codename1/ui/list/DefaultListCellRenderer.java index 0b419a1e31..f1f6a7d920 100644 --- a/CodenameOne/src/com/codename1/ui/list/DefaultListCellRenderer.java +++ b/CodenameOne/src/com/codename1/ui/list/DefaultListCellRenderer.java @@ -57,7 +57,7 @@ public DefaultListCellRenderer() { setEndsWith3Points(false); focusComponent.setUIID("ListRendererFocus"); focusComponent.setFocus(true); - setUIID("ListRenderer"); + setUIIDFinal("ListRenderer"); } /** diff --git a/CodenameOne/src/com/codename1/ui/list/GenericListCellRenderer.java b/CodenameOne/src/com/codename1/ui/list/GenericListCellRenderer.java index 4eede42812..b681c4e437 100644 --- a/CodenameOne/src/com/codename1/ui/list/GenericListCellRenderer.java +++ b/CodenameOne/src/com/codename1/ui/list/GenericListCellRenderer.java @@ -23,7 +23,6 @@ */ package com.codename1.ui.list; -import com.codename1.cloud.CloudObject; import com.codename1.ui.Button; import com.codename1.ui.CheckBox; import com.codename1.ui.Command; @@ -328,34 +327,8 @@ public Component getCellRendererComponent(Component list, Object model, T value, entries[iter].setFocus(lead || entries[iter].isFocusable()); } } else { - if (value instanceof CloudObject) { - CloudObject h = (CloudObject) value; - Boolean enabled = h.getBoolean(ENABLED); - if (enabled != null) { - cmp.setEnabled(enabled.booleanValue()); - } - int elen = entries.length; - for (int iter = 0; iter < elen; iter++) { - String currentName = entries[iter].getName(); - - Object val; - if (currentName.equals("$number")) { - val = "" + (index + 1); - } else { - // a selected entry might differ in its value to allow for - // behavior such as rollover images - val = h.getObject("#" + currentName); - if (val == null) { - val = h.getObject(currentName); - } - } - setComponentValueWithTickering(entries[iter], val, list, cmp); - entries[iter].setFocus(entries[iter].isFocusable()); - } - } else { - setComponentValueWithTickering(entries[0], value, list, cmp); - entries[0].setFocus(entries[0].isFocusable()); - } + setComponentValueWithTickering(entries[0], value, list, cmp); + entries[0].setFocus(entries[0].isFocusable()); } return cmp; } else { @@ -389,25 +362,8 @@ public Component getCellRendererComponent(Component list, Object model, T value, setComponentValue(entries[iter], val, list, cmp); } } else { - if (value instanceof CloudObject) { - CloudObject h = (CloudObject) value; - Boolean enabled = h.getBoolean(ENABLED); - if (enabled != null) { - cmp.setEnabled(enabled.booleanValue()); - } - int elen = entries.length; - for (int iter = 0; iter < elen; iter++) { - String currentName = entries[iter].getName(); - if (currentName.equals("$number")) { - setComponentValue(entries[iter], "" + (index + 1), list, cmp); - continue; - } - setComponentValue(entries[iter], h.getObject(currentName), list, cmp); - } - } else { - if (entries.length > 0) { - setComponentValue(entries[0], value, list, cmp); - } + if (entries.length > 0) { + setComponentValue(entries[0], value, list, cmp); } } return cmp; diff --git a/CodenameOne/src/com/codename1/ui/list/ListCellRenderer.java b/CodenameOne/src/com/codename1/ui/list/ListCellRenderer.java index dfb34b9891..daa10676a6 100644 --- a/CodenameOne/src/com/codename1/ui/list/ListCellRenderer.java +++ b/CodenameOne/src/com/codename1/ui/list/ListCellRenderer.java @@ -60,7 +60,7 @@ public interface ListCellRenderer { * and is animated to provide smooth scrolling. * When the selection moves, this component is drawn above/below the list items - * it is recommended to give this component some level of transparency (see above code example). - * This method is optional an implementation + * This method is optional, an implementation * can choose to return null. * * @param list the parent list diff --git a/CodenameOne/src/com/codename1/ui/plaf/CSSBorder.java b/CodenameOne/src/com/codename1/ui/plaf/CSSBorder.java index 33c067eefe..ec059a0212 100644 --- a/CodenameOne/src/com/codename1/ui/plaf/CSSBorder.java +++ b/CodenameOne/src/com/codename1/ui/plaf/CSSBorder.java @@ -627,6 +627,10 @@ public boolean isBackgroundPainter() { return true; } + private static void setContext(Context ctx) { + context = ctx; + } + /** * {@inheritDoc } */ @@ -647,7 +651,7 @@ public void paintBorderBackground(Graphics g, Component c) { calculateContentRect(c.getWidth(), c.getHeight(), contentRect); contentRect.setX(contentRect.getX() + c.getX()); contentRect.setY(contentRect.getY() + c.getY()); - context = new Context(c, contentRect); + setContext(new Context(c, contentRect)); String borderPathKey = "$$CSSBorderPath"; GeneralPath p = (GeneralPath) c.getClientProperty(borderPathKey); if (p == null) { @@ -1988,17 +1992,19 @@ public String toCSSString() { } private static class LinearGradient { - float angle; + //float angle; ColorStop[] colors = new ColorStop[0]; double directionRadian() { - return angle * Math.PI / 180.0; + //return angle * Math.PI / 180.0; + return 0; } private String toCSSString() { StringBuilder sb = new StringBuilder(); sb.append("linear-gradient("); - sb.append(angle).append("deg"); + //sb.append(angle); + sb.append("deg"); sb.append(","); boolean first = true; @@ -2016,11 +2022,6 @@ private String toCSSString() { } private static class RadialGradient { - byte shape; - byte size; - float xPos, yPos; - ColorStop[] colors = new ColorStop[0]; - private String toCSSString() { throw new RuntimeException("RadialGradlient toCSSString() not implemented yet"); } diff --git a/CodenameOne/src/com/codename1/ui/plaf/DefaultLookAndFeel.java b/CodenameOne/src/com/codename1/ui/plaf/DefaultLookAndFeel.java index 53a8f531fd..9f50ba0729 100644 --- a/CodenameOne/src/com/codename1/ui/plaf/DefaultLookAndFeel.java +++ b/CodenameOne/src/com/codename1/ui/plaf/DefaultLookAndFeel.java @@ -423,12 +423,9 @@ public void drawLabel(Graphics g, Label l) { public Span calculateLabelSpan(TextSelection sel, Label l) { Image icon = l.getMaskedIcon(); - Image stateIcon = null; int preserveSpaceForState = 0; - //setFG(g, l); int gap = l.getGap(); - int stateIconSize = 0; String text = l.getText(); Style style = l.getStyle(); int cmpX = l.getX(); @@ -580,49 +577,30 @@ public Span calculateLabelSpan(TextSelection sel, Label l) { if (iconHeight > fontHeight) { iconStringHGap = (iconHeight - fontHeight) / 2; return calculateSpanForLabelStringValign(sel, l, text, x, y, iconStringHGap, iconHeight, textSpaceW, fontHeight); - } else { - iconStringHGap = (fontHeight - iconHeight) / 2; - //strWidth = drawLabelString(l, text, x, y, textSpaceW); - return calculateSpanForLabelString(sel, l, text, x, y, textSpaceW); - //g.drawImage(icon, x + strWidth + gap, y + iconStringHGap); } + return calculateSpanForLabelString(sel, l, text, x, y, textSpaceW); case Label.RIGHT: if (iconHeight > fontHeight) { iconStringHGap = (iconHeight - fontHeight) / 2; - //g.drawImage(icon, x, y); return calculateSpanForLabelStringValign(sel, l, text, x + iconWidth + gap, y, iconStringHGap, iconHeight, textSpaceW, fontHeight); - } else { - iconStringHGap = (fontHeight - iconHeight) / 2; - //g.drawImage(icon, x, y + iconStringHGap); - return calculateSpanForLabelString(sel, l, text, x + iconWidth + gap, y, textSpaceW); } + return calculateSpanForLabelString(sel, l, text, x + iconWidth + gap, y, textSpaceW); case Label.BOTTOM: if (iconWidth > strWidth) { //center align the smaller - iconStringWGap = (iconWidth - strWidth) / 2; - //g.drawImage(icon, x, y); return calculateSpanForLabelString(sel, l, text, x + iconStringWGap, y + iconHeight + gap, textSpaceW); - } else { - iconStringWGap = (Math.min(strWidth, textSpaceW) - iconWidth) / 2; - //g.drawImage(icon, x + iconStringWGap, y); - - return calculateSpanForLabelString(sel, l, text, x, y + iconHeight + gap, textSpaceW); } + return calculateSpanForLabelString(sel, l, text, x, y + iconHeight + gap, textSpaceW); case Label.TOP: if (iconWidth > strWidth) { //center align the smaller iconStringWGap = (iconWidth - strWidth) / 2; return calculateSpanForLabelString(sel, l, text, x + iconStringWGap, y, textSpaceW); - //g.drawImage(icon, x, y + fontHeight + gap); - } else { - iconStringWGap = (Math.min(strWidth, textSpaceW) - iconWidth) / 2; - return calculateSpanForLabelString(sel, l, text, x, y, textSpaceW); - //g.drawImage(icon, x + iconStringWGap, y + fontHeight + gap); } - // break; // unreachable because of return + return calculateSpanForLabelString(sel, l, text, x, y, textSpaceW); default: break; @@ -825,13 +803,7 @@ private void append(TextSelection sel, Component l, Span span, String text, Font @Override public Spans calculateTextAreaSpan(TextSelection sel, TextArea ta) { Spans out = sel.newSpans(); - //setFG(g, ta); - //Span out = sel.newSpan(ta); int line = ta.getLines(); - //int oX = g.getClipX(); - //int oY = g.getClipY(); - //int oWidth = g.getClipWidth(); - //int oHeight = g.getClipHeight(); Font f = ta.getStyle().getFont(); int fontHeight = f.getHeight(); @@ -850,7 +822,6 @@ public Spans calculateTextAreaSpan(TextSelection sel, TextArea ta) { default: break; } - //boolean shouldBreak = false; int posOffset = 0; int lastRowBottom = 0; for (int i = 0; i < line; i++) { @@ -862,10 +833,7 @@ public Spans calculateTextAreaSpan(TextSelection sel, TextArea ta) { int yDiff = adjustedY - y; y = adjustedY; - //if(Rectangle.intersects(x, y, ta.getWidth(), fontHeight, oX, oY, oWidth, oHeight)) { - String rowText = ta.getTextAt(i); - //display ******** if it is a password field String displayText = ""; if ((ta.getConstraint() & TextArea.PASSWORD) != 0) { int rlen = rowText.length(); @@ -888,33 +856,21 @@ public Spans calculateTextAreaSpan(TextSelection sel, TextArea ta) { default: break; } - //int nextY = ta.getY() + topPadding + (ta.getRowsGap() + fontHeight) * (i + 2); - //if this is the last line to display and there is more content and isEndsWith3Points() is true - //add "..." at the last row if (ta.isEndsWith3Points() && ta.getGrowLimit() == (i + 1) && ta.getGrowLimit() != line) { if (displayText.length() > 3) { displayText = displayText.substring(0, displayText.length() - 3); } - //g.drawString(displayText + "...", x, y ,ta.getStyle().getTextDecoration()); append(sel, ta, rowSpan, displayText + "...", f, posOffset, x, y, getSelectionHeight(f) - yDiff); - lastRowBottom = rowSpan.getBounds().getY() + rowSpan.getBounds().getHeight(); rowSpan = rowSpan.translate(ta.getAbsoluteX() - sel.getSelectionRoot().getAbsoluteX() - ta.getX(), ta.getAbsoluteY() - sel.getSelectionRoot().getAbsoluteY() - ta.getY()); out.add(rowSpan); return out; } else { - //g.drawString(displayText, x, y ,ta.getStyle().getTextDecoration()); append(sel, ta, rowSpan, displayText, f, posOffset, x, y, getSelectionHeight(f) - yDiff); lastRowBottom = rowSpan.getBounds().getY() + rowSpan.getBounds().getHeight(); rowSpan = rowSpan.translate(ta.getAbsoluteX() - sel.getSelectionRoot().getAbsoluteX() - ta.getX(), ta.getAbsoluteY() - sel.getSelectionRoot().getAbsoluteY() - ta.getY()); out.add(rowSpan); } posOffset += displayText.length(); - //shouldBreak = true; - //}else{ - // if(shouldBreak){ - // break; - // } - //} } return out; } @@ -981,7 +937,6 @@ public void drawTextArea(Graphics g, TextArea ta) { default: break; } - int nextY = ta.getY() + topPadding + (ta.getRowsGap() + fontHeight) * (i + 2); //if this is the last line to display and there is more content and isEndsWith3Points() is true //add "..." at the last row if (ta.isEndsWith3Points() && ta.getGrowLimit() == (i + 1) && ta.getGrowLimit() != line) { @@ -2345,20 +2300,8 @@ public void paint(Graphics g) { // We need to make the InfiniteProgress to animate, otherwise the progress // just stays static. - ComponentSelector.select("*", pull).each(new ComponentClosure() { - - - @Override - public void call(Component c) { - if (c instanceof InfiniteProgress) { - ((InfiniteProgress) c).animate(true); - } else { - c.animate(); - } - } - }); + ComponentSelector.select("*", pull).each(new PullToRefreshComponentClosure()); pull.paintComponent(g); - } /** @@ -2567,22 +2510,19 @@ public Span calculateSpanForLabelText(TextSelection sel, Label l, String text, i int txtW = l.getStringWidth(f); int curPos = text.length(); if ((!isTickerRunning) || rtl) { - //if there is no space to draw the text add ... at the end + // if there is no space to draw the text, add ... at the end if (txtW > textSpaceW && textSpaceW > 0) { - // Handling of adding 3 points and in fact all text positioning when the text is bigger than + // Handling of adding 3 points and in fact, all text positioning when the text is bigger than // the allowed space is handled differently in RTL, this is due to the reverse algorithm // effects - i.e. when the text includes both Hebrew/Arabic and English/numbers then simply // trimming characters from the end of the text (as done with LTR) won't do. - // Instead we simple reposition the text, and draw the 3 points, this is quite simple, but + // Instead, we simply reposition the text, and draw the 3 points, this is quite simple, but // the downside is that a part of a letter may be shown here as well. if (rtl) { if ((!isTickerRunning) && (l.isEndsWith3Points())) { String points = "..."; int pointsW = f.stringWidth(points); - //xPos = f.stringWidth(displayText.substring(0, cursorCharPosition)); - //g.drawString(points, l.getShiftText() + x, y,l.getStyle().getTextDecoration()); - //g.clipRect(pointsW+l.getShiftText() + x, y, textSpaceW - pointsW, f.getHeight()); Char nextChar = sel.newChar(curPos, pointsW + l.getShiftText() + x, y, textSpaceW - pointsW, h); span.add(nextChar); } @@ -2598,7 +2538,6 @@ public Span calculateSpanForLabelText(TextSelection sel, Label l, String text, i index++; } text = text.substring(0, Math.min(text.length(), Math.max(1, index - 1))) + points; - txtW = f.stringWidth(text); } } } @@ -2617,4 +2556,15 @@ public Span calculateSpanForLabelText(TextSelection sel, Label l, String text, i //System.out.println("Span: "+span); return span.translate(l.getAbsoluteX() - sel.getSelectionRoot().getAbsoluteX() - l.getX(), l.getAbsoluteY() - sel.getSelectionRoot().getAbsoluteY() - l.getY()); } + + private static class PullToRefreshComponentClosure implements ComponentClosure { + @Override + public void call(Component c) { + if (c instanceof InfiniteProgress) { + ((InfiniteProgress) c).animate(true); + } else { + c.animate(); + } + } + } } diff --git a/CodenameOne/src/com/codename1/ui/plaf/Style.java b/CodenameOne/src/com/codename1/ui/plaf/Style.java index c3a5c7843d..e4d36ee0a2 100644 --- a/CodenameOne/src/com/codename1/ui/plaf/Style.java +++ b/CodenameOne/src/com/codename1/ui/plaf/Style.java @@ -997,7 +997,7 @@ public int getFgColor() { * * @param fgColor foreground color */ - public void setFgColor(int fgColor) { + public final void setFgColor(int fgColor) { setFgColor(fgColor, false); } @@ -1470,7 +1470,7 @@ public int getOpacity() { * * @param opacity the opacity value */ - public void setOpacity(int opacity) { + public final void setOpacity(int opacity) { setOpacity(opacity, false); } @@ -1482,7 +1482,7 @@ public void setOpacity(int opacity) { * @param override If set to true allows the look and feel/theme to override * the value in this attribute when changing a theme/look and feel */ - public void setOpacity(int opacity, boolean override) { + public final void setOpacity(int opacity, boolean override) { if (proxyTo != null) { for (Style s : proxyTo) { s.setOpacity(opacity, override); @@ -2602,7 +2602,7 @@ public void setBackgroundGradientRelativeSize(float backgroundGradientRelativeSi * @param override If set to true allows the look and feel/theme to override * the value in this attribute when changing a theme/look and feel */ - public void setFgColor(int fgColor, boolean override) { + public final void setFgColor(int fgColor, boolean override) { if (proxyTo != null) { for (Style s : proxyTo) { s.setFgColor(fgColor, override); @@ -2799,7 +2799,6 @@ public void setSuppressChangeEvents(boolean suppress) { } private void firePropertyChanged(String propertName) { - roundRectCache = null; nativeOSCache = null; if (listeners == null || suppressChangeEvents) { diff --git a/CodenameOne/src/com/codename1/ui/plaf/StyleParser.java b/CodenameOne/src/com/codename1/ui/plaf/StyleParser.java index 78eb9320c2..2784ccc98f 100644 --- a/CodenameOne/src/com/codename1/ui/plaf/StyleParser.java +++ b/CodenameOne/src/com/codename1/ui/plaf/StyleParser.java @@ -347,19 +347,6 @@ private static String getAlignmentString(Integer alignment) { return null; } - private static int getPixelValue(String val) { - ScalarValue v = parseSingleTRBLValue(val); - switch (v.getUnit()) { - case Style.UNIT_TYPE_PIXELS: - return (int) Math.round(v.getValue()); - case Style.UNIT_TYPE_DIPS: - return Display.getInstance().convertToPixels((float) v.getValue()); - case Style.UNIT_TYPE_SCREEN_PERCENTAGE: - return (int) Math.round(Display.getInstance().getDisplayWidth() * v.getValue() / 100.0); - } - return 0; - } - private static float getMMValue(String val) { ScalarValue v = parseSingleTRBLValue(val); switch (v.getUnit()) { @@ -623,10 +610,6 @@ private static Image getImage(Resources theme, String imageStr) { return im; } - static Integer parseTextDecoration(String decoration) { - return null; - } - private static FontInfo parseFontSize(FontInfo out, String arg) { arg = arg.trim(); ScalarValue sizeVal = parseSingleTRBLValue(arg); diff --git a/CodenameOne/src/com/codename1/ui/plaf/UIManager.java b/CodenameOne/src/com/codename1/ui/plaf/UIManager.java index 1587e89729..4db9bbcc5c 100644 --- a/CodenameOne/src/com/codename1/ui/plaf/UIManager.java +++ b/CodenameOne/src/com/codename1/ui/plaf/UIManager.java @@ -366,7 +366,7 @@ public void setComponentSelectedStyle(String id, Style style) { * @param id the component id whose style we want * @return the appropriate style (this method never returns null) */ - public Style getComponentStyle(String id) { + public final Style getComponentStyle(String id) { return getComponentStyleImpl(id, false, ""); } @@ -1458,7 +1458,7 @@ public int getThemeConstant(String constantName, int def) { * @param def default value * @return the value of the constant or the default if the constant isn't in the theme */ - public String getThemeConstant(String constantName, String def) { + public final String getThemeConstant(String constantName, String def) { String v = (String) themeConstants.get(constantName); if (v != null) { return v; @@ -1473,7 +1473,7 @@ public String getThemeConstant(String constantName, String def) { * @param def default value * @return the value of the constant or the default if the constant isn't in the theme */ - public boolean isThemeConstant(String constantName, boolean def) { + public final boolean isThemeConstant(String constantName, boolean def) { String c = getThemeConstant(constantName, null); if (c == null) { return def; @@ -2146,7 +2146,8 @@ private String[][] tokenizeMultiArray(String s, char separator, char lineBreak) * @param defaultValue the value returned if no such key exists * @return either default value or the appropriate value */ - public String localize(String key, String defaultValue) { + public final String localize(String key, String defaultValue) { + onLocalize(key, defaultValue); if (bundle != null && key != null) { Object o = bundle.get(key); if (o != null) { @@ -2156,6 +2157,15 @@ public String localize(String key, String defaultValue) { return defaultValue; } + /** + * Callback for subclasses that wish to track localization invocations. + * + * @param key The key used to lookup in the resource bundle + * @param defaultValue the value returned if no such key exists + */ + protected void onLocalize(String key, String defaultValue) { + } + /** * Adds a Theme refresh listener. * The listenres will get a callback when setThemeProps method is invoked. diff --git a/CodenameOne/src/com/codename1/ui/scene/Scene.java b/CodenameOne/src/com/codename1/ui/scene/Scene.java index a1be66a13a..de720807fa 100644 --- a/CodenameOne/src/com/codename1/ui/scene/Scene.java +++ b/CodenameOne/src/com/codename1/ui/scene/Scene.java @@ -40,7 +40,7 @@ public class Scene extends Container { private Node root; public Scene() { - setUIID("Scene"); + setUIIDFinal("Scene"); camera = new Property("camera", (Camera) null); } diff --git a/CodenameOne/src/com/codename1/ui/spinner/BaseSpinner.java b/CodenameOne/src/com/codename1/ui/spinner/BaseSpinner.java index 85902b9707..c0885bffd0 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/BaseSpinner.java +++ b/CodenameOne/src/com/codename1/ui/spinner/BaseSpinner.java @@ -43,7 +43,7 @@ public abstract class BaseSpinner extends Container { */ public BaseSpinner() { super(new BoxLayout(BoxLayout.X_AXIS)); - setUIID("SpinnerWrapper"); + setUIIDFinal("SpinnerWrapper"); overlayStyle = getUIManager().getComponentStyle("SpinnerOverlay"); installDefaultPainter(overlayStyle); } @@ -92,12 +92,7 @@ public void refreshTheme(boolean merge) { } Component createSeparator() { - Label l = new Label(" ") { - - public void repaint() { - getParent().repaint(); - } - }; + Label l = new ParentRepaintingLabel(); l.setUIID("SpinnerSeparator"); return l; } @@ -126,4 +121,14 @@ private void paintOverlay(Graphics g) { } g.translate(-x, -y); } + + private static class ParentRepaintingLabel extends Label { + public ParentRepaintingLabel() { + super(" "); + } + + public void repaint() { + getParent().repaint(); + } + } } diff --git a/CodenameOne/src/com/codename1/ui/spinner/DateSpinner3D.java b/CodenameOne/src/com/codename1/ui/spinner/DateSpinner3D.java index 6799942b6b..4ac5c7fdd3 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/DateSpinner3D.java +++ b/CodenameOne/src/com/codename1/ui/spinner/DateSpinner3D.java @@ -101,42 +101,13 @@ protected void initComponent() { void initSpinner() { if (month == null) { day = Spinner3D.create(1, 31, currentDay, 1); - day.setRowFormatter(new SpinnerNode.RowFormatter() { - - @Override - public String format(String input) { - if (input != null) { - return String.valueOf((int) Double.parseDouble(input)); - } - return null; - } - }); + day.setRowFormatter(new DayRowFormatter()); month = Spinner3D.create(1, 12, currentMonth, 1); - month.setRowFormatter(new SpinnerNode.RowFormatter() { - @Override - public String format(String input) { - if (input != null) { - Calendar c = Calendar.getInstance(); - c.set(Calendar.MONTH, (int) Double.parseDouble(input) - 1); - c.set(Calendar.DAY_OF_MONTH, 15); - return monthFormat.format(c.getTime()); - } - return null; - } - }); + month.setRowFormatter(new MonthRowFormatter()); year = Spinner3D.create(startYear, endYear, currentYear, 1); - year.setRowFormatter(new SpinnerNode.RowFormatter() { - - @Override - public String format(String input) { - if (input != null) { - return String.valueOf((int) Double.parseDouble(input)); - } - return null; - } - }); + year.setRowFormatter(new YearRowFormatter()); addComponents(); //getAllStyles().setBgColor(year.getUnselectedStyle().getBgColor()); @@ -637,4 +608,38 @@ public void paint(Graphics g) { } + private static class YearRowFormatter implements SpinnerNode.RowFormatter { + + @Override + public String format(String input) { + if (input != null) { + return String.valueOf((int) Double.parseDouble(input)); + } + return null; + } + } + + private static class DayRowFormatter implements SpinnerNode.RowFormatter { + + @Override + public String format(String input) { + if (input != null) { + return String.valueOf((int) Double.parseDouble(input)); + } + return null; + } + } + + private class MonthRowFormatter implements SpinnerNode.RowFormatter { + @Override + public String format(String input) { + if (input != null) { + Calendar c = Calendar.getInstance(); + c.set(Calendar.MONTH, (int) Double.parseDouble(input) - 1); + c.set(Calendar.DAY_OF_MONTH, 15); + return monthFormat.format(c.getTime()); + } + return null; + } + } } diff --git a/CodenameOne/src/com/codename1/ui/spinner/Picker.java b/CodenameOne/src/com/codename1/ui/spinner/Picker.java index 53cb691c62..1562b19e50 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/Picker.java +++ b/CodenameOne/src/com/codename1/ui/spinner/Picker.java @@ -114,7 +114,7 @@ public class Picker extends Button { * Default constructor */ public Picker() { - setUIID("Picker"); + setUIIDFinal("Picker"); setPreferredTabIndex(0); // Fixes iOS picker issue https://github.com/codenameone/CodenameOne/issues/3283 @@ -1207,8 +1207,17 @@ public void setSelectedString(String str) { */ public int getSelectedStringIndex() { int offset = 0; + if (value == null) { + for (String s : (String[]) metaData) { + if (s == null) { + return offset; + } + offset++; + } + return -1; + } for (String s : (String[]) metaData) { - if (s == value) { + if (value.equals(s)) { return offset; } offset++; diff --git a/CodenameOne/src/com/codename1/ui/spinner/Spinner.java b/CodenameOne/src/com/codename1/ui/spinner/Spinner.java index 3496dc6676..6cbfd6efdb 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/Spinner.java +++ b/CodenameOne/src/com/codename1/ui/spinner/Spinner.java @@ -103,7 +103,7 @@ class Spinner extends List { } SpinnerRenderer.iOS7Mode = ios7Mode; setRenderer(rendererInstance); - setUIID("Spinner"); + setUIIDFinal("Spinner"); setFixedSelection(FIXED_CENTER); setOrientation(VERTICAL); setInputOnFocus(false); diff --git a/CodenameOne/src/com/codename1/ui/spinner/SpinnerNode.java b/CodenameOne/src/com/codename1/ui/spinner/SpinnerNode.java index 52c452df3c..362a97782a 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/SpinnerNode.java +++ b/CodenameOne/src/com/codename1/ui/spinner/SpinnerNode.java @@ -69,20 +69,7 @@ public SpinnerNode() { selectedRowStyle = rowTemplate.getSelectedStyle(); overlayStyle = overlayTemplate.getUnselectedStyle(); selectedRowOverlay.setStyle(overlayStyle); - selectedRowOverlay.setRenderer(new NodePainter() { - public void paint(Graphics g, Rectangle bounds, Node node) { - Style style = node.getStyle(); - g.setColor(style.getBgColor()); - g.fillRect(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight()); - g.setColor(style.getFgColor()); - int alpha = g.concatenateAlpha(style.getFgAlpha()); - g.drawLine(bounds.getX(), bounds.getY(), bounds.getWidth() + bounds.getX(), bounds.getY()); - g.drawLine(bounds.getX(), bounds.getY() + bounds.getHeight(), - bounds.getX() + bounds.getWidth(), bounds.getY() + bounds.getHeight() - ); - g.setAlpha(alpha); - } - }); + selectedRowOverlay.setRenderer(new SpinnerNodePainter()); } private static boolean usePerspective() { @@ -290,16 +277,7 @@ private Node getOrCreateChild(int i) { if (rowFormatter != null) { lbl = rowFormatter.format(lbl); } - Label renderer = new Label(lbl, "Spinner3DRow") { - @Override - public Style getStyle() { - if (n.hasTag("selected")) { - return this.getSelectedStyle(); - } else { - return this.getUnselectedStyle(); - } - } - }; + Label renderer = new SpinnerRenderer(lbl, n); renderer.setSelectedStyle(getSelectedRowStyle()); renderer.setUnselectedStyle(getRowStyle()); @@ -448,4 +426,36 @@ public interface RowFormatter { String format(String input); } + private static class SpinnerRenderer extends Label { + private final Node n; + + public SpinnerRenderer(String lbl, Node n) { + super(lbl, "Spinner3DRow"); + this.n = n; + } + + @Override + public Style getStyle() { + if (n.hasTag("selected")) { + return this.getSelectedStyle(); + } else { + return this.getUnselectedStyle(); + } + } + } + + private static class SpinnerNodePainter implements NodePainter { + public void paint(Graphics g, Rectangle bounds, Node node) { + Style style = node.getStyle(); + g.setColor(style.getBgColor()); + g.fillRect(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight()); + g.setColor(style.getFgColor()); + int alpha = g.concatenateAlpha(style.getFgAlpha()); + g.drawLine(bounds.getX(), bounds.getY(), bounds.getWidth() + bounds.getX(), bounds.getY()); + g.drawLine(bounds.getX(), bounds.getY() + bounds.getHeight(), + bounds.getX() + bounds.getWidth(), bounds.getY() + bounds.getHeight() + ); + g.setAlpha(alpha); + } + } } diff --git a/CodenameOne/src/com/codename1/ui/spinner/SpinnerRenderer.java b/CodenameOne/src/com/codename1/ui/spinner/SpinnerRenderer.java index 58bd42ee51..644352e109 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/SpinnerRenderer.java +++ b/CodenameOne/src/com/codename1/ui/spinner/SpinnerRenderer.java @@ -119,7 +119,7 @@ private int drawCharPerspectivePosition(Graphics g, char c, int x, int y) { } } } - Character chr = new Character(c); + Character chr = c; Image i = imageCache[perspective].get(chr); if (i == null) { //UIManager.getInstance().getLookAndFeel().setFG(g, this); diff --git a/CodenameOne/src/com/codename1/ui/spinner/TimeSpinner.java b/CodenameOne/src/com/codename1/ui/spinner/TimeSpinner.java index d9b319e7c3..761612e663 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/TimeSpinner.java +++ b/CodenameOne/src/com/codename1/ui/spinner/TimeSpinner.java @@ -97,32 +97,10 @@ void initSpinner() { amPM = Spinner.create(0, 2, 0, 1); } ((DefaultListCellRenderer) hour.getRenderer()).setRightAlignNumbers(true); - SpinnerRenderer twoDigitRender = new SpinnerRenderer() { - public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) { - if (value != null && value instanceof Integer) { - int i = ((Integer) value).intValue(); - if (i < 10) { - value = "0" + i; - } - } - return super.getListCellRendererComponent(list, value, index, isSelected); - } - }; + SpinnerRenderer twoDigitRender = new TwoDigitSpinnerRenderer(); minute.setRenderer(twoDigitRender); - SpinnerRenderer render = new SpinnerRenderer() { - public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) { - if (value != null && value instanceof Integer) { - int d = ((Integer) value).intValue(); - if (d == 0) { - value = "AM"; - } else { - value = "PM"; - } - } - return super.getListCellRendererComponent(list, value, index, isSelected); - } - }; + SpinnerRenderer render = new TimeSpinnerRenderer(); amPM.setRenderer(render); render.setRTL(false); render.setShowNumbers(false); @@ -447,4 +425,30 @@ public void setMinutesVisible(boolean visible) { c.setHidden(!visible); } } + + private static class TimeSpinnerRenderer extends SpinnerRenderer { + public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) { + if (value != null && value instanceof Integer) { + int d = ((Integer) value).intValue(); + if (d == 0) { + value = "AM"; + } else { + value = "PM"; + } + } + return super.getListCellRendererComponent(list, value, index, isSelected); + } + } + + private static class TwoDigitSpinnerRenderer extends SpinnerRenderer { + public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) { + if (value != null && value instanceof Integer) { + int i = ((Integer) value).intValue(); + if (i < 10) { + value = "0" + i; + } + } + return super.getListCellRendererComponent(list, value, index, isSelected); + } + } } diff --git a/CodenameOne/src/com/codename1/ui/spinner/TimeSpinner3D.java b/CodenameOne/src/com/codename1/ui/spinner/TimeSpinner3D.java index fd99efed1c..f740bd5284 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/TimeSpinner3D.java +++ b/CodenameOne/src/com/codename1/ui/spinner/TimeSpinner3D.java @@ -84,66 +84,24 @@ public TimeSpinner3D() { void initSpinner() { if (hour == null) { hour = Spinner3D.create(startHour, endHour, currentHour, 1); - hour.setRowFormatter(new RowFormatter() { - - @Override - public String format(String input) { - if (input != null) { - return Integer.toString((int) Double.parseDouble(input)); - } - return null; - } - - }); + hour.setRowFormatter(new HourRowFormatter()); Style hourStyle = Style.createProxyStyle(hour.getRowStyle(), hour.getSelectedRowStyle()); hourStyle.setAlignment(Component.RIGHT); hourStyle.setPaddingRight(3f); - //hour.refreshStyles(); minute = Spinner3D.create(0, 59, currentMinute, minuteStep); - minute.setRowFormatter(new SpinnerNode.RowFormatter() { - - @Override - public String format(String input) { - if (input != null) { - try { - int i = (int) Double.parseDouble(input); - if (i < 10) { - return "0" + i; - } else { - return Integer.toString(i); - } - } catch (Throwable t) { - // ignore and return null below - } - } - return null; - } - }); + minute.setRowFormatter(new MinuteRowFormatter()); Style minuteStyle = Style.createProxyStyle(minute.getRowStyle(), minute.getSelectedRowStyle()); minuteStyle.setAlignment(Component.RIGHT); minuteStyle.setPaddingRight(3f); - //minute.refreshStyles(); if (currentMeridiem) { amPM = Spinner3D.create(0, 2, 1, 1); } else { amPM = Spinner3D.create(0, 2, 0, 1); } - amPM.setRowFormatter(new RowFormatter() { - - @Override - public String format(String input) { - if (Double.parseDouble(input) < 1) { - return "AM"; - } - return "PM"; - } - - }); - //getAllStyles().setBgColor(hour.getUnselectedStyle().getBgColor()); - //getAllStyles().setBgTransparency(255); + amPM.setRowFormatter(new AmPmRowFormatter()); addComponents(); } } @@ -156,17 +114,30 @@ void addComponents() { setLayout(new LayeredLayout()); addComponent(hour); - addComponent(minute); LayeredLayout ll = (LayeredLayout) getLayout(); - if (showMeridiem) { - //content.addComponent(createSeparator()); - addComponent(amPM); - ll.setInsets(hour, "0 67% 0 0") - .setInsets(minute, "0 33% 0 33%") - .setInsets(amPM, "0 0 0 67%"); + if (durationMode) { + Label hoursLabel = new Label(getUIManager().localize("hours", "hours"), "TimeSpinnerHoursLabel"); + Label minutesLabel = new Label(getUIManager().localize("minutes", "minutes"), "TimeSpinnerMinutesLabel"); + addComponent(hoursLabel); + addComponent(minute); + addComponent(minutesLabel); + + ll.setInsets(hour, "0 75% 0 0"); + ll.setInsets(hoursLabel, "0 50% 0 25%"); + ll.setInsets(minute, "0 25% 0 50%"); + ll.setInsets(minutesLabel, "0 0 0 75%"); } else { - ll.setInsets(hour, "0 50% 0 0") - .setInsets(minute, "0 0 0 50%"); + addComponent(minute); + if (showMeridiem) { + //content.addComponent(createSeparator()); + addComponent(amPM); + ll.setInsets(hour, "0 67% 0 0") + .setInsets(minute, "0 33% 0 33%") + .setInsets(amPM, "0 0 0 67%"); + } else { + ll.setInsets(hour, "0 50% 0 0") + .setInsets(minute, "0 0 0 50%"); + } } @@ -352,7 +323,10 @@ public void setShowMeridiem(boolean showMeridiem) { } private void rebuildHours() { - if (showMeridiem) { + if (durationMode) { + startHour = 0; + endHour = 24; + } else if (showMeridiem) { startHour = 1; endHour = 12; } else { @@ -449,6 +423,27 @@ public void setCurrentMeridiem(boolean currentMeridiem) { } } + /** + * Duration mode uses the time spinner to indicate a duration in hours and minutes + * + * @return the durationMode + */ + public boolean isDurationMode() { + return durationMode; + } + + /** + * Duration mode uses the time spinner to indicate a duration in hours and minutes + * + * @param durationMode the durationMode to set + */ + public void setDurationMode(boolean durationMode) { + this.durationMode = durationMode; + if (durationMode) { + showMeridiem = false; + } + rebuildHours(); + } /** * Show or hide the hours spinner. @@ -533,4 +528,45 @@ public void paint(Graphics g) { } + private static class AmPmRowFormatter implements RowFormatter { + @Override + public String format(String input) { + if (Double.parseDouble(input) < 1) { + return "AM"; + } + return "PM"; + } + } + + private static class MinuteRowFormatter implements RowFormatter { + + @Override + public String format(String input) { + if (input != null) { + try { + int i = (int) Double.parseDouble(input); + if (i < 10) { + return "0" + i; + } else { + return Integer.toString(i); + } + } catch (Throwable t) { + // ignore and return null below + } + } + return null; + } + } + + private static class HourRowFormatter implements RowFormatter { + + @Override + public String format(String input) { + if (input != null) { + return Integer.toString((int) Double.parseDouble(input)); + } + return null; + } + + } } diff --git a/CodenameOne/src/com/codename1/ui/table/SortableTableModel.java b/CodenameOne/src/com/codename1/ui/table/SortableTableModel.java index e0cbdd7de3..6d1b44cd87 100644 --- a/CodenameOne/src/com/codename1/ui/table/SortableTableModel.java +++ b/CodenameOne/src/com/codename1/ui/table/SortableTableModel.java @@ -86,18 +86,7 @@ private void initTable(final TableModel model1, final boolean asc, } // sort(int[]) doesn't accept a comparator how stupid is that... Arrays.sort(sortedTemp, - new Comparator() { - public int compare(Object o1, Object o2) { - int i1 = (Integer) o1; - int i2 = (Integer) o2; - if (asc) { - return cmp.compare(model1.getValueAt(i1, column), - model1.getValueAt(i2, column)) * -1; - } - return cmp.compare(model1.getValueAt(i1, column), - model1.getValueAt(i2, column)); - } - }); + new TemporarySorterComparator(asc, cmp, model1, column)); for (int iter = 0; iter < sorted.length; iter++) { sorted[iter] = sortedTemp[iter]; } @@ -219,4 +208,29 @@ public void setValidator(Validator validator) { } super.setValidator(validator); } + + private static class TemporarySorterComparator implements Comparator { + private final boolean asc; + private final Comparator cmp; + private final TableModel model1; + private final int column; + + public TemporarySorterComparator(boolean asc, Comparator cmp, TableModel model1, int column) { + this.asc = asc; + this.cmp = cmp; + this.model1 = model1; + this.column = column; + } + + public int compare(Object o1, Object o2) { + int i1 = (Integer) o1; + int i2 = (Integer) o2; + if (asc) { + return cmp.compare(model1.getValueAt(i1, column), + model1.getValueAt(i2, column)) * -1; + } + return cmp.compare(model1.getValueAt(i1, column), + model1.getValueAt(i2, column)); + } + } } diff --git a/CodenameOne/src/com/codename1/ui/table/Table.java b/CodenameOne/src/com/codename1/ui/table/Table.java index c25f0d9748..01e3f45c2b 100644 --- a/CodenameOne/src/com/codename1/ui/table/Table.java +++ b/CodenameOne/src/com/codename1/ui/table/Table.java @@ -140,7 +140,7 @@ public Table() { * @param model the model underlying this table */ public Table(TableModel model) { - setUIID("Table"); + setUIIDFinal("Table"); this.model = model; updateModel(); } @@ -152,7 +152,7 @@ public Table(TableModel model) { * @param includeHeader Indicates whether the table should render a table header as the first row */ public Table(TableModel model, boolean includeHeader) { - setUIID("Table"); + setUIIDFinal("Table"); this.includeHeader = includeHeader; this.model = model; updateModel(); @@ -236,16 +236,13 @@ private void updateModel() { Component cell = createCellImpl(value, r, c, e); TableLayout.Constraint con = createCellConstraint(value, r, c); - // returns the current row we iterate about - int currentRow = ((TableLayout) getLayout()).getNextRow(); - - if (r > model.getRowCount()) { - return; - } - addComponent(con, cell); - if (r == selectionRow && c == selectionColumn) { - cell.requestFocus(); - } + if (r > model.getRowCount()) { + return; + } + addComponent(con, cell); + if (r == selectionRow && c == selectionColumn) { + cell.requestFocus(); + } } } } @@ -426,53 +423,14 @@ private Component createCellImpl(Object value, final int row, final int column, /** * Returns a generic comparator that tries to work in a way that will sort columns with similar object types. - * This method can be overriden to create custom sort orders or return null and thus disable sorting for a + * This method can be overridden to create custom sort orders or return null and thus disable sorting for a * specific column * * @param column the column that's sorted * @return the comparator instance */ - protected Comparator createColumnSortComparator(int column) { - final CaseInsensitiveOrder ccmp = new CaseInsensitiveOrder(); - return new Comparator() { - public int compare(Object o1, Object o2) { - if (o1 == null) { - if (o2 == null) { - return 0; - } - return -1; - } else { - if (o2 == null) { - return 1; - } - } - if (o1 instanceof String && o2 instanceof String) { - return ccmp.compare((String) o1, (String) o2); - } - try { - double d1 = Util.toDoubleValue(o1); - double d2 = Util.toDoubleValue(o2); - if (d1 < d2) { - return -1; - } - if (d1 > d2) { - return 1; - } - long bits1 = Double.doubleToLongBits(d1); - long bits2 = Double.doubleToLongBits(d2); - if (bits1 < bits2) { - return -1; - } - if (bits1 > bits2) { - return 1; - } - } catch (IllegalArgumentException err) { - long dd = Util.toDateValue(o1).getTime() - Util.toDateValue(o2).getTime(); - return (int) dd; - } - return 0; - } - }; + protected Comparator createColumnSortComparator(int column) { + return new ColumnSortComparator(new CaseInsensitiveOrder()); } /** @@ -483,7 +441,7 @@ public int compare(Object o1, Object o2) { */ public void sort(int column, boolean ascending) { sortedColumn = column; - Comparator cmp = createColumnSortComparator(column); + Comparator cmp = createColumnSortComparator(column); if (model instanceof SortableTableModel) { model = ((SortableTableModel) model).getUnderlying(); } @@ -505,9 +463,9 @@ protected Component createCell(Object value, int row, final int column, boolean header.getAllStyles().setAlignment(titleAlignment); header.setTextPosition(LEFT); if (isSortSupported()) { - header.addActionListener(new ActionListener() { + header.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { - Comparator cmp = createColumnSortComparator(column); + Comparator cmp = createColumnSortComparator(column); if (column == sortedColumn) { ascending = !ascending; } else { @@ -991,6 +949,38 @@ private boolean isAbstractTableModel() { return model instanceof AbstractTableModel; } + private static class ColumnSortComparator implements Comparator { + private final CaseInsensitiveOrder ccmp; + + public ColumnSortComparator(CaseInsensitiveOrder ccmp) { + this.ccmp = ccmp; + } + + public int compare(Object o1, Object o2) { + if (o1 == null) { + if (o2 == null) { + return 0; + } + return -1; + } else { + if (o2 == null) { + return 1; + } + } + if (o1 instanceof String && o2 instanceof String) { + return ccmp.compare((String) o1, (String) o2); + } + try { + double d1 = Util.toDoubleValue(o1); + double d2 = Util.toDoubleValue(o2); + return Double.compare(d1, d2); + } catch (IllegalArgumentException err) { + long dd = Util.toDateValue(o1).getTime() - Util.toDateValue(o2).getTime(); + return (int) dd; + } + } + } + class Listener implements DataChangedListener, ActionListener { private int editingColumn = -1; private int editingRow = -1; diff --git a/CodenameOne/src/com/codename1/ui/tree/Tree.java b/CodenameOne/src/com/codename1/ui/tree/Tree.java index aed8edd102..a116544581 100644 --- a/CodenameOne/src/com/codename1/ui/tree/Tree.java +++ b/CodenameOne/src/com/codename1/ui/tree/Tree.java @@ -112,7 +112,7 @@ public Tree(TreeModel model) { } buildBranch(null, 0, this); setScrollableY(true); - setUIID("Tree"); + setUIIDFinal("Tree"); } /** @@ -810,7 +810,7 @@ public Vector getChildren(Object parent) { int aolen = arr[0].length; Vector v = new Vector(); for (int iter = 0; iter < aolen; iter++) { - if (parent == arr[0][iter]) { + if (parent.equals(arr[0][iter])) { if (alen > iter + 1 && arr[iter + 1] != null) { int ailen = arr[iter + 1].length; for (int i = 0; i < ailen; i++) { diff --git a/CodenameOne/src/com/codename1/ui/util/GlassTutorial.java b/CodenameOne/src/com/codename1/ui/util/GlassTutorial.java index 11d0e11781..5ee589bb39 100644 --- a/CodenameOne/src/com/codename1/ui/util/GlassTutorial.java +++ b/CodenameOne/src/com/codename1/ui/util/GlassTutorial.java @@ -83,11 +83,7 @@ public void addHint(Component hintComponent, Component destinationComponent, Str public void showOn(Form f) { Painter oldPane = f.getGlassPane(); f.setGlassPane(this); - Dialog dummy = new Dialog() { - public void keyReleased(int i) { - dispose(); - } - }; + Dialog dummy = new DisposableDialog(); int oldTint = f.getTintColor(); f.setTintColor(0); @@ -157,4 +153,9 @@ public void paint(Graphics g, Rectangle rect) { } } + private static class DisposableDialog extends Dialog { + public void keyReleased(int i) { + dispose(); + } + } } diff --git a/CodenameOne/src/com/codename1/ui/util/Resources.java b/CodenameOne/src/com/codename1/ui/util/Resources.java index ac872d0f7d..fe6a32dff8 100644 --- a/CodenameOne/src/com/codename1/ui/util/Resources.java +++ b/CodenameOne/src/com/codename1/ui/util/Resources.java @@ -1070,7 +1070,8 @@ Image createImage(DataInputStream input) throws IOException { while (svgSize > 0) { svgSize -= input.skip(svgSize); } - String baseURL = input.readUTF(); + // reading baseURL + input.readUTF(); // read the animated property to skip it as well... input.readBoolean(); @@ -1198,19 +1199,8 @@ Font loadFont(DataInputStream input, String id, boolean packed) throws IOExcepti // read a system font fallback int fallback = input.readByte() & 0xff; - // do we have an emedded truetype font? Do we support embedded fonts? - boolean trueTypeIncluded = input.readBoolean(); + // do we have an embedded truetype font? Do we support embedded fonts? Font font = null; - /*if(trueTypeIncluded) { - int size = input.readInt(); - if(Font.isTrueTypeFileSupported()) { - font = Font.createTrueTypeFont(input); - } else { - while(size > 0) { - size -= input.skip(size); - } - } - }*/ boolean lookupIncluded = input.readBoolean(); if (lookupIncluded) { String lookup = input.readUTF(); @@ -1310,6 +1300,13 @@ Font createTrueTypeFont(Font f, String fontName, String fileName, float fontSize return Font.createTrueTypeFont(fontName, fileName).derive(fontSize, f.getStyle()); } + static class MediaRule { + int matchCount; + int bestMatchScore; + String rawKey; + String translatedKey; + } + Hashtable loadTheme(String id, boolean newerVersion) throws IOException { Hashtable theme = new Hashtable(); String densityStr = Display.getInstance().getDensityStr(); @@ -1328,14 +1325,6 @@ Hashtable loadTheme(String id, boolean newerVersion) throws IOException { int size = input.readShort(); List fontKeys = new ArrayList(); Map fontScaleRules = null; - class MediaRule { - int matchCount; - int bestMatchScore; - String rawKey; - String translatedKey; - - - } Map mediaRules = new HashMap(); int defaultFontSizeSetPriority = 0; for (int iter = 0; iter < size; iter++) { diff --git a/CodenameOne/src/com/codename1/ui/util/SwipeBackSupport.java b/CodenameOne/src/com/codename1/ui/util/SwipeBackSupport.java index 36deae6d90..9a794e3462 100644 --- a/CodenameOne/src/com/codename1/ui/util/SwipeBackSupport.java +++ b/CodenameOne/src/com/codename1/ui/util/SwipeBackSupport.java @@ -172,11 +172,7 @@ void startBackTransition(final Form currentForm, Form destination) { if (t instanceof CommonTransitions) { Transition originalTransition = currentForm.getTransitionOutAnimator(); currentForm.setTransitionOutAnimator(CommonTransitions.createEmpty()); - Form blank = new Form() { - protected boolean shouldSendPointerReleaseToOtherForm() { - return true; - } - }; + Form blank = new SendPointerReleaseToOtherForm(); blank.addPointerDraggedListener(pointerDragged); blank.addPointerReleasedListener(pointerReleased); blank.addPointerPressedListener(pointerPressed); @@ -191,12 +187,26 @@ public Motion get(Object... args) { }); t.init(currentForm, destination); t.initTransition(); - blank.setGlassPane(new Painter() { - public void paint(Graphics g, Rectangle rect) { - t.animate(); - t.paint(g); - } - }); + blank.setGlassPane(new BackGlassPanePainter(t)); + } + } + + private static class BackGlassPanePainter implements Painter { + private final Transition t; + + public BackGlassPanePainter(Transition t) { + this.t = t; + } + + public void paint(Graphics g, Rectangle rect) { + t.animate(); + t.paint(g); + } + } + + private static class SendPointerReleaseToOtherForm extends Form { + protected boolean shouldSendPointerReleaseToOtherForm() { + return true; } } diff --git a/CodenameOne/src/com/codename1/ui/util/UIBuilder.java b/CodenameOne/src/com/codename1/ui/util/UIBuilder.java index 15c270201b..e7b9c237bd 100644 --- a/CodenameOne/src/com/codename1/ui/util/UIBuilder.java +++ b/CodenameOne/src/com/codename1/ui/util/UIBuilder.java @@ -907,9 +907,8 @@ private Object readCustomPropertyValue(DataInputStream in, Class type, String ty // resource might have been removed we need to fail gracefully String[] uiNames = res.getUIResourceNames(); String currentName = in.readUTF(); - int ulen = uiNames.length; - for (int iter = 0; iter < ulen; iter++) { - if (uiNames[iter].equals(currentName)) { + for (String uiName : uiNames) { + if (uiName.equals(currentName)) { return createContainer(res, currentName); } } @@ -931,7 +930,7 @@ private Object readCustomPropertyValue(DataInputStream in, Class type, String ty } } - return new Character(in.readChar()); + return in.readChar(); } private Component createComponent(DataInputStream in, Container parent, Container root, Resources res, Hashtable componentListeners, EmbeddedContainer embedded) throws Exception { diff --git a/CodenameOne/src/com/codename1/ui/validation/Validator.java b/CodenameOne/src/com/codename1/ui/validation/Validator.java index fef571c550..53dbd2e016 100644 --- a/CodenameOne/src/com/codename1/ui/validation/Validator.java +++ b/CodenameOne/src/com/codename1/ui/validation/Validator.java @@ -424,18 +424,7 @@ public void run() { } }; - FocusListener myFocusListener = new FocusListener() { - - @Override - public void focusLost(Component cmp) { - showError.run(); - } - - @Override - public void focusGained(Component cmp) { - // no code here - } - }; + FocusListener myFocusListener = new ConstraintFocusListener(showError); if (inputComponent instanceof TextComponent) { ((TextComponent) inputComponent).getField().addFocusListener(myFocusListener); @@ -730,6 +719,24 @@ public enum HighlightMode { NONE } + private static class ConstraintFocusListener implements FocusListener { + private final Runnable showError; + + public ConstraintFocusListener(Runnable showError) { + this.showError = showError; + } + + @Override + public void focusLost(Component cmp) { + showError.run(); + } + + @Override + public void focusGained(Component cmp) { + // no code here + } + } + class ComponentListener implements ActionListener, DataChangedListener, Painter { private final Component cmp; private Rectangle visibleRect = new Rectangle(); diff --git a/CodenameOne/src/com/codename1/util/AsyncResource.java b/CodenameOne/src/com/codename1/util/AsyncResource.java index dc90efbce5..6e9c63f1f4 100644 --- a/CodenameOne/src/com/codename1/util/AsyncResource.java +++ b/CodenameOne/src/com/codename1/util/AsyncResource.java @@ -164,7 +164,7 @@ public static void await(AsyncResource... resources) throws AsyncExecutionExc public void onSucess(Object arg) { synchronized (complete) { complete[0] = true; - complete.notify(); + complete.notifyAll(); } } }).except(new SuccessCallback() { @@ -173,7 +173,7 @@ public void onSucess(Throwable ex) { synchronized (complete) { t[0] = ex; complete[0] = true; - complete.notify(); + complete.notifyAll(); } } }); @@ -282,7 +282,7 @@ public void update(Observable obj, Object arg) { if (isDone()) { complete[0] = true; synchronized (complete) { - complete.notify(); + complete.notifyAll(); } } } diff --git a/CodenameOne/src/com/codename1/util/EasyThread.java b/CodenameOne/src/com/codename1/util/EasyThread.java index c2a2815f98..5d49c79a0b 100644 --- a/CodenameOne/src/com/codename1/util/EasyThread.java +++ b/CodenameOne/src/com/codename1/util/EasyThread.java @@ -140,7 +140,7 @@ public void run(RunnableWithResult r, SuccessCallback t) { synchronized (LOCK) { queue.add(r); queue.add(t); - LOCK.notify(); + LOCK.notifyAll(); } } @@ -152,7 +152,7 @@ public void run(RunnableWithResult r, SuccessCallback t) { public void run(Runnable r) { synchronized (LOCK) { queue.add(r); - LOCK.notify(); + LOCK.notifyAll(); } } @@ -163,38 +163,18 @@ public void run(Runnable r) { * @return value returned by r */ public T run(final RunnableWithResultSync r) { - // we need the flag and can't use the result object. Since null would be a valid value for the result - // we would have a hard time of detecting the case of the code completing before the wait call + // we need the flag and can't use the result object. Since null would be a valid value for the result, + // we would have a hard time of detecting the case of code completing before the wait call final boolean[] flag = new boolean[1]; final Object[] result = new Object[1]; - final SuccessCallback sc = new SuccessCallback() { - public void onSucess(T value) { - synchronized (flag) { - result[0] = value; - flag[0] = true; - flag.notify(); - } - } - }; - RunnableWithResult rr = new RunnableWithResult() { - public void run(SuccessCallback onSuccess) { - sc.onSucess(r.run()); - } - }; + final SuccessCallback sc = new RunSuccessCallback(flag, result); + RunnableWithResult rr = new RunCallbackRunnableWithResult(sc, r); synchronized (LOCK) { queue.add(rr); queue.add(sc); - LOCK.notify(); + LOCK.notifyAll(); } - Display.getInstance().invokeAndBlock(new Runnable() { - public void run() { - synchronized (flag) { - if (!flag[0]) { - Util.wait(flag); - } - } - } - }); + Display.getInstance().invokeAndBlock(new RunInvokeAndBlockRunnable(flag)); return (T) result[0]; } @@ -206,29 +186,10 @@ public void run() { public void runAndWait(final Runnable r) { final boolean[] flag = new boolean[1]; synchronized (LOCK) { - queue.add(new Runnable() { - public void run() { - try { - r.run(); - } finally { - synchronized (flag) { - flag[0] = true; - flag.notify(); - } - } - } - }); - LOCK.notify(); + queue.add(new InQueueRunnable(r, flag)); + LOCK.notifyAll(); } - Display.getInstance().invokeAndBlock(new Runnable() { - public void run() { - synchronized (flag) { - if (!flag[0]) { - Util.wait(flag); - } - } - } - }); + Display.getInstance().invokeAndBlock(new RunAndWaitRunnable(flag)); } /** @@ -237,7 +198,7 @@ public void run() { public void kill() { synchronized (LOCK) { running = false; - LOCK.notify(); + LOCK.notifyAll(); } } @@ -306,4 +267,89 @@ public interface ErrorListener { */ void onError(EasyThread t, T callback, Throwable error); } + + private static class RunAndWaitRunnable implements Runnable { + private final boolean[] flag; + + public RunAndWaitRunnable(boolean[] flag) { + this.flag = flag; + } + + public void run() { + synchronized (flag) { + if (!flag[0]) { + Util.wait(flag); + } + } + } + } + + private static class InQueueRunnable implements Runnable { + private final Runnable r; + private final boolean[] flag; + + public InQueueRunnable(Runnable r, boolean[] flag) { + this.r = r; + this.flag = flag; + } + + public void run() { + try { + r.run(); + } finally { + synchronized (flag) { + flag[0] = true; + flag.notifyAll(); + } + } + } + } + + private static class RunInvokeAndBlockRunnable implements Runnable { + private final boolean[] flag; + + public RunInvokeAndBlockRunnable(boolean[] flag) { + this.flag = flag; + } + + public void run() { + synchronized (flag) { + if (!flag[0]) { + Util.wait(flag); + } + } + } + } + + private static class RunCallbackRunnableWithResult implements RunnableWithResult { + private final SuccessCallback sc; + private final RunnableWithResultSync r; + + public RunCallbackRunnableWithResult(SuccessCallback sc, RunnableWithResultSync r) { + this.sc = sc; + this.r = r; + } + + public void run(SuccessCallback onSuccess) { + sc.onSucess(r.run()); + } + } + + private static class RunSuccessCallback implements SuccessCallback { + private final boolean[] flag; + private final Object[] result; + + public RunSuccessCallback(boolean[] flag, Object[] result) { + this.flag = flag; + this.result = result; + } + + public void onSucess(T value) { + synchronized (flag) { + result[0] = value; + flag[0] = true; + flag.notifyAll(); + } + } + } } diff --git a/CodenameOne/src/com/codename1/util/regex/RECompiler.java b/CodenameOne/src/com/codename1/util/regex/RECompiler.java index d8e26a5683..68b53f8630 100644 --- a/CodenameOne/src/com/codename1/util/regex/RECompiler.java +++ b/CodenameOne/src/com/codename1/util/regex/RECompiler.java @@ -47,20 +47,20 @@ public class RECompiler { static final HashMap hashPOSIX = new HashMap(); static { - hashPOSIX.put("alnum", new Character(RE.POSIX_CLASS_ALNUM)); - hashPOSIX.put("alpha", new Character(RE.POSIX_CLASS_ALPHA)); - hashPOSIX.put("blank", new Character(RE.POSIX_CLASS_BLANK)); - hashPOSIX.put("cntrl", new Character(RE.POSIX_CLASS_CNTRL)); - hashPOSIX.put("digit", new Character(RE.POSIX_CLASS_DIGIT)); - hashPOSIX.put("graph", new Character(RE.POSIX_CLASS_GRAPH)); - hashPOSIX.put("lower", new Character(RE.POSIX_CLASS_LOWER)); - hashPOSIX.put("print", new Character(RE.POSIX_CLASS_PRINT)); - hashPOSIX.put("punct", new Character(RE.POSIX_CLASS_PUNCT)); - hashPOSIX.put("space", new Character(RE.POSIX_CLASS_SPACE)); - hashPOSIX.put("upper", new Character(RE.POSIX_CLASS_UPPER)); - hashPOSIX.put("xdigit", new Character(RE.POSIX_CLASS_XDIGIT)); - hashPOSIX.put("javastart", new Character(RE.POSIX_CLASS_JSTART)); - hashPOSIX.put("javapart", new Character(RE.POSIX_CLASS_JPART)); + hashPOSIX.put("alnum", RE.POSIX_CLASS_ALNUM); + hashPOSIX.put("alpha", RE.POSIX_CLASS_ALPHA); + hashPOSIX.put("blank", RE.POSIX_CLASS_BLANK); + hashPOSIX.put("cntrl", RE.POSIX_CLASS_CNTRL); + hashPOSIX.put("digit", RE.POSIX_CLASS_DIGIT); + hashPOSIX.put("graph", RE.POSIX_CLASS_GRAPH); + hashPOSIX.put("lower", RE.POSIX_CLASS_LOWER); + hashPOSIX.put("print", RE.POSIX_CLASS_PRINT); + hashPOSIX.put("punct", RE.POSIX_CLASS_PUNCT); + hashPOSIX.put("space", RE.POSIX_CLASS_SPACE); + hashPOSIX.put("upper", RE.POSIX_CLASS_UPPER); + hashPOSIX.put("xdigit", RE.POSIX_CLASS_XDIGIT); + hashPOSIX.put("javastart", RE.POSIX_CLASS_JSTART); + hashPOSIX.put("javapart", RE.POSIX_CLASS_JPART); } // The compiled program @@ -550,8 +550,8 @@ int characterClass() throws RESyntaxException { case RE.E_DIGIT: range.include('0', '9', include); break; - default: - break; + default: + break; } // Make last char invalid (can't be a range start) @@ -869,9 +869,9 @@ int closure(int[] flags) throws RESyntaxException { if ((terminalFlags[0] & NODE_NULLABLE) != 0) { syntaxError("Closure operand can't be nullable"); } - break; - default: - break; + break; + default: + break; } // If the next character is a '?', make the closure non-greedy (reluctant) @@ -959,8 +959,8 @@ int closure(int[] flags) throws RESyntaxException { setNextOfEnd(n, ret); break; } - default: - break; + default: + break; } } else { // Actually do the closure now @@ -986,8 +986,8 @@ int closure(int[] flags) throws RESyntaxException { setNextOfEnd(ret + RE.nodeSize, n); break; } - default: - break; + default: + break; } } @@ -1169,7 +1169,7 @@ public REProgram compile(String pattern) throws RESyntaxException { /** * Local, nested class for maintaining character ranges for character classes. */ - static class RERange { + static class RERange { int size = 16; // Capacity of current range arrays int[] minRange = new int[size]; // Range minima int[] maxRange = new int[size]; // Range maxima diff --git a/CodenameOneDesigner/src/com/codename1/designer/L10nEditor.java b/CodenameOneDesigner/src/com/codename1/designer/L10nEditor.java index 13e36c1548..7b72526e82 100644 --- a/CodenameOneDesigner/src/com/codename1/designer/L10nEditor.java +++ b/CodenameOneDesigner/src/com/codename1/designer/L10nEditor.java @@ -1042,11 +1042,10 @@ private void syncWithUIActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FI final Map allKeys = new HashMap(); com.codename1.ui.plaf.UIManager original = com.codename1.ui.plaf.UIManager.getInstance(); Accessor.setUIManager(new com.codename1.ui.plaf.ProtectedUIManager() { - public String localize(String key, String defaultValue) { + public void onLocalize(String key, String defaultValue) { if(key != null && key.length() > 0 && defaultValue != null && defaultValue.length() > 0) { allKeys.put(key, defaultValue); } - return super.localize(key, defaultValue); } }); UIBuilderOverride o = new UIBuilderOverride(); diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java b/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java index 35875bf4f6..9aab124e56 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidImplementation.java @@ -52,7 +52,7 @@ import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.net.Uri; -import android.os.Vibrator; +import android.os.Vibrator; import android.os.PowerManager; import android.telephony.TelephonyManager; import android.util.DisplayMetrics; @@ -281,19 +281,19 @@ public static void setActivity(CodenameOneActivity aActivity) { private int displayHeight; static CodenameOneActivity activity; static ComponentName activityComponentName; - private static PowerManager.WakeLock pushWakeLock; - public static void acquirePushWakeLock(long timeout) { - if (getContext() == null) return; - try { - if (pushWakeLock == null) { - PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE); - pushWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "CN1:PushWakeLock"); - } - pushWakeLock.acquire(timeout); - } catch (Exception ex) { - com.codename1.io.Log.e(ex); - } - } + private static PowerManager.WakeLock pushWakeLock; + public static void acquirePushWakeLock(long timeout) { + if (getContext() == null) return; + try { + if (pushWakeLock == null) { + PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE); + pushWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "CN1:PushWakeLock"); + } + pushWakeLock.acquire(timeout); + } catch (Exception ex) { + com.codename1.io.Log.e(ex); + } + } private static Context context; RelativeLayout relativeLayout; @@ -2797,18 +2797,18 @@ public void exitApplication() { android.os.Process.killProcess(android.os.Process.myPid()); } - @Override - public void notifyPushCompletion() { - if (pushWakeLock != null && pushWakeLock.isHeld()) { - try { - pushWakeLock.release(); - } catch (Exception ex) { - com.codename1.io.Log.e(ex); - } - } - } - - @Override + @Override + public void notifyPushCompletion() { + if (pushWakeLock != null && pushWakeLock.isHeld()) { + try { + pushWakeLock.release(); + } catch (Exception ex) { + com.codename1.io.Log.e(ex); + } + } + } + + @Override public void notifyCommandBehavior(int commandBehavior) { if (commandBehavior == Display.COMMAND_BEHAVIOR_NATIVE) { if (getActivity() instanceof CodenameOneActivity) { @@ -2979,14 +2979,14 @@ private boolean isEmulator() { } - /** - * @inheritDoc - */ - @Override - public boolean canDial() { - return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY); - } - + /** + * @inheritDoc + */ + @Override + public boolean canDial() { + return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY); + } + /** * @inheritDoc */ @@ -4612,9 +4612,8 @@ public boolean isFocusable() { } @Override - public void setFocusable(final boolean focusable) { + public void onSetFocusable(final boolean focusable) { // EDT - super.setFocusable(focusable); if (getActivity() == null) { return; } @@ -6977,7 +6976,7 @@ public void sendMessage(String[] recipients, String subject, Message msg) { } if (msg.getMimeType().equals(Message.MIME_HTML)) { emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, Html.fromHtml(msg.getContent())); - emailIntent.putExtra("android.intent.extra.HTML_TEXT", msg.getContent()); + emailIntent.putExtra("android.intent.extra.HTML_TEXT", msg.getContent()); }else{ /* // Attempted this workaround to fix the ClassCastException that occurs on android when @@ -10924,36 +10923,36 @@ public static boolean checkForPermission(String permission, String description, if(android.os.Build.VERSION.SDK_INT < 23){ return true; } - - if (android.os.Build.VERSION.SDK_INT >= 30 && "android.permission.ACCESS_BACKGROUND_LOCATION".equals(permission)) { - if (android.support.v4.content.ContextCompat.checkSelfPermission(getContext(), permission) == PackageManager.PERMISSION_GRANTED) { - return true; - } - if (getActivity() == null) { - return false; - } - - String prompt = Display.getInstance().getProperty(permission, description); - String title = Display.getInstance().getProperty("android.permission.ACCESS_BACKGROUND_LOCATION.title", "Requires permission"); - String settingsBtn = Display.getInstance().getProperty("android.permission.ACCESS_BACKGROUND_LOCATION.settings", "Settings"); - String cancelBtn = Display.getInstance().getProperty("android.permission.ACCESS_BACKGROUND_LOCATION.cancel", "Cancel"); - - if(Dialog.show(title, prompt, settingsBtn, cancelBtn)){ - Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); - Uri uri = Uri.fromParts("package", getContext().getPackageName(), null); - intent.setData(uri); - getActivity().startActivity(intent); - - String explanationTitle = Display.getInstance().getProperty("android.permission.ACCESS_BACKGROUND_LOCATION.explanation_title", "Permission Required"); - String explanationBody = Display.getInstance().getProperty("android.permission.ACCESS_BACKGROUND_LOCATION.explanation_body", "Please enable 'Allow all the time' in the settings, then press OK."); - String okBtn = Display.getInstance().getProperty("android.permission.ACCESS_BACKGROUND_LOCATION.ok", "OK"); - - Dialog.show(explanationTitle, explanationBody, okBtn, null); - return android.support.v4.content.ContextCompat.checkSelfPermission(getActivity(), permission) == PackageManager.PERMISSION_GRANTED; - } else { - return false; - } - } + + if (android.os.Build.VERSION.SDK_INT >= 30 && "android.permission.ACCESS_BACKGROUND_LOCATION".equals(permission)) { + if (android.support.v4.content.ContextCompat.checkSelfPermission(getContext(), permission) == PackageManager.PERMISSION_GRANTED) { + return true; + } + if (getActivity() == null) { + return false; + } + + String prompt = Display.getInstance().getProperty(permission, description); + String title = Display.getInstance().getProperty("android.permission.ACCESS_BACKGROUND_LOCATION.title", "Requires permission"); + String settingsBtn = Display.getInstance().getProperty("android.permission.ACCESS_BACKGROUND_LOCATION.settings", "Settings"); + String cancelBtn = Display.getInstance().getProperty("android.permission.ACCESS_BACKGROUND_LOCATION.cancel", "Cancel"); + + if(Dialog.show(title, prompt, settingsBtn, cancelBtn)){ + Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + Uri uri = Uri.fromParts("package", getContext().getPackageName(), null); + intent.setData(uri); + getActivity().startActivity(intent); + + String explanationTitle = Display.getInstance().getProperty("android.permission.ACCESS_BACKGROUND_LOCATION.explanation_title", "Permission Required"); + String explanationBody = Display.getInstance().getProperty("android.permission.ACCESS_BACKGROUND_LOCATION.explanation_body", "Please enable 'Allow all the time' in the settings, then press OK."); + String okBtn = Display.getInstance().getProperty("android.permission.ACCESS_BACKGROUND_LOCATION.ok", "OK"); + + Dialog.show(explanationTitle, explanationBody, okBtn, null); + return android.support.v4.content.ContextCompat.checkSelfPermission(getActivity(), permission) == PackageManager.PERMISSION_GRANTED; + } else { + return false; + } + } String prompt = Display.getInstance().getProperty(permission, description); diff --git a/Ports/CLDC11/src/java/lang/Class.java b/Ports/CLDC11/src/java/lang/Class.java index 8e7c93474c..d79fe6660e 100644 --- a/Ports/CLDC11/src/java/lang/Class.java +++ b/Ports/CLDC11/src/java/lang/Class.java @@ -67,9 +67,9 @@ public java.lang.String getName(){ * In the absolute format, the programmer provides a fully qualified name that includes both the full path and the name of the resource inside the JAR file. In the path names, the character "/" is used as the separator. * In the relative format, the programmer provides only the name of the actual resource. Relative names are converted to absolute names by the system by prepending the resource name with the fully qualified package name of class upon which the getResourceAsStream method was called. */ - /*public java.io.InputStream getResourceAsStream(java.lang.String name){ + public java.io.InputStream getResourceAsStream(java.lang.String name){ return null; //TODO codavaj!! - }*/ + } /** * Determines if this Class object represents an array class. diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index c3d94d882b..1ce8740ba6 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -1,85 +1,192 @@ + - + + + - + - + + + + + - + + + - + + + - + + + - + + + + + + + + + + + - + + + - + + + - + + + + - + + + + - + + + + - + + + - + + + + - + + + + - + + + + - + + + + + - + + + + + - + + + + + - + + + + + + - - + + + - - + diff --git a/maven/core-unittests/src/test/java/com/codename1/charts/transitions/SeriesTransitionTest.java b/maven/core-unittests/src/test/java/com/codename1/charts/transitions/SeriesTransitionTest.java index 13dc7e9012..59b4477b60 100644 --- a/maven/core-unittests/src/test/java/com/codename1/charts/transitions/SeriesTransitionTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/charts/transitions/SeriesTransitionTest.java @@ -117,11 +117,10 @@ private static class RecordingForm extends Form { private final List deregisteredAnimations = new ArrayList<>(); @Override - public void registerAnimated(Animation cmp) { + public void onRegisterAnimated(Animation cmp) { if (registeredAnimations != null) { registeredAnimations.add(cmp); } - super.registerAnimated(cmp); } @Override diff --git a/maven/core-unittests/src/test/java/com/codename1/components/ButtonListTest.java b/maven/core-unittests/src/test/java/com/codename1/components/ButtonListTest.java index 15ea5093a0..21bd5b851a 100644 --- a/maven/core-unittests/src/test/java/com/codename1/components/ButtonListTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/components/ButtonListTest.java @@ -161,12 +161,7 @@ private static class TestButtonList extends ButtonList { private int refreshCount = 0; public TestButtonList(DefaultListModel model) { - super(model); - } - - @Override - public boolean isAllowMultipleSelection() { - return false; + super(model, false); } @Override diff --git a/maven/core-unittests/src/test/java/com/codename1/components/CheckBoxListTest.java b/maven/core-unittests/src/test/java/com/codename1/components/CheckBoxListTest.java index d7a447424d..32af68cf78 100644 --- a/maven/core-unittests/src/test/java/com/codename1/components/CheckBoxListTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/components/CheckBoxListTest.java @@ -17,12 +17,6 @@ void testConstructorInitializesWithModel() { assertEquals(3, list.getComponentCount()); } - @FormTest - void testIsAllowMultipleSelectionReturnsTrue() { - DefaultListModel model = new DefaultListModel<>("One"); - CheckBoxList list = new CheckBoxList(model); - assertTrue(list.isAllowMultipleSelection()); - } @FormTest void testCreateButtonCreatesCheckBox() { diff --git a/maven/core-unittests/src/test/java/com/codename1/components/RadioButtonListTest.java b/maven/core-unittests/src/test/java/com/codename1/components/RadioButtonListTest.java index b1060f30e9..f65c1ff383 100644 --- a/maven/core-unittests/src/test/java/com/codename1/components/RadioButtonListTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/components/RadioButtonListTest.java @@ -17,13 +17,6 @@ void testConstructorInitializesWithModel() { assertEquals(3, list.getComponentCount()); } - @FormTest - void testIsAllowMultipleSelectionReturnsFalse() { - DefaultListModel model = new DefaultListModel<>("One"); - RadioButtonList list = new RadioButtonList(model); - assertFalse(list.isAllowMultipleSelection()); - } - @FormTest void testCreateButtonCreatesRadioButton() { DefaultListModel model = new DefaultListModel<>("Test"); diff --git a/maven/core-unittests/src/test/java/com/codename1/components/SwitchListTest.java b/maven/core-unittests/src/test/java/com/codename1/components/SwitchListTest.java index 3ea9f1d584..ebbaefd7e3 100644 --- a/maven/core-unittests/src/test/java/com/codename1/components/SwitchListTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/components/SwitchListTest.java @@ -20,11 +20,6 @@ void configureDisplay() { implementation.setBuiltinSoundsEnabled(false); } - @Test - void testAllowMultipleSelection() { - SwitchList list = new SwitchList(new DefaultListModel<>("One", "Two")); - assertTrue(list.isAllowMultipleSelection()); - } @FormTest void testCreateButtonContainsSwitchAndLabel() { diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/DisplayTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/DisplayTest.java index abb38fab07..d6f4d766a5 100644 --- a/maven/core-unittests/src/test/java/com/codename1/ui/DisplayTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/ui/DisplayTest.java @@ -33,8 +33,8 @@ public void run() { @AfterEach void resetStatics() { - Container.blockOverdraw = false; - Component.revalidateOnStyleChange = true; + Container.setBlockOverdraw(false); + Component.setRevalidateOnStyleChange(true); } @Test @@ -62,16 +62,16 @@ void testSetPropertyHandlesSpecialKeys() { assertEquals("launch", display.getProperty("AppArg", "")); display.setProperty("blockOverdraw", "ignored"); - assertTrue(Container.blockOverdraw); + assertTrue(Container.isBlockOverdraw()); display.setProperty("blockCopyPaste", "true"); assertTrue(implementation.isBlockCopyAndPaste()); display.setProperty("Component.revalidateOnStyleChange", "false"); - assertFalse(Component.revalidateOnStyleChange); + assertFalse(Component.isRevalidateOnStyleChange()); display.setProperty("Component.revalidateOnStyleChange", "TRUE"); - assertTrue(Component.revalidateOnStyleChange); + assertTrue(Component.isRevalidateOnStyleChange()); } @Test diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/TextComponentPasswordTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/TextComponentPasswordTest.java index 1b1799ebbe..7d7ab2fde6 100644 --- a/maven/core-unittests/src/test/java/com/codename1/ui/TextComponentPasswordTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/ui/TextComponentPasswordTest.java @@ -18,8 +18,8 @@ class TextComponentPasswordTest extends UITestBase { private void triggerAction(Button action) { @SuppressWarnings("unchecked") - Vector listeners = action.getActionListeners(); - for (ActionListener listener : listeners) { + Vector> listeners = action.getActionListeners(); + for (ActionListener listener : listeners) { listener.actionPerformed(new ActionEvent(action)); } } diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/plaf/CSSBorderTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/plaf/CSSBorderTest.java index 97bcfce3a6..834a7f907a 100644 --- a/maven/core-unittests/src/test/java/com/codename1/ui/plaf/CSSBorderTest.java +++ b/maven/core-unittests/src/test/java/com/codename1/ui/plaf/CSSBorderTest.java @@ -67,85 +67,7 @@ public void testBorderImage() { Assertions.assertTrue(border.toCSSString().contains("border-image")); } - - @FormTest - public void testLinearGradient() throws Exception { - // Use reflection to test LinearGradient since parsing logic seems unimplemented or internal - CSSBorder border = new CSSBorder((Resources)null); - - // Reflection to create LinearGradient - Class linearGradientClass = Class.forName("com.codename1.ui.plaf.CSSBorder$LinearGradient"); - java.lang.reflect.Constructor lgCtor = linearGradientClass.getDeclaredConstructor(); - lgCtor.setAccessible(true); - Object linearGradient = lgCtor.newInstance(); - - // Set angle - java.lang.reflect.Field angleField = linearGradientClass.getDeclaredField("angle"); - angleField.setAccessible(true); - angleField.setFloat(linearGradient, 90f); - - // Create ColorStops - Class colorStopClass = Class.forName("com.codename1.ui.plaf.CSSBorder$ColorStop"); - java.lang.reflect.Constructor csCtor = colorStopClass.getDeclaredConstructor(); - csCtor.setAccessible(true); - - Object stop1 = csCtor.newInstance(); - - // Create Colors - Class colorClass = Class.forName("com.codename1.ui.plaf.CSSBorder$Color"); - java.lang.reflect.Constructor colorCtor = colorClass.getDeclaredConstructor(String.class); - colorCtor.setAccessible(true); - Object red = colorCtor.newInstance("#ff0000"); - Object blue = colorCtor.newInstance("#0000ff"); - - java.lang.reflect.Field colorField = colorStopClass.getDeclaredField("color"); - colorField.setAccessible(true); - colorField.set(stop1, red); - - Object stop2 = csCtor.newInstance(); - colorField.set(stop2, blue); - java.lang.reflect.Field positionField = colorStopClass.getDeclaredField("position"); - positionField.setAccessible(true); - positionField.setInt(stop2, 100); - - Object stops = java.lang.reflect.Array.newInstance(colorStopClass, 2); - java.lang.reflect.Array.set(stops, 0, stop1); - java.lang.reflect.Array.set(stops, 1, stop2); - - java.lang.reflect.Field colorsField = linearGradientClass.getDeclaredField("colors"); - colorsField.setAccessible(true); - colorsField.set(linearGradient, stops); - - // Create BackgroundImage and attach LinearGradient - Class bgImageClass = Class.forName("com.codename1.ui.plaf.CSSBorder$BackgroundImage"); - java.lang.reflect.Constructor bgCtor = bgImageClass.getDeclaredConstructor(); - bgCtor.setAccessible(true); - Object bgImage = bgCtor.newInstance(); - - java.lang.reflect.Field lgField = bgImageClass.getDeclaredField("linearGradient"); - lgField.setAccessible(true); - lgField.set(bgImage, linearGradient); - - // Attach BackgroundImage to CSSBorder - java.lang.reflect.Field bgImagesField = CSSBorder.class.getDeclaredField("backgroundImages"); - bgImagesField.setAccessible(true); - Object bgImagesArray = java.lang.reflect.Array.newInstance(bgImageClass, 1); - java.lang.reflect.Array.set(bgImagesArray, 0, bgImage); - bgImagesField.set(border, bgImagesArray); - - // Verify toCSSString - Assertions.assertTrue(border.toCSSString().contains("linear-gradient")); - - // Verify painting - Form f = new Form(); - Component c = new Component() {}; - c.setSize(new com.codename1.ui.geom.Dimension(100, 100)); - c.getStyle().setBorder(border); - - Image buffer = Image.createImage(100, 100); - border.paintBorderBackground(buffer.getGraphics(), c); - } - + @FormTest public void testBoxShadow() { CSSBorder border = new CSSBorder(); diff --git a/maven/core-unittests/src/test/java/com/codename1/ui/spinner/TimeSpinner3DTest.java b/maven/core-unittests/src/test/java/com/codename1/ui/spinner/TimeSpinner3DTest.java new file mode 100644 index 0000000000..8a05af9d4e --- /dev/null +++ b/maven/core-unittests/src/test/java/com/codename1/ui/spinner/TimeSpinner3DTest.java @@ -0,0 +1,51 @@ +package com.codename1.ui.spinner; + +import com.codename1.ui.Component; +import com.codename1.ui.Display; +import com.codename1.ui.Form; +import com.codename1.ui.Label; +import com.codename1.ui.layouts.LayeredLayout; +import com.codename1.junit.UITestBase; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class TimeSpinner3DTest extends UITestBase { + + @Test + public void testDurationMode() { + TimeSpinner3D ts = new TimeSpinner3D(); + ts.setDurationMode(true); + + Assertions.assertTrue(ts.isDurationMode(), "durationMode should be true"); + Assertions.assertFalse(ts.isShowMeridiem(), "showMeridiem should be false in duration mode"); + + // Check components + // In duration mode we expect: Hour spinner, Hour label, Minute spinner, Minute label + // That is 4 components. + + Assertions.assertEquals(4, ts.getComponentCount(), "Should have 4 components in duration mode"); + + boolean foundHoursLabel = false; + boolean foundMinutesLabel = false; + + for (int i = 0; i < ts.getComponentCount(); i++) { + Component c = ts.getComponentAt(i); + if (c instanceof Label) { + Label l = (Label) c; + if ("hours".equals(l.getText()) || "hours".equals(l.getUIID())) { + if ("TimeSpinnerHoursLabel".equals(l.getUIID())) { + foundHoursLabel = true; + } + } + if ("minutes".equals(l.getText()) || "minutes".equals(l.getUIID())) { + if ("TimeSpinnerMinutesLabel".equals(l.getUIID())) { + foundMinutesLabel = true; + } + } + } + } + + Assertions.assertTrue(foundHoursLabel, "Should find hours label"); + Assertions.assertTrue(foundMinutesLabel, "Should find minutes label"); + } +}