From 7e5e0396842cc87abe0081bf192f91055a9f9b8d Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Tue, 30 Dec 2025 05:27:53 +0200 Subject: [PATCH 01/58] Initial work on improving spotless fixes --- .github/scripts/generate-quality-report.py | 13 ++++- .../capture/VideoCaptureConstraints.java | 2 +- CodenameOne/src/com/codename1/io/Util.java | 14 ++--- .../com/codename1/io/WebServiceProxyCall.java | 32 ++++++------ .../src/com/codename1/io/gzip/GZIPHeader.java | 2 +- .../src/com/codename1/payment/Purchase.java | 17 +++--- .../processing/HashtableContent.java | 8 +-- .../codename1/processing/PrettyPrinter.java | 52 +++---------------- .../com/codename1/share/FacebookShare.java | 4 +- .../src/com/codename1/ui/Component.java | 5 +- CodenameOne/src/com/codename1/ui/Display.java | 22 ++++---- .../src/com/codename1/ui/EncodedImage.java | 6 +-- .../src/com/codename1/ui/SideMenuBar.java | 2 +- .../src/com/codename1/ui/TextSelection.java | 25 ++------- .../ui/animations/CommonTransitions.java | 2 - .../codename1/ui/plaf/DefaultLookAndFeel.java | 32 ++---------- .../src/com/codename1/ui/spinner/Picker.java | 2 +- .../src/com/codename1/ui/table/Table.java | 28 +++------- .../src/com/codename1/ui/tree/Tree.java | 2 +- .../src/com/codename1/ui/util/Resources.java | 13 +---- .../src/com/codename1/ui/util/UIBuilder.java | 7 ++- .../com/codename1/util/regex/RECompiler.java | 48 ++++++++--------- maven/core-unittests/spotbugs-exclude.xml | 23 ++++++-- 23 files changed, 143 insertions(+), 218 deletions(-) diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py index 80ca0ad17e..f5c1b28598 100755 --- a/.github/scripts/generate-quality-report.py +++ b/.github/scripts/generate-quality-report.py @@ -776,7 +776,18 @@ 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" } violations = [ f for f in spotbugs.findings 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/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/payment/Purchase.java b/CodenameOne/src/com/codename1/payment/Purchase.java index 4ada6161d9..114088f219 100644 --- a/CodenameOne/src/com/codename1/payment/Purchase.java +++ b/CodenameOne/src/com/codename1/payment/Purchase.java @@ -53,6 +53,7 @@ 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; @@ -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(); } }); - } /** 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/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/ui/Component.java b/CodenameOne/src/com/codename1/ui/Component.java index dfd4d310c5..3e2767aadf 100644 --- a/CodenameOne/src/com/codename1/ui/Component.java +++ b/CodenameOne/src/com/codename1/ui/Component.java @@ -6531,7 +6531,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()) { diff --git a/CodenameOne/src/com/codename1/ui/Display.java b/CodenameOne/src/com/codename1/ui/Display.java index 0cacf01423..db43f8179e 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; /** @@ -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) { @@ -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; 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/SideMenuBar.java b/CodenameOne/src/com/codename1/ui/SideMenuBar.java index 2a02da2c45..4005f35c11 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(); 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/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/plaf/DefaultLookAndFeel.java b/CodenameOne/src/com/codename1/ui/plaf/DefaultLookAndFeel.java index 53a8f531fd..d2a629dacd 100644 --- a/CodenameOne/src/com/codename1/ui/plaf/DefaultLookAndFeel.java +++ b/CodenameOne/src/com/codename1/ui/plaf/DefaultLookAndFeel.java @@ -825,13 +825,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 +844,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 +855,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 +878,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; } @@ -2567,22 +2545,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 +2573,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); } } } diff --git a/CodenameOne/src/com/codename1/ui/spinner/Picker.java b/CodenameOne/src/com/codename1/ui/spinner/Picker.java index 53cb691c62..0f60b06d42 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/Picker.java +++ b/CodenameOne/src/com/codename1/ui/spinner/Picker.java @@ -1208,7 +1208,7 @@ public void setSelectedString(String str) { public int getSelectedStringIndex() { int offset = 0; for (String s : (String[]) metaData) { - if (s == value) { + if (s == value || (s != null && s.equals(value))) { return offset; } offset++; diff --git a/CodenameOne/src/com/codename1/ui/table/Table.java b/CodenameOne/src/com/codename1/ui/table/Table.java index c25f0d9748..8c5010d94e 100644 --- a/CodenameOne/src/com/codename1/ui/table/Table.java +++ b/CodenameOne/src/com/codename1/ui/table/Table.java @@ -426,15 +426,15 @@ 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) { + protected Comparator createColumnSortComparator(int column) { final CaseInsensitiveOrder ccmp = new CaseInsensitiveOrder(); - return new Comparator() { + return new Comparator() { public int compare(Object o1, Object o2) { if (o1 == null) { if (o2 == null) { @@ -452,25 +452,11 @@ public int compare(Object o1, Object 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; - } + return Double.compare(d1, d2); } catch (IllegalArgumentException err) { long dd = Util.toDateValue(o1).getTime() - Util.toDateValue(o2).getTime(); return (int) dd; } - return 0; } }; } @@ -483,7 +469,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 +491,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 { diff --git a/CodenameOne/src/com/codename1/ui/tree/Tree.java b/CodenameOne/src/com/codename1/ui/tree/Tree.java index aed8edd102..7215f46549 100644 --- a/CodenameOne/src/com/codename1/ui/tree/Tree.java +++ b/CodenameOne/src/com/codename1/ui/tree/Tree.java @@ -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/Resources.java b/CodenameOne/src/com/codename1/ui/util/Resources.java index ac872d0f7d..110baff320 100644 --- a/CodenameOne/src/com/codename1/ui/util/Resources.java +++ b/CodenameOne/src/com/codename1/ui/util/Resources.java @@ -1198,19 +1198,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(); 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/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/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index c3d94d882b..44efc82049 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -1,5 +1,5 @@ - + + + - + + + @@ -82,4 +86,15 @@ + + + + + + + + + + + From ce41dd352105d54bcd80ef7e2d86a6081186d2da Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Tue, 30 Dec 2025 05:46:15 +0200 Subject: [PATCH 02/58] Fixed compilation issues and hardened build --- .github/scripts/generate-quality-report.py | 26 +++++++++- .../src/com/codename1/testing/TestUtils.java | 20 -------- .../com/codename1/ui/BrowserComponent.java | 51 ++++--------------- .../com/codename1/ui/plaf/StyleParser.java | 17 ------- 4 files changed, 35 insertions(+), 79 deletions(-) diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py index f5c1b28598..8242bff876 100755 --- a/.github/scripts/generate-quality-report.py +++ b/.github/scripts/generate-quality-report.py @@ -787,7 +787,31 @@ def main() -> None: "EQ_GETCLASS_AND_CLASS_CONSTANT", "EQ_UNUSUAL", "ES_COMPARING_STRINGS_WITH_EQ", - "FI_EMPTY" + "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_CONVERT_CASE", + "DM_EXIT", + "EI_EXPOSE_REP", + "EI_EXPOSE_REP2", + "EI_EXPOSE_STATIC_REP2", + "EQ_COMPARETO_USE_OBJECT_EQUALS", + "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR", + "MS_EXPOSE_REP", + "NM_CONFUSING", + "NO_NOTIFY_NOT_NOTIFYALL", + "NP_BOOLEAN_RETURN_NULL", + "PZLA_PREFER_ZERO_LENGTH_ARRAYS", + "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" } violations = [ f for f in spotbugs.findings 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/BrowserComponent.java b/CodenameOne/src/com/codename1/ui/BrowserComponent.java index 6d39ec7e27..9ec1f91c1f 100644 --- a/CodenameOne/src/com/codename1/ui/BrowserComponent.java +++ b/CodenameOne/src/com/codename1/ui/BrowserComponent.java @@ -290,13 +290,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 +541,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(); @@ -1698,6 +1684,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 +1699,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 +1749,6 @@ public String getValue() { return value; } - /** - * Returns the type of the value - * - * @return - */ - private String getType() { - return type; - } - /** * Returns the type of the value. * 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); From 53919536d6f3d6f5160029e640483f2840796cf9 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Tue, 30 Dec 2025 06:40:07 +0200 Subject: [PATCH 03/58] Fixed path --- CodenameOne/nbproject/project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodenameOne/nbproject/project.properties b/CodenameOne/nbproject/project.properties index 9b85c92082..5c7da1fbe3 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=\ From 91c799ce5bd7fdd1d7fca819d5db312b4e859db2 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Tue, 30 Dec 2025 12:45:19 +0200 Subject: [PATCH 04/58] Improved CI build validation --- .../impl/CodenameOneImplementation.java | 16 +++--------- .../com/codename1/io/FileSystemStorage.java | 1 - .../codename1/location/LocationManager.java | 2 +- .../src/com/codename1/payment/Purchase.java | 8 +++--- .../src/com/codename1/ui/Component.java | 18 +++++++++---- .../src/com/codename1/ui/Container.java | 26 ++++++++++++------- CodenameOne/src/com/codename1/ui/Display.java | 10 +++---- CodenameOne/src/com/codename1/ui/Form.java | 24 ++++++++++++++--- CodenameOne/src/com/codename1/ui/Tabs.java | 6 ++--- maven/core-unittests/spotbugs-exclude.xml | 11 ++++++++ 10 files changed, 77 insertions(+), 45 deletions(-) diff --git a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java index 5be7e0fea4..dd44fc77a3 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; @@ -927,16 +927,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. @@ -8786,7 +8776,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/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/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/payment/Purchase.java b/CodenameOne/src/com/codename1/payment/Purchase.java index 114088f219..6a05448b88 100644 --- a/CodenameOne/src/com/codename1/payment/Purchase.java +++ b/CodenameOne/src/com/codename1/payment/Purchase.java @@ -56,9 +56,9 @@ public abstract class Purchase { 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. @@ -281,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 diff --git a/CodenameOne/src/com/codename1/ui/Component.java b/CodenameOne/src/com/codename1/ui/Component.java index 3e2767aadf..4470fbd719 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; @@ -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 * @@ -3197,8 +3205,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()); } } @@ -4497,7 +4505,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) { @@ -7063,7 +7071,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(); } } diff --git a/CodenameOne/src/com/codename1/ui/Container.java b/CodenameOne/src/com/codename1/ui/Container.java index 8111f45dbd..5941b37ca3 100644 --- a/CodenameOne/src/com/codename1/ui/Container.java +++ b/CodenameOne/src/com/codename1/ui/Container.java @@ -78,13 +78,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; /** @@ -152,6 +152,10 @@ public Container(Layout layout, String uiid) { setFocusable(false); } + static void blockOverdraw() { + blockOverdraw = true; + } + /** * Constructs a new Container with a new layout manager. * @@ -1002,6 +1006,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 +1022,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); } /** @@ -3700,7 +3708,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 +3763,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 +3861,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 +3921,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]; @@ -4362,7 +4370,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/Display.java b/CodenameOne/src/com/codename1/ui/Display.java index db43f8179e..df91b22126 100644 --- a/CodenameOne/src/com/codename1/ui/Display.java +++ b/CodenameOne/src/com/codename1/ui/Display.java @@ -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; @@ -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.blockOverdraw(); 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); diff --git a/CodenameOne/src/com/codename1/ui/Form.java b/CodenameOne/src/com/codename1/ui/Form.java index 0de0968d67..fe752bb72b 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; /** @@ -256,6 +256,10 @@ public Form(Layout contentPaneLayout) { initGlobalToolbar(); } + static Motion getRippleMotion() { + return rippleMotion; + } + /** * Sets the title after invoking the constructor * @@ -2031,6 +2035,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 +2051,7 @@ void repaintAnimations() { if (rippleComponent != null) { rippleComponent.repaint(); if (rippleMotion == null) { - rippleComponent = null; + resetRippleComponent(); } } if (animatableComponents != null) { @@ -3089,11 +3101,15 @@ 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; + setRippleComponent(cmp); rippleX = x; rippleY = y; } diff --git a/CodenameOne/src/com/codename1/ui/Tabs.java b/CodenameOne/src/com/codename1/ui/Tabs.java index 685080739f..5b63579f02 100644 --- a/CodenameOne/src/com/codename1/ui/Tabs.java +++ b/CodenameOne/src/com/codename1/ui/Tabs.java @@ -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/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 44efc82049..52c12b1b09 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -65,6 +65,17 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 430d720b10451145c4f056802eecd77db64d199f Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Tue, 30 Dec 2025 20:02:39 +0200 Subject: [PATCH 07/58] Removed additional settings --- .../com/codename1/charts/views/LineChart.java | 3 +- .../codename1/charts/views/ScatterChart.java | 21 ++++++------ .../com/codename1/components/Progress.java | 20 ++++++----- .../codename1/components/SliderBridge.java | 2 +- .../com/codename1/components/SplitPane.java | 21 +++++++----- .../codename1/facebook/FaceBookAccess.java | 33 ++++++++++++------- maven/core-unittests/spotbugs-exclude.xml | 28 ++++++++++++++-- 7 files changed, 84 insertions(+), 44 deletions(-) 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/components/Progress.java b/CodenameOne/src/com/codename1/components/Progress.java index 9524171772..99bcabc4db 100644 --- a/CodenameOne/src/com/codename1/components/Progress.java +++ b/CodenameOne/src/com/codename1/components/Progress.java @@ -137,15 +137,17 @@ public void setDisposeOnCompletion(boolean disposeOnCompletion) { * {@inheritDoc} */ public void actionPerformed(ActionEvent evt) { - NetworkEvent ev = (NetworkEvent) evt; - if (ev.getConnectionRequest() == request) { - if (disposeOnCompletion && ev.getProgressType() == NetworkEvent.PROGRESS_TYPE_COMPLETED) { - dispose(); - return; - } - if (autoShow && !showing) { - showing = true; - showModeless(); + if(evt instanceof NetworkEvent) { + NetworkEvent ev = (NetworkEvent) evt; + if (ev.getConnectionRequest() == request) { + if (disposeOnCompletion && ev.getProgressType() == NetworkEvent.PROGRESS_TYPE_COMPLETED) { + dispose(); + return; + } + if (autoShow && !showing) { + showing = true; + showModeless(); + } } } } 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/SplitPane.java b/CodenameOne/src/com/codename1/components/SplitPane.java index 84105bbb9b..ec6d393df3 100644 --- a/CodenameOne/src/com/codename1/components/SplitPane.java +++ b/CodenameOne/src/com/codename1/components/SplitPane.java @@ -967,10 +967,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 +992,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) { diff --git a/CodenameOne/src/com/codename1/facebook/FaceBookAccess.java b/CodenameOne/src/com/codename1/facebook/FaceBookAccess.java index 195ff905e9..6224cd2efe 100644 --- a/CodenameOne/src/com/codename1/facebook/FaceBookAccess.java +++ b/CodenameOne/src/com/codename1/facebook/FaceBookAccess.java @@ -513,13 +513,19 @@ public void getPost(String postId, final Post post, final ActionListener callbac 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); + final Object val = ((NetworkEvent) 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); + } + } } } }); @@ -548,10 +554,15 @@ public void actionPerformed(ActionEvent evt) { getFaceBookObject(postId, new ActionListener() { public void actionPerformed(ActionEvent evt) { - Vector v = (Vector) ((NetworkEvent) evt).getMetaData(); - Hashtable t = (Hashtable) v.elementAt(0); - post.copy(t); - + final Object val = ((NetworkEvent) 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); + } + } } }, needAuth, false); if (err.size() > 0) { diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 792303e3e2..2168ad7e5a 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -96,6 +96,23 @@ + + + + + + + + + + + + + + + + + + + - - + From ee188244eb36338b8b6db2a32906b6f1a1fb1538 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 04:29:22 +0200 Subject: [PATCH 08/58] Fixing exclusion logic --- maven/core-unittests/spotbugs-exclude.xml | 88 +++-------------------- 1 file changed, 10 insertions(+), 78 deletions(-) diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 2168ad7e5a..2f7f878818 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -1,65 +1,4 @@ - - @@ -69,8 +8,6 @@ - - @@ -103,7 +40,6 @@ - - + + + @@ -150,7 +76,13 @@ - + + + + + + + From 79e5e4207f5de9a89e444b77d2524dbfebfd10d5 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 04:56:28 +0200 Subject: [PATCH 09/58] Refined rules --- maven/core-unittests/spotbugs-exclude.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 2f7f878818..29a6445e14 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -76,13 +76,15 @@ - + + + From 2ddd88606110fe27c9bfaa16c931c83c6dd8d904 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 05:18:14 +0200 Subject: [PATCH 10/58] Additional improvements --- .../javascript/JavascriptContext.java | 6 ++-- .../codename1/maps/CacheProviderProxy.java | 16 ++-------- .../src/com/codename1/payment/Purchase.java | 10 ++++-- .../com/codename1/properties/UiBinding.java | 4 ++- maven/core-unittests/spotbugs-exclude.xml | 32 ++++++++++++++++++- 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/CodenameOne/src/com/codename1/javascript/JavascriptContext.java b/CodenameOne/src/com/codename1/javascript/JavascriptContext.java index eca93b55a5..4256cbe2b4 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 @@ -1000,9 +1000,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/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/payment/Purchase.java b/CodenameOne/src/com/codename1/payment/Purchase.java index 6a05448b88..8fc6139628 100644 --- a/CodenameOne/src/com/codename1/payment/Purchase.java +++ b/CodenameOne/src/com/codename1/payment/Purchase.java @@ -574,7 +574,10 @@ public void run() { while (!complete[0]) { synchronized (complete) { try { - complete.wait(); + // need to recheck condition within the synchronized block + if(!complete[0]) { + complete.wait(); + } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); return; @@ -778,7 +781,10 @@ public void run() { while (!complete[0]) { synchronized (complete) { try { - complete.wait(); + // need to recheck condition within the synchronized block + if(!complete[0]) { + complete.wait(); + } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); return; 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/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 29a6445e14..da76dd060d 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -12,6 +12,16 @@ + + + + + + + + + + + + + + + + + - + + + + + + From b3bae009508709c167f111881f74b5e238897dfd Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 05:40:09 +0200 Subject: [PATCH 11/58] Fixing exclusions to include inner classes --- maven/core-unittests/spotbugs-exclude.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index da76dd060d..82f4b2e8e4 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -113,13 +113,15 @@ + + - + - + From 49a02fea6604306c0bb5a3196edf327591e0bc6b Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 05:48:59 +0200 Subject: [PATCH 12/58] Removed cloud storage package and further improvements --- .../src/com/codename1/capture/Capture.java | 14 +- .../codename1/charts/views/BubbleChart.java | 26 +- .../src/com/codename1/cloud/BindTarget.java | 43 - .../com/codename1/cloud/CloudException.java | 52 -- .../codename1/cloud/CloudImageProperty.java | 171 ---- .../com/codename1/cloud/CloudListModel.java | 460 ---------- .../src/com/codename1/cloud/CloudObject.java | 808 ------------------ .../src/com/codename1/cloud/CloudPersona.java | 94 -- .../com/codename1/cloud/CloudResponse.java | 46 - .../src/com/codename1/cloud/CloudStorage.java | 578 ------------- .../com/codename1/cloud/CustomProperty.java | 45 - .../src/com/codename1/cloud/package.html | 12 - .../codename1/ui/spinner/SpinnerRenderer.java | 2 +- maven/core-unittests/spotbugs-exclude.xml | 7 +- 14 files changed, 26 insertions(+), 2332 deletions(-) delete mode 100644 CodenameOne/src/com/codename1/cloud/BindTarget.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudException.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudImageProperty.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudListModel.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudObject.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudPersona.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudResponse.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudStorage.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CustomProperty.java delete mode 100644 CodenameOne/src/com/codename1/cloud/package.html diff --git a/CodenameOne/src/com/codename1/capture/Capture.java b/CodenameOne/src/com/codename1/capture/Capture.java index cd8815805c..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(); } } 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/cloud/BindTarget.java b/CodenameOne/src/com/codename1/cloud/BindTarget.java deleted file mode 100644 index 4e31a452db..0000000000 --- a/CodenameOne/src/com/codename1/cloud/BindTarget.java +++ /dev/null @@ -1,43 +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.ui.Component; - -/** - * Allows binding arbitrary components to data storage - * - * @author Shai Almog - * @deprecated this mapped to an older iteration of properties that is no longer used - */ -public interface BindTarget { - /** - * Fired when a property of the component changes to a new value - * - * @param source the source component - * @param propertyName the name of the property - * @param oldValue the old value of the property - * @param newValue the new value for the property - */ - void propertyChanged(Component source, String propertyName, Object oldValue, Object newValue); // PMD Fix: UnnecessaryModifier removed -} 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/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/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 82f4b2e8e4..a4259e024a 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -21,6 +21,9 @@ + + + - + From 26edf9ad05a3ef502542545ff1b7ee33eee9c90b Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 06:30:22 +0200 Subject: [PATCH 13/58] BindTarget was still used. Restored it and deprecated code --- .../src/com/codename1/cloud/BindTarget.java | 43 +++++++++++++++ .../src/com/codename1/ui/CheckBox.java | 2 + CodenameOne/src/com/codename1/ui/Label.java | 2 + .../src/com/codename1/ui/RadioButton.java | 2 + .../src/com/codename1/ui/TextArea.java | 2 + .../ui/list/GenericListCellRenderer.java | 52 ++----------------- .../codename1/ui/util/EventDispatcher.java | 2 + 7 files changed, 57 insertions(+), 48 deletions(-) create mode 100644 CodenameOne/src/com/codename1/cloud/BindTarget.java diff --git a/CodenameOne/src/com/codename1/cloud/BindTarget.java b/CodenameOne/src/com/codename1/cloud/BindTarget.java new file mode 100644 index 0000000000..4e31a452db --- /dev/null +++ b/CodenameOne/src/com/codename1/cloud/BindTarget.java @@ -0,0 +1,43 @@ +/* + * 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.ui.Component; + +/** + * Allows binding arbitrary components to data storage + * + * @author Shai Almog + * @deprecated this mapped to an older iteration of properties that is no longer used + */ +public interface BindTarget { + /** + * Fired when a property of the component changes to a new value + * + * @param source the source component + * @param propertyName the name of the property + * @param oldValue the old value of the property + * @param newValue the new value for the property + */ + void propertyChanged(Component source, String propertyName, Object oldValue, Object newValue); // PMD Fix: UnnecessaryModifier removed +} diff --git a/CodenameOne/src/com/codename1/ui/CheckBox.java b/CodenameOne/src/com/codename1/ui/CheckBox.java index 46c4a9932a..b462ad6673 100644 --- a/CodenameOne/src/com/codename1/ui/CheckBox.java +++ b/CodenameOne/src/com/codename1/ui/CheckBox.java @@ -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/Label.java b/CodenameOne/src/com/codename1/ui/Label.java index e535d9e540..ef81248596 100644 --- a/CodenameOne/src/com/codename1/ui/Label.java +++ b/CodenameOne/src/com/codename1/ui/Label.java @@ -1221,6 +1221,7 @@ public Class[] getBindablePropertyTypes() { /** * {@inheritDoc} + * @deprecated uses the deprecated BindTarget interface */ public void bindProperty(String prop, BindTarget target) { if (prop.equals("text")) { @@ -1235,6 +1236,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/RadioButton.java b/CodenameOne/src/com/codename1/ui/RadioButton.java index f5f11982ec..46f3188cce 100644 --- a/CodenameOne/src/com/codename1/ui/RadioButton.java +++ b/CodenameOne/src/com/codename1/ui/RadioButton.java @@ -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/TextArea.java b/CodenameOne/src/com/codename1/ui/TextArea.java index cb8a0704f0..e8f9cd272e 100644 --- a/CodenameOne/src/com/codename1/ui/TextArea.java +++ b/CodenameOne/src/com/codename1/ui/TextArea.java @@ -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/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/util/EventDispatcher.java b/CodenameOne/src/com/codename1/ui/util/EventDispatcher.java index 232100bb1c..efaf6d30fe 100644 --- a/CodenameOne/src/com/codename1/ui/util/EventDispatcher.java +++ b/CodenameOne/src/com/codename1/ui/util/EventDispatcher.java @@ -167,6 +167,7 @@ public void fireDataChangeEvent(int index, int type) { * @param propertyName the name of the property * @param oldValue the old value of the property * @param newValue the new value for the property + * @deprecated uses the deprecated BindTarget interface */ public void fireBindTargetChange(Component source, String propertyName, Object oldValue, Object newValue) { if (listeners == null || listeners.size() == 0) { @@ -201,6 +202,7 @@ public void fireBindTargetChange(Component source, String propertyName, Object o * @param propertyName the name of the property * @param oldValue the old value of the property * @param newValue the new value for the property + * @deprecated uses the deprecated BindTarget interface */ private void fireBindTargetChangeSync(BindTarget[] arr, Component source, String propertyName, Object oldValue, Object newValue) { int alen = arr.length; From f0fb3e595db163ee0b147d4b9a6eb03fcef3b81e Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 07:54:27 +0200 Subject: [PATCH 14/58] Trying again for TarEntry --- maven/core-unittests/spotbugs-exclude.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index a4259e024a..a3988ce5c9 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -125,6 +125,6 @@ - + From 431d0cdc3bdde02fde51d2a0756b03f7b97c5e80 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 10:51:08 +0200 Subject: [PATCH 15/58] WTF --- .../src/com/codename1/components/Accordion.java | 2 +- CodenameOne/src/com/codename1/ui/Component.java | 2 +- CodenameOne/src/com/codename1/ui/Form.java | 1 + maven/core-unittests/spotbugs-exclude.xml | 16 ++++++++++++---- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CodenameOne/src/com/codename1/components/Accordion.java b/CodenameOne/src/com/codename1/components/Accordion.java index 912846105c..16c1c03121 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); } /** diff --git a/CodenameOne/src/com/codename1/ui/Component.java b/CodenameOne/src/com/codename1/ui/Component.java index 4470fbd719..12dc72fce4 100644 --- a/CodenameOne/src/com/codename1/ui/Component.java +++ b/CodenameOne/src/com/codename1/ui/Component.java @@ -7252,7 +7252,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/Form.java b/CodenameOne/src/com/codename1/ui/Form.java index 555c9cd419..776c890def 100644 --- a/CodenameOne/src/com/codename1/ui/Form.java +++ b/CodenameOne/src/com/codename1/ui/Form.java @@ -4406,6 +4406,7 @@ public boolean isScrollableY() { /** * {@inheritDoc} */ + @Override public void setScrollableY(boolean scrollableY) { getContentPane().setScrollableY(scrollableY); } diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index a3988ce5c9..d03c11dbe3 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -25,6 +25,14 @@ + + + + + - + - + - + - + From c5730b5dd170d828259ef30c21b7d2dc2c190185 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 11:09:46 +0200 Subject: [PATCH 16/58] Trying source name --- maven/core-unittests/spotbugs-exclude.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index d03c11dbe3..e78aef88ff 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -128,7 +128,7 @@ - + From da30271452cf523a2981d7add32f7cd07030a8b3 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 11:55:19 +0200 Subject: [PATCH 17/58] Fixed python script to ignore the tags failure --- .github/scripts/generate-quality-report.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py index 8242bff876..0c64a87545 100755 --- a/.github/scripts/generate-quality-report.py +++ b/.github/scripts/generate-quality-report.py @@ -813,10 +813,19 @@ def main() -> None: "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:") From 841668f0d8c5027cd6519f020e07bd26d93093d6 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 13:53:52 +0200 Subject: [PATCH 18/58] Major fixes for calls from constructors --- .github/scripts/generate-quality-report.py | 1 - .../com/codename1/charts/ChartComponent.java | 2 +- .../com/codename1/components/Accordion.java | 2 +- .../src/com/codename1/components/Ads.java | 35 +++-- .../com/codename1/components/ButtonList.java | 5 +- .../com/codename1/components/FileTree.java | 4 +- .../components/FloatingActionButton.java | 49 ++++--- .../codename1/components/FloatingHint.java | 35 +++-- .../com/codename1/components/ImageViewer.java | 2 +- .../components/InfiniteProgress.java | 2 +- .../components/InteractionDialog.java | 2 +- .../com/codename1/components/MultiButton.java | 2 +- .../com/codename1/components/OnOffSwitch.java | 2 +- .../com/codename1/components/RSSReader.java | 2 +- .../components/ScaleImageButton.java | 4 +- .../codename1/components/ScaleImageLabel.java | 4 +- .../com/codename1/components/ShareButton.java | 2 +- .../components/SignatureComponent.java | 2 +- .../com/codename1/components/SpanButton.java | 2 +- .../com/codename1/components/SpanLabel.java | 2 +- .../codename1/components/SpanMultiButton.java | 2 +- .../com/codename1/components/SplitPane.java | 2 +- .../src/com/codename1/components/Switch.java | 2 +- .../com/codename1/facebook/ui/LikeButton.java | 2 +- .../com/codename1/ui/BrowserComponent.java | 2 +- CodenameOne/src/com/codename1/ui/Button.java | 2 +- .../src/com/codename1/ui/Calendar.java | 4 +- .../src/com/codename1/ui/CheckBox.java | 2 +- .../src/com/codename1/ui/ComboBox.java | 2 +- .../src/com/codename1/ui/Component.java | 25 +++- .../src/com/codename1/ui/ComponentGroup.java | 2 +- .../src/com/codename1/ui/Container.java | 4 +- CodenameOne/src/com/codename1/ui/Dialog.java | 8 +- CodenameOne/src/com/codename1/ui/Form.java | 4 +- CodenameOne/src/com/codename1/ui/Label.java | 17 ++- CodenameOne/src/com/codename1/ui/List.java | 4 +- .../src/com/codename1/ui/RadioButton.java | 2 +- .../src/com/codename1/ui/SearchBar.java | 2 +- CodenameOne/src/com/codename1/ui/Sheet.java | 2 +- CodenameOne/src/com/codename1/ui/Slider.java | 2 +- CodenameOne/src/com/codename1/ui/Tabs.java | 2 +- .../src/com/codename1/ui/TextArea.java | 2 +- .../src/com/codename1/ui/TextField.java | 8 +- CodenameOne/src/com/codename1/ui/Toolbar.java | 22 +-- .../com/codename1/ui/html/HTMLImageMap.java | 2 +- .../src/com/codename1/ui/html/HTMLLink.java | 2 +- .../com/codename1/ui/html/MultiComboBox.java | 10 +- .../com/codename1/ui/list/ContainerList.java | 4 +- .../ui/list/DefaultListCellRenderer.java | 2 +- .../src/com/codename1/ui/scene/Scene.java | 2 +- .../com/codename1/ui/spinner/BaseSpinner.java | 2 +- .../src/com/codename1/ui/spinner/Picker.java | 2 +- .../src/com/codename1/ui/spinner/Spinner.java | 2 +- .../src/com/codename1/ui/table/Table.java | 4 +- .../src/com/codename1/ui/tree/Tree.java | 2 +- .../impl/android/AndroidImplementation.java | 133 +++++++++--------- maven/core-unittests/spotbugs-exclude.xml | 8 ++ 57 files changed, 264 insertions(+), 198 deletions(-) diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py index 0c64a87545..f8be78fe2f 100755 --- a/.github/scripts/generate-quality-report.py +++ b/.github/scripts/generate-quality-report.py @@ -806,7 +806,6 @@ def main() -> None: "NM_CONFUSING", "NO_NOTIFY_NOT_NOTIFYALL", "NP_BOOLEAN_RETURN_NULL", - "PZLA_PREFER_ZERO_LENGTH_ARRAYS", "REFLC_REFLECTION_MAY_INCREASE_ACCESSIBILITY_OF_CLASS", "UI_INHERITANCE_UNSAFE_GETRESOURCE", "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", 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/components/Accordion.java b/CodenameOne/src/com/codename1/components/Accordion.java index 16c1c03121..92d643038d 100644 --- a/CodenameOne/src/com/codename1/components/Accordion.java +++ b/CodenameOne/src/com/codename1/components/Accordion.java @@ -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..9df016b2b6 100644 --- a/CodenameOne/src/com/codename1/components/ButtonList.java +++ b/CodenameOne/src/com/codename1/components/ButtonList.java @@ -110,7 +110,6 @@ public ButtonList(ListModel model) { ((DefaultListModel) model).setMultiSelectionMode(true); } setModel(model); - } /** @@ -130,7 +129,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 +159,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); 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..8ba0c59533 100644 --- a/CodenameOne/src/com/codename1/components/ImageViewer.java +++ b/CodenameOne/src/com/codename1/components/ImageViewer.java @@ -117,7 +117,7 @@ public class ImageViewer extends Component { */ public ImageViewer() { setFocusable(true); - setUIID("ImageViewer"); + setUIIDFinal("ImageViewer"); $(this).selectAllStyles().setBgTransparency(0x0); } 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/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/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..3c1f1b222e 100644 --- a/CodenameOne/src/com/codename1/components/ShareButton.java +++ b/CodenameOne/src/com/codename1/components/ShareButton.java @@ -69,7 +69,7 @@ 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); diff --git a/CodenameOne/src/com/codename1/components/SignatureComponent.java b/CodenameOne/src/com/codename1/components/SignatureComponent.java index 7ebc070ffe..e378988467 100644 --- a/CodenameOne/src/com/codename1/components/SignatureComponent.java +++ b/CodenameOne/src/com/codename1/components/SignatureComponent.java @@ -451,7 +451,7 @@ private static class SignaturePanel extends Component { private final Style signatureStyle; SignaturePanel() { - setUIID("SignaturePanel"); + setUIIDFinal("SignaturePanel"); signatureBoxStyle = getUIManager().getComponentStyle("SignaturePanelBox"); signatureStyle = getUIManager().getComponentStyle("SignaturePanelSignature"); stroke.setLineWidth(Math.max(1, Display.getInstance().convertToPixels(1, true) / 2)); diff --git a/CodenameOne/src/com/codename1/components/SpanButton.java b/CodenameOne/src/com/codename1/components/SpanButton.java index b2aa3f573f..2af42a64da 100644 --- a/CodenameOne/src/com/codename1/components/SpanButton.java +++ b/CodenameOne/src/com/codename1/components/SpanButton.java @@ -82,7 +82,7 @@ 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.setColumns(100); diff --git a/CodenameOne/src/com/codename1/components/SpanLabel.java b/CodenameOne/src/com/codename1/components/SpanLabel.java index cc5f37dd8d..4b389e11d8 100644 --- a/CodenameOne/src/com/codename1/components/SpanLabel.java +++ b/CodenameOne/src/com/codename1/components/SpanLabel.java @@ -80,7 +80,7 @@ public SpanLabel(String txt, String textUiid) { * Constructor accepting default text */ public SpanLabel(String txt) { - setUIID("Container"); + setUIIDFinal("Container"); setLayout(new BorderLayout()); text = new TextArea(getUIManager().localize(txt, txt)); text.setActAsLabel(true); 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 ec6d393df3..08d4323429 100644 --- a/CodenameOne/src/com/codename1/components/SplitPane.java +++ b/CodenameOne/src/com/codename1/components/SplitPane.java @@ -959,7 +959,7 @@ private class Divider extends Container { Divider() { super(new LayeredLayout()); if (dividerUIID != null) { - setUIID(dividerUIID); + setUIIDFinal(dividerUIID); } btnCollapse = $(new Button()) .setUIID(collapseButtonUIID) 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/facebook/ui/LikeButton.java b/CodenameOne/src/com/codename1/facebook/ui/LikeButton.java index 66ce5a7480..88c6950d0a 100644 --- a/CodenameOne/src/com/codename1/facebook/ui/LikeButton.java +++ b/CodenameOne/src/com/codename1/facebook/ui/LikeButton.java @@ -60,7 +60,7 @@ public LikeButton(String postId) { * Default constructor */ public LikeButton() { - setUIID("LikeButton"); + setUIIDFinal("LikeButton"); setText("Like"); addActionListener(this); } diff --git a/CodenameOne/src/com/codename1/ui/BrowserComponent.java b/CodenameOne/src/com/codename1/ui/BrowserComponent.java index 9ec1f91c1f..b09b9ec962 100644 --- a/CodenameOne/src/com/codename1/ui/BrowserComponent.java +++ b/CodenameOne/src/com/codename1/ui/BrowserComponent.java @@ -154,7 +154,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); diff --git a/CodenameOne/src/com/codename1/ui/Button.java b/CodenameOne/src/com/codename1/ui/Button.java index 4dad66f706..6ffb28c572 100644 --- a/CodenameOne/src/com/codename1/ui/Button.java +++ b/CodenameOne/src/com/codename1/ui/Button.java @@ -186,7 +186,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; 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 b462ad6673..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(); } 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/Component.java b/CodenameOne/src/com/codename1/ui/Component.java index 12dc72fce4..555074af58 100644 --- a/CodenameOne/src/com/codename1/ui/Component.java +++ b/CodenameOne/src/com/codename1/ui/Component.java @@ -729,7 +729,7 @@ public Object getNativeOverlay() { * * @return a unified style object for the purpose of setting on object object instances */ - public Style getAllStyles() { + public final Style getAllStyles() { if (allStyles == null) { allStyles = Style.createProxyStyle(getUnselectedStyle(), getSelectedStyle(), getPressedStyle(), getDisabledStyle()); } @@ -1315,7 +1315,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; } @@ -1712,6 +1712,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; @@ -3704,8 +3713,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) { } /** 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 f3dbe5438e..965e7749cf 100644 --- a/CodenameOne/src/com/codename1/ui/Container.java +++ b/CodenameOne/src/com/codename1/ui/Container.java @@ -147,7 +147,7 @@ public class Container extends Component implements Iterable { */ public Container(Layout layout, String uiid) { super(); - setUIID(uiid); + setUIIDFinal(uiid); this.layout = layout; setFocusable(false); } @@ -498,7 +498,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; } diff --git a/CodenameOne/src/com/codename1/ui/Dialog.java b/CodenameOne/src/com/codename1/ui/Dialog.java index 699c2dde9d..692c4069b1 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); } @@ -768,7 +768,7 @@ public void setTitle(String 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/Form.java b/CodenameOne/src/com/codename1/ui/Form.java index 776c890def..014881b9cf 100644 --- a/CodenameOne/src/com/codename1/ui/Form.java +++ b/CodenameOne/src/com/codename1/ui/Form.java @@ -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(); @@ -3924,7 +3924,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); } diff --git a/CodenameOne/src/com/codename1/ui/Label.java b/CodenameOne/src/com/codename1/ui/Label.java index ef81248596..dd5b8f10e0 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) { @@ -1350,7 +1359,7 @@ public boolean isShowEvenIfBlank() { * * @param showEvenIfBlank the showEvenIfBlank to set */ - public void setShowEvenIfBlank(boolean showEvenIfBlank) { + public final void setShowEvenIfBlank(boolean showEvenIfBlank) { this.showEvenIfBlank = showEvenIfBlank; } diff --git a/CodenameOne/src/com/codename1/ui/List.java b/CodenameOne/src/com/codename1/ui/List.java index 1e4b6ce247..00b872829a 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); } @@ -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/RadioButton.java b/CodenameOne/src/com/codename1/ui/RadioButton.java index 46f3188cce..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"); } /** 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..0351ba5db0 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"); 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 5b63579f02..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)) { diff --git a/CodenameOne/src/com/codename1/ui/TextArea.java b/CodenameOne/src/com/codename1/ui/TextArea.java index e8f9cd272e..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); 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/Toolbar.java b/CodenameOne/src/com/codename1/ui/Toolbar.java index 0bb80e3db0..6100496093 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 @@ -2308,11 +2308,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 +2598,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(); 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/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/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/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/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..b3f84407c2 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); } diff --git a/CodenameOne/src/com/codename1/ui/spinner/Picker.java b/CodenameOne/src/com/codename1/ui/spinner/Picker.java index 0f60b06d42..e4990002f1 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 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/table/Table.java b/CodenameOne/src/com/codename1/ui/table/Table.java index 8c5010d94e..c247686c34 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(); diff --git a/CodenameOne/src/com/codename1/ui/tree/Tree.java b/CodenameOne/src/com/codename1/ui/tree/Tree.java index 7215f46549..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"); } /** 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/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index e78aef88ff..862d8c12d3 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -44,6 +44,14 @@ + + + + + + + + + + + + + + + + + + + + From bf4c0420402017aa7747c866e6315997ff427ea7 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 1 Jan 2026 07:09:30 +0200 Subject: [PATCH 25/58] Multiple fixes and removed call in constructor --- .github/scripts/generate-quality-report.py | 1 - .../impl/CodenameOneImplementation.java | 4 +- CodenameOne/src/com/codename1/io/Oauth2.java | 50 ++++++++++++------- .../src/com/codename1/share/ShareForm.java | 16 ++++++ .../com/codename1/social/FacebookConnect.java | 20 +++++++- .../com/codename1/social/GoogleConnect.java | 17 +++++++ CodenameOne/src/com/codename1/ui/Button.java | 2 +- .../ui/CommonProgressAnimations.java | 8 +-- .../src/com/codename1/ui/Component.java | 12 +++-- CodenameOne/src/com/codename1/ui/Display.java | 20 ++++---- CodenameOne/src/com/codename1/ui/Form.java | 1 - CodenameOne/src/com/codename1/ui/List.java | 2 +- .../src/com/codename1/ui/RunnableWrapper.java | 8 +-- CodenameOne/src/com/codename1/ui/Sheet.java | 23 +++++---- .../src/com/codename1/ui/SideMenuBar.java | 2 +- CodenameOne/src/com/codename1/ui/Toolbar.java | 5 +- .../ui/animations/ComponentAnimation.java | 2 +- .../html/AsyncDocumentRequestHandlerImpl.java | 2 +- .../src/com/codename1/ui/html/HTMLTable.java | 5 +- .../codename1/ui/list/ListCellRenderer.java | 2 +- .../src/com/codename1/ui/plaf/Style.java | 9 ++-- .../src/com/codename1/util/AsyncResource.java | 6 +-- .../src/com/codename1/util/EasyThread.java | 14 +++--- maven/core-unittests/spotbugs-exclude.xml | 8 +++ 24 files changed, 156 insertions(+), 83 deletions(-) diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py index 374952f45a..9a8afb8edf 100755 --- a/.github/scripts/generate-quality-report.py +++ b/.github/scripts/generate-quality-report.py @@ -800,7 +800,6 @@ def main() -> None: "EI_EXPOSE_REP2", "EI_EXPOSE_STATIC_REP2", "EQ_COMPARETO_USE_OBJECT_EQUALS", - "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR", "MS_EXPOSE_REP", "NM_CONFUSING", "NO_NOTIFY_NOT_NOTIFYALL", diff --git a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java index 06109217d1..4c07a3be91 100644 --- a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java +++ b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java @@ -575,7 +575,9 @@ public void stopTextEditing() { */ public void stopTextEditing(Runnable onFinish) { stopTextEditing(); - onFinish.run(); + if(onFinish != null) { + onFinish.run(); + } } /** diff --git a/CodenameOne/src/com/codename1/io/Oauth2.java b/CodenameOne/src/com/codename1/io/Oauth2.java index 0ad308c371..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; @@ -542,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() { @@ -660,7 +654,6 @@ private Hashtable getParamsFromURL(String url) { } public static class RefreshTokenRequest extends AsyncResource { - } private static class RefreshTokenActionListener implements ActionListener { @@ -692,6 +685,25 @@ public ShowAuthenticationCommand(Dialog progress, Form old) { 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(); diff --git a/CodenameOne/src/com/codename1/share/ShareForm.java b/CodenameOne/src/com/codename1/share/ShareForm.java index 972798b113..8508dc5b92 100644 --- a/CodenameOne/src/com/codename1/share/ShareForm.java +++ b/CodenameOne/src/com/codename1/share/ShareForm.java @@ -116,6 +116,22 @@ public BackCommand(Form contacts) { 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 fc1b227cb8..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"}; @@ -267,6 +269,22 @@ 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 diff --git a/CodenameOne/src/com/codename1/social/GoogleConnect.java b/CodenameOne/src/com/codename1/social/GoogleConnect.java index 5ddaa0d24d..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; /** @@ -115,6 +116,22 @@ 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 diff --git a/CodenameOne/src/com/codename1/ui/Button.java b/CodenameOne/src/com/codename1/ui/Button.java index fe8bf9076e..04bcb80e73 100644 --- a/CodenameOne/src/com/codename1/ui/Button.java +++ b/CodenameOne/src/com/codename1/ui/Button.java @@ -1087,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/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 555074af58..1616a0bbd4 100644 --- a/CodenameOne/src/com/codename1/ui/Component.java +++ b/CodenameOne/src/com/codename1/ui/Component.java @@ -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); } @@ -727,7 +727,7 @@ 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 final Style getAllStyles() { if (allStyles == null) { @@ -1047,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) { @@ -1695,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; @@ -6043,7 +6047,7 @@ protected void initSelectedStyle(Style selectedStyle) { * * @return the component Style object */ - public Style getUnselectedStyle() { + public final Style getUnselectedStyle() { if (unSelectedStyle == null) { initStyle(); } diff --git a/CodenameOne/src/com/codename1/ui/Display.java b/CodenameOne/src/com/codename1/ui/Display.java index 784d71730f..e345f7ac13 100644 --- a/CodenameOne/src/com/codename1/ui/Display.java +++ b/CodenameOne/src/com/codename1/ui/Display.java @@ -1313,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; @@ -1332,7 +1332,7 @@ boolean isProcessingSerialCalls() { void notifyDisplay() { synchronized (lock) { - lock.notify(); + lock.notifyAll(); } } @@ -1621,7 +1621,7 @@ void setCurrent(final Form newForm, boolean reverse) { } } synchronized (lock) { - lock.notify(); + lock.notifyAll(); } if (!transitionExists) { @@ -1847,7 +1847,7 @@ private void addSingleArgumentEvent(int type, int code) { inputEventStackPointer++; inputEventStack[inputEventStackPointer] = code; inputEventStackPointer++; - lock.notify(); + lock.notifyAll(); } } @@ -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(); } } diff --git a/CodenameOne/src/com/codename1/ui/Form.java b/CodenameOne/src/com/codename1/ui/Form.java index 1f7c63dee3..26d8f8e11c 100644 --- a/CodenameOne/src/com/codename1/ui/Form.java +++ b/CodenameOne/src/com/codename1/ui/Form.java @@ -1730,7 +1730,6 @@ void updateIcsIconCommandBehavior() { @Override public void stopEditing(Runnable onFinish) { Display.getInstance().stopEditing(this, onFinish); - } @Override diff --git a/CodenameOne/src/com/codename1/ui/List.java b/CodenameOne/src/com/codename1/ui/List.java index 00b872829a..1af6bc1374 100644 --- a/CodenameOne/src/com/codename1/ui/List.java +++ b/CodenameOne/src/com/codename1/ui/List.java @@ -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; } diff --git a/CodenameOne/src/com/codename1/ui/RunnableWrapper.java b/CodenameOne/src/com/codename1/ui/RunnableWrapper.java index 0fc0f60569..0d1324dfb0 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: diff --git a/CodenameOne/src/com/codename1/ui/Sheet.java b/CodenameOne/src/com/codename1/ui/Sheet.java index 0351ba5db0..477a2a6845 100644 --- a/CodenameOne/src/com/codename1/ui/Sheet.java +++ b/CodenameOne/src/com/codename1/ui/Sheet.java @@ -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 4005f35c11..6d453136f3 100644 --- a/CodenameOne/src/com/codename1/ui/SideMenuBar.java +++ b/CodenameOne/src/com/codename1/ui/SideMenuBar.java @@ -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/Toolbar.java b/CodenameOne/src/com/codename1/ui/Toolbar.java index 6100496093..9d9a31fa8b 100644 --- a/CodenameOne/src/com/codename1/ui/Toolbar.java +++ b/CodenameOne/src/com/codename1/ui/Toolbar.java @@ -1508,10 +1508,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(); 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..004c509347 100644 --- a/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java +++ b/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java @@ -144,7 +144,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/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/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/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/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..8ef7b66237 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(); } } @@ -172,7 +172,7 @@ public void onSucess(T value) { synchronized (flag) { result[0] = value; flag[0] = true; - flag.notify(); + flag.notifyAll(); } } }; @@ -184,7 +184,7 @@ public void run(SuccessCallback onSuccess) { synchronized (LOCK) { queue.add(rr); queue.add(sc); - LOCK.notify(); + LOCK.notifyAll(); } Display.getInstance().invokeAndBlock(new Runnable() { public void run() { @@ -213,12 +213,12 @@ public void run() { } finally { synchronized (flag) { flag[0] = true; - flag.notify(); + flag.notifyAll(); } } } }); - LOCK.notify(); + LOCK.notifyAll(); } Display.getInstance().invokeAndBlock(new Runnable() { public void run() { @@ -237,7 +237,7 @@ public void run() { public void kill() { synchronized (LOCK) { running = false; - LOCK.notify(); + LOCK.notifyAll(); } } diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index e194262d2e..6e26c2a1e9 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -112,6 +112,14 @@ + + + + + From c9ac07a00f1ec2b4f2b417f89649e3d4a9ce4aff Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 1 Jan 2026 18:44:23 +0200 Subject: [PATCH 26/58] Further fixes --- .../src/com/codename1/ui/Container.java | 34 ++----------------- .../com/codename1/ui/ElevationComparator.java | 15 ++++++++ .../codename1/ui/RefreshThemeCallback.java | 21 ++++++++++++ .../codename1/ui/RefreshThemeRunnable.java | 13 +++++++ 4 files changed, 52 insertions(+), 31 deletions(-) create mode 100644 CodenameOne/src/com/codename1/ui/ElevationComparator.java create mode 100644 CodenameOne/src/com/codename1/ui/RefreshThemeCallback.java create mode 100644 CodenameOne/src/com/codename1/ui/RefreshThemeRunnable.java diff --git a/CodenameOne/src/com/codename1/ui/Container.java b/CodenameOne/src/com/codename1/ui/Container.java index f42851baa4..b382a8f184 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; @@ -304,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; } - } /** @@ -961,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))) { @@ -1904,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(); 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/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); + } +} From b163ebb17b796adbe7e2e55f2c7bb293bb890a9f Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 1 Jan 2026 20:58:53 +0200 Subject: [PATCH 27/58] Fixed most issues --- CodenameOne/src/com/codename1/ui/Form.java | 49 +++---- .../src/com/codename1/ui/InputComponent.java | 40 +++-- CodenameOne/src/com/codename1/ui/Label.java | 5 +- CodenameOne/src/com/codename1/ui/MenuBar.java | 18 ++- .../src/com/codename1/ui/RunnableWrapper.java | 4 +- CodenameOne/src/com/codename1/ui/Toolbar.java | 29 ++-- .../html/AsyncDocumentRequestHandlerImpl.java | 77 ++++++---- .../com/codename1/ui/html/HTMLComponent.java | 19 ++- .../codename1/ui/html/HTMLInputFormat.java | 13 +- .../com/codename1/ui/layouts/GroupLayout.java | 1 - .../codename1/ui/layouts/LayeredLayout.java | 30 ++-- .../ui/layouts/mig/ConstraintParser.java | 2 +- .../codename1/ui/plaf/DefaultLookAndFeel.java | 56 ++----- .../com/codename1/ui/spinner/BaseSpinner.java | 17 ++- .../codename1/ui/spinner/DateSpinner3D.java | 69 +++++---- .../src/com/codename1/ui/spinner/Picker.java | 11 +- .../com/codename1/ui/spinner/SpinnerNode.java | 58 +++++--- .../com/codename1/ui/spinner/TimeSpinner.java | 52 ++++--- .../codename1/ui/spinner/TimeSpinner3D.java | 89 ++++++----- .../ui/table/SortableTableModel.java | 38 +++-- .../src/com/codename1/ui/table/Table.java | 76 +++++----- .../com/codename1/ui/util/GlassTutorial.java | 11 +- .../src/com/codename1/ui/util/Resources.java | 18 +-- .../codename1/ui/util/SwipeBackSupport.java | 32 ++-- .../codename1/ui/validation/Validator.java | 31 ++-- .../src/com/codename1/util/EasyThread.java | 138 ++++++++++++------ 26 files changed, 563 insertions(+), 420 deletions(-) diff --git a/CodenameOne/src/com/codename1/ui/Form.java b/CodenameOne/src/com/codename1/ui/Form.java index 26d8f8e11c..1dfbc0f1eb 100644 --- a/CodenameOne/src/com/codename1/ui/Form.java +++ b/CodenameOne/src/com/codename1/ui/Form.java @@ -736,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(); } /** @@ -2954,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); } @@ -4831,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 0670939746..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; @@ -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 dd5b8f10e0..a06befc8cb 100644 --- a/CodenameOne/src/com/codename1/ui/Label.java +++ b/CodenameOne/src/com/codename1/ui/Label.java @@ -914,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()); @@ -1569,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/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/RunnableWrapper.java b/CodenameOne/src/com/codename1/ui/RunnableWrapper.java index 0d1324dfb0..985534c41c 100644 --- a/CodenameOne/src/com/codename1/ui/RunnableWrapper.java +++ b/CodenameOne/src/com/codename1/ui/RunnableWrapper.java @@ -122,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/Toolbar.java b/CodenameOne/src/com/codename1/ui/Toolbar.java index 9d9a31fa8b..154af57907 100644 --- a/CodenameOne/src/com/codename1/ui/Toolbar.java +++ b/CodenameOne/src/com/codename1/ui/Toolbar.java @@ -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); @@ -1642,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(); @@ -2784,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/html/AsyncDocumentRequestHandlerImpl.java b/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java index 004c509347..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.notifyAll(); - } + 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/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/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/plaf/DefaultLookAndFeel.java b/CodenameOne/src/com/codename1/ui/plaf/DefaultLookAndFeel.java index d2a629dacd..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; @@ -959,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) { @@ -2323,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); - } /** @@ -2591,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/spinner/BaseSpinner.java b/CodenameOne/src/com/codename1/ui/spinner/BaseSpinner.java index b3f84407c2..c0885bffd0 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/BaseSpinner.java +++ b/CodenameOne/src/com/codename1/ui/spinner/BaseSpinner.java @@ -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 e4990002f1..1562b19e50 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/Picker.java +++ b/CodenameOne/src/com/codename1/ui/spinner/Picker.java @@ -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 || (s != null && s.equals(value))) { + if (value.equals(s)) { return offset; } offset++; 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/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..0913f63bf3 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(); } } @@ -533,4 +491,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 c247686c34..01e3f45c2b 100644 --- a/CodenameOne/src/com/codename1/ui/table/Table.java +++ b/CodenameOne/src/com/codename1/ui/table/Table.java @@ -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(); + } } } } @@ -433,32 +430,7 @@ private Component createCellImpl(Object value, final int row, final int column, * @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); - return Double.compare(d1, d2); - } catch (IllegalArgumentException err) { - long dd = Util.toDateValue(o1).getTime() - Util.toDateValue(o2).getTime(); - return (int) dd; - } - } - }; + return new ColumnSortComparator(new CaseInsensitiveOrder()); } /** @@ -977,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/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 110baff320..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(); @@ -1299,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(); @@ -1317,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/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/EasyThread.java b/CodenameOne/src/com/codename1/util/EasyThread.java index 8ef7b66237..5d49c79a0b 100644 --- a/CodenameOne/src/com/codename1/util/EasyThread.java +++ b/CodenameOne/src/com/codename1/util/EasyThread.java @@ -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.notifyAll(); - } - } - }; - 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.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.notifyAll(); - } - } - } - }); + 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)); } /** @@ -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(); + } + } + } } From 3b6b67f48df69a87afc24a5e2e146663a8201960 Mon Sep 17 00:00:00 2001 From: ThomasH99 Date: Fri, 2 Jan 2026 06:32:26 +0100 Subject: [PATCH 28/58] Added missing null check in SimpleDateFormat parse() (#4377) --- CodenameOne/src/com/codename1/l10n/SimpleDateFormat.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From fc491b4d87259bcaf819b027ad8423b328dc5a26 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Fri, 2 Jan 2026 08:03:38 +0200 Subject: [PATCH 29/58] Update corevm.jar reference path in project.properties --- CodenameOne/nbproject/project.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From e5f712e62793d87fd38aeb8016f383b2b494b3ae Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Fri, 2 Jan 2026 08:04:41 +0200 Subject: [PATCH 30/58] Uncomment getResourceAsStream method in Class.java --- Ports/CLDC11/src/java/lang/Class.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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. From 7198cddc67184a4e79fea813935cc679410b4c66 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 2 Jan 2026 20:09:23 +0200 Subject: [PATCH 31/58] Implement durationMode in TimeSpinner3D (#4379) * Implemented durationMode in TimeSpinner3D Added setDurationMode(boolean) logic to toggle duration mode (0-24h range, no meridiem). Updated addComponents to include "hours" and "minutes" labels when in duration mode. Updated rebuildHours to adjust startHour/endHour for duration mode. Verified with TimeSpinner3DTest. * Implemented durationMode in TimeSpinner3D and added unit test. - In `TimeSpinner3D.java`: - Implemented `setDurationMode(boolean)` to update state and rebuild UI. - Updated `addComponents` to add "hours" and "minutes" labels in duration mode. - Updated `rebuildHours` to set correct hour range (0-24) for duration mode. - Added `TimeSpinner3DTest.java` in `maven/core-unittests` to verify duration mode behavior. --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- .../codename1/ui/spinner/TimeSpinner3D.java | 57 +++++++++++++++---- .../ui/spinner/TimeSpinner3DTest.java | 51 +++++++++++++++++ 2 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 maven/core-unittests/src/test/java/com/codename1/ui/spinner/TimeSpinner3DTest.java diff --git a/CodenameOne/src/com/codename1/ui/spinner/TimeSpinner3D.java b/CodenameOne/src/com/codename1/ui/spinner/TimeSpinner3D.java index fd99efed1c..d614c58f2d 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/TimeSpinner3D.java +++ b/CodenameOne/src/com/codename1/ui/spinner/TimeSpinner3D.java @@ -156,17 +156,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 +365,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 +465,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. 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"); + } +} From 486c2b9854d2e9127299a7977ef0a2d192481a38 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Tue, 30 Dec 2025 05:27:53 +0200 Subject: [PATCH 32/58] Initial work on improving spotless fixes --- .github/scripts/generate-quality-report.py | 13 ++++- .../capture/VideoCaptureConstraints.java | 2 +- CodenameOne/src/com/codename1/io/Util.java | 14 ++--- .../com/codename1/io/WebServiceProxyCall.java | 32 ++++++------ .../src/com/codename1/io/gzip/GZIPHeader.java | 2 +- .../src/com/codename1/payment/Purchase.java | 17 +++--- .../processing/HashtableContent.java | 8 +-- .../codename1/processing/PrettyPrinter.java | 52 +++---------------- .../com/codename1/share/FacebookShare.java | 4 +- .../src/com/codename1/ui/Component.java | 5 +- CodenameOne/src/com/codename1/ui/Display.java | 22 ++++---- .../src/com/codename1/ui/EncodedImage.java | 6 +-- .../src/com/codename1/ui/SideMenuBar.java | 2 +- .../src/com/codename1/ui/TextSelection.java | 25 ++------- .../ui/animations/CommonTransitions.java | 2 - .../codename1/ui/plaf/DefaultLookAndFeel.java | 32 ++---------- .../src/com/codename1/ui/spinner/Picker.java | 2 +- .../src/com/codename1/ui/table/Table.java | 28 +++------- .../src/com/codename1/ui/tree/Tree.java | 2 +- .../src/com/codename1/ui/util/Resources.java | 13 +---- .../src/com/codename1/ui/util/UIBuilder.java | 7 ++- .../com/codename1/util/regex/RECompiler.java | 48 ++++++++--------- maven/core-unittests/spotbugs-exclude.xml | 23 ++++++-- 23 files changed, 143 insertions(+), 218 deletions(-) diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py index 80ca0ad17e..f5c1b28598 100755 --- a/.github/scripts/generate-quality-report.py +++ b/.github/scripts/generate-quality-report.py @@ -776,7 +776,18 @@ 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" } violations = [ f for f in spotbugs.findings 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/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/payment/Purchase.java b/CodenameOne/src/com/codename1/payment/Purchase.java index 4ada6161d9..114088f219 100644 --- a/CodenameOne/src/com/codename1/payment/Purchase.java +++ b/CodenameOne/src/com/codename1/payment/Purchase.java @@ -53,6 +53,7 @@ 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; @@ -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(); } }); - } /** 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/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/ui/Component.java b/CodenameOne/src/com/codename1/ui/Component.java index dfd4d310c5..3e2767aadf 100644 --- a/CodenameOne/src/com/codename1/ui/Component.java +++ b/CodenameOne/src/com/codename1/ui/Component.java @@ -6531,7 +6531,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()) { diff --git a/CodenameOne/src/com/codename1/ui/Display.java b/CodenameOne/src/com/codename1/ui/Display.java index 0cacf01423..db43f8179e 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; /** @@ -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) { @@ -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; 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/SideMenuBar.java b/CodenameOne/src/com/codename1/ui/SideMenuBar.java index 2a02da2c45..4005f35c11 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(); 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/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/plaf/DefaultLookAndFeel.java b/CodenameOne/src/com/codename1/ui/plaf/DefaultLookAndFeel.java index 53a8f531fd..d2a629dacd 100644 --- a/CodenameOne/src/com/codename1/ui/plaf/DefaultLookAndFeel.java +++ b/CodenameOne/src/com/codename1/ui/plaf/DefaultLookAndFeel.java @@ -825,13 +825,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 +844,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 +855,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 +878,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; } @@ -2567,22 +2545,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 +2573,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); } } } diff --git a/CodenameOne/src/com/codename1/ui/spinner/Picker.java b/CodenameOne/src/com/codename1/ui/spinner/Picker.java index 53cb691c62..0f60b06d42 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/Picker.java +++ b/CodenameOne/src/com/codename1/ui/spinner/Picker.java @@ -1208,7 +1208,7 @@ public void setSelectedString(String str) { public int getSelectedStringIndex() { int offset = 0; for (String s : (String[]) metaData) { - if (s == value) { + if (s == value || (s != null && s.equals(value))) { return offset; } offset++; diff --git a/CodenameOne/src/com/codename1/ui/table/Table.java b/CodenameOne/src/com/codename1/ui/table/Table.java index c25f0d9748..8c5010d94e 100644 --- a/CodenameOne/src/com/codename1/ui/table/Table.java +++ b/CodenameOne/src/com/codename1/ui/table/Table.java @@ -426,15 +426,15 @@ 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) { + protected Comparator createColumnSortComparator(int column) { final CaseInsensitiveOrder ccmp = new CaseInsensitiveOrder(); - return new Comparator() { + return new Comparator() { public int compare(Object o1, Object o2) { if (o1 == null) { if (o2 == null) { @@ -452,25 +452,11 @@ public int compare(Object o1, Object 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; - } + return Double.compare(d1, d2); } catch (IllegalArgumentException err) { long dd = Util.toDateValue(o1).getTime() - Util.toDateValue(o2).getTime(); return (int) dd; } - return 0; } }; } @@ -483,7 +469,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 +491,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 { diff --git a/CodenameOne/src/com/codename1/ui/tree/Tree.java b/CodenameOne/src/com/codename1/ui/tree/Tree.java index aed8edd102..7215f46549 100644 --- a/CodenameOne/src/com/codename1/ui/tree/Tree.java +++ b/CodenameOne/src/com/codename1/ui/tree/Tree.java @@ -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/Resources.java b/CodenameOne/src/com/codename1/ui/util/Resources.java index ac872d0f7d..110baff320 100644 --- a/CodenameOne/src/com/codename1/ui/util/Resources.java +++ b/CodenameOne/src/com/codename1/ui/util/Resources.java @@ -1198,19 +1198,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(); 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/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/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index c3d94d882b..44efc82049 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -1,5 +1,5 @@ - + + + - + + + @@ -82,4 +86,15 @@ + + + + + + + + + + + From d7266e30384cd469430458a99148af487c97bd83 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Tue, 30 Dec 2025 05:46:15 +0200 Subject: [PATCH 33/58] Fixed compilation issues and hardened build --- .github/scripts/generate-quality-report.py | 26 +++++++++- .../src/com/codename1/testing/TestUtils.java | 20 -------- .../com/codename1/ui/BrowserComponent.java | 51 ++++--------------- .../com/codename1/ui/plaf/StyleParser.java | 17 ------- 4 files changed, 35 insertions(+), 79 deletions(-) diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py index f5c1b28598..8242bff876 100755 --- a/.github/scripts/generate-quality-report.py +++ b/.github/scripts/generate-quality-report.py @@ -787,7 +787,31 @@ def main() -> None: "EQ_GETCLASS_AND_CLASS_CONSTANT", "EQ_UNUSUAL", "ES_COMPARING_STRINGS_WITH_EQ", - "FI_EMPTY" + "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_CONVERT_CASE", + "DM_EXIT", + "EI_EXPOSE_REP", + "EI_EXPOSE_REP2", + "EI_EXPOSE_STATIC_REP2", + "EQ_COMPARETO_USE_OBJECT_EQUALS", + "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR", + "MS_EXPOSE_REP", + "NM_CONFUSING", + "NO_NOTIFY_NOT_NOTIFYALL", + "NP_BOOLEAN_RETURN_NULL", + "PZLA_PREFER_ZERO_LENGTH_ARRAYS", + "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" } violations = [ f for f in spotbugs.findings 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/BrowserComponent.java b/CodenameOne/src/com/codename1/ui/BrowserComponent.java index 6d39ec7e27..9ec1f91c1f 100644 --- a/CodenameOne/src/com/codename1/ui/BrowserComponent.java +++ b/CodenameOne/src/com/codename1/ui/BrowserComponent.java @@ -290,13 +290,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 +541,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(); @@ -1698,6 +1684,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 +1699,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 +1749,6 @@ public String getValue() { return value; } - /** - * Returns the type of the value - * - * @return - */ - private String getType() { - return type; - } - /** * Returns the type of the value. * 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); From 7ae5f291f515f3ef2053db592d6639445b16873f Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Tue, 30 Dec 2025 12:45:19 +0200 Subject: [PATCH 34/58] Improved CI build validation --- .../impl/CodenameOneImplementation.java | 16 +++--------- .../com/codename1/io/FileSystemStorage.java | 1 - .../codename1/location/LocationManager.java | 2 +- .../src/com/codename1/payment/Purchase.java | 8 +++--- .../src/com/codename1/ui/Component.java | 18 +++++++++---- .../src/com/codename1/ui/Container.java | 26 ++++++++++++------- CodenameOne/src/com/codename1/ui/Display.java | 10 +++---- CodenameOne/src/com/codename1/ui/Form.java | 24 ++++++++++++++--- CodenameOne/src/com/codename1/ui/Tabs.java | 6 ++--- maven/core-unittests/spotbugs-exclude.xml | 11 ++++++++ 10 files changed, 77 insertions(+), 45 deletions(-) diff --git a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java index 5be7e0fea4..dd44fc77a3 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; @@ -927,16 +927,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. @@ -8786,7 +8776,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/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/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/payment/Purchase.java b/CodenameOne/src/com/codename1/payment/Purchase.java index 114088f219..6a05448b88 100644 --- a/CodenameOne/src/com/codename1/payment/Purchase.java +++ b/CodenameOne/src/com/codename1/payment/Purchase.java @@ -56,9 +56,9 @@ public abstract class Purchase { 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. @@ -281,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 diff --git a/CodenameOne/src/com/codename1/ui/Component.java b/CodenameOne/src/com/codename1/ui/Component.java index 3e2767aadf..4470fbd719 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; @@ -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 * @@ -3197,8 +3205,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()); } } @@ -4497,7 +4505,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) { @@ -7063,7 +7071,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(); } } diff --git a/CodenameOne/src/com/codename1/ui/Container.java b/CodenameOne/src/com/codename1/ui/Container.java index 8111f45dbd..5941b37ca3 100644 --- a/CodenameOne/src/com/codename1/ui/Container.java +++ b/CodenameOne/src/com/codename1/ui/Container.java @@ -78,13 +78,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; /** @@ -152,6 +152,10 @@ public Container(Layout layout, String uiid) { setFocusable(false); } + static void blockOverdraw() { + blockOverdraw = true; + } + /** * Constructs a new Container with a new layout manager. * @@ -1002,6 +1006,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 +1022,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); } /** @@ -3700,7 +3708,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 +3763,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 +3861,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 +3921,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]; @@ -4362,7 +4370,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/Display.java b/CodenameOne/src/com/codename1/ui/Display.java index db43f8179e..df91b22126 100644 --- a/CodenameOne/src/com/codename1/ui/Display.java +++ b/CodenameOne/src/com/codename1/ui/Display.java @@ -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; @@ -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.blockOverdraw(); 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); diff --git a/CodenameOne/src/com/codename1/ui/Form.java b/CodenameOne/src/com/codename1/ui/Form.java index 0de0968d67..fe752bb72b 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; /** @@ -256,6 +256,10 @@ public Form(Layout contentPaneLayout) { initGlobalToolbar(); } + static Motion getRippleMotion() { + return rippleMotion; + } + /** * Sets the title after invoking the constructor * @@ -2031,6 +2035,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 +2051,7 @@ void repaintAnimations() { if (rippleComponent != null) { rippleComponent.repaint(); if (rippleMotion == null) { - rippleComponent = null; + resetRippleComponent(); } } if (animatableComponents != null) { @@ -3089,11 +3101,15 @@ 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; + setRippleComponent(cmp); rippleX = x; rippleY = y; } diff --git a/CodenameOne/src/com/codename1/ui/Tabs.java b/CodenameOne/src/com/codename1/ui/Tabs.java index 685080739f..5b63579f02 100644 --- a/CodenameOne/src/com/codename1/ui/Tabs.java +++ b/CodenameOne/src/com/codename1/ui/Tabs.java @@ -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/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 44efc82049..52c12b1b09 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -65,6 +65,17 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 475a5ef81ca025ade3517a2955da39ad7d7925ea Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Tue, 30 Dec 2025 20:02:39 +0200 Subject: [PATCH 37/58] Removed additional settings --- .../com/codename1/charts/views/LineChart.java | 3 +- .../codename1/charts/views/ScatterChart.java | 21 ++++++------ .../com/codename1/components/Progress.java | 20 ++++++----- .../codename1/components/SliderBridge.java | 2 +- .../com/codename1/components/SplitPane.java | 21 +++++++----- .../codename1/facebook/FaceBookAccess.java | 33 ++++++++++++------- maven/core-unittests/spotbugs-exclude.xml | 28 ++++++++++++++-- 7 files changed, 84 insertions(+), 44 deletions(-) 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/components/Progress.java b/CodenameOne/src/com/codename1/components/Progress.java index 9524171772..99bcabc4db 100644 --- a/CodenameOne/src/com/codename1/components/Progress.java +++ b/CodenameOne/src/com/codename1/components/Progress.java @@ -137,15 +137,17 @@ public void setDisposeOnCompletion(boolean disposeOnCompletion) { * {@inheritDoc} */ public void actionPerformed(ActionEvent evt) { - NetworkEvent ev = (NetworkEvent) evt; - if (ev.getConnectionRequest() == request) { - if (disposeOnCompletion && ev.getProgressType() == NetworkEvent.PROGRESS_TYPE_COMPLETED) { - dispose(); - return; - } - if (autoShow && !showing) { - showing = true; - showModeless(); + if(evt instanceof NetworkEvent) { + NetworkEvent ev = (NetworkEvent) evt; + if (ev.getConnectionRequest() == request) { + if (disposeOnCompletion && ev.getProgressType() == NetworkEvent.PROGRESS_TYPE_COMPLETED) { + dispose(); + return; + } + if (autoShow && !showing) { + showing = true; + showModeless(); + } } } } 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/SplitPane.java b/CodenameOne/src/com/codename1/components/SplitPane.java index 84105bbb9b..ec6d393df3 100644 --- a/CodenameOne/src/com/codename1/components/SplitPane.java +++ b/CodenameOne/src/com/codename1/components/SplitPane.java @@ -967,10 +967,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 +992,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) { diff --git a/CodenameOne/src/com/codename1/facebook/FaceBookAccess.java b/CodenameOne/src/com/codename1/facebook/FaceBookAccess.java index 195ff905e9..6224cd2efe 100644 --- a/CodenameOne/src/com/codename1/facebook/FaceBookAccess.java +++ b/CodenameOne/src/com/codename1/facebook/FaceBookAccess.java @@ -513,13 +513,19 @@ public void getPost(String postId, final Post post, final ActionListener callbac 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); + final Object val = ((NetworkEvent) 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); + } + } } } }); @@ -548,10 +554,15 @@ public void actionPerformed(ActionEvent evt) { getFaceBookObject(postId, new ActionListener() { public void actionPerformed(ActionEvent evt) { - Vector v = (Vector) ((NetworkEvent) evt).getMetaData(); - Hashtable t = (Hashtable) v.elementAt(0); - post.copy(t); - + final Object val = ((NetworkEvent) 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); + } + } } }, needAuth, false); if (err.size() > 0) { diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 792303e3e2..2168ad7e5a 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -96,6 +96,23 @@ + + + + + + + + + + + + + + + + + + + - - + From 068aead73752e1eb541466ad1989ef3a456a1876 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 04:29:22 +0200 Subject: [PATCH 38/58] Fixing exclusion logic --- maven/core-unittests/spotbugs-exclude.xml | 88 +++-------------------- 1 file changed, 10 insertions(+), 78 deletions(-) diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 2168ad7e5a..2f7f878818 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -1,65 +1,4 @@ - - @@ -69,8 +8,6 @@ - - @@ -103,7 +40,6 @@ - - + + + @@ -150,7 +76,13 @@ - + + + + + + + From fb3fe56f0b9dd5a3f3edc5ea16265e916b8e42eb Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 04:56:28 +0200 Subject: [PATCH 39/58] Refined rules --- maven/core-unittests/spotbugs-exclude.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 2f7f878818..29a6445e14 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -76,13 +76,15 @@ - + + + From dfe012320582582c4fef252520549be7e569f6c0 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 05:18:14 +0200 Subject: [PATCH 40/58] Additional improvements --- .../javascript/JavascriptContext.java | 6 ++-- .../codename1/maps/CacheProviderProxy.java | 16 ++-------- .../src/com/codename1/payment/Purchase.java | 10 ++++-- .../com/codename1/properties/UiBinding.java | 4 ++- maven/core-unittests/spotbugs-exclude.xml | 32 ++++++++++++++++++- 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/CodenameOne/src/com/codename1/javascript/JavascriptContext.java b/CodenameOne/src/com/codename1/javascript/JavascriptContext.java index eca93b55a5..4256cbe2b4 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 @@ -1000,9 +1000,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/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/payment/Purchase.java b/CodenameOne/src/com/codename1/payment/Purchase.java index 6a05448b88..8fc6139628 100644 --- a/CodenameOne/src/com/codename1/payment/Purchase.java +++ b/CodenameOne/src/com/codename1/payment/Purchase.java @@ -574,7 +574,10 @@ public void run() { while (!complete[0]) { synchronized (complete) { try { - complete.wait(); + // need to recheck condition within the synchronized block + if(!complete[0]) { + complete.wait(); + } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); return; @@ -778,7 +781,10 @@ public void run() { while (!complete[0]) { synchronized (complete) { try { - complete.wait(); + // need to recheck condition within the synchronized block + if(!complete[0]) { + complete.wait(); + } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); return; 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/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 29a6445e14..da76dd060d 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -12,6 +12,16 @@ + + + + + + + + + + + + + + + + + - + + + + + + From e601654c0527869ad20f07a307e3d552fd559f02 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 05:40:09 +0200 Subject: [PATCH 41/58] Fixing exclusions to include inner classes --- maven/core-unittests/spotbugs-exclude.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index da76dd060d..82f4b2e8e4 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -113,13 +113,15 @@ + + - + - + From 66b33580a263aab1a3c84ce08cd0c1f3e06ccdd0 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 05:48:59 +0200 Subject: [PATCH 42/58] Removed cloud storage package and further improvements --- .../src/com/codename1/capture/Capture.java | 14 +- .../codename1/charts/views/BubbleChart.java | 26 +- .../src/com/codename1/cloud/BindTarget.java | 43 - .../com/codename1/cloud/CloudException.java | 52 -- .../codename1/cloud/CloudImageProperty.java | 171 ---- .../com/codename1/cloud/CloudListModel.java | 460 ---------- .../src/com/codename1/cloud/CloudObject.java | 808 ------------------ .../src/com/codename1/cloud/CloudPersona.java | 94 -- .../com/codename1/cloud/CloudResponse.java | 46 - .../src/com/codename1/cloud/CloudStorage.java | 578 ------------- .../com/codename1/cloud/CustomProperty.java | 45 - .../src/com/codename1/cloud/package.html | 12 - .../codename1/ui/spinner/SpinnerRenderer.java | 2 +- maven/core-unittests/spotbugs-exclude.xml | 7 +- 14 files changed, 26 insertions(+), 2332 deletions(-) delete mode 100644 CodenameOne/src/com/codename1/cloud/BindTarget.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudException.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudImageProperty.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudListModel.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudObject.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudPersona.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudResponse.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CloudStorage.java delete mode 100644 CodenameOne/src/com/codename1/cloud/CustomProperty.java delete mode 100644 CodenameOne/src/com/codename1/cloud/package.html diff --git a/CodenameOne/src/com/codename1/capture/Capture.java b/CodenameOne/src/com/codename1/capture/Capture.java index cd8815805c..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(); } } 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/cloud/BindTarget.java b/CodenameOne/src/com/codename1/cloud/BindTarget.java deleted file mode 100644 index 4e31a452db..0000000000 --- a/CodenameOne/src/com/codename1/cloud/BindTarget.java +++ /dev/null @@ -1,43 +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.ui.Component; - -/** - * Allows binding arbitrary components to data storage - * - * @author Shai Almog - * @deprecated this mapped to an older iteration of properties that is no longer used - */ -public interface BindTarget { - /** - * Fired when a property of the component changes to a new value - * - * @param source the source component - * @param propertyName the name of the property - * @param oldValue the old value of the property - * @param newValue the new value for the property - */ - void propertyChanged(Component source, String propertyName, Object oldValue, Object newValue); // PMD Fix: UnnecessaryModifier removed -} 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/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/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 82f4b2e8e4..a4259e024a 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -21,6 +21,9 @@ + + + - + From 25bdfc1489fbb2291e027454cc53deb9bd824f08 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 06:30:22 +0200 Subject: [PATCH 43/58] BindTarget was still used. Restored it and deprecated code --- .../src/com/codename1/cloud/BindTarget.java | 43 +++++++++++++++ .../src/com/codename1/ui/CheckBox.java | 2 + CodenameOne/src/com/codename1/ui/Label.java | 2 + .../src/com/codename1/ui/RadioButton.java | 2 + .../src/com/codename1/ui/TextArea.java | 2 + .../ui/list/GenericListCellRenderer.java | 52 ++----------------- .../codename1/ui/util/EventDispatcher.java | 2 + 7 files changed, 57 insertions(+), 48 deletions(-) create mode 100644 CodenameOne/src/com/codename1/cloud/BindTarget.java diff --git a/CodenameOne/src/com/codename1/cloud/BindTarget.java b/CodenameOne/src/com/codename1/cloud/BindTarget.java new file mode 100644 index 0000000000..4e31a452db --- /dev/null +++ b/CodenameOne/src/com/codename1/cloud/BindTarget.java @@ -0,0 +1,43 @@ +/* + * 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.ui.Component; + +/** + * Allows binding arbitrary components to data storage + * + * @author Shai Almog + * @deprecated this mapped to an older iteration of properties that is no longer used + */ +public interface BindTarget { + /** + * Fired when a property of the component changes to a new value + * + * @param source the source component + * @param propertyName the name of the property + * @param oldValue the old value of the property + * @param newValue the new value for the property + */ + void propertyChanged(Component source, String propertyName, Object oldValue, Object newValue); // PMD Fix: UnnecessaryModifier removed +} diff --git a/CodenameOne/src/com/codename1/ui/CheckBox.java b/CodenameOne/src/com/codename1/ui/CheckBox.java index 46c4a9932a..b462ad6673 100644 --- a/CodenameOne/src/com/codename1/ui/CheckBox.java +++ b/CodenameOne/src/com/codename1/ui/CheckBox.java @@ -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/Label.java b/CodenameOne/src/com/codename1/ui/Label.java index e535d9e540..ef81248596 100644 --- a/CodenameOne/src/com/codename1/ui/Label.java +++ b/CodenameOne/src/com/codename1/ui/Label.java @@ -1221,6 +1221,7 @@ public Class[] getBindablePropertyTypes() { /** * {@inheritDoc} + * @deprecated uses the deprecated BindTarget interface */ public void bindProperty(String prop, BindTarget target) { if (prop.equals("text")) { @@ -1235,6 +1236,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/RadioButton.java b/CodenameOne/src/com/codename1/ui/RadioButton.java index f5f11982ec..46f3188cce 100644 --- a/CodenameOne/src/com/codename1/ui/RadioButton.java +++ b/CodenameOne/src/com/codename1/ui/RadioButton.java @@ -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/TextArea.java b/CodenameOne/src/com/codename1/ui/TextArea.java index cb8a0704f0..e8f9cd272e 100644 --- a/CodenameOne/src/com/codename1/ui/TextArea.java +++ b/CodenameOne/src/com/codename1/ui/TextArea.java @@ -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/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/util/EventDispatcher.java b/CodenameOne/src/com/codename1/ui/util/EventDispatcher.java index 232100bb1c..efaf6d30fe 100644 --- a/CodenameOne/src/com/codename1/ui/util/EventDispatcher.java +++ b/CodenameOne/src/com/codename1/ui/util/EventDispatcher.java @@ -167,6 +167,7 @@ public void fireDataChangeEvent(int index, int type) { * @param propertyName the name of the property * @param oldValue the old value of the property * @param newValue the new value for the property + * @deprecated uses the deprecated BindTarget interface */ public void fireBindTargetChange(Component source, String propertyName, Object oldValue, Object newValue) { if (listeners == null || listeners.size() == 0) { @@ -201,6 +202,7 @@ public void fireBindTargetChange(Component source, String propertyName, Object o * @param propertyName the name of the property * @param oldValue the old value of the property * @param newValue the new value for the property + * @deprecated uses the deprecated BindTarget interface */ private void fireBindTargetChangeSync(BindTarget[] arr, Component source, String propertyName, Object oldValue, Object newValue) { int alen = arr.length; From 93c13e4c3057bf9eb877f35e2d87bf0ea3ff5916 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 07:54:27 +0200 Subject: [PATCH 44/58] Trying again for TarEntry --- maven/core-unittests/spotbugs-exclude.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index a4259e024a..a3988ce5c9 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -125,6 +125,6 @@ - + From 35b21acadb1eec6f874ceb9c00e36bb771755f59 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 10:51:08 +0200 Subject: [PATCH 45/58] WTF --- .../src/com/codename1/components/Accordion.java | 2 +- CodenameOne/src/com/codename1/ui/Component.java | 2 +- CodenameOne/src/com/codename1/ui/Form.java | 1 + maven/core-unittests/spotbugs-exclude.xml | 16 ++++++++++++---- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CodenameOne/src/com/codename1/components/Accordion.java b/CodenameOne/src/com/codename1/components/Accordion.java index 912846105c..16c1c03121 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); } /** diff --git a/CodenameOne/src/com/codename1/ui/Component.java b/CodenameOne/src/com/codename1/ui/Component.java index 4470fbd719..12dc72fce4 100644 --- a/CodenameOne/src/com/codename1/ui/Component.java +++ b/CodenameOne/src/com/codename1/ui/Component.java @@ -7252,7 +7252,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/Form.java b/CodenameOne/src/com/codename1/ui/Form.java index 555c9cd419..776c890def 100644 --- a/CodenameOne/src/com/codename1/ui/Form.java +++ b/CodenameOne/src/com/codename1/ui/Form.java @@ -4406,6 +4406,7 @@ public boolean isScrollableY() { /** * {@inheritDoc} */ + @Override public void setScrollableY(boolean scrollableY) { getContentPane().setScrollableY(scrollableY); } diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index a3988ce5c9..d03c11dbe3 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -25,6 +25,14 @@ + + + + + - + - + - + - + From ac345b3bd6bbc6f11e19b18cf0845824d1e9dc2e Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 11:09:46 +0200 Subject: [PATCH 46/58] Trying source name --- maven/core-unittests/spotbugs-exclude.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index d03c11dbe3..e78aef88ff 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -128,7 +128,7 @@ - + From a3b6aa46432dfd885e0936b803b513bc935dc89c Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 11:55:19 +0200 Subject: [PATCH 47/58] Fixed python script to ignore the tags failure --- .github/scripts/generate-quality-report.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py index 8242bff876..0c64a87545 100755 --- a/.github/scripts/generate-quality-report.py +++ b/.github/scripts/generate-quality-report.py @@ -813,10 +813,19 @@ def main() -> None: "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:") From 61b68f4f6319aa78980b4fc0f39603cca6433d7f Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Wed, 31 Dec 2025 13:53:52 +0200 Subject: [PATCH 48/58] Major fixes for calls from constructors --- .github/scripts/generate-quality-report.py | 1 - .../com/codename1/charts/ChartComponent.java | 2 +- .../com/codename1/components/Accordion.java | 2 +- .../src/com/codename1/components/Ads.java | 35 +++-- .../com/codename1/components/ButtonList.java | 5 +- .../com/codename1/components/FileTree.java | 4 +- .../components/FloatingActionButton.java | 49 ++++--- .../codename1/components/FloatingHint.java | 35 +++-- .../com/codename1/components/ImageViewer.java | 2 +- .../components/InfiniteProgress.java | 2 +- .../components/InteractionDialog.java | 2 +- .../com/codename1/components/MultiButton.java | 2 +- .../com/codename1/components/OnOffSwitch.java | 2 +- .../com/codename1/components/RSSReader.java | 2 +- .../components/ScaleImageButton.java | 4 +- .../codename1/components/ScaleImageLabel.java | 4 +- .../com/codename1/components/ShareButton.java | 2 +- .../components/SignatureComponent.java | 2 +- .../com/codename1/components/SpanButton.java | 2 +- .../com/codename1/components/SpanLabel.java | 2 +- .../codename1/components/SpanMultiButton.java | 2 +- .../com/codename1/components/SplitPane.java | 2 +- .../src/com/codename1/components/Switch.java | 2 +- .../com/codename1/facebook/ui/LikeButton.java | 2 +- .../com/codename1/ui/BrowserComponent.java | 2 +- CodenameOne/src/com/codename1/ui/Button.java | 2 +- .../src/com/codename1/ui/Calendar.java | 4 +- .../src/com/codename1/ui/CheckBox.java | 2 +- .../src/com/codename1/ui/ComboBox.java | 2 +- .../src/com/codename1/ui/Component.java | 25 +++- .../src/com/codename1/ui/ComponentGroup.java | 2 +- .../src/com/codename1/ui/Container.java | 4 +- CodenameOne/src/com/codename1/ui/Dialog.java | 8 +- CodenameOne/src/com/codename1/ui/Form.java | 4 +- CodenameOne/src/com/codename1/ui/Label.java | 17 ++- CodenameOne/src/com/codename1/ui/List.java | 4 +- .../src/com/codename1/ui/RadioButton.java | 2 +- .../src/com/codename1/ui/SearchBar.java | 2 +- CodenameOne/src/com/codename1/ui/Sheet.java | 2 +- CodenameOne/src/com/codename1/ui/Slider.java | 2 +- CodenameOne/src/com/codename1/ui/Tabs.java | 2 +- .../src/com/codename1/ui/TextArea.java | 2 +- .../src/com/codename1/ui/TextField.java | 8 +- CodenameOne/src/com/codename1/ui/Toolbar.java | 22 +-- .../com/codename1/ui/html/HTMLImageMap.java | 2 +- .../src/com/codename1/ui/html/HTMLLink.java | 2 +- .../com/codename1/ui/html/MultiComboBox.java | 10 +- .../com/codename1/ui/list/ContainerList.java | 4 +- .../ui/list/DefaultListCellRenderer.java | 2 +- .../src/com/codename1/ui/scene/Scene.java | 2 +- .../com/codename1/ui/spinner/BaseSpinner.java | 2 +- .../src/com/codename1/ui/spinner/Picker.java | 2 +- .../src/com/codename1/ui/spinner/Spinner.java | 2 +- .../src/com/codename1/ui/table/Table.java | 4 +- .../src/com/codename1/ui/tree/Tree.java | 2 +- .../impl/android/AndroidImplementation.java | 133 +++++++++--------- maven/core-unittests/spotbugs-exclude.xml | 8 ++ 57 files changed, 264 insertions(+), 198 deletions(-) diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py index 0c64a87545..f8be78fe2f 100755 --- a/.github/scripts/generate-quality-report.py +++ b/.github/scripts/generate-quality-report.py @@ -806,7 +806,6 @@ def main() -> None: "NM_CONFUSING", "NO_NOTIFY_NOT_NOTIFYALL", "NP_BOOLEAN_RETURN_NULL", - "PZLA_PREFER_ZERO_LENGTH_ARRAYS", "REFLC_REFLECTION_MAY_INCREASE_ACCESSIBILITY_OF_CLASS", "UI_INHERITANCE_UNSAFE_GETRESOURCE", "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", 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/components/Accordion.java b/CodenameOne/src/com/codename1/components/Accordion.java index 16c1c03121..92d643038d 100644 --- a/CodenameOne/src/com/codename1/components/Accordion.java +++ b/CodenameOne/src/com/codename1/components/Accordion.java @@ -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..9df016b2b6 100644 --- a/CodenameOne/src/com/codename1/components/ButtonList.java +++ b/CodenameOne/src/com/codename1/components/ButtonList.java @@ -110,7 +110,6 @@ public ButtonList(ListModel model) { ((DefaultListModel) model).setMultiSelectionMode(true); } setModel(model); - } /** @@ -130,7 +129,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 +159,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); 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..8ba0c59533 100644 --- a/CodenameOne/src/com/codename1/components/ImageViewer.java +++ b/CodenameOne/src/com/codename1/components/ImageViewer.java @@ -117,7 +117,7 @@ public class ImageViewer extends Component { */ public ImageViewer() { setFocusable(true); - setUIID("ImageViewer"); + setUIIDFinal("ImageViewer"); $(this).selectAllStyles().setBgTransparency(0x0); } 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/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/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..3c1f1b222e 100644 --- a/CodenameOne/src/com/codename1/components/ShareButton.java +++ b/CodenameOne/src/com/codename1/components/ShareButton.java @@ -69,7 +69,7 @@ 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); diff --git a/CodenameOne/src/com/codename1/components/SignatureComponent.java b/CodenameOne/src/com/codename1/components/SignatureComponent.java index 7ebc070ffe..e378988467 100644 --- a/CodenameOne/src/com/codename1/components/SignatureComponent.java +++ b/CodenameOne/src/com/codename1/components/SignatureComponent.java @@ -451,7 +451,7 @@ private static class SignaturePanel extends Component { private final Style signatureStyle; SignaturePanel() { - setUIID("SignaturePanel"); + setUIIDFinal("SignaturePanel"); signatureBoxStyle = getUIManager().getComponentStyle("SignaturePanelBox"); signatureStyle = getUIManager().getComponentStyle("SignaturePanelSignature"); stroke.setLineWidth(Math.max(1, Display.getInstance().convertToPixels(1, true) / 2)); diff --git a/CodenameOne/src/com/codename1/components/SpanButton.java b/CodenameOne/src/com/codename1/components/SpanButton.java index b2aa3f573f..2af42a64da 100644 --- a/CodenameOne/src/com/codename1/components/SpanButton.java +++ b/CodenameOne/src/com/codename1/components/SpanButton.java @@ -82,7 +82,7 @@ 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.setColumns(100); diff --git a/CodenameOne/src/com/codename1/components/SpanLabel.java b/CodenameOne/src/com/codename1/components/SpanLabel.java index cc5f37dd8d..4b389e11d8 100644 --- a/CodenameOne/src/com/codename1/components/SpanLabel.java +++ b/CodenameOne/src/com/codename1/components/SpanLabel.java @@ -80,7 +80,7 @@ public SpanLabel(String txt, String textUiid) { * Constructor accepting default text */ public SpanLabel(String txt) { - setUIID("Container"); + setUIIDFinal("Container"); setLayout(new BorderLayout()); text = new TextArea(getUIManager().localize(txt, txt)); text.setActAsLabel(true); 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 ec6d393df3..08d4323429 100644 --- a/CodenameOne/src/com/codename1/components/SplitPane.java +++ b/CodenameOne/src/com/codename1/components/SplitPane.java @@ -959,7 +959,7 @@ private class Divider extends Container { Divider() { super(new LayeredLayout()); if (dividerUIID != null) { - setUIID(dividerUIID); + setUIIDFinal(dividerUIID); } btnCollapse = $(new Button()) .setUIID(collapseButtonUIID) 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/facebook/ui/LikeButton.java b/CodenameOne/src/com/codename1/facebook/ui/LikeButton.java index 66ce5a7480..88c6950d0a 100644 --- a/CodenameOne/src/com/codename1/facebook/ui/LikeButton.java +++ b/CodenameOne/src/com/codename1/facebook/ui/LikeButton.java @@ -60,7 +60,7 @@ public LikeButton(String postId) { * Default constructor */ public LikeButton() { - setUIID("LikeButton"); + setUIIDFinal("LikeButton"); setText("Like"); addActionListener(this); } diff --git a/CodenameOne/src/com/codename1/ui/BrowserComponent.java b/CodenameOne/src/com/codename1/ui/BrowserComponent.java index 9ec1f91c1f..b09b9ec962 100644 --- a/CodenameOne/src/com/codename1/ui/BrowserComponent.java +++ b/CodenameOne/src/com/codename1/ui/BrowserComponent.java @@ -154,7 +154,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); diff --git a/CodenameOne/src/com/codename1/ui/Button.java b/CodenameOne/src/com/codename1/ui/Button.java index 4dad66f706..6ffb28c572 100644 --- a/CodenameOne/src/com/codename1/ui/Button.java +++ b/CodenameOne/src/com/codename1/ui/Button.java @@ -186,7 +186,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; 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 b462ad6673..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(); } 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/Component.java b/CodenameOne/src/com/codename1/ui/Component.java index 12dc72fce4..555074af58 100644 --- a/CodenameOne/src/com/codename1/ui/Component.java +++ b/CodenameOne/src/com/codename1/ui/Component.java @@ -729,7 +729,7 @@ public Object getNativeOverlay() { * * @return a unified style object for the purpose of setting on object object instances */ - public Style getAllStyles() { + public final Style getAllStyles() { if (allStyles == null) { allStyles = Style.createProxyStyle(getUnselectedStyle(), getSelectedStyle(), getPressedStyle(), getDisabledStyle()); } @@ -1315,7 +1315,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; } @@ -1712,6 +1712,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; @@ -3704,8 +3713,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) { } /** 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 f3dbe5438e..965e7749cf 100644 --- a/CodenameOne/src/com/codename1/ui/Container.java +++ b/CodenameOne/src/com/codename1/ui/Container.java @@ -147,7 +147,7 @@ public class Container extends Component implements Iterable { */ public Container(Layout layout, String uiid) { super(); - setUIID(uiid); + setUIIDFinal(uiid); this.layout = layout; setFocusable(false); } @@ -498,7 +498,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; } diff --git a/CodenameOne/src/com/codename1/ui/Dialog.java b/CodenameOne/src/com/codename1/ui/Dialog.java index 699c2dde9d..692c4069b1 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); } @@ -768,7 +768,7 @@ public void setTitle(String 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/Form.java b/CodenameOne/src/com/codename1/ui/Form.java index 776c890def..014881b9cf 100644 --- a/CodenameOne/src/com/codename1/ui/Form.java +++ b/CodenameOne/src/com/codename1/ui/Form.java @@ -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(); @@ -3924,7 +3924,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); } diff --git a/CodenameOne/src/com/codename1/ui/Label.java b/CodenameOne/src/com/codename1/ui/Label.java index ef81248596..dd5b8f10e0 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) { @@ -1350,7 +1359,7 @@ public boolean isShowEvenIfBlank() { * * @param showEvenIfBlank the showEvenIfBlank to set */ - public void setShowEvenIfBlank(boolean showEvenIfBlank) { + public final void setShowEvenIfBlank(boolean showEvenIfBlank) { this.showEvenIfBlank = showEvenIfBlank; } diff --git a/CodenameOne/src/com/codename1/ui/List.java b/CodenameOne/src/com/codename1/ui/List.java index 1e4b6ce247..00b872829a 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); } @@ -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/RadioButton.java b/CodenameOne/src/com/codename1/ui/RadioButton.java index 46f3188cce..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"); } /** 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..0351ba5db0 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"); 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 5b63579f02..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)) { diff --git a/CodenameOne/src/com/codename1/ui/TextArea.java b/CodenameOne/src/com/codename1/ui/TextArea.java index e8f9cd272e..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); 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/Toolbar.java b/CodenameOne/src/com/codename1/ui/Toolbar.java index 0bb80e3db0..6100496093 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 @@ -2308,11 +2308,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 +2598,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(); 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/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/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/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/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..b3f84407c2 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); } diff --git a/CodenameOne/src/com/codename1/ui/spinner/Picker.java b/CodenameOne/src/com/codename1/ui/spinner/Picker.java index 0f60b06d42..e4990002f1 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 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/table/Table.java b/CodenameOne/src/com/codename1/ui/table/Table.java index 8c5010d94e..c247686c34 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(); diff --git a/CodenameOne/src/com/codename1/ui/tree/Tree.java b/CodenameOne/src/com/codename1/ui/tree/Tree.java index 7215f46549..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"); } /** 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/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index e78aef88ff..862d8c12d3 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -44,6 +44,14 @@ + + + + + + + + + + + + + + + + + + + + From f428c5e6c894d134f93491db5b7aba0aa07ab2c0 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 1 Jan 2026 07:09:30 +0200 Subject: [PATCH 54/58] Multiple fixes and removed call in constructor --- .github/scripts/generate-quality-report.py | 1 - .../impl/CodenameOneImplementation.java | 4 +- CodenameOne/src/com/codename1/io/Oauth2.java | 50 ++++++++++++------- .../src/com/codename1/share/ShareForm.java | 16 ++++++ .../com/codename1/social/FacebookConnect.java | 20 +++++++- .../com/codename1/social/GoogleConnect.java | 17 +++++++ CodenameOne/src/com/codename1/ui/Button.java | 2 +- .../ui/CommonProgressAnimations.java | 8 +-- .../src/com/codename1/ui/Component.java | 12 +++-- CodenameOne/src/com/codename1/ui/Display.java | 20 ++++---- CodenameOne/src/com/codename1/ui/Form.java | 1 - CodenameOne/src/com/codename1/ui/List.java | 2 +- .../src/com/codename1/ui/RunnableWrapper.java | 8 +-- CodenameOne/src/com/codename1/ui/Sheet.java | 23 +++++---- .../src/com/codename1/ui/SideMenuBar.java | 2 +- CodenameOne/src/com/codename1/ui/Toolbar.java | 5 +- .../ui/animations/ComponentAnimation.java | 2 +- .../html/AsyncDocumentRequestHandlerImpl.java | 2 +- .../src/com/codename1/ui/html/HTMLTable.java | 5 +- .../codename1/ui/list/ListCellRenderer.java | 2 +- .../src/com/codename1/ui/plaf/Style.java | 9 ++-- .../src/com/codename1/util/AsyncResource.java | 6 +-- .../src/com/codename1/util/EasyThread.java | 14 +++--- maven/core-unittests/spotbugs-exclude.xml | 8 +++ 24 files changed, 156 insertions(+), 83 deletions(-) diff --git a/.github/scripts/generate-quality-report.py b/.github/scripts/generate-quality-report.py index 374952f45a..9a8afb8edf 100755 --- a/.github/scripts/generate-quality-report.py +++ b/.github/scripts/generate-quality-report.py @@ -800,7 +800,6 @@ def main() -> None: "EI_EXPOSE_REP2", "EI_EXPOSE_STATIC_REP2", "EQ_COMPARETO_USE_OBJECT_EQUALS", - "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR", "MS_EXPOSE_REP", "NM_CONFUSING", "NO_NOTIFY_NOT_NOTIFYALL", diff --git a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java index 06109217d1..4c07a3be91 100644 --- a/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java +++ b/CodenameOne/src/com/codename1/impl/CodenameOneImplementation.java @@ -575,7 +575,9 @@ public void stopTextEditing() { */ public void stopTextEditing(Runnable onFinish) { stopTextEditing(); - onFinish.run(); + if(onFinish != null) { + onFinish.run(); + } } /** diff --git a/CodenameOne/src/com/codename1/io/Oauth2.java b/CodenameOne/src/com/codename1/io/Oauth2.java index 0ad308c371..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; @@ -542,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() { @@ -660,7 +654,6 @@ private Hashtable getParamsFromURL(String url) { } public static class RefreshTokenRequest extends AsyncResource { - } private static class RefreshTokenActionListener implements ActionListener { @@ -692,6 +685,25 @@ public ShowAuthenticationCommand(Dialog progress, Form old) { 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(); diff --git a/CodenameOne/src/com/codename1/share/ShareForm.java b/CodenameOne/src/com/codename1/share/ShareForm.java index 972798b113..8508dc5b92 100644 --- a/CodenameOne/src/com/codename1/share/ShareForm.java +++ b/CodenameOne/src/com/codename1/share/ShareForm.java @@ -116,6 +116,22 @@ public BackCommand(Form contacts) { 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 fc1b227cb8..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"}; @@ -267,6 +269,22 @@ 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 diff --git a/CodenameOne/src/com/codename1/social/GoogleConnect.java b/CodenameOne/src/com/codename1/social/GoogleConnect.java index 5ddaa0d24d..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; /** @@ -115,6 +116,22 @@ 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 diff --git a/CodenameOne/src/com/codename1/ui/Button.java b/CodenameOne/src/com/codename1/ui/Button.java index fe8bf9076e..04bcb80e73 100644 --- a/CodenameOne/src/com/codename1/ui/Button.java +++ b/CodenameOne/src/com/codename1/ui/Button.java @@ -1087,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/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 555074af58..1616a0bbd4 100644 --- a/CodenameOne/src/com/codename1/ui/Component.java +++ b/CodenameOne/src/com/codename1/ui/Component.java @@ -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); } @@ -727,7 +727,7 @@ 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 final Style getAllStyles() { if (allStyles == null) { @@ -1047,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) { @@ -1695,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; @@ -6043,7 +6047,7 @@ protected void initSelectedStyle(Style selectedStyle) { * * @return the component Style object */ - public Style getUnselectedStyle() { + public final Style getUnselectedStyle() { if (unSelectedStyle == null) { initStyle(); } diff --git a/CodenameOne/src/com/codename1/ui/Display.java b/CodenameOne/src/com/codename1/ui/Display.java index 784d71730f..e345f7ac13 100644 --- a/CodenameOne/src/com/codename1/ui/Display.java +++ b/CodenameOne/src/com/codename1/ui/Display.java @@ -1313,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; @@ -1332,7 +1332,7 @@ boolean isProcessingSerialCalls() { void notifyDisplay() { synchronized (lock) { - lock.notify(); + lock.notifyAll(); } } @@ -1621,7 +1621,7 @@ void setCurrent(final Form newForm, boolean reverse) { } } synchronized (lock) { - lock.notify(); + lock.notifyAll(); } if (!transitionExists) { @@ -1847,7 +1847,7 @@ private void addSingleArgumentEvent(int type, int code) { inputEventStackPointer++; inputEventStack[inputEventStackPointer] = code; inputEventStackPointer++; - lock.notify(); + lock.notifyAll(); } } @@ -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(); } } diff --git a/CodenameOne/src/com/codename1/ui/Form.java b/CodenameOne/src/com/codename1/ui/Form.java index 1f7c63dee3..26d8f8e11c 100644 --- a/CodenameOne/src/com/codename1/ui/Form.java +++ b/CodenameOne/src/com/codename1/ui/Form.java @@ -1730,7 +1730,6 @@ void updateIcsIconCommandBehavior() { @Override public void stopEditing(Runnable onFinish) { Display.getInstance().stopEditing(this, onFinish); - } @Override diff --git a/CodenameOne/src/com/codename1/ui/List.java b/CodenameOne/src/com/codename1/ui/List.java index 00b872829a..1af6bc1374 100644 --- a/CodenameOne/src/com/codename1/ui/List.java +++ b/CodenameOne/src/com/codename1/ui/List.java @@ -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; } diff --git a/CodenameOne/src/com/codename1/ui/RunnableWrapper.java b/CodenameOne/src/com/codename1/ui/RunnableWrapper.java index 0fc0f60569..0d1324dfb0 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: diff --git a/CodenameOne/src/com/codename1/ui/Sheet.java b/CodenameOne/src/com/codename1/ui/Sheet.java index 0351ba5db0..477a2a6845 100644 --- a/CodenameOne/src/com/codename1/ui/Sheet.java +++ b/CodenameOne/src/com/codename1/ui/Sheet.java @@ -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 4005f35c11..6d453136f3 100644 --- a/CodenameOne/src/com/codename1/ui/SideMenuBar.java +++ b/CodenameOne/src/com/codename1/ui/SideMenuBar.java @@ -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/Toolbar.java b/CodenameOne/src/com/codename1/ui/Toolbar.java index 6100496093..9d9a31fa8b 100644 --- a/CodenameOne/src/com/codename1/ui/Toolbar.java +++ b/CodenameOne/src/com/codename1/ui/Toolbar.java @@ -1508,10 +1508,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(); 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..004c509347 100644 --- a/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java +++ b/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java @@ -144,7 +144,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/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/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/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/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..8ef7b66237 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(); } } @@ -172,7 +172,7 @@ public void onSucess(T value) { synchronized (flag) { result[0] = value; flag[0] = true; - flag.notify(); + flag.notifyAll(); } } }; @@ -184,7 +184,7 @@ public void run(SuccessCallback onSuccess) { synchronized (LOCK) { queue.add(rr); queue.add(sc); - LOCK.notify(); + LOCK.notifyAll(); } Display.getInstance().invokeAndBlock(new Runnable() { public void run() { @@ -213,12 +213,12 @@ public void run() { } finally { synchronized (flag) { flag[0] = true; - flag.notify(); + flag.notifyAll(); } } } }); - LOCK.notify(); + LOCK.notifyAll(); } Display.getInstance().invokeAndBlock(new Runnable() { public void run() { @@ -237,7 +237,7 @@ public void run() { public void kill() { synchronized (LOCK) { running = false; - LOCK.notify(); + LOCK.notifyAll(); } } diff --git a/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index e194262d2e..6e26c2a1e9 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -112,6 +112,14 @@ + + + + + From fa99f273f084a73f978857a9b3a2ffe8e6b09ba0 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 1 Jan 2026 18:44:23 +0200 Subject: [PATCH 55/58] Further fixes --- .../src/com/codename1/ui/Container.java | 34 ++----------------- .../com/codename1/ui/ElevationComparator.java | 15 ++++++++ .../codename1/ui/RefreshThemeCallback.java | 21 ++++++++++++ .../codename1/ui/RefreshThemeRunnable.java | 13 +++++++ 4 files changed, 52 insertions(+), 31 deletions(-) create mode 100644 CodenameOne/src/com/codename1/ui/ElevationComparator.java create mode 100644 CodenameOne/src/com/codename1/ui/RefreshThemeCallback.java create mode 100644 CodenameOne/src/com/codename1/ui/RefreshThemeRunnable.java diff --git a/CodenameOne/src/com/codename1/ui/Container.java b/CodenameOne/src/com/codename1/ui/Container.java index f42851baa4..b382a8f184 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; @@ -304,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; } - } /** @@ -961,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))) { @@ -1904,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(); 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/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); + } +} From a3869a20d042952932c0355ae00035928cc9d9bb Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 1 Jan 2026 20:58:53 +0200 Subject: [PATCH 56/58] Fixed most issues --- CodenameOne/src/com/codename1/ui/Form.java | 49 +++---- .../src/com/codename1/ui/InputComponent.java | 40 +++-- CodenameOne/src/com/codename1/ui/Label.java | 5 +- CodenameOne/src/com/codename1/ui/MenuBar.java | 18 ++- .../src/com/codename1/ui/RunnableWrapper.java | 4 +- CodenameOne/src/com/codename1/ui/Toolbar.java | 29 ++-- .../html/AsyncDocumentRequestHandlerImpl.java | 77 ++++++---- .../com/codename1/ui/html/HTMLComponent.java | 19 ++- .../codename1/ui/html/HTMLInputFormat.java | 13 +- .../com/codename1/ui/layouts/GroupLayout.java | 1 - .../codename1/ui/layouts/LayeredLayout.java | 30 ++-- .../ui/layouts/mig/ConstraintParser.java | 2 +- .../codename1/ui/plaf/DefaultLookAndFeel.java | 56 ++----- .../com/codename1/ui/spinner/BaseSpinner.java | 17 ++- .../codename1/ui/spinner/DateSpinner3D.java | 69 +++++---- .../src/com/codename1/ui/spinner/Picker.java | 11 +- .../com/codename1/ui/spinner/SpinnerNode.java | 58 +++++--- .../com/codename1/ui/spinner/TimeSpinner.java | 52 ++++--- .../codename1/ui/spinner/TimeSpinner3D.java | 89 ++++++----- .../ui/table/SortableTableModel.java | 38 +++-- .../src/com/codename1/ui/table/Table.java | 76 +++++----- .../com/codename1/ui/util/GlassTutorial.java | 11 +- .../src/com/codename1/ui/util/Resources.java | 18 +-- .../codename1/ui/util/SwipeBackSupport.java | 32 ++-- .../codename1/ui/validation/Validator.java | 31 ++-- .../src/com/codename1/util/EasyThread.java | 138 ++++++++++++------ 26 files changed, 563 insertions(+), 420 deletions(-) diff --git a/CodenameOne/src/com/codename1/ui/Form.java b/CodenameOne/src/com/codename1/ui/Form.java index 26d8f8e11c..1dfbc0f1eb 100644 --- a/CodenameOne/src/com/codename1/ui/Form.java +++ b/CodenameOne/src/com/codename1/ui/Form.java @@ -736,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(); } /** @@ -2954,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); } @@ -4831,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 0670939746..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; @@ -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 dd5b8f10e0..a06befc8cb 100644 --- a/CodenameOne/src/com/codename1/ui/Label.java +++ b/CodenameOne/src/com/codename1/ui/Label.java @@ -914,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()); @@ -1569,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/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/RunnableWrapper.java b/CodenameOne/src/com/codename1/ui/RunnableWrapper.java index 0d1324dfb0..985534c41c 100644 --- a/CodenameOne/src/com/codename1/ui/RunnableWrapper.java +++ b/CodenameOne/src/com/codename1/ui/RunnableWrapper.java @@ -122,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/Toolbar.java b/CodenameOne/src/com/codename1/ui/Toolbar.java index 9d9a31fa8b..154af57907 100644 --- a/CodenameOne/src/com/codename1/ui/Toolbar.java +++ b/CodenameOne/src/com/codename1/ui/Toolbar.java @@ -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); @@ -1642,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(); @@ -2784,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/html/AsyncDocumentRequestHandlerImpl.java b/CodenameOne/src/com/codename1/ui/html/AsyncDocumentRequestHandlerImpl.java index 004c509347..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.notifyAll(); - } + 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/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/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/plaf/DefaultLookAndFeel.java b/CodenameOne/src/com/codename1/ui/plaf/DefaultLookAndFeel.java index d2a629dacd..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; @@ -959,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) { @@ -2323,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); - } /** @@ -2591,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/spinner/BaseSpinner.java b/CodenameOne/src/com/codename1/ui/spinner/BaseSpinner.java index b3f84407c2..c0885bffd0 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/BaseSpinner.java +++ b/CodenameOne/src/com/codename1/ui/spinner/BaseSpinner.java @@ -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 e4990002f1..1562b19e50 100644 --- a/CodenameOne/src/com/codename1/ui/spinner/Picker.java +++ b/CodenameOne/src/com/codename1/ui/spinner/Picker.java @@ -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 || (s != null && s.equals(value))) { + if (value.equals(s)) { return offset; } offset++; 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/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 d614c58f2d..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(); } } @@ -570,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 c247686c34..01e3f45c2b 100644 --- a/CodenameOne/src/com/codename1/ui/table/Table.java +++ b/CodenameOne/src/com/codename1/ui/table/Table.java @@ -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(); + } } } } @@ -433,32 +430,7 @@ private Component createCellImpl(Object value, final int row, final int column, * @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); - return Double.compare(d1, d2); - } catch (IllegalArgumentException err) { - long dd = Util.toDateValue(o1).getTime() - Util.toDateValue(o2).getTime(); - return (int) dd; - } - } - }; + return new ColumnSortComparator(new CaseInsensitiveOrder()); } /** @@ -977,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/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 110baff320..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(); @@ -1299,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(); @@ -1317,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/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/EasyThread.java b/CodenameOne/src/com/codename1/util/EasyThread.java index 8ef7b66237..5d49c79a0b 100644 --- a/CodenameOne/src/com/codename1/util/EasyThread.java +++ b/CodenameOne/src/com/codename1/util/EasyThread.java @@ -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.notifyAll(); - } - } - }; - 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.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.notifyAll(); - } - } - } - }); + 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)); } /** @@ -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(); + } + } + } } From 5eb12b1bea7c07d0503a32a4c693d14a1bd851d6 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 3 Jan 2026 13:32:26 +0200 Subject: [PATCH 57/58] Fixed a few more bugs but didn't exclude yet --- .../com/codename1/facebook/FacebookRESTService.java | 5 ----- CodenameOne/src/com/codename1/ui/Container.java | 12 ++---------- .../src/com/codename1/ui/plaf/CSSBorder.java | 13 +++++-------- maven/core-unittests/spotbugs-exclude.xml | 8 ++++++++ 4 files changed, 15 insertions(+), 23 deletions(-) diff --git a/CodenameOne/src/com/codename1/facebook/FacebookRESTService.java b/CodenameOne/src/com/codename1/facebook/FacebookRESTService.java index 5e1e111408..e6fe3ad0d5 100644 --- a/CodenameOne/src/com/codename1/facebook/FacebookRESTService.java +++ b/CodenameOne/src/com/codename1/facebook/FacebookRESTService.java @@ -66,7 +66,6 @@ class FacebookRESTService extends ConnectionRequest implements JSONParseCallback private String connectionType = ""; private DefaultListModel responseDestination; private int responseOffset = -1; - private String imageKey; private String root; public FacebookRESTService(String token, String id, String connectionType, boolean post) { @@ -296,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; } @@ -313,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/ui/Container.java b/CodenameOne/src/com/codename1/ui/Container.java index b382a8f184..b20a49b4a0 100644 --- a/CodenameOne/src/com/codename1/ui/Container.java +++ b/CodenameOne/src/com/codename1/ui/Container.java @@ -4174,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; @@ -4249,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(); } } } @@ -4261,9 +4256,6 @@ public void destroy() { } static class MorphAnimation extends ComponentAnimation { - Runnable onFinish; - int growSpeed; - int layoutAnimationSpeed; Vector animatedComponents; Motion[] opacity; boolean dontRevalidate; diff --git a/CodenameOne/src/com/codename1/ui/plaf/CSSBorder.java b/CodenameOne/src/com/codename1/ui/plaf/CSSBorder.java index 5381bd3771..ec059a0212 100644 --- a/CodenameOne/src/com/codename1/ui/plaf/CSSBorder.java +++ b/CodenameOne/src/com/codename1/ui/plaf/CSSBorder.java @@ -1992,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; @@ -2020,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/maven/core-unittests/spotbugs-exclude.xml b/maven/core-unittests/spotbugs-exclude.xml index 6e26c2a1e9..9d6407839b 100644 --- a/maven/core-unittests/spotbugs-exclude.xml +++ b/maven/core-unittests/spotbugs-exclude.xml @@ -76,6 +76,14 @@ + + + + +